fix(maria): mesajul si captura sunt acelasi lucru, iar cosinusul singur nu mai e dovada

Doua greseli din grupul "Maria Test", 2026-09-01, pe care 27409fb le-a atenuat dar
nu le-a rezolvat.

1. La o reclamatie vaga Maria cauta, in loc sa intrebe. "Buna . Am si eu o factura
   pe luna august cu eroare in spv la trimitere AUTO SULE" nu spune CE eroare e —
   n-are ce cauta in documente si n-are ce trimite la suport, fiindca programatorul
   ar pune exact aceeasi intrebare. Gardul (triaj.prea_vag) exista, dar cerea text
   sub 12 cuvinte; mesajul are 14. Gresea si invers: "nu pot incarca factura in SPV,
   imi da eroare de certificat" are 9 cuvinte si ARE raspuns in documente, si era
   oprita degeaba. Lungimea nu masoara cat de precis e mesajul.
   -> gardul nu mai numara cuvinte si se aplica DUPA cautare, doar cand nu exista
      acoperire. O singura data pe fir: daca nici intrebat omul nu spune mai mult,
      mesajul pleaca la suport.

2. Textul si captura, trimise una dupa alta, erau tratate ca doua probleme fara
   legatura. `este_continuare` rupea firul la ORICE imagine — dar cazul frecvent e
   tocmai omul care scrie problema si trimite captura imediat dupa, sau care
   raspunde la "trimite-mi o captura". Textul se pierdea, captura se cauta doar pe
   OCR-ul ei, se deschideau doua fire si se puteau deschide doua escaladari pentru
   aceeasi problema.
   -> o captura in primele FIR_IMAGINE_MIN (5) minute continua firul: textul citit
      din ea intra in ancora (cu tot cu coduri), cautarea se face pe mesaj +
      captura, iar pe o escaladare deschisa pleaca la aceeasi referinta — cu
      imaginea, nu doar cu textul citit din ea (_notifica_suport ia si media).

Si, ca urmare a lui (2): RANK_STRONG_COSINE dispare. Interogarea pe un fir e ancora
plus mesajul nou, deci cosinusul urca la fiecare replica fara sa apara vreo dovada
noua — aceeasi captura da 0,778 singura si 0,836 cu mesajul de dinainte, adica peste
0,80 pus ieri. Orice prag fix de sus e trecut de o discutie destul de lunga. Acoperirea
ramane pe dovada lexicala (termenii distinctivi ai intrebarii chiar in chunk-uri),
care e stabila la lungime. Niciun caz cu raspuns in documente nu avea nevoie de
scurtatura.

ops/calibrate-rank.py: 26/26, cu interogarea combinata adaugata la set. Teste: 102 pass.
Verificat end-to-end pe scenariul real (mesaj, apoi captura la 10 secunde): intrebare
de detalii, apoi o singura escaladare care poarta si textul si captura.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q4uzvgm7AyJch5WH8QHRhY
This commit is contained in:
Claude Agent
2026-09-01 19:17:09 +00:00
parent 45b36591c9
commit 47110d71bf
11 changed files with 192 additions and 94 deletions

View File

