fulldata
This commit is contained in:
@@ -4,15 +4,12 @@ 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 { auditService } from './auditService.js';
|
||||
import { JSONParser } from './jsonUtils.js';
|
||||
import { getPrompt } from '../config/prompts.js';
|
||||
import 'dotenv/config';
|
||||
|
||||
interface PipelineConfig {
|
||||
microTaskDelay: number;
|
||||
//maxContextTokens: number;
|
||||
maxPromptTokens: number;
|
||||
taskRelevanceModeration: {
|
||||
maxInitialScore: number;
|
||||
maxWithPhaseBonus: number;
|
||||
@@ -36,7 +33,6 @@ interface MicroTaskResult {
|
||||
interface AnalysisResult {
|
||||
recommendation: any;
|
||||
processingStats: {
|
||||
//embeddingsUsed: boolean;
|
||||
candidatesFromEmbeddings: number;
|
||||
finalSelectedItems: number;
|
||||
processingTimeMs: number;
|
||||
@@ -57,7 +53,6 @@ interface PipelineContext {
|
||||
mode: string;
|
||||
filteredData: any;
|
||||
contextHistory: string[];
|
||||
//maxContextLength: number;
|
||||
currentContextLength: number;
|
||||
scenarioAnalysis?: string;
|
||||
problemAnalysis?: string;
|
||||
@@ -91,16 +86,12 @@ class AIPipeline {
|
||||
constructor() {
|
||||
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),
|
||||
taskRelevanceModeration: {
|
||||
maxInitialScore: 85,
|
||||
maxWithPhaseBonus: 95,
|
||||
moderationThreshold: 80
|
||||
}
|
||||
};
|
||||
|
||||
console.log('[AI-PIPELINE] Initialized with dynamic phase handling');
|
||||
}
|
||||
|
||||
async processQuery(userQuery: string, mode: string): Promise<AnalysisResult> {
|
||||
@@ -108,8 +99,6 @@ class AIPipeline {
|
||||
let completedTasks = 0;
|
||||
let failedTasks = 0;
|
||||
this.totalTokensUsed = 0;
|
||||
|
||||
console.log('[AI-PIPELINE] Starting', mode, 'analysis pipeline');
|
||||
|
||||
auditService.clearAuditTrail();
|
||||
|
||||
@@ -118,90 +107,102 @@ class AIPipeline {
|
||||
const aiConfig = aiService.getConfig();
|
||||
const toolsDataHash = getDataVersion?.() || 'unknown';
|
||||
|
||||
// Record the tools.yaml version being used
|
||||
auditService.addEntry(
|
||||
'initialization',
|
||||
'tools-data-loaded',
|
||||
{
|
||||
toolsFile: 'tools.yaml',
|
||||
hashAlgorithm: 'SHA256'
|
||||
},
|
||||
{
|
||||
toolsDataHash: toolsDataHash,
|
||||
toolsCount: toolsData.tools.length,
|
||||
conceptsCount: toolsData.concepts.length,
|
||||
domainsCount: toolsData.domains.length,
|
||||
phasesCount: toolsData.phases.length
|
||||
},
|
||||
100,
|
||||
Date.now(),
|
||||
{
|
||||
toolsDataHash: toolsDataHash,
|
||||
verification: `Users can verify with: sha256sum src/data/tools.yaml`,
|
||||
dataVersion: toolsDataHash.slice(0, 12),
|
||||
reasoning: `Geladen: ${toolsData.tools.length} Tools, ${toolsData.concepts.length} Konzepte aus tools.yaml (Hash: ${toolsDataHash.slice(0, 12)}...)`
|
||||
}
|
||||
);
|
||||
|
||||
const context: PipelineContext = {
|
||||
userQuery,
|
||||
mode,
|
||||
filteredData: {},
|
||||
contextHistory: [],
|
||||
//maxContextLength: this.config.maxContextTokens,
|
||||
currentContextLength: 0,
|
||||
seenToolNames: new Set<string>(),
|
||||
embeddingsSimilarities: new Map<string, number>(),
|
||||
phaseMetadata: this.initializePhaseMetadata(toolsData.phases)
|
||||
};
|
||||
|
||||
console.log('[AI-PIPELINE] Phase 1: Tool candidate selection');
|
||||
const candidateSelectionStart = Date.now();
|
||||
|
||||
const candidateData = await toolSelector.getIntelligentCandidates(userQuery, toolsData, mode, context);
|
||||
|
||||
const selectionConfidence = this.calculateToolSelectionConfidence(
|
||||
candidateData.tools.length,
|
||||
toolsData.tools.length,
|
||||
//candidateData.selectionMethod,
|
||||
candidateData.concepts.length
|
||||
);
|
||||
|
||||
auditService.addToolSelection(
|
||||
candidateData.tools.map(t => t.name),
|
||||
toolsData.tools.map(t => t.name),
|
||||
//candidateData.selectionMethod,
|
||||
selectionConfidence,
|
||||
candidateSelectionStart,
|
||||
{
|
||||
//embeddingsUsed: embeddingsService.isEnabled(),
|
||||
toolsDataHash: toolsDataHash,
|
||||
totalCandidatesFound: candidateData.tools.length + candidateData.concepts.length,
|
||||
//selectionMethod: candidateData.selectionMethod,
|
||||
reductionRatio: candidateData.tools.length / toolsData.tools.length
|
||||
}
|
||||
);
|
||||
|
||||
context.filteredData = candidateData;
|
||||
|
||||
console.log('[AI-PIPELINE] Phase 2: Contextual analysis');
|
||||
|
||||
const analysisResult = await this.analyzeScenario(context, startTime);
|
||||
const analysisResult = await this.analyzeScenario(context, startTime, toolsDataHash);
|
||||
if (analysisResult.success) completedTasks++; else failedTasks++;
|
||||
this.trackTokenUsage(analysisResult.aiUsage);
|
||||
await this.delay(this.config.microTaskDelay);
|
||||
|
||||
const approachResult = await this.generateApproach(context, startTime);
|
||||
const approachResult = await this.generateApproach(context, startTime, toolsDataHash);
|
||||
if (approachResult.success) completedTasks++; else failedTasks++;
|
||||
this.trackTokenUsage(approachResult.aiUsage);
|
||||
await this.delay(this.config.microTaskDelay);
|
||||
|
||||
const considerationsResult = await this.generateCriticalConsiderations(context, startTime);
|
||||
const considerationsResult = await this.generateCriticalConsiderations(context, startTime, toolsDataHash);
|
||||
if (considerationsResult.success) completedTasks++; else failedTasks++;
|
||||
this.trackTokenUsage(considerationsResult.aiUsage);
|
||||
await this.delay(this.config.microTaskDelay);
|
||||
|
||||
console.log('[AI-PIPELINE] Phase 3: Tool-specific analysis');
|
||||
|
||||
if (mode === 'workflow') {
|
||||
const workflowResults = await this.processWorkflowMode(context, toolsData, completedTasks, failedTasks, startTime);
|
||||
const workflowResults = await this.processWorkflowMode(context, toolsData, completedTasks, failedTasks, startTime, toolsDataHash);
|
||||
completedTasks = workflowResults.completed;
|
||||
failedTasks = workflowResults.failed;
|
||||
} else {
|
||||
const toolResults = await this.processToolMode(context, completedTasks, failedTasks, startTime);
|
||||
const toolResults = await this.processToolMode(context, completedTasks, failedTasks, startTime, toolsDataHash);
|
||||
completedTasks = toolResults.completed;
|
||||
failedTasks = toolResults.failed;
|
||||
}
|
||||
|
||||
console.log('[AI-PIPELINE] Phase 4: Knowledge synthesis');
|
||||
|
||||
const knowledgeResult = await this.selectBackgroundKnowledge(context, startTime);
|
||||
const knowledgeResult = await this.selectBackgroundKnowledge(context, startTime, toolsDataHash);
|
||||
if (knowledgeResult.success) completedTasks++; else failedTasks++;
|
||||
this.trackTokenUsage(knowledgeResult.aiUsage);
|
||||
await this.delay(this.config.microTaskDelay);
|
||||
|
||||
const finalResult = await this.generateFinalRecommendations(context, startTime);
|
||||
const finalResult = await this.generateFinalRecommendations(context, startTime, toolsDataHash);
|
||||
if (finalResult.success) completedTasks++; else failedTasks++;
|
||||
this.trackTokenUsage(finalResult.aiUsage);
|
||||
|
||||
const recommendation = this.buildRecommendation(context, mode, finalResult.content);
|
||||
const recommendation = this.buildRecommendation(context, mode, finalResult.content, toolsDataHash);
|
||||
|
||||
const processingStats = {
|
||||
//embeddingsUsed: embeddingsService.isEnabled(),
|
||||
candidatesFromEmbeddings: candidateData.tools.length,
|
||||
finalSelectedItems: (context.selectedTools?.length || 0) + (context.backgroundKnowledge?.length || 0),
|
||||
processingTimeMs: Date.now() - startTime,
|
||||
@@ -216,16 +217,6 @@ class AIPipeline {
|
||||
maxTokensUsed: 32768
|
||||
};
|
||||
|
||||
console.log('[AI-PIPELINE] Pipeline completed successfully:', {
|
||||
mode,
|
||||
processingTimeMs: processingStats.processingTimeMs,
|
||||
completedTasks,
|
||||
failedTasks,
|
||||
finalItems: processingStats.finalSelectedItems,
|
||||
totalTokensUsed: this.totalTokensUsed,
|
||||
auditEntries: processingStats.auditEntriesGenerated
|
||||
});
|
||||
|
||||
const finalAuditTrail = auditService.finalizeAuditTrail();
|
||||
|
||||
return {
|
||||
@@ -249,7 +240,6 @@ class AIPipeline {
|
||||
phaseComplexity: Map<string, number>;
|
||||
} {
|
||||
if (!phases || !Array.isArray(phases)) {
|
||||
console.warn('[AI-PIPELINE] No phases data available, using fallback');
|
||||
return {
|
||||
phases: [],
|
||||
criticalPhaseIds: [],
|
||||
@@ -268,20 +258,12 @@ class AIPipeline {
|
||||
const phaseComplexity = new Map<string, number>();
|
||||
phases.forEach(phase => {
|
||||
let complexity = 1;
|
||||
|
||||
if (phase.typical_tools?.length > 5) complexity += 1;
|
||||
if (phase.key_activities?.length > 3) complexity += 1;
|
||||
if (phase.description?.length > 100) complexity += 1;
|
||||
|
||||
phaseComplexity.set(phase.id, complexity);
|
||||
});
|
||||
|
||||
console.log('[AI-PIPELINE] Initialized phase metadata:', {
|
||||
totalPhases: phases.length,
|
||||
criticalPhases: criticalPhaseIds.length,
|
||||
avgComplexity: Array.from(phaseComplexity.values()).reduce((sum, c) => sum + c, 0) / phases.length
|
||||
});
|
||||
|
||||
return {
|
||||
phases,
|
||||
criticalPhaseIds,
|
||||
@@ -292,11 +274,9 @@ class AIPipeline {
|
||||
private calculateToolSelectionConfidence(
|
||||
selectedCount: number,
|
||||
totalCount: number,
|
||||
//method: string,
|
||||
conceptsCount: number
|
||||
): number {
|
||||
let confidence = 50;
|
||||
|
||||
const selectionRatio = selectedCount / totalCount;
|
||||
|
||||
if (selectionRatio >= 0.05 && selectionRatio <= 0.20) {
|
||||
@@ -307,17 +287,8 @@ class AIPipeline {
|
||||
confidence -= 15;
|
||||
}
|
||||
|
||||
//if (method.includes('embeddings')) {
|
||||
//confidence += 15;
|
||||
//}
|
||||
|
||||
if (conceptsCount > 0) {
|
||||
confidence += 10;
|
||||
}
|
||||
|
||||
if (selectedCount >= 8 && selectedCount <= 25) {
|
||||
confidence += 10;
|
||||
}
|
||||
if (conceptsCount > 0) confidence += 10;
|
||||
if (selectedCount >= 8 && selectedCount <= 25) confidence += 10;
|
||||
|
||||
return Math.min(95, Math.max(40, confidence));
|
||||
}
|
||||
@@ -327,7 +298,8 @@ class AIPipeline {
|
||||
toolsData: any,
|
||||
completedTasks: number,
|
||||
failedTasks: number,
|
||||
pipelineStart: number
|
||||
pipelineStart: number,
|
||||
toolsDataHash: string
|
||||
): Promise<{ completed: number; failed: number }> {
|
||||
const phases = toolsData.phases || [];
|
||||
|
||||
@@ -337,10 +309,7 @@ class AIPipeline {
|
||||
tool && tool.phases && Array.isArray(tool.phases) && tool.phases.includes(phase.id)
|
||||
);
|
||||
|
||||
if (phaseTools.length === 0) {
|
||||
console.log(`[AI-PIPELINE] No tools available for phase: ${phase.id}`);
|
||||
continue;
|
||||
}
|
||||
if (phaseTools.length === 0) continue;
|
||||
|
||||
const selections = await toolSelector.selectToolsForPhase(context.userQuery, phase, phaseTools, context);
|
||||
|
||||
@@ -370,6 +339,7 @@ class AIPipeline {
|
||||
phaseConfidence,
|
||||
phaseStart,
|
||||
{
|
||||
toolsDataHash: toolsDataHash,
|
||||
phaseId: phase.id,
|
||||
availableToolsCount: phaseTools.length,
|
||||
selectedToolsCount: selections.length,
|
||||
@@ -383,7 +353,6 @@ class AIPipeline {
|
||||
if (tool) {
|
||||
const moderatedTaskRelevance = this.moderateTaskRelevance(sel.taskRelevance);
|
||||
const priority = this.derivePriorityFromScore(moderatedTaskRelevance);
|
||||
|
||||
const dynamicLimitations = this.generateDynamicLimitations(tool, phase, sel);
|
||||
|
||||
this.addToolToSelection(context, tool, phase.id, priority, sel.justification, moderatedTaskRelevance, dynamicLimitations);
|
||||
@@ -405,6 +374,7 @@ class AIPipeline {
|
||||
moderatedTaskRelevance || 70,
|
||||
phaseStart,
|
||||
{
|
||||
toolsDataHash: toolsDataHash,
|
||||
toolType: tool.type,
|
||||
priority,
|
||||
moderationApplied: sel.taskRelevance !== moderatedTaskRelevance,
|
||||
@@ -418,7 +388,7 @@ class AIPipeline {
|
||||
await this.delay(this.config.microTaskDelay);
|
||||
}
|
||||
|
||||
const completionResult = await this.completeUnderrepresentedPhases(context, toolsData, pipelineStart);
|
||||
const completionResult = await this.completeUnderrepresentedPhases(context, toolsData, pipelineStart, toolsDataHash);
|
||||
completedTasks += completionResult.completed;
|
||||
failedTasks += completionResult.failed;
|
||||
|
||||
@@ -437,7 +407,6 @@ class AIPipeline {
|
||||
}
|
||||
): number {
|
||||
let confidence = 60;
|
||||
|
||||
const isCritical = phaseMetadata?.criticalPhaseIds.includes(phaseId) || false;
|
||||
const phaseComplexity = phaseMetadata?.phaseComplexity.get(phaseId) || 1;
|
||||
|
||||
@@ -454,13 +423,8 @@ class AIPipeline {
|
||||
confidence += 10;
|
||||
}
|
||||
|
||||
if (isCritical && selectedCount >= 2) {
|
||||
confidence += 10;
|
||||
}
|
||||
|
||||
if (phaseComplexity > 2 && selectedCount >= phaseComplexity) {
|
||||
confidence += 5;
|
||||
}
|
||||
if (isCritical && selectedCount >= 2) confidence += 10;
|
||||
if (phaseComplexity > 2 && selectedCount >= phaseComplexity) confidence += 5;
|
||||
|
||||
const avgRelevance = selections.length > 0 ?
|
||||
selections.reduce((sum, s) => sum + (s.taskRelevance || 70), 0) / selections.length : 0;
|
||||
@@ -504,12 +468,13 @@ class AIPipeline {
|
||||
context: PipelineContext,
|
||||
completedTasks: number,
|
||||
failedTasks: number,
|
||||
pipelineStart: number
|
||||
pipelineStart: number,
|
||||
toolsDataHash: string
|
||||
): Promise<{ completed: number; failed: number }> {
|
||||
const topTools = context.filteredData.tools.slice(0, 3);
|
||||
|
||||
for (let i = 0; i < topTools.length; i++) {
|
||||
const evaluationResult = await this.evaluateSpecificTool(context, topTools[i], i + 1, pipelineStart);
|
||||
const evaluationResult = await this.evaluateSpecificTool(context, topTools[i], i + 1, pipelineStart, toolsDataHash);
|
||||
if (evaluationResult.success) completedTasks++; else failedTasks++;
|
||||
this.trackTokenUsage(evaluationResult.aiUsage);
|
||||
await this.delay(this.config.microTaskDelay);
|
||||
@@ -521,7 +486,8 @@ class AIPipeline {
|
||||
private async completeUnderrepresentedPhases(
|
||||
context: PipelineContext,
|
||||
toolsData: any,
|
||||
pipelineStart: number
|
||||
pipelineStart: number,
|
||||
toolsDataHash: string
|
||||
): Promise<{ completed: number; failed: number }> {
|
||||
const phases = toolsData.phases || [];
|
||||
const selectedPhases = new Map<string, number>();
|
||||
@@ -538,15 +504,10 @@ class AIPipeline {
|
||||
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(', '));
|
||||
if (underrepresentedPhases.length === 0) return { completed: 0, failed: 0 };
|
||||
|
||||
for (const phase of underrepresentedPhases) {
|
||||
const result = await this.completePhaseWithSemanticSearchAndAI(context, phase, toolsData, pipelineStart);
|
||||
const result = await this.completePhaseWithSemanticSearchAndAI(context, phase, toolsData, pipelineStart, toolsDataHash);
|
||||
if (result.success) completedTasks++; else failedTasks++;
|
||||
await this.delay(this.config.microTaskDelay);
|
||||
}
|
||||
@@ -558,13 +519,12 @@ class AIPipeline {
|
||||
context: PipelineContext,
|
||||
phase: any,
|
||||
toolsData: any,
|
||||
pipelineStart: number
|
||||
pipelineStart: number,
|
||||
toolsDataHash: string
|
||||
): 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);
|
||||
|
||||
@@ -574,6 +534,7 @@ class AIPipeline {
|
||||
0.2,
|
||||
phaseStart,
|
||||
{
|
||||
toolsDataHash: toolsDataHash,
|
||||
phaseId: phase.id,
|
||||
phaseName: phase.name,
|
||||
completionPurpose: 'underrepresented-phase-enhancement'
|
||||
@@ -581,7 +542,6 @@ class AIPipeline {
|
||||
);
|
||||
|
||||
if (phaseResults.length === 0) {
|
||||
console.log('[AI-PIPELINE] No semantic results for phase:', phase.id);
|
||||
return {
|
||||
taskType: 'phase-completion',
|
||||
content: '',
|
||||
@@ -613,7 +573,6 @@ class AIPipeline {
|
||||
.slice(0, 2);
|
||||
|
||||
if (phaseTools.length === 0) {
|
||||
console.log('[AI-PIPELINE] No suitable tools for phase completion:', phase.id);
|
||||
return {
|
||||
taskType: 'phase-completion',
|
||||
content: '',
|
||||
@@ -623,10 +582,9 @@ class AIPipeline {
|
||||
}
|
||||
|
||||
const selectionPrompt = getPrompt('generatePhaseCompletionPrompt', context.userQuery, phase, phaseTools, phaseConcepts);
|
||||
const selectionResult = await this.callMicroTaskAI(selectionPrompt, context, 800, 'phase-completion-selection');
|
||||
const selectionResult = await this.callMicroTaskAI(selectionPrompt, context, 'phase-completion-selection');
|
||||
|
||||
if (!selectionResult.success) {
|
||||
console.error('[AI-PIPELINE] Phase completion selection failed for:', phase.id);
|
||||
return {
|
||||
taskType: 'phase-completion',
|
||||
content: '',
|
||||
@@ -648,7 +606,6 @@ class AIPipeline {
|
||||
.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 || '',
|
||||
@@ -660,8 +617,6 @@ class AIPipeline {
|
||||
const actualToolsAdded = validTools.map(tool => tool.name);
|
||||
|
||||
for (const tool of validTools) {
|
||||
console.log('[AI-PIPELINE] Generating AI reasoning for phase completion tool:', tool.name);
|
||||
|
||||
const reasoningPrompt = getPrompt(
|
||||
'phaseCompletionReasoning',
|
||||
context.userQuery,
|
||||
@@ -671,7 +626,7 @@ class AIPipeline {
|
||||
selection.completionReasoning || 'Nachergänzung zur Vervollständigung der Phasenabdeckung'
|
||||
);
|
||||
|
||||
const reasoningResult = await this.callMicroTaskAI(reasoningPrompt, context, 400, 'phase-completion-reasoning');
|
||||
const reasoningResult = await this.callMicroTaskAI(reasoningPrompt, context, 'phase-completion-reasoning');
|
||||
|
||||
let detailedJustification: string;
|
||||
let moderatedTaskRelevance = 75;
|
||||
@@ -695,8 +650,6 @@ class AIPipeline {
|
||||
moderatedTaskRelevance,
|
||||
dynamicLimitations
|
||||
);
|
||||
|
||||
console.log('[AI-PIPELINE] Added phase completion tool with AI reasoning:', tool.name);
|
||||
}
|
||||
|
||||
auditService.addPhaseCompletion(
|
||||
@@ -705,6 +658,7 @@ class AIPipeline {
|
||||
selection.completionReasoning || `${actualToolsAdded.length} Tools für ${phase.name} hinzugefügt`,
|
||||
phaseStart,
|
||||
{
|
||||
toolsDataHash: toolsDataHash,
|
||||
toolsAdded: actualToolsAdded,
|
||||
toolType: validTools[0]?.type,
|
||||
semanticSimilarity: phaseResults.find(r => r.name === validTools[0]?.name)?.similarity,
|
||||
@@ -723,8 +677,6 @@ class AIPipeline {
|
||||
};
|
||||
|
||||
} catch (error) {
|
||||
console.error('[AI-PIPELINE] Phase completion failed for:', phase.id, error);
|
||||
|
||||
return {
|
||||
taskType: 'phase-completion',
|
||||
content: '',
|
||||
@@ -756,9 +708,7 @@ class AIPipeline {
|
||||
}
|
||||
|
||||
private moderateTaskRelevance(taskRelevance: number): number {
|
||||
if (typeof taskRelevance !== 'number') {
|
||||
return 70;
|
||||
}
|
||||
if (typeof taskRelevance !== 'number') return 70;
|
||||
|
||||
let moderated = Math.min(taskRelevance, this.config.taskRelevanceModeration.maxInitialScore);
|
||||
|
||||
@@ -770,13 +720,12 @@ class AIPipeline {
|
||||
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');
|
||||
private async analyzeScenario(context: PipelineContext, pipelineStart: number, toolsDataHash: string): Promise<MicroTaskResult> {
|
||||
const taskStart = Date.now();
|
||||
const isWorkflow = context.mode === 'workflow';
|
||||
const prompt = getPrompt('scenarioAnalysis', isWorkflow, context.userQuery);
|
||||
|
||||
const result = await this.callMicroTaskAI(prompt, context, 400, 'scenario-analysis');
|
||||
const result = await this.callMicroTaskAI(prompt, context, 'scenario-analysis');
|
||||
|
||||
if (result.success) {
|
||||
if (isWorkflow) {
|
||||
@@ -801,6 +750,7 @@ class AIPipeline {
|
||||
`Analysierte ${isWorkflow ? 'Szenario' : 'Problem'} basierend auf Nutzereingabe: "${context.userQuery.slice(0, 100)}..." - Identifizierte Kernaspekte und Herausforderungen für forensische Untersuchung`,
|
||||
taskStart,
|
||||
{
|
||||
toolsDataHash: toolsDataHash,
|
||||
microTaskType: 'scenario-analysis',
|
||||
analysisType: isWorkflow ? 'scenario' : 'problem',
|
||||
contentLength: result.content.length,
|
||||
@@ -814,13 +764,12 @@ class AIPipeline {
|
||||
return result;
|
||||
}
|
||||
|
||||
private async generateApproach(context: PipelineContext, pipelineStart: number): Promise<MicroTaskResult> {
|
||||
console.log('[AI-PIPELINE] Micro-task: Investigation approach');
|
||||
private async generateApproach(context: PipelineContext, pipelineStart: number, toolsDataHash: string): Promise<MicroTaskResult> {
|
||||
const taskStart = Date.now();
|
||||
const isWorkflow = context.mode === 'workflow';
|
||||
const prompt = getPrompt('investigationApproach', isWorkflow, context.userQuery);
|
||||
|
||||
const result = await this.callMicroTaskAI(prompt, context, 400, 'investigation-approach');
|
||||
const result = await this.callMicroTaskAI(prompt, context, 'investigation-approach');
|
||||
|
||||
if (result.success) {
|
||||
context.investigationApproach = result.content;
|
||||
@@ -840,6 +789,7 @@ class AIPipeline {
|
||||
`Entwickelte ${isWorkflow ? 'Untersuchungs' : 'Lösungs'}ansatz unter Berücksichtigung der Szenario-Analyse - Strukturierte Herangehensweise für forensische Methodik`,
|
||||
taskStart,
|
||||
{
|
||||
toolsDataHash: toolsDataHash,
|
||||
microTaskType: 'investigation-approach',
|
||||
approachType: isWorkflow ? 'investigation' : 'solution',
|
||||
contentLength: result.content.length,
|
||||
@@ -854,13 +804,12 @@ class AIPipeline {
|
||||
return result;
|
||||
}
|
||||
|
||||
private async generateCriticalConsiderations(context: PipelineContext, pipelineStart: number): Promise<MicroTaskResult> {
|
||||
console.log('[AI-PIPELINE] Micro-task: Critical considerations');
|
||||
private async generateCriticalConsiderations(context: PipelineContext, pipelineStart: number, toolsDataHash: string): Promise<MicroTaskResult> {
|
||||
const taskStart = Date.now();
|
||||
const isWorkflow = context.mode === 'workflow';
|
||||
const prompt = getPrompt('criticalConsiderations', isWorkflow, context.userQuery);
|
||||
|
||||
const result = await this.callMicroTaskAI(prompt, context, 350, 'critical-considerations');
|
||||
const result = await this.callMicroTaskAI(prompt, context, 'critical-considerations');
|
||||
|
||||
if (result.success) {
|
||||
context.criticalConsiderations = result.content;
|
||||
@@ -880,6 +829,7 @@ class AIPipeline {
|
||||
'Identifizierte kritische Überlegungen für forensische Untersuchung - Berücksichtigung von Beweissicherung, Chain of Custody und methodischen Herausforderungen',
|
||||
taskStart,
|
||||
{
|
||||
toolsDataHash: toolsDataHash,
|
||||
microTaskType: 'critical-considerations',
|
||||
contentLength: result.content.length,
|
||||
decisionBasis: 'ai-analysis',
|
||||
@@ -896,9 +846,9 @@ class AIPipeline {
|
||||
context: PipelineContext,
|
||||
tool: any,
|
||||
rank: number,
|
||||
pipelineStart: number
|
||||
pipelineStart: number,
|
||||
toolsDataHash: string
|
||||
): Promise<MicroTaskResult> {
|
||||
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 originalTaskRelevance = existingSelection?.taskRelevance || 70;
|
||||
@@ -906,7 +856,7 @@ class AIPipeline {
|
||||
const priority = this.derivePriorityFromScore(moderatedTaskRelevance);
|
||||
|
||||
const prompt = getPrompt('toolEvaluation', context.userQuery, tool, rank, moderatedTaskRelevance);
|
||||
const result = await this.callMicroTaskAI(prompt, context, 1000, 'tool-evaluation');
|
||||
const result = await this.callMicroTaskAI(prompt, context, 'tool-evaluation');
|
||||
|
||||
if (result.success) {
|
||||
const evaluation = JSONParser.safeParseJSON(result.content, {
|
||||
@@ -942,6 +892,7 @@ class AIPipeline {
|
||||
`Bewertete Tool "${tool.name}" (Rang ${rank}) - Analysierte Eignung für spezifische Aufgabenstellung mit Fokus auf praktische Anwendbarkeit und methodische Integration`,
|
||||
taskStart,
|
||||
{
|
||||
toolsDataHash: toolsDataHash,
|
||||
microTaskType: 'tool-evaluation',
|
||||
toolName: tool.name,
|
||||
toolType: tool.type,
|
||||
@@ -964,8 +915,7 @@ class AIPipeline {
|
||||
return result;
|
||||
}
|
||||
|
||||
private async selectBackgroundKnowledge(context: PipelineContext, pipelineStart: number): Promise<MicroTaskResult> {
|
||||
console.log('[AI-PIPELINE] Micro-task: Background knowledge selection');
|
||||
private async selectBackgroundKnowledge(context: PipelineContext, pipelineStart: number, toolsDataHash: string): Promise<MicroTaskResult> {
|
||||
const taskStart = Date.now();
|
||||
const availableConcepts = context.filteredData.concepts;
|
||||
|
||||
@@ -980,7 +930,7 @@ class AIPipeline {
|
||||
|
||||
const selectedToolNames = context.selectedTools?.map((st: any) => st.tool && st.tool.name).filter(Boolean) || [];
|
||||
const prompt = getPrompt('backgroundKnowledgeSelection', context.userQuery, context.mode, selectedToolNames, availableConcepts);
|
||||
const result = await this.callMicroTaskAI(prompt, context, 700, 'background-knowledge');
|
||||
const result = await this.callMicroTaskAI(prompt, context, 'background-knowledge');
|
||||
|
||||
if (result.success) {
|
||||
const selections = JSONParser.safeParseJSON(result.content, []);
|
||||
@@ -1017,6 +967,7 @@ class AIPipeline {
|
||||
finalConfidence,
|
||||
taskStart,
|
||||
{
|
||||
toolsDataHash: toolsDataHash,
|
||||
microTaskType: 'background-knowledge',
|
||||
availableConceptsCount: availableConcepts.length,
|
||||
selectedConceptsCount: context.backgroundKnowledge.length,
|
||||
@@ -1041,32 +992,25 @@ class AIPipeline {
|
||||
): number {
|
||||
let bonus = 0;
|
||||
|
||||
if (selectedKnowledge.length > 0) {
|
||||
bonus += 10;
|
||||
}
|
||||
if (selectedKnowledge.length > 0) bonus += 10;
|
||||
|
||||
const ratio = selectedKnowledge.length / availableConcepts.length;
|
||||
if (ratio >= 0.1 && ratio <= 0.3) {
|
||||
bonus += 15;
|
||||
}
|
||||
if (ratio >= 0.1 && ratio <= 0.3) bonus += 15;
|
||||
|
||||
const hasGoodReasonings = selectedKnowledge.some(bk =>
|
||||
bk.relevance && bk.relevance.length > 30
|
||||
);
|
||||
if (hasGoodReasonings) {
|
||||
bonus += 10;
|
||||
}
|
||||
if (hasGoodReasonings) bonus += 10;
|
||||
|
||||
return bonus;
|
||||
}
|
||||
|
||||
private async generateFinalRecommendations(context: PipelineContext, pipelineStart: number): Promise<MicroTaskResult> {
|
||||
console.log('[AI-PIPELINE] Micro-task: Final recommendations');
|
||||
private async generateFinalRecommendations(context: PipelineContext, pipelineStart: number, toolsDataHash: string): Promise<MicroTaskResult> {
|
||||
const taskStart = Date.now();
|
||||
const selectedToolNames = context.selectedTools?.map((st: any) => st.tool && st.tool.name).filter(Boolean) || [];
|
||||
const prompt = getPrompt('finalRecommendations', context.mode === 'workflow', context.userQuery, selectedToolNames);
|
||||
|
||||
const result = await this.callMicroTaskAI(prompt, context, 350, 'final-recommendations');
|
||||
const result = await this.callMicroTaskAI(prompt, context, 'final-recommendations');
|
||||
|
||||
if (result.success) {
|
||||
const confidence = auditService.calculateAIResponseConfidence(
|
||||
@@ -1086,6 +1030,7 @@ class AIPipeline {
|
||||
`Generierte abschließende ${context.mode}-Empfehlungen basierend auf ausgewählten ${selectedToolNames.length} Tools - Synthese aller Analyseschritte zu kohärenter Handlungsempfehlung`,
|
||||
taskStart,
|
||||
{
|
||||
toolsDataHash: toolsDataHash,
|
||||
microTaskType: 'final-recommendations',
|
||||
mode: context.mode,
|
||||
selectedToolsCount: selectedToolNames.length,
|
||||
@@ -1105,30 +1050,17 @@ class AIPipeline {
|
||||
private calculateSynthesisBonus(selectedToolNames: string[], context: PipelineContext): number {
|
||||
let bonus = 0;
|
||||
|
||||
if (selectedToolNames.length >= 3) {
|
||||
bonus += 10;
|
||||
}
|
||||
|
||||
if (context.backgroundKnowledge && context.backgroundKnowledge.length > 0) {
|
||||
bonus += 10;
|
||||
}
|
||||
|
||||
if (context.scenarioAnalysis || context.problemAnalysis) {
|
||||
bonus += 5;
|
||||
}
|
||||
|
||||
if (context.investigationApproach) {
|
||||
bonus += 5;
|
||||
}
|
||||
if (selectedToolNames.length >= 3) bonus += 10;
|
||||
if (context.backgroundKnowledge && context.backgroundKnowledge.length > 0) bonus += 10;
|
||||
if (context.scenarioAnalysis || context.problemAnalysis) bonus += 5;
|
||||
if (context.investigationApproach) bonus += 5;
|
||||
|
||||
return bonus;
|
||||
}
|
||||
|
||||
private buildRecommendation(context: PipelineContext, mode: string, finalContent: string): any {
|
||||
private buildRecommendation(context: PipelineContext, mode: string, finalContent: string, toolsDataHash: string): any {
|
||||
const isWorkflow = mode === 'workflow';
|
||||
|
||||
console.log('[AI-PIPELINE] Building recommendation for', mode, 'mode with', context.selectedTools?.length || 0, 'tools');
|
||||
|
||||
const base = {
|
||||
[isWorkflow ? 'scenario_analysis' : 'problem_analysis']:
|
||||
isWorkflow ? context.scenarioAnalysis : context.problemAnalysis,
|
||||
@@ -1161,6 +1093,7 @@ class AIPipeline {
|
||||
confidence,
|
||||
Date.now(),
|
||||
{
|
||||
toolsDataHash: toolsDataHash,
|
||||
phase: st.phase,
|
||||
priority: st.priority,
|
||||
toolType: st.tool.type,
|
||||
@@ -1205,6 +1138,7 @@ class AIPipeline {
|
||||
confidence,
|
||||
Date.now(),
|
||||
{
|
||||
toolsDataHash: toolsDataHash,
|
||||
rank: st.tool.evaluation?.rank || 1,
|
||||
toolType: st.tool.type,
|
||||
moderatedTaskRelevance: st.taskRelevance
|
||||
@@ -1237,7 +1171,6 @@ class AIPipeline {
|
||||
private async callMicroTaskAI(
|
||||
prompt: string,
|
||||
context: PipelineContext,
|
||||
maxTokens: number = 500,
|
||||
taskType: string = 'micro-task'
|
||||
): Promise<MicroTaskResult> {
|
||||
const startTime = Date.now();
|
||||
@@ -1245,15 +1178,11 @@ class AIPipeline {
|
||||
let contextPrompt = prompt;
|
||||
if (context.contextHistory.length > 0) {
|
||||
const contextSection = `BISHERIGE ANALYSE:\n${context.contextHistory.join('\n\n')}\n\nAKTUELLE AUFGABE:\n`;
|
||||
const combinedPrompt = contextSection + prompt;
|
||||
|
||||
if (aiService.estimateTokens(combinedPrompt) <= this.config.maxPromptTokens) {
|
||||
contextPrompt = combinedPrompt;
|
||||
}
|
||||
contextPrompt = contextSection + prompt;
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await aiService.callMicroTaskAI(contextPrompt, maxTokens);
|
||||
const response = await aiService.callMicroTaskAI(contextPrompt);
|
||||
|
||||
return {
|
||||
taskType,
|
||||
@@ -1280,12 +1209,10 @@ class AIPipeline {
|
||||
context.contextHistory.push(newEntry);
|
||||
context.currentContextLength += entryTokens;
|
||||
|
||||
/*while (context.currentContextLength > this.config.maxContextTokens && context.contextHistory.length > 1) {
|
||||
if (context.contextHistory.length > 1) {
|
||||
const removed = context.contextHistory.shift()!;
|
||||
context.currentContextLength -= aiService.estimateTokens(removed);
|
||||
}*/
|
||||
const removed = context.contextHistory.shift()!;
|
||||
context.currentContextLength -= aiService.estimateTokens(removed);
|
||||
}
|
||||
}
|
||||
|
||||
private addToolToSelection(
|
||||
|
||||
Reference in New Issue
Block a user