This commit is contained in:
overcuriousity 2025-08-16 17:11:03 +02:00
parent 3ad0d8120a
commit 1d98dd3257
4 changed files with 203648 additions and 152 deletions

203539
data/embeddings.json Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,6 @@
--- ---
//src/components/ToolMatrix.astro //src/components/ToolMatrix.astro
import { getToolsData } from '../utils/dataService.js'; import { getToolsData } from '../utils/dataService.js';
import ShareButton from './ShareButton.astro';
const data = await getToolsData(); const data = await getToolsData();

View File

@ -4,6 +4,7 @@ import { getCompressedToolsDataForAI } from './dataService.js';
import { embeddingsService, type EmbeddingData, type SimilarityResult } from './embeddings.js'; import { embeddingsService, type EmbeddingData, type SimilarityResult } from './embeddings.js';
import { AI_PROMPTS, getPrompt } from '../config/prompts.js'; import { AI_PROMPTS, getPrompt } from '../config/prompts.js';
import { isToolHosted } from './toolHelpers.js'; import { isToolHosted } from './toolHelpers.js';
import { auditService, type AuditEntry } from './auditService.js';
import dotenv from 'dotenv'; import dotenv from 'dotenv';
dotenv.config(); dotenv.config();
@ -35,17 +36,6 @@ interface AnalysisResult {
}; };
} }
interface AuditEntry {
timestamp: number;
phase: string;
action: string;
input: any;
output: any;
confidence: number;
processingTimeMs: number;
metadata: Record<string, any>;
}
interface AnalysisContext { interface AnalysisContext {
userQuery: string; userQuery: string;
mode: string; mode: string;
@ -70,7 +60,6 @@ interface AnalysisContext {
relevance: string; relevance: string;
}>; }>;
seenToolNames: Set<string>; seenToolNames: Set<string>;
auditTrail: AuditEntry[];
embeddingsSimilarities: Map<string, number>; embeddingsSimilarities: Map<string, number>;
aiSelectedTools?: any[]; aiSelectedTools?: any[];
aiSelectedConcepts?: any[]; aiSelectedConcepts?: any[];
@ -100,10 +89,6 @@ class ImprovedMicroTaskAIPipeline {
private softwareSelectionRatio: number; private softwareSelectionRatio: number;
private maxContextTokens: number; private maxContextTokens: number;
private maxPromptTokens: number; private maxPromptTokens: number;
private auditConfig: {
enabled: boolean;
detailLevel: string;
};
private confidenceConfig: { private confidenceConfig: {
semanticWeight: number; semanticWeight: number;
suitabilityWeight: number; suitabilityWeight: number;
@ -134,11 +119,6 @@ class ImprovedMicroTaskAIPipeline {
this.maxContextTokens = this.getEnvInt('AI_MAX_CONTEXT_TOKENS', 4000); this.maxContextTokens = this.getEnvInt('AI_MAX_CONTEXT_TOKENS', 4000);
this.maxPromptTokens = this.getEnvInt('AI_MAX_PROMPT_TOKENS', 1500); this.maxPromptTokens = this.getEnvInt('AI_MAX_PROMPT_TOKENS', 1500);
this.auditConfig = {
enabled: process.env.FORENSIC_AUDIT_ENABLED === 'true',
detailLevel: process.env.FORENSIC_AUDIT_DETAIL_LEVEL || 'standard'
};
this.confidenceConfig = { this.confidenceConfig = {
semanticWeight: this.getEnvFloat('CONFIDENCE_SEMANTIC_WEIGHT', 0.3), semanticWeight: this.getEnvFloat('CONFIDENCE_SEMANTIC_WEIGHT', 0.3),
suitabilityWeight: this.getEnvFloat('CONFIDENCE_SUITABILITY_WEIGHT', 0.7), suitabilityWeight: this.getEnvFloat('CONFIDENCE_SUITABILITY_WEIGHT', 0.7),
@ -147,7 +127,7 @@ class ImprovedMicroTaskAIPipeline {
highThreshold: this.getEnvInt('CONFIDENCE_HIGH_THRESHOLD', 80) highThreshold: this.getEnvInt('CONFIDENCE_HIGH_THRESHOLD', 80)
}; };
this.logPipelineInit(); console.log('[AI-PIPELINE] Initialized with audit service integration');
} }
private getRequiredEnv(key: string): string { private getRequiredEnv(key: string): string {
@ -168,12 +148,7 @@ class ImprovedMicroTaskAIPipeline {
return value ? parseFloat(value) : defaultValue; return value ? parseFloat(value) : defaultValue;
} }
private logPipelineInit(): void { // SIMPLIFIED AUDIT INTEGRATION - Use auditService instead of local implementation
console.log('[AI-PIPELINE] Initialized with audit:', this.auditConfig.enabled);
console.log('[AI-PIPELINE] Method/Software balance:',
`${(this.methodSelectionRatio * 100).toFixed(0)}%/${(this.softwareSelectionRatio * 100).toFixed(0)}%`);
}
private addAuditEntry( private addAuditEntry(
context: AnalysisContext, context: AnalysisContext,
phase: string, phase: string,
@ -184,25 +159,7 @@ class ImprovedMicroTaskAIPipeline {
startTime: number, startTime: number,
metadata: Record<string, any> = {} metadata: Record<string, any> = {}
): void { ): void {
if (!this.auditConfig.enabled) return; auditService.addEntry(phase, action, input, output, confidence, startTime, metadata);
const entry: AuditEntry = {
timestamp: Date.now(),
phase,
action,
input,
output,
confidence: Math.round(confidence),
processingTimeMs: Date.now() - startTime,
metadata
};
context.auditTrail.push(entry);
this.logAuditEntry(phase, action, confidence, entry.processingTimeMs);
}
private logAuditEntry(phase: string, action: string, confidence: number, timeMs: number): void {
console.log(`[AUDIT] ${phase}/${action}: ${confidence}% confidence, ${timeMs}ms`);
} }
private calculateSelectionConfidence(result: any, candidateCount: number): number { private calculateSelectionConfidence(result: any, candidateCount: number): number {
@ -474,24 +431,22 @@ class ImprovedMicroTaskAIPipeline {
selectionMethod = 'full_dataset'; selectionMethod = 'full_dataset';
} }
if (this.auditConfig.enabled) { this.addAuditEntry(
this.addAuditEntry( context,
context, 'retrieval',
'retrieval', 'embeddings-search',
'embeddings-search', { query: userQuery, threshold: this.similarityThreshold, candidates: this.embeddingCandidates },
{ query: userQuery, threshold: this.similarityThreshold, candidates: this.embeddingCandidates }, {
{ candidatesFound: similarItems.length,
candidatesFound: similarItems.length, reductionRatio: reductionRatio,
reductionRatio: reductionRatio, usingEmbeddings: selectionMethod === 'embeddings_candidates',
usingEmbeddings: selectionMethod === 'embeddings_candidates', totalAvailable: totalAvailableTools,
totalAvailable: totalAvailableTools, filtered: similarTools.length
filtered: similarTools.length },
}, selectionMethod === 'embeddings_candidates' ? 85 : 60,
selectionMethod === 'embeddings_candidates' ? 85 : 60, embeddingsStart,
embeddingsStart, { selectionMethod, embeddingsEnabled: true }
{ selectionMethod, embeddingsEnabled: true } );
);
}
} else { } else {
console.log('[AI-PIPELINE] Embeddings disabled, using full dataset'); console.log('[AI-PIPELINE] Embeddings disabled, using full dataset');
candidateTools = toolsData.tools; candidateTools = toolsData.tools;
@ -599,18 +554,16 @@ class ImprovedMicroTaskAIPipeline {
if (!result || !Array.isArray(result.selectedTools) || !Array.isArray(result.selectedConcepts)) { if (!result || !Array.isArray(result.selectedTools) || !Array.isArray(result.selectedConcepts)) {
console.error('[AI-PIPELINE] AI selection returned invalid structure'); console.error('[AI-PIPELINE] AI selection returned invalid structure');
if (this.auditConfig.enabled) { this.addAuditEntry(
this.addAuditEntry( context,
context, 'selection',
'selection', 'ai-tool-selection-failed',
'ai-tool-selection-failed', { candidateCount: candidateTools.length, mode },
{ candidateCount: candidateTools.length, mode }, { error: 'Invalid JSON structure' },
{ error: 'Invalid JSON structure' }, 10,
10, selectionStart,
selectionStart, { aiModel: this.config.model, selectionMethod }
{ aiModel: this.config.model, selectionMethod } );
);
}
throw new Error('AI selection failed to return valid tool and concept selection'); throw new Error('AI selection failed to return valid tool and concept selection');
} }
@ -636,44 +589,40 @@ class ImprovedMicroTaskAIPipeline {
console.log('[AI-PIPELINE] AI selected:', selectedMethods.length, 'methods,', selectedSoftware.length, 'software,', selectedConcepts.length, 'concepts'); console.log('[AI-PIPELINE] AI selected:', selectedMethods.length, 'methods,', selectedSoftware.length, 'software,', selectedConcepts.length, 'concepts');
if (this.auditConfig.enabled) { const confidence = this.calculateSelectionConfidence(result, candidateTools.length + candidateConcepts.length);
const confidence = this.calculateSelectionConfidence(result, candidateTools.length + candidateConcepts.length);
this.addAuditEntry( this.addAuditEntry(
context, context,
'selection', 'selection',
'ai-tool-selection', 'ai-tool-selection',
{ candidateCount: candidateTools.length, mode }, { candidateCount: candidateTools.length, mode },
{ {
selectedMethodCount: selectedMethods.length, selectedMethodCount: selectedMethods.length,
selectedSoftwareCount: selectedSoftware.length, selectedSoftwareCount: selectedSoftware.length,
selectedConceptCount: selectedConcepts.length, selectedConceptCount: selectedConcepts.length,
reasoning: result.reasoning?.slice(0, 200), reasoning: result.reasoning?.slice(0, 200),
methodBalance: `${((selectedMethods.length / (selectedTools.length || 1)) * 100).toFixed(0)}%` methodBalance: `${((selectedMethods.length / (selectedTools.length || 1)) * 100).toFixed(0)}%`
}, },
confidence, confidence,
selectionStart, selectionStart,
{ aiModel: this.config.model, selectionMethod } { aiModel: this.config.model, selectionMethod }
); );
}
return { selectedTools, selectedConcepts }; return { selectedTools, selectedConcepts };
} catch (error) { } catch (error) {
console.error('[AI-PIPELINE] AI selection failed:', error); console.error('[AI-PIPELINE] AI selection failed:', error);
if (this.auditConfig.enabled) { this.addAuditEntry(
this.addAuditEntry( context,
context, 'selection',
'selection', 'ai-tool-selection-error',
'ai-tool-selection-error', { candidateCount: candidateTools.length, mode },
{ candidateCount: candidateTools.length, mode }, { error: error.message },
{ error: error.message }, 5,
5, selectionStart,
selectionStart, { aiModel: this.config.model, selectionMethod }
{ aiModel: this.config.model, selectionMethod } );
);
}
throw error; throw error;
} }
} }
@ -1371,6 +1320,9 @@ class ImprovedMicroTaskAIPipeline {
console.log('[AI-PIPELINE] Starting', mode, 'query processing'); console.log('[AI-PIPELINE] Starting', mode, 'query processing');
// CLEAR AUDIT TRAIL for new analysis
auditService.clearAuditTrail();
try { try {
const toolsData = await getCompressedToolsDataForAI(); const toolsData = await getCompressedToolsDataForAI();
@ -1382,7 +1334,6 @@ class ImprovedMicroTaskAIPipeline {
maxContextLength: this.maxContextTokens, maxContextLength: this.maxContextTokens,
currentContextLength: 0, currentContextLength: 0,
seenToolNames: new Set<string>(), seenToolNames: new Set<string>(),
auditTrail: [],
embeddingsSimilarities: new Map<string, number>(), embeddingsSimilarities: new Map<string, number>(),
aiSelectedTools: [], aiSelectedTools: [],
aiSelectedConcepts: [] aiSelectedConcepts: []
@ -1410,7 +1361,7 @@ class ImprovedMicroTaskAIPipeline {
{ candidateTools: filteredData.tools.length, candidateConcepts: filteredData.concepts.length }, { candidateTools: filteredData.tools.length, candidateConcepts: filteredData.concepts.length },
90, 90,
startTime, startTime,
{ auditEnabled: this.auditConfig.enabled } { auditEnabled: auditService.isEnabled() }
); );
const analysisResult = await this.analyzeScenario(context); const analysisResult = await this.analyzeScenario(context);
@ -1459,7 +1410,7 @@ class ImprovedMicroTaskAIPipeline {
'completion', 'completion',
'pipeline-end', 'pipeline-end',
{ completedTasks: completeTasks, failedTasks }, { completedTasks: completeTasks, failedTasks },
{ finalRecommendation: !!recommendation, auditEntriesGenerated: context.auditTrail.length }, { finalRecommendation: !!recommendation, auditEntriesGenerated: auditService.getCurrentAuditTrail().length },
completeTasks > failedTasks ? 85 : 60, completeTasks > failedTasks ? 85 : 60,
startTime, startTime,
{ totalProcessingTimeMs: Date.now() - startTime } { totalProcessingTimeMs: Date.now() - startTime }
@ -1477,10 +1428,13 @@ class ImprovedMicroTaskAIPipeline {
console.log('[AI-PIPELINE] Processing complete. Tasks completed:', completeTasks, 'failed:', failedTasks); console.log('[AI-PIPELINE] Processing complete. Tasks completed:', completeTasks, 'failed:', failedTasks);
// FINALIZE AUDIT TRAIL and get final trail
const finalAuditTrail = auditService.finalizeAuditTrail();
return { return {
recommendation: { recommendation: {
...recommendation, ...recommendation,
auditTrail: this.auditConfig.enabled ? context.auditTrail : undefined auditTrail: auditService.isEnabled() ? finalAuditTrail : undefined
}, },
processingStats processingStats
}; };
@ -1522,8 +1476,6 @@ class ImprovedMicroTaskAIPipeline {
})) || [] })) || []
}; };
const processedAuditTrail = this.auditConfig.enabled && context.auditTrail ? context.auditTrail : [];
if (isWorkflow) { if (isWorkflow) {
const recommendedToolsWithConfidence = context.selectedTools?.map((st: any) => { const recommendedToolsWithConfidence = context.selectedTools?.map((st: any) => {
const confidence = this.calculateRecommendationConfidence( const confidence = this.calculateRecommendationConfidence(
@ -1565,8 +1517,7 @@ class ImprovedMicroTaskAIPipeline {
return { return {
...base, ...base,
recommended_tools: recommendedToolsWithConfidence, recommended_tools: recommendedToolsWithConfidence,
workflow_suggestion: finalContent, workflow_suggestion: finalContent
auditTrail: processedAuditTrail
}; };
} else { } else {
const recommendedToolsWithConfidence = context.selectedTools?.map((st: any) => { const recommendedToolsWithConfidence = context.selectedTools?.map((st: any) => {
@ -1610,8 +1561,7 @@ class ImprovedMicroTaskAIPipeline {
return { return {
...base, ...base,
recommended_tools: recommendedToolsWithConfidence, recommended_tools: recommendedToolsWithConfidence,
additional_considerations: finalContent, additional_considerations: finalContent
auditTrail: processedAuditTrail
}; };
} }
} }

View File

@ -11,7 +11,8 @@ function env(key: string, fallback: string | undefined = undefined): string | un
return fallback; return fallback;
} }
interface AuditEntry { // CONSOLIDATED AUDIT INTERFACES - Single source of truth
export interface AuditEntry {
timestamp: number; timestamp: number;
phase: string; phase: string;
action: string; action: string;
@ -40,7 +41,7 @@ interface CompressedAuditEntry {
metadata: Record<string, any>; metadata: Record<string, any>;
} }
interface ProcessedAuditTrail { export interface ProcessedAuditTrail {
totalTime: number; totalTime: number;
avgConfidence: number; avgConfidence: number;
stepCount: number; stepCount: number;
@ -63,7 +64,7 @@ interface ProcessedAuditTrail {
class AuditService { class AuditService {
private config: AuditConfig; private config: AuditConfig;
private tempEntries: AuditEntry[] = []; private activeAuditTrail: AuditEntry[] = [];
private readonly phaseConfig = { private readonly phaseConfig = {
'initialization': { icon: '🚀', displayName: 'Initialisierung' }, 'initialization': { icon: '🚀', displayName: 'Initialisierung' },
@ -83,11 +84,16 @@ class AuditService {
'tool-evaluation': 'Tool-Bewertung erstellt', 'tool-evaluation': 'Tool-Bewertung erstellt',
'background-knowledge-selection': 'Hintergrundwissen ausgewählt', 'background-knowledge-selection': 'Hintergrundwissen ausgewählt',
'confidence-scoring': 'Vertrauenswertung berechnet', 'confidence-scoring': 'Vertrauenswertung berechnet',
'phase-completion': 'Phasenergänzung durchgeführt',
'pipeline-end': 'Analyse abgeschlossen' 'pipeline-end': 'Analyse abgeschlossen'
}; };
constructor() { constructor() {
this.config = this.loadConfig(); this.config = this.loadConfig();
console.log('[AUDIT-SERVICE] Initialized:', {
enabled: this.config.enabled,
detailLevel: this.config.detailLevel
});
} }
private loadConfig(): AuditConfig { private loadConfig(): AuditConfig {
@ -96,14 +102,6 @@ class AuditService {
const retentionHours = parseInt(env('FORENSIC_AUDIT_RETENTION_HOURS', '72') || '72', 10); const retentionHours = parseInt(env('FORENSIC_AUDIT_RETENTION_HOURS', '72') || '72', 10);
const maxEntries = parseInt(env('FORENSIC_AUDIT_MAX_ENTRIES', '50') || '50', 10); const maxEntries = parseInt(env('FORENSIC_AUDIT_MAX_ENTRIES', '50') || '50', 10);
console.log('[AUDIT SERVICE] Configuration loaded:', {
enabled: enabledFlag === 'true',
detailLevel,
retentionHours,
maxEntries,
context: typeof process !== 'undefined' ? 'server' : 'client'
});
return { return {
enabled: enabledFlag === 'true', enabled: enabledFlag === 'true',
detailLevel, detailLevel,
@ -112,6 +110,7 @@ class AuditService {
}; };
} }
// CONSOLIDATED AUDIT ENTRY CREATION - Single method for all audit operations
addEntry( addEntry(
phase: string, phase: string,
action: string, action: string,
@ -134,35 +133,44 @@ class AuditService {
metadata metadata
}; };
this.tempEntries.push(entry); this.activeAuditTrail.push(entry);
console.log(`[AUDIT] ${phase}/${action}: ${confidence}% confidence, ${entry.processingTimeMs}ms`); console.log(`[AUDIT-SERVICE] ${phase}/${action}: ${confidence}% confidence, ${entry.processingTimeMs}ms`);
} }
// GET CURRENT AUDIT TRAIL - For integration with AI pipeline
mergeAndClear(auditTrail: AuditEntry[]): void { getCurrentAuditTrail(): AuditEntry[] {
if (!this.config.enabled || this.tempEntries.length === 0) return; return [...this.activeAuditTrail];
auditTrail.unshift(...this.tempEntries);
const entryCount = this.tempEntries.length;
this.tempEntries = [];
console.log(`[AUDIT] Merged ${entryCount} entries into audit trail`);
} }
// CLEAR AUDIT TRAIL - Start fresh for new analysis
clearAuditTrail(): void {
if (this.activeAuditTrail.length > 0) {
console.log(`[AUDIT-SERVICE] Cleared ${this.activeAuditTrail.length} audit entries`);
this.activeAuditTrail = [];
}
}
// FINALIZE AUDIT TRAIL - Complete analysis and return final trail
finalizeAuditTrail(): AuditEntry[] {
const finalTrail = [...this.activeAuditTrail];
console.log(`[AUDIT-SERVICE] Finalized audit trail with ${finalTrail.length} entries`);
this.clearAuditTrail();
return finalTrail;
}
processAuditTrail(rawAuditTrail: AuditEntry[]): ProcessedAuditTrail | null { processAuditTrail(rawAuditTrail: AuditEntry[]): ProcessedAuditTrail | null {
if (!this.config.enabled) { if (!this.config.enabled) {
console.log('[AUDIT] Service disabled, returning null'); console.log('[AUDIT-SERVICE] Processing disabled');
return null; return null;
} }
if (!rawAuditTrail || !Array.isArray(rawAuditTrail) || rawAuditTrail.length === 0) { if (!rawAuditTrail || !Array.isArray(rawAuditTrail) || rawAuditTrail.length === 0) {
console.log('[AUDIT] No audit trail data provided'); console.log('[AUDIT-SERVICE] No audit trail data to process');
return null; return null;
} }
try { try {
console.log('[AUDIT] Processing', rawAuditTrail.length, 'audit entries'); console.log(`[AUDIT-SERVICE] Processing ${rawAuditTrail.length} audit entries`);
const totalTime = rawAuditTrail.reduce((sum, entry) => sum + (entry.processingTimeMs || 0), 0); const totalTime = rawAuditTrail.reduce((sum, entry) => sum + (entry.processingTimeMs || 0), 0);
const validConfidenceEntries = rawAuditTrail.filter(entry => typeof entry.confidence === 'number'); const validConfidenceEntries = rawAuditTrail.filter(entry => typeof entry.confidence === 'number');
@ -197,8 +205,8 @@ class AuditService {
avgConfidence: phaseAvgConfidence, avgConfidence: phaseAvgConfidence,
totalTime: phaseTotalTime, totalTime: phaseTotalTime,
entries: validEntries entries: validEntries
.map(e => this.compressEntry(e)) .map(e => this.compressEntry(e))
.filter((e): e is CompressedAuditEntry => e !== null) .filter((e): e is CompressedAuditEntry => e !== null)
}; };
}).filter(phase => phase.entries.length > 0); }).filter(phase => phase.entries.length > 0);
@ -214,18 +222,18 @@ class AuditService {
summary summary
}; };
console.log('[AUDIT] Successfully processed audit trail:', result); console.log(`[AUDIT-SERVICE] Successfully processed audit trail: ${result.phases.length} phases, ${result.avgConfidence}% avg confidence`);
return result; return result;
} catch (error) { } catch (error) {
console.error('[AUDIT] Error processing audit trail:', error); console.error('[AUDIT-SERVICE] Error processing audit trail:', error);
return null; return null;
} }
} }
private compressEntry(entry: AuditEntry): CompressedAuditEntry | null { private compressEntry(entry: AuditEntry): CompressedAuditEntry | null {
if (!entry || typeof entry !== 'object') { if (!entry || typeof entry !== 'object') {
console.warn('[AUDIT] Invalid audit entry:', entry); console.warn('[AUDIT-SERVICE] Invalid audit entry skipped');
return null; return null;
} }
@ -241,7 +249,7 @@ class AuditService {
metadata: entry.metadata || {} metadata: entry.metadata || {}
}; };
} catch (error) { } catch (error) {
console.error('[AUDIT] Error compressing entry:', error); console.error('[AUDIT-SERVICE] Error compressing entry:', error);
return null; return null;
} }
} }
@ -375,4 +383,4 @@ class AuditService {
} }
export const auditService = new AuditService(); export const auditService = new AuditService();
export type { ProcessedAuditTrail, CompressedAuditEntry }; export type { CompressedAuditEntry };