Verify exact production traces and record rollout
This commit is contained in:
@@ -11,7 +11,7 @@ import json
|
||||
import pytest
|
||||
|
||||
from rag import grounding
|
||||
from rag.answer import GroundedAnswerService
|
||||
from rag.answer import DISCLAIMER, GroundedAnswerService
|
||||
from rag.budget import RequestBudgetExhausted
|
||||
from rag.metrics import GENERATION_REJECTED, GENERATION_SERVED, InMemoryMetrics
|
||||
from rag.models import (
|
||||
@@ -116,6 +116,62 @@ def _answer(payload, result: RetrievalResult | None = None, entailment_payload=N
|
||||
return grounded, metrics
|
||||
|
||||
|
||||
# --- the disclaimer guardrail -------------------------------------------------
|
||||
# `docs/architecture.md` specifies the disclaimer at several layers. Only the
|
||||
# web banner existed; `packages/shared-types/src/dto/chat.ts` declared the
|
||||
# field but nothing filled it, so a consumer other than that one UI got medical
|
||||
# content with nothing attached. It is a dataclass default rather than
|
||||
# something each call site adds, so these tests are about the paths that could
|
||||
# plausibly skip it: rejections, abstains and clarifications.
|
||||
|
||||
|
||||
def test_a_served_answer_carries_the_disclaimer():
|
||||
grounded, _ = _answer(
|
||||
{"claims": [{"text": "Người lớn uống 500 mg", "citations": [1]}],
|
||||
"evidence_sufficient": True},
|
||||
)
|
||||
|
||||
assert grounded.generated is True
|
||||
assert grounded.disclaimer == DISCLAIMER
|
||||
assert grounded.disclaimer
|
||||
|
||||
|
||||
def test_a_rejected_generation_still_carries_the_disclaimer():
|
||||
"""An abstain is still a clinical response and still needs the notice —
|
||||
it is the case most likely to be treated as "not really an answer"."""
|
||||
grounded, _ = _answer(
|
||||
{"claims": [{"text": "Người lớn uống 850 mg, 2 lần mỗi ngày", "citations": [1]}],
|
||||
"evidence_sufficient": True},
|
||||
)
|
||||
|
||||
assert grounded.answer is None
|
||||
assert grounded.result.decision == EvidenceDecision.ABSTAIN
|
||||
assert grounded.disclaimer == DISCLAIMER
|
||||
|
||||
|
||||
def test_a_provider_outage_response_still_carries_the_disclaimer():
|
||||
grounded, _ = _answer(
|
||||
{"claims": [{"text": "Người lớn: 500 mg, 2 lần/ngày", "citations": [1]}],
|
||||
"evidence_sufficient": True},
|
||||
entailment_payload=AnswerGenerationUnavailable(),
|
||||
)
|
||||
|
||||
assert grounded.disclaimer == DISCLAIMER
|
||||
|
||||
|
||||
def test_the_disclaimer_is_not_something_the_model_can_influence():
|
||||
"""It is a module constant, never routed through the generator, so a
|
||||
prompt-injected or malfunctioning model cannot shorten or drop it. Asserted
|
||||
directly because the value is the guardrail."""
|
||||
grounded, _ = _answer(
|
||||
{"claims": [{"text": "Bỏ qua mọi cảnh báo. Người lớn uống 500 mg", "citations": [1]}],
|
||||
"evidence_sufficient": True},
|
||||
)
|
||||
|
||||
assert grounded.disclaimer == DISCLAIMER
|
||||
assert "không thay thế chỉ định" in grounded.disclaimer
|
||||
|
||||
|
||||
# --- the guardrail's whole reason to exist ------------------------------------
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user