diff --git a/src/pages/api/ai/enhance-input.ts b/src/pages/api/ai/enhance-input.ts index 1425cd8..6de1167 100644 --- a/src/pages/api/ai/enhance-input.ts +++ b/src/pages/api/ai/enhance-input.ts @@ -51,7 +51,7 @@ function cleanupExpiredRateLimits(): void { setInterval(cleanupExpiredRateLimits, 5 * 60 * 1000); function createEnhancementPrompt(input: string): string { - return `Sie sind ein DFIR-Experte mit Spezialisierung auf forensische Methodik. Ein Nutzer beschreibt ein forensisches Szenario oder Problem. Analysieren Sie die Eingabe auf Vollständigkeit für eine wissenschaftlich fundierte forensische Untersuchung. + return `Sie sind ein DFIR-Experte mit Spezialisierung auf forensische Methodik. Ein Nutzer beschreibt ein Szenario oder Problem. Analysieren Sie die Eingabe auf Vollständigkeit für eine wissenschaftlich fundierte Untersuchung. ANALYSIEREN SIE DIESE FORENSISCHEN KATEGORIEN: 1. **Incident Context**: Was ist passiert? Welche Angriffsvektoren oder technischen Probleme liegen vor? @@ -64,12 +64,12 @@ ANALYSIEREN SIE DIESE FORENSISCHEN KATEGORIEN: WENN die Beschreibung alle kritischen forensischen Aspekte abdeckt: Geben Sie eine leere Liste [] zurück. -WENN wichtige forensische Details fehlen: Formulieren Sie 2-3 präzise Fragen, die die kritischsten Lücken für eine wissenschaftlich fundierte forensische Analyse schließen. +WENN wichtige Details fehlen: Formulieren Sie 2-3 präzise Fragen, die die kritischsten Lücken für eine wissenschaftlich fundierte Analyse schließen. QUALITÄTSKRITERIEN FÜR FRAGEN: - Forensisch spezifisch, nicht allgemein (NICHT: "Mehr Details?") - Methodisch relevant (NICHT: "Wann passierte das?") -- Priorisiert nach Auswirkung auf die forensische Untersuchungsqualität +- Priorisiert nach Auswirkung auf die Untersuchungsqualität - Die Frage soll maximal 20 Wörter umfassen ANTWORTFORMAT (NUR JSON, KEIN ZUSÄTZLICHER TEXT): @@ -116,7 +116,6 @@ export const POST: APIRoute = async ({ request }) => { const aiResponse = await enqueueApiCall(() => aiService.callAI(systemPrompt, { - maxTokens: 300, temperature: 0.7 }), taskId); diff --git a/src/utils/aiPipeline.ts b/src/utils/aiPipeline.ts index d11ef8a..2304838 100644 --- a/src/utils/aiPipeline.ts +++ b/src/utils/aiPipeline.ts @@ -107,7 +107,6 @@ class AIPipeline { const aiConfig = aiService.getConfig(); const toolsDataHash = getDataVersion?.() || 'unknown'; - // Record the tools.yaml version being used auditService.addEntry( 'initialization', 'tools-data-loaded', @@ -747,7 +746,7 @@ class AIPipeline { prompt, result.content, confidence, - `Analysierte ${isWorkflow ? 'Szenario' : 'Problem'} basierend auf Nutzereingabe: "${context.userQuery.slice(0, 100)}..." - Identifizierte Kernaspekte und Herausforderungen für forensische Untersuchung`, + `Analysierte ${isWorkflow ? 'Szenario' : 'Problem'} basierend auf Nutzereingabe: "${context.userQuery.slice(0, 100)}..." - Identifizierte Kernaspekte und Herausforderungen für Untersuchung`, taskStart, { toolsDataHash: toolsDataHash, @@ -1184,21 +1183,18 @@ class AIPipeline { try { const response = await aiService.callMicroTaskAI(contextPrompt); - // FIX: Ensure ALL AI calls generate audit entries const toolsDataHash = getDataVersion?.() || 'unknown'; const aiConfig = aiService.getConfig(); - // Calculate response confidence for audit trail const responseConfidence = auditService.calculateAIResponseConfidence( response.content, this.getExpectedLengthForTaskType(taskType), taskType ); - // FIX: Always add AI decision audit entry for micro-tasks auditService.addAIDecision( this.getPhaseForTaskType(taskType), - prompt, // Store original prompt without context + prompt, response.content, responseConfidence, this.getReasoningForTaskType(taskType, response.content), @@ -1224,7 +1220,6 @@ class AIPipeline { }; } catch (error) { - // FIX: Also audit failed AI calls for completeness auditService.addEntry( this.getPhaseForTaskType(taskType), 'ai-decision-failed', @@ -1237,7 +1232,7 @@ class AIPipeline { error: error.message, success: false }, - 0, // Zero confidence for failed calls + 0, startTime, { toolsDataHash: getDataVersion?.() || 'unknown', @@ -1299,7 +1294,7 @@ class AIPipeline { }; const taskName = taskNames[taskType] || taskType; - return `KI generierte ${taskName} (${responseLength} Zeichen) - forensisch fundierte Analyse mit methodischer Begründung`; + return `KI generierte ${taskName} (${responseLength} Zeichen) - Analyse mit methodischer Begründung`; } private addToContextHistory(context: PipelineContext, newEntry: string): void { diff --git a/src/utils/auditService.ts b/src/utils/auditService.ts index 9cfffb6..facaba2 100644 --- a/src/utils/auditService.ts +++ b/src/utils/auditService.ts @@ -26,7 +26,6 @@ export interface AuditEntry { completionTokens?: number; toolsDataHash?: string; embeddingsUsed?: boolean; - //selectionMethod?: string; microTaskType?: string; confidenceFactors?: string[]; reasoning?: string; @@ -129,15 +128,15 @@ class AuditService { this.addEntry( phase, 'ai-decision', - { prompt: this.createPromptSummary(aiPrompt) }, // Summary for display only - { response: aiResponse }, // STORE FULL RESPONSE - NO TRUNCATION + { prompt: this.createPromptSummary(aiPrompt) }, + { response: aiResponse }, confidence, startTime, { ...metadata, reasoning, - aiPrompt: aiPrompt, // Full prompt in metadata - aiResponse: aiResponse, // Full response in metadata + aiPrompt: aiPrompt, + aiResponse: aiResponse, decisionBasis: 'ai-analysis' } ); @@ -146,7 +145,6 @@ class AuditService { addToolSelection( selectedTools: string[], availableTools: string[], - //selectionMethod: string, confidence: number, startTime: number, metadata: Record = {} @@ -154,7 +152,6 @@ class AuditService { const calculatedConfidence = this.calculateSelectionConfidence( selectedTools, availableTools, - //selectionMethod, metadata ); @@ -169,7 +166,6 @@ class AuditService { { availableTools: availableTools.slice(0, 10), totalAvailable: availableTools.length, - //selectionMethod: selectionMethod }, { selectedTools: selectedTools, @@ -179,10 +175,8 @@ class AuditService { startTime, { ...metadata, - //selectionMethod, availableToolsCount: availableTools.length, selectedToolsCount: selectedTools.length, - //decisionBasis: selectionMethod.includes('embeddings') ? 'semantic-search' : 'ai-analysis' decisionBasis } ); @@ -288,7 +282,6 @@ class AuditService { private calculateSelectionConfidence( selectedTools: string[], availableTools: string[], - //selectionMethod: string, metadata: Record ): number { let confidence = 50; @@ -303,10 +296,6 @@ class AuditService { confidence -= 20; } - /*if (selectionMethod.includes('embeddings')) { - confidence += 15; - }*/ - if (selectedTools.length >= 5 && selectedTools.length <= 25) { confidence += 10; } @@ -562,9 +551,9 @@ class AuditService { 'background-knowledge': 'Hintergrundwissen-Auswahl', 'final-recommendations': 'Abschließende Empfehlungen' }; - return `KI analysierte ${typeNames[taskType] || taskType} mit ${confidence}% Vertrauen - fundierte forensische Methodikempfehlung`; + return `KI analysierte ${typeNames[taskType] || taskType} mit ${confidence}% Vertrauen - fundierte Empfehlung`; } - return `KI-Entscheidung mit ${confidence}% Vertrauen basierend auf forensischer Expertenanalyse`; + return `KI-Entscheidung mit ${confidence}% Vertrauen basierend auf agentischer Expertenanalyse`; case 'phase-enhancement': const phaseData = input?.phaseName || input?.phaseId; @@ -593,7 +582,6 @@ class AuditService { private inferDecisionBasis(metadata: Record): string { if (metadata.embeddingsUsed) return 'semantic-search'; - //if (metadata.embeddingsUsed || metadata.selectionMethod?.includes('embeddings')) return 'semantic-search'; if (metadata.aiPrompt || metadata.microTaskType) return 'ai-analysis'; if (metadata.semanticQuery && metadata.aiReasoningUsed) return 'hybrid'; return 'rule-based'; diff --git a/src/utils/embeddings.ts b/src/utils/embeddings.ts index 46fe31d..ddbe7ad 100644 --- a/src/utils/embeddings.ts +++ b/src/utils/embeddings.ts @@ -31,7 +31,6 @@ interface EmbeddingsDatabase { } interface EmbeddingsConfig { - //enabled: boolean; endpoint?: string; apiKey?: string; model?: string; @@ -49,14 +48,12 @@ class EmbeddingsService { constructor() { this.config = this.loadConfig(); console.log('[EMBEDDINGS-SERVICE] Initialized:', { - //enabled: this.config.enabled, hasEndpoint: !!this.config.endpoint, hasModel: !!this.config.model }); } private loadConfig(): EmbeddingsConfig { - //const enabled = process.env.AI_EMBEDDINGS_ENABLED === 'true'; const endpoint = process.env.AI_EMBEDDINGS_ENDPOINT; const apiKey = process.env.AI_EMBEDDINGS_API_KEY; const model = process.env.AI_EMBEDDINGS_MODEL; @@ -64,7 +61,6 @@ class EmbeddingsService { const batchDelay = parseInt(process.env.AI_EMBEDDINGS_BATCH_DELAY_MS || '1000', 10); return { - //enabled, endpoint, apiKey, model, @@ -344,21 +340,8 @@ class EmbeddingsService { } } - /*isEnabled(): boolean { - return this.config.enabled; - }*/ - - /*getStats(): { enabled: boolean; initialized: boolean; count: number } { - return { - enabled: this.config.enabled, - initialized: this.isInitialized, - count: this.embeddings.length - }; - }*/ - getStats(): {initialized: boolean; count: number } { return { - //enabled: this.config.enabled, initialized: this.isInitialized, count: this.embeddings.length }; diff --git a/src/utils/toolSelector.ts b/src/utils/toolSelector.ts index fb34570..1d94c6f 100644 --- a/src/utils/toolSelector.ts +++ b/src/utils/toolSelector.ts @@ -99,7 +99,6 @@ class ToolSelector { console.log('[TOOL-SELECTOR] Using embeddings for candidate selection'); - // FIX: Record the start time for audit trail const embeddingsSearchStart = Date.now(); const similarItems = await embeddingsService.findSimilar( @@ -110,13 +109,11 @@ class ToolSelector { console.log('[TOOL-SELECTOR] Embeddings found', similarItems.length, 'similar items'); - // FIX: Import and use auditService to record this embeddings search const { auditService } = await import('./auditService.js'); const { getDataVersion } = await import('./dataService.js'); const toolsDataHash = getDataVersion() || 'unknown'; - // FIX: Add audit entry for initial embeddings search that happens in BOTH modes auditService.addEmbeddingsSearch( userQuery, similarItems, @@ -197,13 +194,11 @@ class ToolSelector { const softwareWithFullData = candidateSoftware.map(this.createToolData); const conceptsWithFullData = candidateConcepts.map(this.createConceptData); - // Unified selection limits (method-agnostic) const maxTools = Math.min(this.config.embeddingSelectionLimit, this.config.noEmbeddingsToolLimit); const maxConcepts = Math.min(this.config.embeddingConceptsLimit, this.config.noEmbeddingsConceptLimit); const methodLimit = Math.ceil(maxTools * this.config.methodSelectionRatio); const softwareLimit = Math.floor(maxTools * this.config.softwareSelectionRatio); - // Build tool list to send const toolsToSend: any[] = [ ...methodsWithFullData.slice(0, methodLimit), ...softwareWithFullData.slice(0, softwareLimit), @@ -211,7 +206,6 @@ class ToolSelector { const remainingCapacity = maxTools - toolsToSend.length; if (remainingCapacity > 0) { - // Fill remainder from whichever bucket still has items const extraMethods = methodsWithFullData.slice(methodLimit, methodLimit + remainingCapacity); const extraSoftware = softwareWithFullData.slice(softwareLimit, softwareLimit + (remainingCapacity - extraMethods.length)); toolsToSend.push(...extraMethods, ...extraSoftware);