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
 OLLAMA_VISION_MODEL=llava
 
 
 # RAG (valores padrão se não definidos)
 # RAG (valores padrão se não definidos)
-RAG_TOP_K=6
+RAG_TOP_K=8
 RAG_CHUNK_SIZE=900
 RAG_CHUNK_SIZE=900
 RAG_CHUNK_OVERLAP=150
 RAG_CHUNK_OVERLAP=150
 
 
@@ -39,11 +39,11 @@ RAG_CHUNK_OVERLAP=150
 RATE_LIMIT_PER_MINUTE=0
 RATE_LIMIT_PER_MINUTE=0
 
 
 # Ajuste fino das respostas do LLM
 # Ajuste fino das respostas do LLM
-LLM_TEMPERATURE=0.7
+LLM_TEMPERATURE=0.2
 LLM_TOP_P=0.9
 LLM_TOP_P=0.9
 LLM_NUM_PREDICT=2048
 LLM_NUM_PREDICT=2048
 LLM_REPEAT_PENALTY=1.1
 LLM_REPEAT_PENALTY=1.1
 
 
 # RAG avançado
 # RAG avançado
 RAG_QUERY_REWRITE=false
 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_QUERY_REWRITE` | Reescrever query antes da busca | `true` |
 | `RAG_HISTORY_TOKEN_BUDGET` | Tokens de histórico enviados ao LLM | `1500` |
 | `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_SIZE` | Tamanho de cada chunk (caracteres) | `900` |
 | `RAG_CHUNK_OVERLAP` | Sobreposição entre chunks | `150` |
 | `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 |
 | 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_TOP_P` | Nucleus sampling | `0.9` |
 | `LLM_NUM_PREDICT` | Máximo de tokens gerados | `2048` |
 | `LLM_NUM_PREDICT` | Máximo de tokens gerados | `2048` |
 | `LLM_REPEAT_PENALTY` | Penalidade de repetição | `1.1` |
 | `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.",
   "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.",
   "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."
   "Nunca invente dados específicos da empresa (processos, valores, nomes) que não estejam no CONTEXTO."
+  
 ].join("\n");
 ].join("\n");
 
 
 function buildContextBlock(hits) {
 function buildContextBlock(hits) {
@@ -23,10 +24,18 @@ function buildContextBlock(hits) {
   return lines.join("\n").trim();
   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 = []) {
 function buildMessages(message, context, history = []) {
   return [
   return [
     { role: "system", content: SYSTEM_PROMPT },
     { 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 })),
     ...history.map((m) => ({ role: m.Role.toLowerCase(), content: m.Content })),
     { role: "user", content: message }
     { 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"
     visionModel: process.env.OLLAMA_VISION_MODEL ?? "llava:latest"
   },
   },
   rag: {
   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),
     chunkSize: Number(process.env.RAG_CHUNK_SIZE ?? 900),
     chunkOverlap: Number(process.env.RAG_CHUNK_OVERLAP ?? 150),
     chunkOverlap: Number(process.env.RAG_CHUNK_OVERLAP ?? 150),
     queryRewrite: process.env.RAG_QUERY_REWRITE === "true",
     queryRewrite: process.env.RAG_QUERY_REWRITE === "true",
     historyLimit: Number(process.env.RAG_HISTORY_LIMIT ?? 6)
     historyLimit: Number(process.env.RAG_HISTORY_LIMIT ?? 6)
   },
   },
   llm: {
   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),
     topP: Number(process.env.LLM_TOP_P ?? 0.9),
     numPredict: Number(process.env.LLM_NUM_PREDICT ?? 2048),
     numPredict: Number(process.env.LLM_NUM_PREDICT ?? 2048),
     repeatPenalty: Number(process.env.LLM_REPEAT_PENALTY ?? 1.1)
     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 { config } from "../config/index.js";
 import { embedTexts } from "./ollamaClient.js";
 import { embedTexts } from "./ollamaClient.js";
 import { qdrant } from "./qdrantClient.js";
 import { qdrant } from "./qdrantClient.js";
-import { isRefusal } from "../utils/isRefusal.js";
 
 
 export async function searchDocs({ query, topK }) {
 export async function searchDocs({ query, topK }) {
   const collectionName = config.qdrant.collection;
   const collectionName = config.qdrant.collection;
@@ -23,6 +22,5 @@ export async function searchDocs({ query, topK }) {
       source: r.payload?.source ?? null,
       source: r.payload?.source ?? null,
       chunkIndex: r.payload?.chunkIndex ?? null,
       chunkIndex: r.payload?.chunkIndex ?? null,
       metadata: r.payload?.metadata ?? null
       metadata: r.payload?.metadata ?? null
-    }))
-    .filter((h) => !isRefusal(h.text));
+    }));
 }
 }