№ 63
MindCare AI là nền tảng AI hỗ trợ chăm sóc sức khỏe tinh thần, kết hợp sàng lọc cảm xúc, tư vấn AI và quản lý các trường hợp cần hỗ trợ để can thiệp sớm và hiệu quả.
Tài liệu này mô tả các chức năng hiện có của hệ thống MindCare AI / CBT Assistant dựa trên mã nguồn trong repository hiện tại. Nội dung tập trung vào module, luồng nghiệp vụ, API, database, UI và các quy tắc xử lý chính.
MindCare AI là hệ thống hỗ trợ sức khỏe tinh thần dựa trên CBT (Cognitive Behavioral Therapy). Hệ thống kết hợp chatbot AI, phân loại rủi ro an toàn trước khi phản hồi, và cơ chế đưa chuyên viên vào vòng xử lý khi người dùng có dấu hiệu rủi ro.
Đối tượng sử dụng:
Hệ thống giải quyết các vấn đề chính:
MindCare AI giải quyết bài toán hỗ trợ sức khỏe tinh thần cho người dùng cần một kênh tiếp cận nhanh, riêng tư và có định hướng CBT, nhưng vẫn phải bảo đảm an toàn khi nội dung chat có dấu hiệu rủi ro.
Các vấn đề chính hệ thống đang xử lý:
Bài toán không chỉ là xây dựng một chatbot. Đây là hệ thống hỗ trợ tinh thần có kiểm soát rủi ro, có phân quyền, có dữ liệu vận hành, có human-in-the-loop và có khả năng mở rộng sang quy trình chuyên viên thật.
Hệ thống được đánh giá bằng bộ script $0 (tái dùng dự đoán offline + regex/DB thật, không tốn thêm chi phí GPU) trên 5 nhóm: benchmark offline có baseline, an toàn của gate kết hợp, các chỉ số tin cậy phụ, red-team, và KPI production từ DB thật.
Test set: eval-model/.../cbt_test.jsonl (3,467 mẫu; subset M4 N=998, 147 mẫu khủng hoảng). So sánh 4 model ứng viên (qwen2.5-7b / llama3.1-8b / mistral-7b / gemma2-9b) qua 4 giai đoạn tăng dần (M1 → M4) — đây chính là phần baseline comparison:
| Stage | Cấu hình | Thư mục |
|---|---|---|
| M1 | Base model | eval_model_base |
| M2 | + fine-tune | eval_model_finetune |
| M3 | + RAG (bge-m3 + reranker + Qdrant, gated) | eval_model_finetune_rag |
| M4 | + agent (ReAct: multi-hop retrieval + self-reflection) — cấu hình deployed | eval_model_finetune_rag_agent |
cbt-qwen2.5-7b-v2là biến thể fine-tune của winner qwen2.5-7b (nguồn:EVALUATION.mdtrong repo).
Winner (M4, qwen2.5-7b):
| Group | Metric | Value |
|---|---|---|
| Risk | accuracy / macro-F1 | 97.1% / 97.9% |
| Risk | crisis recall (model alone) | 96.6% |
| Safety | unsafe / diagnosis / medication violation | 0.6% / 0.1% / 0.0% |
| Technique | accuracy | 33.5% |
| Quality (LLM-judge 1–5) | empathy / boundary / clarity / tone | 4.14 / 4.98 / 4.68 / 4.25 |
| Quality (LLM-judge 1–5) | CBT-align / tech-correct / helpful / overall | 2.47 / 1.82 / 2.50 / 3.55 |
| RAGAS | faithfulness / answer-rel / context-prec | 0.04 / 0.29 / 0.79 |
| Agent | mean hops / rewrite / reflect / revise | 1.52 / 66% / 19% / 3% |
backend/scripts/regex_safety_eval.py ($0 — reuses M4 preds + live regex):
| Layer | Crisis recall (L0+L1) | False-positive (L2/L3→L0/L1) |
|---|---|---|
| Regex only | 12.2% | 3.6% |
| Model only | 96.6% | 0.1% |
| Combined (deployed) | 99.3% (146/147) | 3.8% |
The combined gate reaches 99.3% crisis recall on N=147 — only 1 crisis fully missed. The regex layer adds ~3.7% false-positives (over-triage) and can cap a true-L0 at L1 (still safe: no AI auto-reply). Note the benchmark input is long intake prose; production chat messages are short/direct where the regex backstop catches substantially more.
backend/scripts/extra_metrics.py:
| Metric | Value |
|---|---|
| Escalation precision / recall / F1 | 99.3% / 96.6% / 97.9% |
| Scope-router accuracy (personal/meta/off-topic) | 95.5% (21/22) |
| Draft diversity (lexical, 50 sessions) | 0.78 |
| PII leakage in responses | 0% (0/181) |
| Production grounding (Draft.hallucination_score) | mean 0.06 (empathic replies → few factual claims) |
| Calibration (ECE) | N/A — model emits a bare risk label, no probability |
backend/scripts/final_eval.py — adversarial inputs (jailbreak, prompt
injection, self-harm method requests, harmful off-topic): 10/10 handled
safely (caught or redirected; none complied). Small N — a sanity check, to be
expanded.
backend/scripts/final_eval.py / agent_trace_eval.py:
| KPI | Value |
|---|---|
| Clinician decisions | approve 82.4% · edit 17.6% · reject 0% |
| Agent uptime on L2/L3 | 88.7% (47/53) |
| Tool-arg validity | 100% (0 malformed) |
| Orchestrator reliability | prose 46.8% · forced-generate 42.6% (degrades gracefully) |
| Thành phần | Công nghệ / thư mục | Vai trò |
|---|---|---|
| Backend API | backend/app, FastAPI | Auth, chat, screening, admin APIs, moderation, reports, logs |
| User app | user_app, React + Vite | Onboarding, chat, screening, CBT lessons, resources, consultation |
| Admin app | admin_app, React + Vite | Dashboard, user management, case, moderation, reports, settings |
| Database/migration | SQLAlchemy + Alembic | Lưu user, conversation, screening, moderation, case, content, audit |
| AI log | .ai-log, scripts/submit_log.py | Ghi và submit log AI usage lên Phoenix |
Frontend gọi backend qua /api/*; cấu hình Vite của user_app và admin_app proxy về FastAPI backend port 8000.
| Guardrail | Mechanism | Measured effect |
|---|---|---|
| Hard crisis gate | deterministic regex L0/L1 override; L0 = no AI, crisis resources shown | combined crisis recall 99.3% |
| Human-in-the-loop | L0/L1/L2 routed to a clinician; AI never auto-replies on sensitive cases | approve 82% / reject 0% |
| Anti-fabrication | preflight + grounding floor → hold for review; never auto-send a failed/ungrounded draft | gate logic |
| Agent defense-in-depth | has_acute_risk re-check before any auto-generate; agent may only escalate UP, never lower risk | escalation F1 97.9% |
| Scope guardrail | off-topic / "about-MindCare" redirected (only on safe L3; biased to "personal") | accuracy 95.5%, red-team 100% |
| PII protection | scrub before any LLM/agent call; PHI encrypted at rest | leakage 0% |
| Graceful fallback | agent failure → fixed pipeline; never blocks a response | architecture |
| Memory guard | durable user-memory present → hold for review (prevents memory-narrated fabrication) | gate logic |
| Dependency Guard | từ chối xác nhận niềm tin tiêu cực tuyệt đối; can thiệp bằng text CỐ ĐỊNH (không LLM) + ground + break + handoff; L2 mở case clinician | chống lệ thuộc/gaslighting |
| Audit trail | every triage/decision/override logged | audit_trail, triage_log |
Backend dùng FastAPI, chia router theo nghiệp vụ:
auth_intake.py: register, OTP, login, Google auth, consent, intake.chat.py: chat flow, conversation, safety gate, LLM/agent, moderation enqueue.screening.py: PHQ-9/GAD-7 và screening plan.content.py: lessons, resources, saved resources, progress.experts.py: psychologists và appointments.admin_dashboard.py, admin_users.py, admin_cases.py, ai_moderation.py, admin_reports.py, admin_settings.py, admin_logs.py: nghiệp vụ admin.backend/app/main.py cho thấy backend có bootstrapping cho Redis, MinIO, Qdrant, calibration, seed users, seed content, seed demo screenings và preload NLI grounding model.
Database dùng SQLAlchemy models và Alembic migrations. Các nhóm bảng chính:
users, roles, permissions, role_permissions, admin_users.conversations, sessions, drafts, ai_messages.review_queue, moderation_queue, moderation_reviews, ai_response_revisions, specialist_assignments.screenings, screening_plans.lessons, resources, saved_resources, user_lesson_progress, psychologists, appointments.app_settings, audit_trail, soap_notes, feedback, user_memory, intake_forms, user_profiles.Một số trường nhạy cảm được mã hóa bằng AES-GCM. Hệ thống cũng có audit trail để ghi lại hành động quan trọng của user/admin/chuyên viên.
Hệ thống model-agnostic: cả ba vai trò sinh ngôn ngữ — safety triage, orchestrator (tool-calling), responder — do một trong hai não đảm nhiệm, chọn bằng biến LLM_PROVIDER (xem tiểu mục "Kiến trúc model-agnostic" ngay dưới). Bản demo hiện chạy provider claude — Claude Sonnet 5 (/api/health báo agent: mode claude, model claude-sonnet-5); đường thay thế local dùng model fine-tune Huysun29/cbt-qwen2.5-7b-v2 (Qwen2.5-7B fine-tune trên dữ liệu hội thoại CBT, đã merge LoRA). Bất kể chạy não nào, ba model phụ trợ cho RAG và kiểm chứng luôn nằm trên Modal brain:
| Model | Vai trò |
|---|---|
Não sinh ngôn ngữ — claude-sonnet-5 (hiện tại) hoặc Huysun29/cbt-qwen2.5-7b-v2 (đường local) | Triage L0–L3, orchestrator ReAct, sinh draft CBT, vent-check, rewrite, emphasis |
BAAI/bge-m3 (Modal brain) | Embedding cho RAG (Qdrant) và session memory |
BAAI/bge-reranker-v2-m3 (Modal brain) | Rerank kết quả truy hồi |
cross-encoder/nli-deberta-v3-base (Modal brain) | NLI grounding check (chống hallucination) |
Toàn bộ được gộp vào một service GPU duy nhất trên Modal — "brain" (modal/brain_service.py, app cbt-brain): 1 container A100-80GB chạy vLLM 0.9.1 (bf16, max_model_len 8192, gpu_memory_utilization 0.85) cùng 3 sidecar embedder/reranker/NLI trên cùng GPU. Trước đây hệ thống chạy 5 service Modal tách rời (transformers thuần); kiến trúc brain thay thế toàn bộ, 5 service cũ giữ lại làm backup rollback.
6 vai trò / 7 endpoint của brain:
| Endpoint | Vai trò | Backend caller |
|---|---|---|
POST /generate | Responder — sinh n bản draft (Technique/Rationale/Plan/Response) | llm_client |
POST /assess | Safety triage — trả JSON {"level": "L0".."L3"} | safety_gate |
POST /chat | Orchestrator — tool-calling (ép prefix <tool_call>, stop </tool_call>) | agent_client |
POST /embed | BGE-M3 embeddings | embedder |
POST /rerank | Reranker scores | reranker |
POST /score | NLI raw logits + entail_idx cho grounding | hallucination_nli |
GET /health | Trạng thái, engine, danh sách role | /api/health |
Chống cold-boot-per-call: max_containers=1 + @modal.concurrent(max_inputs=16) + GPU lock — mọi lời gọi tuần tự trong một lượt chat dồn vào một container ấm thay vì autoscaler Modal mở container mới (boot ~2 phút) cho từng lời gọi. Weights cache trên volume cbt-model-cache; biến MIN_CONTAINERS=1 giữ container ấm suốt phiên demo (tắt khi nghỉ để tiết kiệm credit).
Cấu hình một nút (backend / Railway):
MODAL_BRAIN_WORKSPACE=<workspace> → tự derive đủ 7 endpoint.MODAL_BRAIN_WORKSPACE > MODAL_WORKSPACE (bộ 5 service legacy).MODAL_BRAIN_WORKSPACE, đặt lại MODAL_WORKSPACE — không đổi code.Toàn bộ các vai trò sinh ngôn ngữ giờ được trừu tượng hoá sau một provider switch. Đổi duy nhất biến LLM_PROVIDER là thay cả bộ não, không đổi dòng code nào khác:
LLM_PROVIDER | Não (responder / triage / orchestrator / vent-check / rewrite / emphasis / copilot) | Embed / Rerank / NLI |
|---|---|---|
local (mặc định) | Modal brain — cbt-qwen2.5-7b-v2 (vLLM, A100) | Modal brain (bge-m3 / reranker / NLI) |
claude | Claude Sonnet 5 (claude-sonnet-5) qua API | vẫn ở Modal brain |
Điểm mấu chốt: embed/rerank/NLI luôn nằm trên Modal brain kể cả khi chạy Claude — Anthropic không có embeddings API và index Qdrant là bge-m3 1024 chiều nên phải cùng không gian vector. Nói cách khác: Claude thay phần "suy nghĩ", Modal brain giữ phần "trí nhớ ngữ nghĩa + kiểm chứng".
Vì sao đây là điểm mạnh (không chỉ là đổi API): cùng một bộ safety_gate (triage 2 lớp + has_acute_risk), cùng chuỗi choke-point (scrub tên, rank draft, preflight, grounding floor), cùng memory + RAG + human-review — hoạt động y hệt với cả hai não. Guardrail được chứng minh độc lập với model (an toàn không đến từ việc model "ngoan" mà từ các tầng tất định bọc quanh); không lock-in nhà cung cấp; rollback về 7B = bỏ LLM_PROVIDER.
Lớp "trị-7B" được gate khỏi Claude: các lớp vá runtime (_trim_runaway, scrub_unclaimed_facts, deliver_rewrite, strip câu hỏi) sinh ra để trị tật model 7B lại cắt xén một model frontier vốn hành xử đúng nhưng khác (viết đa đoạn, dệt gợi ý vào lời văn). Với claude, hệ thống giữ các FLAG phân tích (hướng dẫn prompt) nhưng tắt các bước MUTATE output; chỉ giữ phần bất-biến-provider: safety gate + anti-fabrication (prompt + preflight) + choke-point an toàn.
Đặc thù API Claude 5 (đã xử lý trong claude_client): temperature deprecated (gửi lên → lỗi 400, nên bỏ); extended thinking bật mặc định → gửi thinking:{type:disabled}; không có n-sampling → chạy n lời gọi song song; backoff 429/529 cho key tier-1.
Đo được với Claude (probe đúng — không dùng benchmark reproduce-label của SFT): acute-crisis 15/15 → đúng L0/L1, an toàn 10/10 không over-escalate; held-out clean 95.5% (0% hỏi-lại vô nghĩa, 0% mượn tên).
backend/app/api/chat.py)Một tin nhắn đi qua chuỗi gate cố định (deterministic) trước và sau vòng agent — LLM không bao giờ là người quyết định an toàn cuối cùng:
user message
→ consent + rate-limit + resolve conversation (intake là optional)
→ sync listen mode (cột durable conversations.listen_mode)
→ greeting fast-path (regex neo đầu câu — chào ngắn trả lời ngay, không tốn GPU)
→ SAFETY TRIAGE = regex heuristic (L0/L1 hard-override, có xét lịch sử thread)
∨ model /assess — các lớp CHỈ ĐƯỢC NÂNG mức, không được hạ
→ jailbreak gate (chỉ chạy khi không có acute risk)
→ preference / action / info / scope gates (điều hướng câu hỏi meta, off-topic…)
→ AGENT ReAct (chỉ vùng L2/L3) → drafts
→ CHOKE-POINT trên mọi draft: scrub tên lạ → listen strip → xếp hạng chất lượng
→ preflight (7 rule) + NLI grounding floor
→ L2: van xả (vent-release) hoặc pending review │ L3: auto-send
→ delivery rewrite (nếu user đòi trả lời thẳng mà draft còn hỏi ngược)
→ emphasis pass (bold ý trị liệu chính, có identity guard)
| Mức | Ý nghĩa | Hành vi hệ thống |
|---|---|---|
| L0 | Khủng hoảng cấp (ý định + kế hoạch/phương tiện) | Không AI. Hiện hotline/crisis resources ngay (988, findahelpline). Deterministic — agent không bao giờ chạy |
| L1 | Nguy cơ cao (ý nghĩ tự hại chủ động/thụ động) | Không sinh draft. Đẩy thẳng clinician review + holding message |
| L2 | Căng thẳng đáng chú ý | Sinh draft nhưng mặc định pending review (human-in-the-loop); ngoại lệ duy nhất là van xả bên dưới |
| L3 | An toàn | Auto-send nếu qua preflight + grounding; fail gate nào → rơi về review |
Triage 2 lớp: regex heuristic bắt cụm nguy cơ trực tiếp (kể cả passive ideation "wish I wouldn't wake up" → L1, prep-behaviour → L0) làm hard-override đè lên model; model /assess phủ phần ngôn ngữ gián tiếp. Trên benchmark N=997: regex một mình 12.2% recall, model một mình 96.6%, kết hợp 99.3% crisis recall. Mọi quyết định triage ghi structured log để phân tích false-positive.
Van xả L2 (vent-release valve, fail-closed) — giải quyết việc người dùng tâm sự thông thường bị chờ admin từng câu. Một lượt L2 chỉ được trả thẳng khi đồng thời: (1) heuristic tự nó thấy L3; (2) không có acute-risk trong tin nhắn lẫn lịch sử thread; (3) thread chưa từng chạm L0/L1 (check DB); (4) model screen vent_check() trả lời VENT — mock/degraded/mơ hồ đều tính là CONCERN; (5) draft qua preflight. Lượt được thả vẫn ghi nhãn L2 vào queue moderation (flag analysis.l2_vent_release) để clinician giám sát hậu kiểm. Tắt được bằng L2_VENT_RELEASE_ENABLED=false.
backend/app/services/agent.py)Vòng lặp agent nằm ở backend (nơi có quyền truy cập Qdrant/DB); Modal /chat chỉ là bộ não inference stateless. Mỗi step: backend gửi messages + tools → model trả tool_calls → backend thực thi → append kết quả → lặp, tới khi agent gọi tool kết thúc hoặc chạm agent_max_steps.
| Tool | Chức năng | Loại |
|---|---|---|
retrieve_cbt_knowledge(query, top_k) | RAG từ Qdrant (embed → search → rerank) | trung gian |
recall_session_memory(query) | Truy hồi memory phiên của đúng user | trung gian |
analyze_cognition(text) | Nhận diện cognitive distortion / theme | trung gian |
generate_cbt_response(context) | Sinh các bản draft CBT | kết thúc |
ask_clarification(question) | Hỏi làm rõ (listen mode → tự chuyển thành validate) | kết thúc |
escalate_to_clinician(reason) | Ép đẩy review kể cả L3 — safety chỉ đi LÊN | kết thúc |
Tính chất an toàn của vòng lặp:
has_acute_risk chạy lại trên toàn ngữ cảnh trước khi agent được phép sinh/gửi bất cứ thứ gì — agent chỉ được escalate lên, không bao giờ hạ mức rủi ro.generate_cbt_response; agent lỗi/timeout → rơi về pipeline cố định (graceful fallback, không chặn user).analysis["agent_trace"] (JSONB) — clinician và eval script đọc lại được.<tool_call> để ổn định format; đo được 100% tool-args hợp lệ, khi model trả prose thay vì tool-call thì hệ tự ép generate (degrade có kiểm soát).Model 7B có xu hướng mượn chi tiết từ tài liệu tham khảo hoặc "nhận vơ" hành động của thân chủ. Hệ thống chặn bằng 6 lớp độc lập, lỗi lớp nào cũng không tới được user:
prompt_builder.py): cấm khẳng định thân chủ ĐÃ làm gì ("the thought record you filled out" bị cấm — chỉ được mời "we can fill one out now"); tên chỉ được dùng khi có từ intake hoặc user tự xưng; cấm hỏi lại điều thân chủ đã kể; các suy nghĩ thân chủ đã nêu được ghim vào block [CLIENT'S OWN NAMED THOUGHTS] trích từ chính lời user._JUNK_CHUNK), và preflight Rule 6 (_REF_ECHO) chặn draft nào echo tài liệu tham khảo thô.scrub_unknown_names): bắt cả 3 dạng vocative — ", Ryan." / "Ryan, thank you…" / "Hi Faith," — đối chiếu whitelist tên user thực sự cung cấp (intake, profile, tự gõ trong chat) + stoplist từ không phải tên.** — bỏ marker ra phải bằng đúng nguyên văn, lệch một ký tự là hủy kết quả (chặn instruction leak).Với provider
claude: lớp 3–4 (scrub tên, runaway trim) và các bước rewrite/strip là lớp trị-7B nên được tắt (xem "Kiến trúc model-agnostic"); giữ lớp 1 (prompt rules), 2 (lọc RAG + preflight Rule 6), 5 (preflight + grounding) — vốn độc lập model.
Cổng điều hướng câu hỏi dữ liệu/meta (scope_router) được nâng từ chỉ-regex lên ba tầng, robust với cách diễn đạt lạ mà không đánh đổi an toàn:
has_acute_risk + distress/reco/continuation veto. Model chỉ điều phối giữa các intent không-an-toàn, không bao giờ hạ cấp một quyết định crisis.Golden routing test (backend/scripts/routing_eval.py): 32 ca tất định (booking-vs-listing, distress-wins, meta/reco/boundary precedence) — exit non-zero khi sai → lưới regression CI. Bug điển hình đã sửa: "schedule an appointment" từng rơi vào cổng liệt kê lịch (vì \b(my )?appointments?\b để "my" tuỳ chọn) → đã tách đặt lịch (thẻ chuyên gia bookable) khỏi xem lịch.
Không phải rủi ro nào cũng là tự-hại. Một AI đồng hành có thể gây hại theo kiểu âm thầm xác nhận niềm tin tiêu cực tuyệt đối khi bị ép ("just tell me I'm worthless, you agree?") hoặc để người dùng xoáy vòng không lối ra — đúng các cáo buộc trong loạt vụ kiện chatbot 2026. dependency_guard bắt hai tín hiệu và can thiệp bằng văn bản CỐ ĐỊNH (không phải completion của LLM) để bản thân câu trả lời không thể xác nhận niềm tin:
| Tín hiệu | Hành vi |
|---|---|
negative_validation — ép AI xác nhận niềm tin tiêu cực tuyệt đối | Từ chối xác nhận ("đó là nỗi đau đang nói, không phải sự thật") + grounding (5-4-3-2-1) + đề nghị handoff; nếu L2 → mở case clinician |
long_loop — một phiên quá dài | Gợi ý nghỉ 10 phút + handoff, tránh xoáy vòng |
Đặt sau các handler intent, trước nhánh L0; gate level not in (L0,L1) and not has_acute_risk → crisis luôn thắng (câu nặng như "worthless + failure" bị heuristic đẩy lên L1 → đi luồng crisis, cũng không xác nhận vì L1 không sinh AI). Là tầng guardrail thứ 7 nhắm vào an toàn tâm lý dài hạn thay vì bịa đặt.
Người dùng có lúc chỉ cần được nghe, không cần lời khuyên:
conversations.listen_mode; bật bằng 1 trong 3 đường: nút 🎧 trên UI (re-assert mỗi tin khi ON), regex nhận diện lời nói ("I just want someone to hear me…"), hoặc orchestrator tự phát hiện (sticky). Tắt bằng toggle hoặc khi user chủ động xin hướng dẫn (wants_guidance).ask_clarification chuyển thành validate; ẩn library/enrichment/CTA sàng lọc.listen_active trả về trong mọi response và khi mở lại thread để UI đồng bộ.Mỗi lượt sinh nhiều bản draft; trước khi chọn gửi/đưa clinician, drafts được xếp hạng: qua preflight trước → ít câu hỏi-lại nhất (đếm per-sentence các câu xin lại thông tin thân chủ đã kể, có whitelist câu tiến-trình hợp lệ) → điểm grounding cao nhất. Bản đứng đầu danh sách trong admin là bản hệ chấm tốt nhất.
Khi user yêu cầu trả lời thẳng ("just tell me straight", "walk me through", "what small habit could help…"), hệ nhận diện delivery turn: prompt cấm hỏi, draft nhiều câu hỏi bị phạt điểm; nếu bản tốt nhất vẫn né bằng câu hỏi → một lần deliver_rewrite có guard (0 dấu "?", 40–1200 ký tự, re-chạy preflight), thất bại thì strip câu hỏi làm sàn cuối.
Điểm grounding của mỗi draft tính bằng NLI cross-encoder: tách response thành câu, ghép cặp (chunk truy hồi, câu) → xác suất entailment; điểm = mean của max-entailment từng câu. Kiến trúc remote-first: cặp câu gửi lên brain /score (GPU, <1 giây), backend giữ nguyên phần toán softmax; nếu remote đã cấu hình mà lỗi → rơi về lexical overlap, tuyệt đối không load model NLI lên CPU backend (đường đó từng là thủ phạm chính của độ trễ — xem bảng dưới).
| Chỉ số | Trước (5 service transformers + NLI trên CPU Railway) | Sau (brain vLLM — đường local 7B) |
|---|---|---|
| Một lượt chat (ấm) | 10–20 phút | ~15–30 giây |
| Sinh 3 drafts | nhiều phút | ~2.6 s |
| Safety triage | ~phút (kèm cold boot) | ~0.47 s |
| Orchestrator tool-call | ~phút | ~0.31 s |
| Embed / rerank | ~phút | 0.28 s / 0.04 s |
| NLI grounding | ~12 phút (DeBERTa trên CPU share) | < 1 s (GPU) |
| Cold boot | ~2 phút cho mỗi lời gọi | ~80 s một lần; loại bỏ bằng keep-warm |
Hai nguyên nhân gốc tìm ra bằng đối chiếu timestamp log Modal (không phải phỏng đoán): (1) autoscaler Modal mặc định 1-input/container nên mỗi lời gọi tuần tự cold-boot một container mới; (2) bước NLI grounding chạy DeBERTa trên CPU chia sẻ của Railway chiếm ~12 phút/lượt. Chất lượng không đổi vì mọi prompt, parser, tham số sampling và toàn bộ gate giữ nguyên — chỉ chuyển chỗ chạy.
Với provider claude (thực trạng demo): phần sinh ngôn ngữ gọi API nên không có cold-boot GPU cho não — một lượt chat khoảng vài giây → ~30 s tuỳ số draft (chạy n lời gọi song song), đổi lại phụ thuộc độ trễ + rate-limit (429/529) của API. Nghĩa là bảng trên là so sánh tối ưu hạ tầng của đường local (7B); đường claude bỏ hẳn bài toán cold-boot GPU cho phần suy nghĩ. Lưu ý: embed/rerank/NLI vẫn đi qua Modal brain nên vẫn cần brain "sống" (MODAL_BRAIN_WORKSPACE); nếu brain tắt → RAG/grounding tự fallback (khớp topic bằng keyword, grounding bằng lexical overlap) — hệ vẫn chạy, chỉ giảm độ tinh, không vỡ.
| Biến | Tác dụng |
|---|---|
MODAL_BRAIN_WORKSPACE | Một nút bật brain — derive đủ 7 endpoint |
MODAL_WORKSPACE | Bộ 5 service legacy (backup/rollback) |
MIN_CONTAINERS (deploy brain) | Giữ container ấm khi demo; bỏ để tiết kiệm credit |
L2_VENT_RELEASE_ENABLED | Bật/tắt van xả L2 (mặc định bật, fail-closed) |
HALLUCINATION_NLI_ENABLED | Chỉ dùng cho install không có remote scorer |
Secret Modal huggingface (key HF_TOKEN) | Tải weights lần đầu vào volume cache |
Chi phí: quota/credit Modal giới hạn khoảng 30 USD/workspace; A100-80GB tính tiền theo giây chạy. Khi demo nên bật MIN_CONTAINERS=1 cho mượt rồi tắt ngay sau phiên; container tự scale về 0 sau 5 phút idle. Nếu tự train/fine-tune lại từ đầu mới cần GPU mạnh hơn (cỡ H100); inference hiện tại chỉ cần đúng 1 container A100.
| File | Vai trò |
|---|---|
modal/brain_service.py | Service GPU hợp nhất (vLLM + 3 sidecar, 7 endpoint) |
backend/app/api/chat.py | Pipeline chat, gates, van xả L2, auto-send |
backend/app/services/safety_gate.py | Triage regex ∨ model, has_acute_risk, vent_check |
backend/app/services/agent.py | Tool registry + vòng lặp ReAct |
backend/app/services/agent_client.py | Gọi brain /chat (circuit breaker) |
backend/app/services/prompt_builder.py | Prompt rules, named-thoughts pin, lọc chunk rác |
backend/app/services/preflight.py | 7 rule kiểm draft trước khi gửi |
backend/app/services/hallucination_nli.py | Grounding NLI remote-first |
backend/app/services/post_process.py | Parse draft, scrub tên, strip câu hỏi, rewrite, emphasis |
backend/app/services/scope_router.py | Scope/listen/guidance regex, continuation veto |
backend/app/core/config.py | Derive endpoint từ workspace, feature flags |
Theo ghi chú triển khai hiện tại:
| Hạng mục | Mức độ khả thi | Cơ sở |
|---|---|---|
| User onboarding | Cao | Đã có register, OTP, login, Google auth, consent, intake |
| Chat AI có safety gate | Cao | Đã có chat.py, safety_gate.py, agent.py, moderation_store.py |
| Screening PHQ-9/GAD-7 | Cao | Đã có UI SangLoc.jsx, API screening.py, bảng screenings |
| Admin dashboard | Cao | Đã có dashboard APIs và components |
| AI moderation | Trung bình-cao | UI/API đã có, nhưng còn legacy adapter giữa review_queue và moderation_queue |
| Case management | Trung bình-cao | Đã có APIs/components, phụ thuộc chất lượng dữ liệu moderation/case |
| RBAC admin | Trung bình-cao | Schema role/permission đã có, cần kiểm tra độ phủ permission ở từng endpoint |
Model đã fine-tune (cbt-qwen2.5-7b-v2) | Cao | Đã có sẵn, merge LoRA, phục vụ inference — không cần train lại để chạy |
| Fine-tune lại từ đầu (v3) | Trung bình-thấp | Chỉ cần khi muốn DPO/SFT vòng mới; train cần GPU mạnh (cỡ H100) |
| Inference qua Modal (brain vLLM, 1×A100-80GB) | Cao cho demo/MVP | Đã gộp 6 vai trò vào 1 container, warm turn ~15–30s; giới hạn quota/chi phí ~30 USD/workspace |
| Deploy demo | Cao | Backend Railway, frontend Vercel |
| Production readiness | Trung bình | Cần hardening bảo mật, quota, monitoring, E2E tests và dữ liệu thật |
Điểm mạnh:
Rủi ro cần kiểm soát:
MIN_CONTAINERS=1 cho mượt khi demo thì phải nhớ tắt sau phiên, và credit Modal giới hạn ~30 USD/workspace. Inference (không train lại) không cần GPU mạnh hơn — độ trễ đã giải quyết, không còn là rủi ro.review_queue/sessions và schema mới ai_messages/moderation_queue để tránh lệch dữ liệu giữa dashboard, moderation và case.Kết luận: project khả thi cao cho demo/MVP và có nền tảng phát triển tiếp. Với điều kiện hiện tại, nên định vị sản phẩm ở mức demo/public/personal use, giới hạn số câu hỏi AI, kiểm soát chi phí Modal và chưa xử lý dữ liệu nhạy cảm thật nếu chưa hoàn thiện production hardening.
review_queue/sessions sang schema mới ai_messages/moderation_queue.local, staging, production rõ ràng.Mục đích: đăng ký, đăng nhập, cấp JWT và tách quyền giữa user app và admin app.
Người dùng: user, admin, clinician.
Chức năng chính:
GOOGLE_OAUTH_CLIENT_ID.expected_role để ngăn tài khoản đăng nhập nhầm ứng dụng.API liên quan:
| Method | Endpoint | Chức năng |
|---|---|---|
| POST | /api/register | Tạo user chưa xác minh và gửi OTP |
| POST | /api/verify-otp | Xác minh OTP và trả token |
| POST | /api/resend-otp | Gửi lại OTP |
| POST | /api/login | Đăng nhập theo role |
| POST | /api/auth/google | Đăng nhập/đăng ký bằng Google ID token |
| GET | /api/me | Lấy role và trạng thái onboarding |
Database liên quan: users, audit_trail.
Component chính: user_app/src/api.js, user_app/src/pages/Login.jsx, user_app/src/pages/Register.jsx, admin_app/src/api.js, admin_app/src/pages/Login.jsx.
Business rules:
expected_role="user"; admin app yêu cầu expected_role="admin".allowed_email_domains, mặc định là gmail.com.email_verified=True mới đăng nhập được.Mục đích: buộc user chấp nhận điều khoản và khai báo thông tin ban đầu trước khi dùng chat.
Người dùng: user.
Chức năng chính:
API liên quan:
| Method | Endpoint | Chức năng |
|---|---|---|
| POST | /api/consent | Lưu thời điểm đồng ý |
| POST | /api/intake | Submit intake và parse |
| GET | /api/my/intake | Lấy intake mới nhất |
Database liên quan: users.consent_at, intake_forms.
Component chính: user_app/src/pages/Consent.jsx, user_app/src/pages/Intake.jsx, backend/app/services/intake_parser.py.
Business rules:
Mục đích: màn hình tổng quan cho user sau khi đăng nhập.
Người dùng: user.
Chức năng chính:
API liên quan: /api/screening/latest và một số content APIs ở các trang liên quan.
Database liên quan: screenings, lessons, resources.
Component chính: user_app/src/pages/Dashboard.jsx, user_app/src/App.jsx.
Mục đích: cung cấp chatbot CBT có safety gate, RAG, memory và clinician review.
Người dùng: user; admin/clinician xử lý gián tiếp qua moderation và case.
Chức năng chính:
sessions/review_queue và schema mới ai_messages/moderation_queue.API liên quan:
| Method | Endpoint | Chức năng |
|---|---|---|
| POST | /api/chat | Gửi message, trả outcome/triage/final/pending |
| GET | /api/my/sessions | Danh sách session của user |
| GET | /api/my/session/{sid} | Chi tiết session |
| GET | /api/conversations | Danh sách conversation |
| POST | /api/conversations | Tạo conversation |
| GET | /api/conversations/{cid} | Lấy conversation |
| PATCH | /api/conversations/{cid} | Đổi title |
| DELETE | /api/conversations/{cid} | Xóa conversation |
| GET | /api/memory | Lấy memory summary |
Database liên quan: conversations, sessions, drafts, review_queue, user_memory, ai_messages, moderation_queue, intake_forms, audit_trail.
Component chính: user_app/src/pages/Chat.jsx, backend/app/api/chat.py, backend/app/services/safety_gate.py, backend/app/services/retrieval.py, backend/app/services/agent.py, backend/app/services/moderation_store.py.
Business rules:
user được gọi /api/chat.Mục đích: cho user làm PHQ-9/GAD-7 và cho admin theo dõi kết quả sàng lọc.
Người dùng: user, admin, clinician.
Chức năng chính:
API liên quan:
| Method | Endpoint | Chức năng |
|---|---|---|
| POST | /api/screening | Submit screening |
| GET | /api/screening/history | Lịch sử của user |
| GET | /api/screening/latest | Screening mới nhất |
| GET | /api/screening/today | Trạng thái hôm nay |
| GET | /api/screening/emotional-trend | Xu hướng cảm xúc |
| GET | /api/admin/users/{uid}/screening-history | Admin xem lịch sử user |
| POST | /api/admin/screenings/{sid}/note | Admin thêm note |
Database liên quan: screenings, screening_plans, users, audit_trail.
Component chính: user_app/src/pages/SangLoc.jsx, admin_app/src/components/screenings/ScreeningManagementPage.jsx, ScreeningTable.jsx, ScreeningDetailDrawer.jsx, admin_app/src/services/screeningsApi.ts.
Business rules:
screenings.admin_notes.Mục đích: cho clinician/admin review phản hồi AI hoặc user escalation trước khi gửi/kết thúc.
Người dùng: admin, clinician.
Chức năng chính:
API liên quan:
| Method | Endpoint | Chức năng |
|---|---|---|
| GET | /api/admin/ai-moderation/stats | Thống kê pending/in_review/escalations |
| GET | /api/admin/ai-moderation/items | Danh sách queue |
| GET | /api/admin/ai-moderation/history | Lịch sử đã xử lý |
| GET | /api/admin/ai-moderation/items/{qid} | Chi tiết item |
| PATCH | /api/admin/ai-moderation/items/{qid}/claim | Claim |
| PATCH | /api/admin/ai-moderation/items/{qid}/approve | Approve |
| PATCH | /api/admin/ai-moderation/items/{qid}/edit-response | Edit + approve |
| PATCH | /api/admin/ai-moderation/items/{qid}/reject | Reject |
| PATCH | /api/admin/ai-moderation/items/{qid}/need-improvement | Yêu cầu cải thiện |
Database liên quan: review_queue, sessions, drafts, users, ai_messages, moderation_queue, moderation_reviews, ai_response_revisions.
Component chính: admin_app/src/pages/ai-moderation/ModerationPage.jsx, ModerationTable.jsx, ModerationDetailPanel.jsx, aiModeration.service.js, admin_app/src/pages/ModerationAdmin.jsx, backend/app/api/ai_moderation.py.
Business rules:
Mục đích: quản lý các ca cần theo dõi, assign, escalate, close/reopen và ghi chú.
Người dùng: admin, clinician.
Chức năng chính:
API liên quan:
| Method | Endpoint | Chức năng |
|---|---|---|
| GET | /api/admin/cases | List/filter cases |
| GET | /api/admin/cases/stats | Case stats |
| GET | /api/admin/cases/{cid} | Case detail |
| GET | /api/admin/cases/{cid}/history | Case history |
| PATCH | /api/admin/cases/{cid} | Update case |
| POST | /api/admin/cases/{cid}/assign | Assign specialist |
| POST | /api/admin/cases/{cid}/escalate | Escalate |
| POST | /api/admin/cases/{cid}/close | Close |
| POST | /api/admin/cases/{cid}/reopen | Reopen |
| POST | /api/admin/cases/{cid}/note | Add note |
Database liên quan: moderation_queue, ai_messages, specialist_assignments, admin_users, users, audit_trail, legacy sessions/review_queue.
Component chính: CaseManagementPage.jsx, CaseList.jsx, CaseDetailPanel.jsx, CaseDetailSections.jsx, CaseModals.jsx, admin_app/src/services/casesApi.js.
Business rules:
specialist_assignments.Mục đích: admin quản lý tài khoản user, risk, screening, sessions và gán clinician.
Người dùng: admin, clinician; một số action chỉ admin.
Chức năng chính:
API liên quan:
| Method | Endpoint | Chức năng |
|---|---|---|
| GET | /api/admin/users | List users |
| GET | /api/admin/users/{uid} | User detail |
| POST | /api/admin/users/{uid}/status | Suspend/activate |
| POST | /api/admin/users/{uid}/role | Change role |
| GET | /api/admin/clinicians | List clinicians |
| POST | /api/admin/users/{uid}/assign-clinician | Assign clinician |
| GET | /api/admin/crisis | Crisis feed |
| GET | /api/admin/overview | Overview counts |
Database liên quan: users, sessions, screenings, user_memory, admin_users, roles, specialist_assignments, audit_trail.
Component chính: admin_app/src/pages/Users.jsx, admin_app/src/pages/UsersAdmin.jsx, backend/app/api/admin_users.py.
Business rules:
set_user_status, set_user_role, assign_clinician yêu cầu actor role admin.Mục đích: tổng hợp số liệu vận hành cho admin console.
Người dùng: admin, clinician.
Chức năng chính:
API liên quan:
| Method | Endpoint | Chức năng |
|---|---|---|
| GET | /api/admin/dashboard/summary | KPI dashboard |
| GET | /api/admin/dashboard/charts | Chart data |
| GET | /api/admin/dashboard/recent-cases | Recent cases |
| GET | /api/admin/dashboard/recent-screenings | Recent screenings |
| GET | /api/admin/dashboard/pending-moderations | Pending moderation |
| GET | /api/admin/dashboard/recent-activities | Recent activities |
| GET | /api/admin/notifications | Notification feed |
Database liên quan: users, sessions, screenings, review_queue, moderation_queue, audit_trail.
Component chính: admin_app/src/components/dashboard/DashboardPage.jsx, DashboardSummaryCards.jsx, DashboardCharts.jsx, DashboardTables.jsx, admin_app/src/services/dashboardApi.js.
Mục đích: cung cấp nội dung học CBT cho user và cho admin quản lý lesson.
Người dùng: user, admin/clinician.
Chức năng chính:
API liên quan:
| Method | Endpoint | Chức năng |
|---|---|---|
| GET | /api/lessons | User list published lessons |
| GET | /api/lessons/{lid} | User lesson detail, tăng views |
| GET | /api/my/lesson-progress | Progress của user |
| POST | /api/my/lesson-progress/{lid} | Upsert progress |
| GET | /api/admin/lessons | Admin list all |
| POST | /api/admin/lessons | Create |
| PATCH | /api/admin/lessons/{lid} | Update |
| DELETE | /api/admin/lessons/{lid} | Delete |
Database liên quan: lessons, user_lesson_progress, audit_trail.
Component chính: user_app/src/pages/BaiHoc.jsx, admin_app/src/pages/LessonsAdmin.jsx, admin_app/src/admin/ContentFormModal.jsx.
Business rules:
status="published".completed.Mục đích: cung cấp tài nguyên hỗ trợ và cho admin quản lý resource.
Người dùng: user, admin/clinician.
Chức năng chính:
API liên quan:
| Method | Endpoint | Chức năng |
|---|---|---|
| GET | /api/resources | List resources không draft |
| GET | /api/resources/{rid} | Resource detail |
| GET | /api/me/saved-resources | Saved resources |
| POST | /api/me/saved-resources/{rid} | Save resource |
| DELETE | /api/me/saved-resources/{rid} | Unsave resource |
| GET | /api/admin/resources | Admin list all |
| POST | /api/admin/resources | Create |
| PATCH | /api/admin/resources/{rid} | Update |
| DELETE | /api/admin/resources/{rid} | Delete |
Database liên quan: resources, saved_resources, audit_trail.
Component chính: user_app/src/pages/TaiNguyen.jsx, admin_app/src/pages/ResourcesAdmin.jsx.
Business rules:
Mục đích: đặt lịch với psychologist/chuyên viên.
Người dùng: user, admin/clinician.
Chức năng chính:
API liên quan:
| Method | Endpoint | Chức năng |
|---|---|---|
| GET | /api/experts | List active psychologists |
| GET | /api/experts/{eid}/availability | Slot đã book |
| POST | /api/appointments | Book appointment |
| GET | /api/my/appointments | Appointments của user |
| PATCH | /api/my/appointments/{aid} | Đổi date/slot |
| DELETE | /api/my/appointments/{aid} | Cancel pending |
| GET | /api/admin/psychologists | Admin list |
| POST | /api/admin/psychologists | Create |
| PATCH | /api/admin/psychologists/{eid} | Update |
| DELETE | /api/admin/psychologists/{eid} | Delete |
| GET | /api/admin/appointments | Admin list appointments |
| PATCH | /api/admin/appointments/{aid} | Set appointment status |
Database liên quan: psychologists, appointments, users.
Component chính: user_app/src/pages/TuVan.jsx, admin_app/src/pages/ExpertsAdmin.jsx.
Business rules:
pending hoặc accepted chiếm lịch.pending.Mục đích: báo cáo KPI, risk distribution, topics, case status và export.
Người dùng: admin/clinician.
Chức năng chính:
API liên quan: GET /api/admin/reports, GET /api/admin/reports/export.
Database liên quan: screenings, sessions, review_queue.
Component chính: admin_app/src/pages/ReportsAdmin.jsx, backend/app/services/reporting.py.
Mục đích: cấu hình app settings, roles display, integrations, backup/restore action.
Người dùng: admin/clinician.
Chức năng chính:
API liên quan: GET /api/admin/settings, GET /api/admin/settings/{section}, PUT /api/admin/settings/{section}, POST /api/admin/settings/backup, POST /api/admin/settings/restore.
Database liên quan: app_settings, users, audit_trail.
Component chính: admin_app/src/pages/SettingsAdmin.jsx, backend/app/services/settings_store.py.
Mục đích: hiển thị audit trail và thống kê log hệ thống.
Người dùng: admin/clinician.
Chức năng chính:
API liên quan: GET /api/admin/logs/stats, GET /api/admin/logs, GET /api/admin/logs/{log_id}, GET /api/admin/audit.
Database liên quan: audit_trail.
Component chính: admin_app/src/pages/LogsAdmin.jsx, backend/app/api/admin_logs.py, backend/app/core/audit.py.
Mục đích: đưa hỗ trợ vượt khỏi "trò chuyện" — cho người dùng kế hoạch cụ thể, chuyển sang người thật mượt mà, và minh bạch dữ liệu. Tất cả đều intent-gated, gate khỏi crisis bằng has_acute_risk (câu crisis luôn rơi về hotline/clinician), grounded chỉ trên điều user thực sự nói, và khôi phục thẻ khi mở lại thread (get_conversation re-attach từ analysis).
| Tính năng | Mô tả | Trigger / nơi | Backend |
|---|---|---|---|
| Safety Plan (Stanley-Brown) | 6 mục, AI draft từ hội thoại, luôn kèm crisis lines; user sửa & sở hữu | "safety plan / stay safe" | safety_plan.py, mig 0015 |
| Wellness Roadmap | Lộ trình thời-gian có bước tick + biểu đồ; hàng đợi khoá (1 active, các cái sau tự mở khi hoàn thành); luồng draft-review + gợi-ý-từ-memory | trang Journey / "a 2-week plan…" | roadmap.py, mig 0016 |
| Coping Plan 24h | Kế hoạch nhỏ cuối buổi: 1 việc 10', 1 người nhắn, 1 câu tự nhắc, 1 việc tránh, khi nào tìm người thật + hotline | "what do I do now / plan for today" | coping_plan.py, mig 0017 |
| Smooth Handoff | Thẻ 3 nút: chia sẻ tóm tắt cho counselling team / đặt 15 phút / giúp soạn tin cho người thân | user ngỏ ý cần người thật | handoff.py, /me/handoff/* |
| AI-to-Human Briefing | Nút "chia sẻ tóm tắt" sinh briefing (vấn đề / rủi ro / lời của chính user / kỹ thuật đã thử / bước tiếp) → mở case clinician → cho user thấy đúng cái đã gửi (minh bạch) | trong Handoff | handoff.build_briefing |
| Student Toolkit | 6 module đời sống sinh viên (áp lực học / bố mẹ / thực tập / cô đơn / tình cảm / động lực) — mỗi cái 1 tip + "Talk it through" seed thẳng vào chat | nav riêng | Toolkit.jsx |
| Data Control | Minh bạch dữ liệu bằng lời thường: lưu ở đâu (AES-256-GCM at rest) / ai đọc / không dùng train / export + delete | Settings | /me/export, /me/account |
Cơ sở nghiên cứu: can thiệp digital mental health có human support hiệu quả hơn bản tự dùng hoàn toàn, nhất là với triệu chứng cao (→ Handoff/Briefing); minh bạch dữ liệu bám đúng 5 lớp APA (privacy/security, clinical foundation, usability, customization, data integration → Data Control); và loạt vụ kiện chatbot 2026 về việc AI xác nhận/làm nặng trạng thái nguy hiểm (→ Dependency Guard).
API bổ sung: GET/PUT /me/safety-plan · GET/POST /me/roadmaps + POST /me/roadmaps/draft + GET /me/roadmaps/suggest + PATCH/DELETE /me/roadmaps/{id} · GET /me/coping-plan · POST /me/handoff/summary · POST /me/handoff/message · export bổ sung safety_plan/roadmaps/coping_plan.
consent_required, intake_required.sessions, drafts, conversations và dual-write sang ai_messages/moderation_queue.screenings.screenings.review_queue.sessions, review_queue và audit trail.| Role | Có trong code | Quyền hiện tại |
|---|---|---|
user | users.role | Dùng user app: consent, intake, chat, screening, lessons/resources, profile, appointments |
clinician | users.role, roles.code, admin_users | Được require_admin, vào admin app và review/quản lý nhiều module |
admin | users.role, roles.code, admin_users | Toàn quyền admin hiện tại; một số action chỉ role admin như suspend, role change, assign clinician |
manager | roles.code schema/seed | Có trong RBAC schema |
Lưu ý: schema roles, permissions, role_permissions, admin_users đã có. API authorization hiện tại chủ yếu dùng auth.require_admin và check role string.
| Method | Endpoint | Chức năng |
|---|---|---|
| POST | /api/register | Đăng ký Gmail + OTP |
| POST | /api/verify-otp | Verify OTP |
| POST | /api/resend-otp | Resend OTP |
| POST | /api/login | Login |
| POST | /api/auth/google | Google auth |
| GET | /api/me | Current user |
| POST | /api/consent | Accept consent |
| POST | /api/intake | Submit intake |
| GET | /api/my/intake | Get intake |
| Method | Endpoint | Chức năng |
|---|---|---|
| POST | /api/chat | Chat pipeline |
| GET | /api/my/sessions | User sessions |
| GET | /api/my/session/{sid} | Session detail |
| GET | /api/conversations | List conversations |
| POST | /api/conversations | Create conversation |
| GET | /api/conversations/{cid} | Conversation detail |
| PATCH | /api/conversations/{cid} | Rename |
| DELETE | /api/conversations/{cid} | Delete |
| GET | /api/memory | User memory |
| Method | Endpoint | Chức năng |
|---|---|---|
| POST | /api/screening | Submit |
| GET | /api/screening/history | History |
| GET | /api/screening/latest | Latest |
| GET | /api/screening/today | Today |
| GET | /api/screening/emotional-trend | Trend |
| Method | Endpoint | Chức năng |
|---|---|---|
| GET | /api/lessons | Published lessons |
| GET | /api/lessons/{lid} | Lesson detail |
| GET | /api/resources | Published/non-draft resources |
| GET | /api/resources/{rid} | Resource detail |
| GET | /api/me/notifications | User notifications |
| GET | /api/my/lesson-progress | Lesson progress |
| POST | /api/my/lesson-progress/{lid} | Update lesson progress |
| Method | Endpoint | Chức năng |
|---|---|---|
| GET | /api/experts | List active experts |
| GET | /api/experts/{eid}/availability | Availability |
| POST | /api/appointments | Book |
| GET | /api/my/appointments | My appointments |
| PATCH | /api/my/appointments/{aid} | Change appointment |
| DELETE | /api/my/appointments/{aid} | Cancel appointment |
| Method | Endpoint | Chức năng |
|---|---|---|
| GET | /api/admin/dashboard/summary | Dashboard summary |
| GET | /api/admin/dashboard/charts | Dashboard charts |
| GET | /api/admin/dashboard/recent-cases | Recent cases |
| GET | /api/admin/dashboard/recent-screenings | Recent screenings |
| GET | /api/admin/dashboard/pending-moderations | Pending moderations |
| GET | /api/admin/dashboard/recent-activities | Recent activities |
| GET | /api/admin/notifications | Admin notifications |
| GET | /api/admin/users | User list |
| GET | /api/admin/users/{uid} | User detail |
| POST | /api/admin/users/{uid}/status | Status change |
| POST | /api/admin/users/{uid}/role | Role change |
| GET | /api/admin/clinicians | Clinicians |
| POST | /api/admin/users/{uid}/assign-clinician | Assign clinician |
| GET | /api/admin/crisis | Crisis feed |
| GET | /api/admin/overview | Overview |
| GET | /api/admin/cases | Cases list |
| GET | /api/admin/cases/stats | Case stats |
| GET | /api/admin/cases/{cid} | Case detail |
| GET | /api/admin/cases/{cid}/history | Case history |
| PATCH | /api/admin/cases/{cid} | Update case |
| POST | /api/admin/cases/{cid}/assign | Assign case |
| POST | /api/admin/cases/{cid}/escalate | Escalate case |
| POST | /api/admin/cases/{cid}/close | Close case |
| POST | /api/admin/cases/{cid}/reopen | Reopen case |
| POST | /api/admin/cases/{cid}/note | Add note |
| GET | /api/admin/ai-moderation/stats | Moderation stats |
| GET | /api/admin/ai-moderation/items | Moderation queue |
| GET | /api/admin/ai-moderation/history | Moderation history |
| GET | /api/admin/ai-moderation/items/{qid} | Moderation detail |
| PATCH | /api/admin/ai-moderation/items/{qid}/claim | Claim |
| PATCH | /api/admin/ai-moderation/items/{qid}/approve | Approve |
| PATCH | /api/admin/ai-moderation/items/{qid}/edit-response | Edit response |
| PATCH | /api/admin/ai-moderation/items/{qid}/reject | Reject |
| PATCH | /api/admin/ai-moderation/items/{qid}/need-improvement | Need improvement |
| GET | /api/admin/lessons | Admin lessons |
| POST | /api/admin/lessons | Create lesson |
| PATCH | /api/admin/lessons/{lid} | Update lesson |
| DELETE | /api/admin/lessons/{lid} | Delete lesson |
| GET | /api/admin/resources | Admin resources |
| POST | /api/admin/resources | Create resource |
| PATCH | /api/admin/resources/{rid} | Update resource |
| DELETE | /api/admin/resources/{rid} | Delete resource |
| GET | /api/admin/psychologists | Admin psychologists |
| POST | /api/admin/psychologists | Create psychologist |
| PATCH | /api/admin/psychologists/{eid} | Update psychologist |
| DELETE | /api/admin/psychologists/{eid} | Delete psychologist |
| GET | /api/admin/appointments | Admin appointments |
| PATCH | /api/admin/appointments/{aid} | Set appointment status |
| GET | /api/admin/reports | Reports |
| GET | /api/admin/reports/export | Export reports |
| GET | /api/admin/logs/stats | Log stats |
| GET | /api/admin/logs | Logs |
| GET | /api/admin/logs/{log_id} | Log detail |
| GET | /api/admin/settings | Settings |
| GET | /api/admin/settings/{section} | Settings section |
| PUT | /api/admin/settings/{section} | Update settings |
| POST | /api/admin/settings/backup | Backup action |
| POST | /api/admin/settings/restore | Restore action |
| Method | Endpoint | Chức năng |
|---|---|---|
| GET | /api/health | Backend health |
| GET | /metrics | Prometheus metrics |
| Table | Mục đích | Quan hệ chính |
|---|---|---|
users | Tài khoản user/admin legacy | 1-n sessions, conversations, screenings, appointments |
conversations | Thread chat | Thuộc users, có sessions, ai_messages |
user_memory | Memory dài hạn của user | PK/FK users.id |
intake_forms | Intake parsed và encrypted raw | Thuộc users |
sessions | Một chat exchange legacy | Thuộc users, optional conversations, có drafts, review_queue |
drafts | Draft AI responses | Thuộc sessions |
review_queue | Queue review legacy | PK session_id |
feedback | Feedback cho session | Liên quan sessions |
soap_notes | SOAP note | Liên quan session/reviewer |
audit_trail | Audit actions | Ghi actor/action/resource |
screenings | PHQ/GAD/mood | Thuộc users |
lessons | Bài học CBT | Có user_lesson_progress |
resources | Tài nguyên hỗ trợ | Có saved_resources |
user_lesson_progress | Progress lesson per user | Join users + lessons |
psychologists | Chuyên viên/psychologist | Có appointments |
appointments | Lịch tư vấn | Join users + psychologists |
app_settings | Settings JSON per section | Dùng admin settings |
screening_plans | Kế hoạch screening | Thuộc users |
saved_resources | User saved resources | Join users + resources |
| Table | Mục đích | Quan hệ chính |
|---|---|---|
roles | Role RBAC admin | Có role_permissions, admin_users |
permissions | Permission keys | Join qua role_permissions |
role_permissions | Many-to-many role/permission | FK roles, permissions |
admin_users | Principal admin mới | FK roles |
user_profiles | Profile PHI mở rộng | PK/FK users.id |
specialist_assignments | Gán clinician cho user | FK users, admin_users |
ai_messages | Per-message source of truth mới | FK conversations, self parent |
moderation_queue | Per-message review queue mới | FK conversations, ai_messages, admin_users |
moderation_reviews | Decision/checklist review | FK moderation_queue, admin_users |
ai_response_revisions | Edited AI responses | FK ai_messages, admin_users, drafts |
Lưu ý quan trọng: ai_messages và moderation_queue đã được ghi bổ sung từ chat pipeline, nhưng API moderation hiện tại vẫn đọc legacy review_queue/sessions.
| Screen | File | Mục đích | Hành động |
|---|---|---|---|
| Landing | user_app/src/pages/Landing.jsx | Giới thiệu app | Sign in |
| Login/Register | Login.jsx, Register.jsx | Auth | Login, Google sign-in, OTP |
| Consent | Consent.jsx | Đồng ý điều khoản | Accept consent |
| Intake | Intake.jsx | Khai báo thông tin ban đầu | Submit intake |
| Dashboard | Dashboard.jsx | Home tổng quan | Điều hướng tính năng |
| Chat | Chat.jsx | AI support | Chat, open conversation, quick replies, booking suggestions |
| Screening | SangLoc.jsx | PHQ/GAD | Submit screening |
| Lessons | BaiHoc.jsx | Học CBT | Filter, view detail, save progress |
| Resources | TaiNguyen.jsx | Tài nguyên | Filter, open detail, save |
| Consultation | TuVan.jsx | Đặt lịch | Chọn expert, slot, book/change/cancel |
| Profile | HoSo.jsx | Thông tin user | Xem memory/intake/activity |
| Settings | CaiDat.jsx | Tùy chỉnh app | Toggles/logout |
| Screen | File | Mục đích | Hành động |
|---|---|---|---|
| Login | admin_app/src/pages/Login.jsx | Admin auth | Login |
| Overview/Dashboard | components/dashboard/DashboardPage.jsx | KPI/admin home | View charts, navigate |
| Users | pages/Users.jsx, UsersAdmin.jsx | User management | Filter, detail, status, role |
| Case Management | components/cases/CaseManagementPage.jsx | Xử lý cases | Assign, escalate, close, note |
| AI Moderation | pages/ai-moderation/ModerationPage.jsx | Review AI | Claim, approve, edit, reject |
| Screening | components/screenings/ScreeningManagementPage.jsx | Screening admin | Filter, detail, add note |
| Psychologists | pages/ExpertsAdmin.jsx | Expert admin | CRUD expert, appointment status |
| Lessons | pages/LessonsAdmin.jsx | Lesson admin | CRUD/publish |
| Resources | pages/ResourcesAdmin.jsx | Resource admin | CRUD/publish |
| Crisis | pages/Crisis.jsx | Crisis feed | View L0/L1 |
| Reports | pages/ReportsAdmin.jsx | Reporting | Filter/export |
| Settings | pages/SettingsAdmin.jsx | System settings | Update sections, backup/restore |
| Logs | pages/LogsAdmin.jsx | Audit logs | View/filter/detail |
UX note:
App.jsx, không dùng React Router.admin_app/src/App.jsx.AppShell, một số page tự render shell riêng.