import { config } from "../src/config/index.js"; import { chatCompletion, chatCompletionStream } from "../src/services/ollamaClient.js"; import { searchDocs } from "../chat/searchChat.js"; function buildContextBlock(hits) { const lines = []; hits.forEach((h, i) => { const header = `# Fonte ${i + 1}${h.source ? ` (${h.source})` : ""}`; lines.push(header); lines.push(h.text); lines.push(""); }); return lines.join("\n").trim(); } function buildMessages(message, context, sessionId) { const system = [ "Você é um assistente de atendimento interno de uma empresa.", "Responda apenas com base no CONTEXTO quando ele estiver disponível.", "Se o CONTEXTO não tiver a informação, diga que não encontrou na base da empresa e sugira o que solicitar ao time responsável.", "Seja direto e em português." ].join("\n"); return [ { role: "system", content: system }, ...(context ? [{ role: "system", content: `CONTEXTO:\n${context}` }] : []), ...(sessionId ? [{ role: "system", content: `session_id:${sessionId}` }] : []), { role: "user", content: message } ]; } function hitsToSources(hits) { return hits.map((h) => ({ id: h.id, source: h.source, score: h.score, chunkIndex: h.chunkIndex, metadata: h.metadata })); } export async function answerWithContext({ message, sessionId }) { const hits = await searchDocs({ query: message, topK: config.rag.topK }); const context = buildContextBlock(hits); const messages = buildMessages(message, context, sessionId); const completion = await chatCompletion({ messages }); return { answer: completion.content, sources: hitsToSources(hits) }; } export async function answerWithContextStream({ message, sessionId, onChunk, signal }) { const hits = await searchDocs({ query: message, topK: config.rag.topK }); const context = buildContextBlock(hits); const messages = buildMessages(message, context, sessionId); const sources = hitsToSources(hits); const completion = await chatCompletionStream({ messages, onChunk, signal }); return { answer: completion.content, sources }; }