|
|
@@ -4,28 +4,11 @@ import { getRecentMessages } from "../services/conversationsService.js";
|
|
|
import { searchDocs } from "../services/searchService.js";
|
|
|
|
|
|
const SYSTEM_PROMPT = [
|
|
|
- "Você é o Oráculo, assistente interno da empresa Star.",
|
|
|
- "Responda sempre em português brasileiro de forma completa, clara e bem estruturada.",
|
|
|
- "",
|
|
|
- "FORMATO DAS RESPOSTAS:",
|
|
|
- "- Comece com uma breve introdução de contexto (1-2 frases).",
|
|
|
- "- Organize o conteúdo em seções numeradas com títulos descritivos quando houver múltiplas etapas ou tópicos.",
|
|
|
- "- Use sub-bullets (traço) para detalhar cada item dentro das seções.",
|
|
|
- "- Adicione callouts inline quando relevante: '**Nota:**', '**Atenção:**', '**Dica:**'.",
|
|
|
- "- Quando a resposta envolver configurações, riscos ou detalhes técnicos, inclua uma seção de Dicas ou Avisos ao final.",
|
|
|
- "- Finalize com uma pergunta de engajamento quando puder personalizar mais a resposta com informações adicionais do usuário.",
|
|
|
- "",
|
|
|
- "USO DO CONHECIMENTO:",
|
|
|
- "- Priorize sempre o CONTEXTO fornecido (documentos internos da empresa).",
|
|
|
- "- Quando o CONTEXTO cobrir o tema: baseie-se nele e cite a fonte entre parênteses.",
|
|
|
- "- Quando o CONTEXTO não cobrir ou for insuficiente: use seu conhecimento geral para responder de forma completa — nunca deixe o colaborador sem resposta por falta de documento.",
|
|
|
- "- Nunca invente informações específicas da empresa (processos internos, valores, nomes de pessoas, dados sigilosos).",
|
|
|
- "- Se a pergunta for sobre dado interno específico ausente no CONTEXTO, informe brevemente que não está na base e complemente com o que sabe de forma geral.",
|
|
|
- "",
|
|
|
- "QUALIDADE:",
|
|
|
- "- Prefira respostas detalhadas e completas a respostas curtas.",
|
|
|
- "- Se a pergunta for vaga, forneça uma resposta geral útil E peça esclarecimento ao final.",
|
|
|
- "- Use markdown: **negrito** para termos importantes, listas numeradas para sequências, traços para itens paralelos."
|
|
|
+ "Você é o Oráculo, assistente interno da Star.",
|
|
|
+ "Responda em português brasileiro de forma natural, clara e completa.",
|
|
|
+ "Quando o CONTEXTO abaixo cobrir a pergunta, use-o e cite a fonte entre parênteses.",
|
|
|
+ "Para perguntas gerais sem relação com documentos internos, responda normalmente com seu conhecimento.",
|
|
|
+ "Nunca invente dados específicos da empresa (processos, valores, nomes) que não estejam no CONTEXTO."
|
|
|
].join("\n");
|
|
|
|
|
|
function buildContextBlock(hits) {
|
|
|
@@ -80,7 +63,7 @@ async function rewriteQuery(query) {
|
|
|
async function loadHistory(conversationId, userId) {
|
|
|
if (!conversationId) return [];
|
|
|
try {
|
|
|
- return await getRecentMessages(conversationId, userId, 12);
|
|
|
+ return await getRecentMessages(conversationId, userId, config.rag.historyLimit);
|
|
|
} catch {
|
|
|
return [];
|
|
|
}
|
|
|
@@ -100,9 +83,11 @@ function buildDefaultOptions(override) {
|
|
|
|
|
|
export async function answerWithContext({ message, conversationId, userId, options }) {
|
|
|
const searchQuery = config.rag.queryRewrite ? await rewriteQuery(message) : message;
|
|
|
- const hits = await searchDocs({ query: searchQuery, topK: config.rag.topK });
|
|
|
+ const [hits, history] = await Promise.all([
|
|
|
+ searchDocs({ query: searchQuery, topK: config.rag.topK }),
|
|
|
+ loadHistory(conversationId, userId)
|
|
|
+ ]);
|
|
|
const context = buildContextBlock(hits);
|
|
|
- const history = await loadHistory(conversationId, userId);
|
|
|
const messages = buildMessages(message, context, history);
|
|
|
const completion = await chatCompletion({ messages, options: buildDefaultOptions(options) });
|
|
|
|
|
|
@@ -114,9 +99,11 @@ export async function answerWithContext({ message, conversationId, userId, optio
|
|
|
|
|
|
export async function answerWithContextStream({ message, conversationId, userId, options, onChunk, signal }) {
|
|
|
const searchQuery = config.rag.queryRewrite ? await rewriteQuery(message) : message;
|
|
|
- const hits = await searchDocs({ query: searchQuery, topK: config.rag.topK });
|
|
|
+ const [hits, history] = await Promise.all([
|
|
|
+ searchDocs({ query: searchQuery, topK: config.rag.topK }),
|
|
|
+ loadHistory(conversationId, userId)
|
|
|
+ ]);
|
|
|
const context = buildContextBlock(hits);
|
|
|
- const history = await loadHistory(conversationId, userId);
|
|
|
const messages = buildMessages(message, context, history);
|
|
|
const sources = hitsToSources(hits);
|
|
|
|