restore old after-confidence-scoring
This commit is contained in:
@@ -1,11 +1,11 @@
|
||||
// src/utils/aiPipeline.ts - Enhanced with comprehensive audit logging
|
||||
// src/utils/aiPipeline.ts - Enhanced with comprehensive audit logging and restored sophisticated logic
|
||||
import { getCompressedToolsDataForAI, getDataVersion } from './dataService.js';
|
||||
import { aiService } from './aiService.js';
|
||||
import { toolSelector, type SelectionContext } from './toolSelector.js';
|
||||
import { confidenceScoring, type AnalysisContext } from './confidenceScoring.js';
|
||||
import { embeddingsService } from './embeddings.js';
|
||||
import { auditService, type AuditEntry } from './auditService.js';
|
||||
import { JSONParser } from './jsonUtils.js'; // FIXED: Use centralized JSON parsing
|
||||
import { JSONParser } from './jsonUtils.js';
|
||||
import { getPrompt } from '../config/prompts.js';
|
||||
import 'dotenv/config';
|
||||
|
||||
@@ -13,6 +13,11 @@ interface PipelineConfig {
|
||||
microTaskDelay: number;
|
||||
maxContextTokens: number;
|
||||
maxPromptTokens: number;
|
||||
taskRelevanceModeration: {
|
||||
maxInitialScore: number;
|
||||
maxWithPhaseBonus: number;
|
||||
moderationThreshold: number;
|
||||
};
|
||||
}
|
||||
|
||||
interface MicroTaskResult {
|
||||
@@ -40,6 +45,10 @@ interface AnalysisResult {
|
||||
contextContinuityUsed: boolean;
|
||||
totalAITokensUsed: number;
|
||||
auditEntriesGenerated: number;
|
||||
aiModel: string;
|
||||
toolsDataHash: string;
|
||||
temperature: number;
|
||||
maxTokensUsed: number;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -78,10 +87,15 @@ class AIPipeline {
|
||||
this.config = {
|
||||
microTaskDelay: parseInt(process.env.AI_MICRO_TASK_DELAY_MS || '500', 10),
|
||||
maxContextTokens: parseInt(process.env.AI_MAX_CONTEXT_TOKENS || '4000', 10),
|
||||
maxPromptTokens: parseInt(process.env.AI_MAX_PROMPT_TOKENS || '1500', 10)
|
||||
maxPromptTokens: parseInt(process.env.AI_MAX_PROMPT_TOKENS || '1500', 10),
|
||||
taskRelevanceModeration: {
|
||||
maxInitialScore: 85,
|
||||
maxWithPhaseBonus: 95,
|
||||
moderationThreshold: 80
|
||||
}
|
||||
};
|
||||
|
||||
console.log('[AI-PIPELINE] Initialized orchestration pipeline');
|
||||
console.log('[AI-PIPELINE] Initialized orchestration pipeline with enhanced logic');
|
||||
}
|
||||
|
||||
async processQuery(userQuery: string, mode: string): Promise<AnalysisResult> {
|
||||
@@ -92,7 +106,6 @@ class AIPipeline {
|
||||
|
||||
console.log('[AI-PIPELINE] Starting', mode, 'analysis pipeline');
|
||||
|
||||
// Initialize audit trail
|
||||
auditService.clearAuditTrail();
|
||||
|
||||
try {
|
||||
@@ -111,7 +124,6 @@ class AIPipeline {
|
||||
embeddingsSimilarities: new Map<string, number>()
|
||||
};
|
||||
|
||||
// AUDIT: Pipeline initialization
|
||||
auditService.addEntry(
|
||||
'initialization',
|
||||
'pipeline-start',
|
||||
@@ -132,17 +144,15 @@ class AIPipeline {
|
||||
toolsDataHash,
|
||||
aiModel: aiConfig.model,
|
||||
embeddingsUsed: embeddingsService.isEnabled(),
|
||||
pipelineVersion: '2.0-enhanced'
|
||||
pipelineVersion: '2.1-enhanced'
|
||||
}
|
||||
);
|
||||
|
||||
// Phase 1: Get intelligent tool candidates with enhanced logging
|
||||
console.log('[AI-PIPELINE] Phase 1: Tool candidate selection');
|
||||
const candidateSelectionStart = Date.now();
|
||||
|
||||
const candidateData = await toolSelector.getIntelligentCandidates(userQuery, toolsData, mode, context);
|
||||
|
||||
// AUDIT: Tool candidate selection
|
||||
auditService.addToolSelection(
|
||||
candidateData.tools.map(t => t.name),
|
||||
toolsData.tools.map(t => t.name),
|
||||
@@ -159,7 +169,6 @@ class AIPipeline {
|
||||
|
||||
context.filteredData = candidateData;
|
||||
|
||||
// Phase 2: Contextual analysis micro-tasks with enhanced logging
|
||||
console.log('[AI-PIPELINE] Phase 2: Contextual analysis');
|
||||
|
||||
const analysisResult = await this.analyzeScenario(context, startTime);
|
||||
@@ -177,7 +186,6 @@ class AIPipeline {
|
||||
this.trackTokenUsage(considerationsResult.aiUsage);
|
||||
await this.delay(this.config.microTaskDelay);
|
||||
|
||||
// Phase 3: Tool-specific analysis with enhanced logging
|
||||
console.log('[AI-PIPELINE] Phase 3: Tool-specific analysis');
|
||||
|
||||
if (mode === 'workflow') {
|
||||
@@ -190,7 +198,6 @@ class AIPipeline {
|
||||
failedTasks = toolResults.failed;
|
||||
}
|
||||
|
||||
// Phase 4: Knowledge and finalization with enhanced logging
|
||||
console.log('[AI-PIPELINE] Phase 4: Knowledge synthesis');
|
||||
|
||||
const knowledgeResult = await this.selectBackgroundKnowledge(context, startTime);
|
||||
@@ -202,10 +209,8 @@ class AIPipeline {
|
||||
if (finalResult.success) completedTasks++; else failedTasks++;
|
||||
this.trackTokenUsage(finalResult.aiUsage);
|
||||
|
||||
// Build final recommendation
|
||||
const recommendation = this.buildRecommendation(context, mode, finalResult.content);
|
||||
|
||||
// AUDIT: Pipeline completion
|
||||
auditService.addEntry(
|
||||
'completion',
|
||||
'pipeline-end',
|
||||
@@ -235,7 +240,11 @@ class AIPipeline {
|
||||
microTasksFailed: failedTasks,
|
||||
contextContinuityUsed: true,
|
||||
totalAITokensUsed: this.totalTokensUsed,
|
||||
auditEntriesGenerated: auditService.getCurrentAuditTrail().length
|
||||
auditEntriesGenerated: auditService.getCurrentAuditTrail().length,
|
||||
aiModel: aiConfig.model,
|
||||
toolsDataHash,
|
||||
temperature: 0.3,
|
||||
maxTokensUsed: 2500
|
||||
};
|
||||
|
||||
console.log('[AI-PIPELINE] Pipeline completed successfully:', {
|
||||
@@ -248,13 +257,13 @@ class AIPipeline {
|
||||
auditEntries: processingStats.auditEntriesGenerated
|
||||
});
|
||||
|
||||
// Finalize audit trail
|
||||
const finalAuditTrail = auditService.finalizeAuditTrail();
|
||||
|
||||
return {
|
||||
recommendation: {
|
||||
...recommendation,
|
||||
auditTrail: auditService.isEnabled() ? finalAuditTrail : undefined
|
||||
auditTrail: auditService.isEnabled() ? finalAuditTrail : undefined,
|
||||
processingStats
|
||||
},
|
||||
processingStats
|
||||
};
|
||||
@@ -262,7 +271,6 @@ class AIPipeline {
|
||||
} catch (error) {
|
||||
console.error('[AI-PIPELINE] Pipeline failed:', error);
|
||||
|
||||
// AUDIT: Pipeline failure
|
||||
auditService.addEntry(
|
||||
'error',
|
||||
'pipeline-failure',
|
||||
@@ -286,7 +294,6 @@ class AIPipeline {
|
||||
): Promise<{ completed: number; failed: number }> {
|
||||
const phases = toolsData.phases || [];
|
||||
|
||||
// Select tools for each phase with enhanced logging
|
||||
for (const phase of phases) {
|
||||
const phaseStart = Date.now();
|
||||
const phaseTools = context.filteredData.tools.filter((tool: any) =>
|
||||
@@ -295,7 +302,6 @@ class AIPipeline {
|
||||
|
||||
const selections = await toolSelector.selectToolsForPhase(context.userQuery, phase, phaseTools, context);
|
||||
|
||||
// AUDIT: Phase tool selection
|
||||
auditService.addEntry(
|
||||
'workflow-phase',
|
||||
'phase-tool-selection',
|
||||
@@ -321,21 +327,23 @@ class AIPipeline {
|
||||
selections.forEach((sel: any) => {
|
||||
const tool = phaseTools.find((t: any) => t && t.name === sel.toolName);
|
||||
if (tool) {
|
||||
const priority = this.derivePriorityFromScore(sel.taskRelevance);
|
||||
this.addToolToSelection(context, tool, phase.id, priority, sel.justification, sel.taskRelevance, sel.limitations);
|
||||
const moderatedTaskRelevance = this.moderateTaskRelevance(sel.taskRelevance);
|
||||
const priority = this.derivePriorityFromScore(moderatedTaskRelevance);
|
||||
|
||||
this.addToolToSelection(context, tool, phase.id, priority, sel.justification, moderatedTaskRelevance, sel.limitations);
|
||||
|
||||
// AUDIT: Individual tool selection reasoning
|
||||
auditService.addEntry(
|
||||
'tool-reasoning',
|
||||
'tool-added-to-phase',
|
||||
{ toolName: tool.name, phaseId: phase.id, taskRelevance: sel.taskRelevance },
|
||||
{ toolName: tool.name, phaseId: phase.id, originalTaskRelevance: sel.taskRelevance, moderatedTaskRelevance },
|
||||
{ justification: sel.justification, limitations: sel.limitations },
|
||||
sel.taskRelevance || 70,
|
||||
moderatedTaskRelevance || 70,
|
||||
phaseStart,
|
||||
{
|
||||
toolType: tool.type,
|
||||
priority,
|
||||
selectionReasoning: sel.justification
|
||||
selectionReasoning: sel.justification,
|
||||
moderationApplied: sel.taskRelevance !== moderatedTaskRelevance
|
||||
}
|
||||
);
|
||||
}
|
||||
@@ -345,8 +353,9 @@ class AIPipeline {
|
||||
await this.delay(this.config.microTaskDelay);
|
||||
}
|
||||
|
||||
// Complete underrepresented phases with enhanced logging
|
||||
const completionResult = await this.completeUnderrepresentedPhases(context, toolsData, pipelineStart);
|
||||
completedTasks += completionResult.completed;
|
||||
failedTasks += completionResult.failed;
|
||||
|
||||
return { completed: completedTasks, failed: failedTasks };
|
||||
}
|
||||
@@ -369,6 +378,267 @@ class AIPipeline {
|
||||
return { completed: completedTasks, failed: failedTasks };
|
||||
}
|
||||
|
||||
private async completeUnderrepresentedPhases(
|
||||
context: PipelineContext,
|
||||
toolsData: any,
|
||||
pipelineStart: number
|
||||
): Promise<{ completed: number; failed: number }> {
|
||||
const phases = toolsData.phases || [];
|
||||
const selectedPhases = new Map<string, number>();
|
||||
let completedTasks = 0;
|
||||
let failedTasks = 0;
|
||||
|
||||
context.selectedTools?.forEach((st: any) => {
|
||||
const count = selectedPhases.get(st.phase) || 0;
|
||||
selectedPhases.set(st.phase, count + 1);
|
||||
});
|
||||
|
||||
const underrepresentedPhases = phases.filter((phase: any) => {
|
||||
const count = selectedPhases.get(phase.id) || 0;
|
||||
return count <= 1;
|
||||
});
|
||||
|
||||
if (underrepresentedPhases.length === 0) {
|
||||
console.log('[AI-PIPELINE] All phases adequately represented');
|
||||
return { completed: 0, failed: 0 };
|
||||
}
|
||||
|
||||
console.log('[AI-PIPELINE] Completing underrepresented phases:', underrepresentedPhases.map((p: any) => p.id).join(', '));
|
||||
|
||||
auditService.addEntry(
|
||||
'phase-completion',
|
||||
'underrepresented-phases-detected',
|
||||
{
|
||||
underrepresentedPhases: underrepresentedPhases.map(p => p.id),
|
||||
currentPhaseDistribution: Array.from(selectedPhases.entries())
|
||||
},
|
||||
{
|
||||
phasesToComplete: underrepresentedPhases.length,
|
||||
completionStrategy: 'semantic-search-with-ai-reasoning'
|
||||
},
|
||||
70,
|
||||
pipelineStart,
|
||||
{
|
||||
totalPhases: phases.length,
|
||||
adequatelyRepresented: phases.length - underrepresentedPhases.length,
|
||||
completionMethod: 'sophisticated-ai-reasoning'
|
||||
}
|
||||
);
|
||||
|
||||
for (const phase of underrepresentedPhases) {
|
||||
const result = await this.completePhaseWithSemanticSearchAndAI(context, phase, toolsData, pipelineStart);
|
||||
if (result.success) completedTasks++; else failedTasks++;
|
||||
await this.delay(this.config.microTaskDelay);
|
||||
}
|
||||
|
||||
return { completed: completedTasks, failed: failedTasks };
|
||||
}
|
||||
|
||||
private async completePhaseWithSemanticSearchAndAI(
|
||||
context: PipelineContext,
|
||||
phase: any,
|
||||
toolsData: any,
|
||||
pipelineStart: number
|
||||
): Promise<MicroTaskResult> {
|
||||
const phaseStart = Date.now();
|
||||
const phaseQuery = `forensic ${phase.name.toLowerCase()} tools methods`;
|
||||
|
||||
console.log('[AI-PIPELINE] Phase completion for:', phase.id);
|
||||
|
||||
try {
|
||||
const phaseResults = await embeddingsService.findSimilar(phaseQuery, 20, 0.2);
|
||||
|
||||
auditService.addEmbeddingsSearch(
|
||||
phaseQuery,
|
||||
phaseResults,
|
||||
0.2,
|
||||
phaseStart,
|
||||
{
|
||||
phaseId: phase.id,
|
||||
phaseName: phase.name,
|
||||
completionPurpose: 'underrepresented-phase-enhancement'
|
||||
}
|
||||
);
|
||||
|
||||
if (phaseResults.length === 0) {
|
||||
console.log('[AI-PIPELINE] No semantic results for phase:', phase.id);
|
||||
return {
|
||||
taskType: 'phase-completion',
|
||||
content: '',
|
||||
processingTimeMs: Date.now() - phaseStart,
|
||||
success: true
|
||||
};
|
||||
}
|
||||
|
||||
const toolsMap = new Map(toolsData.tools.map((tool: any) => [tool.name, tool]));
|
||||
const conceptsMap = new Map(toolsData.concepts.map((concept: any) => [concept.name, concept]));
|
||||
|
||||
const phaseTools = phaseResults
|
||||
.filter((result: any) => result.type === 'tool')
|
||||
.map((result: any) => toolsMap.get(result.name))
|
||||
.filter((tool: any): tool is NonNullable<any> =>
|
||||
tool !== undefined &&
|
||||
tool !== null &&
|
||||
tool.phases &&
|
||||
Array.isArray(tool.phases) &&
|
||||
tool.phases.includes(phase.id) &&
|
||||
!context.seenToolNames.has(tool.name)
|
||||
)
|
||||
.slice(0, 5);
|
||||
|
||||
const phaseConcepts = phaseResults
|
||||
.filter((result: any) => result.type === 'concept')
|
||||
.map((result: any) => conceptsMap.get(result.name))
|
||||
.filter((concept: any): concept is NonNullable<any> => concept !== undefined && concept !== null)
|
||||
.slice(0, 2);
|
||||
|
||||
if (phaseTools.length === 0) {
|
||||
console.log('[AI-PIPELINE] No suitable tools for phase completion:', phase.id);
|
||||
return {
|
||||
taskType: 'phase-completion',
|
||||
content: '',
|
||||
processingTimeMs: Date.now() - phaseStart,
|
||||
success: true
|
||||
};
|
||||
}
|
||||
|
||||
const selectionPrompt = getPrompt('generatePhaseCompletionPrompt', context.userQuery, phase, phaseTools, phaseConcepts);
|
||||
const selectionResult = await this.callMicroTaskAI(selectionPrompt, context, 800, 'phase-completion-selection');
|
||||
|
||||
if (!selectionResult.success) {
|
||||
console.error('[AI-PIPELINE] Phase completion selection failed for:', phase.id);
|
||||
return {
|
||||
taskType: 'phase-completion',
|
||||
content: '',
|
||||
processingTimeMs: Date.now() - phaseStart,
|
||||
success: false,
|
||||
error: 'Selection micro-task failed'
|
||||
};
|
||||
}
|
||||
|
||||
const selection = JSONParser.safeParseJSON(selectionResult.content, {
|
||||
selectedTools: [],
|
||||
selectedConcepts: [],
|
||||
completionReasoning: ''
|
||||
});
|
||||
|
||||
const validTools = selection.selectedTools
|
||||
.map((name: string) => phaseTools.find((t: any) => t && t.name === name))
|
||||
.filter((tool: any): tool is NonNullable<any> => tool !== undefined && tool !== null)
|
||||
.slice(0, 2);
|
||||
|
||||
if (validTools.length === 0) {
|
||||
console.log('[AI-PIPELINE] No valid tools selected for phase completion:', phase.id);
|
||||
return {
|
||||
taskType: 'phase-completion',
|
||||
content: selection.completionReasoning || '',
|
||||
processingTimeMs: Date.now() - phaseStart,
|
||||
success: true
|
||||
};
|
||||
}
|
||||
|
||||
for (const tool of validTools) {
|
||||
console.log('[AI-PIPELINE] Generating AI reasoning for phase completion tool:', tool.name);
|
||||
|
||||
const reasoningPrompt = getPrompt(
|
||||
'phaseCompletionReasoning',
|
||||
context.userQuery,
|
||||
phase,
|
||||
tool.name,
|
||||
tool,
|
||||
selection.completionReasoning || 'Nachergänzung zur Vervollständigung der Phasenabdeckung'
|
||||
);
|
||||
|
||||
const reasoningResult = await this.callMicroTaskAI(reasoningPrompt, context, 400, 'phase-completion-reasoning');
|
||||
|
||||
let detailedJustification: string;
|
||||
let moderatedTaskRelevance = 75;
|
||||
|
||||
if (reasoningResult.success && reasoningResult.content.trim()) {
|
||||
detailedJustification = reasoningResult.content.trim();
|
||||
moderatedTaskRelevance = this.moderateTaskRelevance(80);
|
||||
} else {
|
||||
detailedJustification = `Nachträglich hinzugefügt zur Vervollständigung der ${phase.name}-Phase. Die ursprüngliche KI-Auswahl war zu spezifisch und hat wichtige Tools für diese Phase übersehen.`;
|
||||
moderatedTaskRelevance = this.moderateTaskRelevance(75);
|
||||
}
|
||||
|
||||
this.addToolToSelection(
|
||||
context,
|
||||
tool,
|
||||
phase.id,
|
||||
'medium',
|
||||
detailedJustification,
|
||||
moderatedTaskRelevance,
|
||||
['Nachträgliche Ergänzung via semantische Phasensuche mit KI-Bewertung']
|
||||
);
|
||||
|
||||
auditService.addPhaseCompletion(
|
||||
phase.id,
|
||||
[tool.name],
|
||||
detailedJustification,
|
||||
phaseStart,
|
||||
{
|
||||
toolName: tool.name,
|
||||
toolType: tool.type,
|
||||
semanticSimilarity: phaseResults.find(r => r.name === tool.name)?.similarity,
|
||||
completionReason: 'underrepresented-phase',
|
||||
originalSelectionMissed: true,
|
||||
aiReasoningUsed: reasoningResult.success,
|
||||
moderatedTaskRelevance
|
||||
}
|
||||
);
|
||||
|
||||
console.log('[AI-PIPELINE] Added phase completion tool with AI reasoning:', tool.name);
|
||||
}
|
||||
|
||||
return {
|
||||
taskType: 'phase-completion',
|
||||
content: selection.completionReasoning || '',
|
||||
processingTimeMs: Date.now() - phaseStart,
|
||||
success: true
|
||||
};
|
||||
|
||||
} catch (error) {
|
||||
console.error('[AI-PIPELINE] Phase completion failed for:', phase.id, error);
|
||||
|
||||
auditService.addEntry(
|
||||
'phase-completion',
|
||||
'completion-failed',
|
||||
{ phaseId: phase.id, error: error.message },
|
||||
{ success: false },
|
||||
20,
|
||||
phaseStart,
|
||||
{
|
||||
errorType: error.constructor.name,
|
||||
phaseId: phase.id
|
||||
}
|
||||
);
|
||||
|
||||
return {
|
||||
taskType: 'phase-completion',
|
||||
content: '',
|
||||
processingTimeMs: Date.now() - phaseStart,
|
||||
success: false,
|
||||
error: error.message
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private moderateTaskRelevance(taskRelevance: number): number {
|
||||
if (typeof taskRelevance !== 'number') {
|
||||
return 70;
|
||||
}
|
||||
|
||||
let moderated = Math.min(taskRelevance, this.config.taskRelevanceModeration.maxInitialScore);
|
||||
|
||||
if (moderated > this.config.taskRelevanceModeration.moderationThreshold) {
|
||||
const excess = moderated - this.config.taskRelevanceModeration.moderationThreshold;
|
||||
moderated = this.config.taskRelevanceModeration.moderationThreshold + (excess * 0.7);
|
||||
}
|
||||
|
||||
return Math.round(Math.min(moderated, this.config.taskRelevanceModeration.maxInitialScore));
|
||||
}
|
||||
|
||||
private async analyzeScenario(context: PipelineContext, pipelineStart: number): Promise<MicroTaskResult> {
|
||||
console.log('[AI-PIPELINE] Micro-task: Scenario analysis');
|
||||
const taskStart = Date.now();
|
||||
@@ -386,7 +656,6 @@ class AIPipeline {
|
||||
|
||||
this.addToContextHistory(context, `${isWorkflow ? 'Szenario' : 'Problem'}-Analyse: ${result.content.slice(0, 200)}...`);
|
||||
|
||||
// AUDIT: Scenario analysis
|
||||
auditService.addAIDecision(
|
||||
'contextual-analysis',
|
||||
prompt,
|
||||
@@ -418,7 +687,6 @@ class AIPipeline {
|
||||
context.investigationApproach = result.content;
|
||||
this.addToContextHistory(context, `${isWorkflow ? 'Untersuchungs' : 'Lösungs'}ansatz: ${result.content.slice(0, 200)}...`);
|
||||
|
||||
// AUDIT: Investigation approach
|
||||
auditService.addAIDecision(
|
||||
'contextual-analysis',
|
||||
prompt,
|
||||
@@ -451,7 +719,6 @@ class AIPipeline {
|
||||
context.criticalConsiderations = result.content;
|
||||
this.addToContextHistory(context, `Kritische Überlegungen: ${result.content.slice(0, 200)}...`);
|
||||
|
||||
// AUDIT: Critical considerations
|
||||
auditService.addAIDecision(
|
||||
'contextual-analysis',
|
||||
prompt,
|
||||
@@ -479,14 +746,14 @@ class AIPipeline {
|
||||
console.log('[AI-PIPELINE] Micro-task: Tool evaluation for:', tool.name);
|
||||
const taskStart = Date.now();
|
||||
const existingSelection = context.selectedTools?.find((st: any) => st.tool && st.tool.name === tool.name);
|
||||
const taskRelevance = existingSelection?.taskRelevance || 70;
|
||||
const priority = this.derivePriorityFromScore(taskRelevance);
|
||||
const originalTaskRelevance = existingSelection?.taskRelevance || 70;
|
||||
const moderatedTaskRelevance = this.moderateTaskRelevance(originalTaskRelevance);
|
||||
const priority = this.derivePriorityFromScore(moderatedTaskRelevance);
|
||||
|
||||
const prompt = getPrompt('toolEvaluation', context.userQuery, tool, rank, taskRelevance);
|
||||
const prompt = getPrompt('toolEvaluation', context.userQuery, tool, rank, moderatedTaskRelevance);
|
||||
const result = await this.callMicroTaskAI(prompt, context, 1000, 'tool-evaluation');
|
||||
|
||||
if (result.success) {
|
||||
// FIXED: Use centralized JSON parsing
|
||||
const evaluation = JSONParser.safeParseJSON(result.content, {
|
||||
detailed_explanation: 'Evaluation failed',
|
||||
implementation_approach: '',
|
||||
@@ -500,16 +767,15 @@ class AIPipeline {
|
||||
evaluation: {
|
||||
...evaluation,
|
||||
rank,
|
||||
task_relevance: taskRelevance
|
||||
task_relevance: moderatedTaskRelevance
|
||||
}
|
||||
}, 'evaluation', priority, evaluation.detailed_explanation, taskRelevance, evaluation.limitations);
|
||||
}, 'evaluation', priority, evaluation.detailed_explanation, moderatedTaskRelevance, evaluation.limitations);
|
||||
|
||||
// AUDIT: Tool evaluation
|
||||
auditService.addAIDecision(
|
||||
'tool-evaluation',
|
||||
prompt,
|
||||
result.content,
|
||||
taskRelevance,
|
||||
moderatedTaskRelevance,
|
||||
`Evaluated tool ${tool.name} for ${context.mode} mode`,
|
||||
taskStart,
|
||||
{
|
||||
@@ -517,7 +783,9 @@ class AIPipeline {
|
||||
toolName: tool.name,
|
||||
toolType: tool.type,
|
||||
rank,
|
||||
taskRelevance,
|
||||
originalTaskRelevance,
|
||||
moderatedTaskRelevance,
|
||||
moderationApplied: originalTaskRelevance !== moderatedTaskRelevance,
|
||||
evaluationParsed: !!evaluation.detailed_explanation,
|
||||
prosCount: evaluation.pros?.length || 0,
|
||||
limitationsCount: evaluation.limitations?.length || 0,
|
||||
@@ -548,7 +816,6 @@ class AIPipeline {
|
||||
const result = await this.callMicroTaskAI(prompt, context, 700, 'background-knowledge');
|
||||
|
||||
if (result.success) {
|
||||
// FIXED: Use centralized JSON parsing
|
||||
const selections = JSONParser.safeParseJSON(result.content, []);
|
||||
|
||||
if (Array.isArray(selections)) {
|
||||
@@ -559,7 +826,6 @@ class AIPipeline {
|
||||
relevance: sel.relevance
|
||||
}));
|
||||
|
||||
// AUDIT: Background knowledge selection
|
||||
auditService.addEntry(
|
||||
'knowledge-synthesis',
|
||||
'concept-selection',
|
||||
@@ -596,7 +862,6 @@ class AIPipeline {
|
||||
const result = await this.callMicroTaskAI(prompt, context, 350, 'final-recommendations');
|
||||
|
||||
if (result.success) {
|
||||
// AUDIT: Final recommendations
|
||||
auditService.addAIDecision(
|
||||
'synthesis',
|
||||
prompt,
|
||||
@@ -617,152 +882,6 @@ class AIPipeline {
|
||||
return result;
|
||||
}
|
||||
|
||||
private async completeUnderrepresentedPhases(context: PipelineContext, toolsData: any, pipelineStart: number): Promise<void> {
|
||||
const phases = toolsData.phases || [];
|
||||
const selectedPhases = new Map<string, number>();
|
||||
|
||||
context.selectedTools?.forEach((st: any) => {
|
||||
const count = selectedPhases.get(st.phase) || 0;
|
||||
selectedPhases.set(st.phase, count + 1);
|
||||
});
|
||||
|
||||
const underrepresentedPhases = phases.filter((phase: any) => {
|
||||
const count = selectedPhases.get(phase.id) || 0;
|
||||
return count <= 1;
|
||||
});
|
||||
|
||||
if (underrepresentedPhases.length === 0) {
|
||||
console.log('[AI-PIPELINE] All phases adequately represented');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('[AI-PIPELINE] Completing underrepresented phases:', underrepresentedPhases.map((p: any) => p.id).join(', '));
|
||||
|
||||
// AUDIT: Phase completion start
|
||||
auditService.addEntry(
|
||||
'phase-completion',
|
||||
'underrepresented-phases-detected',
|
||||
{
|
||||
underrepresentedPhases: underrepresentedPhases.map(p => p.id),
|
||||
currentPhaseDistribution: Array.from(selectedPhases.entries())
|
||||
},
|
||||
{
|
||||
phasesToComplete: underrepresentedPhases.length,
|
||||
completionStrategy: 'semantic-search'
|
||||
},
|
||||
70,
|
||||
pipelineStart,
|
||||
{
|
||||
totalPhases: phases.length,
|
||||
adequatelyRepresented: phases.length - underrepresentedPhases.length,
|
||||
completionMethod: 'semantic-phase-search'
|
||||
}
|
||||
);
|
||||
|
||||
for (const phase of underrepresentedPhases) {
|
||||
await this.completePhaseWithSemanticSearch(context, phase, toolsData, pipelineStart);
|
||||
await this.delay(this.config.microTaskDelay);
|
||||
}
|
||||
}
|
||||
|
||||
private async completePhaseWithSemanticSearch(context: PipelineContext, phase: any, toolsData: any, pipelineStart: number): Promise<void> {
|
||||
const phaseStart = Date.now();
|
||||
const phaseQuery = `forensic ${phase.name.toLowerCase()} tools methods`;
|
||||
|
||||
console.log('[AI-PIPELINE] Phase completion for:', phase.id);
|
||||
|
||||
try {
|
||||
const phaseResults = await embeddingsService.findSimilar(phaseQuery, 20, 0.2);
|
||||
|
||||
// AUDIT: Embeddings search for phase completion
|
||||
auditService.addEmbeddingsSearch(
|
||||
phaseQuery,
|
||||
phaseResults,
|
||||
0.2,
|
||||
phaseStart,
|
||||
{
|
||||
phaseId: phase.id,
|
||||
phaseName: phase.name,
|
||||
completionPurpose: 'underrepresented-phase-enhancement'
|
||||
}
|
||||
);
|
||||
|
||||
if (phaseResults.length === 0) {
|
||||
console.log('[AI-PIPELINE] No semantic results for phase:', phase.id);
|
||||
return;
|
||||
}
|
||||
|
||||
const toolsMap = new Map(toolsData.tools.map((tool: any) => [tool.name, tool]));
|
||||
|
||||
const phaseTools = phaseResults
|
||||
.filter((result: any) => result.type === 'tool')
|
||||
.map((result: any) => toolsMap.get(result.name))
|
||||
.filter((tool: any): tool is NonNullable<any> =>
|
||||
tool !== undefined &&
|
||||
tool !== null &&
|
||||
tool.phases &&
|
||||
Array.isArray(tool.phases) &&
|
||||
tool.phases.includes(phase.id) &&
|
||||
!context.seenToolNames.has(tool.name)
|
||||
)
|
||||
.slice(0, 2);
|
||||
|
||||
if (phaseTools.length === 0) {
|
||||
console.log('[AI-PIPELINE] No suitable tools for phase completion:', phase.id);
|
||||
return;
|
||||
}
|
||||
|
||||
// Add tools with justification and audit each addition
|
||||
for (const tool of phaseTools) {
|
||||
const justification = `Nachträglich hinzugefügt zur Vervollständigung der ${phase.name}-Phase. Die ursprüngliche KI-Auswahl war zu spezifisch und hat wichtige Tools für diese Phase übersehen.`;
|
||||
|
||||
this.addToolToSelection(
|
||||
context,
|
||||
tool,
|
||||
phase.id,
|
||||
'medium',
|
||||
justification,
|
||||
75,
|
||||
['Nachträgliche Ergänzung via semantische Phasensuche']
|
||||
);
|
||||
|
||||
// AUDIT: Phase completion tool addition
|
||||
auditService.addPhaseCompletion(
|
||||
phase.id,
|
||||
[tool.name],
|
||||
justification,
|
||||
phaseStart,
|
||||
{
|
||||
toolName: tool.name,
|
||||
toolType: tool.type,
|
||||
semanticSimilarity: phaseResults.find(r => r.name === tool.name)?.similarity,
|
||||
completionReason: 'underrepresented-phase',
|
||||
originalSelectionMissed: true
|
||||
}
|
||||
);
|
||||
|
||||
console.log('[AI-PIPELINE] Added phase completion tool:', tool.name);
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('[AI-PIPELINE] Phase completion failed for:', phase.id, error);
|
||||
|
||||
// AUDIT: Phase completion failure
|
||||
auditService.addEntry(
|
||||
'phase-completion',
|
||||
'completion-failed',
|
||||
{ phaseId: phase.id, error: error.message },
|
||||
{ success: false },
|
||||
20,
|
||||
phaseStart,
|
||||
{
|
||||
errorType: error.constructor.name,
|
||||
phaseId: phase.id
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private buildRecommendation(context: PipelineContext, mode: string, finalContent: string): any {
|
||||
const isWorkflow = mode === 'workflow';
|
||||
|
||||
@@ -795,7 +914,6 @@ class AIPipeline {
|
||||
st.limitations || []
|
||||
);
|
||||
|
||||
// AUDIT: Confidence calculation for each tool
|
||||
auditService.addConfidenceCalculation(
|
||||
st.tool.name,
|
||||
confidence,
|
||||
@@ -803,7 +921,8 @@ class AIPipeline {
|
||||
{
|
||||
phase: st.phase,
|
||||
priority: st.priority,
|
||||
toolType: st.tool.type
|
||||
toolType: st.tool.type,
|
||||
moderatedTaskRelevance: st.taskRelevance
|
||||
}
|
||||
);
|
||||
|
||||
@@ -839,14 +958,14 @@ class AIPipeline {
|
||||
st.limitations || []
|
||||
);
|
||||
|
||||
// AUDIT: Confidence calculation for each tool
|
||||
auditService.addConfidenceCalculation(
|
||||
st.tool.name,
|
||||
confidence,
|
||||
Date.now(),
|
||||
{
|
||||
rank: st.tool.evaluation?.rank || 1,
|
||||
toolType: st.tool.type
|
||||
toolType: st.tool.type,
|
||||
moderatedTaskRelevance: st.taskRelevance
|
||||
}
|
||||
);
|
||||
|
||||
@@ -873,7 +992,6 @@ class AIPipeline {
|
||||
}
|
||||
}
|
||||
|
||||
// Helper methods
|
||||
private async callMicroTaskAI(
|
||||
prompt: string,
|
||||
context: PipelineContext,
|
||||
|
||||
Reference in New Issue
Block a user