Wire up query history: localStorage session persistence + sidebar UI
This commit is contained in:
@@ -30,7 +30,7 @@ from .routing import QueryRoutingService
|
||||
# be different prompts (or a different judge) to be independent evidence —
|
||||
# see this function's own reasoning above.
|
||||
|
||||
_QUICK_REPLY_MAX_ITEMS = 18 # one per monograph section (see rag/sections.py SECTION_ORDER)
|
||||
_QUICK_REPLY_MAX_ITEMS = 19 # one per monograph section (see rag/sections.py SECTION_ORDER)
|
||||
_QUICK_REPLY_MAX_CHARS = 40
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -368,6 +368,39 @@ def _presentation_for_sources(source_ids: tuple[str, ...]) -> tuple[str, str]:
|
||||
return "Trả lời", "fact_list"
|
||||
|
||||
|
||||
# Feature-List #14: a condition/symptom -> drug reverse lookup
|
||||
# (`list_mode=True`, `RagAgent._condition_to_drug`) states which drugs the
|
||||
# formulary's `chi_dinh` sections name for this indication — a factual
|
||||
# lookup, never a treatment ranking (see
|
||||
# `[[feedback_no_recommendation_gate]]`) — but rendered as a bare drug list
|
||||
# it reads exactly like a recommendation. Fixed, non-generated block, same
|
||||
# guarantee as `DISCLAIMER` above: the model never sees or writes this text,
|
||||
# so it cannot reword, shorten, or drop it. Always the first block; `kind`
|
||||
# matches `_plan_answer`'s forced `needs_warning=True` for `list_mode`, so
|
||||
# the UI renders it with the same visual separation as any other warning
|
||||
# block, not a plain bullet.
|
||||
_LIST_MODE_NOTICE_BLOCK = AnswerBlock(
|
||||
title="Đọc cho đúng",
|
||||
kind="warning",
|
||||
claims=(
|
||||
AnswerClaim(
|
||||
text=(
|
||||
"Đây là kết quả TRA CỨU các thuốc mà Dược thư Quốc gia Việt "
|
||||
"Nam ghi nhận chỉ định cho triệu chứng/bệnh này, KHÔNG PHẢI "
|
||||
"khuyến nghị điều trị hay chỉ định lâm sàng cho một người "
|
||||
"bệnh cụ thể."
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
def _with_list_mode_notice(
|
||||
blocks: tuple[AnswerBlock, ...], list_mode: bool
|
||||
) -> tuple[AnswerBlock, ...]:
|
||||
return (_LIST_MODE_NOTICE_BLOCK, *blocks) if list_mode else blocks
|
||||
|
||||
|
||||
def _build_blocks(
|
||||
claims: tuple[tuple[str, tuple[int, ...]], ...],
|
||||
indexed: list[tuple[str, Citation]],
|
||||
@@ -437,7 +470,10 @@ def _plan_answer(query: str, result: RetrievalResult, list_mode: bool) -> Answer
|
||||
layout=layout,
|
||||
reasoning_mode="synthesis" if multi_source else "direct_lookup",
|
||||
show_heading=multi_source or verbosity == "detailed",
|
||||
needs_warning=any(section in _WARNING_SECTIONS for section in sections),
|
||||
# `list_mode` always carries `_LIST_MODE_NOTICE_BLOCK` (see below) —
|
||||
# this is what gives that block its actual warning presentation in
|
||||
# the UI, not just a plain untitled bullet.
|
||||
needs_warning=list_mode or any(section in _WARNING_SECTIONS for section in sections),
|
||||
)
|
||||
|
||||
|
||||
@@ -677,7 +713,7 @@ class GroundedAnswerService:
|
||||
(text, (index,))
|
||||
for index, text in enumerate(evidence_texts, start=1)
|
||||
)
|
||||
blocks = _build_blocks(claims, indexed)
|
||||
blocks = _with_list_mode_notice(_build_blocks(claims, indexed), list_mode)
|
||||
return GroundedAnswer(
|
||||
result,
|
||||
"\n".join(text for text, _ in claims),
|
||||
@@ -724,7 +760,7 @@ class GroundedAnswerService:
|
||||
if 1 <= index <= len(indexed)
|
||||
))
|
||||
citations = tuple(indexed[index - 1][1] for index in cited_indices)
|
||||
blocks = _build_blocks(outcome.claims, indexed)
|
||||
blocks = _with_list_mode_notice(_build_blocks(outcome.claims, indexed), list_mode)
|
||||
clean_answer = "\n".join(text for text, _ in outcome.claims)
|
||||
self._metrics.increment(metric_names.GENERATION_SERVED)
|
||||
return GroundedAnswer(
|
||||
|
||||
Reference in New Issue
Block a user