Bläddra i källkod

ajuste para as respostas do chat

leonardo 2 månader sedan
förälder
incheckning
d183f19e8e
5 ändrade filer med 20 tillägg och 13 borttagningar
  1. 3 3
      .env.example
  2. 3 3
      docs/setup.md
  3. 10 1
      src/chat/chatChain.js
  4. 3 3
      src/config/index.js
  5. 1 3
      src/services/searchService.js

+ 3 - 3
.env.example

@@ -31,7 +31,7 @@ OLLAMA_CHAT_MODEL=llama3
 OLLAMA_VISION_MODEL=llava
 
 # RAG (valores padrão se não definidos)
-RAG_TOP_K=6
+RAG_TOP_K=8
 RAG_CHUNK_SIZE=900
 RAG_CHUNK_OVERLAP=150
 
@@ -39,11 +39,11 @@ RAG_CHUNK_OVERLAP=150
 RATE_LIMIT_PER_MINUTE=0
 
 # Ajuste fino das respostas do LLM
-LLM_TEMPERATURE=0.7
+LLM_TEMPERATURE=0.2
 LLM_TOP_P=0.9
 LLM_NUM_PREDICT=2048
 LLM_REPEAT_PENALTY=1.1
 
 # RAG avançado
 RAG_QUERY_REWRITE=false
-RAG_MIN_SCORE=0.45
+RAG_MIN_SCORE=0.40

+ 3 - 3
docs/setup.md

@@ -64,8 +64,8 @@ Crie o arquivo `backend/.env` com base nas variáveis abaixo:
 |---|---|---|
 | `RAG_QUERY_REWRITE` | Reescrever query antes da busca | `true` |
 | `RAG_HISTORY_TOKEN_BUDGET` | Tokens de histórico enviados ao LLM | `1500` |
-| `RAG_TOP_K` | Número de chunks recuperados (default `6`) | `8` |
-| `RAG_MIN_SCORE` | Score mínimo de similaridade | `0.45` |
+| `RAG_TOP_K` | Número de chunks recuperados (default `8`) | `8` |
+| `RAG_MIN_SCORE` | Score mínimo de similaridade (default `0.40`) | `0.40` |
 | `RAG_CHUNK_SIZE` | Tamanho de cada chunk (caracteres) | `900` |
 | `RAG_CHUNK_OVERLAP` | Sobreposição entre chunks | `150` |
 
@@ -73,7 +73,7 @@ Crie o arquivo `backend/.env` com base nas variáveis abaixo:
 
 | Variável | Descrição | Exemplo |
 |---|---|---|
-| `LLM_TEMPERATURE` | Criatividade das respostas (0–1) | `0.7` |
+| `LLM_TEMPERATURE` | Criatividade das respostas (0–1); baixo = mais fiel à fonte (default `0.2`) | `0.2` |
 | `LLM_TOP_P` | Nucleus sampling | `0.9` |
 | `LLM_NUM_PREDICT` | Máximo de tokens gerados | `2048` |
 | `LLM_REPEAT_PENALTY` | Penalidade de repetição | `1.1` |

+ 10 - 1
src/chat/chatChain.js

@@ -9,6 +9,7 @@ const SYSTEM_PROMPT = [
   "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) {
@@ -23,10 +24,18 @@ function buildContextBlock(hits) {
   return lines.join("\n").trim();
 }
 
+const EMPTY_CONTEXT_GUARD = [
+  "Nenhum documento interno foi encontrado para esta pergunta.",
+  "Se ela for sobre processos, valores, nomes ou políticas da Star, responda que não há informação na base interna e não invente.",
+  "Perguntas gerais podem ser respondidas normalmente."
+].join("\n");
+
 function buildMessages(message, context, history = []) {
   return [
     { role: "system", content: SYSTEM_PROMPT },
-    ...(context ? [{ role: "system", content: `CONTEXTO:\n${context}` }] : []),
+    ...(context
+      ? [{ role: "system", content: `CONTEXTO:\n${context}` }]
+      : [{ role: "system", content: EMPTY_CONTEXT_GUARD }]),
     ...history.map((m) => ({ role: m.Role.toLowerCase(), content: m.Content })),
     { role: "user", content: message }
   ];

+ 3 - 3
src/config/index.js

@@ -35,15 +35,15 @@ export const config = {
     visionModel: process.env.OLLAMA_VISION_MODEL ?? "llava:latest"
   },
   rag: {
-    topK: Number(process.env.RAG_TOP_K ?? 4),
-    minScore: Number(process.env.RAG_MIN_SCORE ?? 0.55),
+    topK: Number(process.env.RAG_TOP_K ?? 8),
+    minScore: Number(process.env.RAG_MIN_SCORE ?? 0.40),
     chunkSize: Number(process.env.RAG_CHUNK_SIZE ?? 900),
     chunkOverlap: Number(process.env.RAG_CHUNK_OVERLAP ?? 150),
     queryRewrite: process.env.RAG_QUERY_REWRITE === "true",
     historyLimit: Number(process.env.RAG_HISTORY_LIMIT ?? 6)
   },
   llm: {
-    temperature: Number(process.env.LLM_TEMPERATURE ?? 0.7),
+    temperature: Number(process.env.LLM_TEMPERATURE ?? 0.2),
     topP: Number(process.env.LLM_TOP_P ?? 0.9),
     numPredict: Number(process.env.LLM_NUM_PREDICT ?? 2048),
     repeatPenalty: Number(process.env.LLM_REPEAT_PENALTY ?? 1.1)

+ 1 - 3
src/services/searchService.js

@@ -1,7 +1,6 @@
 import { config } from "../config/index.js";
 import { embedTexts } from "./ollamaClient.js";
 import { qdrant } from "./qdrantClient.js";
-import { isRefusal } from "../utils/isRefusal.js";
 
 export async function searchDocs({ query, topK }) {
   const collectionName = config.qdrant.collection;
@@ -23,6 +22,5 @@ export async function searchDocs({ query, topK }) {
       source: r.payload?.source ?? null,
       chunkIndex: r.payload?.chunkIndex ?? null,
       metadata: r.payload?.metadata ?? null
-    }))
-    .filter((h) => !isRefusal(h.text));
+    }));
 }