some cleanup
This commit is contained in:
parent
07c8f707df
commit
5ecbabea90
@ -423,8 +423,6 @@ class AIQueryInterface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setupEventListeners() {
|
setupEventListeners() {
|
||||||
console.log('[AI Interface] Setting up event listeners...');
|
|
||||||
|
|
||||||
this.elements.toggleSwitch?.addEventListener('click', () => this.toggleMode());
|
this.elements.toggleSwitch?.addEventListener('click', () => this.toggleMode());
|
||||||
this.elements.workflowLabel?.addEventListener('click', () => this.setMode('workflow'));
|
this.elements.workflowLabel?.addEventListener('click', () => this.setMode('workflow'));
|
||||||
this.elements.toolLabel?.addEventListener('click', () => this.setMode('tool'));
|
this.elements.toolLabel?.addEventListener('click', () => this.setMode('tool'));
|
||||||
@ -438,13 +436,10 @@ class AIQueryInterface {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (this.elements.submitBtn) {
|
if (this.elements.submitBtn) {
|
||||||
console.log('[AI Interface] Attaching click handler to submit button');
|
|
||||||
this.elements.submitBtn.addEventListener('click', () => {
|
this.elements.submitBtn.addEventListener('click', () => {
|
||||||
console.log('[AI Interface] Submit button clicked!');
|
|
||||||
this.handleSubmit();
|
this.handleSubmit();
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
console.error('[AI Interface] Submit button not found!');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.elements.dismissSuggestions?.addEventListener('click', () => this.hideSmartPrompting());
|
this.elements.dismissSuggestions?.addEventListener('click', () => this.hideSmartPrompting());
|
||||||
@ -655,8 +650,6 @@ class AIQueryInterface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async handleSubmit() {
|
async handleSubmit() {
|
||||||
console.log('[AI Interface] handleSubmit called');
|
|
||||||
|
|
||||||
const query = this.elements.input.value.trim();
|
const query = this.elements.input.value.trim();
|
||||||
|
|
||||||
if (!query) {
|
if (!query) {
|
||||||
@ -1084,7 +1077,6 @@ class AIQueryInterface {
|
|||||||
if (downloadBtn && !downloadBtn.hasAttribute('data-setup')) {
|
if (downloadBtn && !downloadBtn.hasAttribute('data-setup')) {
|
||||||
downloadBtn.setAttribute('data-setup', 'true');
|
downloadBtn.setAttribute('data-setup', 'true');
|
||||||
downloadBtn.addEventListener('click', () => this.downloadResults());
|
downloadBtn.addEventListener('click', () => this.downloadResults());
|
||||||
console.log('[AI Interface] Download button setup complete');
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1119,7 +1111,6 @@ class AIQueryInterface {
|
|||||||
qualityMetrics: {
|
qualityMetrics: {
|
||||||
avgProcessingTime: 0,
|
avgProcessingTime: 0,
|
||||||
confidenceDistribution: { high: 0, medium: 0, low: 0 }
|
confidenceDistribution: { high: 0, medium: 0, low: 0 }
|
||||||
// Removed aiTransparency
|
|
||||||
},
|
},
|
||||||
analysisQuality: 'excellent',
|
analysisQuality: 'excellent',
|
||||||
keyInsights: [
|
keyInsights: [
|
||||||
@ -1602,25 +1593,33 @@ class AIQueryInterface {
|
|||||||
concept_name: bg.concept_name,
|
concept_name: bg.concept_name,
|
||||||
relevance: bg.relevance
|
relevance: bg.relevance
|
||||||
})) || [],
|
})) || [],
|
||||||
contextHistory: [], // This would need to be passed from server if needed
|
contextHistory: [],
|
||||||
embeddingsSimilarities: {} // This would need to be passed from server if needed
|
embeddingsSimilarities: {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Enhanced export structure with proper audit trail handling
|
||||||
const exportData = {
|
const exportData = {
|
||||||
metadata: {
|
metadata: {
|
||||||
timestamp: new Date().toISOString(),
|
timestamp: new Date().toISOString(),
|
||||||
version: "1.0",
|
version: "1.1", // Increment version for improved structure
|
||||||
toolsDataHash: toolsDataHash,
|
toolsDataHash: toolsDataHash,
|
||||||
aiModel: aiModel,
|
aiModel: aiModel,
|
||||||
aiParameters: aiParameters,
|
aiParameters: aiParameters,
|
||||||
userQuery: inputValue,
|
userQuery: inputValue,
|
||||||
mode: this.currentMode,
|
mode: this.currentMode,
|
||||||
processingStats: processingStats,
|
processingStats: processingStats,
|
||||||
exportedBy: 'ForensicPathways'
|
exportedBy: 'ForensicPathways',
|
||||||
|
auditTrailVersion: '1.1' // Track audit trail format version
|
||||||
},
|
},
|
||||||
recommendation: this.currentRecommendation,
|
recommendation: {
|
||||||
auditTrail: this.currentRecommendation.auditTrail || [],
|
// Export recommendation without auditTrail to avoid duplication
|
||||||
rawContext: rawContext
|
...this.currentRecommendation,
|
||||||
|
auditTrail: undefined // Remove from recommendation as it's at top level
|
||||||
|
},
|
||||||
|
auditTrail: this.currentRecommendation.auditTrail || [], // Extract to top level
|
||||||
|
rawContext: rawContext,
|
||||||
|
// Add validation checksum for integrity
|
||||||
|
checksum: this.calculateDataChecksum(this.currentRecommendation)
|
||||||
};
|
};
|
||||||
|
|
||||||
const blob = new Blob([JSON.stringify(exportData, null, 2)], {
|
const blob = new Blob([JSON.stringify(exportData, null, 2)], {
|
||||||
@ -1634,17 +1633,46 @@ class AIQueryInterface {
|
|||||||
a.click();
|
a.click();
|
||||||
URL.revokeObjectURL(url);
|
URL.revokeObjectURL(url);
|
||||||
|
|
||||||
console.log('[AI Interface] Analysis downloaded with real metadata:', {
|
console.log('[AI Interface] Analysis downloaded with enhanced structure:', {
|
||||||
|
version: '1.1',
|
||||||
aiModel,
|
aiModel,
|
||||||
toolsDataHash: toolsDataHash.slice(0, 8) + '...',
|
toolsDataHash: toolsDataHash.slice(0, 8) + '...',
|
||||||
tokensUsed: aiParameters.totalTokensUsed,
|
tokensUsed: aiParameters.totalTokensUsed,
|
||||||
auditEntries: exportData.auditTrail.length
|
auditEntries: exportData.auditTrail.length,
|
||||||
|
checksum: exportData.checksum.slice(0, 8) + '...'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
calculateDataChecksum(data) {
|
||||||
|
if (!data) return 'empty';
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Simple checksum based on key data properties
|
||||||
|
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; // Convert to 32-bit integer
|
||||||
|
}
|
||||||
|
return Math.abs(hash).toString(36);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('[AI Interface] Checksum calculation failed:', error);
|
||||||
|
return 'error';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
validateUploadStructure(data) {
|
validateUploadStructure(data) {
|
||||||
try {
|
try {
|
||||||
return !!(
|
const isValid = !!(
|
||||||
data &&
|
data &&
|
||||||
typeof data === 'object' &&
|
typeof data === 'object' &&
|
||||||
data.metadata &&
|
data.metadata &&
|
||||||
@ -1652,8 +1680,32 @@ class AIQueryInterface {
|
|||||||
typeof data.metadata.timestamp === 'string' &&
|
typeof data.metadata.timestamp === 'string' &&
|
||||||
data.recommendation &&
|
data.recommendation &&
|
||||||
typeof data.recommendation === 'object' &&
|
typeof data.recommendation === 'object' &&
|
||||||
Array.isArray(data.auditTrail)
|
Array.isArray(data.auditTrail) // Audit trail at top level
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (!isValid) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enhanced validation for audit trail structure
|
||||||
|
if (data.auditTrail.length > 0) {
|
||||||
|
const sampleEntry = data.auditTrail[0];
|
||||||
|
const hasRequiredFields = !!(
|
||||||
|
sampleEntry &&
|
||||||
|
typeof sampleEntry === 'object' &&
|
||||||
|
typeof sampleEntry.timestamp === 'number' &&
|
||||||
|
typeof sampleEntry.phase === 'string' &&
|
||||||
|
typeof sampleEntry.action === 'string' &&
|
||||||
|
typeof sampleEntry.confidence === 'number'
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!hasRequiredFields) {
|
||||||
|
console.warn('[AI Interface] Audit trail entries missing required fields');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('[AI Interface] Structure validation error:', error);
|
console.error('[AI Interface] Structure validation error:', error);
|
||||||
return false;
|
return false;
|
||||||
@ -1666,7 +1718,11 @@ class AIQueryInterface {
|
|||||||
|
|
||||||
this.showUploadedBanner(data.metadata);
|
this.showUploadedBanner(data.metadata);
|
||||||
|
|
||||||
this.currentRecommendation = data.recommendation;
|
// Fix: Ensure audit trail is available in recommendation for restoreAIResults
|
||||||
|
this.currentRecommendation = {
|
||||||
|
...data.recommendation,
|
||||||
|
auditTrail: data.auditTrail // Restore audit trail to recommendation object
|
||||||
|
};
|
||||||
|
|
||||||
this.showResults();
|
this.showResults();
|
||||||
|
|
||||||
@ -1757,7 +1813,15 @@ class AIQueryInterface {
|
|||||||
throw new Error('Ungültiges Analyse-Dateiformat');
|
throw new Error('Ungültiges Analyse-Dateiformat');
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('[AI Interface] Valid previous analysis file uploaded');
|
// Store audit trail separately for restore function
|
||||||
|
this.uploadedAuditTrail = data.auditTrail;
|
||||||
|
|
||||||
|
console.log('[AI Interface] Valid previous analysis file uploaded:', {
|
||||||
|
version: data.metadata.version || '1.0',
|
||||||
|
auditEntries: data.auditTrail?.length || 0,
|
||||||
|
toolsCount: data.recommendation.recommended_tools?.length || 0,
|
||||||
|
checksum: data.checksum?.slice(0, 8) + '...' || 'none'
|
||||||
|
});
|
||||||
|
|
||||||
this.hideResults();
|
this.hideResults();
|
||||||
this.hideError();
|
this.hideError();
|
||||||
@ -2218,15 +2282,20 @@ class AIQueryInterface {
|
|||||||
if (this.currentRecommendation && this.elements.results) {
|
if (this.currentRecommendation && this.elements.results) {
|
||||||
this.showResults();
|
this.showResults();
|
||||||
|
|
||||||
if (this.currentRecommendation.auditTrail) {
|
// Check both locations for audit trail for backward compatibility
|
||||||
|
const auditTrail = this.currentRecommendation.auditTrail || this.uploadedAuditTrail;
|
||||||
|
|
||||||
|
if (auditTrail && Array.isArray(auditTrail) && auditTrail.length > 0) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
try {
|
try {
|
||||||
this.renderAuditTrail(this.currentRecommendation.auditTrail);
|
this.renderAuditTrail(auditTrail);
|
||||||
console.log('[AI Interface] Audit trail restored successfully');
|
console.log('[AI Interface] Audit trail restored successfully:', auditTrail.length, 'entries');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('[AI Interface] Audit trail restore failed:', error);
|
console.error('[AI Interface] Audit trail restore failed:', error);
|
||||||
}
|
}
|
||||||
}, 100);
|
}, 100);
|
||||||
|
} else {
|
||||||
|
console.warn('[AI Interface] No audit trail available for restore');
|
||||||
}
|
}
|
||||||
|
|
||||||
this.hideLoading();
|
this.hideLoading();
|
||||||
|
@ -511,8 +511,6 @@ if (aiAuthRequired) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
function handleSharedURL() {
|
function handleSharedURL() {
|
||||||
console.log('[SHARE] Handling shared URL:', window.location.search);
|
|
||||||
|
|
||||||
const urlParams = new URLSearchParams(window.location.search);
|
const urlParams = new URLSearchParams(window.location.search);
|
||||||
const toolParam = urlParams.get('tool');
|
const toolParam = urlParams.get('tool');
|
||||||
const viewParam = urlParams.get('view');
|
const viewParam = urlParams.get('view');
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// src/utils/aiPipeline.ts - Fixed with accurate audit data and meaningful confidence
|
// src/utils/aiPipeline.ts - Fixed to remove hardcoded values and improve dynamics
|
||||||
import { getCompressedToolsDataForAI, getDataVersion } from './dataService.js';
|
import { getCompressedToolsDataForAI, getDataVersion } from './dataService.js';
|
||||||
import { aiService } from './aiService.js';
|
import { aiService } from './aiService.js';
|
||||||
import { toolSelector, type SelectionContext } from './toolSelector.js';
|
import { toolSelector, type SelectionContext } from './toolSelector.js';
|
||||||
@ -77,6 +77,12 @@ interface PipelineContext {
|
|||||||
}>;
|
}>;
|
||||||
seenToolNames: Set<string>;
|
seenToolNames: Set<string>;
|
||||||
embeddingsSimilarities: Map<string, number>;
|
embeddingsSimilarities: Map<string, number>;
|
||||||
|
// Add phase metadata for dynamic phase handling
|
||||||
|
phaseMetadata?: {
|
||||||
|
phases: any[];
|
||||||
|
criticalPhaseIds: string[];
|
||||||
|
phaseComplexity: Map<string, number>;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
class AIPipeline {
|
class AIPipeline {
|
||||||
@ -95,7 +101,7 @@ class AIPipeline {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
console.log('[AI-PIPELINE] Initialized with improved audit accuracy');
|
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> {
|
||||||
@ -121,17 +127,16 @@ class AIPipeline {
|
|||||||
maxContextLength: this.config.maxContextTokens,
|
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>(),
|
||||||
|
// Initialize phase metadata dynamically
|
||||||
|
phaseMetadata: this.initializePhaseMetadata(toolsData.phases)
|
||||||
};
|
};
|
||||||
|
|
||||||
// Skip initialization audit entry - it doesn't add transparency value
|
|
||||||
|
|
||||||
console.log('[AI-PIPELINE] Phase 1: Tool candidate selection');
|
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);
|
||||||
|
|
||||||
// Calculate meaningful confidence for tool selection
|
|
||||||
const selectionConfidence = this.calculateToolSelectionConfidence(
|
const selectionConfidence = this.calculateToolSelectionConfidence(
|
||||||
candidateData.tools.length,
|
candidateData.tools.length,
|
||||||
toolsData.tools.length,
|
toolsData.tools.length,
|
||||||
@ -197,8 +202,6 @@ class AIPipeline {
|
|||||||
|
|
||||||
const recommendation = this.buildRecommendation(context, mode, finalResult.content);
|
const recommendation = this.buildRecommendation(context, mode, finalResult.content);
|
||||||
|
|
||||||
// Skip completion audit entry - it doesn't add transparency value
|
|
||||||
|
|
||||||
const processingStats = {
|
const processingStats = {
|
||||||
embeddingsUsed: embeddingsService.isEnabled(),
|
embeddingsUsed: embeddingsService.isEnabled(),
|
||||||
candidatesFromEmbeddings: candidateData.tools.length,
|
candidatesFromEmbeddings: candidateData.tools.length,
|
||||||
@ -242,6 +245,55 @@ class AIPipeline {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private initializePhaseMetadata(phases: any[]): {
|
||||||
|
phases: any[];
|
||||||
|
criticalPhaseIds: string[];
|
||||||
|
phaseComplexity: Map<string, number>;
|
||||||
|
} {
|
||||||
|
if (!phases || !Array.isArray(phases)) {
|
||||||
|
console.warn('[AI-PIPELINE] No phases data available, using fallback');
|
||||||
|
return {
|
||||||
|
phases: [],
|
||||||
|
criticalPhaseIds: [],
|
||||||
|
phaseComplexity: new Map()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dynamically determine critical phases based on typical_tools or key_activities
|
||||||
|
const criticalPhaseIds = phases
|
||||||
|
.filter(phase => {
|
||||||
|
const typicalToolsCount = phase.typical_tools?.length || 0;
|
||||||
|
const keyActivitiesCount = phase.key_activities?.length || 0;
|
||||||
|
// Consider phases with many tools or activities as critical
|
||||||
|
return typicalToolsCount >= 3 || keyActivitiesCount >= 2;
|
||||||
|
})
|
||||||
|
.map(phase => phase.id);
|
||||||
|
|
||||||
|
// Calculate phase complexity based on metadata
|
||||||
|
const phaseComplexity = new Map<string, number>();
|
||||||
|
phases.forEach(phase => {
|
||||||
|
let complexity = 1; // Base complexity
|
||||||
|
|
||||||
|
if (phase.typical_tools?.length > 5) complexity += 1;
|
||||||
|
if (phase.key_activities?.length > 3) complexity += 1;
|
||||||
|
if (phase.description?.length > 100) complexity += 1;
|
||||||
|
|
||||||
|
phaseComplexity.set(phase.id, complexity);
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log('[AI-PIPELINE] Initialized phase metadata:', {
|
||||||
|
totalPhases: phases.length,
|
||||||
|
criticalPhases: criticalPhaseIds.length,
|
||||||
|
avgComplexity: Array.from(phaseComplexity.values()).reduce((sum, c) => sum + c, 0) / phases.length
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
phases,
|
||||||
|
criticalPhaseIds,
|
||||||
|
phaseComplexity
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
private calculateToolSelectionConfidence(
|
private calculateToolSelectionConfidence(
|
||||||
selectedCount: number,
|
selectedCount: number,
|
||||||
totalCount: number,
|
totalCount: number,
|
||||||
@ -252,26 +304,22 @@ class AIPipeline {
|
|||||||
|
|
||||||
const selectionRatio = selectedCount / totalCount;
|
const selectionRatio = selectedCount / totalCount;
|
||||||
|
|
||||||
// Good selection ratio (5-20% is optimal)
|
|
||||||
if (selectionRatio >= 0.05 && selectionRatio <= 0.20) {
|
if (selectionRatio >= 0.05 && selectionRatio <= 0.20) {
|
||||||
confidence += 25;
|
confidence += 25;
|
||||||
} else if (selectionRatio < 0.05) {
|
} else if (selectionRatio < 0.05) {
|
||||||
confidence += 15; // Very selective
|
confidence += 15;
|
||||||
} else if (selectionRatio > 0.30) {
|
} else if (selectionRatio > 0.30) {
|
||||||
confidence -= 15; // Too inclusive
|
confidence -= 15;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Embeddings method bonus
|
|
||||||
if (method.includes('embeddings')) {
|
if (method.includes('embeddings')) {
|
||||||
confidence += 15;
|
confidence += 15;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Concepts also selected
|
|
||||||
if (conceptsCount > 0) {
|
if (conceptsCount > 0) {
|
||||||
confidence += 10;
|
confidence += 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reasonable absolute numbers
|
|
||||||
if (selectedCount >= 8 && selectedCount <= 25) {
|
if (selectedCount >= 8 && selectedCount <= 25) {
|
||||||
confidence += 10;
|
confidence += 10;
|
||||||
}
|
}
|
||||||
@ -301,12 +349,12 @@ class AIPipeline {
|
|||||||
|
|
||||||
const selections = await toolSelector.selectToolsForPhase(context.userQuery, phase, phaseTools, context);
|
const selections = await toolSelector.selectToolsForPhase(context.userQuery, phase, phaseTools, context);
|
||||||
|
|
||||||
// Calculate meaningful confidence based on phase selection quality
|
|
||||||
const phaseConfidence = this.calculatePhaseSelectionConfidence(
|
const phaseConfidence = this.calculatePhaseSelectionConfidence(
|
||||||
selections.length,
|
selections.length,
|
||||||
phaseTools.length,
|
phaseTools.length,
|
||||||
phase.id,
|
phase.id,
|
||||||
selections
|
selections,
|
||||||
|
context.phaseMetadata
|
||||||
);
|
);
|
||||||
|
|
||||||
auditService.addEntry(
|
auditService.addEntry(
|
||||||
@ -341,7 +389,10 @@ class AIPipeline {
|
|||||||
const moderatedTaskRelevance = this.moderateTaskRelevance(sel.taskRelevance);
|
const moderatedTaskRelevance = this.moderateTaskRelevance(sel.taskRelevance);
|
||||||
const priority = this.derivePriorityFromScore(moderatedTaskRelevance);
|
const priority = this.derivePriorityFromScore(moderatedTaskRelevance);
|
||||||
|
|
||||||
this.addToolToSelection(context, tool, phase.id, priority, sel.justification, moderatedTaskRelevance, sel.limitations);
|
// Generate dynamic limitations based on context
|
||||||
|
const dynamicLimitations = this.generateDynamicLimitations(tool, phase, sel);
|
||||||
|
|
||||||
|
this.addToolToSelection(context, tool, phase.id, priority, sel.justification, moderatedTaskRelevance, dynamicLimitations);
|
||||||
|
|
||||||
auditService.addEntry(
|
auditService.addEntry(
|
||||||
'tool-reasoning',
|
'tool-reasoning',
|
||||||
@ -354,7 +405,7 @@ class AIPipeline {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
justification: sel.justification,
|
justification: sel.justification,
|
||||||
limitations: sel.limitations,
|
limitations: dynamicLimitations,
|
||||||
addedToPhase: phase.name
|
addedToPhase: phase.name
|
||||||
},
|
},
|
||||||
moderatedTaskRelevance || 70,
|
moderatedTaskRelevance || 70,
|
||||||
@ -384,19 +435,24 @@ class AIPipeline {
|
|||||||
selectedCount: number,
|
selectedCount: number,
|
||||||
availableCount: number,
|
availableCount: number,
|
||||||
phaseId: string,
|
phaseId: string,
|
||||||
selections: any[]
|
selections: any[],
|
||||||
|
phaseMetadata?: {
|
||||||
|
phases: any[];
|
||||||
|
criticalPhaseIds: string[];
|
||||||
|
phaseComplexity: Map<string, number>;
|
||||||
|
}
|
||||||
): number {
|
): number {
|
||||||
let confidence = 60;
|
let confidence = 60;
|
||||||
|
|
||||||
// Phase-specific expectations
|
// Use dynamic phase metadata instead of hardcoded values
|
||||||
const criticalPhases = ['acquisition', 'examination', 'analysis'];
|
const isCritical = phaseMetadata?.criticalPhaseIds.includes(phaseId) || false;
|
||||||
const isCritical = criticalPhases.includes(phaseId);
|
const phaseComplexity = phaseMetadata?.phaseComplexity.get(phaseId) || 1;
|
||||||
|
|
||||||
// Selection made
|
// Selection made
|
||||||
if (selectedCount > 0) {
|
if (selectedCount > 0) {
|
||||||
confidence += 20;
|
confidence += 20;
|
||||||
} else {
|
} else {
|
||||||
return 30; // No selection is concerning
|
return 30;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Selection ratio (for phases, 20-50% is reasonable)
|
// Selection ratio (for phases, 20-50% is reasonable)
|
||||||
@ -404,14 +460,19 @@ class AIPipeline {
|
|||||||
if (ratio >= 0.2 && ratio <= 0.5) {
|
if (ratio >= 0.2 && ratio <= 0.5) {
|
||||||
confidence += 15;
|
confidence += 15;
|
||||||
} else if (ratio < 0.2 && selectedCount >= 1) {
|
} else if (ratio < 0.2 && selectedCount >= 1) {
|
||||||
confidence += 10; // Selective is ok
|
confidence += 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Critical phases should have adequate tools
|
// Dynamic critical phase handling
|
||||||
if (isCritical && selectedCount >= 2) {
|
if (isCritical && selectedCount >= 2) {
|
||||||
confidence += 10;
|
confidence += 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Phase complexity factor
|
||||||
|
if (phaseComplexity > 2 && selectedCount >= phaseComplexity) {
|
||||||
|
confidence += 5;
|
||||||
|
}
|
||||||
|
|
||||||
// Quality of selections (based on task relevance)
|
// Quality of selections (based on task relevance)
|
||||||
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;
|
||||||
@ -425,6 +486,35 @@ class AIPipeline {
|
|||||||
return Math.min(95, Math.max(30, confidence));
|
return Math.min(95, Math.max(30, confidence));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private generateDynamicLimitations(tool: any, phase: any, selection: any): string[] {
|
||||||
|
const limitations: string[] = [];
|
||||||
|
|
||||||
|
// Add existing limitations if provided
|
||||||
|
if (selection.limitations && Array.isArray(selection.limitations)) {
|
||||||
|
limitations.push(...selection.limitations);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate context-aware limitations
|
||||||
|
if (tool.type === 'software' && !tool.projectUrl) {
|
||||||
|
limitations.push('Installation und Konfiguration erforderlich');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tool.skillLevel === 'expert') {
|
||||||
|
limitations.push('Erfordert spezialisierte Kenntnisse');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tool.license === 'Proprietary') {
|
||||||
|
limitations.push('Kommerzielle Lizenz erforderlich');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Phase-specific limitations
|
||||||
|
if (phase.id === 'acquisition' && tool.type === 'method') {
|
||||||
|
limitations.push('Sorgfältige Dokumentation für Chain of Custody erforderlich');
|
||||||
|
}
|
||||||
|
|
||||||
|
return limitations.slice(0, 3); // Limit to 3 most relevant
|
||||||
|
}
|
||||||
|
|
||||||
private async processToolMode(
|
private async processToolMode(
|
||||||
context: PipelineContext,
|
context: PipelineContext,
|
||||||
completedTasks: number,
|
completedTasks: number,
|
||||||
@ -582,7 +672,6 @@ class AIPipeline {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is the fix for "0 tools added" - use the actual valid tools
|
|
||||||
const actualToolsAdded = validTools.map(tool => tool.name);
|
const actualToolsAdded = validTools.map(tool => tool.name);
|
||||||
|
|
||||||
for (const tool of validTools) {
|
for (const tool of validTools) {
|
||||||
@ -610,6 +699,9 @@ class AIPipeline {
|
|||||||
moderatedTaskRelevance = this.moderateTaskRelevance(75);
|
moderatedTaskRelevance = this.moderateTaskRelevance(75);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Generate dynamic limitations instead of hardcoded ones
|
||||||
|
const dynamicLimitations = this.generateCompletionLimitations(tool, phase, selection);
|
||||||
|
|
||||||
this.addToolToSelection(
|
this.addToolToSelection(
|
||||||
context,
|
context,
|
||||||
tool,
|
tool,
|
||||||
@ -617,16 +709,15 @@ class AIPipeline {
|
|||||||
'medium',
|
'medium',
|
||||||
detailedJustification,
|
detailedJustification,
|
||||||
moderatedTaskRelevance,
|
moderatedTaskRelevance,
|
||||||
['Nachträgliche Ergänzung via semantische Phasensuche mit KI-Bewertung']
|
dynamicLimitations
|
||||||
);
|
);
|
||||||
|
|
||||||
console.log('[AI-PIPELINE] Added phase completion tool with AI reasoning:', tool.name);
|
console.log('[AI-PIPELINE] Added phase completion tool with AI reasoning:', tool.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use the actual tools added for audit
|
|
||||||
auditService.addPhaseCompletion(
|
auditService.addPhaseCompletion(
|
||||||
phase.id,
|
phase.id,
|
||||||
actualToolsAdded, // This ensures correct count
|
actualToolsAdded,
|
||||||
selection.completionReasoning || `${actualToolsAdded.length} Tools für ${phase.name} hinzugefügt`,
|
selection.completionReasoning || `${actualToolsAdded.length} Tools für ${phase.name} hinzugefügt`,
|
||||||
phaseStart,
|
phaseStart,
|
||||||
{
|
{
|
||||||
@ -660,6 +751,29 @@ class AIPipeline {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private generateCompletionLimitations(tool: any, phase: any, selection: any): string[] {
|
||||||
|
const limitations: string[] = [];
|
||||||
|
|
||||||
|
// Context-specific limitation for completion tools
|
||||||
|
limitations.push('Nachträgliche Ergänzung - ursprünglich nicht als Hauptmethode identifiziert');
|
||||||
|
|
||||||
|
// Tool-specific limitations
|
||||||
|
if (tool.skillLevel === 'expert') {
|
||||||
|
limitations.push('Erfordert Expertenwissen für optimale Nutzung');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tool.type === 'software' && !tool.projectUrl) {
|
||||||
|
limitations.push('Zusätzliche Setup-Zeit erforderlich');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Phase-specific context
|
||||||
|
if (phase.typical_tools && !phase.typical_tools.includes(tool.name)) {
|
||||||
|
limitations.push(`Nicht typisch für ${phase.name}-Phase - alternative Anwendung`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return limitations.slice(0, 3);
|
||||||
|
}
|
||||||
|
|
||||||
private moderateTaskRelevance(taskRelevance: number): number {
|
private moderateTaskRelevance(taskRelevance: number): number {
|
||||||
if (typeof taskRelevance !== 'number') {
|
if (typeof taskRelevance !== 'number') {
|
||||||
return 70;
|
return 70;
|
||||||
@ -904,7 +1018,6 @@ class AIPipeline {
|
|||||||
'background-knowledge'
|
'background-knowledge'
|
||||||
);
|
);
|
||||||
|
|
||||||
// Calculate confidence based on quality of selections
|
|
||||||
const selectionQualityBonus = this.calculateKnowledgeSelectionBonus(context.backgroundKnowledge, availableConcepts);
|
const selectionQualityBonus = this.calculateKnowledgeSelectionBonus(context.backgroundKnowledge, availableConcepts);
|
||||||
const finalConfidence = Math.min(95, responseConfidence + selectionQualityBonus);
|
const finalConfidence = Math.min(95, responseConfidence + selectionQualityBonus);
|
||||||
|
|
||||||
@ -951,13 +1064,11 @@ class AIPipeline {
|
|||||||
bonus += 10;
|
bonus += 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Good selection ratio (10-30% of available concepts)
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Quality reasoning provided
|
|
||||||
const hasGoodReasonings = selectedKnowledge.some(bk =>
|
const hasGoodReasonings = selectedKnowledge.some(bk =>
|
||||||
bk.relevance && bk.relevance.length > 30
|
bk.relevance && bk.relevance.length > 30
|
||||||
);
|
);
|
||||||
@ -983,7 +1094,6 @@ class AIPipeline {
|
|||||||
'final-recommendations'
|
'final-recommendations'
|
||||||
);
|
);
|
||||||
|
|
||||||
// Calculate bonus based on context quality
|
|
||||||
const contextBonus = this.calculateSynthesisBonus(selectedToolNames, context);
|
const contextBonus = this.calculateSynthesisBonus(selectedToolNames, context);
|
||||||
const finalConfidence = Math.min(95, confidence + contextBonus);
|
const finalConfidence = Math.min(95, confidence + contextBonus);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user