import json import sys import unittest from pathlib import Path sys.path.insert(0, str(Path(__file__).resolve().parents[1])) from pharmacy_agent import QUERY_SETTINGS, build_aliases, detect_drugs, prepare_query from scripts.evaluation.run_evaluation import metrics, summarize from scripts.evaluation.judge_answers import parse_verdict def product(name, subs, rep="https://example.org/a"): return dict(name=name,subs=subs,rep=rep,url=rep or "https://example.org/b",form="",rx="",type="",group="",ind="") class AgentTests(unittest.TestCase): def setUp(self): self.products=[product("Nurofen 200 mg",["ibuprofén"]),product("Warfarin 5 mg",["warfarín"])] self.aliases,self.prefixes,_=build_aliases(self.products) def test_slovak_inflection_and_brand(self): matches=detect_drugs("Nurofen spolu s warfarínom",self.aliases,self.prefixes) self.assertEqual({m["label"].lower() for m in matches},{"nurofen","warfarín"}) def test_short_brand_and_full_name(self): items=[product("ACC Long 600 mg",["acetylcysteín"])] a,p,_=build_aliases(items) self.assertEqual(len(detect_drugs("Na čo je ACC Long?",a,p)),1) def test_ambiguous_brand_does_not_invent_single_substance(self): items=[product("Brand 200 mg",["one"]),product("Brand Plus 200 mg",["one","two"])] a,p,_=build_aliases(items) result=prepare_query("Môžem užiť Brand?",items,a,p) self.assertIn("nejednoznačný",result["user_prompt"]) self.assertNotIn("Brand = účinná látka one",result["query"]) def test_unrelated_prefix_not_detected(self): self.assertEqual(detect_drugs("warfarinovyneznamyprodukt",self.aliases,self.prefixes),[]) def test_missing_data_is_not_no_interaction(self): items=[product("Spofaplast náplasť",[],None)] a,p,_=build_aliases(items) result=prepare_query("Spofaplast a iné lieky?",items,a,p) self.assertIn("neznamená",result["user_prompt"]) def test_source_identity_accepts_pil_and_detail(self): case={"sources":["https://adc.sk/detail/x"]} response={"references":[{"file_path":"https://adc.sk/pil/x","content":["text"]}]} self.assertEqual(metrics(case,response,"mix")["source_hit"],1) self.assertIsNone(metrics(case,response,"bypass")["source_hit"]) def test_failures_are_reported_not_scored_as_wrong(self): result=summarize([{"mode":"mix","status":"error"},{"mode":"mix","status":"ok","seconds":2,"metrics":{"source_hit":1}}]) self.assertEqual(result["mix"]["failed"],1) self.assertEqual(result["mix"]["source_hit"],1) def test_graph_budget_reserves_original_source_text(self): available=QUERY_SETTINGS["max_total_tokens"]-QUERY_SETTINGS["max_entity_tokens"]-QUERY_SETTINGS["max_relation_tokens"] self.assertGreaterEqual(available,4000) def test_judge_rejects_more_supported_claims_than_claims(self): verdict={"grounding":{"total":2,"supported":3},"coverage":{"total":1,"supported":1},"appropriate_abstention":False} with self.assertRaises(ValueError): parse_verdict(json.dumps(verdict)) def test_judge_accepts_reasoning_prefix_without_scoring_it(self): verdict={"grounding":{"total":2,"supported":1},"coverage":{"total":1,"supported":1},"appropriate_abstention":False} self.assertEqual(parse_verdict("not a verdict"+json.dumps(verdict)),verdict) if __name__ == "__main__": unittest.main()