45 KiB
BÁO CÁO KIỂM KÊ TÍNH NĂNG VÀ TRIỂN KHAI
Nền tảng chatbot RAG Dược thư Quốc gia Việt Nam 2018
| Thuộc tính | Giá trị |
|---|---|
| Dự án | VSF-DUOCTHU |
| Kỳ báo cáo | 30/07/2026–13/08/2026 |
| Ngày chốt kiểm kê | 13/08/2026 |
| Đối tượng trình bày | Quản lý kỹ thuật, quản lý sản phẩm, hội đồng đánh giá |
| Phạm vi | Source code, dữ liệu đã xử lý, kiểm thử, CI/CD, hạ tầng và vận hành |
| Trạng thái Git tại thời điểm kiểm kê | 88 commit trong kỳ; 413 file được Git theo dõi |
| Tác giả commit trong kỳ | BaoVu2k4 |
1. Mục đích báo cáo
Báo cáo này trả lời năm câu hỏi quản trị:
- Hệ thống hiện giải quyết bài toán gì và dành cho ai?
- Những tính năng nào đã được triển khai trong code và đang nằm trên đường runtime?
- Hệ thống được đưa từ PDF nguồn đến chatbot và production bằng cách nào?
- Bằng chứng nào cho thấy các thành phần đang hoạt động?
- Những giới hạn, rủi ro và hạng mục tiếp theo là gì?
Báo cáo chủ động phân biệt bốn trạng thái để tránh báo cáo vượt quá thực tế:
| Nhãn | Ý nghĩa |
|---|---|
| Đang dùng trên runtime | Có wiring từ entrypoint tới implementation và có test hoặc bằng chứng vận hành |
| Đã triển khai trong code | Có implementation và test, nhưng có thể cần cấu hình hoặc chưa có bằng chứng production đầy đủ |
| Deployment kit | Có manifest/workflow phục vụ triển khai, nhưng chưa được chứng minh đã áp dụng vào môi trường đích |
| Chưa hoạt động | Mới là scaffold, thử nghiệm, dead code hoặc kế hoạch |
Nguồn sự thật ưu tiên theo thứ tự: code tại Git HEAD → workflow/config đang được runtime dùng → test chạy lại tại ngày kiểm kê → handoff/progress log có bằng chứng → tài liệu kế hoạch.
2. Tóm tắt điều hành
Trong hai tuần, dự án được xây dựng lại từ đầu và đi từ monorepo scaffold đến một nền tảng RAG có thể phục vụ tra cứu Dược thư bằng hội thoại. Các kết quả chính:
- Xây dựng pipeline PDF deterministic cho Dược thư 1.668 trang.
- Phân đoạn 684 chuyên luận thuộc Part 2 của sách.
- Tạo và nạp 15.100 chunks vào Qdrant collection
duocthu_v1. - Xây dựng FastAPI AI service với query understanding, retrieval, generation, grounding, citation, abstention và multi-turn.
- Xây dựng Next.js web chat với evidence panel, PDF deep-link và feedback.
- Bổ sung luồng condition/disease → medication dựa riêng trên mục
Chỉ định. - Container hóa toàn bộ runtime bằng Docker Compose và Caddy HTTPS.
- Bổ sung Prometheus, Grafana, Tempo và OpenTelemetry.
- Bổ sung CI, deploy, rollback và Qdrant snapshot migration workflow.
- Xây dựng Helm chart làm migration kit cho Kubernetes/ArgoCD.
Theo hồ sơ trong repository, hệ thống đã được triển khai trên một EC2 cá nhân tại https://realvuxbaro.me. Báo cáo này không thực hiện kiểm tra trực tiếp website tại thời điểm lập báo cáo, do đó đây là trạng thái được xác nhận từ workflow và handoff đã lưu trong repository, không phải một uptime attestation tại ngày 13/08.
Kết quả kiểm tra lại trên workspace ngày 13/08:
| Hạng mục | Kết quả |
|---|---|
| AI service pytest | 278 passed, 6 skipped |
| Ingestion pytest | 277 passed, 12 skipped |
| Tổng Python test pass | 555 |
| Frontend ESLint | 0 warning, 0 error |
| Frontend unit/component test | Chưa có |
3. Bài toán, người dùng và ranh giới sản phẩm
3.1 Bài toán
Dược thư Quốc gia Việt Nam 2018 là tài liệu khoảng 1.668 trang. Nội dung thuốc được tổ chức theo chuyên luận và các mục cố định như chỉ định, chống chỉ định, thận trọng, liều dùng, tương tác và phản ứng có hại. Việc tra cứu thủ công chậm và dễ bỏ sót mục liên quan.
Hệ thống cung cấp giao diện hội thoại tiếng Việt để:
- Xác định thuốc và mục thông tin người dùng cần tra.
- Truy xuất đoạn nguồn từ Dược thư.
- Trình bày lại câu trả lời với citation tới đúng trang và đoạn bằng chứng.
- Từ chối hoặc yêu cầu đối chiếu PDF nếu bằng chứng không đủ an toàn.
3.2 Người dùng mục tiêu
- Bác sĩ.
- Dược sĩ.
- Nhân sự chuyên môn cần tra cứu nội dung Dược thư.
UI và prompt giữ thuật ngữ chuyên môn, không chủ động đơn giản hóa thành hướng dẫn tự điều trị cho người phổ thông.
3.3 Phạm vi hiện tại
Đang hỗ trợ:
- 684 chuyên luận thuốc thuộc Part 2, trang in 99–1496.
- Tra cứu theo thuốc và theo mục.
- Tương tác hai thuốc.
- Một số câu hỏi condition → medication có bằng chứng ở mục
Chỉ định. - Context bệnh nhân có cấu trúc để cảnh báo hoặc yêu cầu thêm dữ kiện.
Không hỗ trợ hoặc không tuyên bố hỗ trợ:
- Part 1: chương nguyên tắc, đối tượng đặc biệt, ngộ độc và nội dung tổng quan.
- Part 3: phụ lục BSA, tương hợp thuốc tiêm, ATC index.
- Kê đơn, xếp hạng thuốc hoặc khuyến cáo first-line.
- Reverse lookup “thuốc nào gây X” hoặc “thuốc nào chống chỉ định trong X”.
- Tính liều tự động.
- Thú y hoặc chủ thể không phải người.
- Đọc tự động số liệu từ bảng/công thức 2D đã bị quarantine.
4. Kiến trúc tổng thể
flowchart LR
U[Người dùng chuyên môn] -->|HTTPS| C[Caddy]
C --> W[Next.js Web/BFF]
W -->|POST /v1/rag/query| A[FastAPI AI Service]
A --> Q[(Qdrant 15.100 chunks)]
A --> P[(PostgreSQL)]
A --> B[AWS Bedrock]
A --> M[Prometheus metrics]
A --> O[OTel Collector]
O --> T[Tempo]
M --> G[Grafana]
T --> G
PDF[Dược thư PDF] --> I[Offline ingestion]
I --> Q
4.1 Thành phần runtime
| Thành phần | Công nghệ | Trạng thái | Trách nhiệm |
|---|---|---|---|
apps/web |
Next.js 14, React 18, TypeScript | Đang dùng | Chat UI, BFF, PDF route, feedback route, rate limit |
apps/ai-service |
Python, FastAPI | Đang dùng | Query understanding, orchestration, retrieval, generation, grounding, traces |
| Qdrant | Qdrant v1.19.0 ở chart | Đang dùng | Vector và payload corpus |
| PostgreSQL | PostgreSQL 16 | Đang dùng | Retrieval trace, conversation turn, correlation và feedback |
| AWS Bedrock | Cohere embedding/rerank, Converse model | Đang dùng khi provider bật | Query embedding, hiểu câu hỏi, sinh và kiểm tra câu trả lời |
| Caddy | Caddy 2 | Đang dùng theo production config | Reverse proxy và TLS |
| Prometheus | Prometheus | Đã triển khai trong config | Metrics và PromQL |
| Tempo | Grafana Tempo | Đã triển khai trong config | Distributed trace |
| Grafana | Grafana | Đã triển khai trong config | Dashboard và Explore |
| OTel Collector | OpenTelemetry Collector | Đã triển khai trong config | Nhận và export span |
4.2 Thành phần chưa xây dựng
Các thư mục sau chỉ có README.md và package.json tối thiểu, không có source runtime:
apps/api-gateway.apps/auth-service.apps/user-service.apps/chat-service.apps/mobile.
Vì vậy web hiện gọi trực tiếp AI service và không có authentication/authorization.
5. Kiểm kê pipeline dữ liệu và ingestion
5.1 Nguồn dữ liệu
- PDF: Dược thư Quốc gia Việt Nam 2018.
- Số trang vật lý: 1.668.
- Phạm vi chuyên luận được ingest: Part 2.
- Số chuyên luận runtime: 684.
- Artifact verified gồm danh mục thuốc, formula regions và outlined-text transcriptions.
5.2 Luồng xử lý
flowchart TD
PDF[PDF nguồn] --> PM[Page map]
PDF --> SP[Extract spans]
SP --> GO[Glyph/reading-order scan]
SP --> VT[Merge vector-outlined transcriptions]
PDF --> TB[Detect/lift table regions]
PDF --> FR[Verified 2D formula regions]
VT --> SG[Segment monographs/sections]
TB --> SG
FR --> SG
SG --> CK[Section-aware chunking]
CK --> RD[Readiness and coverage gates]
RD --> EM[Embedding]
EM --> Q[Qdrant upsert]
Q --> MF[Manifest sidecar]
5.3 Extraction và sửa lỗi PDF
Đang dùng trong pipeline:
- PyMuPDF span extraction.
- Page map giữa trang vật lý và trang in.
- Kiểm tra glyph order và reading order.
- Merge lại 51 text runs chỉ tồn tại dưới dạng vector outline.
- Tách table/formula region khỏi prose trước khi phân đoạn.
- Giữ bbox và page provenance.
Nguyên tắc an toàn:
- Không tự sửa vùng công thức 2D chỉ dựa trên thứ tự text extraction.
- Không biến bảng không chắc chắn thành prose giả.
- Region không thể tái tạo đáng tin được đánh dấu quarantine.
- Quarantined block vẫn được gắn với chunk để UI chỉ người dùng tới ảnh/PDF gốc.
5.4 Phân đoạn chuyên luận
Pipeline xử lý:
- Tiêu đề chuyên luận nhiều dòng.
- Chuyên luận nhóm có nhiều mã ATC.
- Mã ATC có khoảng trắng hoặc nhầm O/0 từ PDF.
- Part divider không được coi nhầm thành tên thuốc.
- Section vocabulary và section order.
- Đơn vị và chuỗi liều dùng nhạy cảm.
- Duplicate drug ID là lỗi chặn, không silently overwrite.
5.5 Chunking
- Chunk theo ranh giới section thay vì chia đều toàn văn bản.
- Có token estimate và oversized detection.
- Có chunk kind riêng cho prose và block descriptor.
- Prose chunk có thể tham chiếu attachment table/formula.
- Citation giữ trang in, trang vật lý, bbox và block ID.
- Context header của bảng có thể được gắn khi chunk liên quan.
5.6 Validation gates
Các công cụ validation hiện có:
- Back-index recall/precision.
- Span-level coverage ledger.
- Residual-ink scan.
- Table/formula region audit.
- Chunk readiness metrics.
- Clinical readiness checks.
- Token and oversized chunk checks.
- Golden/scaffold utilities ở các mức hoàn thiện khác nhau.
Một số CLI được khai báo nhưng tài liệu trong code vẫn ghi chưa hoàn thiện hoàn toàn; do đó không được mô tả toàn bộ validation CLI là production-complete.
5.7 Embedding và load
- Adapter Cohere embeddings qua AWS Bedrock.
- Vector dimension: 1.024.
- Qdrant collection:
duocthu_v1. - Số points theo README/handoff: 15.100.
- Upsert có batch và repository abstraction.
- Payload index được định nghĩa theo schema corpus.
- Manifest sidecar lưu corpus hash/model/dimension.
- AI service kiểm manifest lúc startup và từ chối chạy nếu mismatch.
Giá trị kỹ thuật: Qdrant có thể trả kết quả bình thường dù corpus được embed bằng model khác; manifest check biến lỗi chất lượng âm thầm thành lỗi startup rõ ràng.
6. Kiểm kê query understanding và orchestration
6.1 Query understanding
Đang dùng trên runtime khi generator được cấu hình:
- Chuẩn hóa câu hỏi thành structured frame.
- Xác định subject scope.
- Xác định intent và turn type.
- Xác định tên thuốc hoặc condition.
- Xác định section/facet cần tra.
- Nhận biết population, route, age, weight và context phụ thuộc turn trước.
- Tạo standalone query cho follow-up.
- Sinh clarification khi thiếu dữ kiện.
6.2 Entity resolution và autocomplete
- Danh mục 684 thuốc và hơn 10.000 alias theo tài liệu hiện tại.
- Catalog được nạp từ
drug_entities.json. - Candidate gửi vào LLM được giới hạn deterministic.
- Canonical name luôn được ưu tiên để tránh danh sách alias toàn biệt dược khó nhận biết.
- Autocomplete chạy local/deterministic, không gọi model.
- Autocomplete khớp token đang gõ thay vì toàn bộ câu.
6.3 Multi-turn
conversation_idtối đa 128 ký tự.- Raw turns được lưu trong PostgreSQL.
- Structured prior frame và clarify streak hiện vẫn giữ trong memory process.
- Follow-up có thể kế thừa thuốc hoặc field đã trả lời ở turn trước.
- Clarify loop circuit breaker dừng vòng hỏi lặp vô hạn.
Giới hạn: structured frame không được chia sẻ giữa nhiều replica; scale ngang có thể làm chất lượng multi-turn không ổn định.
6.4 Routing
Các nhóm routing chính:
- Drug overview.
- Drug attribute/section lookup.
- Dosage-related query.
- Two-drug interaction.
- Condition → drug indication lookup.
- Condition relation không được hỗ trợ.
- Out-of-scope hoặc non-human.
- Clarification khi thiếu thuốc hoặc dữ kiện lâm sàng.
6.5 Request budget
- Mặc định tối đa 40.000 ms wall-clock ở backend.
- Mặc định tối đa 8 LLM calls/turn.
- Provider timeout/retry được kiểm soát.
- Bedrock read timeout riêng có retry cho lỗi đọc cô lập.
- Reason code phân biệt hết budget, provider outage, malformed output và lỗi nội dung.
7. Kiểm kê retrieval
7.1 Section retrieval
- Khi biết đúng thuốc và section, retrieval dùng Qdrant payload filter.
- Không phụ thuộc hoàn toàn vào vector similarity cho câu hỏi section rõ ràng.
- Section resolver chuẩn hóa các cách hỏi tiếng Việt.
- Rerank không chạy trên section route vì section route đã deterministic.
7.2 Similarity/overview retrieval
- Query embedding bằng Cohere qua Bedrock.
- Dense vector search trên Qdrant.
- Rerank tùy cấu hình bằng Cohere reranker.
- Token-budget packing chọn evidence vừa context.
- Có fallback overview/rerank.
7.3 Lexical retrieval
- Có lexical search dùng token match và Python re-scoring.
- Đây không phải BM25 hoàn chỉnh: chưa có IDF, term frequency hoặc length normalization chuẩn.
- Hiệu lực của
MatchTextphụ thuộc full-text index của payload field; cần tiếp tục xác minh collection đang deploy.
7.4 Parent/child và neighbour pooling
- Có parent store/hydration abstraction.
- Corpus hiện không phát
parent_id, nên parent hydration hầu như không tạo năng lực thực tế. - Section-neighbour pooling hiện chỉ được mở có giới hạn cho một số trường hợp như
thận trọng.
7.5 Module có code nhưng chưa nối runtime
rag/fusion.py: Reciprocal Rank Fusion.rag/expansion.py: query/sibling expansion.rag/calculators.py: DuBois body-surface-area calculator.
Các module này có test nhưng không có runtime caller; không được báo cáo là tính năng người dùng đang sử dụng.
8. Kiểm kê generation, grounding và guardrails
8.1 Provider modes
AI service hỗ trợ các cấu hình:
disabled: không có conversational agent/generation.stub: local test không gọi cloud.bedrock-claude.bedrock-converse.
Model ID là cấu hình; code default hiện là deepseek.v3.2, nhưng model production thực tế phụ thuộc environment ngoài Git.
8.2 Structured answer contract
Thay vì model trả prose tự do có marker [n], response nội bộ gồm:
- Answer plan.
- Answer blocks.
- Claims.
source_idstheo từng claim.- Candidate assessments khi là condition → medication.
UI hiển thị cấu trúc đã được backend xác minh; không tự parse semantics từ prose.
8.3 Numeric grounding
- Mọi số trong claim phải có trong evidence thực.
- Không dùng “global number pool” để cho phép số từ evidence không được citation.
- Số phải thuộc evidence mà claim tham chiếu.
- Sai số liệu dẫn tới
ungrounded_numbervà câu trả lời bị hủy.
8.4 Citation validation
- Citation index/chunk ID phải tồn tại.
- Claim không có citation bị hủy.
- Citation phải trỏ tới đúng evidence.
- Với condition → medication, citation phải thuộc đúng thuốc của claim.
- Thuốc ngoài candidate set retrieval bị hủy bằng
unsupported_drug.
8.5 Entailment và completeness
- Có một LLM entailment pass kiểm ngữ nghĩa phi số.
- Có completeness check/repair cho câu trả lời thiếu dữ kiện liên quan.
- Provider outage không còn bị báo nhầm thành “nội dung không được nguồn hỗ trợ”.
- Một entailment pass không phải bằng chứng hoàn hảo; accuracy của judge chưa có benchmark committed đầy đủ.
8.6 Abstention
Các nhóm lý do từ chối:
- Không resolve được thuốc.
- Câu hỏi mơ hồ.
- Ngoài phạm vi hoặc non-human.
- Xin khuyến nghị điều trị.
- Retrieval score không đủ.
- Thiếu provenance.
- Bảng/công thức cần kiểm tra PDF.
- Provider unavailable.
- Hết request budget.
- Invalid citation/uncited claim.
- Unsupported claim/drug.
- Incomplete answer.
BFF có bản đồ thông báo tiếng Việt riêng cho reason code, tránh biến mọi lỗi thành “không có dữ liệu trong Dược thư”.
8.7 Prompt injection và disclaimer
- User text được đặt trong fenced region.
- Marker có thể bị người dùng chèn vào được loại bỏ trước khi tạo prompt.
- System prompt quy định vùng này là dữ liệu, không phải chỉ thị.
- Output grounding vẫn là lớp bảo vệ chính.
- Disclaimer là chuỗi cố định từ backend, không do model tạo.
- BFF có fallback disclaimer để version skew không làm response y khoa mất cảnh báo.
9. Condition/disease → medication
9.1 Mục tiêu
Mở rộng chatbot từ “biết tên thuốc rồi tra thông tin” sang “condition nào có thuốc được Dược thư ghi chỉ định”. Đây là factual evidence lookup, không phải recommendation engine.
9.2 Luồng retrieval
flowchart TD
Q[Condition query] --> N[Normalize condition/relation]
N --> A{Mơ hồ đáng kể?}
A -->|Có| C[Clarify subtype]
A -->|Không| L[Lexical search trong chi_dinh]
L -->|Không đủ| D[Dense fallback trong chi_dinh]
L --> GR[Group theo drug_id]
D --> GR
GR --> CAP[Rank/cap drug candidates]
CAP --> PC{Có patient context?}
PC -->|Không| G[Grounded list]
PC -->|Có| S[Safety second stage]
S --> G
9.3 Safety second stage
Khi query có dữ kiện bệnh nhân, hệ thống có thể kiểm top candidates theo:
- Thuốc đang dùng và interaction evidence.
- Contraindication/precaution.
- Renal/hepatic context.
- Thai kỳ/cho con bú.
- Tuổi và cân nặng.
- Dị ứng/ADR trước đó.
Status có thể gồm:
- Supported.
- Supported with caution.
- Requires additional information.
- Insufficient evidence.
Hệ thống không tự kết luận “contraindicated” chỉ từ lexical hit và không tự tạo dose adjustment không có trong corpus.
9.4 Evaluation status
- Có
condition_to_drug_v1.jsonl: 20 case trọng tâm. - Có
production_manual_60.jsonl: 60 case manual battery. - Theo handoff, 20/20 case unique đầu tiên đã pass sau fix.
- 40 case còn lại chưa được chạy ở thời điểm handoff.
- Có deploy smoke hỏi về đợt gout cấp và yêu cầu
decision=answerablecùng citationsection_key=chi_dinh.
Không nên tuyên bố feature đạt production-quality toàn diện trước khi chạy đủ battery và có baseline lưu được.
10. Kiểm kê API
10.1 FastAPI endpoints
| Method | Endpoint | Chức năng | Trạng thái |
|---|---|---|---|
| GET | /health |
Liveness | Đang dùng |
| GET | /ready |
Readiness | Đang dùng |
| GET | /metrics |
OpenMetrics, bearer token tùy chọn | Đang dùng khi metrics bật |
| POST | /v1/rag/query |
Query RAG/conversation | Đang dùng |
| GET | /v1/rag/suggest |
Drug autocomplete | Đang dùng |
| POST | /v1/rag/feedback |
Lưu rating/comment theo trace | Đang dùng |
10.2 Query request contract
query: 1–4.000 ký tự.subject_scope: enum.intent: enum.conversation_id: tùy chọn, tối đa 128 ký tự.
10.3 Query response contract
Response có:
trace_id,correlation_id,otel_trace_id.decision,reason.answer,resolved_drug_id.citationsvới chunk/page/bbox/evidence/drug/section.generatedphân biệt paraphrase đã verify và extractive.quick_replies.- Structured
blocksvàanswer_plan. candidate_assessments.disclaimertrên mọi decision.
10.4 Web BFF routes
| Method | Route | Chức năng |
|---|---|---|
| POST | /api/chat |
Validate input, correlation, gọi AI service và map DTO |
| GET | /api/suggest |
Proxy autocomplete |
| POST | /api/feedback |
Proxy feedback |
| GET | /api/pdf |
Phục vụ PDF nguồn cho citation viewer |
11. Kiểm kê frontend
11.1 Màn hình
/: chat workspace./tra-cuu: split view chat/PDF phục vụ đối chiếu nguồn.
11.2 Thành phần chính
- Sidebar phiên tra cứu.
- Chat panel.
- Composer.
- Prompt/quick-reply chips.
- Evidence panel.
- Citation cards.
- Citation beam overlay.
- Disclaimer banner.
- Answer feedback.
- Theme context/selector.
11.3 Citation experience
- Citation được group theo chunk để không hiện trùng prose và attachment ref.
- Evidence card hiển thị thuốc, section, trang và exact retrieved text.
- Attachment giữ trang vật lý riêng khi bảng nằm ở trang khác prose.
- Quarantined content có cảnh báo và link tới PDF gốc.
- Click citation của message cũ dùng đúng citation array của message đó.
11.4 Reliability fixes
- Không mất message khi đổi session.
- Abort/disconnect từ browser được propagate lên BFF fetch.
- Client timeout được điều chỉnh để không hủy response tốt khi backend còn trong budget.
- Refusal messages ánh xạ reason code cụ thể.
- Version skew vẫn giữ disclaimer.
11.5 Rate limiting
| Route | Giới hạn hiện tại |
|---|---|
/api/chat |
12/phút và 120/giờ/IP |
/api/suggest |
120/phút/IP |
/api/pdf |
30/phút/IP |
/api/feedback |
60/phút/IP |
Rate limit lưu trong memory của một web process. Đây là cost/abuse guard, không phải security control; scale nhiều replica cần Redis hoặc gateway.
12. Persistence và audit trail
12.1 PostgreSQL migrations
| Migration | Nội dung |
|---|---|
001_rag_retrieval_trace.sql |
Retrieval trace |
002_rag_conversation_turn.sql |
Conversation history |
003_rag_trace_correlation.sql |
Correlation và OTel trace ID |
004_rag_answer_feedback.sql |
Answer feedback |
12.2 Retrieval trace
Trace lưu các trường phục vụ audit như:
- Query.
- Resolved drug.
- Decision/reason.
- Citation/evidence.
- Correlation ID.
- OpenTelemetry trace ID.
12.3 Conversation history
- Lưu raw turn trong PostgreSQL.
- Query understanding có thể đọc recent turns.
- Trace/history persistence fail-open: lỗi DB không nhất thiết chặn câu trả lời.
12.4 Feedback
- Rating:
helpfulhoặcnot_helpful. - Comment tối đa 2.000 ký tự.
- Upsert theo trace.
- Theo handoff, production feedback smoke đã lưu thành công một bản ghi.
12.5 Giới hạn dữ liệu
- Chưa có retention/deletion policy.
- Chưa có redaction PII/patient context.
- Chưa có conversation ownership.
- PostgreSQL connection mở theo call, chưa có pool.
13. Observability
13.1 Metrics
Prometheus exporter theo dõi:
- Request count và latency.
- Duration từng RAG stage.
- Routing decisions/reasons.
- Provider failures.
- Trace write failures.
- Grounding/answer domain counters.
13.2 Tracing
OpenTelemetry trace bao phủ:
- Receive.
- Understanding.
- Routing.
- Retrieval.
- Rerank/evidence.
- Generation.
- Grounding/entailment.
- Persistence.
- Response.
Correlation và trace ID đi từ BFF tới AI service và PostgreSQL.
13.3 Grafana/Tempo
- Prometheus datasource được provision.
- Tempo datasource được provision.
- Dashboard
duocthu-observabilityđược provision. - Grafana có thể truy cập theo đường
/grafana/trong Caddy config production. - Prometheus không được expose public theo thiết kế.
13.4 Ba lớp provenance
- UI citation/evidence panel: người dùng thấy nguồn đã chọn.
- Tempo trace: kỹ sư thấy stage nào đã chạy và mất bao lâu.
- PostgreSQL trace: audit record bền và có thể join theo trace ID.
Hệ thống không lưu chain-of-thought; không đưa patient text vào metric labels/span names.
13.5 Khoảng trống observability
- Chưa Alertmanager/alert rules.
- Chưa log aggregation.
- Web chưa được instrument đầy đủ.
- Chưa có SLO/error budget.
- Một số metric cũ được đăng ký nhưng không increment.
14. Security và safety
14.1 Đã có
- HTTPS qua Caddy.
- Bedrock dùng EC2 IAM instance role, không cần long-lived AWS key trên host.
- Input length validation.
- Rate limit tại web middleware.
- Prompt injection fencing.
- Numeric/citation/entailment guardrails.
- Optional bearer token cho
/metrics. - Grafana anonymous access tắt ở production overlay.
- Prometheus/Grafana native ports có thể chỉ bind loopback.
- Secret có thể lấy từ GitHub Actions/Kubernetes Secret.
14.2 Chưa có
- Authentication.
- Authorization/RBAC.
- Per-user session ownership.
- API gateway thực.
- NetworkPolicy cho Kubernetes.
- Container securityContext/runAsNonRoot trong chart.
- Dependency scanning/SBOM.
- Security headers đầy đủ.
- Secret rotation/retention runbook hoàn chỉnh.
- Patient-data retention/redaction policy.
14.3 Rủi ro ưu tiên
- Endpoint công khai có thể bị bất kỳ ai gọi.
conversation_iddo client tự chọn và không có ownership check.- Một số default password trong Compose/Helm không phù hợp production mới.
- Container image hiện chạy root.
- In-memory rate limiting không bảo vệ khi scale nhiều replica.
15. Local development
15.1 Prerequisites
- Python 3.11+.
- Node.js 20 và pnpm.
- Docker.
- AWS credentials/IAM có quyền Bedrock nếu cần generation.
- Corpus Qdrant đã load hoặc snapshot restore.
15.2 Khởi động datastore
docker compose -f infra\docker\docker-compose.yml up -d postgres qdrant
15.3 AI service
cd apps\ai-service
python -m migrate
python -m uvicorn main:app --port 8079
Không khuyến nghị --reload trên Windows trong dự án này vì đã quan sát trường hợp reloader phục vụ code cũ.
15.4 Web
corepack enable
pnpm install
pnpm --filter @duoc-thu/web dev
15.5 Observability local
docker compose -f infra\docker\docker-compose.yml up -d `
prometheus tempo otel-collector grafana
15.6 Test
cd apps\ai-service
python -m pytest tests -q
cd ..\..\ingestion
python -m pytest tests -q
cd ..
corepack pnpm --filter @duoc-thu/web lint
corepack pnpm --filter @duoc-thu/web build
Integration tests cần datastore/provider live có thể skip theo điều kiện.
16. Production deployment hiện tại
16.1 Topology theo repository
- Một EC2
t3.largetạius-east-1theo handoff. - Docker Compose.
- PostgreSQL named volume.
- Qdrant named volume.
- AI service container.
- Web container.
- Caddy reverse proxy/TLS.
- Observability overlay.
- AWS Bedrock qua instance role.
16.2 Deploy workflow
Trigger:
- Push vào
mastervới path thuộc runtime/deploy scope. - Manual
workflow_dispatch.
Path filter bao gồm:
apps/ai-service/**.apps/web/**.packages/**.ingestion/data/verified/drug_entities.json.infra/docker/**.- Chính
deploy.yml.
Docs-only push không còn tự redeploy production.
16.3 Các bước deploy
flowchart TD
P[Push master] --> F[Path filter]
F --> SSH[SSH EC2]
SSH --> R[git fetch/reset target]
R --> D[Docker Compose up -d --build]
D --> C[Caddy validate/reload]
C --> MIG[Run migrations]
MIG --> H[Health/ready/web checks]
H --> CS[Condition retrieval smoke]
CS --> OBS[Prometheus/Tempo/Grafana checks]
OBS --> TR[Generate and verify exact trace]
16.4 Post-deploy verification
- AI service
/health. - AI service
/ready. - Web root.
- Condition query phải
answerable. - Citation phải có
section_key=chi_dinh. - Prometheus ready.
- Tempo ready với retry.
- Grafana health/datasources/dashboard.
- Public Grafana login route.
- Tạo request có correlation ID.
- Kiểm tra
X-Trace-IDđúng 32 hex characters. - Xác minh metric xuất hiện trong Prometheus.
- Xác minh trace đọc được trong Tempo.
16.5 Rollback
- Workflow manual nhận
target_sha. - Verify target là commit.
- Reset/rebuild về target.
- Chạy lại migrations idempotent hiện có.
- Verify health và Grafana.
Giới hạn: rollback không tự động khi deploy fail; image được build lại trên host, không phải immutable artifact. Migration chưa có down migration.
16.6 Qdrant snapshot migration
- Workflow one-off tạo snapshot production.
- Download qua Qdrant HTTP API.
- Chuyển snapshot thành GitHub artifact/thực hiện bridge sang practice environment.
- Ghi nhận Qdrant version trước snapshot.
- Tránh re-embed và chi phí Bedrock.
17. CI/CD
17.1 CI workflow
Chạy trên mọi push và pull request:
| Job | Checks |
|---|---|
| AI service | Ruff + pytest |
| Ingestion | Pytest |
| Web | Install lockfile + lint + production build |
CI dùng concurrency cancel-in-progress theo branch/ref.
17.2 Điểm cần lưu ý
deploy.yml trigger độc lập với ci.yml; không có needs: nối deploy với CI. Vì vậy một push master có thể khởi chạy CI và deploy song song. Đây chưa phải “test gate trước production” theo nghĩa chặt.
Khuyến nghị ưu tiên cao:
- Dùng reusable workflow hoặc workflow_run.
- Chỉ deploy commit có CI success.
- Build immutable images trong CI.
- Tag theo commit SHA.
- Push registry.
- Rollback bằng image đã biết tốt thay vì rebuild.
18. Helm/Kubernetes/ArgoCD
18.1 Helm chart hiện có
Chart infra/helm/medical-chatbot chứa:
- AI service Deployment/Service.
- Web Deployment/Service.
- PostgreSQL workload/storage.
- Qdrant workload/storage.
- Ingress.
- Secret hoặc existing Secret.
- ServiceAccount.
- Prometheus, Tempo, OTel Collector, Grafana.
- ServiceMonitor tùy chọn.
18.2 Khả năng cấu hình
- Bật/tắt
aiServicevàweb. - Bật/tắt PostgreSQL, Qdrant và observability.
- Dùng PostgreSQL ngoài release qua
secret.postgresHost. - Dùng external Qdrant URL.
- Cấu hình
ENTITIES_PATHtrong image. - Image/tag/pull policy theo môi trường.
- Resource requests/limits.
- Ingress/TLS.
- Existing Kubernetes Secret cho staging/prod.
18.3 Trạng thái thật
Helm chart là deployment/migration kit, chưa có bằng chứng đã được apply thành công lên k3s/ArgoCD trong repository hiện tại.
Chart mặc định cũng chưa tự tạo corpus. Qdrant mới sẽ rỗng và AI service manifest check sẽ từ chối startup. Cần snapshot restore hoặc corpus-load Job trước khi chart có thể vận hành end-to-end.
18.4 Hạng mục trước khi apply
- Registry và immutable image tags.
- Corpus restore/load Job.
- Secret management chuẩn.
- Security context.
- NetworkPolicy.
- PodDisruptionBudget/HPA nếu cần.
- Backup strategy.
- Helm lint/template trong CI.
- ArgoCD Application values và image promotion flow.
19. So sánh với dự án cũ D:\AITT_VSF
19.1 Những cải tiến thực sự
| Lĩnh vực | Dự án cũ | Dự án mới |
|---|---|---|
| Ingestion | Nhiều lỗi bảng/công thức/heading phát hiện muộn | Rebuild với full-document survey, quarantine và readiness gates |
| Data safety | Một số lỗi extraction có thể lọt vào corpus | Residual-ink scan, vector transcription và VERIFY_PDF |
| Query experience | Chủ yếu drug-centric | Structured conversational understanding và multi-turn |
| Condition lookup | Primitive/chưa tạo UX hoàn chỉnh | Indication-only condition→drug với patient-context second stage |
| Answer contract | Extractive/summary với validator | Structured claim–citation, candidate-set guard, entailment/completeness |
| Production proof | Workflow/Compose có nhưng trạng thái tài liệu không nhất quán | Có handoff deploy, smoke, trace và observability production |
| Observability | Chưa có stack end-to-end tương đương | Metrics + tracing + dashboard + DB audit |
| Feedback | Chưa có | Feedback theo trace |
| Python tests | Khoảng 197 test definitions ở HEAD cũ | 555 test pass khi kiểm kê mới |
19.2 Những điểm dự án cũ đang tốt hơn
- Hybrid dense+sparse và RRF đã nằm trên đường retrieval cũ; dự án mới chưa nối RRF runtime.
- BSA calculator cũ được route; calculator mới hiện là dead code.
- Dự án cũ có frontend Vitest; dự án mới không có frontend tests.
- CI cũ khai báo deploy
needsbackend/frontend; CI mới chưa gate deploy. - Dự án cũ có
uv.lock; dự án mới chưa có Python lockfile. - Dự án cũ hướng đến corpus rộng hơn; dự án mới chủ động giới hạn Part 2.
19.3 Kết luận so sánh
Dự án mới phát triển hơn ở ba trục cốt lõi:
- Độ tin cậy dữ liệu: phát hiện và quarantine thay vì serialize sai.
- An toàn câu trả lời: structured grounding và fail-closed sâu hơn.
- Vận hành: production traceability và observability tốt hơn.
Tuy nhiên cần mang lại ba năng lực tốt từ dự án cũ: hybrid retrieval thật, frontend tests và CI bắt buộc xanh trước deploy.
20. Chất lượng và bằng chứng kiểm thử
20.1 Test inventory
- AI service: unit, API, agent, routing, policy, grounding, generation, Qdrant adapter, condition flow, observability và prompt injection.
- Ingestion: extraction, glyph order, formula, segmentation, tables, chunking, validation, embed adapters và Qdrant load.
- Web: lint/build trong CI, chưa có test runner.
20.2 Kết quả ngày kiểm kê
AI service: 278 passed, 6 skipped
Ingestion: 277 passed, 12 skipped
Web lint: no warnings or errors
20.3 Ý nghĩa của skipped tests
Skipped tests không được coi là pass. Chúng thường yêu cầu:
- Qdrant live.
- PostgreSQL live.
- Provider/cloud access.
- Integration flag.
Kết quả 555 pass chứng minh unit/offline suite hiện xanh; không chứng minh toàn bộ production integrations hoặc chất lượng lâm sàng.
20.4 Evaluation assets
- Golden CSVs cho entity, intent, summary, multi-turn và E2E.
- JSONL manual/adversarial/condition cases.
- Condition evaluation summarizer.
- Manual battery script.
Khoảng trống: chưa có một evaluation runner duy nhất chạy mọi dataset trên runtime thật, lưu baseline và fail CI khi chất lượng giảm.
21. Known limitations và technical debt
21.1 P0 – cần xử lý trước khi mở rộng người dùng
- Authentication/authorization chưa có.
- CI chưa chặn deploy production.
- Chưa có backup tự động cho PostgreSQL và Qdrant.
- Default credentials trong config mẫu cần loại bỏ khỏi mọi production path.
- Chưa có ownership và retention cho conversation data.
21.2 P1 – ảnh hưởng reliability/scale
- Structured multi-turn state nằm trong memory process.
- PostgreSQL chưa có connection pool.
- Python dependencies chưa có lockfile.
- Frontend không có test.
- Evaluation chưa thành regression gate.
- Rate limit không chia sẻ giữa replicas.
- No streaming và latency có thể cao.
21.3 P2 – chất lượng và completeness
- Hybrid retrieval/RRF chưa nối runtime.
- Query expansion chưa nối runtime.
- BSA calculator chưa nối runtime.
- Part 1/Part 3 chưa ingest.
- Quarantined tables/formulas chưa được reconstruct.
- Web chưa có telemetry.
- Chưa có alerts/SLO.
21.4 Rủi ro claim sản phẩm
Không nên nói:
- “Chatbot biết toàn bộ Dược thư” — hiện chỉ Part 2.
- “Chatbot tư vấn thuốc” — hệ thống chỉ factual lookup.
- “Kubernetes đã production” — mới là deployment kit.
- “Hybrid search đang chạy” — chưa nối runtime mới.
- “Tính được liều/BSA” — calculator chưa được gọi.
- “Condition-to-drug đã eval đủ” — mới ghi nhận 20/60 manual cases.
- “Mọi test đều chạy” — có integration tests skipped.
22. Đề xuất roadmap
Giai đoạn 1 – Production safety gate
- Nối CI success vào deploy.
- Build/push immutable images.
- Backup PostgreSQL/Qdrant và restore drill.
- Chuyển toàn bộ credential sang secret store.
- Bổ sung frontend tests cho BFF mapping, middleware và citation state.
Giai đoạn 2 – Product access và data governance
- Xây API gateway/auth hoặc access gate tối thiểu.
- Conversation ownership.
- Retention/deletion/redaction.
- Audit roles và rate limit chia sẻ.
Giai đoạn 3 – Quality regression
- Hợp nhất eval runner.
- Chạy đủ condition manual 60.
- Baseline retrieval, grounding, abstention và latency.
- Gate theo nhóm critical sections.
- Human clinical review sampling.
Giai đoạn 4 – Retrieval and performance
- Xác minh full-text payload index.
- Nối native sparse/BM25 và RRF.
- Cache safe deterministic routes.
- PostgreSQL pool.
- Streaming hoặc staged response.
Giai đoạn 5 – Kubernetes migration
- Registry và image promotion.
- Snapshot restore Job.
- Helm CI.
- Security hardening.
- Staging deploy.
- ArgoCD rollout và rollback drill.
Giai đoạn 6 – Corpus expansion
- Thiết kế riêng cho Part 1 và Part 3.
- Không ép appendix/table vào cùng schema prose của Part 2.
- Bổ sung source-grounded eval trước khi mở query surface.
23. Bộ chỉ số đề xuất báo cáo định kỳ
23.1 Product
- Số queries/ngày.
- Tỷ lệ answerable/clarify/abstain/verify_pdf.
- Feedback helpful rate.
- Clarification turns/query.
- Citation click-through.
23.2 Quality
- Retrieval hit@k/MRR theo section.
- Citation validity.
- Numeric grounding pass rate.
- Entailment pass/reject rate.
- Condition-to-drug candidate precision.
- Regression theo critical section.
23.3 Reliability
- Availability.
- P50/P95/P99 latency.
- Provider failure rate.
- Request budget exhaustion rate.
- Trace write failure rate.
- Qdrant/PostgreSQL error rate.
23.4 Cost
- LLM calls/turn.
- Embedding/rerank calls.
- Bedrock cost/query.
- EC2/storage cost.
- Re-embedding avoided qua snapshot/reuse.
23.5 Data
- Corpus points và manifest version.
- Quarantined blocks.
- Coverage/monograph count.
- Unclassified residual-ink regions.
- Failed ingestion gates.
24. Kịch bản trình bày 10 phút
Phút 0–1: Bài toán
“Dược thư dài 1.668 trang và thông tin được chia theo chuyên luận, section và bảng. Mục tiêu không chỉ là tìm gần đúng mà là trả lời có thể truy ngược tới đúng nguồn.”
Phút 1–3: Điểm khó nhất – dữ liệu
Trình bày:
- Hai cột, bảng nối trang, công thức 2D, vector-outlined text.
- Vì sao hệ thống quarantine thay vì đoán.
- Manifest mismatch protection.
Phút 3–5: RAG và safety
Trình bày pipeline:
understand → route → retrieve → generate → ground → entail → cite/abstain
Nhấn mạnh mỗi claim có citation, số phải có trong evidence và unsupported drug bị chặn.
Phút 5–6: Tính năng người dùng
- Multi-turn.
- Evidence panel/PDF.
- Condition → medication.
- Feedback.
Phút 6–8: Production và observability
- Docker/Caddy/EC2.
- CI/deploy/rollback.
- Prometheus/Tempo/Grafana/PostgreSQL trace.
Phút 8–9: Bằng chứng
- 15.100 Qdrant points.
- 555 Python tests pass.
- Frontend lint sạch.
- Production smoke và trace workflow.
Phút 9–10: Trung thực về khoảng trống
- Chưa auth.
- Chưa CI gate deploy.
- Chưa frontend tests.
- Chưa hybrid runtime mới.
- K8s chưa apply.
Kết thúc bằng roadmap ba ưu tiên: production gate, access control và quality regression.
25. Câu hỏi quản lý có thể hỏi và câu trả lời đề xuất
“Có đang tư vấn điều trị không?”
Không. Sản phẩm tra cứu factual content trong Dược thư. Prompt cấm first-line/treatment-of-choice; câu xin recommendation bị từ chối.
“Làm sao biết model không bịa số?”
Mỗi số phải xuất hiện trong evidence mà claim citation. Nếu không, response bị hủy với ungrounded_number trước khi tới người dùng.
“Nếu bảng PDF bị đọc sai thì sao?”
Bảng/công thức 2D không đủ tin cậy được quarantine. Hệ thống trả VERIFY_PDF hoặc cảnh báo và dẫn tới đúng trang nguồn, không tự rút số.
“Có thể audit một câu trả lời production không?”
Có ba lớp: citation UI, Tempo trace và PostgreSQL retrieval trace, liên kết qua trace/correlation ID.
“Hệ thống đã sẵn sàng scale chưa?”
Chưa hoàn toàn. Runtime hiện phù hợp single-host/single-replica. Structured multi-turn state và rate limit còn in-memory; Postgres chưa pool.
“Kubernetes chạy chưa?”
Chưa có bằng chứng apply. Helm chart là migration kit; cần image registry, corpus restore Job và hardening trước staging.
“Điểm hơn dự án cũ là gì?”
Data safety, structured grounding và production observability. Điểm cần học lại từ dự án cũ là hybrid retrieval, frontend test và gated deploy.
“Rủi ro lớn nhất hiện nay?”
Không có auth/ownership trên endpoint công khai, CI chưa chặn deploy và chưa có backup/restore automation.
26. Kết luận
Trong kỳ 30/07–13/08/2026, dự án đã hoàn thành một vòng xây dựng end-to-end từ PDF đến giao diện chat và hạ tầng production. Giá trị nổi bật không chỉ nằm ở khả năng sinh câu trả lời, mà ở việc thiết kế hệ thống có thể từ chối, truy nguồn và điều tra khi câu trả lời không đủ an toàn.
Trạng thái phù hợp nhất để báo cáo là:
Một nền tảng RAG Dược thư Part 2 đã có runtime, kiểm thử, deployment và observability; đang ở giai đoạn hardening trước khi mở rộng người dùng, scale hoặc chuyển sang Kubernetes/GitOps chính thức.
Ba ưu tiên tiếp theo:
- Bắt buộc CI xanh trước deploy và tạo rollback artifact bất biến.
- Thêm access control, ownership và data governance.
- Biến golden/manual evaluation thành quality regression gate.
Phụ lục A – File/source quan trọng
| Phạm vi | File/thư mục |
|---|---|
| Runtime assembly | apps/ai-service/bootstrap.py |
| FastAPI entrypoint | apps/ai-service/main.py |
| RAG API | apps/ai-service/routers/rag.py |
| Agent | apps/ai-service/rag/agent.py |
| Retrieval | apps/ai-service/rag/service.py |
| Generation/verification | apps/ai-service/rag/answer.py |
| Grounding | apps/ai-service/rag/grounding.py |
| Query understanding | apps/ai-service/rag/understanding.py |
| Condition contracts | apps/ai-service/rag/clinical.py |
| Qdrant adapter | apps/ai-service/adapters/qdrant.py |
| PostgreSQL adapter | apps/ai-service/adapters/postgres.py |
| Ingestion CLI | ingestion/ingestion/cli.py |
| Web chat page | apps/web/app/page.tsx |
| Web BFF | apps/web/app/api/chat/route.ts |
| Rate limit | apps/web/middleware.ts |
| Production Compose | infra/docker/docker-compose.prod.yml |
| Observability overlay | infra/docker/docker-compose.observability.yml |
| Deploy | .github/workflows/deploy.yml |
| CI | .github/workflows/ci.yml |
| Rollback | .github/workflows/rollback.yml |
| Snapshot migration | .github/workflows/migrate-qdrant-snapshot.yml |
| Helm chart | infra/helm/medical-chatbot/ |
Phụ lục B – Quy ước quyết định trả lời
| Decision | Ý nghĩa |
|---|---|
answerable |
Có evidence và answer vượt guardrails |
clarify |
Cần người dùng bổ sung dữ kiện |
abstain |
Không đủ điều kiện an toàn/phạm vi/provider |
verify_pdf |
Nguồn có bảng/công thức cần đối chiếu bản gốc |
Phụ lục C – Checklist trước khi demo
- Xác nhận production URL đang reachable.
- Xác nhận
/healthvà/ready. - Xác nhận Grafana login và datasource.
- Chọn trước ba câu hỏi demo: drug section, multi-turn, condition lookup.
- Chọn một case
VERIFY_PDFđể thể hiện safety. - Chuẩn bị trace ID để mở trong Tempo.
- Không demo câu hỏi đang nằm trong known flaky/unsupported scope.
- Không trình chiếu secrets, environment file hoặc patient data thật.
- Nêu rõ Part 2 scope và disclaimer.
- Chốt roadmap/đề nghị nguồn lực ở slide cuối.