"""Confronto "metodi" DERIVATO dalle tracce della singola run (debug == analizza). Il tab metodi non ri-esegue i layer: ricostruisce "chi ha catturato cosa" dai contributi grezzi già presenti nelle tracce della run di analisi. """ from __future__ import annotations from core.output.trace import ClusterTrace, SpanContribution from web.services.analysis import build_methods_comparison # process -> (layer_key, label) PROCESS_INDEX = { "gliner": ("zero_shot", "Zero-shot (GLiNER)"), "rule_cig": ("rules", "Regole deterministiche"), } def _contrib(process, text, etype, score): return SpanContribution( process=process, layer="X", entity_type=etype, text=text, start=0, end=len(text), score=score, validated=False, source=process, is_representative=False, ) def _trace(contribs): return ClusterTrace( text=contribs[0].text, entity_type=contribs[0].entity_type, label="", severity="", start=0, end=10, base_score=0.5, agreement_boost=0.0, final_score=0.5, agreement_count=1, validated=False, threshold=0.5, passed_threshold=True, kept=True, contributions=contribs, ) def test_only_selected_layers_appear(): """Selezionato solo zero_shot: un contributo 'rules' NON deve comparire.""" traces = [_trace([ _contrib("gliner", "CIG1234", "CIG", 0.9), _contrib("rule_cig", "CIG1234", "CIG", 1.0), ])] out = build_methods_comparison(traces, PROCESS_INDEX, selected={"zero_shot"}) assert out["methods"] == ["zero_shot"] assert "rules" not in out["method_labels"] assert out["entities"][0]["found_by"] == ["zero_shot"] def test_found_by_and_not_found_by_across_layers(): """Entrambi i layer selezionati; entità catturata solo da uno.""" traces = [_trace([_contrib("gliner", "Mario Rossi", "RUP", 0.8)])] out = build_methods_comparison( traces, PROCESS_INDEX, selected={"zero_shot", "rules"} ) e = out["entities"][0] assert e["found_by"] == ["zero_shot"] assert e["not_found_by"] == ["rules"] assert e["by_method"]["zero_shot"]["score"] == 0.8 assert e["by_method"]["zero_shot"]["processes"] == ["gliner"] def test_scores_use_best_contribution_per_layer(): traces = [ _trace([_contrib("gliner", "Comune di Milano", "STAZIONE_APPALTANTE", 0.7)]), _trace([_contrib("gliner", "Comune di Milano", "STAZIONE_APPALTANTE", 0.95)]), ] out = build_methods_comparison(traces, PROCESS_INDEX, selected={"zero_shot"}) e = out["entities"][0] assert e["by_method"]["zero_shot"]["score"] == 0.95 assert e["by_method"]["zero_shot"]["count"] == 2