fix(maria): pragul de acoperire la 0,80 si temperatura 0 — doua raspunsuri inventate
Grupul "Maria Test", 2026-09-01, ambele mesaje au primit raspunsuri inventate:
- "am si eu o factura pe luna august cu eroare in spv la trimitere AUTO SULE"
(cosinus 0,768) — mesajul nu spune CE eroare e; Maria a explicat cum se reface
o factura stearsa si a trimis omul sa verifice drepturile pe CIF in SPV.
- captura cu `<Error errorMessage="CUI cumparator incorect"/>` (0,778) — eroarea
nu exista in niciun document; Maria a inventat o procedura cu "ID de descarcare",
Borderou eFactura si retrimitere manuala.
Cauza: `RANK_STRONG_COSINE=0,70` inseamna "cosinusul singur e destul", dar toate
chunk-urile eFactura seamana intre ele — la 0,7x cosinusul nu mai distinge "e in
documente" de "e despre eFactura". Aceeasi greseala ca la codurile Oracle
(ORA-06550 vs ORA-12541, b7d75f0), doar ca fara cod pe care sa te sprijini.
- RANK_STRONG_COSINE 0,70 -> 0,80: peste atat trec doar potrivirile aproape
textuale, restul cad pe dovada lexicala (termenii rari ai intrebarii chiar in
chunk-uri). Ambele mesaje escaladeaza acum la suport.
- LLM_TEMPERATURE=0 la apelul modelului. Fara el llama.cpp foloseste 0,8 —
creativitate exact acolo unde vrem doar ce scrie in context.
- Cele doua cazuri reale sunt adaugate in ops/calibrate-rank.py: 25/25.
Teste: 99 pass.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q4uzvgm7AyJch5WH8QHRhY
This commit is contained in:
@@ -362,6 +362,19 @@ Fuziunea da mereu un clasament, si la o intrebare complet straina. De aceea deci
|
||||
Fractiunea din pasul 3 nu e cosmetica: cu un singur termen gasit, „cum imi resetez
|
||||
parola de la Windows" trecea drept acoperita fiindca „parola" apare in documente.
|
||||
|
||||
`RANK_STRONG_COSINE` a fost 0,70 si a lasat sa treaca doua raspunsuri inventate
|
||||
(2026-09-01, grupul „Maria Test"): „am o factura pe luna august cu eroare in SPV"
|
||||
(0,768 — nu spune ce eroare e) si o captura cu `errorMessage="CUI cumparator
|
||||
incorect"` (0,778 — eroarea nu exista in documente). **Toate chunk-urile eFactura
|
||||
seamana intre ele**, deci pe 0,7x cosinusul nu mai distinge „e in documente" de „e
|
||||
despre eFactura"; e acelasi tip de greseala ca la codurile Oracle de mai sus, doar
|
||||
ca fara cod pe care sa te sprijini. La **0,80** trec doar potrivirile aproape
|
||||
textuale, iar restul cad pe dovada lexicala de la pasul 3. `ops/calibrate-rank.py`:
|
||||
25/25, cu ambele cazuri adaugate la set.
|
||||
|
||||
Modelul primeste `temperature=0` (`LLM_TEMPERATURE`). Fara ea, llama.cpp raspunde
|
||||
cu 0,8 — creativitate exact acolo unde vrem sa se rezume la context.
|
||||
|
||||
Pasul 0 e mai tare decat cosinusul pentru ca **doua erori Oracle diferite se scriu
|
||||
aproape la fel**. O captura cu `ORA-06550 / PLS-00906` a primit cosinus 0,736 pe
|
||||
chunk-ul despre `ORA-12541: TNS no listener` — peste pragul „sigur", deci Maria a
|
||||
|
||||
@@ -61,6 +61,13 @@ CAZURI: list[tuple[str, bool]] = [
|
||||
("ORA-06550: line 1, column 7 PLS-00906 object invalid\nda, ma blocheaza complet", True),
|
||||
("ORA-12154 TNS could not resolve the connect identifier\n"
|
||||
"eram la salvarea unei facturi", True),
|
||||
# 2026-09-01, grup „Maria Test": ambele au primit raspunsuri inventate.
|
||||
# Prima e o reclamatie vaga (nu spune CE eroare), a doua e o eroare eFactura
|
||||
# care nu exista in documente — dar toate chunk-urile eFactura ii seamana.
|
||||
("Buna . Am si eu o factura pe luna august cu eroare in spv la trimitere AUTO SULE", False),
|
||||
("O) Pers. Juridice (798) O Netrimise DI Trimise (fara raspuns) [5 Timis (cu raspuns Erori) (1). "
|
||||
"O Tamise (cu diferente Reg. V2.) (1)\nMesaj raspuns. | Factura cu id incarcare=6638295792 nu po] "
|
||||
"| | <Error errorMessage=\"CUI cumparator incorect\"/>", False),
|
||||
("care e capitala Frantei", False),
|
||||
("cat costa un bilet de avion la Paris", False),
|
||||
("imi da eroare la imprimanta HP LaserJet, nu trage hartia", False),
|
||||
|
||||
@@ -35,7 +35,7 @@ OCR_TIMEOUT_S=60
|
||||
# Peste RANK_STRONG_COSINE raspundem din documente fara alte conditii; sub
|
||||
# RANK_WEAK_COSINE escaladam direct; intre ele, raspundem doar daca termenii rari
|
||||
# din intrebare (coduri de eroare, in general) chiar apar in chunk-urile gasite.
|
||||
RANK_STRONG_COSINE=0.70
|
||||
RANK_STRONG_COSINE=0.80
|
||||
RANK_WEAK_COSINE=0.58
|
||||
RANK_RECALL_N=12
|
||||
# Ce fractiune din termenii distinctivi ai intrebarii trebuie sa apara in
|
||||
@@ -63,6 +63,8 @@ OLLAMA_URL=http://127.0.0.1:11434
|
||||
EMBED_MODEL=nomic-embed-text
|
||||
TOP_K=3
|
||||
MAX_TOKENS=250
|
||||
# 0 = raspunsul e mereu acelasi si sta in context. Nu urca fara motiv.
|
||||
LLM_TEMPERATURE=0
|
||||
POLL_INTERVAL_S=2
|
||||
|
||||
# --- Depozit de documente + sincronizare Google Drive -----------------------
|
||||
|
||||
@@ -39,6 +39,7 @@ DEFAULTS: dict[str, str] = {
|
||||
"EMBED_MODEL": "nomic-embed-text",
|
||||
"TOP_K": "3",
|
||||
"MAX_TOKENS": "250",
|
||||
"LLM_TEMPERATURE": "0",
|
||||
"POLL_INTERVAL_S": "2",
|
||||
"TEST_MODE_SELF_CHAT_ONLY": "true",
|
||||
# Grupuri in care Maria are voie sa raspunda (JID-uri separate prin virgula).
|
||||
@@ -56,7 +57,7 @@ DEFAULTS: dict[str, str] = {
|
||||
"OCR_TIMEOUT_S": "60",
|
||||
# Ordonarea chunk-urilor si pragul de la care se considera ca raspunsul chiar
|
||||
# e in documente (vezi rag/rank.py pentru masuratoarea din spatele valorilor).
|
||||
"RANK_STRONG_COSINE": "0.70",
|
||||
"RANK_STRONG_COSINE": "0.80",
|
||||
"RANK_WEAK_COSINE": "0.58",
|
||||
"RANK_RECALL_N": "12",
|
||||
"RANK_MIN_RARE_RATIO": "0.5",
|
||||
|
||||
@@ -175,6 +175,11 @@ def ask_llm(chunks: list[str], question: str, istoric: list[dict] | None = None)
|
||||
json={
|
||||
"messages": mesaje,
|
||||
"max_tokens": config.get_int("MAX_TOKENS", 250),
|
||||
# Fara asta llama.cpp raspunde cu temperatura lui implicita (0,8).
|
||||
# Aici nu vrem creativitate: raspunsul trebuie sa fie ce scrie in
|
||||
# context, la fel de fiecare data. Vezi raspunsurile inventate din
|
||||
# 2026-09-01 (grup „Maria Test").
|
||||
"temperature": float(config.get("LLM_TEMPERATURE", "0")),
|
||||
},
|
||||
timeout=60,
|
||||
)
|
||||
|
||||
@@ -39,8 +39,17 @@ RRF_K = 60 # constanta standard din Reciprocal Rank Fusion
|
||||
|
||||
|
||||
def strong_cosine() -> float:
|
||||
"""Peste atat, singur cosinusul e de ajuns (RANK_STRONG_COSINE)."""
|
||||
return float(config.get("RANK_STRONG_COSINE", "0.70"))
|
||||
"""Peste atat, singur cosinusul e de ajuns (RANK_STRONG_COSINE).
|
||||
|
||||
Era 0,70 si a fost prea jos: pe 2026-09-01, „am o factura cu eroare in SPV"
|
||||
(0,768) si o captura cu `errorMessage="CUI cumparator incorect"` (0,778) au
|
||||
trecut drept acoperite, desi prima nu spune ce eroare e, iar a doua nu exista
|
||||
in documente. Toate chunk-urile eFactura seamana intre ele: 0,7x nu distinge
|
||||
„e in documente" de „e despre eFactura". La 0,80 trec doar potrivirile
|
||||
aproape textuale, restul cad pe dovada lexicala (termenii rari din intrebare
|
||||
chiar in chunk-uri). Verificat cu ops/calibrate-rank.py: 25/25.
|
||||
"""
|
||||
return float(config.get("RANK_STRONG_COSINE", "0.80"))
|
||||
|
||||
|
||||
def weak_cosine() -> float:
|
||||
|
||||
Reference in New Issue
Block a user