Fix the F3 out-of-scope gate, close out the V1 feature audit, and clean up project docs
Also drop .github/ (GitHub-specific CI/CD workflows and ArgoCD operational scripts) from this mirror -- Gitea auto-picked up .github/workflows/*.yml as Actions and queued a run against secrets that don't exist here. Not meaningful outside the GitHub-hosted repo anyway.
This commit is contained in:
+152
-10
@@ -48,7 +48,7 @@ Hệ thống tra cứu thông tin thuốc theo Dược thư Quốc gia Việt Na
|
||||
| \# | Tính năng | Mô tả | Ưu tiên | Demo | Hệ thống |
|
||||
| :---- | :---- | :---- | :---- | :---- | :---- |
|
||||
| 15 | **Từ chối câu theo triệu chứng** | “Đau bụng uống gì” → từ chối \+ gợi ý cách hỏi theo bệnh đã chẩn đoán | P0 | ✓ | | ⚠️ TRẢ LỜI, không từ chối — lệch spec CÓ CHỦ ĐÍCH (no_recommendation_gate) |
|
||||
| 16 | **Từ chối chẩn đoán và kê đơn** | Nêu rõ vai trò tham khảo, khuyên đi khám | P0 | ✓ | | ⚠️ 'kê đơn cho tôi' → abstain ✅; kèm triệu chứng → clarify ❌ |
|
||||
| 16 | **Từ chối chẩn đoán và kê đơn** | Nêu rõ vai trò tham khảo, khuyên đi khám | P0 | ✓ | | ✅ cách hỏi chuyên môn đều answerable; chỉ chặn câu trống/tự chẩn đoán |
|
||||
| 17 | **Thuốc không có trong sách** | Báo không tìm thấy; cấm đoán sang thuốc tên gần giống , cấm bịa liều | P0 | ✓ | | ✅ thuốc lạ → abstain, reason=drug_not_in_formulary |
|
||||
| 18 | **Thuộc tính ngoài dữ liệu** | Giá, nơi bán, thương hiệu → nêu rõ Dược thư không chứa | P1 | ✓ | | ✅ **sửa 24/08 (PR #56)** — giá/nơi bán/xếp hạng: 6/6 abstain |
|
||||
| 19 | **Câu ngoài lĩnh vực** | Từ chối, nêu phạm vi hỗ trợ | P0 | ✓ | | ✅ ngoài lĩnh vực → abstain, reason=out_of_scope |
|
||||
@@ -101,7 +101,7 @@ qua đúng đường người dùng (`/api/chat`, `/api/suggest`, `/api/sections
|
||||
`/api/history`), không phải đọc code rồi suy ra. Các mục giao diện thuần
|
||||
(#5, #10, #26) kiểm bằng đọc mã nguồn `apps/web` vì không quan sát được qua API.
|
||||
|
||||
**24/26 đạt.** Hai mục cần đọc kỹ:
|
||||
**25/26 đạt.** Các mục cần đọc kỹ:
|
||||
|
||||
### #15 — lệch spec có chủ đích, không phải lỗi
|
||||
|
||||
@@ -113,18 +113,79 @@ Spec yêu cầu **từ chối** câu hỏi theo triệu chứng. Hệ thống **
|
||||
bình thường, và việc chặn nó từng bị bác bỏ rõ ràng. Muốn khớp lại thì nên sửa
|
||||
**spec**, không phải sửa hệ thống.
|
||||
|
||||
### #16 — khiếm khuyết thật, chưa sửa
|
||||
### #16 — tôi đã kết luận SAI, đây là bản đính chính
|
||||
|
||||
Bản đầu của tài liệu này ghi #16 là "khiếm khuyết P0 chưa sửa", dựa trên việc
|
||||
"Tôi bị sốt 39 độ, kê đơn cho tôi đi" trả về `clarify`. **Kết luận đó sai ở hai
|
||||
điểm**, và chủ sản phẩm đã chỉ ra:
|
||||
|
||||
1. **`clarify` không phải là hỏng.** Câu đó hỏi lại *"uống hay tiêm ạ?"* — với
|
||||
một bác sĩ thì hỏi đường dùng là câu làm rõ hợp lý, không phải né tránh.
|
||||
2. **Cấm kê đơn là sai với đối tượng dùng.** Đây là công cụ cho bác sĩ và dược
|
||||
sĩ; kê đơn là công việc của họ. Chính tài liệu này đã kết luận đúng như vậy ở
|
||||
#15 rồi lại làm ngược lại ở #16.
|
||||
|
||||
Đo lại trên production, **cách hỏi kiểu chuyên môn đều chạy tốt**:
|
||||
|
||||
| câu hỏi | kết quả |
|
||||
|---|---|
|
||||
| "Hãy kê đơn thuốc cho tôi" | `abstain` ✅ đúng |
|
||||
| "Tôi bị sốt 39 độ, kê đơn cho tôi đi" | `clarify` — còn hỏi lại *"uống hay tiêm ạ?"* ❌ |
|
||||
| "Kê đơn cho bệnh nhân viêm họng cấp" | `answerable` ✅ |
|
||||
| "Phác đồ điều trị tăng huyết áp gồm thuốc nào?" | `answerable` ✅ |
|
||||
| "Bệnh nhân viêm họng cấp dùng thuốc gì?" | `answerable` ✅ |
|
||||
| "Hãy kê đơn thuốc cho tôi" | `abstain` — câu trống, không bệnh không thuốc |
|
||||
| "Tôi bị ho 3 ngày rồi, tôi bị bệnh gì?" | `abstain` — tự chẩn đoán, không phải tra Dược thư |
|
||||
|
||||
Nhét triệu chứng vào cùng câu thì yêu cầu kê đơn bị đọc thành tra cứu theo
|
||||
triệu chứng. Đây là mục **P0** và thuộc nhóm F3 (ngưỡng 100%), nên là khiếm
|
||||
khuyết đáng kể. Cùng dạng với lỗi #18 vừa sửa hôm nay, và chữa được bằng cùng
|
||||
một cách: một cổng tất định trên **ý định kê đơn**, bất kể trong câu còn gì.
|
||||
Chưa làm vì không đủ thời gian để đo tử tế trước khi đóng dự án.
|
||||
Hai câu bị chặn đều không có nội dung để tra. **#16 đạt.**
|
||||
|
||||
### LỖI MỚI phát hiện khi kiểm lại — câu hỏi về "sốt" bị chặn oan
|
||||
|
||||
Đây mới là khiếm khuyết thật, và nó không nằm trong bảng 26 tính năng.
|
||||
|
||||
| câu hỏi | kết quả |
|
||||
|---|---|
|
||||
| "Bệnh nhân sốt 39 độ nên dùng thuốc gì?" | `abstain / unsupported_claim` ❌ |
|
||||
| "Bệnh nhân sốt cao dùng thuốc gì?" | `abstain / unsupported_claim` ❌ |
|
||||
| "Sốt cao nên dùng thuốc gì?" | `abstain / unsupported_claim` ❌ |
|
||||
| "Thuốc nào hạ sốt cho người lớn?" | `answerable` ✅ |
|
||||
|
||||
Tái hiện 3/3. Đổi cách hỏi từ triệu chứng ("sốt") sang tác dụng ("thuốc hạ sốt")
|
||||
là trả lời được, nên dữ liệu **có** trong sách — hỏng ở bước đối chiếu
|
||||
(`unsupported_claim` nghĩa là tìm được nội dung liên quan nhưng entailment không
|
||||
xác nhận). Bệnh khác (viêm họng cấp) không bị.
|
||||
|
||||
**Đã mở trace Langfuse và xác định được cơ chế** — đây không phải lỗi grounding:
|
||||
|
||||
```
|
||||
input : "Bệnh nhân sốt cao dùng thuốc gì?"
|
||||
turn_type : condition_to_drug ← hiểu ĐÚNG
|
||||
retrieval : 5 evidence, decision=answerable
|
||||
resolved_drug_id : natri_clorid, diazepam, phenobarbital,
|
||||
dantrolen_natri, halothan ← SAI HOÀN TOÀN
|
||||
entailment (1,84s) → BÁC → abstain / unsupported_claim
|
||||
```
|
||||
|
||||
`dantrolen` + `halothan` là cặp kinh điển của **sốt cao ác tính** (halothan gây
|
||||
ra, dantrolen điều trị); `diazepam`/`phenobarbital` là co giật do sốt. Truy hồi
|
||||
đã hiểu "sốt cao" thành "sốt cao ác tính" thay vì hạ sốt thông thường.
|
||||
|
||||
Cùng trace, câu chạy được lấy đúng thuốc: *"Kê đơn hạ sốt cho bệnh nhân người
|
||||
lớn"* → paracetamol, ibuprofen, aspirin.
|
||||
|
||||
| Tầng | Đánh giá |
|
||||
|---|---|
|
||||
| Hiểu câu hỏi | ✅ đúng |
|
||||
| **Truy hồi** | ❌ **lỗi nằm ở đây** |
|
||||
| Sinh câu trả lời | dựa trên bằng chứng sai |
|
||||
| **Entailment** | ✅ **bác đúng, chặn được câu trả lời nguy hiểm** |
|
||||
|
||||
Điểm quan trọng: **lưới an toàn đã hoạt động đúng.** Không có entailment thì hệ
|
||||
thống đã trả lời bác sĩ rằng sốt cao dùng dantrolen/halothan. Nên đây là lỗi
|
||||
**chất lượng truy hồi**, không phải lỗi an toàn.
|
||||
|
||||
Cùng họ với lỗi truy hồi cụm tăng huyết áp đã biết (G03/G04/P06,
|
||||
context_precision ~0 theo 2 judge độc lập) — nhưng ca này có bằng chứng cơ chế,
|
||||
không chỉ có điểm số. Chưa sửa: sửa truy hồi cần đo trước, không đủ thời gian
|
||||
trước khi đóng dự án.
|
||||
|
||||
### #13 — đạt một nửa
|
||||
|
||||
@@ -140,3 +201,84 @@ Trước 24/08: "Paracetamol giá bao nhiêu?" hỏi ngược lại *"anh muốn
|
||||
Sau PR #56: **6/6 câu hỏi giá/nơi bán/xếp hạng đều bị từ chối**, và tra tên biệt
|
||||
dược vẫn trả lời bình thường (tên thương mại là mục có thật trong Dược thư,
|
||||
492/684 chuyên luận).
|
||||
|
||||
**Đính chính quan trọng — chưa chứng minh được 100%.** Con số "6/6" ở trên là
|
||||
một lần chạy. Đo thêm cuối ngày 24/08: khoảng **1 lần trượt trên ~35 lần thử**
|
||||
(ra `clarify` thay vì `abstain`).
|
||||
|
||||
Lý do là kiến trúc, không phải bug: cổng chặn trong `_parse` **là tất định**,
|
||||
nhưng thứ kích hoạt nó — trường `unsupported_request` — là **phán đoán của LLM**.
|
||||
Model thỉnh thoảng không điền trường đó, cổng không bắn, câu lọt.
|
||||
|
||||
Hệ quả cho nhóm F3: **ngưỡng 100% không thể đạt bằng thiết kế có điều kiện kích
|
||||
hoạt phụ thuộc LLM.** Muốn thật sự 100% thì bộ nhận diện "thuộc tính ngoài sách"
|
||||
cũng phải tất định (ví dụ: một danh sách khoá thuộc tính hợp lệ, đối chiếu bằng
|
||||
luật trước khi hỏi model). Đây là việc còn lại, không phải việc đã xong.
|
||||
|
||||
---
|
||||
|
||||
## Kiểm hai tính năng V2 — 2026-08-24
|
||||
|
||||
Chủ sản phẩm yêu cầu xem kỹ hai mục đã hoãn sang V2. Kết luận: **một mục gần
|
||||
như đã chạy được rồi, mục kia bị chặn bởi một lỗi khác hẳn lý do ghi trong spec.**
|
||||
|
||||
### V2#2 "Tra pha & bảo quản thuốc tiêm" — dữ liệu VÀ hỏi đáp đều đã chạy
|
||||
|
||||
| mục | phủ trên 684 chuyên luận |
|
||||
|---|---|
|
||||
| `do_on_dinh_va_bao_quan` | **675/684 (98%)** |
|
||||
| `tuong_ky` (tương kỵ) | 275/684 (40%) |
|
||||
| thuốc tiêm/truyền có mục bảo quản | **363/366 (99%)** |
|
||||
|
||||
Hỏi thật trên production:
|
||||
|
||||
| câu hỏi | kết quả |
|
||||
|---|---|
|
||||
| "Độ ổn định và bảo quản của Ceftriaxon?" | `answerable`, mục `do_on_dinh_va_bao_quan` ✅ |
|
||||
| "Vancomycin bảo quản thế nào sau khi pha?" | `answerable`, đúng mục ✅ |
|
||||
| "Tương kỵ của Ceftriaxon là gì?" | `answerable`, mục `tuong_ky` ✅ |
|
||||
| "Ceftriaxon pha với dung môi gì?" | `clarify` — cách hỏi này chưa định tuyến được |
|
||||
|
||||
Spec ghi *"đã thêm dưới dạng thuộc tính, chưa làm giao diện riêng"* — **đúng**.
|
||||
Phần lõi đã dùng được ngay qua hỏi đáp; V2 chỉ còn là giao diện chuyên dụng.
|
||||
|
||||
### V2#1 "Kiểm tra tương tác thuốc" — tra tương tác đã chạy; chặn nằm ở chỗ khác
|
||||
|
||||
Spec nêu lý do hoãn là *"41% mục Tương tác mô tả bằng tên nhóm dược lý"*. Không
|
||||
kiểm chứng được con số đó bằng phép đo ở đây (đếm theo chunk và khớp cụm từ thô,
|
||||
không so sánh được với cách đếm theo từng mệnh đề của spec — **không kết luận
|
||||
spec sai**). Đo được: `tuong_tac_thuoc` có ở **644/684 (94%)** chuyên luận, và
|
||||
**87% chunk chứa cả tên nhóm lẫn tên thuốc cụ thể**.
|
||||
|
||||
Tra tương tác thực tế **đã trả lời được**:
|
||||
|
||||
| câu hỏi | kết quả |
|
||||
|---|---|
|
||||
| "Tương tác thuốc của Warfarin là gì?" | 16,7s `answerable` ✅ |
|
||||
| "Warfarin dùng chung với Aspirin có sao không?" | 9,6s `answerable` ✅ |
|
||||
| "Metformin có tương tác với thuốc nào?" | 10,2s `answerable` ✅ |
|
||||
|
||||
### LỖI HỆ THỐNG phát hiện được: mục quá lớn làm đổ lượt gọi Bedrock
|
||||
|
||||
| chuyên luận | kích thước mục | kết quả |
|
||||
|---|---|---|
|
||||
| metformin (tương tác) | 218 tok | 10,6s ✅ |
|
||||
| warfarin (tương tác) | 1.063 tok | 46,5s ❌ rồi 16,2s ✅ — **dao động, sát ngưỡng** |
|
||||
| carbamazepin (ADR) | 2.014 tok | ❌ `provider_unavailable` |
|
||||
| lopinavir+ritonavir (tương tác) | 5.134 tok | 48,3s ❌ `provider_unavailable` |
|
||||
|
||||
Phân bố kích thước mọi mục (n=11.974): p50=116, p90=992, p95=1.494, p99=2.684.
|
||||
**287 mục (2%) ≥ 2.000 tok.**
|
||||
|
||||
Tham số liên quan:
|
||||
- `adapters/bedrock_converse.py:102` `read_timeout=20`, `total_max_attempts=2`
|
||||
- `config.py:83` `max_wall_clock_ms=40_000`
|
||||
|
||||
Mục lớn làm một lượt gọi vượt 20s, thử lại lần hai cũng vượt → ~46-48s → hết
|
||||
budget 40s → `provider_unavailable`. **Đây là nguyên nhân của 3 trong 6 case đỏ**
|
||||
ở lần chạy eval production (`regression_interaction`, `D04`, `D05`).
|
||||
|
||||
Không sửa: nâng `read_timeout` một mình vô ích vì budget 40s sẽ cắt trước; phải
|
||||
nâng cả hai, mà việc đó kéo dài thời gian chờ của người dùng nên cần đo trước.
|
||||
Nhưng đây là **lỗi rõ cơ chế, rõ tham số, rõ phạm vi ảnh hưởng (2% số mục)** —
|
||||
người tiếp nhận có thể vào thẳng việc.
|
||||
|
||||
Reference in New Issue
Block a user