route-claudecode
Version:
Advanced routing and transformation system for Claude Code outputs to multiple AI providers
626 lines • 27.5 kB
JavaScript
"use strict";
/**
* Auto-Correction Tool
* 根据历史对比数据自动学习修正规则
* Project owner: Jason Zhang
*/
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.AutoCorrectionTool = void 0;
const logger_1 = require("@/utils/logger");
const promises_1 = __importDefault(require("fs/promises"));
const path_1 = __importDefault(require("path"));
class AutoCorrectionTool {
config;
analysisEngine;
correctionEngine;
learningData;
autoSaveTimer;
constructor(analysisEngine, correctionEngine, config) {
this.config = config;
this.analysisEngine = analysisEngine;
this.correctionEngine = correctionEngine;
this.learningData = {
patterns: [],
statistics: this.initializeStatistics(),
rules: [],
confidence: 0,
lastUpdated: new Date()
};
this.startAutoSave();
}
/**
* 从历史数据学习并生成修正规则
*/
async learnFromHistory() {
logger_1.logger.info('Starting auto-correction learning process');
try {
// 获取分析历史数据
const analysisHistory = this.analysisEngine.getAnalysisHistory();
const correctionHistory = this.correctionEngine.getCorrectionHistory();
if (analysisHistory.length < this.config.minimumDataPoints) {
logger_1.logger.warn(`Insufficient data for learning: ${analysisHistory.length} < ${this.config.minimumDataPoints}`);
return;
}
// Step 1: 检测修正模式
await this.detectCorrectionPatterns(analysisHistory, correctionHistory);
// Step 2: 生成学习规则
await this.generateLearnedRules(analysisHistory, correctionHistory);
// Step 3: 更新统计数据
await this.updateLearningStatistics(analysisHistory, correctionHistory);
// Step 4: 计算整体置信度
this.calculateOverallConfidence();
// Step 5: 保存学习数据
await this.saveLearningData();
logger_1.logger.info('Auto-correction learning completed', {
patterns: this.learningData.patterns.length,
rules: this.learningData.rules.length,
confidence: this.learningData.confidence
});
}
catch (error) {
logger_1.logger.error('Auto-correction learning failed', error);
throw error;
}
}
/**
* 应用学习到的规则进行自动修正
*/
async applyAutomaticCorrection(request, codewhispererResponse, openaiReference) {
logger_1.logger.debug('Applying automatic correction', {
rulesAvailable: this.learningData.rules.length,
patternsAvailable: this.learningData.patterns.length
});
const result = {
correctedResponse: { ...codewhispererResponse },
appliedRules: [],
confidence: 0,
improvements: []
};
try {
// 先进行快速分析识别问题
const quickAnalysis = await this.performQuickAnalysis(codewhispererResponse, openaiReference);
// 根据分析结果应用合适的规则
for (const rule of this.learningData.rules) {
if (await this.shouldApplyRule(rule, quickAnalysis, codewhispererResponse, openaiReference)) {
const applied = await this.applyRule(rule, result.correctedResponse, openaiReference);
if (applied.success) {
result.appliedRules.push(rule.name);
result.improvements.push(applied.improvement);
result.confidence = Math.max(result.confidence, applied.confidence);
}
}
}
// 应用检测到的模式
for (const pattern of this.learningData.patterns) {
if (await this.shouldApplyPattern(pattern, result.correctedResponse, openaiReference)) {
const applied = await this.applyPattern(pattern, result.correctedResponse, openaiReference);
if (applied.success) {
result.improvements.push(applied.improvement);
result.confidence = Math.max(result.confidence, applied.confidence);
}
}
}
logger_1.logger.debug('Automatic correction applied', {
rulesApplied: result.appliedRules.length,
confidence: result.confidence,
improvements: result.improvements.length
});
return result;
}
catch (error) {
logger_1.logger.error('Automatic correction failed', error);
return result; // 返回原始响应作为fallback
}
}
/**
* 评估修正效果并更新学习数据
*/
async evaluateAndUpdateLearning(correctionResult, actualPerformance) {
logger_1.logger.debug('Evaluating correction performance for learning update');
try {
// 更新规则性能
for (const correction of correctionResult.appliedCorrections) {
const rule = this.learningData.rules.find(r => r.name === correction.method);
if (rule) {
rule.performance.totalApplications++;
if (actualPerformance.correctnessScore && actualPerformance.correctnessScore > 0.7) {
rule.performance.successfulApplications++;
}
rule.performance.averageImprovement = (rule.performance.averageImprovement * (rule.performance.totalApplications - 1) +
(actualPerformance.correctnessScore || 0)) / rule.performance.totalApplications;
rule.performance.lastUsed = new Date();
}
}
// 更新模式置信度
const performanceScore = Object.values(actualPerformance).reduce((sum, score) => sum + (score || 0), 0) /
Object.keys(actualPerformance).length;
for (const pattern of this.learningData.patterns) {
// 根据实际性能调整模式置信度
if (performanceScore > 0.8) {
pattern.confidence = Math.min(1, pattern.confidence + 0.05);
}
else if (performanceScore < 0.5) {
pattern.confidence = Math.max(0, pattern.confidence - 0.1);
}
}
await this.saveLearningData();
}
catch (error) {
logger_1.logger.error('Failed to update learning from evaluation', error);
}
}
/**
* 获取修正建议
*/
async getRecommendations(request, codewhispererResponse, openaiReference) {
const recommendations = {
urgentRecommendations: [],
improvementSuggestions: [],
preventiveMeasures: [],
confidence: 0
};
try {
const analysis = await this.performQuickAnalysis(codewhispererResponse, openaiReference);
// 基于学习到的模式生成建议
for (const pattern of this.learningData.patterns) {
if (pattern.confidence > 0.8 && await this.patternMatches(pattern, analysis)) {
switch (pattern.type) {
case 'content':
if (analysis.contentSimilarity < 0.5) {
recommendations.urgentRecommendations.push(`Content differs significantly from reference - consider using ${pattern.correctionAction.method}`);
}
break;
case 'structure':
recommendations.improvementSuggestions.push('Response structure inconsistencies detected - automatic normalization recommended');
break;
case 'tools':
recommendations.urgentRecommendations.push('Tool call format issues detected - automatic correction available');
break;
}
}
}
// 基于统计数据生成预防性建议
for (const issue of this.learningData.statistics.mostCommonIssues) {
if (issue.frequency > this.learningData.statistics.totalComparisons * 0.3) {
recommendations.preventiveMeasures.push(`Common issue detected: ${issue.issue} - occurs in ${((issue.frequency / this.learningData.statistics.totalComparisons) * 100).toFixed(1)}% of cases`);
}
}
recommendations.confidence = this.learningData.confidence;
return recommendations;
}
catch (error) {
logger_1.logger.error('Failed to generate recommendations', error);
return recommendations;
}
}
// 私有方法
async detectCorrectionPatterns(analysisHistory, correctionHistory) {
logger_1.logger.debug('Detecting correction patterns from history');
const patternCandidates = new Map();
for (const analysis of analysisHistory) {
for (const difference of analysis.differences) {
const patternKey = `${difference.type}_${difference.severity}`;
if (!patternCandidates.has(patternKey)) {
patternCandidates.set(patternKey, {
id: patternKey,
type: difference.type,
triggerConditions: [],
correctionAction: {
method: 'auto_detected',
parameters: {},
expectedImpact: 0
},
successRate: 0,
frequency: 0,
confidence: 0,
examples: []
});
}
const pattern = patternCandidates.get(patternKey);
pattern.frequency++;
// 添加示例
pattern.examples.push({
originalValue: difference.codewhispererValue,
correctedValue: difference.openaiValue,
context: difference.description,
success: true, // 假设参考值是正确的
confidence: 0.8
});
}
}
// 计算模式成功率和置信度
for (const [key, pattern] of patternCandidates) {
if (pattern.frequency >= this.config.patternDetectionThreshold) {
pattern.successRate = pattern.examples.filter(e => e.success).length / pattern.examples.length;
pattern.confidence = Math.min(pattern.successRate, pattern.frequency / analysisHistory.length);
if (pattern.confidence >= this.config.confidenceThreshold) {
this.learningData.patterns.push(pattern);
}
}
}
// 限制模式数量
this.learningData.patterns = this.learningData.patterns
.sort((a, b) => b.confidence - a.confidence)
.slice(0, this.config.maxPatternsPerType * 4); // 4 types maximum
}
async generateLearnedRules(analysisHistory, correctionHistory) {
logger_1.logger.debug('Generating learned rules from patterns');
const ruleGenerators = [
this.generateContentRules,
this.generateStructureRules,
this.generateToolRules,
this.generateMetadataRules
];
for (const generator of ruleGenerators) {
const rules = await generator.call(this, analysisHistory, correctionHistory);
this.learningData.rules.push(...rules);
}
// 限制规则数量
this.learningData.rules = this.learningData.rules
.sort((a, b) => b.confidence - a.confidence)
.slice(0, this.config.maxRules);
}
async generateContentRules(analysisHistory, correctionHistory) {
const rules = [];
// 内容长度差异规则
const lengthDiffCases = analysisHistory.filter(a => a.analysis.contentComparison.lengthDifference > 0.5);
if (lengthDiffCases.length >= this.config.ruleGenerationThreshold) {
rules.push({
id: 'content_length_correction',
name: 'Content Length Correction',
description: 'Correct content when reference is significantly longer',
conditions: [
{
type: 'length_ratio',
threshold: 1.5,
operator: 'gt',
value: 1.5
}
],
actions: [
{
type: 'replace_content',
strategy: 'use_reference_when_longer',
parameters: { minimumRatio: 1.5 },
confidence: 0.8
}
],
priority: 1,
confidence: lengthDiffCases.length / analysisHistory.length,
applicableScenarios: ['content_generation', 'explanation_tasks'],
performance: {
totalApplications: 0,
successfulApplications: 0,
averageImprovement: 0,
averageConfidence: 0.8,
lastUsed: new Date()
}
});
}
return rules;
}
async generateStructureRules(analysisHistory, correctionHistory) {
const rules = [];
// 结构标准化规则
const structureDiffCases = analysisHistory.filter(a => a.analysis.contentComparison.structuralDifference > 0.3);
if (structureDiffCases.length >= this.config.ruleGenerationThreshold) {
rules.push({
id: 'structure_normalization',
name: 'Structure Normalization',
description: 'Normalize response structure to match reference format',
conditions: [
{
type: 'structure_diff',
threshold: 0.3,
operator: 'gt',
value: 0.3
}
],
actions: [
{
type: 'fix_structure',
strategy: 'normalize_to_reference',
parameters: { preserveOriginalData: true },
confidence: 0.9
}
],
priority: 2,
confidence: structureDiffCases.length / analysisHistory.length,
applicableScenarios: ['all'],
performance: {
totalApplications: 0,
successfulApplications: 0,
averageImprovement: 0,
averageConfidence: 0.9,
lastUsed: new Date()
}
});
}
return rules;
}
async generateToolRules(analysisHistory, correctionHistory) {
const rules = [];
// 工具调用修正规则
const toolDiffCases = analysisHistory.filter(a => a.differences.some(d => d.type === 'tools'));
if (toolDiffCases.length >= this.config.ruleGenerationThreshold) {
rules.push({
id: 'tool_format_correction',
name: 'Tool Format Correction',
description: 'Correct tool call format to match reference',
conditions: [
{
type: 'tool_presence',
threshold: 1,
operator: 'eq',
value: 1
}
],
actions: [
{
type: 'correct_tools',
strategy: 'adopt_reference_format',
parameters: { validateParameters: true },
confidence: 0.85
}
],
priority: 1,
confidence: toolDiffCases.length / analysisHistory.length,
applicableScenarios: ['tool_calling'],
performance: {
totalApplications: 0,
successfulApplications: 0,
averageImprovement: 0,
averageConfidence: 0.85,
lastUsed: new Date()
}
});
}
return rules;
}
async generateMetadataRules(analysisHistory, correctionHistory) {
const rules = [];
// 元数据标准化规则
const metadataDiffCases = analysisHistory.filter(a => a.differences.some(d => d.type === 'metadata'));
if (metadataDiffCases.length >= this.config.ruleGenerationThreshold) {
rules.push({
id: 'metadata_standardization',
name: 'Metadata Standardization',
description: 'Standardize metadata format while preserving original data',
conditions: [
{
type: 'token_ratio',
threshold: 0.1,
operator: 'gt',
value: 0.1
}
],
actions: [
{
type: 'normalize_metadata',
strategy: 'standardize_format',
parameters: { preserveOriginalValues: true },
confidence: 0.7
}
],
priority: 3,
confidence: metadataDiffCases.length / analysisHistory.length,
applicableScenarios: ['all'],
performance: {
totalApplications: 0,
successfulApplications: 0,
averageImprovement: 0,
averageConfidence: 0.7,
lastUsed: new Date()
}
});
}
return rules;
}
async performQuickAnalysis(codewhispererResponse, openaiReference) {
const cwContent = this.extractTextContent(codewhispererResponse);
const oaiContent = this.extractTextContent(openaiReference);
return {
contentSimilarity: this.calculateContentSimilarity(cwContent, oaiContent),
lengthRatio: oaiContent.length / Math.max(cwContent.length, 1),
structureDifference: this.calculateStructuralDifference(codewhispererResponse, openaiReference),
hasToolDifferences: JSON.stringify(this.extractToolCalls(codewhispererResponse)) !==
JSON.stringify(this.extractToolCalls(openaiReference)),
hasMetadataDifferences: JSON.stringify(codewhispererResponse.usage) !==
JSON.stringify(openaiReference.usage)
};
}
// 其他辅助方法...
extractTextContent(response) {
if (!response.content || !Array.isArray(response.content))
return '';
return response.content.filter(item => item.type === 'text').map(item => item.text || '').join(' ');
}
extractToolCalls(response) {
if (!response.content || !Array.isArray(response.content))
return [];
return response.content.filter(item => item.type === 'tool_use');
}
calculateContentSimilarity(content1, content2) {
const words1 = content1.toLowerCase().split(/\s+/);
const words2 = content2.toLowerCase().split(/\s+/);
const commonWords = words1.filter(word => words2.includes(word));
const totalWords = [...new Set([...words1, ...words2])];
return commonWords.length / Math.max(totalWords.length, 1);
}
calculateStructuralDifference(response1, response2) {
const keys1 = Object.keys(response1);
const keys2 = Object.keys(response2);
const allKeys = [...new Set([...keys1, ...keys2])];
const commonKeys = keys1.filter(key => keys2.includes(key));
return 1 - (commonKeys.length / allKeys.length);
}
async shouldApplyRule(rule, analysis, cw, oai) {
for (const condition of rule.conditions) {
const value = this.getAnalysisValue(analysis, condition.type);
if (!this.evaluateCondition(value, condition))
return false;
}
return rule.confidence >= this.config.confidenceThreshold;
}
async shouldApplyPattern(pattern, cw, oai) {
return pattern.confidence >= this.config.confidenceThreshold;
}
async applyRule(rule, response, reference) {
// 简化的规则应用逻辑
try {
for (const action of rule.actions) {
switch (action.type) {
case 'replace_content':
if (action.strategy === 'use_reference_when_longer') {
const refContent = this.extractTextContent(reference);
const respContent = this.extractTextContent(response);
if (refContent.length > respContent.length * action.parameters.minimumRatio) {
response.content = reference.content;
return {
success: true,
confidence: action.confidence,
improvement: 'Content replaced with more complete reference'
};
}
}
break;
}
}
return { success: false, confidence: 0, improvement: '' };
}
catch (error) {
return { success: false, confidence: 0, improvement: '' };
}
}
async applyPattern(pattern, response, reference) {
// 简化的模式应用逻辑
return { success: false, confidence: 0, improvement: '' };
}
async patternMatches(pattern, analysis) {
// 简化的模式匹配逻辑
return pattern.confidence > 0.7;
}
getAnalysisValue(analysis, type) {
switch (type) {
case 'content_similarity': return analysis.contentSimilarity;
case 'length_ratio': return analysis.lengthRatio;
case 'structure_diff': return analysis.structureDifference;
case 'token_ratio': return 1; // 简化
case 'tool_presence': return analysis.hasToolDifferences ? 1 : 0;
default: return 0;
}
}
evaluateCondition(value, condition) {
switch (condition.operator) {
case 'gt': return value > condition.threshold;
case 'lt': return value < condition.threshold;
case 'eq': return Math.abs(value - condition.threshold) < 0.01;
case 'between':
const [min, max] = Array.isArray(condition.value) ? condition.value : [0, 1];
return value >= min && value <= max;
default: return false;
}
}
initializeStatistics() {
return {
totalComparisons: 0,
totalCorrections: 0,
averageSuccessRate: 0,
patternCount: 0,
ruleCount: 0,
mostCommonIssues: [],
improvementTrends: []
};
}
async updateLearningStatistics(analysisHistory, correctionHistory) {
this.learningData.statistics.totalComparisons = analysisHistory.length;
this.learningData.statistics.totalCorrections = correctionHistory.length;
this.learningData.statistics.patternCount = this.learningData.patterns.length;
this.learningData.statistics.ruleCount = this.learningData.rules.length;
// 计算平均成功率
const successfulCorrections = correctionHistory.filter(c => c.success).length;
this.learningData.statistics.averageSuccessRate = correctionHistory.length > 0
? successfulCorrections / correctionHistory.length
: 0;
// 识别最常见问题
const allDifferences = analysisHistory.flatMap(a => a.differences);
const issueFrequency = allDifferences.reduce((acc, diff) => {
acc[diff.description] = (acc[diff.description] || 0) + 1;
return acc;
}, {});
this.learningData.statistics.mostCommonIssues = Object.entries(issueFrequency)
.sort(([, a], [, b]) => b - a)
.slice(0, 10)
.map(([issue, frequency]) => ({ issue, frequency }));
}
calculateOverallConfidence() {
const patternConfidence = this.learningData.patterns.length > 0
? this.learningData.patterns.reduce((sum, p) => sum + p.confidence, 0) / this.learningData.patterns.length
: 0;
const ruleConfidence = this.learningData.rules.length > 0
? this.learningData.rules.reduce((sum, r) => sum + r.confidence, 0) / this.learningData.rules.length
: 0;
this.learningData.confidence = (patternConfidence + ruleConfidence) / 2;
}
async saveLearningData() {
try {
const dataPath = path_1.default.join(this.config.dataStoragePath, 'learning-data.json');
await promises_1.default.writeFile(dataPath, JSON.stringify(this.learningData, null, 2));
this.learningData.lastUpdated = new Date();
}
catch (error) {
logger_1.logger.error('Failed to save learning data', error);
}
}
async loadLearningData() {
try {
const dataPath = path_1.default.join(this.config.dataStoragePath, 'learning-data.json');
const data = await promises_1.default.readFile(dataPath, 'utf8');
this.learningData = JSON.parse(data);
}
catch (error) {
logger_1.logger.debug('No existing learning data found, starting fresh');
}
}
startAutoSave() {
if (this.config.autoSaveInterval > 0) {
this.autoSaveTimer = setInterval(() => {
this.saveLearningData().catch(error => {
logger_1.logger.error('Auto-save failed', error);
});
}, this.config.autoSaveInterval);
}
}
/**
* 清理资源
*/
destroy() {
if (this.autoSaveTimer) {
clearInterval(this.autoSaveTimer);
this.autoSaveTimer = undefined;
}
}
/**
* 获取学习数据统计
*/
getLearningStatistics() {
return { ...this.learningData.statistics };
}
/**
* 获取学习到的模式
*/
getLearnedPatterns() {
return [...this.learningData.patterns];
}
/**
* 获取学习到的规则
*/
getLearnedRules() {
return [...this.learningData.rules];
}
}
exports.AutoCorrectionTool = AutoCorrectionTool;
//# sourceMappingURL=auto-correction.js.map