"""US-006 (PRD 5.18) — enrich_suggestions = pre-filtru NUL + k-NN pe corpus etichetat. Ordinea de precedenta: pre-filtru NUL -> (daca NUL: fara cod) altfel GOLD partajat > exact (SILVER) > k-NN embeddings. k-NN sub prag -> abtinere. Vecin k-NN NUL -> supresie. Invariant #13: nimic din asta nu intra in resolve_prestatii/load_mapping. """ from __future__ import annotations import os import tempfile import pytest @pytest.fixture() def env(monkeypatch): tmp = tempfile.mkdtemp() monkeypatch.setenv("AUTOPASS_DB_PATH", os.path.join(tmp, "us006.db")) monkeypatch.setenv("AUTOPASS_WEB_AUTH_REQUIRED", "false") monkeypatch.setenv("AUTOPASS_EMBEDDINGS_ENABLED", "true") from app.config import get_settings get_settings.cache_clear() from app.db import init_db init_db() yield monkeypatch get_settings.cache_clear() @pytest.fixture() def conn(env): from app.db import get_connection c = get_connection() yield c c.close() def _silver(conn, denumire_norm, cod, is_nul=0): conn.execute( "INSERT OR IGNORE INTO mapping_suggestions " "(denumire_normalizata, cod_prestatie, is_nul, source, confidence) VALUES (?, ?, ?, 'llm_seed', 0.7)", (denumire_norm, cod, is_nul), ) conn.commit() def _mock_embedding(monkeypatch, cod, sim, is_nul=False): import app.embeddings as emb monkeypatch.setattr(emb, "has_corpus", lambda: True) monkeypatch.setattr(emb, "suggest_nearest", lambda text, top_k=1: [{"cod": cod, "is_nul": is_nul, "similaritate": sim}]) def test_prefiltru_nul_supreseaza_inainte_de_knn(conn, monkeypatch): # Embedding-ul AR sugera un cod, dar pre-filtrul NUL trebuie sa scurtcircuiteze. chemat = {"da": False} import app.embeddings as emb monkeypatch.setattr(emb, "has_corpus", lambda: True) def spion(text, top_k=1): chemat["da"] = True return [{"cod": "OE-1", "is_nul": False, "similaritate": 0.99}] monkeypatch.setattr(emb, "suggest_nearest", spion) from app.mapping import enrich_suggestions out = enrich_suggestions(conn, "13 X ITP") assert out["sugestie_principala"] is None # non-operatie -> fara cod assert out["surse"]["nul"] is True assert chemat["da"] is False # k-NN nici macar interogat def test_precedenta_gold_exact_embedding(conn, monkeypatch): from app.shared_store import record_human_validation from app.mapping import enrich_suggestions, normalize_for_match den = "OPERATIE DE TEST UNICA" norm = normalize_for_match(den) # Toate trei sursele dau coduri diferite. record_human_validation(conn, den, "OE-1") # GOLD partajat _silver(conn, norm, "OE-2") # SILVER exact _mock_embedding(monkeypatch, "OE-3", 0.99) # embedding conn.commit() out = enrich_suggestions(conn, den) assert out["sugestie_principala"] == {"cod_prestatie": "OE-1", "sursa": "gold_partajat"} # Fara GOLD -> castiga SILVER. conn.execute("DELETE FROM shared_mappings") conn.commit() out = enrich_suggestions(conn, den) assert out["sugestie_principala"]["sursa"] == "silver" assert out["sugestie_principala"]["cod_prestatie"] == "OE-2" # Fara GOLD si fara SILVER -> castiga embedding. conn.execute("DELETE FROM mapping_suggestions") conn.commit() out = enrich_suggestions(conn, den) assert out["sugestie_principala"] == {"cod_prestatie": "OE-3", "sursa": "embedding"} def test_prag_similaritate(conn, monkeypatch): from app.mapping import enrich_suggestions, EMB_MIN_SIMILARITATE _mock_embedding(monkeypatch, "OE-3", EMB_MIN_SIMILARITATE + 0.01) out = enrich_suggestions(conn, "CEVA NEVAZUT") assert out["surse"]["embedding"] == "OE-3" def test_abtinere_sub_prag(conn, monkeypatch): from app.mapping import enrich_suggestions, EMB_MIN_SIMILARITATE _mock_embedding(monkeypatch, "OE-3", EMB_MIN_SIMILARITATE - 0.01) out = enrich_suggestions(conn, "CEVA NEVAZUT") assert out["surse"]["embedding"] is None # sub prag -> abtinere 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 out = enrich_suggestions(conn, "CEVA CARE SEAMANA CU GUNOI") assert out["surse"]["embedding"] is None # NUL -> nu produce cod assert out["surse"]["nul"] is True assert out["sugestie_principala"] is None def test_invariant_13_resolve_neatins(conn): """Regresie #13: SILVER populat NU produce auto-rezolvare in resolve_prestatii.""" from app.mapping import resolve_prestatii, normalize_for_match _silver(conn, normalize_for_match("OPERATIE X"), "OE-1") resolved, unmapped = resolve_prestatii( [{"cod_op_service": "OPERATIE X", "denumire": "OPERATIE X"}], mapping={}, valid_codes={"OE-1"} ) assert resolved[0]["cod_prestatie"] is None # ramane nemapat, NU ia codul din SILVER assert unmapped and unmapped[0]["cod_op_service"] == "OPERATIE X"