Xu ly SSO

This commit is contained in:
2026-05-09 10:31:28 +00:00
parent 9d04e7484c
commit f937d1a98e
21 changed files with 2515 additions and 271 deletions

View File

@@ -1,88 +1,202 @@
# 🧭 AGENT ARCHITECTURE MAP (LIVING DOCUMENT)
*Đây là tài liệu dẫn đường dành riêng cho các AI Agent tương lai và lập trình viên bảo trì. Không quét toàn bộ code, hãy đọc file này trước.*
**Lần cập nhật cuối:** Phase 6 (Hoàn thiện Semantic Chunking & Vector Indexing)
**Trạng thái Dự án:** Đã hoàn thành Ingestion, Extraction, Chunking & Indexing. Chuẩn bị bước vào Phase 7 (RAG Search & Chat API).
**Lần cập nhật cuối:** Phase 8 Complete (DCE, Text Extraction, ACL, SSO, Logging)
**Trạng thái Dự án:** Phase 8 hoàn thành. Sẵn sàng cho Phase 9 (Production Ready).
---
## 1. Bản Đồ Kiến Trúc Lõi (Core Architecture Patterns)
### Pipeline hiện tại (ĐÃ HOẠT ĐỘNG)
```
SharePoint → Ingestion → DCE → [OCR/Extract/Skip] → Chunking → OpenSearch → Search → RAG Chat → FastAPI → Frontend
```
### A. Tầng Ingestion (Thu thập dữ liệu) - Mẫu Modular Provider Pattern
- **Mục tiêu:** Tách biệt lõi hệ thống khỏi nền tảng lưu trữ (SharePoint, Google Drive, v.v.).
- **Interface gốc:** `ingestion/providers/base_provider.py` (Bắt buộc phải implement `fetch_changes` `download_file`).
- **Implement hiện tại:** `ingestion/providers/sharepoint_provider.py`. Nó bọc lại `GraphClient` tự động xử lý thuật toán phân trang (pagination) để lấy dữ liệu Delta.
- **Nếu cần thêm nguồn dữ liệu mới (ví dụ: NAS, Google Drive):** Chỉ cần tạo một class mới kế thừa `BaseStorageProvider`. Lõi hệ thống không cần biết về API của nguồn đó.
- **Interface:** `ingestion/providers/base_provider.py` (`fetch_changes`, `download_file`, `get_item_details`, `get_item_permissions`).
- **Implement hiện tại:** `ingestion/providers/sharepoint_provider.py`. Bọc lại `GraphClient`, tự động xử lý pagination Delta Query.
- **Sync Engine:** `ingestion/sync.py``SyncEngine` nhận `BaseStorageProvider` qua constructor, provider-agnostic.
- **Nếu cần thêm nguồn dữ liệu mới:** Chỉ cần tạo class mới kế thừa `BaseStorageProvider`.
### B. Tầng Extraction (Xử lý chữ & Ảnh) - Mẫu Distributed VLM Pattern
- **Lịch sử:** Đã từng dùng PaddleOCR + VietOCR nhưng gặp lỗi "Rụng dấu" và "Ảo giác" do cắt ảnh sai.
- **Kiến trúc hiện tại:** Hệ thống đóng vai trò như một **VLM Client**.
- **Cách hoạt động:** `extraction/ocr_service.py` render file PDF thành ảnh (DPI=86), nén Base64 và bắn POST Request sang một Server LLM khác trong mạng LAN (chạy `llama.cpp` với model `Vintern-3B`).
- **Lợi ích:** Giải phóng hoàn toàn RAM cho máy chủ RAG, loại bỏ các thư viện AI nặng nền (Torch, Paddle). Lấy được Markdown nguyên bản, không gãy vỡ layout bảng biểu.
- **Lịch sử:** Đã từng dùng PaddleOCR + VietOCR nhưng gặp lỗi "Rụng dấu" và "Ảo giác". Đã loại bỏ hoàn toàn.
- **Kiến trúc hiện tại:** Hệ thống đóng vai trò **VLM Client**.
- **Cách hoạt động:** `extraction/ocr_service.py` render PDF thành ảnh (Matrix=1.2), nén Base64, POST sang server LAN (`10.202.50.3:8080`) chạy `llama.cpp` + `Vintern-3B`.
- **Lợi ích:** Giải phóng RAM cho máy chủ RAG, lấy được Markdown nguyên bản.
### C. Tầng Chunking & Vector DB (Semantic Indexing)
- **Chunking:** `chunking/markdown_chunker.py` chia nhỏ văn bản bằng Markdown Rules (nhận biết Header `#`, duy trì overlap chống đứt gãy ngữ cảnh), tự động theo dõi `page_from`, `page_to` chuẩn xác.
- **Embedding:** Dùng thư viện `sentence-transformers` với model `keepitreal/vietnamese-sbert` chạy Local/Offline. Tạo ra Vector 768 chiều chuyên biệt cho Tiếng Việt.
- **Database:** `indexing/vector_store.py` cấu hình OpenSearch với thuật toán `k-NN HNSW`. Index mặc định là `poc_sharepoint_docs` hoặc `sharepoint_docs`.
- **Chunking:** `chunking/markdown_chunker.py` chia nhỏ bằng Markdown Rules (Header `#`, overlap), theo dõi `page_from`, `page_to`.
- **Embedding:** `sentence-transformers` với model `keepitreal/vietnamese-sbert` (local, 768 chiều).
- **Database:** `indexing/vector_store.py` OpenSearch `k-NN HNSW`. Index: `poc_sharepoint_docs`.
- **Dedup:** `VectorStore.delete_by_file_id()` xóa chunks cũ trước khi nạp lại.
### D. Tầng Cấu hình (Decoupled Configuration)
- Toàn bộ thông số hệ thống, đặc biệt là IP máy chủ VLM, Token của SharePoint đều nằm trong `.env`.
- Mã nguồn load cấu hình thông qua `core/config.py`.
### D. Tầng Search & RAG Chat
- **Retriever:** `search/retriever.py` → Semantic Search (k-NN vector) trên OpenSearch.
- **RAG Engine:** `chat/rag_engine.py` → Search → Augment Context → LLM Generate.
- **LLM Factory:** `chat/llm_factory.py` → Hỗ trợ Gemini, Groq, Local (config trong `.env`).
### E. Tầng API & Frontend
- **Backend:** `api/main.py` → FastAPI tại port 8000. Endpoint: `/health`, `/auth/login` (SSO), `/auth/callback`, `/auth/login-email`, `/chat`, `/sync`, `/sync/status`.
- **Frontend:** `frontend/` → Glassmorphism UI với SSO login + email fallback + sync button. Gọi `http://localhost:8000`.
### F. Tầng Cấu hình (Decoupled Configuration)
- Toàn bộ thông số trong `.env`. Load qua `core/config.py`.
- **Tuyệt đối KHÔNG hardcode URL, Token hay Password trong code.**
---
## 2. Bản Đồ File & Thư Mục Quan Trọng
## 2. Bản Đồ File & Thư Mục Hoàn Chỉnh
```text
📁 poc_system/
├── 📁 core/
│ ├── config.py # ⚙️ Trái tim cấu hình (Load từ .env)
── models.py # 🧩 Định nghĩa Data Classes (OCRPageResult, v.v.)
│ ├── config.py # ⚙️ Trái tim cấu hình (Load từ .env)
── models.py # 🧩 Data Classes (OCRPageResult, DocumentChunk, IngestedDocument)
│ └── logging.py # 📝 Structured logging (JSON/human formatter)
├── 📁 ingestion/
│ ├── sync.py # 🔄 Bộ điều phối đồng bộ (Đang chuẩn bị ghép với BaseStorageProvider)
│ ├── graph_client.py # 🌐 Microsoft Graph API Client (Bọc Auth)
│ └── 📁 providers/ # 🔌 Nơi chứa các plugin kết nối dữ liệu
│ ├── base_provider.py
│ ├── sync.py # 🔄 SyncEngine (Provider-agnostic)
│ ├── graph_client.py # 🌐 Microsoft Graph API Client
│ └── 📁 providers/
│ ├── base_provider.py # 🔌 Interface: fetch_changes, download_file, get_item_details
│ └── sharepoint_provider.py
├── 📁 extraction/
── ocr_service.py # 👁 VLM Client (Chuyển ảnh -> Text Markdown qua LAN)
├── .env # 🔑 Chìa khoá và địa chỉ mạng (KHÔNG commit file này)
└── test_modular_architecture.py # 🧪 Script kiểm tra nhanh kết nối các module
── dce.py # 🏷 Document Classification Engine (phân loại trước khi xử lý)
│ ├── pdf_inspector.py # 🔎 PDF Inspection (TEXT_PDF / SCAN_PDF / DRAWING_PDF)
│ ├── magic_numbers.py # 🔢 Magic Number validation (chống giả extension)
│ ├── text_extractor.py # 📄 Text extraction: DOCX (python-docx), XLSX (openpyxl), TXT
│ └── ocr_service.py # 👁️ VLM Client (PDF → Markdown qua LAN)
├── 📁 chunking/
│ └── markdown_chunker.py # ✂️ Semantic Chunking theo Markdown rules
├── 📁 indexing/
│ └── vector_store.py # 📦 OpenSearch k-NN Index + Embedding
├── 📁 search/
│ └── retriever.py # 🔍 Semantic Search (k-NN vector)
├── 📁 chat/
│ ├── rag_engine.py # 🤖 RAG: Search → Context → LLM
│ ├── llm_factory.py # 🏭 Factory: Gemini / Groq / Local
│ └── 📁 llm_providers/
│ ├── base_llm.py
│ ├── gemini_llm.py
│ ├── groq_llm.py
│ └── local_llm.py
├── 📁 api/
│ └── main.py # 🚀 FastAPI Backend (port 8000)
├── 📁 frontend/
│ ├── index.html # 🎨 Glassmorphism UI (Login + Chat + Sync)
│ ├── app.js # 💬 Chat, Auth, Sync logic
│ └── style.css # 🖌️ CSS
├── 📁 doc/ # 📚 Tài liệu dự án
│ ├── 00.AGENT_ARCHITECTURE_MAP.md # Bản đồ kiến trúc
│ ├── AGENT_HANDOVER_PROTOCOL.md # Protocol cho AI Agent
│ ├── DEPLOYMENT_GUIDE.md # Hướng dẫn triển khai & cấu hình
│ └── ... # Các tài liệu khác
├── .env # 🔑 Chìa khoá (KHÔNG commit)
├── docker-compose.yml # 🐳 OpenSearch
├── Dockerfile
├── requirements.txt
├── test_rag_pipeline.py # 🧪 Test toàn bộ pipeline
├── test_graph_smoke.py # 🧪 Test kết nối Graph API
├── test_modular_architecture.py
├── test_chat.py
├── test_ocr.py
└── test_dce_pipeline.py
```
---
## 3. Lịch Sử Các Lỗi Khét Tiếng & Cách Xử Lý (Known Gotchas)
1. **Lỗi 401 Unauthorized khi tải file từ SharePoint:**
- *Nguyên nhân:* Microsoft chặn download trực tiếp bằng `@microsoft.graph.downloadUrl` nếu dùng App-Only Token.
- *Giải pháp:* Dùng endpoint `.../items/{item_id}/content` kèm Bearer Token (Đã cài đặt trong `graph_client.py`).
- *Giải pháp:* Dùng endpoint `.../items/{item_id}/content` kèm Bearer Token.
2. **Lỗi 500 Internal Server Error từ Llama.cpp VLM:**
- *Nguyên nhân:* Bức ảnh ném vào VLM có độ phân giải quá cao (Matrix 2.0) làm tràn Context Window (ví dụ: Token ảnh > 4096).
- *Giải pháp:* Hạ `Matrix` xuống `1.2`, hoặc khởi chạy Server Llama.cpp với `-c 8192`. Bắt buộc phải có file `--mmproj`.
- *Nguyên nhân:* Ảnh có độ phân giải quá cao (Matrix 2.0) làm tràn Context Window.
- *Giải pháp:* Hạ `Matrix` xuống `1.2`, hoặc khởi chạy Server với `-c 8192`.
3. **Lỗi Rụng dấu / Ảo giác của VietOCR:**
- *Nguyên nhân:* PaddleOCR bắt khung quá khít, làm cụt phần đuôi của các chữ tiếng Việt có dấu. Mô hình `vgg_seq2seq` tự nội suy ra từ tiếng Anh linh tinh.
- *Giải pháp triệt để:* Đã loại bỏ hoàn toàn VietOCR, chuyển sang dùng VLM (Vintern-3B).
- *Nguyên nhân:* PaddleOCR bắt khung quá khít, mô hình `vgg_seq2seq` nội suy sai.
- *Giải pháp triệt để:* Đã loại bỏ hoàn toàn VietOCR, chuyển sang VLM (Vintern-3B).
4. **Lỗi UTF-8 Surrogate (\udcc3) trong Terminal WSL:**
- *Hiện tượng:* Câu hỏi đầu tiên đúng, nhưng từ câu thứ 2 bị lỗi mã hóa khi dùng `input()`.
- *Nguyên nhân:* Do sự không đồng nhất giữa `sys.stdin` và bộ đệm Terminal sau khi in lượng lớn dữ liệu từ LLM.
- *Giải pháp:* Sử dụng `sys.stdin.buffer.readline()` để đọc dữ liệu thô (Bytes) và tự decode bằng UTF-8. Đây là giải pháp cho môi trường CLI, khi lên Web API (FastAPI) sẽ không bị ảnh hưởng.
- *Giải pháp:* Dùng `sys.stdin.buffer.readline()` cho CLI. Web API (FastAPI) không bị ảnh hưởng.
5. **Lỗi Link SharePoint không ổn định (Bug #101):**
- *Nguyên nhân:* Delta Query không trả về `webUrl``@microsoft.graph.downloadUrl`.
- *Giải pháp:* Thêm `get_item_details()` vào `graph_client.py`, `base_provider.py`, `sharepoint_provider.py`.
6. **Lỗi Chunks trùng lặp khi chạy lại pipeline:**
- *Hiện tượng:* Mỗi lần chạy `test_rag_pipeline.py`, chunks mới được thêm chồng lên chunks cũ (cùng file).
- *Nguyên nhân:* `chunk_id` dùng UUID ngẫu nhiên, không có bước xóa cũ.
- *Giải pháp:* `VectorStore.delete_by_file_id(file_id)` gọi trước `embed_and_index()`.
7. **Lỗi DCE download PDF 401 Unauthorized:**
- *Hiện tượng:* DCE không phân loại được PDF vì download file bị 401.
- *Nguyên nhân:* DCE dùng httpx trực tiếp với `@microsoft.graph.downloadUrl` (không có Bearer Token).
- *Giải pháp:* Truyền `provider` (BaseStorageProvider) vào DCE constructor, dùng `provider.download_file()` thay vì httpx.
8. **Lỗi DCE download 404 (items/None/content):**
- *Hiện tượng:* DCE download PDF bị 404 vì URL có `items/None/content`.
- *Nguyên nhân:* `ingestion_output.json` dùng key `item_id` nhưng `download_file()` cần `id`.
- *Giải pháp:* DCE tự chuẩn hóa `item_id``id` khi thiếu.
9. **Lỗi OpenSearch hostname không resolve khi chạy ngoài Docker:**
- *Hiện tượng:* `ConnectionError: Failed to resolve 'opensearch'`.
- *Nguyên nhân:* Config `.env``opensearch_host=opensearch` (Docker hostname).
- *Giải pháp:* `VectorStore``SearchRetriever` tự detect: nếu host là "opensearch" và ENV != "docker" → đổi sang "localhost".
10. **Lỗi k-NN query format sai cho OpenSearch 2.x:**
- *Hiện tượng:* `Unknown key for a START_OBJECT in [knn]`.
- *Nguyên nhân:* Đặt `knn` ở top level thay vì trong `query`.
- *Giải pháp:* Đặt `knn` bên trong `query` object.
---
## 4. Nhiệm Vụ Tiếp Theo (Dành cho Lập Trình Viên/AI Agent)
- [ ] **Phase 7:** Bọc thành API Backend bằng FastAPI.
## 4. Nhiệm Vụ Tiếp Theo (Phase 9 - Production Ready)
### Đã hoàn thành ✅
- [x] Ingestion: SharePoint Provider + Delta Query + Pagination
- [x] DCE: Document Classification Engine (phân loại file theo extension + PDF inspection)
- [x] PDF Inspection: Detect text layer, classify TEXT_PDF / SCAN_PDF / DRAWING_PDF
- [x] Conditional OCR: Chỉ OCR SCAN_PDF, TEXT_PDF extract trực tiếp, skip DRAWING/UNSUPPORTED
- [x] Extraction: VLM OCR (Vintern-3B qua LAN)
- [x] Chunking: Semantic Markdown Chunker
- [x] Indexing: OpenSearch k-NN HNSW + vietnamese-sbert
- [x] Search: Semantic Retriever
- [x] RAG Chat: LLM Factory (Gemini/Groq/Local)
- [x] API: FastAPI Backend (/chat, /health, /sync, /sync/status)
- [x] Frontend: Glassmorphism UI
- [x] Bug fixes: SharePoint links, Chunk dedup
- [x] Refactor: SyncEngine provider-agnostic
- [x] Logging: Structured logging utility (`core/logging.py`)
- [x] Permission: ACL extraction từ SharePoint + filter search theo user
- [x] Auth UI: Simple email login + SSO Azure AD + user context cho API calls
- [x] DOCX Text Extraction: python-docx (paragraphs + tables)
- [x] XLSX Text Extraction: openpyxl (sheets + cells)
### Chưa triển khai (Phase 9 - Production Ready)
#### Ưu tiên trung bình
- [ ] **Cấu hình Azure AD cho SSO:** Thêm Redirect URI `http://localhost:8000/auth/callback` và bật "ID tokens" trong App Registration.
#### Ưu tiên thấp
- [ ] **Monitoring Dashboard:** Health metrics, ingestion status, OCR success rate.
- [ ] **Multi-tenant:** Hỗ trợ nhiều SharePoint site/tenant.
---
## 5. Tiêu chuẩn Lập trình & Môi trường (Coding Standards)
### A. Quản lý Mã hóa (Encoding)
- **Quy tắc vàng:** Luôn sử dụng `encoding='utf-8'` trong mọi lệnh `open()`. Tuyệt đối không dựa dẫm vào encoding mặc định của hệ điều hành.
- **Môi trường:** Hệ thống được thiết kế để chạy trong môi trường UTF-8. Trong Docker hoặc WSL, luôn đảm bảo biến môi trường `PYTHONIOENCODING=utf-8` được thiết lập. Điều này giúp hệ thống tương thích 100% với các ký tự Tiếng Việt từ LLM mà không cần hack code.
- **Quy tắc vàng:** Luôn sử dụng `encoding='utf-8'` trong mọi lệnh `open()`.
- **Môi trường:** `PYTHONIOENCODING=utf-8` trong Docker/WSL.
### B. Mẫu Provider (Provider Pattern)
- Mọi kết nối tới dịch vụ bên thứ ba (Storage, LLM) phải thông qua Interface/BaseClass để đảm bảo tính "Cắm rút" (Pluggable).
- Mọi kết nối tới dịch vụ bên thứ ba (Storage, LLM) phải thông qua Interface/BaseClass.
- `BaseStorageProvider` cho Storage, `BaseLLMProvider` cho LLM.
### C. Quy tắc an toàn
- Không commit `.env`, không hardcode secrets.
- Không thay đổi kiến trúc đã chốt trong `doc/14.Project-Bridge-Context-for-New-Chat.md` mà không có lý do kỹ thuật rõ ràng.

View File

@@ -0,0 +1,98 @@
# 🤖 AGENT HANDOVER PROTOCOL (Dành cho AI Agent)
> **QUAN TRỌNG:** Nếu bạn là AI Agent mới, hãy đọc file này kết hợp với `doc/00.AGENT_ARCHITECTURE_MAP.md` trước khi viết bất kỳ dòng code nào.
## 1. Tóm tắt "Bộ nhớ" Dự án (Memory Snapshot)
Dự án này là một hệ thống **Enterprise RAG** (Retrieval-Augmented Generation) với các đặc điểm kỹ thuật:
- **Distributed VLM OCR:** Dùng máy chủ LAN (`10.202.50.3:8080`) chạy `Vintern-3B` để trích xuất Markdown từ PDF.
- **Modular Provider Pattern:** Tách biệt Storage (SharePoint) và LLM (Gemini, Groq, Local).
- **Semantic Indexing:** Dùng `vietnamese-sbert` (local) tạo vector 768 chiều, lưu vào OpenSearch k-NN HNSW.
- **FastAPI Backend:** API tại port 8000. Endpoint: `/health`, `/chat`.
- **Glassmorphism UI:** Giao diện web tại `frontend/`, gọi `http://localhost:8000/chat`.
**Pipeline hiện tại (ĐÃ HOẠT ĐỘNG):**
```
SharePoint → Ingestion → VLM OCR → Chunking → OpenSearch → Search → RAG Chat → FastAPI → Frontend
```
## 2. Trạng thái triển khai
### ✅ Đã hoàn thành
| Module | File | Mô tả |
|--------|------|-------|
| Ingestion | `ingestion/providers/sharepoint_provider.py` | Delta Query + Pagination + get_item_details |
| Sync Engine | `ingestion/sync.py` | Provider-agnostic, nhận BaseStorageProvider |
| DCE | `extraction/dce.py` | Document Classification Engine (phân loại file) |
| PDF Inspector | `extraction/pdf_inspector.py` | TEXT_PDF / SCAN_PDF / DRAWING_PDF / AMBIGUOUS_PDF |
| Magic Numbers | `extraction/magic_numbers.py` | Header byte validation |
| OCR | `extraction/ocr_service.py` | VLM Client (Vintern-3B qua LAN) |
| Chunking | `chunking/markdown_chunker.py` | Semantic Markdown rules + page tracking |
| Indexing | `indexing/vector_store.py` | OpenSearch k-NN + delete_by_file_id dedup |
| Search | `search/retriever.py` | Semantic k-NN vector search |
| RAG Chat | `chat/rag_engine.py` | Search → Context → LLM |
| LLM Factory | `chat/llm_factory.py` | Gemini / Groq / Local |
| API | `api/main.py` | FastAPI port 8000 |
| Frontend | `frontend/` | Glassmorphism UI (HTML/CSS/JS) |
| Bug fixes | Nhiều file | SharePoint links (Bug #101), Chunk dedup |
### ❌ Chưa triển khai (Phase 8)
- **DOCX Text Extraction:** Trích xuất text từ DOCX không cần OCR
- **XLSX Text Extraction:** Trích xuất header + key columns từ Excel
- **Permission Enforcement:** ACL filtering theo user/group
- **Authentication UI:** OAuth2 login
- **Ingestion API:** Trigger sync từ frontend
- **Logging & Audit:** Structured logging
## 3. Hướng dẫn dành cho AI Agent tiếp theo
1. **Luôn kiểm tra `.env`:** Toàn bộ cấu hình nằm ở đây. Không bao giờ hardcode.
2. **Sử dụng `core/config.py`:** Cửa ngõ duy nhất để truy cập cài đặt.
3. **UTF-8:** Mọi I/O phải có `encoding='utf-8'`. Đặt `export PYTHONIOENCODING=utf-8`.
4. **Cập nhật tài liệu:** Khi hoàn thành Phase hoặc thay đổi kiến trúc, BẮT BUỘC cập nhật file này và `00.AGENT_ARCHITECTURE_MAP.md`.
5. **Đọc `doc/14.Project-Bridge-Context-for-New-Chat.md`:** Đây là "hợp đồng kiến trúc" - không thay đổi các quyết định đã chốt.
## 4. Cách cập nhật Tài liệu (Protocol for Updates)
- **Bước 1:** Cập nhật trạng thái trong `doc/00.AGENT_ARCHITECTURE_MAP.md` (đánh dấu ✅ vào checkbox).
- **Bước 2:** Nếu phát hiện lỗi mới, ghi lại vào mục **"Lịch sử các lỗi khét tiếng"** kèm giải pháp.
- **Bước 3:** Cập nhật mục **Trạng thái triển khai** trong file này.
## 5. Lệnh chạy nhanh (Quick Start)
```bash
# Khởi động OpenSearch
docker-compose up -d opensearch
# Chạy Backend (FastAPI port 8000)
python3 api/main.py
# Mở Frontend
# Mở frontend/index.html trong trình duyệt (hoặc dùng Live Server)
# Nạp dữ liệu từ SharePoint → OCR → Chunk → Index
python3 test_rag_pipeline.py
```
## 6. Kiểm tra nhanh (Verification)
```bash
# 1. Kiểm tra cú pháp Python
python3 -m py_compile ingestion/graph_client.py
python3 -m py_compile ingestion/providers/sharepoint_provider.py
python3 -m py_compile ingestion/sync.py
python3 -m py_compile indexing/vector_store.py
python3 -m py_compile api/main.py
python3 -m py_compile test_rag_pipeline.py
# 2. Test kết nối Graph API
python3 test_graph_smoke.py
# 3. Test toàn bộ pipeline (cần OpenSearch + VLM server)
python3 test_rag_pipeline.py
# 4. Kiểm tra metadata
cat ingestion_output.json | python3 -m json.tool | grep -E '"web_url"|"download_url"'
# 5. Test API endpoint
curl http://localhost:8000/health
curl -X POST http://localhost:8000/chat -H "Content-Type: application/json" -d '{"query":"test"}'
```
---
*Chúc may mắn, Agent đồng nghiệp! Pipeline RAG đã hoạt động. Tiếp theo: DCE, Permission, Hardening.*

366
doc/DEPLOYMENT_GUIDE.md Normal file
View File

@@ -0,0 +1,366 @@
# 🚀 Hướng dẫn Triển khai & Cấu hình Hệ thống
> Tài liệu này hướng dẫn cấu hình manual, biến môi trường, và các lưu ý khi triển khai từ PoC lên Production.
---
## 1. Cấu hình Azure AD App Registration (MANUAL)
### 1.1 Tạo App Registration (nếu chưa có)
1. Vào **Azure Portal****Azure Active Directory****App registrations****New registration**
2. Điền thông tin:
- **Name:** `VibeCode-RAG-PoC` (hoặc tên tuỳ chọn)
- **Supported account types:** `Single tenant` (chỉ tenant công ty)
- **Redirect URI:** Để trống, sẽ thêm sau
3. Bấm **Register**
4. Ghi lại:
- **Application (client) ID** → dùng cho `CLIENT_ID`
- **Directory (tenant) ID** → dùng cho `TENANT_ID`
### 1.2 Tạo Client Secret
1. App Registration → **Certificates & secrets****New client secret**
2. Điền Description: `RAG PoC Secret`
3. Chọn thời hạn: `24 months` (hoặc tuỳ nhu cầu)
4. Bấm **Add**
5. **Copy ngay giá trị Secret** → dùng cho `CLIENT_SECRET` (chỉ hiện 1 lần)
### 1.3 Cấp quyền Application Permissions
1. App Registration → **API permissions****Add a permission**
2. Chọn **Microsoft Graph****Application permissions**
3. Tìm và tích:
- `Sites.Read.All` (đọc SharePoint sites)
- `Files.Read.All` (đọc files trong drives)
4. Bấm **Add permissions**
5. **Quan trọng:** Bấm **Grant admin consent for [tenant]** → Confirm
### 1.4 Cấu hình Redirect URI cho SSO (khi cần login)
1. App Registration → **Authentication****Add a platform****Web**
2. Nhập Redirect URI:
- **PoC (localhost):** `http://localhost:8000/auth/callback`
- **Production:** `https://your-domain.com/auth/callback`
3. Tích chọn: ✅ **ID tokens** (implicit grant)
4. Bấm **Save**
### 1.5 Kiểm tra Token Claims
Sau khi cấu hình xong, decode token JWT và kiểm tra:
```text
aud : https://graph.microsoft.com
appid : <client-id-của-bạn>
idtyp : app
roles :
- Sites.Read.All
- Files.Read.All
```
Nếu token **không có `roles`** → quyền chưa đúng, kiểm tra lại bước 1.3.
---
## 2. Biến môi trường (.env)
### 2.1 File mẫu
```env
# ===== Azure AD / Microsoft Graph =====
TENANT_ID=your-tenant-id-guid
CLIENT_ID=your-client-id-guid
CLIENT_SECRET=your-client-secret-value
# ===== SharePoint =====
# Site path để ingestion (đổi thành site SharePoint của bạn)
# Format: hostname:/sites/site-name
# Ví dụ: 285pdg.sharepoint.com:/sites/poc_system
# ===== OpenSearch =====
OPENSEARCH_HOST=opensearch # Docker: "opensearch", Local: "localhost"
OPENSEARCH_PORT=9200
OPENSEARCH_USER=admin
OPENSEARCH_PASS=admin
# ===== VLM OCR Server (Vintern-3B) =====
VLM_ENDPOINT=http://10.202.50.3:8080/v1/chat/completions
VLM_TEMPERATURE=0.1
VLM_MAX_TOKENS=2000
VLM_TIMEOUT=120.0
# ===== Chat LLM =====
LLM_PROVIDER=gemini # Options: gemini, groq, local
GEMINI_API_KEY=your-gemini-api-key
GROQ_API_KEY=your-groq-api-key
GROQ_MODEL=llama-3.3-70b-versatile
LOCAL_LLM_ENDPOINT=http://10.202.50.3:8081/v1/chat/completions
# ===== General =====
LOG_LEVEL=INFO
ENVIRONMENT=development # development hoặc production
```
### 2.2 Giải thích từng biến
| Biến | Bắt buộc | Mô tả |
|------|----------|-------|
| `TENANT_ID` | ✅ | Azure AD Tenant ID |
| `CLIENT_ID` | ✅ | Azure AD App Registration Client ID |
| `CLIENT_SECRET` | ✅ | Azure AD App Registration Client Secret |
| `OPENSEARCH_HOST` | ✅ | Hostname OpenSearch |
| `OPENSEARCH_PORT` | ✅ | Port OpenSearch (mặc định 9200) |
| `VLM_ENDPOINT` | ✅ | URL server VLM OCR (Vintern-3B) |
| `LLM_PROVIDER` | ✅ | LLM provider: `gemini`, `groq`, hoặc `local` |
| `GEMINI_API_KEY` | Nếu dùng Gemini | API key từ Google AI Studio |
| `GROQ_API_KEY` | Nếu dùng Groq | API key từ Groq Console |
| `ENVIRONMENT` | ✅ | `development` hoặc `production` |
---
## 3. Kết nối SharePoint khác
### 3.1 Thay đổi Site Path
Chỉnh sửa trong file `ingestion/providers/sharepoint_provider.py`:
```python
# Dòng 14 - Thay đổi hostname và site_path
def __init__(self, hostname: str = "your-company.sharepoint.com", site_path: str = "/sites/your-site-name"):
```
Hoặc gọi từ bên ngoài:
```python
provider = SharePointProvider(
hostname="your-company.sharepoint.com",
site_path="/sites/your-site-name"
)
```
### 3.2 Kiểm tra quyền truy cập
App Registration phải có quyền trên site mới:
1. Nếu dùng **Application Permissions** (`Sites.Read.All`) → tự động truy cập mọi site
2. Nếu muốn giới hạn site cụ thể → dùng **SharePoint App-Only Policy** (nâng cao)
### 3.3 Xoá dữ liệu cũ
Khi đổi SharePoint site, cần xoá index cũ:
```bash
curl -X DELETE -u admin:admin "http://localhost:9200/poc_sharepoint_docs"
```
Sau đó chạy lại `python3 test_rag_pipeline.py` để nạp dữ liệu mới.
---
## 4. Triển khai Production
### 4.1 Yêu cầu hạ tầng
| Component | Yêu cầu tối thiểu | Khuyến nghị |
|-----------|-------------------|-------------|
| Server chính | 4 CPU, 8GB RAM | 8 CPU, 16GB RAM |
| OpenSearch | 2 CPU, 4GB RAM | 4 CPU, 8GB RAM |
| VLM OCR Server | GPU 8GB VRAM | GPU 16GB VRAM |
| Domain | Có SSL certificate | Let's Encrypt |
### 4.2 Docker Compose Production
```yaml
# docker-compose.prod.yml
version: '3.8'
services:
opensearch:
image: opensearchproject/opensearch:2.11.1
environment:
- discovery.type=single-node
- OPENSEARCH_INITIAL_ADMIN_PASSWORD=StrongPassword123!
ports:
- "9200:9200"
volumes:
- opensearch-data:/usr/share/opensearch/data
rag-api:
build: .
ports:
- "8000:8000"
env_file: .env
environment:
- ENVIRONMENT=production
- OPENSEARCH_HOST=opensearch
depends_on:
- opensearch
nginx:
image: nginx:alpine
ports:
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
- ./certs:/etc/nginx/certs
- ./frontend:/usr/share/nginx/html
depends_on:
- rag-api
volumes:
opensearch-data:
```
### 4.3 Nginx config mẫu
```nginx
# nginx.conf
events {
worker_connections 1024;
}
http {
server {
listen 443 ssl;
server_name your-domain.com;
ssl_certificate /etc/nginx/certs/fullchain.pem;
ssl_certificate_key /etc/nginx/certs/privkey.pem;
# Frontend
location / {
root /usr/share/nginx/html;
index index.html;
try_files $uri $uri/ /index.html;
}
# API
location /api/ {
proxy_pass http://rag-api:8000/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
# Redirect HTTP → HTTPS
server {
listen 80;
server_name your-domain.com;
return 301 https://$host$request_uri;
}
}
```
### 4.4 Thay đổi khi Production
1. **Frontend:** Sửa `API_BASE` trong `app.js`:
```javascript
const API_BASE = '/api'; // Thay vì 'http://localhost:8000'
```
2. **SSO Redirect URI:** Cập nhật trong Azure AD:
```
https://your-domain.com/auth/callback
```
3. **.env:**
```env
OPENSEARCH_HOST=opensearch
ENVIRONMENT=production
```
4. **OpenSearch password:** Đổi password mặc định:
```env
OPENSEARCH_USER=admin
OPENSEARCH_PASS=YourStrongPassword123!
```
5. **CORS:** Giới hạn origins trong `api/main.py`:
```python
allow_origins=["https://your-domain.com"]
```
---
## 5. Kiểm tra sau triển khai
### 5.1 Kiểm tra kết nối
```bash
# 1. OpenSearch
curl -u admin:admin http://localhost:9200/_cluster/health
# 2. API
curl http://localhost:8000/health
# 3. Frontend
curl -I http://localhost/
```
### 5.2 Kiểm tra SSO
1. Mở `https://your-domain.com`
2. Bấm "Đăng nhập Microsoft SSO"
3. Đăng nhập bằng tài khoản Microsoft 365
4. Kiểm tra user info hiển thị đúng
### 5.3 Kiểm tra Pipeline
```bash
# Trigger sync
curl -X POST http://localhost:8000/sync
# Kiểm tra sync status
curl http://localhost:8000/sync/status
# Kiểm tra chunks trong OpenSearch
curl -u admin:admin http://localhost:9200/poc_sharepoint_docs/_count
```
### 5.4 Kiểm tra ACL
```bash
# Test search với user có quyền
curl -X POST http://localhost:8000/chat \
-H "Content-Type: application/json" \
-H "X-User-Email: user@yourcompany.com" \
-H "X-User-Role: user" \
-d '{"query": "test"}'
# Test search với admin (bypass ACL)
curl -X POST http://localhost:8000/chat \
-H "Content-Type: application/json" \
-H "X-User-Role: admin" \
-d '{"query": "test"}'
```
---
## 6. Xử lý lỗi thường gặp
| Lỗi | Nguyên nhân | Giải pháp |
|-----|-------------|-----------|
| SSO redirect_uri_mismatch | Redirect URI chưa đúng | Kiểm tra URI trong Azure AD khớp với callback URL |
| Token không có `roles` | App dùng Delegated thay vì Application permissions | Đổi sang Application permissions + Grant admin consent |
| OpenSearch connection refused | Chưa khởi động Docker | `docker-compose up -d opensearch` |
| VLM OCR timeout | Server VLM quá tải hoặc offline | Kiểm tra `VLM_ENDPOINT` có truy cập được |
| Search trả 0 kết quả | Chưa nạp dữ liệu hoặc sai index name | Chạy `python3 test_rag_pipeline.py` |
---
## 7. Checklist trước khi Production
- [ ] Azure AD App Registration đã cấu hình đúng permissions
- [ ] Client Secret còn hạn sử dụng
- [ ] Redirect URI đã thêm cho production domain
- [ ] OpenSearch đã đổi password mặc định
- [ ] SSL certificate đã cài đặt
- [ ] CORS đã giới hạn origins
- [ ] `.env` đã cấu hình cho production
- [ ] Docker Compose production đã test
- [ ] Backup strategy cho OpenSearch data
- [ ] Monitoring (CPU, RAM, disk) đã setup
---
*Tài liệu này cần được cập nhật khi có thay đổi về hạ trúc hoặc cấu hình.*