from rag.answer import GroundedAnswerService from rag.models import ( Evidence, EvidenceDecision, QueryIntent, RetrievalResult, SourceRef, SubjectScope, ) class FixedRouting: def __init__(self, result: RetrievalResult) -> None: self._result = result def retrieve(self, query, subject_scope, intent): del query, subject_scope, intent return self._result def evidence(source: SourceRef, *, visual: bool = False) -> Evidence: return Evidence( evidence_id="chunk-1", matched_doc_id="chunk-1", kind="prose", text="Liều được ghi trong nguồn.", score=0.9, source_refs=(source,), hydrated_from_parent=False, requires_visual_check=visual, ) def test_answer_uses_only_printed_page_citations(): source = SourceRef( physical_page=100, precision="chunk_page_range", page_range=(100, 102), printed_page_range=(101, 103), ) service = GroundedAnswerService(FixedRouting(RetrievalResult( EvidenceDecision.ANSWERABLE, "grounded_evidence_available", (evidence(source),), "abacavir", "resolved", ))) answer = service.answer("q", SubjectScope.HUMAN, QueryIntent.FACT_LOOKUP) assert answer.answer == "Liều được ghi trong nguồn." assert answer.blocks[0].claims[0].source_ids assert answer.citations[0].printed_page_start == 101 assert answer.citations[0].printed_page_end == 103 def test_answer_abstains_when_only_physical_page_is_available(): source = SourceRef(physical_page=100, precision="chunk_page_range") service = GroundedAnswerService(FixedRouting(RetrievalResult( EvidenceDecision.ANSWERABLE, "grounded_evidence_available", (evidence(source),), "abacavir", "resolved", ))) answer = service.answer("q", SubjectScope.HUMAN, QueryIntent.FACT_LOOKUP) assert answer.result.decision == EvidenceDecision.ABSTAIN assert answer.result.reason == "missing_printed_page_provenance" assert answer.answer is None assert answer.citations == () def test_visual_evidence_never_auto_extracts_numbers(): source = SourceRef( physical_page=100, precision="region", printed_page=101, ) service = GroundedAnswerService(FixedRouting(RetrievalResult( EvidenceDecision.VERIFY_PDF, "visual_verification_required", (evidence(source, visual=True),), "abacavir", "resolved", ))) answer = service.answer("q", SubjectScope.HUMAN, QueryIntent.FACT_LOOKUP) assert "không tự động trích số liệu" in answer.answer assert "Liều được ghi" not in answer.answer def test_visual_citation_preserves_block_page_and_bbox_without_a_crop_file(): source = SourceRef( physical_page=209, precision="region", block_id="p209_t0", bbox=(49.5, 68.1, 289.4, 789.4), printed_page=210, ) service = GroundedAnswerService(FixedRouting(RetrievalResult( EvidenceDecision.VERIFY_PDF, "visual_verification_required", (evidence(source, visual=True),), "arsenic_trioxyd", "resolved", ))) answer = service.answer("q", SubjectScope.HUMAN, QueryIntent.FACT_LOOKUP) citation = answer.citations[0] assert citation.physical_page == 209 assert citation.block_id == "p209_t0" assert citation.bbox == (49.5, 68.1, 289.4, 789.4) assert citation.source_crop is None assert citation.attachment == "p209_t0"