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.