fix(sugestii): inlocuirea de anvelope -> OE-8 + vot k-NN ponderat pe rang
Seed-ul Haiku eticheta sistematic "INLOCUIT ANVELOPE ..." cu OE-1 (223 vs 17
OE-8), desi RAR are cod dedicat OE-8 (inlocuire sezoniera anvelope), asa ca
votul k-NN propunea OE-1 pentru orice inlocuire de anvelope.
- tools/mapare-llm/fix_anvelope_oe8.py: re-etichetare deterministica (187
randuri DB + seed JSON -> OE-8; regula exclude singular cu pozitie, D/R,
janta, vulcanizare) + 13 intrari canonice curate manual pentru formularile
sezoniere absente din corpus ("MONTAT CAUCIUCURI VARA" etc.); idempotent
- enrich_suggestions: ponderea votului = EMB_VOTE_DECAY^rang (0.7) in loc de
similaritatea bruta — anizotropia modelului lasa zgomotul de coada (ex.
INLOCUIT BECURII la 0.934 de INLOCUIRE ANVELOPE) sa invinga vecinii corecti
de rang 1-2; LOO: precizie egala (93.1%), cod-gresit 4.67% -> 4.63%
- test_fix_anvelope_oe8: gardii pe regula + seed-ul din repo (regresie la
regenerare); auditul k-NN al dezacordurilor nu a gasit alte erori
sistematice (curatat=OE-2, reglat=OE-4, bujii/ulei=OE-3 raman apararabile)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -638,11 +638,18 @@ def delete_text_rule(conn, account_id: int | None, pattern: str) -> None:
|
||||
# 100% dar 7.4% cod gresit preselectat.
|
||||
EMB_MIN_SIMILARITATE = 0.88
|
||||
|
||||
# Cati vecini intra in votul ponderat cu similaritatea. Vot > top-1: corpusul SILVER
|
||||
# Cati vecini intra in votul ponderat pe rang. Vot > top-1: corpusul SILVER
|
||||
# are etichete contradictorii pe denumiri aproape identice; votul e imun la ele
|
||||
# (+~1pp precizie la acelasi coverage, masurat LOO).
|
||||
EMB_VOTE_TOP_K = 5
|
||||
|
||||
# Ponderea unui vecin = EMB_VOTE_DECAY^rang (1-indexat). Ponderarea cu similaritatea
|
||||
# bruta e pacalita de anizotropia modelului: vecini fara legatura scoreaza aproape
|
||||
# cat cei buni (ex. INLOCUIT BECURII la 0.934 de INLOCUIRE ANVELOPE), deci coada
|
||||
# de zgomot poate invinge 2 vecini corecti de rang 1-2. Ordinea rangurilor ramane
|
||||
# informativa; decay 0.7 = cel mai mic cod-gresit la precizie egala (LOO).
|
||||
EMB_VOTE_DECAY = 0.7
|
||||
|
||||
# Protejeaza secventa hash->load->embed->save->purge->index (embedding_cache) de
|
||||
# executie concurenta intre warmup-ul de fundal (block=True) si calea de request
|
||||
# (block=False, dupa ce modelul e deja incarcat) -- altfel purjarea uneia ar sterge
|
||||
@@ -841,18 +848,18 @@ def enrich_suggestions(
|
||||
# deci query-ul TREBUIE normalizat la fel — altfel cosine degradeaza si
|
||||
# nu mai e configul sub care s-a masurat 94.3%.
|
||||
nn = _emb.suggest_nearest(normalize_for_match(denumire), top_k=EMB_VOTE_TOP_K)
|
||||
# Vot ponderat cu similaritatea pe vecinii peste prag; NUL e eticheta
|
||||
# Vot ponderat pe rang (decay^rang) pe vecinii peste prag; NUL e eticheta
|
||||
# proprie (castiga -> supresie, nu cod). Vecinii sub prag nu voteaza.
|
||||
scoruri: dict[str, float] = {}
|
||||
sim_max: dict[str, float] = {}
|
||||
for v in nn:
|
||||
for rang, v in enumerate(nn, 1):
|
||||
sim = float(v.get("similaritate", 0))
|
||||
if sim < EMB_MIN_SIMILARITATE:
|
||||
continue
|
||||
lab = "NUL" if v.get("is_nul") else (str(v["cod"]) if v.get("cod") else None)
|
||||
if lab is None:
|
||||
continue
|
||||
scoruri[lab] = scoruri.get(lab, 0.0) + sim
|
||||
scoruri[lab] = scoruri.get(lab, 0.0) + EMB_VOTE_DECAY ** rang
|
||||
sim_max[lab] = max(sim_max.get(lab, 0.0), sim)
|
||||
if scoruri:
|
||||
castigator = max(scoruri, key=lambda k: scoruri[k])
|
||||
|
||||
Reference in New Issue
Block a user