Files
makemd/extension/src/background/ABTestOptimizationService.ts
wurenzhi 037e412aad feat: 新增多模块功能与服务实现
新增广告计划、用户资产、B2B交易、合规规则等核心模型
实现爬虫工作器、贸易服务、现金流预测等业务服务
添加RBAC权限测试、压力测试等测试用例
完善扩展程序的消息处理与内容脚本功能
重构应用入口与文档生成器
更新项目规则与业务闭环分析文档
2026-03-18 09:38:09 +08:00

339 lines
11 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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
};
}
}