Wire up query history: localStorage session persistence + sidebar UI

This commit is contained in:
2026-08-14 17:44:36 +07:00
parent 9be5819710
commit 057d4ed9dc
23 changed files with 1231 additions and 30 deletions
+37 -3
View File
@@ -28,6 +28,7 @@ from .clinical import ConditionRelation, MedicationCandidateAssessment
from .models import EvidenceDecision, RetrievalResult
from .policy import looks_non_human
from .service import RetrievalService
from .text import normalize_name
from .understanding import QueryFrame, QueryUnderstander
logger = logging.getLogger(__name__)
@@ -53,6 +54,27 @@ MAX_LLM_CALLS_PER_TURN = 8
# turns on the same conversation, force a hard stop instead of asking again.
MAX_CONSECUTIVE_CLARIFY = 4
# Feature-List #18/#19: "out_of_scope" used to cover two different things
# with one identical message that named neither — a question about data
# the formulary genuinely never contains for ANY drug (price, vendor,
# brand availability), and a question with nothing to do with drugs at
# all. Found live 2026-08-14 asking both "Paracetamol giá bao nhiêu?" and
# "Thời tiết Hà Nội hôm nay?" and getting the same vague "nằm ngoài phần
# chuyên luận... có thể thuộc phụ lục chưa được đưa vào" — which reads as
# "maybe added later" for data that will never be in a drug formulary.
# Deliberately a keyword heuristic, same trade-off as policy.py's
# looks_non_human: cheap, auditable, no model call on the abstain path.
_OUT_OF_SCOPE_DATA_PHRASES = (
"gia bao nhieu", "gia ca", "gia tien", "bao nhieu tien",
"mua o dau", "ban o dau", "nha thuoc nao ban",
"thuong hieu nao", "hang san xuat", "nha san xuat",
)
def _looks_like_missing_data_question(query: str) -> bool:
normalized = normalize_name(query)
return any(phrase in normalized for phrase in _OUT_OF_SCOPE_DATA_PHRASES)
class ConversationStore(Protocol):
"""Durable, cross-worker alternative to the in-process history dict —
@@ -404,11 +426,23 @@ class RagAgent:
turn_type=tt)
if tt == "out_of_scope":
if _looks_like_missing_data_question(turn):
return AgentReply(
"abstain", "out_of_scope",
answer="Dược thư Quốc gia Việt Nam KHÔNG chứa giá bán, nơi bán "
"hay thương hiệu/nhà sản xuất cụ thể của thuốc — đây "
"không phải nội dung sách này tra cứu (sách chỉ có chỉ "
"định, liều dùng, chống chỉ định, tương tác thuốc và các "
"mục chuyên môn khác). Vui lòng tra các nguồn khác cho "
"thông tin này.",
turn_type=tt)
return AgentReply(
"abstain", "out_of_scope",
answer="Nội dung này nằm ngoài phần chuyên luận thuốc của Dược thư "
"(có thể thuộc phần hướng dẫn chung/phụ lục ca được đưa vào). "
"Tôi chưa có dữ liu để trả lời chính xác.",
answer="Câu hỏi này nằm ngoài phạm vi hỗ trợ của hệ thống. Hệ "
"thống chỉ tra cứu thông tin thuốc theo Dược t Quốc gia "
"Việt Nam 2018 — chỉ định, liu dùng, chống chỉ định, tác "
"dụng phụ, tương tác thuốc và các mục chuyên môn khác của "
"một thuốc cụ thể.",
turn_type=tt)
if not frame.drugs: