Log the 2026-08-24 session: F3 fix live, audit filled, corpus re-ingest scoped

This commit is contained in:
2026-08-24 15:07:30 +07:00
parent f3eaab0948
commit 33b16c885b
7 changed files with 575 additions and 11 deletions
@@ -163,6 +163,96 @@ def test_single_section_named_is_unaffected_by_the_multi_section_clarify():
assert frame.needs_clarify is False
def test_patient_comorbidity_question_answers_instead_of_forking_on_ambiguity():
"""Regression for eval case P08, reproduced live 4/4 times 2026-08-20:
"BN tăng huyết áp kèm xơ gan Child-Pugh B dùng thuốc nào cần lưu ý?"
reliably clarified instead of running the patient-safety assessment path
`patient_ckd`/`patient_multi`/etc. already use successfully. The payload
below is the real raw understanding output captured for that turn — the
model read "kèm xơ gan..." as a fork in what the QUESTION means (caution
vs causation) and marked the condition ambiguous with its own
clarify_question, discarding the richly-parsed `patient_context` it
produced in the very same call."""
understander = LlmQueryUnderstander(_FixedLlm({
"turn_type": "condition_relation",
"drugs": [], "unknown_drugs": [], "attribute": None,
"population": None, "weight_kg": None, "age_text": None,
"indication": None,
"condition": {
"original_text": "tăng huyết áp kèm xơ gan Child-Pugh B",
"normalized_condition": "tăng huyết áp",
"subtype": "Child-Pugh B",
"qualifiers": ["xơ gan Child-Pugh B"],
"ambiguous": True,
"clarify_question": (
"Anh/chị muốn biết thuốc nào cần lưu ý khi tăng huyết áp kèm "
"xơ gan Child-Pugh B, hay thuốc nào gây tăng huyết áp ở bệnh "
"nhân này?"
),
},
"condition_relation": "adverse_effect",
"patient_context": {
"comorbidities": ["xơ gan Child-Pugh B"],
"hepatic": {"description": "xơ gan Child-Pugh B", "child_pugh": "Child-Pugh B"},
},
"context_action": "new",
"needs_clarify": True,
"clarify_reason": (
"Anh/chị muốn hỏi thuốc nào GÂY tăng huyết áp ở bệnh nhân xơ gan "
"Child-Pugh B, hay thuốc nào DÙNG ĐỂ điều trị tăng huyết áp "
"nhưng cần lưu ý ở bệnh nhân này?"
),
"quick_replies": ["Thuốc nào gây tăng huyết áp?", "Thuốc nào dùng cần lưu ý?"],
}), CATALOG, RESOLVER)
frame = understander.understand(
"BN tăng huyết áp kèm xơ gan Child-Pugh B dùng thuốc nào cần lưu ý?"
)
assert frame.turn_type == "condition_to_drug"
assert frame.needs_clarify is False
assert frame.condition is not None
assert frame.condition.ambiguous is False
assert frame.condition.clarify_question is None
# The hepatic data must survive untouched -- this is what lets
# `_condition_to_drug`'s `assess_patient_candidates` answer safely
# instead of listing indications blind to the Child-Pugh B impairment.
assert frame.patient_context.hepatic.child_pugh == "Child-Pugh B"
def test_bare_broad_disease_still_clarifies_despite_the_candidate_cue():
"""The P08 fix must not swallow a genuine "which disease" fork: a bare
broad condition with NO patient-comorbidity cue (no "BN", "kèm", organ
impairment, ...) still has to ask for a subtype, same as before."""
understander = LlmQueryUnderstander(_FixedLlm({
"turn_type": "condition_relation",
"drugs": [], "unknown_drugs": [], "attribute": None,
"population": None, "weight_kg": None, "age_text": None,
"indication": None,
"condition": {
"original_text": "viêm gan",
"normalized_condition": "viêm gan",
"ambiguous": True,
"clarify_question": "Anh/chị muốn hỏi viêm gan B hay viêm gan C?",
},
"condition_relation": "indication",
"needs_clarify": True,
"clarify_reason": "Anh/chị muốn hỏi viêm gan B hay viêm gan C?",
}), CATALOG, RESOLVER)
frame = understander.understand("Viêm gan dùng thuốc gì?")
# `_apply_broad_condition_cue` (unaffected by this fix, and applied
# AFTER it) is what actually decides this case: it re-derives `condition`
# straight from the raw turn text via its own deterministic broad-disease
# regex, independent of whatever `_apply_condition_candidate_cue` did —
# `frame.needs_clarify` itself is reset to False either way, same as the
# `ambiguous_hepatitis`/`ambiguous_cancer`/`ambiguous_infection` eval
# cases; `agent.py` clarifies off `frame.condition.ambiguous`, not this.
assert frame.condition is not None
assert frame.condition.ambiguous is True
def test_multi_section_clarify_does_not_inherit_a_stale_prior_attribute():
prior = QueryFrame(
turn_type="drug_attribute",