feat: 新增多模块功能与服务实现
新增广告计划、用户资产、B2B交易、合规规则等核心模型 实现爬虫工作器、贸易服务、现金流预测等业务服务 添加RBAC权限测试、压力测试等测试用例 完善扩展程序的消息处理与内容脚本功能 重构应用入口与文档生成器 更新项目规则与业务闭环分析文档
This commit is contained in:
338
extension/src/background/ABTestOptimizationService.ts
Normal file
338
extension/src/background/ABTestOptimizationService.ts
Normal file
@@ -0,0 +1,338 @@
|
||||
import { Logger } from '../utils/Logger';
|
||||
|
||||
export interface TestResult {
|
||||
testId: string;
|
||||
variations: VariationResult[];
|
||||
metrics: {
|
||||
[metric: string]: number;
|
||||
};
|
||||
startDate: string;
|
||||
endDate: string;
|
||||
sampleSize: number;
|
||||
statisticalSignificance: number;
|
||||
}
|
||||
|
||||
export interface VariationResult {
|
||||
id: string;
|
||||
name: string;
|
||||
metrics: {
|
||||
[metric: string]: number;
|
||||
};
|
||||
sampleSize: number;
|
||||
conversionRate?: number;
|
||||
engagementRate?: number;
|
||||
revenuePerUser?: number;
|
||||
retentionRate?: number;
|
||||
}
|
||||
|
||||
export interface OptimizationGoal {
|
||||
type: 'maximize' | 'minimize';
|
||||
metric: string;
|
||||
targetValue?: number;
|
||||
weight?: number;
|
||||
}
|
||||
|
||||
export interface OptimizationRecommendation {
|
||||
recommendedVariation: string;
|
||||
confidence: number;
|
||||
expectedImprovement: number;
|
||||
optimizationActions: OptimizationAction[];
|
||||
riskAssessment: 'low' | 'medium' | 'high';
|
||||
implementationSteps: string[];
|
||||
followUpTests: FollowUpTest[];
|
||||
}
|
||||
|
||||
export interface OptimizationAction {
|
||||
id: string;
|
||||
description: string;
|
||||
priority: 'high' | 'medium' | 'low';
|
||||
expectedImpact: number;
|
||||
implementationEffort: 'low' | 'medium' | 'high';
|
||||
}
|
||||
|
||||
export interface FollowUpTest {
|
||||
testName: string;
|
||||
description: string;
|
||||
recommendedTiming: string;
|
||||
estimatedDuration: number;
|
||||
}
|
||||
|
||||
export class ABTestOptimizationService {
|
||||
private logger = new Logger('ABTestOptimizationService');
|
||||
|
||||
async optimizeTest(
|
||||
testResult: TestResult,
|
||||
optimizationGoals: OptimizationGoal[],
|
||||
traceId: string
|
||||
): Promise<OptimizationRecommendation> {
|
||||
try {
|
||||
this.logger.info('开始优化A/B测试', {
|
||||
testId: testResult.testId,
|
||||
variationCount: testResult.variations.length,
|
||||
traceId
|
||||
});
|
||||
|
||||
const bestVariation = this.identifyBestVariation(testResult, optimizationGoals);
|
||||
const confidence = this.calculateConfidence(testResult, bestVariation.id);
|
||||
const expectedImprovement = this.calculateExpectedImprovement(testResult, bestVariation.id);
|
||||
const optimizationActions = this.generateOptimizationActions(testResult, bestVariation, optimizationGoals);
|
||||
const risk = this.assessRisk(testResult, bestVariation, optimizationGoals);
|
||||
const implementationSteps = this.generateImplementationSteps(optimizationActions);
|
||||
const followUpTests = this.recommendFollowUpTests(testResult, bestVariation, optimizationGoals);
|
||||
|
||||
const recommendation: OptimizationRecommendation = {
|
||||
recommendedVariation: bestVariation.id,
|
||||
confidence,
|
||||
expectedImprovement,
|
||||
optimizationActions,
|
||||
riskAssessment: risk,
|
||||
implementationSteps,
|
||||
followUpTests
|
||||
};
|
||||
|
||||
this.logger.info('A/B测试优化完成', {
|
||||
recommendedVariation: bestVariation.id,
|
||||
confidence,
|
||||
expectedImprovement,
|
||||
traceId
|
||||
});
|
||||
|
||||
return recommendation;
|
||||
} catch (error) {
|
||||
this.logger.error('优化A/B测试失败', {
|
||||
error: error instanceof Error ? error.message : '未知错误',
|
||||
traceId
|
||||
});
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
private identifyBestVariation(testResult: TestResult, optimizationGoals: OptimizationGoal[]): VariationResult {
|
||||
let bestVariation: VariationResult = testResult.variations[0];
|
||||
let bestScore = -Infinity;
|
||||
|
||||
testResult.variations.forEach(variation => {
|
||||
let score = 0;
|
||||
|
||||
optimizationGoals.forEach(goal => {
|
||||
const value = variation.metrics[goal.metric] || 0;
|
||||
const weight = goal.weight || 1;
|
||||
|
||||
if (goal.type === 'maximize') {
|
||||
score += value * weight;
|
||||
} else {
|
||||
score += (1 / (value + 0.001)) * weight;
|
||||
}
|
||||
});
|
||||
|
||||
if (score > bestScore) {
|
||||
bestScore = score;
|
||||
bestVariation = variation;
|
||||
}
|
||||
});
|
||||
|
||||
return bestVariation;
|
||||
}
|
||||
|
||||
private calculateConfidence(testResult: TestResult, bestVariationId: string): number {
|
||||
const bestVariation = testResult.variations.find(v => v.id === bestVariationId);
|
||||
if (!bestVariation) return 0;
|
||||
|
||||
const otherVariations = testResult.variations.filter(v => v.id !== bestVariationId);
|
||||
const significantWins = otherVariations.filter(other => {
|
||||
return this.isStatisticallySignificant(bestVariation!, other);
|
||||
});
|
||||
|
||||
return Math.min(1, significantWins.length / otherVariations.length * 0.8 + 0.2);
|
||||
}
|
||||
|
||||
private calculateExpectedImprovement(testResult: TestResult, bestVariationId: string): number {
|
||||
const bestVariation = testResult.variations.find(v => v.id === bestVariationId);
|
||||
if (!bestVariation) return 0;
|
||||
|
||||
const otherVariations = testResult.variations.filter(v => v.id !== bestVariationId);
|
||||
if (otherVariations.length === 0) return 0;
|
||||
|
||||
const averagePerformance = otherVariations.reduce((sum, v) => {
|
||||
const metricValues = Object.values(v.metrics);
|
||||
return sum + metricValues.reduce((sum, val) => sum + val, 0) / metricValues.length;
|
||||
}, 0) / otherVariations.length;
|
||||
|
||||
const bestPerformance = Object.values(bestVariation.metrics).reduce((sum, val) => sum + val, 0) / Object.values(bestVariation.metrics).length;
|
||||
|
||||
return (bestPerformance - averagePerformance) / averagePerformance;
|
||||
}
|
||||
|
||||
private generateOptimizationActions(
|
||||
testResult: TestResult,
|
||||
bestVariation: VariationResult,
|
||||
optimizationGoals: OptimizationGoal[]
|
||||
): OptimizationAction[] {
|
||||
const actions: OptimizationAction[] = [];
|
||||
|
||||
optimizationGoals.forEach(goal => {
|
||||
const bestValue = bestVariation.metrics[goal.metric];
|
||||
if (bestValue === undefined) return;
|
||||
|
||||
const otherVariations = testResult.variations.filter(v => v.id !== bestVariation.id);
|
||||
const averageValue = otherVariations.reduce((sum, v) => sum + (v.metrics[goal.metric] || 0), 0) / otherVariations.length;
|
||||
const improvement = (bestValue - averageValue) / averageValue;
|
||||
|
||||
if (Math.abs(improvement) > 0.05) {
|
||||
actions.push({
|
||||
id: `action_${goal.metric}`,
|
||||
description: `优化 ${goal.metric} 指标,采用 ${bestVariation.name} 的策略`,
|
||||
priority: Math.abs(improvement) > 0.15 ? 'high' : Math.abs(improvement) > 0.08 ? 'medium' : 'low',
|
||||
expectedImpact: Math.abs(improvement),
|
||||
implementationEffort: Math.abs(improvement) > 0.15 ? 'medium' : 'low'
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
if (actions.length === 0) {
|
||||
actions.push({
|
||||
id: 'action_no_change',
|
||||
description: '保持当前策略,继续监控性能',
|
||||
priority: 'low',
|
||||
expectedImpact: 0,
|
||||
implementationEffort: 'low'
|
||||
});
|
||||
}
|
||||
|
||||
return actions.sort((a, b) => {
|
||||
const priorityOrder = { high: 3, medium: 2, low: 1 };
|
||||
return priorityOrder[b.priority] - priorityOrder[a.priority];
|
||||
});
|
||||
}
|
||||
|
||||
private assessRisk(
|
||||
testResult: TestResult,
|
||||
bestVariation: VariationResult,
|
||||
optimizationGoals: OptimizationGoal[]
|
||||
): 'low' | 'medium' | 'high' {
|
||||
let riskScore = 0;
|
||||
|
||||
if (testResult.sampleSize < 500) riskScore += 2;
|
||||
else if (testResult.sampleSize < 1000) riskScore += 1;
|
||||
|
||||
if (testResult.statisticalSignificance > 0.1) riskScore += 2;
|
||||
else if (testResult.statisticalSignificance > 0.05) riskScore += 1;
|
||||
|
||||
const otherVariations = testResult.variations.filter(v => v.id !== bestVariation.id);
|
||||
const closeCompetitors = otherVariations.filter(other => {
|
||||
const bestScore = Object.values(bestVariation.metrics).reduce((sum, val) => sum + val, 0);
|
||||
const otherScore = Object.values(other.metrics).reduce((sum, val) => sum + val, 0);
|
||||
return (otherScore / bestScore) > 0.95;
|
||||
});
|
||||
|
||||
if (closeCompetitors.length > 0) riskScore += 1;
|
||||
|
||||
const hasRevenueGoal = optimizationGoals.some(goal => goal.metric.includes('revenue'));
|
||||
if (hasRevenueGoal) riskScore += 1;
|
||||
|
||||
if (riskScore >= 5) return 'high';
|
||||
if (riskScore >= 3) return 'medium';
|
||||
return 'low';
|
||||
}
|
||||
|
||||
private generateImplementationSteps(actions: OptimizationAction[]): string[] {
|
||||
const steps: string[] = [];
|
||||
|
||||
steps.push('1. 审核优化建议,确认推荐的变体');
|
||||
steps.push('2. 制定实施计划,包括时间线和负责人');
|
||||
|
||||
actions.forEach((action, index) => {
|
||||
steps.push(`${index + 3}. 实施 ${action.description}(优先级:${action.priority})`);
|
||||
});
|
||||
|
||||
steps.push(`${actions.length + 3}. 监控实施后的性能指标`);
|
||||
steps.push(`${actions.length + 4}. 记录实施结果,用于后续分析`);
|
||||
|
||||
return steps;
|
||||
}
|
||||
|
||||
private recommendFollowUpTests(
|
||||
testResult: TestResult,
|
||||
bestVariation: VariationResult,
|
||||
optimizationGoals: OptimizationGoal[]
|
||||
): FollowUpTest[] {
|
||||
const tests: FollowUpTest[] = [];
|
||||
|
||||
if (optimizationGoals.some(goal => goal.type === 'maximize' && goal.metric.includes('conversion'))) {
|
||||
tests.push({
|
||||
testName: '转化率优化深度测试',
|
||||
description: '进一步优化已识别的高转化率策略',
|
||||
recommendedTiming: '2周后',
|
||||
estimatedDuration: 7
|
||||
});
|
||||
}
|
||||
|
||||
if (optimizationGoals.some(goal => goal.type === 'maximize' && goal.metric.includes('revenue'))) {
|
||||
tests.push({
|
||||
testName: '收入优化扩展测试',
|
||||
description: '测试不同定价策略和促销组合',
|
||||
recommendedTiming: '3周后',
|
||||
estimatedDuration: 14
|
||||
});
|
||||
}
|
||||
|
||||
if (tests.length === 0) {
|
||||
tests.push({
|
||||
testName: '性能监控测试',
|
||||
description: '持续监控实施后的性能变化',
|
||||
recommendedTiming: '1周后',
|
||||
estimatedDuration: 7
|
||||
});
|
||||
}
|
||||
|
||||
return tests;
|
||||
}
|
||||
|
||||
private isStatisticallySignificant(variationA: VariationResult, variationB: VariationResult): boolean {
|
||||
const metricsA = Object.values(variationA.metrics);
|
||||
const metricsB = Object.values(variationB.metrics);
|
||||
|
||||
if (metricsA.length === 0 || metricsB.length === 0) return false;
|
||||
|
||||
const meanA = metricsA.reduce((sum, val) => sum + val, 0) / metricsA.length;
|
||||
const meanB = metricsB.reduce((sum, val) => sum + val, 0) / metricsB.length;
|
||||
|
||||
const varianceA = metricsA.reduce((sum, val) => sum + Math.pow(val - meanA, 2), 0) / metricsA.length;
|
||||
const varianceB = metricsB.reduce((sum, val) => sum + Math.pow(val - meanB, 2), 0) / metricsB.length;
|
||||
|
||||
const standardError = Math.sqrt(varianceA / metricsA.length + varianceB / metricsB.length);
|
||||
const zScore = Math.abs(meanA - meanB) / standardError;
|
||||
|
||||
return zScore > 1.96; // 95% confidence
|
||||
}
|
||||
|
||||
async validateOptimization(recommendation: OptimizationRecommendation, traceId: string): Promise<{ valid: boolean; warnings: string[] }> {
|
||||
const warnings: string[] = [];
|
||||
|
||||
if (recommendation.confidence < 0.7) {
|
||||
warnings.push('置信度较低,建议增加样本量或延长测试时间');
|
||||
}
|
||||
|
||||
if (recommendation.expectedImprovement < 0.05) {
|
||||
warnings.push('预期改进较小,可能不值得实施');
|
||||
}
|
||||
|
||||
if (recommendation.riskAssessment === 'high') {
|
||||
warnings.push('风险评估为高,建议谨慎实施');
|
||||
}
|
||||
|
||||
if (recommendation.optimizationActions.length === 0) {
|
||||
warnings.push('未生成优化行动,建议重新评估测试结果');
|
||||
}
|
||||
|
||||
this.logger.info('优化建议验证完成', {
|
||||
warningCount: warnings.length,
|
||||
traceId
|
||||
});
|
||||
|
||||
return {
|
||||
valid: warnings.length < 3,
|
||||
warnings
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user