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 { 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 }; } }