Origem: D:/Documents/Github/OllaHub Arquivos omitidos (segredos, bancos de dados, logs, >50 MB): 0
This commit is contained in:
1 parent
a7cbd1a3b4
commit
861af0bb9f
217 files changed
+39421
-1340
No files matched your search
+50
-54
@@ -109,9 +109,9 @@ Query expandida:`;
|
||||
num_predict: 100,
|
||||
},
|
||||
}))
|
||||
.replace(/^["']|["']$/g, '')
|
||||
.replace(/\.$/, '')
|
||||
.trim();
|
||||
.replace(/^["']|["']$/g, '')
|
||||
.replace(/\.$/, '')
|
||||
.trim();
|
||||
|
||||
const sanitized = expanded
|
||||
.replace(/<think>[\s\S]*?<\/think>/gi, '')
|
||||
@@ -143,41 +143,41 @@ export function calculateRelevanceScoreForFallback(
|
||||
): number {
|
||||
const queryLower = query.toLowerCase();
|
||||
const queryWords = queryLower.split(/\s+/).filter(w => w.length > 2);
|
||||
|
||||
|
||||
// Extrair texto para análise
|
||||
const title = (result.title || '').toLowerCase();
|
||||
const content = (result.markdown || '').toLowerCase();
|
||||
const combinedText = `${title} ${content}`;
|
||||
|
||||
|
||||
// Contar matches de palavras-chave
|
||||
let matches = 0;
|
||||
const totalWords = queryWords.length;
|
||||
|
||||
|
||||
for (const word of queryWords) {
|
||||
if (combinedText.includes(word)) {
|
||||
matches++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Score base: proporção de palavras encontradas
|
||||
let score = matches / totalWords;
|
||||
|
||||
|
||||
// Bônus: título tem mais peso
|
||||
const titleMatches = queryWords.filter(w => title.includes(w)).length;
|
||||
if (titleMatches > 0) {
|
||||
score += (titleMatches / totalWords) * 0.3; // 30% de bônus
|
||||
}
|
||||
|
||||
|
||||
// Bônus: conteúdo não vazio
|
||||
if (content.length > 100) {
|
||||
score += 0.1;
|
||||
}
|
||||
|
||||
|
||||
// Penalidade: conteúdo muito curto
|
||||
if (content.length < 50) {
|
||||
score *= 0.5;
|
||||
}
|
||||
|
||||
|
||||
// Normalizar para 0-1
|
||||
return Math.min(1, Math.max(0, score));
|
||||
}
|
||||
@@ -193,16 +193,16 @@ export function areResultsRelevant(
|
||||
if (results.length === 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// Calcular scores de relevância
|
||||
const scores = results.map(r => calculateRelevanceScoreForFallback(r, query));
|
||||
|
||||
|
||||
// Verificar se pelo menos um resultado tem score suficiente
|
||||
const maxScore = Math.max(...scores);
|
||||
const avgScore = scores.reduce((a, b) => a + b, 0) / scores.length;
|
||||
|
||||
|
||||
chatLog.info(`Relevance scores - Max: ${maxScore.toFixed(2)}, Avg: ${avgScore.toFixed(2)}, Min required: ${minScore}`);
|
||||
|
||||
|
||||
// Considerar relevante se:
|
||||
// 1. Pelo menos um resultado tem score alto, OU
|
||||
// 2. Média dos scores é razoável
|
||||
@@ -283,15 +283,15 @@ export async function executeProgressiveSearch(
|
||||
const seenUrls = new Set<string>();
|
||||
const queryStartTime = Date.now();
|
||||
const maxQueryTimeout = finalConfig.maxTimeoutPerQuery || TIMEOUT_CONFIG.maxTimeoutPerQuery;
|
||||
|
||||
|
||||
chatLog.info(`\n=== PROGRESSIVE SEARCH START ===`);
|
||||
chatLog.info(`Original Query: "${originalQuery}"`);
|
||||
chatLog.info(`Config: ${JSON.stringify({ ...finalConfig, context: finalConfig.context ? 'present' : 'none', enrichedQueries: finalConfig.enrichedQueries ? 'present' : 'none' })}`);
|
||||
chatLog.info(`Timeout config: initial=${finalConfig.initialTimeout}ms, max per query=${maxQueryTimeout}ms, max per round=${finalConfig.maxTimeoutPerRound}ms`);
|
||||
|
||||
|
||||
// Se usar semantic search, criar rounds baseados em estratégias
|
||||
let rounds: Array<{ round: number; config: RoundConfig }> = [];
|
||||
|
||||
|
||||
if (finalConfig.useSemanticSearch && finalConfig.enrichedQueries) {
|
||||
const semanticRounds = createSemanticRounds(finalConfig.enrichedQueries, originalQuery);
|
||||
rounds = semanticRounds.map((roundConfig, idx) => ({
|
||||
@@ -312,10 +312,10 @@ export async function executeProgressiveSearch(
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Limitar número de rounds
|
||||
rounds = rounds.slice(0, finalConfig.maxRounds);
|
||||
|
||||
|
||||
for (const { round, config: roundConfig } of rounds) {
|
||||
// Verificar timeout total da query
|
||||
const elapsedTime = Date.now() - queryStartTime;
|
||||
@@ -323,63 +323,59 @@ export async function executeProgressiveSearch(
|
||||
chatLog.warn(`[Round ${round}] Timeout total da query atingido (${elapsedTime}ms >= ${maxQueryTimeout}ms), parando busca`);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// Calcular timeout adaptativo para este round
|
||||
const roundTimeout = calculateAdaptiveTimeout(round, finalConfig.initialTimeout || TIMEOUT_CONFIG.initialTimeout);
|
||||
const maxRoundTimeout = finalConfig.maxTimeoutPerRound || TIMEOUT_CONFIG.maxTimeoutPerRound;
|
||||
const actualRoundTimeout = Math.min(roundTimeout, maxRoundTimeout);
|
||||
|
||||
|
||||
chatLog.info(`\n--- Round ${round}/${rounds.length} [${roundConfig.strategy}] ---`);
|
||||
chatLog.info(`Round timeout: ${actualRoundTimeout}ms (adaptativo: ${roundTimeout}ms, máximo: ${maxRoundTimeout}ms)`);
|
||||
|
||||
|
||||
const roundStartTime = Date.now();
|
||||
const roundResults: ScrapedContent[] = [];
|
||||
const roundQueries: string[] = [];
|
||||
|
||||
|
||||
// Executar todas as queries do round em paralelo com timeout por round
|
||||
const queryPromises = roundConfig.queries.map(async (query) => {
|
||||
// Expandir query se necessário (modo tradicional)
|
||||
const finalQuery = finalConfig.enableQueryExpansion && !finalConfig.useSemanticSearch
|
||||
? await expandQuery(query, model, round)
|
||||
: query;
|
||||
|
||||
|
||||
try {
|
||||
// Passar round para searchFn para timeout adaptativo
|
||||
const results = await searchFn(finalQuery, finalConfig.maxResultsPerRound, round);
|
||||
return { query: finalQuery, results };
|
||||
<<<<<<< HEAD
|
||||
} catch (err) {
|
||||
chatLog.warn(`[Round ${round}] Query "${finalQuery}" failed: ${err instanceof Error ? err.message : String(err)}`);
|
||||
=======
|
||||
} catch (error) {
|
||||
chatLog.warn(`[Round ${round}] Query "${finalQuery}" failed: ${error instanceof Error ? error.message : String(error)}`);
|
||||
>>>>>>> 593efd42e091a845dea82ee6646e027bce1e18c5
|
||||
|
||||
return { query: finalQuery, results: [] };
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// Adicionar timeout total para o round
|
||||
const roundPromise = Promise.all(queryPromises);
|
||||
type QueryResult = { query: string; results: ScrapedContent[] };
|
||||
const timeoutPromise = new Promise<QueryResult[]>((_, reject) => {
|
||||
setTimeout(() => reject(new Error(`Round ${round} timeout após ${actualRoundTimeout}ms`)), actualRoundTimeout);
|
||||
});
|
||||
|
||||
|
||||
let queryResults: QueryResult[];
|
||||
try {
|
||||
queryResults = await Promise.race([roundPromise, timeoutPromise]);
|
||||
} catch (_err) {
|
||||
chatLog.warn(`[Round ${round}] Timeout do round após ${actualRoundTimeout}ms, usando resultados parciais`);
|
||||
// Tentar obter resultados parciais das promises que já completaram
|
||||
queryResults = await Promise.allSettled(queryPromises).then(results =>
|
||||
queryResults = await Promise.allSettled(queryPromises).then(results =>
|
||||
results.map(r => r.status === 'fulfilled' ? r.value : { query: '', results: [] })
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// Agregar resultados de todas as queries do round
|
||||
for (const { query, results } of queryResults) {
|
||||
roundQueries.push(query);
|
||||
|
||||
|
||||
// Filtrar duplicatas
|
||||
const uniqueResults = results.filter(r => {
|
||||
if (seenUrls.has(r.url)) {
|
||||
@@ -388,14 +384,14 @@ export async function executeProgressiveSearch(
|
||||
seenUrls.add(r.url);
|
||||
return true;
|
||||
});
|
||||
|
||||
|
||||
roundResults.push(...uniqueResults);
|
||||
}
|
||||
|
||||
|
||||
const roundDuration = Date.now() - roundStartTime;
|
||||
|
||||
|
||||
chatLog.info(`[Round ${round}] Executed ${roundQueries.length} queries, found ${roundResults.length} unique results in ${roundDuration}ms`);
|
||||
|
||||
|
||||
// Log detalhado se houver resultados
|
||||
if (roundResults.length > 0) {
|
||||
roundResults.slice(0, 3).forEach((result, idx) => {
|
||||
@@ -405,7 +401,7 @@ export async function executeProgressiveSearch(
|
||||
chatLog.info(` ... and ${roundResults.length - 3} more results`);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Calcular relevância usando contexto se disponível
|
||||
let semanticSimilarity: ((ctx: QueryContext, text: string) => number) | null = null;
|
||||
if (finalConfig.context) {
|
||||
@@ -414,13 +410,13 @@ export async function executeProgressiveSearch(
|
||||
}
|
||||
const relevanceScore = roundResults.length > 0
|
||||
? roundResults.reduce((sum, r) => {
|
||||
if (semanticSimilarity && finalConfig.context) {
|
||||
return sum + semanticSimilarity(finalConfig.context, r.markdown || r.title);
|
||||
}
|
||||
return sum + calculateRelevanceScoreForFallback(r, originalQuery);
|
||||
}, 0) / roundResults.length
|
||||
if (semanticSimilarity && finalConfig.context) {
|
||||
return sum + semanticSimilarity(finalConfig.context, r.markdown || r.title);
|
||||
}
|
||||
return sum + calculateRelevanceScoreForFallback(r, originalQuery);
|
||||
}, 0) / roundResults.length
|
||||
: 0;
|
||||
|
||||
|
||||
// Registrar tentativa
|
||||
const attempt: FallbackAttempt = {
|
||||
round,
|
||||
@@ -433,19 +429,19 @@ export async function executeProgressiveSearch(
|
||||
duration: roundDuration,
|
||||
};
|
||||
attempts.push(attempt);
|
||||
|
||||
|
||||
allResults.push(...roundResults);
|
||||
totalResultsAnalyzed += roundResults.length;
|
||||
|
||||
|
||||
// Verificar early exit: resultados suficientes com alta relevância
|
||||
const minResultsForEarlyExit = finalConfig.minResultsForEarlyExit || 5;
|
||||
const minRelevanceForEarlyExit = finalConfig.minRelevanceForEarlyExit || 0.7;
|
||||
|
||||
|
||||
if (roundResults.length >= minResultsForEarlyExit && relevanceScore >= minRelevanceForEarlyExit) {
|
||||
chatLog.info(`[Round ${round}] 🎯 Early exit: resultados suficientes encontrados!`);
|
||||
chatLog.info(`[Round ${round}] Results: ${roundResults.length} (mínimo: ${minResultsForEarlyExit}), Relevance: ${relevanceScore.toFixed(2)} (mínimo: ${minRelevanceForEarlyExit})`);
|
||||
chatLog.info(`[Round ${round}] Total results: ${allResults.length}, Total analyzed: ${totalResultsAnalyzed}`);
|
||||
|
||||
|
||||
return {
|
||||
success: true,
|
||||
knowledgeBaseContext: '', // Será preenchido pelo caller
|
||||
@@ -456,23 +452,23 @@ export async function executeProgressiveSearch(
|
||||
finalQuery: roundQueries.join(' | '),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
// Verificar se atingiu limite de resultados
|
||||
if (totalResultsAnalyzed >= finalConfig.maxTotalResults) {
|
||||
chatLog.warn(`[Round ${round}] ⚠️ Reached max total results limit (${finalConfig.maxTotalResults})`);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// Se não encontrou resultados relevantes, continuar para próxima rodada
|
||||
chatLog.warn(`[Round ${round}] ⚠️ Did not find relevant results (min score: ${finalConfig.minRelevanceScore}), continuing...`);
|
||||
}
|
||||
|
||||
|
||||
// Se chegou aqui, não encontrou resultados relevantes
|
||||
chatLog.warn(`\n⚠️ PROGRESSIVE SEARCH FAILED`);
|
||||
chatLog.warn(`Total rounds: ${attempts.length}`);
|
||||
chatLog.warn(`Total results analyzed: ${totalResultsAnalyzed}`);
|
||||
chatLog.warn(`Using internal knowledge fallback`);
|
||||
|
||||
|
||||
return {
|
||||
success: false,
|
||||
knowledgeBaseContext: '',
|
||||
|
||||
Reference in new issue
Block a user