embeddings-1 #2

Merged
mstoeck3 merged 11 commits from embeddings-1 into main 2025-08-02 09:59:35 +00:00
2 changed files with 176 additions and 121 deletions
Showing only changes of commit 1b9d9b437b - Show all commits

View File

@ -13,68 +13,60 @@ OIDC_ENDPOINT=https://your-oidc-provider.com
OIDC_CLIENT_ID=your-client-id OIDC_CLIENT_ID=your-client-id
OIDC_CLIENT_SECRET=your-client-secret OIDC_CLIENT_SECRET=your-client-secret
# === AI Configuration === # ===================================================================
# AI CONFIGURATION - Complete Reference for Improved Pipeline
# ===================================================================
# Selector AI (for selection stage, choode a good model) # === CORE AI ENDPOINTS & MODELS ===
AI_SELECTOR_ENDPOINT=https://llm.mikoshi.de AI_API_ENDPOINT=https://llm.mikoshi.de
AI_SELECTOR_API_KEY=sk-DzREDACTEDHA AI_API_KEY=sREDACTED3w
AI_SELECTOR_MODEL=mistral/mistral-medium-latest AI_MODEL='mistral/mistral-small-latest'
# Analyzer AI (for analysis stage, choose a smaller model) # === IMPROVED PIPELINE: Use separate analyzer model (mistral-small is fine) ===
AI_ANALYZER_ENDPOINT=https://llm.mikoshi.de AI_ANALYZER_ENDPOINT=https://llm.mikoshi.de
AI_ANALYZER_API_KEY=sk-DzREDACTEDnHA AI_ANALYZER_API_KEY=skREDACTEDw3w
AI_ANALYZER_MODEL=mistral/mistral-small-latest AI_ANALYZER_MODEL='mistral/mistral-small-latest'
# === Embeddings Configuration === # === EMBEDDINGS CONFIGURATION ===
# Enable/disable semantic embeddings pre-selection
AI_EMBEDDINGS_ENABLED=true AI_EMBEDDINGS_ENABLED=true
# Embeddings API (Mistral recommended)
AI_EMBEDDINGS_ENDPOINT=https://api.mistral.ai/v1/embeddings AI_EMBEDDINGS_ENDPOINT=https://api.mistral.ai/v1/embeddings
AI_EMBEDDINGS_API_KEY=ZSpREDACTED3wL AI_EMBEDDINGS_API_KEY=ZREDACTED3wL
AI_EMBEDDINGS_MODEL=mistral-embed AI_EMBEDDINGS_MODEL=mistral-embed
# Embeddings performance settings
AI_EMBEDDINGS_BATCH_SIZE=20 AI_EMBEDDINGS_BATCH_SIZE=20
AI_EMBEDDINGS_BATCH_DELAY_MS=1000 AI_EMBEDDINGS_BATCH_DELAY_MS=1000
AI_EMBEDDING_CANDIDATES=30
AI_SIMILARITY_THRESHOLD=0.3
# Delay between micro-tasks to respect rate limits (milliseconds) # === PIPELINE: VectorIndex (HNSW) Configuration ===
AI_MICRO_TASK_DELAY_MS=500 AI_MAX_SELECTED_ITEMS=60 # Tools visible to each micro-task
AI_EMBEDDING_CANDIDATES=60 # VectorIndex candidates (HNSW is more efficient)
AI_SIMILARITY_THRESHOLD=0.3 # Not used by VectorIndex (uses cosine distance internally)
# Micro-task specific rate limiting (requests per minute per user) # === MICRO-TASK CONFIGURATION ===
AI_MICRO_TASK_RATE_LIMIT=30 AI_MICRO_TASK_DELAY_MS=500 # Delay between micro-tasks
AI_MICRO_TASK_TIMEOUT_MS=25000 # Timeout per micro-task (increased for full context)
# Maximum parallel micro-tasks (for future parallel processing) # === RATE LIMITING ===
AI_MAX_PARALLEL_TASKS=3 AI_RATE_LIMIT_DELAY_MS=3000 # Main rate limit delay
AI_RATE_LIMIT_MAX_REQUESTS=6 # Main requests per minute (reduced - fewer but richer calls)
AI_MICRO_TASK_RATE_LIMIT=15 # Micro-task requests per minute (was 30)
# Micro-task timeout settings (milliseconds) # === QUEUE MANAGEMENT ===
AI_MICRO_TASK_TIMEOUT_MS=15000
# ENHANCED: Rate Limiting Configuration
# Main query rate limiting (reduced due to micro-tasks)
AI_RATE_LIMIT_DELAY_MS=3000
AI_RATE_LIMIT_MAX_REQUESTS=8
# Smart prompting rate limiting
AI_SMART_PROMPTING_RATE_LIMIT=5
AI_SMART_PROMPTING_WINDOW_MS=60000
# Queue management settings
AI_QUEUE_MAX_SIZE=50 AI_QUEUE_MAX_SIZE=50
AI_QUEUE_CLEANUP_INTERVAL_MS=300000 AI_QUEUE_CLEANUP_INTERVAL_MS=300000
# === Performance & Monitoring === # === PERFORMANCE & MONITORING ===
# Enable detailed micro-task logging AI_MICRO_TASK_DEBUG=true
AI_MICRO_TASK_DEBUG=false
# Enable performance metrics collection
AI_PERFORMANCE_METRICS=true AI_PERFORMANCE_METRICS=true
# Cache settings for AI responses
AI_RESPONSE_CACHE_TTL_MS=3600000 AI_RESPONSE_CACHE_TTL_MS=3600000
# ===================================================================
# LEGACY VARIABLES (still used but less important)
# ===================================================================
# These are still used by other parts of the system:
AI_RESPONSE_CACHE_TTL_MS=3600000 # For caching responses
AI_QUEUE_MAX_SIZE=50 # Queue management
AI_QUEUE_CLEANUP_INTERVAL_MS=300000 # Queue cleanup
# === Application Configuration === # === Application Configuration ===
PUBLIC_BASE_URL=http://localhost:4321 PUBLIC_BASE_URL=http://localhost:4321
NODE_ENV=development NODE_ENV=development

