UNPKG

route-claudecode

Version:

Advanced routing and transformation system for Claude Code outputs to multiple AI providers

495 lines 21 kB
"use strict"; /** * Provider Response Correction Engine * 基于 OpenAI 响应修正 CodeWhisperer 输出 * Project owner: Jason Zhang */ Object.defineProperty(exports, "__esModule", { value: true }); exports.CorrectionEngine = void 0; const logger_1 = require("@/utils/logger"); class CorrectionEngine { config; correctionHistory = []; strategies = []; maxHistorySize = 500; constructor(config) { this.config = config; this.initializeStrategies(); } /** * 应用修正到 CodeWhisperer 响应 */ async correctResponse(request, codewhispererResponse, openaiReference, comparisonResult) { const requestId = request.metadata?.requestId || `correction_${Date.now()}`; const startTime = Date.now(); logger_1.logger.info(`Starting response correction`, { requestId, differencesCount: comparisonResult.differences.length, recommendationsCount: comparisonResult.recommendations.length }); const result = { requestId, timestamp: new Date(), originalResponse: { ...codewhispererResponse }, referenceResponse: { ...openaiReference }, correctedResponse: { ...codewhispererResponse }, appliedCorrections: [], correctionMetrics: { totalCorrections: 0, successfulCorrections: 0, failedCorrections: 0, confidenceScore: 0, improvementScore: 0, processingTime: 0 }, success: false, errors: [] }; try { // 按优先级处理差异 const sortedDifferences = comparisonResult.differences .sort((a, b) => this.getDifferencePriority(a) - this.getDifferencePriority(b)); for (const difference of sortedDifferences) { if (result.appliedCorrections.length >= this.config.maxCorrections) { logger_1.logger.warn(`Maximum corrections limit reached`, { requestId, limit: this.config.maxCorrections }); break; } await this.applyCorrection(result, difference); } // 计算修正指标 const endTime = Date.now(); result.correctionMetrics.processingTime = endTime - startTime; result.correctionMetrics.totalCorrections = result.appliedCorrections.length; result.correctionMetrics.successfulCorrections = result.appliedCorrections.filter(c => c.confidence >= this.config.confidenceThreshold).length; result.correctionMetrics.failedCorrections = result.correctionMetrics.totalCorrections - result.correctionMetrics.successfulCorrections; if (result.appliedCorrections.length > 0) { result.correctionMetrics.confidenceScore = result.appliedCorrections .reduce((sum, c) => sum + c.confidence, 0) / result.appliedCorrections.length; } result.correctionMetrics.improvementScore = this.calculateImprovementScore(result.originalResponse, result.correctedResponse, result.referenceResponse); result.success = result.errors.length === 0 && result.appliedCorrections.length > 0; // 存储到历史记录 this.addToHistory(result); logger_1.logger.info(`Response correction completed`, { requestId, success: result.success, correctionsApplied: result.correctionMetrics.successfulCorrections, averageConfidence: result.correctionMetrics.confidenceScore, improvementScore: result.correctionMetrics.improvementScore }); return result; } catch (error) { logger_1.logger.error(`Response correction failed`, error, requestId); result.errors.push(error instanceof Error ? error.message : String(error)); result.success = false; return result; } } /** * 批量修正模式 */ async correctResponseBatch(corrections) { logger_1.logger.info(`Starting batch correction`, { batchSize: corrections.length }); const results = []; for (let i = 0; i < corrections.length; i++) { const { request, codewhispererResponse, openaiReference, comparisonResult } = corrections[i]; try { const result = await this.correctResponse(request, codewhispererResponse, openaiReference, comparisonResult); results.push(result); logger_1.logger.debug(`Batch correction progress: ${i + 1}/${corrections.length}`); } catch (error) { logger_1.logger.error(`Batch correction item ${i} failed`, error); // Continue with next item } } logger_1.logger.info(`Batch correction completed`, { total: corrections.length, successful: results.filter(r => r.success).length, failed: results.filter(r => !r.success).length }); return results; } /** * 应用单个修正 */ async applyCorrection(result, difference) { // 找到适用的策略 const strategy = this.strategies.find(s => s.canCorrect(difference)); if (!strategy) { logger_1.logger.debug(`No strategy found for difference type: ${difference.type}`); return; } try { const operation = await strategy.apply(result.correctedResponse, result.referenceResponse, difference); if (operation.success && operation.confidence >= this.config.confidenceThreshold) { // 应用修正 this.applyOperationToResponse(result.correctedResponse, difference, operation); result.appliedCorrections.push({ type: difference.type, description: difference.description, originalValue: difference.codewhispererValue, correctedValue: operation.correctedValue, confidence: operation.confidence, method: operation.method }); logger_1.logger.debug(`Correction applied successfully`, { type: difference.type, confidence: operation.confidence, method: operation.method }); } else { logger_1.logger.debug(`Correction skipped due to low confidence or failure`, { type: difference.type, confidence: operation.confidence, threshold: this.config.confidenceThreshold, error: operation.error }); } } catch (error) { result.errors.push(`Failed to apply correction for ${difference.type}: ${error instanceof Error ? error.message : String(error)}`); logger_1.logger.error(`Correction application failed`, error); } } /** * 将操作应用到响应对象 */ applyOperationToResponse(response, difference, operation) { switch (difference.type) { case 'content': if (response.content && Array.isArray(response.content)) { response.content = operation.correctedValue; } break; case 'structure': // 应用结构修正 Object.assign(response, operation.correctedValue); break; case 'tools': if (response.content && Array.isArray(response.content)) { // 查找并替换工具调用 const toolIndex = response.content.findIndex(item => item.type === 'tool_use'); if (toolIndex !== -1) { response.content[toolIndex] = operation.correctedValue; } } break; case 'metadata': if (operation.correctedValue.usage) { response.usage = operation.correctedValue.usage; } break; } } /** * 初始化修正策略 */ initializeStrategies() { // 内容修正策略 this.strategies.push({ name: 'content-length-correction', priority: 1, canCorrect: (diff) => diff.type === 'content' && diff.severity !== 'minor', apply: async (original, reference, difference) => { try { const originalContent = this.extractTextContent(original); const referenceContent = this.extractTextContent(reference); if (referenceContent.length > originalContent.length * 1.5) { // 参考响应明显更完整,使用参考内容 const correctedContent = this.normalizeContent(reference.content); return { success: true, correctedValue: correctedContent, confidence: 0.8, method: 'reference-content-adoption' }; } return { success: false, correctedValue: null, confidence: 0, method: 'content-length-check', error: 'Reference content not significantly better' }; } catch (error) { return { success: false, correctedValue: null, confidence: 0, method: 'content-correction', error: error instanceof Error ? error.message : String(error) }; } } }); // 结构修正策略 this.strategies.push({ name: 'structure-normalization', priority: 2, canCorrect: (diff) => diff.type === 'structure', apply: async (original, reference, difference) => { try { const correctedStructure = { ...original, // 添加缺失的字段 ...(reference.type && !original.type && { type: reference.type }), ...(reference.id && !original.id && { id: reference.id }), // 保持原有数据 }; return { success: true, correctedValue: correctedStructure, confidence: 0.9, method: 'structure-field-normalization' }; } catch (error) { return { success: false, correctedValue: null, confidence: 0, method: 'structure-normalization', error: error instanceof Error ? error.message : String(error) }; } } }); // 工具调用修正策略 this.strategies.push({ name: 'tool-format-correction', priority: 3, canCorrect: (diff) => diff.type === 'tools', apply: async (original, reference, difference) => { try { const referenceTools = this.extractToolCalls(reference); if (referenceTools.length === 0) { return { success: false, correctedValue: null, confidence: 0, method: 'tool-format-correction', error: 'No reference tools to correct against' }; } // 使用参考工具调用格式 const correctedTool = { ...referenceTools[0], // 保持原有ID如果存在 ...(difference.codewhispererValue.id && { id: difference.codewhispererValue.id }) }; return { success: true, correctedValue: correctedTool, confidence: 0.85, method: 'reference-tool-format-adoption' }; } catch (error) { return { success: false, correctedValue: null, confidence: 0, method: 'tool-format-correction', error: error instanceof Error ? error.message : String(error) }; } } }); // 元数据修正策略 this.strategies.push({ name: 'metadata-correction', priority: 4, canCorrect: (diff) => diff.type === 'metadata', apply: async (original, reference, difference) => { try { // 保持原始数据,但标准化格式 const correctedMetadata = { usage: original.usage || reference.usage }; return { success: true, correctedValue: correctedMetadata, confidence: 0.7, method: 'metadata-standardization' }; } catch (error) { return { success: false, correctedValue: null, confidence: 0, method: 'metadata-correction', error: error instanceof Error ? error.message : String(error) }; } } }); } // 辅助方法 getDifferencePriority(difference) { switch (difference.severity) { case 'critical': return 1; case 'major': return 2; case 'minor': return 3; default: return 4; } } 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'); } normalizeContent(content) { if (!Array.isArray(content)) return []; return content.map(item => ({ ...item, // 标准化字段 type: item.type || 'text', ...(item.text && { text: item.text.trim() }) })); } calculateImprovementScore(original, corrected, reference) { try { const originalSimilarity = this.calculateResponseSimilarity(original, reference); const correctedSimilarity = this.calculateResponseSimilarity(corrected, reference); return Math.max(0, correctedSimilarity - originalSimilarity); } catch (error) { logger_1.logger.debug('Failed to calculate improvement score', error); return 0; } } calculateResponseSimilarity(response1, response2) { const content1 = this.extractTextContent(response1); const content2 = this.extractTextContent(response2); if (!content1 || !content2) return 0; // 简化的相似度计算 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 / totalWords.length; } addToHistory(result) { this.correctionHistory.push(result); // 限制历史记录大小 if (this.correctionHistory.length > this.maxHistorySize) { this.correctionHistory = this.correctionHistory.slice(-this.maxHistorySize); } } /** * 获取修正历史 */ getCorrectionHistory(limit) { if (limit) { return this.correctionHistory.slice(-limit); } return [...this.correctionHistory]; } /** * 获取修正统计 */ getCorrectionStatistics() { if (this.correctionHistory.length === 0) { return { totalCorrections: 0, averageConfidence: 0, averageImprovement: 0, successRate: 0, commonCorrectionTypes: {}, performanceMetrics: { averageProcessingTime: 0, correctionsPerSecond: 0 } }; } const allCorrections = this.correctionHistory.flatMap(r => r.appliedCorrections); const successfulResults = this.correctionHistory.filter(r => r.success); const averageConfidence = allCorrections.length > 0 ? allCorrections.reduce((sum, c) => sum + c.confidence, 0) / allCorrections.length : 0; const averageImprovement = this.correctionHistory.length > 0 ? this.correctionHistory.reduce((sum, r) => sum + r.correctionMetrics.improvementScore, 0) / this.correctionHistory.length : 0; const successRate = this.correctionHistory.length > 0 ? successfulResults.length / this.correctionHistory.length : 0; const correctionTypes = allCorrections.reduce((acc, correction) => { acc[correction.type] = (acc[correction.type] || 0) + 1; return acc; }, {}); const processingTimes = this.correctionHistory.map(r => r.correctionMetrics.processingTime); const averageProcessingTime = processingTimes.length > 0 ? processingTimes.reduce((sum, time) => sum + time, 0) / processingTimes.length : 0; const totalProcessingTime = processingTimes.reduce((sum, time) => sum + time, 0); const correctionsPerSecond = totalProcessingTime > 0 ? (allCorrections.length * 1000) / totalProcessingTime : 0; return { totalCorrections: allCorrections.length, averageConfidence, averageImprovement, successRate, commonCorrectionTypes: correctionTypes, performanceMetrics: { averageProcessingTime, correctionsPerSecond } }; } /** * 学习并更新策略(简化版机器学习) */ async learnFromHistory() { if (this.correctionHistory.length < 10) { logger_1.logger.info('Insufficient history data for learning'); return; } logger_1.logger.info('Starting correction strategy learning from history'); // 分析成功率最高的策略 const strategySuccessRates = new Map(); for (const result of this.correctionHistory) { for (const correction of result.appliedCorrections) { const method = correction.method; const stats = strategySuccessRates.get(method) || { success: 0, total: 0 }; stats.total++; if (correction.confidence >= this.config.confidenceThreshold) { stats.success++; } strategySuccessRates.set(method, stats); } } // 更新策略优先级(简化版) for (const strategy of this.strategies) { const stats = strategySuccessRates.get(strategy.name); if (stats && stats.total >= 5) { const successRate = stats.success / stats.total; // 根据成功率调整优先级 strategy.priority = Math.round(strategy.priority * (2 - successRate)); } } logger_1.logger.info('Strategy learning completed', { strategiesAnalyzed: strategySuccessRates.size, totalHistory: this.correctionHistory.length }); } } exports.CorrectionEngine = CorrectionEngine; //# sourceMappingURL=correction-engine.js.map