feat: cota lexical na fusão, recusa off-topic no prompt, docs medidas

Fusão:
- fuse_rankings() extrai a fusão RRF e aplica MAX_KEYWORD_ONLY (padrão 2):
  quantas posições podem ser ocupadas por trechos que só o BM25 achou. O que os
  dois lados confirmam nunca conta contra a cota.
- O controle é por cota de posições, não por piso de nota. Medido: a razão da
  nota BM25 não separa acerto de ruído — para 'como posso perdoar quem me
  feriu?', Deuteronômio 28:27 pontua 1,000 do topo e o correto Lucas 7:47 fica
  em 0,716 (rank 12). Um piso cortaria o certo e manteria o errado.
- Ponderar o RRF também não resolve: com peso 0,5 no BM25 os achados só-lexicais
  caem abaixo do 6º vetorial (0,5/61 < 1/66) e somem, levando junto Jó 3:13 e
  Joel 3:14, os melhores resultados medidos.

Portão off-topic:
- MIN_SIMILARITY não consegue implementar 'sem evidência'. Medido no índice
  completo: 0/6 perguntas off-topic bloqueadas em qualquer limiar de 0,30 a
  0,50 ('bolo de chocolate' bate 0,544 em Lv 7:14; 'cotação do dólar' 0,494).
  A recusa passa a ser instruída no SYSTEM_PROMPT e o limiar fica documentado
  como filtro de ruído.
This commit is contained in:
omp committed 2026-11-02 13:04:14 -03:00
1 parent 8f5e098d8f
commit 816e6be159
9 files changed
+212 -26

No files matched your search

+1
View File
@@ -24,6 +24,7 @@ services:
EMBEDDING_MODEL: ${EMBEDDING_MODEL:-paraphrase-multilingual-MiniLM-L12-v2}
TOP_K: ${TOP_K:-6}
MIN_SIMILARITY: ${MIN_SIMILARITY:-0.35}
MAX_KEYWORD_ONLY: ${MAX_KEYWORD_ONLY:-2}
INDEX_BATCH_SIZE: ${INDEX_BATCH_SIZE:-512}
CONTEXT_WINDOW: ${CONTEXT_WINDOW:-2}
CORS_ORIGINS: ${CORS_ORIGINS:-http://localhost:8080,http://127.0.0.1:8080}