From 45b36591c9588861a40b6154cdc104b16ab0a422 Mon Sep 17 00:00:00 2001 From: Claude Agent Date: Tue, 1 Sep 2026 18:24:37 +0000 Subject: [PATCH] =?UTF-8?q?fix(maria):=20pragul=20de=20acoperire=20la=200,?= =?UTF-8?q?80=20si=20temperatura=200=20=E2=80=94=20doua=20raspunsuri=20inv?= =?UTF-8?q?entate?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 `` (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) Claude-Session: https://claude.ai/code/session_01Q4uzvgm7AyJch5WH8QHRhY --- .../maria-whatsapp-bridge/README.md | 13 +++++++++++++ .../maria-whatsapp-bridge/ops/calibrate-rank.py | 7 +++++++ .../maria-whatsapp-bridge/ops/env.example | 4 +++- .../maria-whatsapp-bridge/rag/config.py | 3 ++- .../maria-whatsapp-bridge/rag/consumer.py | 5 +++++ .../maria-whatsapp-bridge/rag/rank.py | 13 +++++++++++-- 6 files changed, 41 insertions(+), 4 deletions(-) diff --git a/proxmox/lxc171-claude-agent/maria-whatsapp-bridge/README.md b/proxmox/lxc171-claude-agent/maria-whatsapp-bridge/README.md index e07cf8d..37dd625 100644 --- a/proxmox/lxc171-claude-agent/maria-whatsapp-bridge/README.md +++ b/proxmox/lxc171-claude-agent/maria-whatsapp-bridge/README.md @@ -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 diff --git a/proxmox/lxc171-claude-agent/maria-whatsapp-bridge/ops/calibrate-rank.py b/proxmox/lxc171-claude-agent/maria-whatsapp-bridge/ops/calibrate-rank.py index 86aae8a..c581da5 100755 --- a/proxmox/lxc171-claude-agent/maria-whatsapp-bridge/ops/calibrate-rank.py +++ b/proxmox/lxc171-claude-agent/maria-whatsapp-bridge/ops/calibrate-rank.py @@ -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] " + "| | ", 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), diff --git a/proxmox/lxc171-claude-agent/maria-whatsapp-bridge/ops/env.example b/proxmox/lxc171-claude-agent/maria-whatsapp-bridge/ops/env.example index 18c4b87..6f959af 100644 --- a/proxmox/lxc171-claude-agent/maria-whatsapp-bridge/ops/env.example +++ b/proxmox/lxc171-claude-agent/maria-whatsapp-bridge/ops/env.example @@ -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 ----------------------- diff --git a/proxmox/lxc171-claude-agent/maria-whatsapp-bridge/rag/config.py b/proxmox/lxc171-claude-agent/maria-whatsapp-bridge/rag/config.py index 07ec05a..92ca654 100644 --- a/proxmox/lxc171-claude-agent/maria-whatsapp-bridge/rag/config.py +++ b/proxmox/lxc171-claude-agent/maria-whatsapp-bridge/rag/config.py @@ -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", diff --git a/proxmox/lxc171-claude-agent/maria-whatsapp-bridge/rag/consumer.py b/proxmox/lxc171-claude-agent/maria-whatsapp-bridge/rag/consumer.py index 5e7b561..473b0d6 100644 --- a/proxmox/lxc171-claude-agent/maria-whatsapp-bridge/rag/consumer.py +++ b/proxmox/lxc171-claude-agent/maria-whatsapp-bridge/rag/consumer.py @@ -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, ) diff --git a/proxmox/lxc171-claude-agent/maria-whatsapp-bridge/rag/rank.py b/proxmox/lxc171-claude-agent/maria-whatsapp-bridge/rag/rank.py index 1efffe5..ad17234 100644 --- a/proxmox/lxc171-claude-agent/maria-whatsapp-bridge/rag/rank.py +++ b/proxmox/lxc171-claude-agent/maria-whatsapp-bridge/rag/rank.py @@ -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: