perf+calitate sugestii k-NN: matvec numpy, vot top-5 cu prag calibrat, indicatori import
- embeddings: corpus ca matrice numpy cu norme precalculate; suggest_nearest
= un matvec (~0.6ms/query fata de ~500ms cosine pur-Python la 17k vectori)
- enrich_suggestions: vot ponderat cu similaritatea pe top-5 vecini (NUL =
eticheta proprie); prag 0.5 -> 0.88, calibrat LOO pe corpusul SILVER
(tools/mapare-llm/knn_calibrate.py): precizie 90.5% -> 93.1%, cod gresit
preselectat 7.2% -> 4.7%; sub prag abtinere -> preselectie fuzzy
- UI: codul sugerat de sistem afisat explicit cu sursa si scorul, separat de
lista fuzzy ("potrivire text"); indicator de progres reparat pe upload
(display:inline anula .htmx-indicator) si adaugat pe pasii 2->3 si
"Salveaza maparile"
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -113,6 +113,58 @@ def test_abtinere_sub_prag(conn, monkeypatch):
|
||||
assert out["sugestie_principala"] is None
|
||||
|
||||
|
||||
def _mock_embedding_multi(monkeypatch, vecini):
|
||||
"""Mock suggest_nearest cu o lista de vecini [(cod, sim, is_nul), ...]."""
|
||||
import app.embeddings as emb
|
||||
monkeypatch.setattr(emb, "has_corpus", lambda: True)
|
||||
monkeypatch.setattr(
|
||||
emb, "suggest_nearest",
|
||||
lambda text, top_k=1: [
|
||||
{"cod": c, "is_nul": n, "similaritate": s} for c, s, n in vecini
|
||||
][:top_k],
|
||||
)
|
||||
|
||||
|
||||
def test_vot_topk_bate_top1_pe_etichete_contradictorii(conn, monkeypatch):
|
||||
"""Corpus cu etichete contradictorii pe denumiri aproape identice:
|
||||
top-1 ar da OE-1, dar votul ponderat (2x OE-8 vs 1x OE-1) da OE-8."""
|
||||
from app.mapping import enrich_suggestions
|
||||
_mock_embedding_multi(monkeypatch, [
|
||||
("OE-1", 0.94, False),
|
||||
("OE-8", 0.93, False),
|
||||
("OE-8", 0.92, False),
|
||||
])
|
||||
out = enrich_suggestions(conn, "INLOCUIRE ANVELOPE")
|
||||
assert out["surse"]["embedding"] == "OE-8"
|
||||
assert out["surse"]["embedding_similaritate"] == 0.93
|
||||
|
||||
|
||||
def test_vot_vecini_sub_prag_nu_voteaza(conn, monkeypatch):
|
||||
"""Vecinii sub EMB_MIN_SIMILARITATE nu intra in vot, chiar daca sunt majoritari."""
|
||||
from app.mapping import enrich_suggestions, EMB_MIN_SIMILARITATE
|
||||
_mock_embedding_multi(monkeypatch, [
|
||||
("OE-3", EMB_MIN_SIMILARITATE + 0.01, False),
|
||||
("OE-1", EMB_MIN_SIMILARITATE - 0.05, False),
|
||||
("OE-1", EMB_MIN_SIMILARITATE - 0.05, False),
|
||||
])
|
||||
out = enrich_suggestions(conn, "CEVA NEVAZUT")
|
||||
assert out["surse"]["embedding"] == "OE-3"
|
||||
|
||||
|
||||
def test_vot_nul_majoritar_supreseaza(conn, monkeypatch):
|
||||
"""Majoritate NUL in vecinatate -> supresie, chiar daca top-1 e un cod."""
|
||||
from app.mapping import enrich_suggestions
|
||||
_mock_embedding_multi(monkeypatch, [
|
||||
("OE-1", 0.93, False),
|
||||
(None, 0.92, True),
|
||||
(None, 0.92, True),
|
||||
])
|
||||
out = enrich_suggestions(conn, "CEVA CARE SEAMANA CU GUNOI")
|
||||
assert out["surse"]["embedding"] is None
|
||||
assert out["surse"]["nul"] is True
|
||||
assert out["sugestie_principala"] is None
|
||||
|
||||
|
||||
def test_vecin_knn_nul_supreseaza(conn, monkeypatch):
|
||||
from app.mapping import enrich_suggestions
|
||||
_mock_embedding(monkeypatch, None, 0.99, is_nul=True) # vecin NUL peste prag
|
||||
|
||||
@@ -278,7 +278,7 @@ def test_embeddings_functional_cand_flag_activ(conn, monkeypatch):
|
||||
conn.execute(
|
||||
"INSERT OR REPLACE INTO mapping_suggestions "
|
||||
"(denumire_normalizata, cod_prestatie, is_nul, source, confidence) VALUES (?, ?, ?, ?, ?)",
|
||||
("Schimb ulei", "UL-1", 0, "llm", 0.95),
|
||||
("Schimb ulei motor", "UL-1", 0, "llm", 0.95),
|
||||
)
|
||||
conn.execute(
|
||||
"INSERT OR REPLACE INTO mapping_suggestions "
|
||||
@@ -292,7 +292,8 @@ def test_embeddings_functional_cand_flag_activ(conn, monkeypatch):
|
||||
ensure_embeddings_corpus(conn)
|
||||
assert emb_mod.has_corpus(), "corpusul trebuie indexat cand flagul e activ"
|
||||
|
||||
# "schimbat uleiul motor" -> vector [1,1,0] -> cel mai apropiat = UL-1 (Schimb ulei).
|
||||
# "schimbat uleiul motor" -> vector [1,1,0] -> identic cu "Schimb ulei motor"
|
||||
# (cosine 1.0, peste EMB_MIN_SIMILARITATE calibrat) -> UL-1.
|
||||
result = enrich_suggestions(conn, "schimbat uleiul motor", include_embeddings=True)
|
||||
assert result["surse"]["embedding"] == "UL-1", (
|
||||
f"embeddings trebuie sa sugereze UL-1, got {result['surse']}"
|
||||
|
||||
@@ -217,4 +217,7 @@ def test_collect_unmapped_ops_conn_none_contract_template(env):
|
||||
assert len(out) == 1
|
||||
e = out[0]
|
||||
assert e["sugestie_principala"] is None
|
||||
assert e["surse_sugestie"] == {"gold_partajat": None, "silver": None, "embedding": None, "nul": False}
|
||||
assert e["surse_sugestie"] == {
|
||||
"gold_partajat": None, "silver": None,
|
||||
"embedding": None, "embedding_similaritate": None, "nul": False,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user