chain-of-thought-executor.ts•19.3 kB
/**
* Chain of Thought Executor - 思维链执行器
* 执行分解后的研究查询,管理思维链推理过程
*/
import { EventEmitter } from 'events';
import { DecomposedQuery, ExecutionPlan, ResearchQuery } from './query-decomposer.js';
import { Logger } from '../utils/logger.js';
export interface ThoughtChain {
id: string;
parentQueryId: string;
steps: ThoughtStep[];
currentStep: number;
status: ChainStatus;
startedAt: string;
completedAt?: string;
totalExecutionTime: number;
confidence: number;
metadata: ChainMetadata;
}
export interface ThoughtStep {
id: string;
stepNumber: number;
query: DecomposedQuery;
reasoning: string;
searchResults: SearchResult[];
analysis: StepAnalysis;
conclusions: string[];
confidence: number;
executionTime: number;
status: StepStatus;
dependencies: string[];
nextSteps: string[];
}
export interface StepAnalysis {
relevanceScore: number;
qualityScore: number;
completenessScore: number;
consistencyScore: number;
noveltyScore: number;
evidenceStrength: number;
biasDetection: BiasAnalysis;
factualAccuracy: number;
}
export interface BiasAnalysis {
detectedBiases: BiasType[];
confidenceInDetection: number;
mitigationSuggestions: string[];
}
export interface ChainMetadata {
createdAt: string;
domain: string;
complexity: string;
totalSteps: number;
parallelSteps: number;
criticalPath: string[];
estimatedTime: number;
}
export interface SearchResult {
id: string;
title: string;
url: string;
snippet: string;
source: string;
relevanceScore: number;
qualityScore: number;
timestamp: string;
metadata: any;
}
export interface ExecutionResult {
chainId: string;
originalQuery: ResearchQuery;
thoughtChain: ThoughtChain;
finalConclusions: Conclusion[];
synthesizedAnswer: string;
confidence: number;
evidenceQuality: number;
completeness: number;
executionMetrics: ExecutionMetrics;
}
export interface Conclusion {
id: string;
statement: string;
confidence: number;
supportingEvidence: Evidence[];
contradictingEvidence: Evidence[];
certaintyLevel: CertaintyLevel;
scope: string;
}
export interface Evidence {
source: string;
content: string;
relevanceScore: number;
credibilityScore: number;
recency: number;
type: EvidenceType;
}
export interface ExecutionMetrics {
totalTime: number;
searchTime: number;
analysisTime: number;
synthesisTime: number;
queriesExecuted: number;
resultsProcessed: number;
averageRelevance: number;
averageQuality: number;
}
export type ChainStatus = 'pending' | 'running' | 'completed' | 'failed' | 'paused';
export type StepStatus = 'pending' | 'running' | 'completed' | 'failed' | 'skipped';
export type BiasType = 'confirmation' | 'selection' | 'temporal' | 'source' | 'cultural' | 'cognitive';
export type CertaintyLevel = 'very_low' | 'low' | 'moderate' | 'high' | 'very_high';
export type EvidenceType = 'primary' | 'secondary' | 'expert_opinion' | 'statistical' | 'anecdotal';
export class ChainOfThoughtExecutor extends EventEmitter {
private logger: Logger;
private activeChains: Map<string, ThoughtChain> = new Map();
private searchEngine: any; // 将与搜索引擎集成
private analysisEngine: any; // 将与分析引擎集成
constructor() {
super();
this.logger = new Logger('ChainOfThoughtExecutor');
}
/**
* 执行思维链
*/
async executeChain(
originalQuery: ResearchQuery,
decomposedQueries: DecomposedQuery[],
executionPlan: ExecutionPlan
): Promise<ExecutionResult> {
const chainId = this.generateChainId();
this.logger.info(`Starting chain of thought execution for query: ${originalQuery.originalQuery}`);
try {
// 1. 初始化思维链
const thoughtChain = this.initializeChain(chainId, originalQuery, decomposedQueries, executionPlan);
this.activeChains.set(chainId, thoughtChain);
// 2. 执行思维链步骤
await this.executeSteps(thoughtChain, executionPlan);
// 3. 分析和综合结果
const conclusions = await this.analyzeAndSynthesize(thoughtChain);
// 4. 生成最终答案
const synthesizedAnswer = await this.generateFinalAnswer(thoughtChain, conclusions);
// 5. 计算执行指标
const executionMetrics = this.calculateExecutionMetrics(thoughtChain);
const result: ExecutionResult = {
chainId,
originalQuery,
thoughtChain,
finalConclusions: conclusions,
synthesizedAnswer,
confidence: this.calculateOverallConfidence(thoughtChain, conclusions),
evidenceQuality: this.calculateEvidenceQuality(thoughtChain),
completeness: this.calculateCompleteness(thoughtChain, originalQuery),
executionMetrics
};
this.logger.info(`Chain of thought execution completed for ${chainId}`);
this.emit('chainCompleted', result);
return result;
} catch (error) {
this.logger.error(`Chain of thought execution failed for ${chainId}:`, error);
this.emit('chainFailed', chainId, error);
throw error;
} finally {
this.activeChains.delete(chainId);
}
}
/**
* 初始化思维链
*/
private initializeChain(
chainId: string,
originalQuery: ResearchQuery,
decomposedQueries: DecomposedQuery[],
executionPlan: ExecutionPlan
): ThoughtChain {
const steps: ThoughtStep[] = decomposedQueries.map((query, index) => ({
id: `step-${index + 1}`,
stepNumber: index + 1,
query,
reasoning: this.generateInitialReasoning(query),
searchResults: [],
analysis: this.initializeStepAnalysis(),
conclusions: [],
confidence: 0,
executionTime: 0,
status: 'pending',
dependencies: query.dependencies,
nextSteps: []
}));
const thoughtChain: ThoughtChain = {
id: chainId,
parentQueryId: originalQuery.id,
steps,
currentStep: 0,
status: 'pending',
startedAt: new Date().toISOString(),
totalExecutionTime: 0,
confidence: 0,
metadata: {
createdAt: new Date().toISOString(),
domain: originalQuery.domain,
complexity: originalQuery.complexity,
totalSteps: steps.length,
parallelSteps: executionPlan.parallelGroups.flat().length,
criticalPath: executionPlan.criticalPath,
estimatedTime: executionPlan.phases.reduce((sum, phase) => sum + phase.estimatedTime, 0)
}
};
return thoughtChain;
}
/**
* 执行思维链步骤
*/
private async executeSteps(thoughtChain: ThoughtChain, executionPlan: ExecutionPlan): Promise<void> {
thoughtChain.status = 'running';
const startTime = Date.now();
for (const phase of executionPlan.phases) {
this.logger.info(`Executing phase: ${phase.name}`);
if (phase.canRunInParallel) {
await this.executeStepsInParallel(thoughtChain, phase.subQueryIds);
} else {
await this.executeStepsSequentially(thoughtChain, phase.subQueryIds);
}
}
thoughtChain.status = 'completed';
thoughtChain.completedAt = new Date().toISOString();
thoughtChain.totalExecutionTime = Date.now() - startTime;
}
/**
* 并行执行步骤
*/
private async executeStepsInParallel(thoughtChain: ThoughtChain, stepIds: string[]): Promise<void> {
const steps = thoughtChain.steps.filter(step => stepIds.includes(step.query.id));
const promises = steps.map(step => this.executeStep(step));
await Promise.allSettled(promises);
}
/**
* 顺序执行步骤
*/
private async executeStepsSequentially(thoughtChain: ThoughtChain, stepIds: string[]): Promise<void> {
const steps = thoughtChain.steps.filter(step => stepIds.includes(step.query.id));
for (const step of steps) {
await this.executeStep(step);
}
}
/**
* 执行单个步骤
*/
private async executeStep(step: ThoughtStep): Promise<void> {
const startTime = Date.now();
step.status = 'running';
try {
this.logger.debug(`Executing step ${step.stepNumber}: ${step.query.subQuery}`);
// 1. 执行搜索
step.searchResults = await this.performSearch(step.query);
// 2. 分析结果
step.analysis = await this.analyzeStepResults(step);
// 3. 生成推理和结论
step.reasoning = await this.generateStepReasoning(step);
step.conclusions = await this.generateStepConclusions(step);
// 4. 计算置信度
step.confidence = this.calculateStepConfidence(step);
step.status = 'completed';
step.executionTime = Date.now() - startTime;
this.logger.debug(`Step ${step.stepNumber} completed with confidence ${step.confidence}`);
} catch (error) {
step.status = 'failed';
step.executionTime = Date.now() - startTime;
this.logger.error(`Step ${step.stepNumber} failed:`, error);
throw error;
}
}
/**
* 执行搜索
*/
private async performSearch(query: DecomposedQuery): Promise<SearchResult[]> {
// 这里将集成实际的搜索引擎
// 暂时返回模拟结果
const mockResults: SearchResult[] = [
{
id: `result-${Date.now()}-1`,
title: `Search result for: ${query.subQuery}`,
url: 'https://example.com/result1',
snippet: `This is a relevant snippet for the query: ${query.subQuery}`,
source: 'example.com',
relevanceScore: 0.85,
qualityScore: 0.8,
timestamp: new Date().toISOString(),
metadata: { searchStrategy: query.searchStrategy }
},
{
id: `result-${Date.now()}-2`,
title: `Additional information about: ${query.subQuery}`,
url: 'https://example.com/result2',
snippet: `More detailed information regarding: ${query.subQuery}`,
source: 'example.com',
relevanceScore: 0.75,
qualityScore: 0.85,
timestamp: new Date().toISOString(),
metadata: { searchStrategy: query.searchStrategy }
}
];
return mockResults;
}
/**
* 分析步骤结果
*/
private async analyzeStepResults(step: ThoughtStep): Promise<StepAnalysis> {
const results = step.searchResults;
const analysis: StepAnalysis = {
relevanceScore: this.calculateAverageRelevance(results),
qualityScore: this.calculateAverageQuality(results),
completenessScore: this.assessCompleteness(results, step.query),
consistencyScore: this.assessConsistency(results),
noveltyScore: this.assessNovelty(results),
evidenceStrength: this.assessEvidenceStrength(results),
biasDetection: await this.detectBias(results),
factualAccuracy: this.assessFactualAccuracy(results)
};
return analysis;
}
/**
* 生成步骤推理
*/
private async generateStepReasoning(step: ThoughtStep): Promise<string> {
const query = step.query;
const results = step.searchResults;
const analysis = step.analysis;
let reasoning = `For the query "${query.subQuery}" (${query.type} type):\n\n`;
reasoning += `Found ${results.length} relevant results with average relevance of ${(analysis.relevanceScore * 100).toFixed(1)}%.\n`;
reasoning += `Quality assessment shows ${(analysis.qualityScore * 100).toFixed(1)}% quality score.\n`;
if (analysis.biasDetection.detectedBiases.length > 0) {
reasoning += `Detected potential biases: ${analysis.biasDetection.detectedBiases.join(', ')}.\n`;
}
reasoning += `Evidence strength is ${(analysis.evidenceStrength * 100).toFixed(1)}% with factual accuracy of ${(analysis.factualAccuracy * 100).toFixed(1)}%.\n`;
return reasoning;
}
/**
* 生成步骤结论
*/
private async generateStepConclusions(step: ThoughtStep): Promise<string[]> {
const conclusions: string[] = [];
// 基于搜索结果生成结论
if (step.searchResults.length > 0) {
const topResult = step.searchResults[0];
conclusions.push(`Based on search results, ${step.query.subQuery.toLowerCase()} shows ${topResult.snippet}`);
}
// 基于分析生成结论
if (step.analysis.relevanceScore > 0.8) {
conclusions.push(`High relevance found for this aspect of the research question`);
}
if (step.analysis.evidenceStrength > 0.7) {
conclusions.push(`Strong evidence supports the findings for this query component`);
}
return conclusions;
}
/**
* 分析和综合结果
*/
private async analyzeAndSynthesize(thoughtChain: ThoughtChain): Promise<Conclusion[]> {
const conclusions: Conclusion[] = [];
// 综合所有步骤的结论
const allStepConclusions = thoughtChain.steps.flatMap(step => step.conclusions);
const allEvidence = thoughtChain.steps.flatMap(step =>
step.searchResults.map(result => ({
source: result.source,
content: result.snippet,
relevanceScore: result.relevanceScore,
credibilityScore: result.qualityScore,
recency: this.calculateRecency(result.timestamp),
type: 'secondary' as EvidenceType
}))
);
// 生成主要结论
const mainConclusion: Conclusion = {
id: `conclusion-main-${Date.now()}`,
statement: this.synthesizeMainConclusion(allStepConclusions),
confidence: this.calculateOverallConfidence(thoughtChain, []),
supportingEvidence: allEvidence.filter(e => e.relevanceScore > 0.7),
contradictingEvidence: [],
certaintyLevel: this.determineCertaintyLevel(thoughtChain),
scope: 'comprehensive'
};
conclusions.push(mainConclusion);
return conclusions;
}
/**
* 生成最终答案
*/
private async generateFinalAnswer(thoughtChain: ThoughtChain, conclusions: Conclusion[]): Promise<string> {
let answer = `Based on comprehensive research analysis:\n\n`;
conclusions.forEach((conclusion, index) => {
answer += `${index + 1}. ${conclusion.statement}\n`;
answer += ` Confidence: ${(conclusion.confidence * 100).toFixed(1)}%\n`;
answer += ` Evidence strength: ${conclusion.supportingEvidence.length} supporting sources\n\n`;
});
answer += `This analysis was conducted through ${thoughtChain.steps.length} research steps `;
answer += `with an overall confidence of ${(thoughtChain.confidence * 100).toFixed(1)}%.`;
return answer;
}
/**
* 工具方法
*/
private generateChainId(): string {
return `chain-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
}
private generateInitialReasoning(query: DecomposedQuery): string {
return `Initial reasoning for ${query.type} query: "${query.subQuery}"`;
}
private initializeStepAnalysis(): StepAnalysis {
return {
relevanceScore: 0,
qualityScore: 0,
completenessScore: 0,
consistencyScore: 0,
noveltyScore: 0,
evidenceStrength: 0,
biasDetection: {
detectedBiases: [],
confidenceInDetection: 0,
mitigationSuggestions: []
},
factualAccuracy: 0
};
}
private calculateAverageRelevance(results: SearchResult[]): number {
if (results.length === 0) return 0;
return results.reduce((sum, result) => sum + result.relevanceScore, 0) / results.length;
}
private calculateAverageQuality(results: SearchResult[]): number {
if (results.length === 0) return 0;
return results.reduce((sum, result) => sum + result.qualityScore, 0) / results.length;
}
private assessCompleteness(results: SearchResult[], query: DecomposedQuery): number {
// 简化的完整性评估
const expectedResults = query.metadata.maxResults;
return Math.min(results.length / expectedResults, 1);
}
private assessConsistency(results: SearchResult[]): number {
// 简化的一致性评估
return 0.8; // 默认值
}
private assessNovelty(results: SearchResult[]): number {
// 简化的新颖性评估
return 0.7; // 默认值
}
private assessEvidenceStrength(results: SearchResult[]): number {
return this.calculateAverageQuality(results);
}
private async detectBias(results: SearchResult[]): Promise<BiasAnalysis> {
// 简化的偏见检测
return {
detectedBiases: [],
confidenceInDetection: 0.5,
mitigationSuggestions: ['Consider diverse sources', 'Verify with multiple perspectives']
};
}
private assessFactualAccuracy(results: SearchResult[]): number {
// 简化的事实准确性评估
return 0.85; // 默认值
}
private calculateStepConfidence(step: ThoughtStep): number {
const analysis = step.analysis;
return (analysis.relevanceScore + analysis.qualityScore + analysis.evidenceStrength) / 3;
}
private calculateOverallConfidence(thoughtChain: ThoughtChain, conclusions: Conclusion[]): number {
const stepConfidences = thoughtChain.steps.map(step => step.confidence);
if (stepConfidences.length === 0) return 0;
return stepConfidences.reduce((sum, conf) => sum + conf, 0) / stepConfidences.length;
}
private calculateEvidenceQuality(thoughtChain: ThoughtChain): number {
const allResults = thoughtChain.steps.flatMap(step => step.searchResults);
return this.calculateAverageQuality(allResults);
}
private calculateCompleteness(thoughtChain: ThoughtChain, originalQuery: ResearchQuery): number {
const completedSteps = thoughtChain.steps.filter(step => step.status === 'completed').length;
return completedSteps / thoughtChain.steps.length;
}
private calculateExecutionMetrics(thoughtChain: ThoughtChain): ExecutionMetrics {
const allResults = thoughtChain.steps.flatMap(step => step.searchResults);
return {
totalTime: thoughtChain.totalExecutionTime,
searchTime: thoughtChain.steps.reduce((sum, step) => sum + step.executionTime * 0.6, 0),
analysisTime: thoughtChain.steps.reduce((sum, step) => sum + step.executionTime * 0.3, 0),
synthesisTime: thoughtChain.steps.reduce((sum, step) => sum + step.executionTime * 0.1, 0),
queriesExecuted: thoughtChain.steps.length,
resultsProcessed: allResults.length,
averageRelevance: this.calculateAverageRelevance(allResults),
averageQuality: this.calculateAverageQuality(allResults)
};
}
private calculateRecency(timestamp: string): number {
const now = Date.now();
const resultTime = new Date(timestamp).getTime();
const daysDiff = (now - resultTime) / (1000 * 60 * 60 * 24);
return Math.max(0, 1 - daysDiff / 365); // 1年内的内容认为是新的
}
private synthesizeMainConclusion(stepConclusions: string[]): string {
if (stepConclusions.length === 0) {
return 'No sufficient evidence found to draw conclusions';
}
return `Based on multi-step analysis, the research indicates: ${stepConclusions[0]}`;
}
private determineCertaintyLevel(thoughtChain: ThoughtChain): CertaintyLevel {
const avgConfidence = this.calculateOverallConfidence(thoughtChain, []);
if (avgConfidence >= 0.9) return 'very_high';
if (avgConfidence >= 0.75) return 'high';
if (avgConfidence >= 0.5) return 'moderate';
if (avgConfidence >= 0.25) return 'low';
return 'very_low';
}
}