feat(web-search): implement two-phase smart search pipeline
Add metadata-first search approach followed by targeted scraping of top URLs. Includes: - New `smartSearchRag` method in web search service - Metadata-only search endpoint in Tauri backend - Bulk URL scraping capability - Payload content override in chat messages
This commit is contained in:
1 parent
5c1a859925
commit
c06e7ae5cf
6 files changed
+380
-10
No files matched your search
+17
-4
@@ -202,6 +202,9 @@ export function useChat() {
|
||||
systemPrompt?: string,
|
||||
options?: {
|
||||
onBeforeModelRequest?: (pendingMessages: Message[]) => Promise<void>;
|
||||
// Quando presente, substitui SOMENTE o conteúdo da última mensagem do usuário
|
||||
// no payload enviado ao LLM, mantendo a UI com o conteúdo original.
|
||||
payloadContentOverride?: string;
|
||||
}
|
||||
) => {
|
||||
setIsLoading(true);
|
||||
@@ -257,12 +260,22 @@ export function useChat() {
|
||||
selectedMessages.push(lastUserMessage);
|
||||
totalTokens += estimateTokens(lastUserMessage.content);
|
||||
|
||||
const apiMessages = (systemPrompt
|
||||
// Constrói mensagens para payload, aplicando override apenas à última mensagem do usuário
|
||||
const baseMessages = systemPrompt
|
||||
? [{ role: 'system', content: systemPrompt }, ...selectedMessages]
|
||||
: selectedMessages).map(m => ({
|
||||
: selectedMessages;
|
||||
|
||||
const apiMessages = baseMessages.map((m, idx) => {
|
||||
// Detecta última mensagem do usuário
|
||||
const isLastUser = m.role === 'user' && idx === baseMessages.length - 1;
|
||||
const payloadContent = isLastUser && options?.payloadContentOverride
|
||||
? options.payloadContentOverride
|
||||
: m.content;
|
||||
return {
|
||||
role: m.role,
|
||||
content: m.content // Send only content, not metadata (unless we want to inject it back)
|
||||
}));
|
||||
content: payloadContent,
|
||||
};
|
||||
});
|
||||
|
||||
// [DEBUG INJECTION START]
|
||||
const systemMsg = apiMessages.find(m => m.role === 'system');
|
||||
|
||||
@@ -119,6 +119,62 @@ export function useWebSearch() {
|
||||
}
|
||||
}, []);
|
||||
|
||||
/**
|
||||
* Pipeline em duas etapas: metadados → scraping das top URLs
|
||||
*/
|
||||
const smartSearchRag = useCallback(async (query: string, limit: number = 3): Promise<ScrapedContent[]> => {
|
||||
if (!query || !query.trim()) {
|
||||
return [];
|
||||
}
|
||||
|
||||
setState(prev => ({
|
||||
...prev,
|
||||
status: 'searching',
|
||||
currentQuery: query,
|
||||
error: null,
|
||||
scrapedSources: [],
|
||||
}));
|
||||
|
||||
try {
|
||||
const settings = useSettingsStore.getState();
|
||||
const searchConfig: SearchConfig = {
|
||||
maxConcurrentTabs: settings.webSearch.maxConcurrentTabs,
|
||||
totalSourcesLimit: settings.webSearch.totalSourcesLimit,
|
||||
categories: settings.webSearch.categories,
|
||||
userCustomSites: settings.webSearch.userCustomSites,
|
||||
excludedDomains: settings.webSearch.excludedDomains,
|
||||
};
|
||||
|
||||
// Etapa 1: metadados
|
||||
setState(prev => ({ ...prev, status: 'searching' }));
|
||||
const { metadata, contents } = await webSearchService.smartSearchRag(query, limit, searchConfig);
|
||||
|
||||
// Etapa 2: scraping
|
||||
setState(prev => ({ ...prev, status: 'scraping' }));
|
||||
|
||||
// [DEBUG] metadados coletados
|
||||
console.log('🔎 Metadados coletados:', metadata);
|
||||
|
||||
setState(prev => ({
|
||||
...prev,
|
||||
status: 'completed',
|
||||
scrapedSources: contents,
|
||||
error: null,
|
||||
}));
|
||||
|
||||
return contents;
|
||||
} catch (error) {
|
||||
const errorMessage = error instanceof Error ? error.message : 'Erro desconhecido no smartSearchRag';
|
||||
setState(prev => ({
|
||||
...prev,
|
||||
status: 'error',
|
||||
error: errorMessage,
|
||||
scrapedSources: [],
|
||||
}));
|
||||
throw error;
|
||||
}
|
||||
}, []);
|
||||
|
||||
/**
|
||||
* Extrai conteúdo de uma URL
|
||||
*/
|
||||
@@ -169,6 +225,7 @@ export function useWebSearch() {
|
||||
...state,
|
||||
setEnabled,
|
||||
search,
|
||||
smartSearchRag,
|
||||
extractUrl,
|
||||
reset,
|
||||
clearCache,
|
||||
|
||||
Reference in new issue
Block a user