@@ -353,24 +353,28 @@ Fuziunea da mereu un clasament, si la o intrebare complet straina. De aceea deci
0. **intrebarea contine un cod de eroare** (`ORA-…`, `PLS-…`, `D406`) → decide
doar prezenta lui in chunk-uri, indiferent de cosinus;
1. cosinus ≥ `RANK_STRONG_COSINE` → raspundem;
2. cosinus < `RANK_WEAK_COSINE` → escaladam direct;
3. intre ele → raspundem doar daca cel putin `RANK_MIN_RARE_RATIO` din termenii
1. cosinus < `RANK_WEAK_COSINE` → escaladam direct;
2. peste → raspundem doar daca cel putin `RANK_MIN_RARE_RATIO` din termenii
distinctivi ai intrebarii (coduri, cuvinte rare in corpus) apar chiar in
chunk-urile gasite.
Fractiunea din pasul 3 nu e cosmetica: cu un singur termen gasit, „cum imi resetez
Fractiunea din pasul 2 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
**Nu exista prag „cosinus destul de mare ca sa nu mai verificam".** A existat
(`RANK_STRONG_COSINE`, 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.
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".
L-am scos, nu urcat, fiindca **cosinusul creste cu lungimea interogarii**: pe un fir
de discutie se cauta dupa ancora plus mesajul nou, deci scorul urca la fiecare
replica fara sa apara vreo dovada in plus. Aceeasi captura: 0,778 singura, 0,836
impreuna cu mesajul de dinainte. Orice prag fix de sus e trecut de o discutie destul
de lunga. `ops/calibrate-rank.py`: 26/26, si niciunul dintre cazurile cu raspuns in
documente nu avea nevoie de scurtatura — toate trec pe dovada lexicala.
Modelul primeste `temperature=0` (`LLM_TEMPERATURE`). Fara ea, llama.cpp raspunde
cu 0,8 — creativitate exact acolo unde vrem sa se rezume la context.
@@ -393,9 +397,18 @@ Nu orice mesaj e o intrebare, si nu orice raspuns e util. `rag/triaj.py` ia trei
decizii inaintea modelului:
**Mesaj prea vag.** „Am o eroare" nu spune nimic. Maria cere operatiunea, ecranul si
textul erorii (sau o captura) — nu ghiceste si nu deranjeaza suportul cu atat. Regula
e ingusta deliberat: doar text scurt, fara captura si fara cod de eroare, in care apar
cuvinte de acuza („nu merge", „imi da"). „Cum trimit D406" trece nestingherit.
textul erorii (sau o captura) — nu ghiceste si nu deranjeaza suportul cu atat, fiindca
programatorul ar pune exact aceeasi intrebare.
Decizia se ia **dupa cautare, si numai cand nu exista acoperire in documente**. Inainte
se lua inaintea cautarii, dupa lungime: text scurt (sub 12 cuvinte), fara captura si
fara cod, cu cuvinte de acuza („nu merge", „imi da"). Gardul gresea in ambele sensuri
— „Buna . Am si eu o factura pe luna august cu eroare in spv la trimitere AUTO SULE"
are 14 cuvinte si tot nu zice CE eroare e (a trecut, si a primit un raspuns inventat),
iar „nu pot incarca factura in SPV, imi da eroare de certificat" are 9 si e in
documente (era oprita degeaba). Lungimea nu masoara cat de precis e mesajul;
acoperirea in documente da. Se cere o singura data pe fir: daca nici dupa ce a fost
intrebat omul nu spune mai mult, mesajul pleaca la suport.
**Erori care oricum ajung la programatori.** Dictionarul de erori Oracle are pe fiecare
intrare campul `cand suni suportul`. Noua incep cu „Intotdeauna" sau „Imediat" — nu se
@@ -437,10 +450,20 @@ La o continuare: cautarea se face pe **ancora + mesajul nou**, modelul primeste
istoricul, mesajul se adauga la escaladarea deschisa (`completari`, de cate ori e
nevoie), iar „mesaj prea vag" nu se mai aplica — detaliile au fost deja cerute.
**Ce rupe firul, necontestat:** o captura noua sau un cod de eroare diferit. Sunt
singurele semne sigure ca omul a trecut la altceva. Schimbarea subiectului in cuvinte
NU rupe firul: e prea usor de confundat cu o continuare, iar greseala aia produce
exact tabelul de mai sus. In rest, firul expira dupa `FIR_TTL_MIN` (120 min).
**Ce rupe firul:** un cod de eroare pe care firul nu-l are, sau o captura venita la
mai mult de `FIR_IMAGINE_MIN` (5 min) dupa ultimul mesaj. Schimbarea subiectului in
cuvinte NU rupe firul: e prea usor de confundat cu o continuare, iar greseala aia
produce exact tabelul de mai sus. In rest, firul expira dupa `FIR_TTL_MIN` (120 min).
Orice captura a rupt firul pana pe 2026-09-01, si era gresit exact in cazul cel mai
frecvent: **omul scrie problema si trimite captura imediat dupa** (sau Maria tocmai
i-a cerut-o). WhatsApp le livreaza ca doua mesaje, dar e un singur lucru. Tratate
separat, textul se pierdea si captura se cauta doar pe OCR-ul ei; se deschideau doua
fire, se puteau deschide doua escaladari pentru aceeasi problema, iar suportul primea
doua mesaje fara legatura. Acum captura din fereastra de 5 minute continua firul:
textul citit din ea intra in ancora (cu tot cu codurile lui), cautarea se face pe
mesaj + captura, iar daca firul are deja o escaladare deschisa captura pleaca la
aceeasi referinta — cu imaginea, nu doar cu textul citit din ea.
### Completarile: trei feluri, trei raspunsuri