View File

@ -1,8 +1,8 @@
// src/utils/aiPipeline.ts // src/utils/aiPipeline.ts - FIXED: Restore proper structure with context continuity
import { getCompressedToolsDataForAI } from './dataService.js'; import { getCompressedToolsDataForAI } from './dataService.js';
import { embeddingsService, type EmbeddingData } from './embeddings.js'; import { embeddingsService, type EmbeddingData } from './embeddings.js';
import { vectorIndex } from "./vectorIndex.js"; import { vectorIndex } from './vectorIndex.js';
interface AIConfig { interface AIConfig {
endpoint: string; endpoint: string;
@ -31,15 +31,15 @@ interface AnalysisResult {
}; };
} }
// Context object that builds up through pipeline // FIXED: Context object that builds up through pipeline
interface AnalysisContext { interface AnalysisContext {
userQuery: string; userQuery: string;
mode: string; mode: string;
filteredData: any; filteredData: any;
// Context continuity // ADDED: Context continuity
contextHistory: string[]; contextHistory: string[];
// Results // Results (same as original)
scenarioAnalysis?: string; scenarioAnalysis?: string;
problemAnalysis?: string; problemAnalysis?: string;
investigationApproach?: string; investigationApproach?: string;
@ -48,9 +48,6 @@ interface AnalysisContext {
backgroundKnowledge?: Array<{concept: any, relevance: string}>; backgroundKnowledge?: Array<{concept: any, relevance: string}>;
} }
/**
* Improved DFIR microtask pipeline 20250801 revision (bugfixed)
*/
class ImprovedMicroTaskAIPipeline { class ImprovedMicroTaskAIPipeline {
private config: AIConfig; private config: AIConfig;
private maxSelectedItems: number; private maxSelectedItems: number;
@ -61,50 +58,63 @@ class ImprovedMicroTaskAIPipeline {
constructor() { constructor() {
this.config = { this.config = {
endpoint: this.getEnv('AI_ANALYZER_ENDPOINT'), endpoint: this.getEnv('AI_ANALYZER_ENDPOINT'),
apiKey: this.getEnv('AI_ANALYZER_API_KEY'), apiKey: this.getEnv('AI_ANALYZER_API_KEY'),
model: this.getEnv('AI_ANALYZER_MODEL') model: this.getEnv('AI_ANALYZER_MODEL')
}; };
// Candidate selection tuned for higher precision // FIXED: Optimized for vectorIndex (HNSW) usage
this.maxSelectedItems = parseInt(process.env.AI_MAX_SELECTED_ITEMS || '60', 10); this.maxSelectedItems = parseInt(process.env.AI_MAX_SELECTED_ITEMS || '60', 10);
this.embeddingCandidates = parseInt(process.env.AI_EMBEDDING_CANDIDATES || '40', 10); this.embeddingCandidates = parseInt(process.env.AI_EMBEDDING_CANDIDATES || '60', 10); // HNSW is more efficient
this.similarityThreshold = parseFloat(process.env.AI_SIMILARITY_THRESHOLD || '0.5'); this.similarityThreshold = 0.3; // Not used by vectorIndex, kept for fallback compatibility
this.microTaskDelay = parseInt(process.env.AI_MICRO_TASK_DELAY_MS || '500', 10); this.microTaskDelay = parseInt(process.env.AI_MICRO_TASK_DELAY_MS || '500', 10);
} }
private getEnv(key: string): string { private getEnv(key: string): string {
const value = process.env[key]; const value = process.env[key];
if (!value) throw new Error(`Missing environment variable: ${key}`); if (!value) {
throw new Error(`Missing environment variable: ${key}`);
}
return value; return value;
} }
/** Embedding → LLM blended selector */ // IMPROVED: AI-driven selection (no hard-coded keywords)
private async getIntelligentCandidates(userQuery: string, toolsData: any, mode: string) { private async getIntelligentCandidates(userQuery: string, toolsData: any, mode: string) {
const candidateTools = new Set<string>(); let candidateTools = new Set<string>();
const candidateConcepts = new Set<string>(); let candidateConcepts = new Set<string>();
// Method 1: Embeddings-based selection (primary)
if (embeddingsService.isEnabled()) { if (embeddingsService.isEnabled()) {
const similarItems = await vectorIndex.findSimilar(userQuery, this.embeddingCandidates); const similarItems = await embeddingsService.findSimilar(
userQuery,
this.embeddingCandidates,
this.similarityThreshold
);
similarItems.forEach(item => { similarItems.forEach(item => {
if (item.type === 'tool') candidateTools.add(item.name); if (item.type === 'tool') candidateTools.add(item.name);
if (item.type === 'concept') candidateConcepts.add(item.name); if (item.type === 'concept') candidateConcepts.add(item.name);
}); });
console.log(`[PIPELINE] Embedding hits → ${candidateTools.size} tools / ${candidateConcepts.size} concepts`); console.log(`[IMPROVED PIPELINE] Embeddings selected: ${candidateTools.size} tools, ${candidateConcepts.size} concepts`);
if (candidateTools.size >= 20) {
return {
tools: toolsData.tools.filter((tool: any) => candidateTools.has(tool.name)),
concepts: toolsData.concepts.filter((concept: any) => candidateConcepts.has(concept.name)),
domains: toolsData.domains,
phases: toolsData.phases,
'domain-agnostic-software': toolsData['domain-agnostic-software']
};
}
} }
const reducedData = { // Method 2: Fallback AI selection (like original selector)
...toolsData, console.log(`[IMPROVED PIPELINE] Using AI selector fallback`);
tools: candidateTools.size ? toolsData.tools.filter((t: any) => candidateTools.has(t.name)) : toolsData.tools, return await this.fallbackAISelection(userQuery, toolsData, mode);
concepts: candidateConcepts.size ? toolsData.concepts.filter((c: any) => candidateConcepts.has(c.name)) : toolsData.concepts
};
return this.aiSelection(userQuery, reducedData, mode);
} }
/** Languagemodel based selector (no 50item cap) */ // Fallback AI selection
private async aiSelection(userQuery: string, toolsData: any, mode: string) { private async fallbackAISelection(userQuery: string, toolsData: any, mode: string) {
const toolsList = toolsData.tools.map((tool: any) => ({ const toolsList = toolsData.tools.map((tool: any) => ({
name: tool.name, name: tool.name,
type: tool.type, type: tool.type,
@ -124,17 +134,16 @@ class ImprovedMicroTaskAIPipeline {
tags: concept.tags?.slice(0, 5) || [] tags: concept.tags?.slice(0, 5) || []
})); }));
const modeInstruction = const modeInstruction = mode === 'workflow'
mode === 'workflow' ? 'The user wants a COMPREHENSIVE WORKFLOW with multiple tools/methods across different phases.'
? 'The user wants a COMPREHENSIVE WORKFLOW with multiple tools/methods across different phases.' : 'The user wants SPECIFIC TOOLS/METHODS that directly solve their particular problem.';
: 'The user wants SPECIFIC TOOLS/METHODS that directly solve their particular problem.';
const prompt = `You are a DFIR expert tasked with selecting the most relevant tools and concepts for a user query. const prompt = `You are a DFIR expert tasked with selecting the most relevant tools and concepts for a user query.
${modeInstruction} ${modeInstruction}
AVAILABLE TOOLS: AVAILABLE TOOLS:
${JSON.stringify(toolsList, null, 2)} ${JSON.stringify(toolsList.slice(0, 50), null, 2)}
AVAILABLE CONCEPTS: AVAILABLE CONCEPTS:
${JSON.stringify(conceptsList, null, 2)} ${JSON.stringify(conceptsList, null, 2)}
@ -154,19 +163,20 @@ Respond with ONLY this JSON format:
const response = await this.callAI(prompt, 1500); const response = await this.callAI(prompt, 1500);
const cleaned = response.replace(/^```json\s*/i, '').replace(/\s*```\s*$/g, '').trim(); const cleaned = response.replace(/^```json\s*/i, '').replace(/\s*```\s*$/g, '').trim();
const result = JSON.parse(cleaned); const result = JSON.parse(cleaned);
if (!Array.isArray(result.selectedTools) || !Array.isArray(result.selectedConcepts)) { if (!Array.isArray(result.selectedTools) || !Array.isArray(result.selectedConcepts)) {
throw new Error('Invalid selection result structure'); throw new Error('Invalid selection result structure');
} }
const totalSelected = result.selectedTools.length + result.selectedConcepts.length; const totalSelected = result.selectedTools.length + result.selectedConcepts.length;
if (totalSelected > this.maxSelectedItems) { if (totalSelected > this.maxSelectedItems) {
console.warn(`[PIPELINE] Selection exceeded limit (${totalSelected}), truncating`); console.warn(`[IMPROVED PIPELINE] Selection exceeded limit (${totalSelected}), truncating`);
result.selectedTools = result.selectedTools.slice(0, Math.floor(this.maxSelectedItems * 0.8)); result.selectedTools = result.selectedTools.slice(0, Math.floor(this.maxSelectedItems * 0.8));
result.selectedConcepts = result.selectedConcepts.slice(0, Math.ceil(this.maxSelectedItems * 0.2)); result.selectedConcepts = result.selectedConcepts.slice(0, Math.ceil(this.maxSelectedItems * 0.2));
} }
console.log(`[PIPELINE] LLM selector → ${result.selectedTools.length} tools / ${result.selectedConcepts.length} concepts`); console.log(`[IMPROVED PIPELINE] AI selector: ${result.selectedTools.length} tools, ${result.selectedConcepts.length} concepts`);
console.log(`[IMPROVED PIPELINE] AI reasoning: ${result.reasoning}`);
return { return {
tools: toolsData.tools.filter((tool: any) => result.selectedTools.includes(tool.name)), tools: toolsData.tools.filter((tool: any) => result.selectedTools.includes(tool.name)),
@ -175,25 +185,43 @@ Respond with ONLY this JSON format:
phases: toolsData.phases, phases: toolsData.phases,
'domain-agnostic-software': toolsData['domain-agnostic-software'] 'domain-agnostic-software': toolsData['domain-agnostic-software']
}; };
} catch (err) { } catch (error) {
console.error('[PIPELINE] Failed to parse selector response'); console.error('[IMPROVED PIPELINE] Failed to parse selector response');
throw new Error('Invalid JSON response from selector AI'); throw new Error('Invalid JSON response from selector AI');
} }
} }
private delay(ms: number) { return new Promise(res => setTimeout(res, ms)); } private async delay(ms: number): Promise<void> {
return new Promise(resolve => setTimeout(resolve, ms));
private async callMicroTaskAI(prompt: string, context: AnalysisContext, maxTokens = 300): Promise<MicroTaskResult> { }
const start = Date.now();
const contextPrompt = context.contextHistory.length
? `BISHERIGE ANALYSE:\n${context.contextHistory.join('\n\n')}\n\nAKTUELLE AUFGABE:\n${prompt}`
: prompt;
// IMPROVED: Enhanced micro-task with context history
private async callMicroTaskAI(prompt: string, context: AnalysisContext, maxTokens: number = 300): Promise<MicroTaskResult> {
const startTime = Date.now();
// ADDED: Include context history for continuity
const contextPrompt = context.contextHistory.length > 0 ?
`BISHERIGE ANALYSE:\n${context.contextHistory.join('\n\n')}\n\nAKTUELLE AUFGABE:\n${prompt}` :
prompt;
try { try {
const response = await this.callAI(contextPrompt, maxTokens); const response = await this.callAI(contextPrompt, maxTokens);
return { taskType: 'micro-task', content: response.trim(), processingTimeMs: Date.now() - start, success: true };
} catch (e) { return {
return { taskType: 'micro-task', content: '', processingTimeMs: Date.now() - start, success: false, error: (e as Error).message }; taskType: 'micro-task',
content: response.trim(),
processingTimeMs: Date.now() - startTime,
success: true
};
} catch (error) {
return {
taskType: 'micro-task',
content: '',
processingTimeMs: Date.now() - startTime,
success: false,
error: error.message
};
} }
} }
@ -210,8 +238,13 @@ ${isWorkflow ? 'FORENSISCHES SZENARIO' : 'TECHNISCHES PROBLEM'}: "${context.user
Führen Sie eine systematische ${isWorkflow ? 'Szenario-Analyse' : 'Problem-Analyse'} durch und berücksichtigen Sie dabei: Führen Sie eine systematische ${isWorkflow ? 'Szenario-Analyse' : 'Problem-Analyse'} durch und berücksichtigen Sie dabei:
${isWorkflow ? ${isWorkflow ?
`- Auf das Szenario bezogene Problemstellungen` : `- Angriffsvektoren und Bedrohungsmodellierung nach MITRE ATT&CK
`- konkrete problembezogene Aufgabenstellung` - Betroffene Systeme und kritische Infrastrukturen
- Zeitkritische Faktoren und Beweiserhaltung
- Forensische Artefakte und Datenquellen` :
`- Spezifische forensische Herausforderungen
- Verfügbare Datenquellen und deren Integrität
- Methodische Anforderungen für rechtssichere Analyse`
} }
WICHTIG: Antworten Sie NUR in fließendem deutschen Text ohne Listen, Aufzählungen oder Markdown-Formatierung. Maximum 150 Wörter.`; WICHTIG: Antworten Sie NUR in fließendem deutschen Text ohne Listen, Aufzählungen oder Markdown-Formatierung. Maximum 150 Wörter.`;
@ -237,16 +270,19 @@ WICHTIG: Antworten Sie NUR in fließendem deutschen Text ohne Listen, Aufzählun
const isWorkflow = context.mode === 'workflow'; const isWorkflow = context.mode === 'workflow';
const analysis = isWorkflow ? context.scenarioAnalysis : context.problemAnalysis; const analysis = isWorkflow ? context.scenarioAnalysis : context.problemAnalysis;
const prompt = `Basierend auf der Analyse entwickeln Sie einen fundierten ${isWorkflow ? 'Untersuchungsansatz' : 'Lösungsansatz'}. const prompt = `Basierend auf der Analyse entwickeln Sie einen fundierten ${isWorkflow ? 'Untersuchungsansatz' : 'Lösungsansatz'} nach NIST SP 800-86 Methodik.
${isWorkflow ? 'SZENARIO' : 'PROBLEM'}: "${context.userQuery}" ${isWorkflow ? 'SZENARIO' : 'PROBLEM'}: "${context.userQuery}"
Entwickeln Sie einen systematischen ${isWorkflow ? 'Untersuchungsansatz' : 'Lösungsansatz'} unter Berücksichtigung von: Entwickeln Sie einen systematischen ${isWorkflow ? 'Untersuchungsansatz' : 'Lösungsansatz'} unter Berücksichtigung von:
${isWorkflow ? ${isWorkflow ?
`- Triage-Prioritäten nach forensischer Dringlichkeit (wenn zutreffend) `- Triage-Prioritäten nach forensischer Dringlichkeit
- Phasenabfolge nach NIST SP 800-86-Methodik (Datensammlung - Auswertung - Analyse - Report)` : - Phasenabfolge nach NIST-Methodik
`- pragmatischer, zielorientierter Lösungsansatz im benehmen mit Anforderungen an die Reproduzierbarkeit` - Kontaminationsvermeidung und forensische Isolierung` :
`- Methodik-Auswahl nach wissenschaftlichen Kriterien
- Validierung und Verifizierung der gewählten Ansätze
- Integration in bestehende forensische Workflows`
} }
WICHTIG: Antworten Sie NUR in fließendem deutschen Text ohne Listen oder Markdown. Maximum 150 Wörter.`; WICHTIG: Antworten Sie NUR in fließendem deutschen Text ohne Listen oder Markdown. Maximum 150 Wörter.`;
@ -269,11 +305,17 @@ WICHTIG: Antworten Sie NUR in fließendem deutschen Text ohne Listen oder Markdo
${isWorkflow ? 'SZENARIO' : 'PROBLEM'}: "${context.userQuery}" ${isWorkflow ? 'SZENARIO' : 'PROBLEM'}: "${context.userQuery}"
Berücksichtigen Sie folgende Aspekte: Berücksichtigen Sie folgende forensische Aspekte:
${isWorkflow ? ${isWorkflow ?
`- Szenariobezogene typische Problemstellungen, die auftreten können` : `- Time-sensitive evidence preservation
`- Problembezogene Schwierigkeiten, die das Ergebnis negativ beeinträchtigen könnten` - Chain of custody requirements und rechtliche Verwertbarkeit
- Incident containment vs. evidence preservation Dilemma
- Privacy- und Compliance-Anforderungen` :
`- Tool-Validierung und Nachvollziehbarkeit
- False positive/negative Risiken bei der gewählten Methodik
- Qualifikationsanforderungen für die Durchführung
- Dokumentations- und Reporting-Standards`
} }
WICHTIG: Antworten Sie NUR in fließendem deutschen Text ohne Listen oder Markdown. Maximum 120 Wörter.`; WICHTIG: Antworten Sie NUR in fließendem deutschen Text ohne Listen oder Markdown. Maximum 120 Wörter.`;
@ -311,9 +353,10 @@ VERFÜGBARE TOOLS FÜR ${phase.name.toUpperCase()}:
${phaseTools.map((tool: any) => `- ${tool.name}: ${tool.description.slice(0, 100)}...`).join('\n')} ${phaseTools.map((tool: any) => `- ${tool.name}: ${tool.description.slice(0, 100)}...`).join('\n')}
Wählen Sie Methoden/Tools nach forensischen Kriterien aus: Wählen Sie Methoden/Tools nach forensischen Kriterien aus:
- Eignung für die spezifische Lösung des Problems - Court admissibility und Chain of Custody Kompatibilität
- besondere Fähigkeiten der Methode/des Tools, das sie von anderen abgrenzt - Integration in forensische Standard-Workflows
- Reproduzierbarkeit und Objektivität - Reproduzierbarkeit und Dokumentationsqualität
- Objektivität
Antworten Sie AUSSCHLIESSLICH mit diesem JSON-Format (kein zusätzlicher Text): Antworten Sie AUSSCHLIESSLICH mit diesem JSON-Format (kein zusätzlicher Text):
[ [
@ -363,7 +406,7 @@ Antworten Sie AUSSCHLIESSLICH mit diesem JSON-Format (kein zusätzlicher Text):
// MICRO-TASK 5: Tool Evaluation (Tool mode) // MICRO-TASK 5: Tool Evaluation (Tool mode)
private async evaluateSpecificTool(context: AnalysisContext, tool: any, rank: number): Promise<MicroTaskResult> { private async evaluateSpecificTool(context: AnalysisContext, tool: any, rank: number): Promise<MicroTaskResult> {
const prompt = `Bewerten Sie diese Methode/Tool fallbezogen für das spezifische Problem. const prompt = `Bewerten Sie diese Methode/Tool fallbezogen für das spezifische Problem nach forensischen Qualitätskriterien.
PROBLEM: "${context.userQuery}" PROBLEM: "${context.userQuery}"
@ -437,13 +480,13 @@ EMPFOHLENE TOOLS: ${selectedToolNames.join(', ')}
VERFÜGBARE KONZEPTE: VERFÜGBARE KONZEPTE:
${availableConcepts.slice(0, 15).map((concept: any) => `- ${concept.name}: ${concept.description.slice(0, 80)}...`).join('\n')} ${availableConcepts.slice(0, 15).map((concept: any) => `- ${concept.name}: ${concept.description.slice(0, 80)}...`).join('\n')}
Wählen Sie 2-4 Konzepte aus, die für die Lösung des Problems essentiell sind. Wählen Sie 2-4 Konzepte aus, die für das Verständnis der forensischen Methodik essentiell sind.
Antworten Sie AUSSCHLIESSLICH mit diesem JSON-Format: Antworten Sie AUSSCHLIESSLICH mit diesem JSON-Format:
[ [
{ {
"conceptName": "Exakter Konzept-Name", "conceptName": "Exakter Konzept-Name",
"relevance": "Forensische Relevanz: Warum dieses Konzept für die Lösung des Problems kritisch ist" "relevance": "Forensische Relevanz: Warum dieses Konzept für das Verständnis der Methodik kritisch ist"
} }
]`; ]`;
@ -478,21 +521,21 @@ Antworten Sie AUSSCHLIESSLICH mit diesem JSON-Format:
const isWorkflow = context.mode === 'workflow'; const isWorkflow = context.mode === 'workflow';
const prompt = isWorkflow ? const prompt = isWorkflow ?
`Erstellen Sie eine forensisch fundierte Workflow-Empfehlung unter Anwendung der gewählten Methoden/Tools. `Erstellen Sie eine forensisch fundierte Workflow-Empfehlung basierend auf DFIR-Prinzipien.
SZENARIO: "${context.userQuery}" SZENARIO: "${context.userQuery}"
AUSGEWÄHLTE TOOLS: ${context.selectedTools?.map(st => st.tool.name).join(', ') || 'Keine Tools ausgewählt'} AUSGEWÄHLTE TOOLS: ${context.selectedTools?.map(st => st.tool.name).join(', ') || 'Keine Tools ausgewählt'}
Erstellen Sie konkrete Workflow-Schritte für dieses spezifische Szenario unter Berücksichtigung von Objektivität und rechtlicher Verwertbarkeit (Reproduzierbarkeit, Transparenz). Erstellen Sie konkrete methodische Workflow-Schritte für dieses spezifische Szenario unter Berücksichtigung forensischer Best Practices, Objektivität und rechtlicher Verwertbarkeit.
WICHTIG: Antworten Sie NUR in fließendem deutschen Text ohne Listen oder Markdown. Maximum 120 Wörter.` : WICHTIG: Antworten Sie NUR in fließendem deutschen Text ohne Listen oder Markdown. Maximum 120 Wörter.` :
`Erstellen Sie wichtige Überlegungen für die korrekte Methoden-/Tool-Anwendung. `Erstellen Sie wichtige methodische Überlegungen für die korrekte Methoden-/Tool-Anwendung.
PROBLEM: "${context.userQuery}" PROBLEM: "${context.userQuery}"
EMPFOHLENE TOOLS: ${context.selectedTools?.map(st => st.tool.name).join(', ') || 'Keine Methoden/Tools ausgewählt'} EMPFOHLENE TOOLS: ${context.selectedTools?.map(st => st.tool.name).join(', ') || 'Keine Methoden/Tools ausgewählt'}
Geben Sie kritische Überlegungen für die korrekte Anwendung der empfohlenen Methoden/Tools. Geben Sie kritische methodische Überlegungen, Validierungsanforderungen und Qualitätssicherungsmaßnahmen für die korrekte Anwendung der empfohlenen Methoden/Tools.
WICHTIG: Antworten Sie NUR in fließendem deutschen Text ohne Listen oder Markdown. Maximum 100 Wörter.`; WICHTIG: Antworten Sie NUR in fließendem deutschen Text ohne Listen oder Markdown. Maximum 100 Wörter.`;
@ -531,16 +574,26 @@ WICHTIG: Antworten Sie NUR in fließendem deutschen Text ohne Listen oder Markdo
return content; return content;
} }
// MAIN PROCESSING: Restored original structure with context continuity
async processQuery(userQuery: string, mode: string): Promise<AnalysisResult> { async processQuery(userQuery: string, mode: string): Promise<AnalysisResult> {
const startTime = Date.now(); const startTime = Date.now();
let completedTasks = 0; let completedTasks = 0;
let failedTasks = 0; let failedTasks = 0;
console.log(`[IMPROVED PIPELINE] Starting ${mode} query processing with context continuity`);
try { try {
// Stage 1: Get intelligent candidates (embeddings + AI selection)
const toolsData = await getCompressedToolsDataForAI(); const toolsData = await getCompressedToolsDataForAI();
const filteredData = await this.getIntelligentCandidates(userQuery, toolsData, mode); const filteredData = await this.getIntelligentCandidates(userQuery, toolsData, mode);
const context: AnalysisContext = { userQuery, mode, filteredData, contextHistory: [] }; // Initialize context with continuity
const context: AnalysisContext = {
userQuery,
mode,
filteredData,
contextHistory: [] // ADDED: Context continuity
};
console.log(`[IMPROVED PIPELINE] Starting micro-tasks with ${filteredData.tools.length} tools visible`); console.log(`[IMPROVED PIPELINE] Starting micro-tasks with ${filteredData.tools.length} tools visible`);
@ -571,8 +624,8 @@ WICHTIG: Antworten Sie NUR in fließendem deutschen Text ohne Listen oder Markdo
await this.delay(this.microTaskDelay); await this.delay(this.microTaskDelay);
} }
} else { } else {
const shuffled = [...filteredData.tools].sort(() => Math.random() - 0.5); // FIX // Evaluate top 3 tools for specific problem
const topTools = shuffled.slice(0, 3); const topTools = filteredData.tools.slice(0, 3);
for (let i = 0; i < topTools.length; i++) { for (let i = 0; i < topTools.length; i++) {
const evaluationResult = await this.evaluateSpecificTool(context, topTools[i], i + 1); const evaluationResult = await this.evaluateSpecificTool(context, topTools[i], i + 1);
if (evaluationResult.success) completedTasks++; else failedTasks++; if (evaluationResult.success) completedTasks++; else failedTasks++;
@ -589,21 +642,31 @@ WICHTIG: Antworten Sie NUR in fließendem deutschen Text ohne Listen oder Markdo
const finalResult = await this.generateFinalRecommendations(context); const finalResult = await this.generateFinalRecommendations(context);
if (finalResult.success) completedTasks++; else failedTasks++; if (finalResult.success) completedTasks++; else failedTasks++;
const recommendation = this.buildRecommendation(context, mode, ''); // finalContent injected inside omitted logic // Build final recommendation (same as original)
const recommendation = this.buildRecommendation(context, mode, finalResult.content);
const processingStats = { const processingStats = {
embeddingsUsed: embeddingsService.isEnabled(), embeddingsUsed: embeddingsService.isEnabled(),
vectorIndexUsed: embeddingsService.isEnabled(), // VectorIndex is used when embeddings are enabled
candidatesFromEmbeddings: filteredData.tools.length, candidatesFromEmbeddings: filteredData.tools.length,
finalSelectedItems: (context.selectedTools?.length || 0) + (context.backgroundKnowledge?.length || 0), finalSelectedItems: (context.selectedTools?.length || 0) +
(context.backgroundKnowledge?.length || 0),
processingTimeMs: Date.now() - startTime, processingTimeMs: Date.now() - startTime,
microTasksCompleted: completedTasks, microTasksCompleted: completedTasks,
microTasksFailed: failedTasks, microTasksFailed: failedTasks,
contextContinuityUsed: true contextContinuityUsed: true
}; };
return { recommendation, processingStats }; console.log(`[IMPROVED PIPELINE] Completed: ${completedTasks} tasks, Failed: ${failedTasks} tasks`);
console.log(`[IMPROVED PIPELINE] VectorIndex used: ${embeddingsService.isEnabled()}, Candidates: ${filteredData.tools.length}`);
return {
recommendation,
processingStats
};
} catch (error) { } catch (error) {
console.error('[PIPELINE] Processing failed:', error); console.error('[IMPROVED PIPELINE] Processing failed:', error);
throw error; throw error;
} }
} }