fix pipeline
This commit is contained in:
		
							parent
							
								
									138a494730
								
							
						
					
					
						commit
						3c6fb568d6
					
				@ -189,6 +189,47 @@ ANTWORT AUSSCHLIESSLICH IM JSON-FORMAT OHNE JEGLICHEN TEXT AUSSERHALB DER JSON-S
 | 
			
		||||
]`;
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  generatePhaseCompletionPrompt(
 | 
			
		||||
    originalQuery: string,
 | 
			
		||||
    phase: any,
 | 
			
		||||
    candidateTools: any[],
 | 
			
		||||
    candidateConcepts: any[]
 | 
			
		||||
  ): string {
 | 
			
		||||
    return `Du bist ein DFIR-Experte. Die Phase "${phase.name}" ist in der aktuellen Analyse unterrepräsentiert.
 | 
			
		||||
 | 
			
		||||
ORIGINAL ANFRAGE: "${originalQuery}"
 | 
			
		||||
PHASE ZU VERVOLLSTÄNDIGEN: ${phase.name} - ${phase.description || ''}
 | 
			
		||||
 | 
			
		||||
Wähle 1-2 BESTE Tools aus den gefundenen Kandidaten, die diese Phase optimal ergänzen:
 | 
			
		||||
 | 
			
		||||
VERFÜGBARE TOOLS (${candidateTools.length}):
 | 
			
		||||
${candidateTools.map((tool: any) => `
 | 
			
		||||
- ${tool.name} (${tool.type})
 | 
			
		||||
  Beschreibung: ${tool.description.slice(0, 120)}...
 | 
			
		||||
  Skill Level: ${tool.skillLevel}
 | 
			
		||||
`).join('')}
 | 
			
		||||
 | 
			
		||||
${candidateConcepts.length > 0 ? `
 | 
			
		||||
VERFÜGBARE KONZEPTE (${candidateConcepts.length}):
 | 
			
		||||
${candidateConcepts.map((concept: any) => `
 | 
			
		||||
- ${concept.name}
 | 
			
		||||
  Beschreibung: ${concept.description.slice(0, 120)}...
 | 
			
		||||
`).join('')}
 | 
			
		||||
` : ''}
 | 
			
		||||
 | 
			
		||||
AUSWAHLREGELN:
 | 
			
		||||
1. Wähle Tools, die die ${phase.name}-Phase der ursprünglichen Anfrage optimal ergänzen
 | 
			
		||||
2. Priorisiere Tools, die zur Gesamtlösung beitragen
 | 
			
		||||
3. Maximal 2 Tools für diese Phase
 | 
			
		||||
 | 
			
		||||
