# DeepMed-AI — Project Reference Document > **Last updated**: 2026-04-14 > **Author**: Pham Ba Thuong > **Repo**: `e:\AI\DeepMed` > **Production URL**: Hugging Face Spaces (Docker) > **Version**: 3.0.0 --- ## 1. Tổng Quan **DeepMed-AI** là chatbot AI y tế chuyên dụng cho **Trung tâm Y tế Khu vực Thanh Ba** (TTYT KV Thanh Ba), tỉnh Phú Thọ, Việt Nam. Hỗ trợ y bác sĩ và dược sĩ: - Tra cứu thông tin thuốc (tên, hoạt chất, **giá**, hãng SX, liều dùng, chống chỉ định) - Chẩn đoán, phác đồ điều trị, tư vấn y khoa - Tra cứu danh mục thuốc nội bộ của TTYT Thanh Ba --- ## 2. Kiến Trúc Hệ Thống ### 2.1. Architecture: HybridRAG ``` ┌──────────────┐ ┌──────────────────────────────────────────────┐ │ React SPA │────▶│ FastAPI Backend (app/main.py) │ │ (Vite) │ │ │ │ Port: 5173 │ │ ┌──────────────────────────────────────┐ │ │ (dev) │ │ │ ChatService (Singleton) │ │ │ │ │ │ │ │ │ │ └───────────┘ │ │ ┌──────────┐ ┌──────────────────┐│ │ │ │ │ │Fast Mode │ │ Deep Mode ││ │ │ │ │ │BM25+Vec │ │ BM25+Vec → Rerank││ │ │ │ │ │ k=15 │ │ k=25 → top 5 ││ │ │ │ │ └──────────┘ └──────────────────┘│ │ │ │ │ │ │ │ │ │ ┌──────────────────────────────────┐│ │ │ │ │ │ ChromaDB (Local Persistent) ││ │ │ │ │ │ Embedding: MiniLM-L12-v2 ││ │ │ │ │ └──────────────────────────────────┘│ │ │ │ │ │ │ │ │ │ LLM: Gemini 2.5 Flash (Google) │ │ │ │ └──────────────────────────────────────┘ │ │ │ │ │ │ SQLite (chat history) via SQLAlchemy │ │ └──────────────────────────────────────────────┘ ``` ### 2.2. Hai Chế Độ Retrieval | Mode | Retriever | k | Reranker | Khi nào dùng | |------|-----------|---|----------|--------------| | **Fast** | BM25 + Vector (EnsembleRetriever 50/50) | 15 | ❌ | Tra cứu thuốc nhanh, câu hỏi đơn giản | | **Deep** | BM25 + Vector (EnsembleRetriever 50/50) → CrossEncoder | 25 → 5 | ✅ BGE-reranker-v2-m3 | Phác đồ, chẩn đoán, điều trị phức tạp | **Auto-detect**: Hệ thống tự nhận diện Deep mode khi câu hỏi chứa keyword: `phác đồ`, `điều trị`, `chẩn đoán`, `xử trí`, `hướng dẫn`, `protocol`, `guideline`, `bệnh nhân bị`, `cách điều trị`, `dùng thuốc gì`, `nên dùng`, `kê đơn`, `toa thuốc`, `sơ cứu`, `cấp cứu`. --- ## 3. Tech Stack ### 3.1. Backend | Component | Technology | Version | |-----------|-----------|---------| | Framework | FastAPI | 0.115.12 | | Server | Uvicorn | 0.34.2 | | LLM | Gemini 2.5 Flash | via `langchain-google-genai` 2.1.4 | | Embedding | `paraphrase-multilingual-MiniLM-L12-v2` | via sentence-transformers 3.4.1 | | Vector DB | ChromaDB (local persistent) | ≥0.4.0 | | Keyword Search | BM25 (rank-bm25) | 0.2.2 | | Reranker | BGE-reranker-v2-m3 (CrossEncoder) | via langchain-community | | LangChain | langchain + langchain-core + langchain-community | 0.3.25 | | ORM | SQLAlchemy | 2.0.40 | | DB | SQLite (chat history) | via pysqlite3-binary | | Data Processing | pypdf, python-docx, openpyxl, pandas | various | | Rate Limiting | slowapi | 0.1.9 | | Validation | Pydantic | 2.11.3 | | PyTorch | CPU-only | 2.2.2+cpu | | Python | 3.10-slim (Docker) | | ### 3.2. Frontend | Component | Technology | Version | |-----------|-----------|---------| | Framework | React | 19.2.0 | | Build Tool | Vite | 7.3.1 | | Styling | Tailwind CSS + Vanilla CSS (index.css 30KB) | 4.1.18 | | Markdown | react-markdown | 10.1.0 | | Icons | Font Awesome (CDN) | | | UI Components | DaisyUI | 5.5.18 | | Testing | Vitest + Testing Library | 4.0.18 | ### 3.3. Deployment | Platform | Config | |----------|--------| | **Primary**: Hugging Face Spaces | Docker, port 7860 | | Docker | Multi-stage build (Node 20 → Python 3.10-slim) | | Alternative | docker-compose (backend:8000, frontend:80) | | CI/CD | Push via `push_hf.bat` | --- ## 4. Cấu Trúc Thư Mục ``` e:\AI\DeepMed\ ├── Dockerfile # Multi-stage: frontend build → backend ├── docker-compose.yml # Local dev: backend:8000 + frontend:80 ├── .env.example # Template env vars ├── push_hf.bat # Deploy to HuggingFace Spaces ├── run.py # Local runner │ ├── backend/ │ ├── requirements.txt # Python dependencies │ ├── pyproject.toml # Project metadata │ ├── app/ │ │ ├── main.py # FastAPI entry + lifespan + SPA serving │ │ ├── core/ │ │ │ ├── config.py # Env vars: GOOGLE_API_KEY, paths │ │ │ ├── logging_config.py │ │ │ └── state.py # (minimal) │ │ ├── api/v1/ │ │ │ ├── api.py # Router aggregator │ │ │ └── endpoints/ │ │ │ ├── chat.py # POST /chat, /clear, /new-chat │ │ │ ├── health.py # GET /health │ │ │ ├── session.py # GET /sessions, /session/{id}, /history │ │ │ └── voice.py # (placeholder) │ │ ├── services/ │ │ │ ├── chat_service.py # ★ CORE: DeepMedBot + ChatService (713 lines) │ │ │ └── database_service.py # CRUD for chat history │ │ ├── tools/ │ │ │ ├── vector_store.py # Qdrant version (LEGACY, not used in current arch) │ │ │ ├── document_loader.py # Drug-aware chunking (for Qdrant version) │ │ │ ├── llm_client.py # Gemini 2.5 Flash singleton │ │ │ └── pdf_loader.py │ │ ├── models/ │ │ │ └── message.py # SQLAlchemy Message model │ │ ├── schemas/ │ │ │ ├── chat.py # ChatRequest, ChatResponse (Pydantic) │ │ │ └── session.py │ │ └── db/ │ │ └── session.py # SQLAlchemy session factory │ │ │ ├── data/ # ★ MEDICAL DATA (Git LFS tracked) │ │ ├── chroma_db/ # ChromaDB persistent storage │ │ ├── thông tin thuốc nội bộ/ # 454 drug .md files │ │ ├── phác đồ bộ y tế/ # 30 MOH guideline PDFs │ │ ├── phác đồ tại ttytkv thanh ba/ # 8 local protocol PDFs │ │ ├── các hiệp hội/ # 10 association guideline PDFs │ │ ├── dược thư quốc gia/ # 1 national formulary PDF (24MB) │ │ └── medical_book.pdf # 16MB reference book │ │ │ ├── storage/ │ │ └── chat_db/ # SQLite DB (medigenius.db) │ └── tests/ │ └── frontend/ ├── package.json ├── vite.config.js ├── tailwind.config.js ├── index.html └── src/ ├── App.jsx # ★ Single-file SPA (722 lines) ├── index.css # Full CSS design system (30KB) ├── index.jsx # React entry point └── App.test.jsx ``` --- ## 5. API Endpoints | Method | Path | Description | Rate Limit | |--------|------|-------------|------------| | POST | `/api/v1/chat` | Send message → HybridRAG response | 15/min/IP | | POST | `/api/v1/clear` | Clear current session history | — | | POST | `/api/v1/new-chat` | Create new session | — | | GET | `/api/v1/health` | Health check | — | | GET | `/api/v1/sessions` | List all chat sessions | — | | GET | `/api/v1/session/{id}` | Get session messages | — | | DELETE | `/api/v1/session/{id}` | Delete a session | — | | GET | `/api/v1/history` | Get current session history | — | ### Request/Response Schema ```python # ChatRequest class ChatRequest(BaseModel): message: str # ChatResponse class ChatResponse(BaseModel): response: str source: str | None timestamp: str | None success: bool ``` --- ## 6. Dữ Liệu Y Tế (Data Sources) ### 6.1. Thông tin thuốc nội bộ (`data/thông tin thuốc nội bộ/`) - **454 file .md** — mỗi file là 1 thuốc trong danh mục TTYT Thanh Ba - Format: `# TÊN_THUỐC` → `Hoạt chất: ...` → nội dung chi tiết - Metadata enrichment: `drug_name`, `active_ingredient`, `ingredient_keywords`, `doc_type` - Ví dụ: MIDANTIN, Ceftriaxone 2000, Amoxicillin 250mg, Metformin... - Bao gồm: giá thuốc, liều dùng, chống chỉ định, tương tác, bảo quản ### 6.2. Phác đồ Bộ Y tế (`data/phác đồ bộ y tế/`) - **30 file PDF** — Quyết định của Bộ Y tế - Các chuyên khoa: Tim mạch, Hô hấp, Tiêu hóa, Thận-Tiết niệu, Nội tiết, Ung bướu, Da liễu, RHM, Lao, Ngộ độc, BPTNMT, COPD... ### 6.3. Phác đồ tại TTYT KV Thanh Ba (`data/phác đồ tại ttytkv thanh ba/`) - **8 file PDF** — phác đồ nội bộ theo chuyên khoa - CKL, HSCC, NTH, NTM, Ngoại, Nhi, Sản, YHCT ### 6.4. Các hiệp hội (`data/các hiệp hội/`) - **10 file PDF** — hướng dẫn từ các hội chuyên khoa (VUNA, etc.) - Viêm phổi cộng đồng, COPD, Bệnh thận mạn, Nhiễm nấm xâm lấn... ### 6.5. Dược thư quốc gia (`data/dược thư quốc gia/`) - **1 file PDF (24MB)** — Dược thư Quốc gia Việt Nam 2023 ### 6.6. Medical book (`data/medical_book.pdf`) - **1 file PDF (16MB)** — sách tham khảo y khoa --- ## 7. Cách Hoạt Động Chi Tiết ### 7.1. Khởi Động (Lifespan) 1. `db_service.init_db()` — tạo bảng SQLite 2. LFS pointer detection — cảnh báo nếu file data < 500 bytes 3. `chat_service.initialize()` → `DeepMedBot()`: - Load embedding model (`paraphrase-multilingual-MiniLM-L12-v2`) - Check ChromaDB có sẵn? → nếu có, skip scan PDF - Nếu chưa: quét toàn bộ `data/` → chunking (1200 chars, overlap 200) → index vào ChromaDB - Build Fast Retriever (BM25 + Vector, k=15) - Build Deep Retriever (BM25 + Vector k=25 → BGE-reranker-v2-m3 top 5) - Init LLM (Gemini 2.5 Flash, temp=0.2) - Build LangChain retrieval chains (history-aware) ### 7.2. Chat Flow 1. User gửi message → `POST /api/v1/chat` 2. Session ID: từ header `X-Session-ID` hoặc cookie 3. Auto-detect mode (Fast/Deep) dựa trên keywords 4. ChatService: - Lưu user message vào SQLite - Convert history → LangChain messages (max 5 turns) - Run active chain: `create_retrieval_chain` → retrieve docs → LLM answer - Extract `[USED_SOURCES: ...]` từ LLM output - Build reference block (chỉ nguồn LLM thực sự dùng) - Lưu assistant response vào SQLite 5. Return JSON response ### 7.3. System Prompt System prompt rất chi tiết (9 nguyên tắc), bắt buộc: - Chỉ trả lời từ Context, không bịa - PHẢI trả lời giá thuốc nếu có trong data - Trích dẫn đúng nguồn, không bịa tên tài liệu - Xác định thuốc đúng bằng header `[Trích từ tài liệu: TÊN_FILE]` - Ưu tiên phác đồ Bộ Y tế VN, WHO - Kết bằng disclaimer - BẮT BUỘC khai báo `[USED_SOURCES: file1 | file2 | ...]` --- ## 8. Environment Variables ```bash # Required GOOGLE_API_KEY=xxx # Gemini 2.5 Flash API key # Optional FORCE_REBUILD_DB=False # True = rebuild ChromaDB on startup DATA_DIR=/app/backend/data CHROMA_DB_PATH=/app/backend/data/chroma_db CHAT_DB_PATH=/app/backend/storage/chat_db/medigenius.db LOG_DIR=/app/backend/logs ALLOWED_ORIGINS=http://localhost:5173,http://localhost:3000,http://localhost:7860 SESSION_SECRET=auto_generated # HF Spaces cache fix (set automatically in Dockerfile) HF_HOME=/tmp/huggingface HUGGINGFACE_HUB_CACHE=/tmp/huggingface/hub SENTENCE_TRANSFORMERS_HOME=/tmp/sentence-transformers TRANSFORMERS_CACHE=/tmp/transformers XDG_CACHE_HOME=/tmp/.cache ``` --- ## 9. Frontend Features - **Single-file SPA**: `App.jsx` (722 lines) — không dùng React Router - **Components**: `ErrorBoundary`, `Sidebar`, `ChatArea`, `MessageBubble`, `InputArea` - **Theme**: Dark/Light mode (toggle, persist localStorage) - **Mobile responsive**: `useIsMobile` hook, sidebar backdrop - **Chat sessions**: New, Load, Delete, Download as .txt - **Quick Questions**: 6 preset medical queries - **Markdown rendering**: `react-markdown` cho bot response - **Copy message**: clipboard API - **Toast notifications**: success/error/info - **Glass morphism design**: `.glass-effect` class - **Animated background**: floating circles + gradient overlay - **Status indicator**: "AI Ready" pulse ring --- ## 10. Deployment (Hugging Face Spaces) ### Dockerfile Flow 1. **Stage 1**: Node 20 Alpine → `npm ci` → `npm run build` → `/app/frontend/dist` 2. **Stage 2**: Python 3.10-slim → install system deps → install torch CPU → install requirements → copy backend → copy frontend dist → set permissions → run uvicorn on port 7860 ### Key Docker Issues (Đã Fix) - **SQLite version**: Python 3.10-slim ships SQLite 3.34, ChromaDB cần ≥ 3.35 → monkey-patch `pysqlite3-binary` - **HF Cache PermissionError**: HF Spaces set `HOME=/nonexistent` → fix: force all cache to `/tmp/` - **Git LFS pointers**: Data files are LFS-tracked → MUST `git lfs pull` before Docker build, or data will be empty stubs - **Non-root user**: `appuser:appgroup` for security, needs `chown` for storage dirs - **ChromaDB batch limit**: Max 5461 per batch → batch upload in groups of 5000 ### Deploy Command ```bash # push_hf.bat git push hf main ``` --- ## 11. Lịch Sử Phát Triển & Các Vấn Đề Đã Giải Quyết ### Phase 1: Initial Build (03/2026) - Xây dựng backend FastAPI + frontend React - Ban đầu dùng Qdrant Cloud cho vector DB - Deploy lên HuggingFace Spaces ### Phase 2: Qdrant Cloud → ChromaDB Migration (04/2026) - Chuyển từ **Qdrant Cloud** sang **ChromaDB local** để giảm latency và dependency - File `tools/vector_store.py` vẫn chứa code Qdrant (LEGACY, không dùng) - Code ChromaDB hiện tại nằm trong `services/chat_service.py` ### Phase 3: LangGraph → HybridRAG Simplification (04/07/2026) - Loại bỏ kiến trúc LangGraph multi-agent phức tạp - Thay bằng HybridRAG đơn giản: ChromaDB + BM25 + CrossEncoder Reranker - 2 modes: Fast / Deep ### Phase 4: UI Modernization (04/08-09/2026) - Redesign UI responsive, mobile-friendly - Thêm sidebar chat history, dark/light theme - Glass morphism, animated background ### Known Issues / TODO - `tools/vector_store.py` — **LEGACY** code cho Qdrant, không dùng nữa nhưng chưa xóa - `tools/document_loader.py` — Version cũ với drug-aware chunking cho Qdrant - `core/langgraph_workflow.py` — Stub file, nội dung trống - `core/state.py` — Stub file, nội dung minimal - `docker-compose.yml` — Lỗi thời, dùng port 8000/80 thay vì 7860 - `agents/` folder — Có file `tavily.py` nhưng không được import trong main flow - `tools/duckduckgo_search.py`, `tools/wikipedia_search.py`, `tools/tavily_search.py` — Search tools không dùng trong HybridRAG hiện tại - Database service vẫn gọi là "MediGenius" trong docstring (tên cũ) - Frontend: Nút Settings chưa có chức năng --- ## 12. Commands ```bash # ── Local Development ── cd e:\AI\DeepMed\frontend && npm run dev # Frontend: localhost:5173 cd e:\AI\DeepMed\backend && uvicorn app.main:app --reload --port 8000 # Backend # ── Docker Build ── docker build -t deepmed-ai . docker run -p 7860:7860 -e GOOGLE_API_KEY=xxx deepmed-ai # ── Force Rebuild ChromaDB ── FORCE_REBUILD_DB=True uvicorn app.main:app # ── Run Tests ── cd frontend && npm test cd backend && pytest # ── Deploy to HF Spaces ── push_hf.bat ``` --- ## 13. File Quan Trọng Nhất (Quick Reference) | Mục đích | File | |----------|------| | **Entry point** | `backend/app/main.py` | | **Core logic** | `backend/app/services/chat_service.py` (713 lines) | | **Chat API** | `backend/app/api/v1/endpoints/chat.py` | | **Config** | `backend/app/core/config.py` | | **LLM** | `backend/app/tools/llm_client.py` | | **Frontend SPA** | `frontend/src/App.jsx` (722 lines) | | **CSS** | `frontend/src/index.css` (30KB) | | **Docker** | `Dockerfile` (92 lines, multi-stage) | | **Dependencies** | `backend/requirements.txt` | | **Env template** | `.env.example` | --- ## 14. Lưu Ý Khi Chỉnh Sửa 1. **System prompt** nằm trong `chat_service.py` (2 bản: `QA_SYSTEM_PROMPT_FAST` và `QA_SYSTEM_PROMPT_DEEP`). Cũng có bản trong `llm_client.py` (LEGACY). 2. **ChromaDB** logic hoàn toàn trong `chat_service.py`, KHÔNG phải `vector_store.py` (đó là Qdrant legacy). 3. **Document loading** trong `chat_service.py` dùng `_load_documents_from_folder()` riêng, KHÔNG phải `document_loader.py` (đó cũng là Qdrant legacy). 4. **Frontend** là single-file React (`App.jsx`), không có routing. CSS ~30KB custom. 5. **Deploy** phải đảm bảo `git lfs pull` trước khi build Docker, nếu không data sẽ trống. 6. **SQLite monkey-patch** PHẢI ở đầu `main.py`, trước mọi chromadb import. 7. **HF cache paths** PHẢI set trước khi import sentence-transformers/transformers.