remove some env vars
This commit is contained in:
parent
bcd92af8a0
commit
2cb25d1dd6
@ -60,7 +60,7 @@ FORENSIC_AUDIT_MAX_ENTRIES=50
|
||||
|
||||
# === AI SEMANTIC SEARCH ===
|
||||
# Enable semantic search (highly recommended for better results)
|
||||
AI_EMBEDDINGS_ENABLED=true
|
||||
REMOVE_AI_EMBEDDINGS_ENABLED=true
|
||||
AI_EMBEDDINGS_ENDPOINT=https://api.mistral.ai/v1/embeddings
|
||||
AI_EMBEDDINGS_API_KEY=your-embeddings-api-key-here
|
||||
AI_EMBEDDINGS_MODEL=mistral-embed
|
||||
@ -122,8 +122,8 @@ AI_EMBEDDINGS_BATCH_SIZE=10
|
||||
AI_EMBEDDINGS_BATCH_DELAY_MS=1000
|
||||
|
||||
# === Context Management ===
|
||||
AI_MAX_CONTEXT_TOKENS=4000
|
||||
AI_MAX_PROMPT_TOKENS=2500
|
||||
REMOVE_AI_MAX_CONTEXT_TOKENS=4000
|
||||
REMOVE_AI_MAX_PROMPT_TOKENS=2500
|
||||
|
||||
# === Confidence Scoring ===
|
||||
CONFIDENCE_SEMANTIC_WEIGHT=0.5
|
||||
|
@ -2,17 +2,15 @@
|
||||
|
||||
export const AI_PROMPTS = {
|
||||
|
||||
toolSelection: (mode: string, userQuery: string, selectionMethod: string, maxSelectedItems: number) => {
|
||||
toolSelection: (mode: string, userQuery: string, maxSelectedItems: number) => {
|
||||
const modeInstruction = mode === 'workflow'
|
||||
? 'Workflow mit 15-25 Items über alle Phasen. PFLICHT: Mindestens 40% Methoden, Rest Tools/Konzepte.'
|
||||
: 'Spezifische Lösung mit 4-10 Items. PFLICHT: Mindestens 30% Methoden wenn verfügbar.';
|
||||
|
||||
return `Du bist ein DFIR-Experte. Wähle die BESTEN Items aus dem vorgefilterten Set.
|
||||
|
||||
AUSWAHLMETHODE: ${selectionMethod}
|
||||
${selectionMethod === 'embeddings_candidates' ?
|
||||
'✓ Semantisch relevante Items bereits vorgefiltert\n✓ Wähle die BESTEN für die konkrete Aufgabe' :
|
||||
'✓ Vollständige Datenbank verfügbar\n✓ Wähle die relevantesten Items'}
|
||||
AUSWAHLMETHODE:
|
||||
'✓ Semantisch relevante Items bereits vorgefiltert\n✓ Wähle die BESTEN für die konkrete Aufgabe'}
|
||||
|
||||
${modeInstruction}
|
||||
|
||||
@ -309,7 +307,7 @@ Antwort: Fließtext ohne Listen, max ${isWorkflow ? '100' : '80'} Wörter.`;
|
||||
}
|
||||
} as const;
|
||||
|
||||
export function getPrompt(key: 'toolSelection', mode: string, userQuery: string, selectionMethod: string, maxSelectedItems: number): string;
|
||||
export function getPrompt(key: 'toolSelection', mode: string, userQuery: string, maxSelectedItems: number): string;
|
||||
export function getPrompt(key: 'toolSelectionWithData', basePrompt: string, toolsToSend: any[], conceptsToSend: any[]): string;
|
||||
export function getPrompt(key: 'scenarioAnalysis', isWorkflow: boolean, userQuery: string): string;
|
||||
export function getPrompt(key: 'investigationApproach', isWorkflow: boolean, userQuery: string): string;
|
||||
|
@ -11,7 +11,7 @@ import 'dotenv/config';
|
||||
|
||||
interface PipelineConfig {
|
||||
microTaskDelay: number;
|
||||
maxContextTokens: number;
|
||||
//maxContextTokens: number;
|
||||
maxPromptTokens: number;
|
||||
taskRelevanceModeration: {
|
||||
maxInitialScore: number;
|
||||
@ -36,7 +36,7 @@ interface MicroTaskResult {
|
||||
interface AnalysisResult {
|
||||
recommendation: any;
|
||||
processingStats: {
|
||||
embeddingsUsed: boolean;
|
||||
//embeddingsUsed: boolean;
|
||||
candidatesFromEmbeddings: number;
|
||||
finalSelectedItems: number;
|
||||
processingTimeMs: number;
|
||||
@ -57,7 +57,7 @@ interface PipelineContext {
|
||||
mode: string;
|
||||
filteredData: any;
|
||||
contextHistory: string[];
|
||||
maxContextLength: number;
|
||||
//maxContextLength: number;
|
||||
currentContextLength: number;
|
||||
scenarioAnalysis?: string;
|
||||
problemAnalysis?: string;
|
||||
@ -91,7 +91,7 @@ class AIPipeline {
|
||||
constructor() {
|
||||
this.config = {
|
||||
microTaskDelay: parseInt(process.env.AI_MICRO_TASK_DELAY_MS || '500', 10),
|
||||
maxContextTokens: parseInt(process.env.AI_MAX_CONTEXT_TOKENS || '4000', 10),
|
||||
//maxContextTokens: parseInt(process.env.AI_MAX_CONTEXT_TOKENS || '4000', 10),
|
||||
maxPromptTokens: parseInt(process.env.AI_MAX_PROMPT_TOKENS || '1500', 10),
|
||||
taskRelevanceModeration: {
|
||||
maxInitialScore: 85,
|
||||
@ -123,7 +123,7 @@ class AIPipeline {
|
||||
mode,
|
||||
filteredData: {},
|
||||
contextHistory: [],
|
||||
maxContextLength: this.config.maxContextTokens,
|
||||
//maxContextLength: this.config.maxContextTokens,
|
||||
currentContextLength: 0,
|
||||
seenToolNames: new Set<string>(),
|
||||
embeddingsSimilarities: new Map<string, number>(),
|
||||
@ -138,20 +138,20 @@ class AIPipeline {
|
||||
const selectionConfidence = this.calculateToolSelectionConfidence(
|
||||
candidateData.tools.length,
|
||||
toolsData.tools.length,
|
||||
candidateData.selectionMethod,
|
||||
//candidateData.selectionMethod,
|
||||
candidateData.concepts.length
|
||||
);
|
||||
|
||||
auditService.addToolSelection(
|
||||
candidateData.tools.map(t => t.name),
|
||||
toolsData.tools.map(t => t.name),
|
||||
candidateData.selectionMethod,
|
||||
//candidateData.selectionMethod,
|
||||
selectionConfidence,
|
||||
candidateSelectionStart,
|
||||
{
|
||||
embeddingsUsed: embeddingsService.isEnabled(),
|
||||
//embeddingsUsed: embeddingsService.isEnabled(),
|
||||
totalCandidatesFound: candidateData.tools.length + candidateData.concepts.length,
|
||||
selectionMethod: candidateData.selectionMethod,
|
||||
//selectionMethod: candidateData.selectionMethod,
|
||||
reductionRatio: candidateData.tools.length / toolsData.tools.length
|
||||
}
|
||||
);
|
||||
@ -201,7 +201,7 @@ class AIPipeline {
|
||||
const recommendation = this.buildRecommendation(context, mode, finalResult.content);
|
||||
|
||||
const processingStats = {
|
||||
embeddingsUsed: embeddingsService.isEnabled(),
|
||||
//embeddingsUsed: embeddingsService.isEnabled(),
|
||||
candidatesFromEmbeddings: candidateData.tools.length,
|
||||
finalSelectedItems: (context.selectedTools?.length || 0) + (context.backgroundKnowledge?.length || 0),
|
||||
processingTimeMs: Date.now() - startTime,
|
||||
@ -213,7 +213,7 @@ class AIPipeline {
|
||||
aiModel: aiConfig.model,
|
||||
toolsDataHash,
|
||||
temperature: 0.3,
|
||||
maxTokensUsed: 2500
|
||||
maxTokensUsed: 32768
|
||||
};
|
||||
|
||||
console.log('[AI-PIPELINE] Pipeline completed successfully:', {
|
||||
@ -292,7 +292,7 @@ class AIPipeline {
|
||||
private calculateToolSelectionConfidence(
|
||||
selectedCount: number,
|
||||
totalCount: number,
|
||||
method: string,
|
||||
//method: string,
|
||||
conceptsCount: number
|
||||
): number {
|
||||
let confidence = 50;
|
||||
@ -307,9 +307,9 @@ class AIPipeline {
|
||||
confidence -= 15;
|
||||
}
|
||||
|
||||
if (method.includes('embeddings')) {
|
||||
confidence += 15;
|
||||
}
|
||||
//if (method.includes('embeddings')) {
|
||||
//confidence += 15;
|
||||
//}
|
||||
|
||||
if (conceptsCount > 0) {
|
||||
confidence += 10;
|
||||
@ -1280,10 +1280,12 @@ class AIPipeline {
|
||||
context.contextHistory.push(newEntry);
|
||||
context.currentContextLength += entryTokens;
|
||||
|
||||
while (context.currentContextLength > this.config.maxContextTokens && context.contextHistory.length > 1) {
|
||||
/*while (context.currentContextLength > this.config.maxContextTokens && context.contextHistory.length > 1) {
|
||||
const removed = context.contextHistory.shift()!;
|
||||
context.currentContextLength -= aiService.estimateTokens(removed);
|
||||
}
|
||||
}*/
|
||||
const removed = context.contextHistory.shift()!;
|
||||
context.currentContextLength -= aiService.estimateTokens(removed);
|
||||
}
|
||||
|
||||
private addToolToSelection(
|
||||
|
@ -34,7 +34,7 @@ class AIService {
|
||||
};
|
||||
|
||||
this.defaultOptions = {
|
||||
maxTokens: 1500,
|
||||
maxTokens: 32768,
|
||||
temperature: 0.3,
|
||||
timeout: 30000
|
||||
};
|
||||
|
@ -26,7 +26,7 @@ export interface AuditEntry {
|
||||
completionTokens?: number;
|
||||
toolsDataHash?: string;
|
||||
embeddingsUsed?: boolean;
|
||||
selectionMethod?: string;
|
||||
//selectionMethod?: string;
|
||||
microTaskType?: string;
|
||||
confidenceFactors?: string[];
|
||||
reasoning?: string;
|
||||
@ -146,7 +146,7 @@ class AuditService {
|
||||
addToolSelection(
|
||||
selectedTools: string[],
|
||||
availableTools: string[],
|
||||
selectionMethod: string,
|
||||
//selectionMethod: string,
|
||||
confidence: number,
|
||||
startTime: number,
|
||||
metadata: Record<string, any> = {}
|
||||
@ -154,17 +154,22 @@ class AuditService {
|
||||
const calculatedConfidence = this.calculateSelectionConfidence(
|
||||
selectedTools,
|
||||
availableTools,
|
||||
selectionMethod,
|
||||
//selectionMethod,
|
||||
metadata
|
||||
);
|
||||
|
||||
const decisionBasis =
|
||||
metadata.embeddingsUsed || metadata.similarityScores
|
||||
? 'semantic-search'
|
||||
: (metadata.aiPrompt || metadata.microTaskType ? 'ai-analysis' : 'rule-based');
|
||||
|
||||
this.addEntry(
|
||||
'tool-selection',
|
||||
'selection-decision',
|
||||
{
|
||||
availableTools: availableTools.slice(0, 10),
|
||||
totalAvailable: availableTools.length,
|
||||
selectionMethod: selectionMethod
|
||||
//selectionMethod: selectionMethod
|
||||
},
|
||||
{
|
||||
selectedTools: selectedTools,
|
||||
@ -174,10 +179,11 @@ class AuditService {
|
||||
startTime,
|
||||
{
|
||||
...metadata,
|
||||
selectionMethod,
|
||||
//selectionMethod,
|
||||
availableToolsCount: availableTools.length,
|
||||
selectedToolsCount: selectedTools.length,
|
||||
decisionBasis: selectionMethod.includes('embeddings') ? 'semantic-search' : 'ai-analysis'
|
||||
//decisionBasis: selectionMethod.includes('embeddings') ? 'semantic-search' : 'ai-analysis'
|
||||
decisionBasis
|
||||
}
|
||||
);
|
||||
}
|
||||
@ -282,7 +288,7 @@ class AuditService {
|
||||
private calculateSelectionConfidence(
|
||||
selectedTools: string[],
|
||||
availableTools: string[],
|
||||
selectionMethod: string,
|
||||
//selectionMethod: string,
|
||||
metadata: Record<string, any>
|
||||
): number {
|
||||
let confidence = 50;
|
||||
@ -297,9 +303,9 @@ class AuditService {
|
||||
confidence -= 20;
|
||||
}
|
||||
|
||||
if (selectionMethod.includes('embeddings')) {
|
||||
/*if (selectionMethod.includes('embeddings')) {
|
||||
confidence += 15;
|
||||
}
|
||||
}*/
|
||||
|
||||
if (selectedTools.length >= 5 && selectedTools.length <= 25) {
|
||||
confidence += 10;
|
||||
@ -589,7 +595,8 @@ class AuditService {
|
||||
}
|
||||
|
||||
private inferDecisionBasis(metadata: Record<string, any>): string {
|
||||
if (metadata.embeddingsUsed || metadata.selectionMethod?.includes('embeddings')) return 'semantic-search';
|
||||
if (metadata.embeddingsUsed) return 'semantic-search';
|
||||
//if (metadata.embeddingsUsed || metadata.selectionMethod?.includes('embeddings')) return 'semantic-search';
|
||||
if (metadata.aiPrompt || metadata.microTaskType) return 'ai-analysis';
|
||||
if (metadata.semanticQuery && metadata.aiReasoningUsed) return 'hybrid';
|
||||
return 'rule-based';
|
||||
|
@ -31,7 +31,7 @@ interface EmbeddingsDatabase {
|
||||
}
|
||||
|
||||
interface EmbeddingsConfig {
|
||||
enabled: boolean;
|
||||
//enabled: boolean;
|
||||
endpoint?: string;
|
||||
apiKey?: string;
|
||||
model?: string;
|
||||
@ -49,14 +49,14 @@ class EmbeddingsService {
|
||||
constructor() {
|
||||
this.config = this.loadConfig();
|
||||
console.log('[EMBEDDINGS-SERVICE] Initialized:', {
|
||||
enabled: this.config.enabled,
|
||||
//enabled: this.config.enabled,
|
||||
hasEndpoint: !!this.config.endpoint,
|
||||
hasModel: !!this.config.model
|
||||
});
|
||||
}
|
||||
|
||||
private loadConfig(): EmbeddingsConfig {
|
||||
const enabled = process.env.AI_EMBEDDINGS_ENABLED === 'true';
|
||||
//const enabled = process.env.AI_EMBEDDINGS_ENABLED === 'true';
|
||||
const endpoint = process.env.AI_EMBEDDINGS_ENDPOINT;
|
||||
const apiKey = process.env.AI_EMBEDDINGS_API_KEY;
|
||||
const model = process.env.AI_EMBEDDINGS_MODEL;
|
||||
@ -64,7 +64,7 @@ class EmbeddingsService {
|
||||
const batchDelay = parseInt(process.env.AI_EMBEDDINGS_BATCH_DELAY_MS || '1000', 10);
|
||||
|
||||
return {
|
||||
enabled,
|
||||
//enabled,
|
||||
endpoint,
|
||||
apiKey,
|
||||
model,
|
||||
@ -92,10 +92,10 @@ class EmbeddingsService {
|
||||
try {
|
||||
console.log('[EMBEDDINGS-SERVICE] Starting initialization');
|
||||
|
||||
if (!this.config.enabled) {
|
||||
/*if (!this.config.enabled) {
|
||||
console.log('[EMBEDDINGS-SERVICE] Service disabled via configuration');
|
||||
return;
|
||||
}
|
||||
}*/
|
||||
|
||||
await fs.mkdir(path.dirname(this.embeddingsPath), { recursive: true });
|
||||
|
||||
@ -263,7 +263,7 @@ class EmbeddingsService {
|
||||
}
|
||||
|
||||
async embedText(text: string): Promise<number[]> {
|
||||
if (!this.isEnabled() || !this.isInitialized) {
|
||||
if (!this.isInitialized) {
|
||||
throw new Error('Embeddings service not available');
|
||||
}
|
||||
|
||||
@ -272,9 +272,9 @@ class EmbeddingsService {
|
||||
}
|
||||
|
||||
async waitForInitialization(): Promise<void> {
|
||||
if (!this.config.enabled) {
|
||||
/*if (!this.config.enabled) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
}*/
|
||||
|
||||
if (this.isInitialized) {
|
||||
return Promise.resolve();
|
||||
@ -303,10 +303,10 @@ class EmbeddingsService {
|
||||
}
|
||||
|
||||
async findSimilar(query: string, maxResults: number = 30, threshold: number = 0.3): Promise<SimilarityResult[]> {
|
||||
if (!this.config.enabled) {
|
||||
/*if (!this.config.enabled) {
|
||||
console.log('[EMBEDDINGS-SERVICE] Service disabled, returning empty results');
|
||||
return [];
|
||||
}
|
||||
}*/
|
||||
|
||||
if (!this.isInitialized || this.embeddings.length === 0) {
|
||||
console.log('[EMBEDDINGS-SERVICE] Not initialized or no embeddings available');
|
||||
@ -349,16 +349,24 @@ class EmbeddingsService {
|
||||
}
|
||||
}
|
||||
|
||||
isEnabled(): boolean {
|
||||
/*isEnabled(): boolean {
|
||||
return this.config.enabled;
|
||||
}
|
||||
}*/
|
||||
|
||||
getStats(): { enabled: boolean; initialized: boolean; count: number } {
|
||||
/*getStats(): { enabled: boolean; initialized: boolean; count: number } {
|
||||
return {
|
||||
enabled: this.config.enabled,
|
||||
initialized: this.isInitialized,
|
||||
count: this.embeddings.length
|
||||
};
|
||||
}*/
|
||||
|
||||
getStats(): {initialized: boolean; count: number } {
|
||||
return {
|
||||
//enabled: this.config.enabled,
|
||||
initialized: this.isInitialized,
|
||||
count: this.embeddings.length
|
||||
};
|
||||
}
|
||||
|
||||
getConfig(): EmbeddingsConfig {
|
||||
|
@ -38,7 +38,7 @@ export interface SelectionContext {
|
||||
export interface ToolSelectionResult {
|
||||
selectedTools: any[];
|
||||
selectedConcepts: any[];
|
||||
selectionMethod: string;
|
||||
//selectionMethod: string;
|
||||
confidence: number;
|
||||
}
|
||||
|
||||
@ -84,13 +84,13 @@ class ToolSelector {
|
||||
domains: any[];
|
||||
phases: any[];
|
||||
'domain-agnostic-software': any[];
|
||||
selectionMethod: string;
|
||||
//selectionMethod: string;
|
||||
}> {
|
||||
console.log('[TOOL-SELECTOR] Getting intelligent candidates for query');
|
||||
|
||||
let candidateTools: any[] = [];
|
||||
let candidateConcepts: any[] = [];
|
||||
let selectionMethod = 'unknown';
|
||||
//let selectionMethod = 'unknown';
|
||||
|
||||
context.embeddingsSimilarities.clear();
|
||||
|
||||
@ -100,62 +100,56 @@ class ToolSelector {
|
||||
console.error('[TOOL-SELECTOR] Embeddings initialization failed:', error);
|
||||
}
|
||||
|
||||
if (embeddingsService.isEnabled()) {
|
||||
console.log('[TOOL-SELECTOR] Using embeddings for candidate selection');
|
||||
console.log('[TOOL-SELECTOR] Using embeddings for candidate selection');
|
||||
|
||||
const similarItems = await embeddingsService.findSimilar(
|
||||
userQuery,
|
||||
this.config.embeddingCandidates,
|
||||
this.config.similarityThreshold
|
||||
) as SimilarityResult[];
|
||||
const similarItems = await embeddingsService.findSimilar(
|
||||
userQuery,
|
||||
this.config.embeddingCandidates,
|
||||
this.config.similarityThreshold
|
||||
) as SimilarityResult[];
|
||||
|
||||
console.log('[TOOL-SELECTOR] Embeddings found', similarItems.length, 'similar items');
|
||||
console.log('[TOOL-SELECTOR] Embeddings found', similarItems.length, 'similar items');
|
||||
|
||||
similarItems.forEach(item => {
|
||||
context.embeddingsSimilarities.set(item.name, item.similarity);
|
||||
});
|
||||
similarItems.forEach(item => {
|
||||
context.embeddingsSimilarities.set(item.name, item.similarity);
|
||||
});
|
||||
|
||||
const toolsMap = new Map(toolsData.tools.map((tool: any) => [tool.name, tool]));
|
||||
const conceptsMap = new Map(toolsData.concepts.map((concept: any) => [concept.name, concept]));
|
||||
const toolsMap = new Map(toolsData.tools.map((tool: any) => [tool.name, tool]));
|
||||
const conceptsMap = new Map(toolsData.concepts.map((concept: any) => [concept.name, concept]));
|
||||
|
||||
const similarTools = similarItems
|
||||
.filter((item: any) => item.type === 'tool')
|
||||
.map((item: any) => toolsMap.get(item.name))
|
||||
.filter((tool: any): tool is NonNullable<any> => tool !== undefined && tool !== null);
|
||||
const similarTools = similarItems
|
||||
.filter((item: any) => item.type === 'tool')
|
||||
.map((item: any) => toolsMap.get(item.name))
|
||||
.filter((tool: any): tool is NonNullable<any> => tool !== undefined && tool !== null);
|
||||
|
||||
const similarConcepts = similarItems
|
||||
.filter((item: any) => item.type === 'concept')
|
||||
.map((item: any) => conceptsMap.get(item.name))
|
||||
.filter((concept: any): concept is NonNullable<any> => concept !== undefined && concept !== null);
|
||||
const similarConcepts = similarItems
|
||||
.filter((item: any) => item.type === 'concept')
|
||||
.map((item: any) => conceptsMap.get(item.name))
|
||||
.filter((concept: any): concept is NonNullable<any> => concept !== undefined && concept !== null);
|
||||
|
||||
const totalAvailableTools = toolsData.tools.length;
|
||||
const reductionRatio = similarTools.length / totalAvailableTools;
|
||||
const totalAvailableTools = toolsData.tools.length;
|
||||
const reductionRatio = similarTools.length / totalAvailableTools;
|
||||
|
||||
if (similarTools.length >= this.config.embeddingsMinTools && reductionRatio <= this.config.embeddingsMaxReductionRatio) {
|
||||
candidateTools = similarTools;
|
||||
candidateConcepts = similarConcepts;
|
||||
selectionMethod = 'embeddings_candidates';
|
||||
if (similarTools.length >= this.config.embeddingsMinTools && reductionRatio <= this.config.embeddingsMaxReductionRatio) {
|
||||
candidateTools = similarTools;
|
||||
candidateConcepts = similarConcepts;
|
||||
//selectionMethod = 'embeddings_candidates';
|
||||
|
||||
console.log('[TOOL-SELECTOR] Using embeddings filtering:', totalAvailableTools, '→', similarTools.length, 'tools');
|
||||
} else {
|
||||
console.log('[TOOL-SELECTOR] Embeddings filtering insufficient, using full dataset');
|
||||
candidateTools = toolsData.tools;
|
||||
candidateConcepts = toolsData.concepts;
|
||||
selectionMethod = 'full_dataset';
|
||||
}
|
||||
console.log('[TOOL-SELECTOR] Using embeddings filtering:', totalAvailableTools, '→', similarTools.length, 'tools');
|
||||
} else {
|
||||
console.log('[TOOL-SELECTOR] Embeddings disabled, using full dataset');
|
||||
console.log('[TOOL-SELECTOR] Embeddings filtering insufficient, using full dataset');
|
||||
candidateTools = toolsData.tools;
|
||||
candidateConcepts = toolsData.concepts;
|
||||
selectionMethod = 'full_dataset';
|
||||
//selectionMethod = 'full_dataset';
|
||||
}
|
||||
|
||||
|
||||
const selection = await this.performAISelection(
|
||||
userQuery,
|
||||
candidateTools,
|
||||
candidateConcepts,
|
||||
mode,
|
||||
selectionMethod,
|
||||
//selectionMethod,
|
||||
context
|
||||
);
|
||||
|
||||
@ -165,7 +159,7 @@ class ToolSelector {
|
||||
domains: toolsData.domains,
|
||||
phases: toolsData.phases,
|
||||
'domain-agnostic-software': toolsData['domain-agnostic-software'],
|
||||
selectionMethod
|
||||
//selectionMethod
|
||||
};
|
||||
}
|
||||
|
||||
@ -174,7 +168,6 @@ class ToolSelector {
|
||||
candidateTools: any[],
|
||||
candidateConcepts: any[],
|
||||
mode: string,
|
||||
selectionMethod: string,
|
||||
context: SelectionContext
|
||||
): Promise<ToolSelectionResult> {
|
||||
console.log('[TOOL-SELECTOR] Performing AI selection');
|
||||
@ -188,53 +181,29 @@ class ToolSelector {
|
||||
const softwareWithFullData = candidateSoftware.map(this.createToolData);
|
||||
const conceptsWithFullData = candidateConcepts.map(this.createConceptData);
|
||||
|
||||
let toolsToSend: any[];
|
||||
let conceptsToSend: any[];
|
||||
// Unified selection limits (method-agnostic)
|
||||
const maxTools = Math.min(this.config.embeddingSelectionLimit, this.config.noEmbeddingsToolLimit);
|
||||
const maxConcepts = Math.min(this.config.embeddingConceptsLimit, this.config.noEmbeddingsConceptLimit);
|
||||
const methodLimit = Math.ceil(maxTools * this.config.methodSelectionRatio);
|
||||
const softwareLimit = Math.floor(maxTools * this.config.softwareSelectionRatio);
|
||||
|
||||
if (selectionMethod === 'embeddings_candidates') {
|
||||
const totalLimit = this.config.embeddingSelectionLimit;
|
||||
const methodLimit = Math.ceil(totalLimit * this.config.methodSelectionRatio);
|
||||
const softwareLimit = Math.floor(totalLimit * this.config.softwareSelectionRatio);
|
||||
// Build tool list to send
|
||||
const toolsToSend: any[] = [
|
||||
...methodsWithFullData.slice(0, methodLimit),
|
||||
...softwareWithFullData.slice(0, softwareLimit),
|
||||
];
|
||||
|
||||
toolsToSend = [
|
||||
...methodsWithFullData.slice(0, methodLimit),
|
||||
...softwareWithFullData.slice(0, softwareLimit)
|
||||
];
|
||||
|
||||
const remainingCapacity = totalLimit - toolsToSend.length;
|
||||
if (remainingCapacity > 0) {
|
||||
if (methodsWithFullData.length > methodLimit) {
|
||||
toolsToSend.push(...methodsWithFullData.slice(methodLimit, methodLimit + remainingCapacity));
|
||||
} else if (softwareWithFullData.length > softwareLimit) {
|
||||
toolsToSend.push(...softwareWithFullData.slice(softwareLimit, softwareLimit + remainingCapacity));
|
||||
}
|
||||
}
|
||||
|
||||
conceptsToSend = conceptsWithFullData.slice(0, this.config.embeddingConceptsLimit);
|
||||
} else {
|
||||
const maxTools = this.config.noEmbeddingsToolLimit;
|
||||
const maxConcepts = this.config.noEmbeddingsConceptLimit;
|
||||
const methodLimit = Math.ceil(maxTools * 0.4);
|
||||
const softwareLimit = Math.floor(maxTools * 0.5);
|
||||
|
||||
toolsToSend = [
|
||||
...methodsWithFullData.slice(0, methodLimit),
|
||||
...softwareWithFullData.slice(0, softwareLimit)
|
||||
];
|
||||
|
||||
const remainingCapacity = maxTools - toolsToSend.length;
|
||||
if (remainingCapacity > 0) {
|
||||
if (methodsWithFullData.length > methodLimit) {
|
||||
toolsToSend.push(...methodsWithFullData.slice(methodLimit, methodLimit + remainingCapacity));
|
||||
} else if (softwareWithFullData.length > softwareLimit) {
|
||||
toolsToSend.push(...softwareWithFullData.slice(softwareLimit, softwareLimit + remainingCapacity));
|
||||
}
|
||||
}
|
||||
|
||||
conceptsToSend = conceptsWithFullData.slice(0, maxConcepts);
|
||||
const remainingCapacity = maxTools - toolsToSend.length;
|
||||
if (remainingCapacity > 0) {
|
||||
// Fill remainder from whichever bucket still has items
|
||||
const extraMethods = methodsWithFullData.slice(methodLimit, methodLimit + remainingCapacity);
|
||||
const extraSoftware = softwareWithFullData.slice(softwareLimit, softwareLimit + (remainingCapacity - extraMethods.length));
|
||||
toolsToSend.push(...extraMethods, ...extraSoftware);
|
||||
}
|
||||
|
||||
const basePrompt = getPrompt('toolSelection', mode, userQuery, selectionMethod, this.config.maxSelectedItems);
|
||||
const conceptsToSend = conceptsWithFullData.slice(0, maxConcepts);
|
||||
|
||||
const basePrompt = getPrompt('toolSelection', mode, userQuery, this.config.maxSelectedItems);
|
||||
const prompt = getPrompt('toolSelectionWithData', basePrompt, toolsToSend, conceptsToSend);
|
||||
|
||||
aiService.validatePromptLength(prompt);
|
||||
@ -246,7 +215,7 @@ class ToolSelector {
|
||||
);
|
||||
|
||||
try {
|
||||
const response = await aiService.callAI(prompt, { maxTokens: 2500 });
|
||||
const response = await aiService.callAI(prompt, { maxTokens: 32768 });
|
||||
const result = JSONParser.safeParseJSON(response.content, null);
|
||||
|
||||
if (!result || !Array.isArray(result.selectedTools) || !Array.isArray(result.selectedConcepts)) {
|
||||
@ -275,21 +244,19 @@ class ToolSelector {
|
||||
|
||||
console.log('[TOOL-SELECTOR] AI selected:', selectedMethods.length, 'methods,', selectedSoftware.length, 'software,', selectedConcepts.length, 'concepts');
|
||||
|
||||
const confidence = confidenceScoring.calculateSelectionConfidence(result, candidateTools.length + candidateConcepts.length);
|
||||
|
||||
return {
|
||||
selectedTools,
|
||||
selectedConcepts,
|
||||
selectionMethod,
|
||||
confidence
|
||||
};
|
||||
const confidence = confidenceScoring.calculateSelectionConfidence(
|
||||
result,
|
||||
candidateTools.length + candidateConcepts.length
|
||||
);
|
||||
|
||||
return { selectedTools, selectedConcepts, confidence };
|
||||
} catch (error) {
|
||||
console.error('[TOOL-SELECTOR] AI selection failed:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
async selectToolsForPhase(
|
||||
userQuery: string,
|
||||
phase: any,
|
||||
|
Loading…
x
Reference in New Issue
Block a user