airefactor #19
@ -1594,6 +1594,7 @@ class AIQueryInterface {
|
|||||||
const exportData = {
|
const exportData = {
|
||||||
metadata: {
|
metadata: {
|
||||||
timestamp: new Date().toISOString(),
|
timestamp: new Date().toISOString(),
|
||||||
|
version: '2.0',
|
||||||
toolsDataHash: toolsDataHash,
|
toolsDataHash: toolsDataHash,
|
||||||
aiModel: aiModel,
|
aiModel: aiModel,
|
||||||
aiParameters: aiParameters,
|
aiParameters: aiParameters,
|
||||||
@ -1607,8 +1608,7 @@ class AIQueryInterface {
|
|||||||
auditTrail: undefined
|
auditTrail: undefined
|
||||||
},
|
},
|
||||||
auditTrail: this.currentRecommendation.auditTrail || [],
|
auditTrail: this.currentRecommendation.auditTrail || [],
|
||||||
rawContext: rawContext,
|
rawContext: rawContext
|
||||||
checksum: this.calculateDataChecksum(this.currentRecommendation)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const blob = new Blob([JSON.stringify(exportData, null, 2)], {
|
const blob = new Blob([JSON.stringify(exportData, null, 2)], {
|
||||||
@ -1622,42 +1622,16 @@ class AIQueryInterface {
|
|||||||
a.click();
|
a.click();
|
||||||
URL.revokeObjectURL(url);
|
URL.revokeObjectURL(url);
|
||||||
|
|
||||||
console.log('[AI Interface] Analysis downloaded with enhanced structure:', {
|
console.log('[AI Interface] Analysis downloaded with verified hash structure:', {
|
||||||
version: '1.1',
|
version: '2.0',
|
||||||
aiModel,
|
aiModel,
|
||||||
toolsDataHash: toolsDataHash.slice(0, 8) + '...',
|
toolsDataHash: toolsDataHash.slice(0, 12) + '...',
|
||||||
tokensUsed: aiParameters.totalTokensUsed,
|
tokensUsed: aiParameters.totalTokensUsed,
|
||||||
auditEntries: exportData.auditTrail.length,
|
auditEntries: exportData.auditTrail.length,
|
||||||
checksum: exportData.checksum.slice(0, 8) + '...'
|
hashVerifiable: toolsDataHash !== 'unknown'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
calculateDataChecksum(data) {
|
|
||||||
if (!data) return 'empty';
|
|
||||||
|
|
||||||
try {
|
|
||||||
const keyData = {
|
|
||||||
recommendedToolsCount: data.recommended_tools?.length || 0,
|
|
||||||
backgroundKnowledgeCount: data.background_knowledge?.length || 0,
|
|
||||||
hasScenarioAnalysis: !!(data.scenario_analysis || data.problem_analysis),
|
|
||||||
hasApproach: !!data.investigation_approach,
|
|
||||||
processingTimeMs: data.processingStats?.processingTimeMs || 0
|
|
||||||
};
|
|
||||||
|
|
||||||
const dataString = JSON.stringify(keyData);
|
|
||||||
let hash = 0;
|
|
||||||
for (let i = 0; i < dataString.length; i++) {
|
|
||||||
const char = dataString.charCodeAt(i);
|
|
||||||
hash = ((hash << 5) - hash) + char;
|
|
||||||
hash = hash & hash;
|
|
||||||
}
|
|
||||||
return Math.abs(hash).toString(36);
|
|
||||||
} catch (error) {
|
|
||||||
console.error('[AI Interface] Checksum calculation failed:', error);
|
|
||||||
return 'error';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
validateUploadStructure(data) {
|
validateUploadStructure(data) {
|
||||||
try {
|
try {
|
||||||
const isValid = !!(
|
const isValid = !!(
|
||||||
|
@ -4,15 +4,12 @@ import { aiService } from './aiService.js';
|
|||||||
import { toolSelector, type SelectionContext } from './toolSelector.js';
|
import { toolSelector, type SelectionContext } from './toolSelector.js';
|
||||||
import { confidenceScoring, type AnalysisContext } from './confidenceScoring.js';
|
import { confidenceScoring, type AnalysisContext } from './confidenceScoring.js';
|
||||||
import { embeddingsService } from './embeddings.js';
|
import { embeddingsService } from './embeddings.js';
|
||||||
import { auditService, type AuditEntry } from './auditService.js';
|
import { auditService } from './auditService.js';
|
||||||
import { JSONParser } from './jsonUtils.js';
|
import { JSONParser } from './jsonUtils.js';
|
||||||
import { getPrompt } from '../config/prompts.js';
|
import { getPrompt } from '../config/prompts.js';
|
||||||
import 'dotenv/config';
|
|
||||||
|
|
||||||
interface PipelineConfig {
|
interface PipelineConfig {
|
||||||
microTaskDelay: number;
|
microTaskDelay: number;
|
||||||
//maxContextTokens: number;
|
|
||||||
maxPromptTokens: number;
|
|
||||||
taskRelevanceModeration: {
|
taskRelevanceModeration: {
|
||||||
maxInitialScore: number;
|
maxInitialScore: number;
|
||||||
maxWithPhaseBonus: number;
|
maxWithPhaseBonus: number;
|
||||||
@ -36,7 +33,6 @@ interface MicroTaskResult {
|
|||||||
interface AnalysisResult {
|
interface AnalysisResult {
|
||||||
recommendation: any;
|
recommendation: any;
|
||||||
processingStats: {
|
processingStats: {
|
||||||
//embeddingsUsed: boolean;
|
|
||||||
candidatesFromEmbeddings: number;
|
candidatesFromEmbeddings: number;
|
||||||
finalSelectedItems: number;
|
finalSelectedItems: number;
|
||||||
processingTimeMs: number;
|
processingTimeMs: number;
|
||||||
@ -57,7 +53,6 @@ interface PipelineContext {
|
|||||||
mode: string;
|
mode: string;
|
||||||
filteredData: any;
|
filteredData: any;
|
||||||
contextHistory: string[];
|
contextHistory: string[];
|
||||||
//maxContextLength: number;
|
|
||||||
currentContextLength: number;
|
currentContextLength: number;
|
||||||
scenarioAnalysis?: string;
|
scenarioAnalysis?: string;
|
||||||
problemAnalysis?: string;
|
problemAnalysis?: string;
|
||||||
@ -91,16 +86,12 @@ class AIPipeline {
|
|||||||
constructor() {
|
constructor() {
|
||||||
this.config = {
|
this.config = {
|
||||||
microTaskDelay: parseInt(process.env.AI_MICRO_TASK_DELAY_MS || '500', 10),
|
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: {
|
taskRelevanceModeration: {
|
||||||
maxInitialScore: 85,
|
maxInitialScore: 85,
|
||||||
maxWithPhaseBonus: 95,
|
maxWithPhaseBonus: 95,
|
||||||
moderationThreshold: 80
|
moderationThreshold: 80
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
console.log('[AI-PIPELINE] Initialized with dynamic phase handling');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async processQuery(userQuery: string, mode: string): Promise<AnalysisResult> {
|
async processQuery(userQuery: string, mode: string): Promise<AnalysisResult> {
|
||||||
@ -108,8 +99,6 @@ class AIPipeline {
|
|||||||
let completedTasks = 0;
|
let completedTasks = 0;
|
||||||
let failedTasks = 0;
|
let failedTasks = 0;
|
||||||
this.totalTokensUsed = 0;
|
this.totalTokensUsed = 0;
|
||||||
|
|
||||||
console.log('[AI-PIPELINE] Starting', mode, 'analysis pipeline');
|
|
||||||
|
|
||||||
auditService.clearAuditTrail();
|
auditService.clearAuditTrail();
|
||||||
|
|
||||||
@ -118,90 +107,102 @@ class AIPipeline {
|
|||||||
const aiConfig = aiService.getConfig();
|
const aiConfig = aiService.getConfig();
|
||||||
const toolsDataHash = getDataVersion?.() || 'unknown';
|
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 = {
|
const context: PipelineContext = {
|
||||||
userQuery,
|
userQuery,
|
||||||
mode,
|
mode,
|
||||||
filteredData: {},
|
filteredData: {},
|
||||||
contextHistory: [],
|
contextHistory: [],
|
||||||
//maxContextLength: this.config.maxContextTokens,
|
|
||||||
currentContextLength: 0,
|
currentContextLength: 0,
|
||||||
seenToolNames: new Set<string>(),
|
seenToolNames: new Set<string>(),
|
||||||
embeddingsSimilarities: new Map<string, number>(),
|
embeddingsSimilarities: new Map<string, number>(),
|
||||||
phaseMetadata: this.initializePhaseMetadata(toolsData.phases)
|
phaseMetadata: this.initializePhaseMetadata(toolsData.phases)
|
||||||
};
|
};
|
||||||
|
|
||||||
console.log('[AI-PIPELINE] Phase 1: Tool candidate selection');
|
|
||||||
const candidateSelectionStart = Date.now();
|
const candidateSelectionStart = Date.now();
|
||||||
|
|
||||||
const candidateData = await toolSelector.getIntelligentCandidates(userQuery, toolsData, mode, context);
|
const candidateData = await toolSelector.getIntelligentCandidates(userQuery, toolsData, mode, context);
|
||||||
|
|
||||||
const selectionConfidence = this.calculateToolSelectionConfidence(
|
const selectionConfidence = this.calculateToolSelectionConfidence(
|
||||||
candidateData.tools.length,
|
candidateData.tools.length,
|
||||||
toolsData.tools.length,
|
toolsData.tools.length,
|
||||||
//candidateData.selectionMethod,
|
|
||||||
candidateData.concepts.length
|
candidateData.concepts.length
|
||||||
);
|
);
|
||||||
|
|
||||||
auditService.addToolSelection(
|
auditService.addToolSelection(
|
||||||
candidateData.tools.map(t => t.name),
|
candidateData.tools.map(t => t.name),
|
||||||
toolsData.tools.map(t => t.name),
|
toolsData.tools.map(t => t.name),
|
||||||
//candidateData.selectionMethod,
|
|
||||||
selectionConfidence,
|
selectionConfidence,
|
||||||
candidateSelectionStart,
|
candidateSelectionStart,
|
||||||
{
|
{
|
||||||
//embeddingsUsed: embeddingsService.isEnabled(),
|
toolsDataHash: toolsDataHash,
|
||||||
totalCandidatesFound: candidateData.tools.length + candidateData.concepts.length,
|
totalCandidatesFound: candidateData.tools.length + candidateData.concepts.length,
|
||||||
//selectionMethod: candidateData.selectionMethod,
|
|
||||||
reductionRatio: candidateData.tools.length / toolsData.tools.length
|
reductionRatio: candidateData.tools.length / toolsData.tools.length
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
context.filteredData = candidateData;
|
context.filteredData = candidateData;
|
||||||
|
|
||||||
console.log('[AI-PIPELINE] Phase 2: Contextual analysis');
|
const analysisResult = await this.analyzeScenario(context, startTime, toolsDataHash);
|
||||||
|
|
||||||
const analysisResult = await this.analyzeScenario(context, startTime);
|
|
||||||
if (analysisResult.success) completedTasks++; else failedTasks++;
|
if (analysisResult.success) completedTasks++; else failedTasks++;
|
||||||
this.trackTokenUsage(analysisResult.aiUsage);
|
this.trackTokenUsage(analysisResult.aiUsage);
|
||||||
await this.delay(this.config.microTaskDelay);
|
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++;
|
if (approachResult.success) completedTasks++; else failedTasks++;
|
||||||
this.trackTokenUsage(approachResult.aiUsage);
|
this.trackTokenUsage(approachResult.aiUsage);
|
||||||
await this.delay(this.config.microTaskDelay);
|
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++;
|
if (considerationsResult.success) completedTasks++; else failedTasks++;
|
||||||
this.trackTokenUsage(considerationsResult.aiUsage);
|
this.trackTokenUsage(considerationsResult.aiUsage);
|
||||||
await this.delay(this.config.microTaskDelay);
|
await this.delay(this.config.microTaskDelay);
|
||||||
|
|
||||||
console.log('[AI-PIPELINE] Phase 3: Tool-specific analysis');
|
|
||||||
|
|
||||||
if (mode === 'workflow') {
|
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;
|
completedTasks = workflowResults.completed;
|
||||||
failedTasks = workflowResults.failed;
|
failedTasks = workflowResults.failed;
|
||||||
} else {
|
} else {
|
||||||
const toolResults = await this.processToolMode(context, completedTasks, failedTasks, startTime);
|
const toolResults = await this.processToolMode(context, completedTasks, failedTasks, startTime, toolsDataHash);
|
||||||
completedTasks = toolResults.completed;
|
completedTasks = toolResults.completed;
|
||||||
failedTasks = toolResults.failed;
|
failedTasks = toolResults.failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('[AI-PIPELINE] Phase 4: Knowledge synthesis');
|
const knowledgeResult = await this.selectBackgroundKnowledge(context, startTime, toolsDataHash);
|
||||||
|
|
||||||
const knowledgeResult = await this.selectBackgroundKnowledge(context, startTime);
|
|
||||||
if (knowledgeResult.success) completedTasks++; else failedTasks++;
|
if (knowledgeResult.success) completedTasks++; else failedTasks++;
|
||||||
this.trackTokenUsage(knowledgeResult.aiUsage);
|
this.trackTokenUsage(knowledgeResult.aiUsage);
|
||||||
await this.delay(this.config.microTaskDelay);
|
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++;
|
if (finalResult.success) completedTasks++; else failedTasks++;
|
||||||
this.trackTokenUsage(finalResult.aiUsage);
|
this.trackTokenUsage(finalResult.aiUsage);
|
||||||
|
|
||||||
const recommendation = this.buildRecommendation(context, mode, finalResult.content);
|
const recommendation = this.buildRecommendation(context, mode, finalResult.content, toolsDataHash);
|
||||||
|
|
||||||
const processingStats = {
|
const processingStats = {
|
||||||
//embeddingsUsed: embeddingsService.isEnabled(),
|
|
||||||
candidatesFromEmbeddings: candidateData.tools.length,
|
candidatesFromEmbeddings: candidateData.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,
|
||||||
@ -216,16 +217,6 @@ class AIPipeline {
|
|||||||
maxTokensUsed: 32768
|
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();
|
const finalAuditTrail = auditService.finalizeAuditTrail();
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -249,7 +240,6 @@ class AIPipeline {
|
|||||||
phaseComplexity: Map<string, number>;
|
phaseComplexity: Map<string, number>;
|
||||||
} {
|
} {
|
||||||
if (!phases || !Array.isArray(phases)) {
|
if (!phases || !Array.isArray(phases)) {
|
||||||
console.warn('[AI-PIPELINE] No phases data available, using fallback');
|
|
||||||
return {
|
return {
|
||||||
phases: [],
|
phases: [],
|
||||||
criticalPhaseIds: [],
|
criticalPhaseIds: [],
|
||||||
@ -268,20 +258,12 @@ class AIPipeline {
|
|||||||
const phaseComplexity = new Map<string, number>();
|
const phaseComplexity = new Map<string, number>();
|
||||||
phases.forEach(phase => {
|
phases.forEach(phase => {
|
||||||
let complexity = 1;
|
let complexity = 1;
|
||||||
|
|
||||||
if (phase.typical_tools?.length > 5) complexity += 1;
|
if (phase.typical_tools?.length > 5) complexity += 1;
|
||||||
if (phase.key_activities?.length > 3) complexity += 1;
|
if (phase.key_activities?.length > 3) complexity += 1;
|
||||||
if (phase.description?.length > 100) complexity += 1;
|
if (phase.description?.length > 100) complexity += 1;
|
||||||
|
|
||||||
phaseComplexity.set(phase.id, complexity);
|
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 {
|
return {
|
||||||
phases,
|
phases,
|
||||||
criticalPhaseIds,
|
criticalPhaseIds,
|
||||||
@ -292,11 +274,9 @@ class AIPipeline {
|
|||||||
private calculateToolSelectionConfidence(
|
private calculateToolSelectionConfidence(
|
||||||
selectedCount: number,
|
selectedCount: number,
|
||||||
totalCount: number,
|
totalCount: number,
|
||||||
//method: string,
|
|
||||||
conceptsCount: number
|
conceptsCount: number
|
||||||
): number {
|
): number {
|
||||||
let confidence = 50;
|
let confidence = 50;
|
||||||
|
|
||||||
const selectionRatio = selectedCount / totalCount;
|
const selectionRatio = selectedCount / totalCount;
|
||||||
|
|
||||||
if (selectionRatio >= 0.05 && selectionRatio <= 0.20) {
|
if (selectionRatio >= 0.05 && selectionRatio <= 0.20) {
|
||||||
@ -307,17 +287,8 @@ class AIPipeline {
|
|||||||
confidence -= 15;
|
confidence -= 15;
|
||||||
}
|
}
|
||||||
|
|
||||||
//if (method.includes('embeddings')) {
|
if (conceptsCount > 0) confidence += 10;
|
||||||
//confidence += 15;
|
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));
|
return Math.min(95, Math.max(40, confidence));
|
||||||
}
|
}
|
||||||
@ -327,7 +298,8 @@ class AIPipeline {
|
|||||||
toolsData: any,
|
toolsData: any,
|
||||||
completedTasks: number,
|
completedTasks: number,
|
||||||
failedTasks: number,
|
failedTasks: number,
|
||||||
pipelineStart: number
|
pipelineStart: number,
|
||||||
|
toolsDataHash: string
|
||||||
): Promise<{ completed: number; failed: number }> {
|
): Promise<{ completed: number; failed: number }> {
|
||||||
const phases = toolsData.phases || [];
|
const phases = toolsData.phases || [];
|
||||||
|
|
||||||
@ -337,10 +309,7 @@ class AIPipeline {
|
|||||||
tool && tool.phases && Array.isArray(tool.phases) && tool.phases.includes(phase.id)
|
tool && tool.phases && Array.isArray(tool.phases) && tool.phases.includes(phase.id)
|
||||||
);
|
);
|
||||||
|
|
||||||
if (phaseTools.length === 0) {
|
if (phaseTools.length === 0) continue;
|
||||||
console.log(`[AI-PIPELINE] No tools available for phase: ${phase.id}`);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const selections = await toolSelector.selectToolsForPhase(context.userQuery, phase, phaseTools, context);
|
const selections = await toolSelector.selectToolsForPhase(context.userQuery, phase, phaseTools, context);
|
||||||
|
|
||||||
@ -370,6 +339,7 @@ class AIPipeline {
|
|||||||
phaseConfidence,
|
phaseConfidence,
|
||||||
phaseStart,
|
phaseStart,
|
||||||
{
|
{
|
||||||
|
toolsDataHash: toolsDataHash,
|
||||||
phaseId: phase.id,
|
phaseId: phase.id,
|
||||||
availableToolsCount: phaseTools.length,
|
availableToolsCount: phaseTools.length,
|
||||||
selectedToolsCount: selections.length,
|
selectedToolsCount: selections.length,
|
||||||
@ -383,7 +353,6 @@ class AIPipeline {
|
|||||||
if (tool) {
|
if (tool) {
|
||||||
const moderatedTaskRelevance = this.moderateTaskRelevance(sel.taskRelevance);
|
const moderatedTaskRelevance = this.moderateTaskRelevance(sel.taskRelevance);
|
||||||
const priority = this.derivePriorityFromScore(moderatedTaskRelevance);
|
const priority = this.derivePriorityFromScore(moderatedTaskRelevance);
|
||||||
|
|
||||||
const dynamicLimitations = this.generateDynamicLimitations(tool, phase, sel);
|
const dynamicLimitations = this.generateDynamicLimitations(tool, phase, sel);
|
||||||
|
|
||||||
this.addToolToSelection(context, tool, phase.id, priority, sel.justification, moderatedTaskRelevance, dynamicLimitations);
|
this.addToolToSelection(context, tool, phase.id, priority, sel.justification, moderatedTaskRelevance, dynamicLimitations);
|
||||||
@ -405,6 +374,7 @@ class AIPipeline {
|
|||||||
moderatedTaskRelevance || 70,
|
moderatedTaskRelevance || 70,
|
||||||
phaseStart,
|
phaseStart,
|
||||||
{
|
{
|
||||||
|
toolsDataHash: toolsDataHash,
|
||||||
toolType: tool.type,
|
toolType: tool.type,
|
||||||
priority,
|
priority,
|
||||||
moderationApplied: sel.taskRelevance !== moderatedTaskRelevance,
|
moderationApplied: sel.taskRelevance !== moderatedTaskRelevance,
|
||||||
@ -418,7 +388,7 @@ class AIPipeline {
|
|||||||
await this.delay(this.config.microTaskDelay);
|
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;
|
completedTasks += completionResult.completed;
|
||||||
failedTasks += completionResult.failed;
|
failedTasks += completionResult.failed;
|
||||||
|
|
||||||
@ -437,7 +407,6 @@ class AIPipeline {
|
|||||||
}
|
}
|
||||||
): number {
|
): number {
|
||||||
let confidence = 60;
|
let confidence = 60;
|
||||||
|
|
||||||
const isCritical = phaseMetadata?.criticalPhaseIds.includes(phaseId) || false;
|
const isCritical = phaseMetadata?.criticalPhaseIds.includes(phaseId) || false;
|
||||||
const phaseComplexity = phaseMetadata?.phaseComplexity.get(phaseId) || 1;
|
const phaseComplexity = phaseMetadata?.phaseComplexity.get(phaseId) || 1;
|
||||||
|
|
||||||
@ -454,13 +423,8 @@ class AIPipeline {
|
|||||||
confidence += 10;
|
confidence += 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isCritical && selectedCount >= 2) {
|
if (isCritical && selectedCount >= 2) confidence += 10;
|
||||||
confidence += 10;
|
if (phaseComplexity > 2 && selectedCount >= phaseComplexity) confidence += 5;
|
||||||
}
|
|
||||||
|
|
||||||
if (phaseComplexity > 2 && selectedCount >= phaseComplexity) {
|
|
||||||
confidence += 5;
|
|
||||||
}
|
|
||||||
|
|
||||||
const avgRelevance = selections.length > 0 ?
|
const avgRelevance = selections.length > 0 ?
|
||||||
selections.reduce((sum, s) => sum + (s.taskRelevance || 70), 0) / selections.length : 0;
|
selections.reduce((sum, s) => sum + (s.taskRelevance || 70), 0) / selections.length : 0;
|
||||||
@ -504,12 +468,13 @@ class AIPipeline {
|
|||||||
context: PipelineContext,
|
context: PipelineContext,
|
||||||
completedTasks: number,
|
completedTasks: number,
|
||||||
failedTasks: number,
|
failedTasks: number,
|
||||||
pipelineStart: number
|
pipelineStart: number,
|
||||||
|
toolsDataHash: string
|
||||||
): Promise<{ completed: number; failed: number }> {
|
): Promise<{ completed: number; failed: number }> {
|
||||||
const topTools = context.filteredData.tools.slice(0, 3);
|
const topTools = context.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, pipelineStart);
|
const evaluationResult = await this.evaluateSpecificTool(context, topTools[i], i + 1, pipelineStart, toolsDataHash);
|
||||||
if (evaluationResult.success) completedTasks++; else failedTasks++;
|
if (evaluationResult.success) completedTasks++; else failedTasks++;
|
||||||
this.trackTokenUsage(evaluationResult.aiUsage);
|
this.trackTokenUsage(evaluationResult.aiUsage);
|
||||||
await this.delay(this.config.microTaskDelay);
|
await this.delay(this.config.microTaskDelay);
|
||||||
@ -521,7 +486,8 @@ class AIPipeline {
|
|||||||
private async completeUnderrepresentedPhases(
|
private async completeUnderrepresentedPhases(
|
||||||
context: PipelineContext,
|
context: PipelineContext,
|
||||||
toolsData: any,
|
toolsData: any,
|
||||||
pipelineStart: number
|
pipelineStart: number,
|
||||||
|
toolsDataHash: string
|
||||||
): Promise<{ completed: number; failed: number }> {
|
): Promise<{ completed: number; failed: number }> {
|
||||||
const phases = toolsData.phases || [];
|
const phases = toolsData.phases || [];
|
||||||
const selectedPhases = new Map<string, number>();
|
const selectedPhases = new Map<string, number>();
|
||||||
@ -538,15 +504,10 @@ class AIPipeline {
|
|||||||
return count <= 1;
|
return count <= 1;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (underrepresentedPhases.length === 0) {
|
if (underrepresentedPhases.length === 0) return { completed: 0, failed: 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(', '));
|
|
||||||
|
|
||||||
for (const phase of underrepresentedPhases) {
|
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++;
|
if (result.success) completedTasks++; else failedTasks++;
|
||||||
await this.delay(this.config.microTaskDelay);
|
await this.delay(this.config.microTaskDelay);
|
||||||
}
|
}
|
||||||
@ -558,13 +519,12 @@ class AIPipeline {
|
|||||||
context: PipelineContext,
|
context: PipelineContext,
|
||||||
phase: any,
|
phase: any,
|
||||||
toolsData: any,
|
toolsData: any,
|
||||||
pipelineStart: number
|
pipelineStart: number,
|
||||||
|
toolsDataHash: string
|
||||||
): Promise<MicroTaskResult> {
|
): Promise<MicroTaskResult> {
|
||||||
const phaseStart = Date.now();
|
const phaseStart = Date.now();
|
||||||
const phaseQuery = `forensic ${phase.name.toLowerCase()} tools methods`;
|
const phaseQuery = `forensic ${phase.name.toLowerCase()} tools methods`;
|
||||||
|
|
||||||
console.log('[AI-PIPELINE] Phase completion for:', phase.id);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const phaseResults = await embeddingsService.findSimilar(phaseQuery, 20, 0.2);
|
const phaseResults = await embeddingsService.findSimilar(phaseQuery, 20, 0.2);
|
||||||
|
|
||||||
@ -574,6 +534,7 @@ class AIPipeline {
|
|||||||
0.2,
|
0.2,
|
||||||
phaseStart,
|
phaseStart,
|
||||||
{
|
{
|
||||||
|
toolsDataHash: toolsDataHash,
|
||||||
phaseId: phase.id,
|
phaseId: phase.id,
|
||||||
phaseName: phase.name,
|
phaseName: phase.name,
|
||||||
completionPurpose: 'underrepresented-phase-enhancement'
|
completionPurpose: 'underrepresented-phase-enhancement'
|
||||||
@ -581,7 +542,6 @@ class AIPipeline {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (phaseResults.length === 0) {
|
if (phaseResults.length === 0) {
|
||||||
console.log('[AI-PIPELINE] No semantic results for phase:', phase.id);
|
|
||||||
return {
|
return {
|
||||||
taskType: 'phase-completion',
|
taskType: 'phase-completion',
|
||||||
content: '',
|
content: '',
|
||||||
@ -613,7 +573,6 @@ class AIPipeline {
|
|||||||
.slice(0, 2);
|
.slice(0, 2);
|
||||||
|
|
||||||
if (phaseTools.length === 0) {
|
if (phaseTools.length === 0) {
|
||||||
console.log('[AI-PIPELINE] No suitable tools for phase completion:', phase.id);
|
|
||||||
return {
|
return {
|
||||||
taskType: 'phase-completion',
|
taskType: 'phase-completion',
|
||||||
content: '',
|
content: '',
|
||||||
@ -623,10 +582,9 @@ class AIPipeline {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const selectionPrompt = getPrompt('generatePhaseCompletionPrompt', context.userQuery, phase, phaseTools, phaseConcepts);
|
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) {
|
if (!selectionResult.success) {
|
||||||
console.error('[AI-PIPELINE] Phase completion selection failed for:', phase.id);
|
|
||||||
return {
|
return {
|
||||||
taskType: 'phase-completion',
|
taskType: 'phase-completion',
|
||||||
content: '',
|
content: '',
|
||||||
@ -648,7 +606,6 @@ class AIPipeline {
|
|||||||
.slice(0, 2);
|
.slice(0, 2);
|
||||||
|
|
||||||
if (validTools.length === 0) {
|
if (validTools.length === 0) {
|
||||||
console.log('[AI-PIPELINE] No valid tools selected for phase completion:', phase.id);
|
|
||||||
return {
|
return {
|
||||||
taskType: 'phase-completion',
|
taskType: 'phase-completion',
|
||||||
content: selection.completionReasoning || '',
|
content: selection.completionReasoning || '',
|
||||||
@ -660,8 +617,6 @@ class AIPipeline {
|
|||||||
const actualToolsAdded = validTools.map(tool => tool.name);
|
const actualToolsAdded = validTools.map(tool => tool.name);
|
||||||
|
|
||||||
for (const tool of validTools) {
|
for (const tool of validTools) {
|
||||||
console.log('[AI-PIPELINE] Generating AI reasoning for phase completion tool:', tool.name);
|
|
||||||
|
|
||||||
const reasoningPrompt = getPrompt(
|
const reasoningPrompt = getPrompt(
|
||||||
'phaseCompletionReasoning',
|
'phaseCompletionReasoning',
|
||||||
context.userQuery,
|
context.userQuery,
|
||||||
@ -671,7 +626,7 @@ class AIPipeline {
|
|||||||
selection.completionReasoning || 'Nachergänzung zur Vervollständigung der Phasenabdeckung'
|
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 detailedJustification: string;
|
||||||
let moderatedTaskRelevance = 75;
|
let moderatedTaskRelevance = 75;
|
||||||
@ -695,8 +650,6 @@ class AIPipeline {
|
|||||||
moderatedTaskRelevance,
|
moderatedTaskRelevance,
|
||||||
dynamicLimitations
|
dynamicLimitations
|
||||||
);
|
);
|
||||||
|
|
||||||
console.log('[AI-PIPELINE] Added phase completion tool with AI reasoning:', tool.name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auditService.addPhaseCompletion(
|
auditService.addPhaseCompletion(
|
||||||
@ -705,6 +658,7 @@ class AIPipeline {
|
|||||||
selection.completionReasoning || `${actualToolsAdded.length} Tools für ${phase.name} hinzugefügt`,
|
selection.completionReasoning || `${actualToolsAdded.length} Tools für ${phase.name} hinzugefügt`,
|
||||||
phaseStart,
|
phaseStart,
|
||||||
{
|
{
|
||||||
|
toolsDataHash: toolsDataHash,
|
||||||
toolsAdded: actualToolsAdded,
|
toolsAdded: actualToolsAdded,
|
||||||
toolType: validTools[0]?.type,
|
toolType: validTools[0]?.type,
|
||||||
semanticSimilarity: phaseResults.find(r => r.name === validTools[0]?.name)?.similarity,
|
semanticSimilarity: phaseResults.find(r => r.name === validTools[0]?.name)?.similarity,
|
||||||
@ -723,8 +677,6 @@ class AIPipeline {
|
|||||||
};
|
};
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('[AI-PIPELINE] Phase completion failed for:', phase.id, error);
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
taskType: 'phase-completion',
|
taskType: 'phase-completion',
|
||||||
content: '',
|
content: '',
|
||||||
@ -756,9 +708,7 @@ class AIPipeline {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private moderateTaskRelevance(taskRelevance: number): number {
|
private moderateTaskRelevance(taskRelevance: number): number {
|
||||||
if (typeof taskRelevance !== 'number') {
|
if (typeof taskRelevance !== 'number') return 70;
|
||||||
return 70;
|
|
||||||
}
|
|
||||||
|
|
||||||
let moderated = Math.min(taskRelevance, this.config.taskRelevanceModeration.maxInitialScore);
|
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));
|
return Math.round(Math.min(moderated, this.config.taskRelevanceModeration.maxInitialScore));
|
||||||
}
|
}
|
||||||
|
|
||||||
private async analyzeScenario(context: PipelineContext, pipelineStart: number): Promise<MicroTaskResult> {
|
private async analyzeScenario(context: PipelineContext, pipelineStart: number, toolsDataHash: string): Promise<MicroTaskResult> {
|
||||||
console.log('[AI-PIPELINE] Micro-task: Scenario analysis');
|
|
||||||
const taskStart = Date.now();
|
const taskStart = Date.now();
|
||||||
const isWorkflow = context.mode === 'workflow';
|
const isWorkflow = context.mode === 'workflow';
|
||||||
const prompt = getPrompt('scenarioAnalysis', isWorkflow, context.userQuery);
|
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 (result.success) {
|
||||||
if (isWorkflow) {
|
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`,
|
`Analysierte ${isWorkflow ? 'Szenario' : 'Problem'} basierend auf Nutzereingabe: "${context.userQuery.slice(0, 100)}..." - Identifizierte Kernaspekte und Herausforderungen für forensische Untersuchung`,
|
||||||
taskStart,
|
taskStart,
|
||||||
{
|
{
|
||||||
|
toolsDataHash: toolsDataHash,
|
||||||
microTaskType: 'scenario-analysis',
|
microTaskType: 'scenario-analysis',
|
||||||
analysisType: isWorkflow ? 'scenario' : 'problem',
|
analysisType: isWorkflow ? 'scenario' : 'problem',
|
||||||
contentLength: result.content.length,
|
contentLength: result.content.length,
|
||||||
@ -814,13 +764,12 @@ class AIPipeline {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async generateApproach(context: PipelineContext, pipelineStart: number): Promise<MicroTaskResult> {
|
private async generateApproach(context: PipelineContext, pipelineStart: number, toolsDataHash: string): Promise<MicroTaskResult> {
|
||||||
console.log('[AI-PIPELINE] Micro-task: Investigation approach');
|
|
||||||
const taskStart = Date.now();
|
const taskStart = Date.now();
|
||||||
const isWorkflow = context.mode === 'workflow';
|
const isWorkflow = context.mode === 'workflow';
|
||||||
const prompt = getPrompt('investigationApproach', isWorkflow, context.userQuery);
|
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) {
|
if (result.success) {
|
||||||
context.investigationApproach = result.content;
|
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`,
|
`Entwickelte ${isWorkflow ? 'Untersuchungs' : 'Lösungs'}ansatz unter Berücksichtigung der Szenario-Analyse - Strukturierte Herangehensweise für forensische Methodik`,
|
||||||
taskStart,
|
taskStart,
|
||||||
{
|
{
|
||||||
|
toolsDataHash: toolsDataHash,
|
||||||
microTaskType: 'investigation-approach',
|
microTaskType: 'investigation-approach',
|
||||||
approachType: isWorkflow ? 'investigation' : 'solution',
|
approachType: isWorkflow ? 'investigation' : 'solution',
|
||||||
contentLength: result.content.length,
|
contentLength: result.content.length,
|
||||||
@ -854,13 +804,12 @@ class AIPipeline {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async generateCriticalConsiderations(context: PipelineContext, pipelineStart: number): Promise<MicroTaskResult> {
|
private async generateCriticalConsiderations(context: PipelineContext, pipelineStart: number, toolsDataHash: string): Promise<MicroTaskResult> {
|
||||||
console.log('[AI-PIPELINE] Micro-task: Critical considerations');
|
|
||||||
const taskStart = Date.now();
|
const taskStart = Date.now();
|
||||||
const isWorkflow = context.mode === 'workflow';
|
const isWorkflow = context.mode === 'workflow';
|
||||||
const prompt = getPrompt('criticalConsiderations', isWorkflow, context.userQuery);
|
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) {
|
if (result.success) {
|
||||||
context.criticalConsiderations = result.content;
|
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',
|
'Identifizierte kritische Überlegungen für forensische Untersuchung - Berücksichtigung von Beweissicherung, Chain of Custody und methodischen Herausforderungen',
|
||||||
taskStart,
|
taskStart,
|
||||||
{
|
{
|
||||||
|
toolsDataHash: toolsDataHash,
|
||||||
microTaskType: 'critical-considerations',
|
microTaskType: 'critical-considerations',
|
||||||
contentLength: result.content.length,
|
contentLength: result.content.length,
|
||||||
decisionBasis: 'ai-analysis',
|
decisionBasis: 'ai-analysis',
|
||||||
@ -896,9 +846,9 @@ class AIPipeline {
|
|||||||
context: PipelineContext,
|
context: PipelineContext,
|
||||||
tool: any,
|
tool: any,
|
||||||
rank: number,
|
rank: number,
|
||||||
pipelineStart: number
|
pipelineStart: number,
|
||||||
|
toolsDataHash: string
|
||||||
): Promise<MicroTaskResult> {
|
): Promise<MicroTaskResult> {
|
||||||
console.log('[AI-PIPELINE] Micro-task: Tool evaluation for:', tool.name);
|
|
||||||
const taskStart = Date.now();
|
const taskStart = Date.now();
|
||||||
const existingSelection = context.selectedTools?.find((st: any) => st.tool && st.tool.name === tool.name);
|
const existingSelection = context.selectedTools?.find((st: any) => st.tool && st.tool.name === tool.name);
|
||||||
const originalTaskRelevance = existingSelection?.taskRelevance || 70;
|
const originalTaskRelevance = existingSelection?.taskRelevance || 70;
|
||||||
@ -906,7 +856,7 @@ class AIPipeline {
|
|||||||
const priority = this.derivePriorityFromScore(moderatedTaskRelevance);
|
const priority = this.derivePriorityFromScore(moderatedTaskRelevance);
|
||||||
|
|
||||||
const prompt = getPrompt('toolEvaluation', context.userQuery, tool, rank, 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) {
|
if (result.success) {
|
||||||
const evaluation = JSONParser.safeParseJSON(result.content, {
|
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`,
|
`Bewertete Tool "${tool.name}" (Rang ${rank}) - Analysierte Eignung für spezifische Aufgabenstellung mit Fokus auf praktische Anwendbarkeit und methodische Integration`,
|
||||||
taskStart,
|
taskStart,
|
||||||
{
|
{
|
||||||
|
toolsDataHash: toolsDataHash,
|
||||||
microTaskType: 'tool-evaluation',
|
microTaskType: 'tool-evaluation',
|
||||||
toolName: tool.name,
|
toolName: tool.name,
|
||||||
toolType: tool.type,
|
toolType: tool.type,
|
||||||
@ -964,8 +915,7 @@ class AIPipeline {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async selectBackgroundKnowledge(context: PipelineContext, pipelineStart: number): Promise<MicroTaskResult> {
|
private async selectBackgroundKnowledge(context: PipelineContext, pipelineStart: number, toolsDataHash: string): Promise<MicroTaskResult> {
|
||||||
console.log('[AI-PIPELINE] Micro-task: Background knowledge selection');
|
|
||||||
const taskStart = Date.now();
|
const taskStart = Date.now();
|
||||||
const availableConcepts = context.filteredData.concepts;
|
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 selectedToolNames = context.selectedTools?.map((st: any) => st.tool && st.tool.name).filter(Boolean) || [];
|
||||||
const prompt = getPrompt('backgroundKnowledgeSelection', context.userQuery, context.mode, selectedToolNames, availableConcepts);
|
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) {
|
if (result.success) {
|
||||||
const selections = JSONParser.safeParseJSON(result.content, []);
|
const selections = JSONParser.safeParseJSON(result.content, []);
|
||||||
@ -1017,6 +967,7 @@ class AIPipeline {
|
|||||||
finalConfidence,
|
finalConfidence,
|
||||||
taskStart,
|
taskStart,
|
||||||
{
|
{
|
||||||
|
toolsDataHash: toolsDataHash,
|
||||||
microTaskType: 'background-knowledge',
|
microTaskType: 'background-knowledge',
|
||||||
availableConceptsCount: availableConcepts.length,
|
availableConceptsCount: availableConcepts.length,
|
||||||
selectedConceptsCount: context.backgroundKnowledge.length,
|
selectedConceptsCount: context.backgroundKnowledge.length,
|
||||||
@ -1041,32 +992,25 @@ class AIPipeline {
|
|||||||
): number {
|
): number {
|
||||||
let bonus = 0;
|
let bonus = 0;
|
||||||
|
|
||||||
if (selectedKnowledge.length > 0) {
|
if (selectedKnowledge.length > 0) bonus += 10;
|
||||||
bonus += 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
const ratio = selectedKnowledge.length / availableConcepts.length;
|
const ratio = selectedKnowledge.length / availableConcepts.length;
|
||||||
if (ratio >= 0.1 && ratio <= 0.3) {
|
if (ratio >= 0.1 && ratio <= 0.3) bonus += 15;
|
||||||
bonus += 15;
|
|
||||||
}
|
|
||||||
|
|
||||||
const hasGoodReasonings = selectedKnowledge.some(bk =>
|
const hasGoodReasonings = selectedKnowledge.some(bk =>
|
||||||
bk.relevance && bk.relevance.length > 30
|
bk.relevance && bk.relevance.length > 30
|
||||||
);
|
);
|
||||||
if (hasGoodReasonings) {
|
if (hasGoodReasonings) bonus += 10;
|
||||||
bonus += 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
return bonus;
|
return bonus;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async generateFinalRecommendations(context: PipelineContext, pipelineStart: number): Promise<MicroTaskResult> {
|
private async generateFinalRecommendations(context: PipelineContext, pipelineStart: number, toolsDataHash: string): Promise<MicroTaskResult> {
|
||||||
console.log('[AI-PIPELINE] Micro-task: Final recommendations');
|
|
||||||
const taskStart = Date.now();
|
const taskStart = Date.now();
|
||||||
const selectedToolNames = context.selectedTools?.map((st: any) => st.tool && st.tool.name).filter(Boolean) || [];
|
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 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) {
|
if (result.success) {
|
||||||
const confidence = auditService.calculateAIResponseConfidence(
|
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`,
|
`Generierte abschließende ${context.mode}-Empfehlungen basierend auf ausgewählten ${selectedToolNames.length} Tools - Synthese aller Analyseschritte zu kohärenter Handlungsempfehlung`,
|
||||||
taskStart,
|
taskStart,
|
||||||
{
|
{
|
||||||
|
toolsDataHash: toolsDataHash,
|
||||||
microTaskType: 'final-recommendations',
|
microTaskType: 'final-recommendations',
|
||||||
mode: context.mode,
|
mode: context.mode,
|
||||||
selectedToolsCount: selectedToolNames.length,
|
selectedToolsCount: selectedToolNames.length,
|
||||||
@ -1105,30 +1050,17 @@ class AIPipeline {
|
|||||||
private calculateSynthesisBonus(selectedToolNames: string[], context: PipelineContext): number {
|
private calculateSynthesisBonus(selectedToolNames: string[], context: PipelineContext): number {
|
||||||
let bonus = 0;
|
let bonus = 0;
|
||||||
|
|
||||||
if (selectedToolNames.length >= 3) {
|
if (selectedToolNames.length >= 3) bonus += 10;
|
||||||
bonus += 10;
|
if (context.backgroundKnowledge && context.backgroundKnowledge.length > 0) bonus += 10;
|
||||||
}
|
if (context.scenarioAnalysis || context.problemAnalysis) bonus += 5;
|
||||||
|
if (context.investigationApproach) bonus += 5;
|
||||||
if (context.backgroundKnowledge && context.backgroundKnowledge.length > 0) {
|
|
||||||
bonus += 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (context.scenarioAnalysis || context.problemAnalysis) {
|
|
||||||
bonus += 5;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (context.investigationApproach) {
|
|
||||||
bonus += 5;
|
|
||||||
}
|
|
||||||
|
|
||||||
return bonus;
|
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';
|
const isWorkflow = mode === 'workflow';
|
||||||
|
|
||||||
console.log('[AI-PIPELINE] Building recommendation for', mode, 'mode with', context.selectedTools?.length || 0, 'tools');
|
|
||||||
|
|
||||||
const base = {
|
const base = {
|
||||||
[isWorkflow ? 'scenario_analysis' : 'problem_analysis']:
|
[isWorkflow ? 'scenario_analysis' : 'problem_analysis']:
|
||||||
isWorkflow ? context.scenarioAnalysis : context.problemAnalysis,
|
isWorkflow ? context.scenarioAnalysis : context.problemAnalysis,
|
||||||
@ -1161,6 +1093,7 @@ class AIPipeline {
|
|||||||
confidence,
|
confidence,
|
||||||
Date.now(),
|
Date.now(),
|
||||||
{
|
{
|
||||||
|
toolsDataHash: toolsDataHash,
|
||||||
phase: st.phase,
|
phase: st.phase,
|
||||||
priority: st.priority,
|
priority: st.priority,
|
||||||
toolType: st.tool.type,
|
toolType: st.tool.type,
|
||||||
@ -1205,6 +1138,7 @@ class AIPipeline {
|
|||||||
confidence,
|
confidence,
|
||||||
Date.now(),
|
Date.now(),
|
||||||
{
|
{
|
||||||
|
toolsDataHash: toolsDataHash,
|
||||||
rank: st.tool.evaluation?.rank || 1,
|
rank: st.tool.evaluation?.rank || 1,
|
||||||
toolType: st.tool.type,
|
toolType: st.tool.type,
|
||||||
moderatedTaskRelevance: st.taskRelevance
|
moderatedTaskRelevance: st.taskRelevance
|
||||||
@ -1237,7 +1171,6 @@ class AIPipeline {
|
|||||||
private async callMicroTaskAI(
|
private async callMicroTaskAI(
|
||||||
prompt: string,
|
prompt: string,
|
||||||
context: PipelineContext,
|
context: PipelineContext,
|
||||||
maxTokens: number = 500,
|
|
||||||
taskType: string = 'micro-task'
|
taskType: string = 'micro-task'
|
||||||
): Promise<MicroTaskResult> {
|
): Promise<MicroTaskResult> {
|
||||||
const startTime = Date.now();
|
const startTime = Date.now();
|
||||||
@ -1245,15 +1178,11 @@ class AIPipeline {
|
|||||||
let contextPrompt = prompt;
|
let contextPrompt = prompt;
|
||||||
if (context.contextHistory.length > 0) {
|
if (context.contextHistory.length > 0) {
|
||||||
const contextSection = `BISHERIGE ANALYSE:\n${context.contextHistory.join('\n\n')}\n\nAKTUELLE AUFGABE:\n`;
|
const contextSection = `BISHERIGE ANALYSE:\n${context.contextHistory.join('\n\n')}\n\nAKTUELLE AUFGABE:\n`;
|
||||||
const combinedPrompt = contextSection + prompt;
|
contextPrompt = contextSection + prompt;
|
||||||
|
|
||||||
if (aiService.estimateTokens(combinedPrompt) <= this.config.maxPromptTokens) {
|
|
||||||
contextPrompt = combinedPrompt;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await aiService.callMicroTaskAI(contextPrompt, maxTokens);
|
const response = await aiService.callMicroTaskAI(contextPrompt);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
taskType,
|
taskType,
|
||||||
@ -1280,12 +1209,10 @@ class AIPipeline {
|
|||||||
context.contextHistory.push(newEntry);
|
context.contextHistory.push(newEntry);
|
||||||
context.currentContextLength += entryTokens;
|
context.currentContextLength += entryTokens;
|
||||||
|
|
||||||
/*while (context.currentContextLength > this.config.maxContextTokens && context.contextHistory.length > 1) {
|
if (context.contextHistory.length > 1) {
|
||||||
const removed = context.contextHistory.shift()!;
|
const removed = context.contextHistory.shift()!;
|
||||||
context.currentContextLength -= aiService.estimateTokens(removed);
|
context.currentContextLength -= aiService.estimateTokens(removed);
|
||||||
}*/
|
}
|
||||||
const removed = context.contextHistory.shift()!;
|
|
||||||
context.currentContextLength -= aiService.estimateTokens(removed);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private addToolToSelection(
|
private addToolToSelection(
|
||||||
|
@ -8,7 +8,6 @@ export interface AIServiceConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface AICallOptions {
|
export interface AICallOptions {
|
||||||
maxTokens?: number;
|
|
||||||
temperature?: number;
|
temperature?: number;
|
||||||
timeout?: number;
|
timeout?: number;
|
||||||
}
|
}
|
||||||
@ -34,9 +33,8 @@ class AIService {
|
|||||||
};
|
};
|
||||||
|
|
||||||
this.defaultOptions = {
|
this.defaultOptions = {
|
||||||
maxTokens: 32768,
|
|
||||||
temperature: 0.3,
|
temperature: 0.3,
|
||||||
timeout: 30000
|
timeout: 60000
|
||||||
};
|
};
|
||||||
|
|
||||||
console.log('[AI-SERVICE] Initialized with model:', this.config.model);
|
console.log('[AI-SERVICE] Initialized with model:', this.config.model);
|
||||||
@ -55,7 +53,6 @@ class AIService {
|
|||||||
|
|
||||||
console.log('[AI-SERVICE] Making API call:', {
|
console.log('[AI-SERVICE] Making API call:', {
|
||||||
promptLength: prompt.length,
|
promptLength: prompt.length,
|
||||||
maxTokens: mergedOptions.maxTokens,
|
|
||||||
temperature: mergedOptions.temperature
|
temperature: mergedOptions.temperature
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -70,7 +67,6 @@ class AIService {
|
|||||||
const requestBody = {
|
const requestBody = {
|
||||||
model: this.config.model,
|
model: this.config.model,
|
||||||
messages: [{ role: 'user', content: prompt }],
|
messages: [{ role: 'user', content: prompt }],
|
||||||
max_tokens: mergedOptions.maxTokens,
|
|
||||||
temperature: mergedOptions.temperature
|
temperature: mergedOptions.temperature
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -122,11 +118,10 @@ class AIService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async callMicroTaskAI(prompt: string, maxTokens: number = 500): Promise<AIResponse> {
|
async callMicroTaskAI(prompt: string): Promise<AIResponse> {
|
||||||
return this.callAI(prompt, {
|
return this.callAI(prompt, {
|
||||||
maxTokens,
|
|
||||||
temperature: 0.3,
|
temperature: 0.3,
|
||||||
timeout: 15000
|
timeout: 30000
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -134,14 +129,6 @@ class AIService {
|
|||||||
return Math.ceil(text.length / 4);
|
return Math.ceil(text.length / 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
validatePromptLength(prompt: string, maxTokens: number = 35000): void {
|
|
||||||
const estimatedTokens = this.estimateTokens(prompt);
|
|
||||||
if (estimatedTokens > maxTokens) {
|
|
||||||
console.warn('[AI-SERVICE] WARNING: Prompt may exceed model limits:', estimatedTokens);
|
|
||||||
throw new Error(`Prompt too long: ${estimatedTokens} tokens (max: ${maxTokens})`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
getConfig(): AIServiceConfig {
|
getConfig(): AIServiceConfig {
|
||||||
return { ...this.config };
|
return { ...this.config };
|
||||||
}
|
}
|
||||||
|
@ -85,7 +85,7 @@ let cachedData: ToolsData | null = null;
|
|||||||
let cachedRandomizedData: ToolsData | null = null;
|
let cachedRandomizedData: ToolsData | null = null;
|
||||||
let cachedCompressedData: EnhancedCompressedToolsData | null = null;
|
let cachedCompressedData: EnhancedCompressedToolsData | null = null;
|
||||||
let lastRandomizationDate: string | null = null;
|
let lastRandomizationDate: string | null = null;
|
||||||
let dataVersion: string | null = null;
|
let cachedToolsHash: string | null = null;
|
||||||
|
|
||||||
function seededRandom(seed: number): () => number {
|
function seededRandom(seed: number): () => number {
|
||||||
let x = Math.sin(seed) * 10000;
|
let x = Math.sin(seed) * 10000;
|
||||||
@ -110,17 +110,6 @@ function shuffleArray<T>(array: T[], randomFn: () => number): T[] {
|
|||||||
return shuffled;
|
return shuffled;
|
||||||
}
|
}
|
||||||
|
|
||||||
function generateDataVersion(data: any): string {
|
|
||||||
const str = JSON.stringify(data, Object.keys(data).sort());
|
|
||||||
let hash = 0;
|
|
||||||
for (let i = 0; i < str.length; i++) {
|
|
||||||
const char = str.charCodeAt(i);
|
|
||||||
hash = ((hash << 5) - hash) + char;
|
|
||||||
hash = hash & hash;
|
|
||||||
}
|
|
||||||
return Math.abs(hash).toString(36);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function loadRawData(): Promise<ToolsData> {
|
async function loadRawData(): Promise<ToolsData> {
|
||||||
if (!cachedData) {
|
if (!cachedData) {
|
||||||
const yamlPath = path.join(process.cwd(), 'src/data/tools.yaml');
|
const yamlPath = path.join(process.cwd(), 'src/data/tools.yaml');
|
||||||
@ -142,8 +131,9 @@ async function loadRawData(): Promise<ToolsData> {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
dataVersion = generateDataVersion(cachedData);
|
const { getToolsFileHash } = await import('./hashUtils.js');
|
||||||
console.log(`[DATA SERVICE] Loaded enhanced data version: ${dataVersion}`);
|
cachedToolsHash = await getToolsFileHash();
|
||||||
|
console.log(`[DATA SERVICE] Loaded data with hash: ${cachedToolsHash.slice(0, 12)}...`);
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error instanceof z.ZodError) {
|
if (error instanceof z.ZodError) {
|
||||||
@ -234,7 +224,7 @@ export async function getCompressedToolsDataForAI(): Promise<EnhancedCompressedT
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function getDataVersion(): string | null {
|
export function getDataVersion(): string | null {
|
||||||
return dataVersion;
|
return cachedToolsHash;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function clearCache(): void {
|
export function clearCache(): void {
|
||||||
@ -242,7 +232,7 @@ export function clearCache(): void {
|
|||||||
cachedRandomizedData = null;
|
cachedRandomizedData = null;
|
||||||
cachedCompressedData = null;
|
cachedCompressedData = null;
|
||||||
lastRandomizationDate = null;
|
lastRandomizationDate = null;
|
||||||
dataVersion = null;
|
cachedToolsHash = null;
|
||||||
|
|
||||||
console.log('[DATA SERVICE] Enhanced cache cleared');
|
console.log('[DATA SERVICE] Enhanced cache cleared');
|
||||||
}
|
}
|
@ -100,7 +100,8 @@ class EmbeddingsService {
|
|||||||
await fs.mkdir(path.dirname(this.embeddingsPath), { recursive: true });
|
await fs.mkdir(path.dirname(this.embeddingsPath), { recursive: true });
|
||||||
|
|
||||||
const toolsData = await getCompressedToolsDataForAI();
|
const toolsData = await getCompressedToolsDataForAI();
|
||||||
const currentDataHash = await this.hashToolsFile();
|
const { getToolsFileHash } = await import('./hashUtils.js');
|
||||||
|
const currentDataHash = await getToolsFileHash();
|
||||||
|
|
||||||
const existing = await this.loadEmbeddings();
|
const existing = await this.loadEmbeddings();
|
||||||
|
|
||||||
@ -129,12 +130,6 @@ class EmbeddingsService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async hashToolsFile(): Promise<string> {
|
|
||||||
const file = path.join(process.cwd(), 'src', 'data', 'tools.yaml');
|
|
||||||
const raw = await fs.readFile(file, 'utf8');
|
|
||||||
return crypto.createHash('sha256').update(raw).digest('hex');
|
|
||||||
}
|
|
||||||
|
|
||||||
private async loadEmbeddings(): Promise<EmbeddingsDatabase | null> {
|
private async loadEmbeddings(): Promise<EmbeddingsDatabase | null> {
|
||||||
try {
|
try {
|
||||||
const data = await fs.readFile(this.embeddingsPath, 'utf8');
|
const data = await fs.readFile(this.embeddingsPath, 'utf8');
|
||||||
|
20
src/utils/hashUtils.ts
Normal file
20
src/utils/hashUtils.ts
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
// src/utils/hashUtils.ts
|
||||||
|
import { promises as fs } from 'fs';
|
||||||
|
import path from 'path';
|
||||||
|
import crypto from 'crypto';
|
||||||
|
|
||||||
|
export async function getToolsFileHash(): Promise<string> {
|
||||||
|
const file = path.join(process.cwd(), 'src', 'data', 'tools.yaml');
|
||||||
|
const raw = await fs.readFile(file, 'utf8');
|
||||||
|
return crypto.createHash('sha256').update(raw).digest('hex');
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getToolsFileHashSync(): string | null {
|
||||||
|
try {
|
||||||
|
const file = path.join(process.cwd(), 'src', 'data', 'tools.yaml');
|
||||||
|
const raw = require('fs').readFileSync(file, 'utf8');
|
||||||
|
return crypto.createHash('sha256').update(raw).digest('hex');
|
||||||
|
} catch {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
@ -38,7 +38,6 @@ export interface SelectionContext {
|
|||||||
export interface ToolSelectionResult {
|
export interface ToolSelectionResult {
|
||||||
selectedTools: any[];
|
selectedTools: any[];
|
||||||
selectedConcepts: any[];
|
selectedConcepts: any[];
|
||||||
//selectionMethod: string;
|
|
||||||
confidence: number;
|
confidence: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,13 +83,11 @@ class ToolSelector {
|
|||||||
domains: any[];
|
domains: any[];
|
||||||
phases: any[];
|
phases: any[];
|
||||||
'domain-agnostic-software': any[];
|
'domain-agnostic-software': any[];
|
||||||
//selectionMethod: string;
|
|
||||||
}> {
|
}> {
|
||||||
console.log('[TOOL-SELECTOR] Getting intelligent candidates for query');
|
console.log('[TOOL-SELECTOR] Getting intelligent candidates for query');
|
||||||
|
|
||||||
let candidateTools: any[] = [];
|
let candidateTools: any[] = [];
|
||||||
let candidateConcepts: any[] = [];
|
let candidateConcepts: any[] = [];
|
||||||
//let selectionMethod = 'unknown';
|
|
||||||
|
|
||||||
context.embeddingsSimilarities.clear();
|
context.embeddingsSimilarities.clear();
|
||||||
|
|
||||||
@ -133,23 +130,19 @@ class ToolSelector {
|
|||||||
if (similarTools.length >= this.config.embeddingsMinTools && reductionRatio <= this.config.embeddingsMaxReductionRatio) {
|
if (similarTools.length >= this.config.embeddingsMinTools && reductionRatio <= this.config.embeddingsMaxReductionRatio) {
|
||||||
candidateTools = similarTools;
|
candidateTools = similarTools;
|
||||||
candidateConcepts = similarConcepts;
|
candidateConcepts = similarConcepts;
|
||||||
//selectionMethod = 'embeddings_candidates';
|
|
||||||
|
|
||||||
console.log('[TOOL-SELECTOR] Using embeddings filtering:', totalAvailableTools, '→', similarTools.length, 'tools');
|
console.log('[TOOL-SELECTOR] Using embeddings filtering:', totalAvailableTools, '→', similarTools.length, 'tools');
|
||||||
} else {
|
} else {
|
||||||
console.log('[TOOL-SELECTOR] Embeddings filtering insufficient, using full dataset');
|
console.log('[TOOL-SELECTOR] Embeddings filtering insufficient, using full dataset');
|
||||||
candidateTools = toolsData.tools;
|
candidateTools = toolsData.tools;
|
||||||
candidateConcepts = toolsData.concepts;
|
candidateConcepts = toolsData.concepts;
|
||||||
//selectionMethod = 'full_dataset';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const selection = await this.performAISelection(
|
const selection = await this.performAISelection(
|
||||||
userQuery,
|
userQuery,
|
||||||
candidateTools,
|
candidateTools,
|
||||||
candidateConcepts,
|
candidateConcepts,
|
||||||
mode,
|
mode,
|
||||||
//selectionMethod,
|
|
||||||
context
|
context
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -158,8 +151,7 @@ class ToolSelector {
|
|||||||
concepts: selection.selectedConcepts,
|
concepts: selection.selectedConcepts,
|
||||||
domains: toolsData.domains,
|
domains: toolsData.domains,
|
||||||
phases: toolsData.phases,
|
phases: toolsData.phases,
|
||||||
'domain-agnostic-software': toolsData['domain-agnostic-software'],
|
'domain-agnostic-software': toolsData['domain-agnostic-software']
|
||||||
//selectionMethod
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -206,8 +198,6 @@ class ToolSelector {
|
|||||||
const basePrompt = getPrompt('toolSelection', mode, userQuery, this.config.maxSelectedItems);
|
const basePrompt = getPrompt('toolSelection', mode, userQuery, this.config.maxSelectedItems);
|
||||||
const prompt = getPrompt('toolSelectionWithData', basePrompt, toolsToSend, conceptsToSend);
|
const prompt = getPrompt('toolSelectionWithData', basePrompt, toolsToSend, conceptsToSend);
|
||||||
|
|
||||||
aiService.validatePromptLength(prompt);
|
|
||||||
|
|
||||||
console.log('[TOOL-SELECTOR] Sending to AI:',
|
console.log('[TOOL-SELECTOR] Sending to AI:',
|
||||||
toolsToSend.filter((t: any) => t.type === 'method').length, 'methods,',
|
toolsToSend.filter((t: any) => t.type === 'method').length, 'methods,',
|
||||||
toolsToSend.filter((t: any) => t.type === 'software').length, 'software,',
|
toolsToSend.filter((t: any) => t.type === 'software').length, 'software,',
|
||||||
@ -215,7 +205,7 @@ class ToolSelector {
|
|||||||
);
|
);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await aiService.callAI(prompt, { maxTokens: 32768 });
|
const response = await aiService.callAI(prompt);
|
||||||
const result = JSONParser.safeParseJSON(response.content, null);
|
const result = JSONParser.safeParseJSON(response.content, null);
|
||||||
|
|
||||||
if (!result || !Array.isArray(result.selectedTools) || !Array.isArray(result.selectedConcepts)) {
|
if (!result || !Array.isArray(result.selectedTools) || !Array.isArray(result.selectedConcepts)) {
|
||||||
@ -256,7 +246,6 @@ class ToolSelector {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
async selectToolsForPhase(
|
async selectToolsForPhase(
|
||||||
userQuery: string,
|
userQuery: string,
|
||||||
phase: any,
|
phase: any,
|
||||||
@ -278,7 +267,7 @@ class ToolSelector {
|
|||||||
const prompt = getPrompt('phaseToolSelection', userQuery, phase, availableTools);
|
const prompt = getPrompt('phaseToolSelection', userQuery, phase, availableTools);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await aiService.callMicroTaskAI(prompt, 1000);
|
const response = await aiService.callMicroTaskAI(prompt);
|
||||||
const selections = JSONParser.safeParseJSON(response.content, []);
|
const selections = JSONParser.safeParseJSON(response.content, []);
|
||||||
|
|
||||||
if (Array.isArray(selections)) {
|
if (Array.isArray(selections)) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user