ANTWORT AUSSCHLIESSLICH IM JSON-FORMAT:
 | 
			
		||||
{
 | 
			
		||||
  "selectedTools": ["ToolName1", "ToolName2"],
 | 
			
		||||
  "selectedConcepts": ["ConceptName1"],
 | 
			
		||||
  "reasoning": "Kurze Begründung der Auswahl für ${phase.name}"
 | 
			
		||||
}`;
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  finalRecommendations: (isWorkflow: boolean, userQuery: string, selectedToolNames: string[]) => {
 | 
			
		||||
    const focus = isWorkflow ? 
 | 
			
		||||
      'Workflow-Schritte, Best Practices, Objektivität' :
 | 
			
		||||
@ -213,6 +254,7 @@ export function getPrompt(key: 'phaseToolSelection', userQuery: string, phase: a
 | 
			
		||||
export function getPrompt(key: 'toolEvaluation', userQuery: string, tool: any, rank: number, taskRelevance: number): string;
 | 
			
		||||
export function getPrompt(key: 'backgroundKnowledgeSelection', userQuery: string, mode: string, selectedToolNames: string[], availableConcepts: any[]): string;
 | 
			
		||||
export function getPrompt(key: 'finalRecommendations', isWorkflow: boolean, userQuery: string, selectedToolNames: string[]): string;
 | 
			
		||||
export function getPrompt(key: 'generatePhaseCompletionPrompt', originalQuery: string, phase: any, candidateTools: any[], candidateConcepts: any[]): string;
 | 
			
		||||
export function getPrompt(promptKey: keyof typeof AI_PROMPTS, ...args: any[]): string {
 | 
			
		||||
  try {
 | 
			
		||||
    const promptFunction = AI_PROMPTS[promptKey];
 | 
			
		||||
 | 
			
		||||
@ -1096,6 +1096,168 @@ class ImprovedMicroTaskAIPipeline {
 | 
			
		||||
    return result;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private async completeUnderrepresentedPhases(
 | 
			
		||||
    context: AnalysisContext, 
 | 
			
		||||
    toolsData: any,
 | 
			
		||||
    originalQuery: string
 | 
			
		||||
  ): Promise<void> {
 | 
			
		||||
    const phases = toolsData.phases || [];
 | 
			
		||||
    const selectedPhases = new Map<string, number>();
 | 
			
		||||
    
 | 
			
		||||
    // Count tools per phase from current selection
 | 
			
		||||
    context.selectedTools?.forEach(st => {
 | 
			
		||||
      const count = selectedPhases.get(st.phase) || 0;
 | 
			
		||||
      selectedPhases.set(st.phase, count + 1);
 | 
			
		||||
    });
 | 
			
		||||
    
 | 
			
		||||
    console.log(`[AI PIPELINE] Phase coverage analysis:`);
 | 
			
		||||
    phases.forEach(phase => {
 | 
			
		||||
      const count = selectedPhases.get(phase.id) || 0;
 | 
			
		||||
      console.log(`[AI PIPELINE]   ${phase.id}: ${count} tools`);
 | 
			
		||||
    });
 | 
			
		||||
    
 | 
			
		||||
    // Define phase-specific semantic queries
 | 
			
		||||
    const phaseQueryTemplates = {
 | 
			
		||||
      'data-collection': 'forensic data acquisition imaging memory disk capture evidence collection',
 | 
			
		||||
      'examination': 'forensic analysis parsing extraction artifact examination file system',
 | 
			
		||||
      'analysis': 'forensic correlation timeline analysis pattern detection investigation',
 | 
			
		||||
      'reporting': 'forensic report documentation case management collaboration presentation findings'
 | 
			
		||||
    };
 | 
			
		||||
    
 | 
			
		||||
    // Identify underrepresented phases (0 tools = missing, 1 tool = underrepresented)
 | 
			
		||||
    const underrepresentedPhases = phases.filter(phase => {
 | 
			
		||||
      const count = selectedPhases.get(phase.id) || 0;
 | 
			
		||||
      return count <= 1; // Missing (0) or underrepresented (1)
 | 
			
		||||
    });
 | 
			
		||||
    
 | 
			
		||||
    if (underrepresentedPhases.length === 0) {
 | 
			
		||||
      console.log(`[AI PIPELINE] All phases adequately represented, no completion needed`);
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    console.log(`[AI PIPELINE] Underrepresented phases: ${underrepresentedPhases.map(p => p.id).join(', ')}`);
 | 
			
		||||
    
 | 
			
		||||
    // Process each underrepresented phase
 | 
			
		||||
    for (const phase of underrepresentedPhases) {
 | 
			
		||||
      await this.completePhaseWithSemanticSearch(context, phase, phaseQueryTemplates, toolsData, originalQuery);
 | 
			
		||||
      await this.delay(this.microTaskDelay);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private async completePhaseWithSemanticSearch(
 | 
			
		||||
    context: AnalysisContext,
 | 
			
		||||
    phase: any,
 | 
			
		||||
    phaseQueryTemplates: Record<string, string>,
 | 
			
		||||
    toolsData: any,
 | 
			
		||||
    originalQuery: string
 | 
			
		||||
  ): Promise<void> {
 | 
			
		||||
    const phaseStart = Date.now();
 | 
			
		||||
    
 | 
			
		||||
    // Generate phase-specific semantic query
 | 
			
		||||
    const phaseQuery = phaseQueryTemplates[phase.id] || `forensic ${phase.name.toLowerCase()} tools methods`;
 | 
			
		||||
    
 | 
			
		||||
    console.log(`[AI PIPELINE] Completing phase ${phase.id} with query: "${phaseQuery}"`);
 | 
			
		||||
    
 | 
			
		||||
    try {
 | 
			
		||||
      // Run semantic search with phase-specific query
 | 
			
		||||
      const phaseResults = await embeddingsService.findSimilar(
 | 
			
		||||
        phaseQuery,
 | 
			
		||||
        20, // Smaller set for phase completion
 | 
			
		||||
        0.2  // Lower threshold for more results
 | 
			
		||||
      );
 | 
			
		||||
      
 | 
			
		||||
      if (phaseResults.length === 0) {
 | 
			
		||||
        console.log(`[AI PIPELINE] No semantic results for phase ${phase.id}`);
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
      
 | 
			
		||||
      // Filter to tools that actually belong to this phase
 | 
			
		||||
      const toolsMap = new Map<string, any>(toolsData.tools.map((tool: any) => [tool.name, tool]));
 | 
			
		||||
      const conceptsMap = new Map<string, any>(toolsData.concepts.map((concept: any) => [concept.name, concept]));
 | 
			
		||||
      
 | 
			
		||||
      const phaseTools = phaseResults
 | 
			
		||||
        .filter(result => result.type === 'tool')
 | 
			
		||||
        .map(result => toolsMap.get(result.name))
 | 
			
		||||
        .filter((tool): tool is any => 
 | 
			
		||||
          tool !== undefined && 
 | 
			
		||||
          tool.phases && 
 | 
			
		||||
          tool.phases.includes(phase.id) &&
 | 
			
		||||
          !context.seenToolNames.has(tool.name) // Don't re-select already chosen tools
 | 
			
		||||
        )
 | 
			
		||||
        .slice(0, 5); // Top 5 candidates for this phase
 | 
			
		||||
      
 | 
			
		||||
      const phaseConcepts = phaseResults
 | 
			
		||||
        .filter(result => result.type === 'concept')
 | 
			
		||||
        .map(result => conceptsMap.get(result.name))
 | 
			
		||||
        .filter((concept): concept is any => concept !== undefined)
 | 
			
		||||
        .slice(0, 2); // Top 2 concepts
 | 
			
		||||
      
 | 
			
		||||
      console.log(`[AI PIPELINE] Phase ${phase.id} semantic search found: ${phaseTools.length} tools, ${phaseConcepts.length} concepts`);
 | 
			
		||||
      
 | 
			
		||||
      if (phaseTools.length === 0) {
 | 
			
		||||
        console.log(`[AI PIPELINE] No suitable tools found for phase ${phase.id} after filtering`);
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
      
 | 
			
		||||
      const prompt = AI_PROMPTS.generatePhaseCompletionPrompt(originalQuery, phase, phaseTools, phaseConcepts);
 | 
			
		||||
      
 | 
			
		||||
      const response = await this.callAI(prompt, 800);
 | 
			
		||||
      const selection = this.safeParseJSON(response, { selectedTools: [], selectedConcepts: [] });
 | 
			
		||||
      
 | 
			
		||||
      const validTools = selection.selectedTools
 | 
			
		||||
        .map(name => phaseTools.find(t => t.name === name))
 | 
			
		||||
        .filter((tool): tool is any => tool !== undefined)
 | 
			
		||||
        .slice(0, 2); 
 | 
			
		||||
      
 | 
			
		||||
      validTools.forEach(tool => {
 | 
			
		||||
        console.log(`[AI PIPELINE] Adding phase completion tool: ${tool.name} for ${phase.id}`);
 | 
			
		||||
        
 | 
			
		||||
        this.addToolToSelection(
 | 
			
		||||
          context,
 | 
			
		||||
          tool,
 | 
			
		||||
          phase.id,
 | 
			
		||||
          'medium', // Phase completion tools get medium priority
 | 
			
		||||
          `Hinzugefügt zur Vervollständigung der ${phase.name}-Phase`,
 | 
			
		||||
          75, // Good relevance for phase-specific search
 | 
			
		||||
          ['Via phasenspezifische semantische Suche hinzugefügt']
 | 
			
		||||
        );
 | 
			
		||||
      });
 | 
			
		||||
      
 | 
			
		||||
      // Audit the phase completion
 | 
			
		||||
      this.addAuditEntry(context, 'validation', 'phase-completion',
 | 
			
		||||
        { 
 | 
			
		||||
          phase: phase.id, 
 | 
			
		||||
          phaseQuery, 
 | 
			
		||||
          candidatesFound: phaseTools.length,
 | 
			
		||||
          originalQuery: originalQuery.slice(0, 100) + '...'
 | 
			
		||||
        },
 | 
			
		||||
        { 
 | 
			
		||||
          toolsAdded: validTools.length,
 | 
			
		||||
          addedTools: validTools.map(t => t.name),
 | 
			
		||||
          semanticResults: phaseResults.length
 | 
			
		||||
        },
 | 
			
		||||
        validTools.length > 0 ? 80 : 40,
 | 
			
		||||
        phaseStart,
 | 
			
		||||
        { 
 | 
			
		||||
          phaseCompletion: true, 
 | 
			
		||||
          semanticSearch: true,
 | 
			
		||||
          originalQueryBias: true 
 | 
			
		||||
        }
 | 
			
		||||
      );
 | 
			
		||||
      
 | 
			
		||||
    } catch (error) {
 | 
			
		||||
      console.error(`[AI PIPELINE] Phase completion failed for ${phase.id}:`, error);
 | 
			
		||||
      
 | 
			
		||||
      this.addAuditEntry(context, 'validation', 'phase-completion-failed',
 | 
			
		||||
        { phase: phase.id, phaseQuery },
 | 
			
		||||
        { error: error.message },
 | 
			
		||||
        10,
 | 
			
		||||
        phaseStart,
 | 
			
		||||
        { phaseCompletion: true, failed: true }
 | 
			
		||||
      );
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private async evaluateSpecificTool(context: AnalysisContext, tool: any, rank: number): Promise<MicroTaskResult> {
 | 
			
		||||
    const existingSelection = context.selectedTools?.find(st => st.tool.name === tool.name);
 | 
			
		||||
    const taskRelevance = existingSelection?.taskRelevance || 70;
 | 
			
		||||
@ -1373,6 +1535,10 @@ class ImprovedMicroTaskAIPipeline {
 | 
			
		||||
          if (toolSelectionResult.success) completeTasks++; else failedTasks++;
 | 
			
		||||
          await this.delay(this.microTaskDelay);
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        console.log('[AI PIPELINE] Checking for underrepresented phases...');
 | 
			
		||||
        await this.completeUnderrepresentedPhases(context, toolsData, userQuery);
 | 
			
		||||
        
 | 
			
		||||
      } else {
 | 
			
		||||
        const topTools = filteredData.tools.slice(0, 3);
 | 
			
		||||
        for (let i = 0; i < topTools.length; i++) {
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user