454edfa492
Weight-based dosing and multi-drug comparison were measured live and recorded as fixtures (known_gaps.jsonl) but never showed up in the canonical docs describing chat capabilities.
82 lines
4.4 KiB
Markdown
82 lines
4.4 KiB
Markdown
# Pipeline RAG và chat
|
|
|
|
> Loại chính: Explanation
|
|
> Đối tượng: backend/RAG engineer
|
|
|
|
## Một lượt hỏi diễn ra thế nào
|
|
|
|
1. Browser gửi message tới Next.js BFF `/api/chat`.
|
|
2. BFF tạo/chuyển correlation ID và gọi `POST /v1/rag/query`.
|
|
3. Query understanding xác định scope, intent, drug candidates, thuộc tính, route
|
|
và dữ kiện lâm sàng còn thiếu.
|
|
4. Deterministic guard chặn câu ngoài phạm vi hoặc yêu cầu làm rõ trước retrieval.
|
|
5. Router chọn đường drug + section, overview similarity hoặc condition → drug.
|
|
6. Retrieval lấy chunks, hydrate context và tạo evidence có provenance.
|
|
7. Evidence policy quyết định đủ bằng chứng, cần xem PDF hay phải abstain.
|
|
8. Generator tạo claims có source IDs khi generation được bật.
|
|
9. Validator kiểm tra citation, con số, semantic support và completeness; có repair
|
|
có giới hạn, sau đó fail closed nếu vẫn sai.
|
|
10. Backend ghi trace/hội thoại, trả decision/reason/answer/citations; BFF map sang DTO UI.
|
|
|
|
## Retrieval routes
|
|
|
|
Khi drug và section đã rõ, filter payload theo `drug_id` + `section_key` được ưu
|
|
tiên để tránh chunk gần nghĩa của thuốc khác. Similarity search dùng cho overview
|
|
hoặc khi section chưa rõ. Rerank mặc định tắt và chỉ áp dụng trên đường
|
|
similarity/overview, không áp dụng route section chính xác.
|
|
|
|
Câu hỏi condition → drug thử keyword trước, chỉ fallback dense khi không có
|
|
candidate keyword. Candidate phải tiếp tục được kiểm tra indication và safety;
|
|
retrieval match không được biến thành khuyến cáo điều trị.
|
|
|
|
## Decision
|
|
|
|
| Decision | Ý nghĩa |
|
|
|---|---|
|
|
| `answerable` | có answer đã vượt qua các cổng kiểm tra |
|
|
| `clarify` | thiếu dữ kiện; có thể kèm quick replies |
|
|
| `verify_pdf` | đã có evidence nhưng nguồn bảng/công thức cần đối chiếu PDF |
|
|
| `abstain` | không phát hành nội dung chuyên môn cho lượt này |
|
|
|
|
## Conversation state
|
|
|
|
Conversation turns được lưu PostgreSQL theo `conversation_id` và dùng lại trong
|
|
multi-turn. Store hoạt động fail-open để lỗi history không làm sập toàn bộ query.
|
|
Một phần state chống clarify loop nằm trong process; đây chưa phải state phân tán
|
|
bền vững giữa nhiều replica. Circuit breaker dừng chuỗi clarify không hội tụ.
|
|
|
|
## Lịch sử truy vấn & duyệt chuyên luận
|
|
|
|
`conversation_id` là session id sinh phía client và giữ trong `localStorage`
|
|
của `apps/web` (không phải server session — hệ thống chưa có auth). `GET
|
|
/v1/rag/history` liệt kê lại các truy vấn cũ của đúng session đó cho Sidebar,
|
|
để bấm lại một câu hỏi cũ; answer prose không được lưu nên đây là re-run, không
|
|
phải replay.
|
|
|
|
`response_mode: "monograph"` là lối đi song song với hỏi-đáp AI: bỏ qua
|
|
generation/grounding, cho người dùng tự chọn section rồi đọc verbatim qua
|
|
`GET /v1/rag/sections` + `/section-text`. Hữu ích khi cần đối chiếu nguyên văn
|
|
thay vì câu trả lời tổng hợp.
|
|
|
|
## Output cho UI
|
|
|
|
Response mang business `trace_id`, `correlation_id`, `otel_trace_id`, decision,
|
|
reason, answer, resolved drug, citations, blocks, answer plan, candidate assessments,
|
|
quick replies và disclaimer cố định. Citation giữ chunk, printed page, physical page,
|
|
source crop/attachment và thông tin drug/section/source document.
|
|
|
|
## Giới hạn đã biết
|
|
|
|
Hai năng lực dưới đây **chưa có code path**, đo trực tiếp qua live query (không
|
|
suy đoán) và ghi lại làm fixture tại `apps/ai-service/evals/known_gaps.jsonl` để
|
|
tái kiểm chứng thay vì chỉ dựa trên tuyên bố:
|
|
|
|
- **Tính liều theo cân nặng.** `rag/calculators.py::body_surface_area_m2()` tồn
|
|
tại nhưng không được `agent.py` gọi trên đường xử lý thật — hỏi liều theo cân
|
|
nặng vẫn quay lại hỏi tuổi thay vì tính ra số.
|
|
- **So sánh nhiều thuốc.** Không có `turn_type` hay đường xử lý riêng cho so
|
|
sánh thuộc tính giữa 2+ thuốc; đường 2-thuốc duy nhất hiện có
|
|
(`agent.py::_interaction`) chỉ xử lý tương tác thuốc-thuốc, không tổng quát
|
|
hoá được. Hệ thống trả lời trung thực "chưa đủ cơ sở" thay vì bịa bảng so sánh.
|
|
|