Phase 7: Hoàn thiện Modular RAG Backend với FastAPI và Đa LLM Provider

This commit is contained in:
2026-05-08 07:30:30 +00:00
commit 26d1298cf6
51 changed files with 5360 additions and 0 deletions

View File

@@ -0,0 +1,88 @@
# 🧭 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).
---
## 1. Bản Đồ Kiến Trúc Lõi (Core Architecture Patterns)
### 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` và 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 đó.
### 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.
### 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`.
### 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`.
- **Tuyệt đối KHÔNG hardcode URL, Token hay Password trong code.**
---
## 2. Bản Đồ File & Thư Mục Quan Trọng
```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.)
├── 📁 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
│ └── 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
```
---
## 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`).
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`.
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).
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.
---
## 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.
---
## 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.
### 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).

View File

@@ -0,0 +1,243 @@
# Kiến trúc và định hướng xây dựng hệ thống tra cứu tài liệu scan SharePoint
## 1. Mục tiêu tổng thể
Hệ thống nhằm giải quyết ba vấn đề cốt lõi trong doanh nghiệp:
1. **Biến kho tài liệu scan trên SharePoint thành dữ liệu có thể tìm kiếm theo ngữ nghĩa**.
2. **Tìm nhanh → đúng tài liệu → đúng vị trí trong tài liệu**.
3. **Giữ nguyên tính kiểm soát, phân quyền và tuân thủ (compliance)** của Microsoft 365.
Hệ thống không thay thế SharePoint, mà **tăng cường khả năng tra cứu và hiểu nội dung**.
---
## 2. Nguyên tắc thiết kế
### 2.1. Không lock-in
- Ưu tiên **Open Source** cho lõi xử lý.
- Có thể thay OCR / embedding / LLM trong tương lai.
### 2.2. File gốc là "nguồn chân lý"
- File **luôn ở SharePoint**.
- Hệ thống chỉ lưu **nội dung trích xuất + metadata + index**.
### 2.3. Permission-aware từ đầu
- Không index kiểu "public rồi filter sau".
- Mỗi kết quả search phải map được tới **ACL tương ứng trên SharePoint**.
---
## 3. Kiến trúc tổng thể (Logical Architecture)
```
SharePoint (Files, PDFs scan)
Ingestion & Sync Layer (tự viết vibecode)
├── Fetch file
├── Fetch metadata & permissions
└── Versioning
Extraction Layer
├── OCR (scan PDF)
└── MarkItDown (→ Markdown)
Normalization & Enrichment
├── Chunking
├── Metadata mapping
└── Page / section anchoring
Index Layer (OpenSearch)
├── Full-text index
├── Vector index
└── Metadata filter
Search / Chat UI
└── Click → mở đúng file SharePoint
```
---
## 4. Thành phần chi tiết và trách nhiệm
### 4.1. Ingestion Layer (then chốt nhất)
**Nhiệm vụ**:
- Kết nối SharePoint bằng Microsoft Graph API.
- Theo dõi thay đổi file (delta query / webhook).
- Tải file + metadata.
**Metadata bắt buộc**:
- site_id
- drive_id / library
- file_id
- file_name
- file_url (mở trực tiếp trên SharePoint)
- created_by, modified_by
- created_at, modified_at
- permission_groups / users
> Lưu ý: permission cần map thành dạng filter-friendly (list group/user IDs).
---
### 4.2. Extraction Layer
#### OCR
- Scan PDF thường là image → cần OCR.
- Định hướng:
- Tesseract / PaddleOCR cho local.
- Có thể thay bằng model mới sau.
#### MarkItDown
- Chuyển output OCR → Markdown sạch.
- Ưu điểm:
- Giữ cấu trúc
- Thuận lợi cho chunk & embedding
Output cần lưu:
```json
{
"file_id": "...",
"page": 12,
"content_md": "## Điều 3...",
"bbox_hint": "page=12"
}
```
---
### 4.3. Normalization & Chunking
**Mục tiêu**: mỗi đơn vị index phải vừa đủ nhỏ để search chính xác, vừa đủ lớn để có ngữ cảnh.
Chiến lược chunk:
- Ưu tiên theo:
1. Heading (##, ###)
2. Trang (page)
3. Đoạn văn
Mỗi chunk gồm:
- chunk_id
- text
- file_id
- page_from / page_to
- sharepoint_url_with_anchor
---
### 4.4. Index Layer (OpenSearch)
**Hai loại index song song**:
1. **Full-text index**
- Phục vụ search truyền thống
- Có highlight
2. **Vector index**
- Phục vụ semantic search
- Dùng embedding OSS (bge, e5, etc.)
**Schema gợi ý**:
```json
{
"chunk_id": "...",
"text": "...",
"embedding": [ ... ],
"file_id": "...",
"file_name": "...",
"sharepoint_url": "...",
"page_from": 10,
"page_to": 11,
"site_id": "...",
"permissions": ["groupA", "userB"],
"updated_at": "..."
}
```
---
## 5. Search & UX định hướng
### 5.1. Search mode
- Keyword search
- Semantic search
- Hybrid (khuyên dùng)
### 5.2. Kết quả search bắt buộc có
- Trích đoạn nội dung
- Tên file
- Thư mục / site
- Trang (page)
- Link mở đúng file
### 5.3. UX nguyên tắc
- Tìm ≤ 3s
- Click ≤ 1 lần để mở file
- Người dùng **không cần biết file nằm ở đâu**
---
## 6. Vibecode: nên tập trung viết gì?
✅ NÊN tự viết:
- SharePoint ingestion & sync
- Permission mapping
- Metadata chuẩn hóa
- UI search phù hợp nghiệp vụ
❌ KHÔNG nên tự viết:
- OCR engine
- Search engine
- Vector index
---
## 7. Lộ trình triển khai thực tế
### Phase 1 PoC (24 tuần)
- Lấy 1 site SharePoint
- OCR + MarkItDown
- Full-text search
### Phase 2 Semantic search
- Chunking
- Embedding
- Vector search
### Phase 3 Permission & scale
- ACL filtering
- Delta sync
- Monitoring
---
## 8. Tương tác AI agent trong tương lai
Hệ thống này có thể:
- Gắn Chat UI (RAG)
- Tóm tắt tài liệu
- So sánh nhiều file
- Trả lời câu hỏi trích dẫn rõ nguồn
---
## 9. Kết luận
Bài toán của bạn **không mới nhưng rất ít hệ thống làm đúng**.
Việc kết hợp:
- SharePoint (nguồn tin cậy)
- MarkItDown (chuẩn hóa nội dung)
- OpenSearch (index & search)
- Vibecode (điều phối thông minh)
**hướng kiến trúc bền vững, mở rộng được nhiều năm**.
---
*Tài liệu này được thiết kế để AI agent hoặc dev khác có thể đọc và triển khai tiếp mà không cần giải thích lại.*

View File

@@ -0,0 +1,220 @@
# 10.Appendix-Document-Type-Classification-and-Processing-Strategy.md
> **Phụ lục chiến lược phân loại & xử lý tài liệu** cho toàn bộ hệ thống SharePoint → Search → RAG.
>
> ⚠️ **Nguyên tắc sử dụng**
> - Đây là **phụ lục độc lập**, không chỉnh sửa các file 19.
> - Được coi là **luật xử lý file của hệ thống**.
> - Mọi pipeline hiện tại và mở rộng trong tương lai **PHẢI tuân theo phụ lục này**.
> - Mục tiêu: an toàn, mở rộng được, không xử lý sai loại tài liệu.
---
## 1. Mục tiêu của phụ lục
Phụ lục này nhằm:
- Chuẩn hoá **cách hệ thống hiểu và xử lý từng loại file**
- Ngăn việc:
- OCR / MarkItDown bừa bãi
- Đưa bản vẽ kỹ thuật vào RAG
- Xử lý sai Excel/dữ liệu bảng
- Tạo **luồng ngoại lệ có kiểm soát** cho file mới hoặc hiếm gặp
---
## 2. Nguyên tắc cốt lõi (BẮT BUỘC)
1. **Không có "one-size-fits-all" cho tài liệu**
2. **Phân loại file xảy ra TRƯỚC OCR và MarkItDown**
3. **Extension là rule đầu, KHÔNG phải rule cuối**
4. **Tài liệu không có giá trị ngôn ngữ → không RAG**
5. **File lạ vẫn được ingest, nhưng xử lý an toàn**
---
## 3. Document Classification Engine (DCE)
### 3.1 Vai trò
DCE chịu trách nhiệm quyết định **file đi vào pipeline nào**.
Nếu chưa quyết định được → file **KHÔNG được xử lý sâu hơn**.
---
### 3.2 Input của DCE
- Extension (vd: `.pdf`, `.dwg`, `.xlsx`)
- MIME type
- File size
- Header bytes (chống giả extension)
- Với PDF:
- Có text layer hay không
- Pattern nhanh (drawing vs text)
---
### 3.3 Output của DCE (bắt buộc)
```json
{
"doc_type": "textual_document | technical_drawing | structured_data | binary_unsupported",
"processing_policy": "text_pipeline | metadata_only | table_pipeline | skip",
"confidence": 0.95,
"reason": "PDF detected as engineering drawing based on layout"
}
```
---
## 4. Các nhóm tài liệu và chiến lược xử lý
## 4.1 Nhóm A Textual Documents (Tài liệu ngôn ngữ)
### Ví dụ
- PDF văn bản (scan hoặc text)
- DOCX, PPTX
- PDF quy định, hợp đồng
### Xử lý
- ✅ OCR (nếu scan)
- ✅ MarkItDown
- ✅ Chunking
- ✅ Search
- ✅ RAG Chat
### Ghi chú
- Đây là **nguồn chính cho RAG**
---
## 4.2 Nhóm B Technical Drawings (Bản vẽ kỹ thuật)
### Ví dụ
- PDF bản vẽ kỹ thuật
- DWG / DXF / IFC
### Xử lý
- ✅ Metadata indexing
- ✅ Thumbnail / preview (nếu có)
- ✅ OCR giới hạn title block (tuỳ chọn)
### KHÔNG làm
- ❌ OCR toàn bộ
- ❌ MarkItDown
- ❌ RAG
### Lý do
- Nội dung chính là hình học, không phải ngôn ngữ
- RAG sẽ dễ hallucinate và gây rủi ro nghiệp vụ
---
## 4.3 Nhóm C Structured Data Documents (Dữ liệu bảng)
### Ví dụ
- Excel (XLSX)
- CSV
### Sub-case 1: Excel có mô tả nghiệp vụ
- ✅ Trích xuất giới hạn
- ✅ Convert sang Markdown có kiểm soát
- ✅ Search
- ⚠️ RAG chỉ áp dụng phần text
### Sub-case 2: Excel số liệu / danh sách lớn
- ✅ Extract header + key columns
- ✅ Index theo field
- ❌ MarkItDown toàn file
- ❌ OCR
- ❌ RAG ngôn ngữ tự do
---
## 4.4 Nhóm D Binary / Unsupported Documents
### Ví dụ
- `.acad`, `.psd`, `.step`, `.zip`
### Xử lý
- ✅ Metadata-only ingestion
- ✅ Search theo tên / project
- ❌ Không OCR
- ❌ Không convert
- ❌ Không RAG
---
## 5. Luồng xử lý ngoại lệ (Exception Flow)
### 5.1 Khi nào kích hoạt
- Extension chưa có rule
- MIME / header không khớp extension
- File có pattern bất thường
---
### 5.2 Luồng chi tiết
```text
File mới
Basic metadata ingest
DCE classify = UNKNOWN
Flag: Pending Classification
Rule-based auto guess (nếu có)
Manual admin review (hiếm)
Update classification rule
Optionally re-process file
```
---
### 5.3 Nguyên tắc an toàn
- ❌ Không OCR file chưa rõ loại
- ❌ Không cho RAG đọc file pending
- ✅ Vẫn search được theo metadata
---
## 6. Tác động tới Search & RAG
- Search
- Phải tôn trọng `processing_policy`
- RAG
- Chỉ dùng `textual_document`
- Skip toàn bộ nhóm B, C(subcase 2), D
---
## 7. Lợi ích dài hạn của chiến lược này
- ✅ Không phá pipeline khi có file mới
- ✅ An toàn AI (no hallucination)
- ✅ Tối ưu chi phí OCR
- ✅ Mở rộng không cần sửa core
- ✅ Dễ audit
---
## 8. Kết luận phụ lục
- Phân loại tài liệu là **điểm quyết định sống còn** của hệ thống
- Extension là **điểm bắt đầu**, không phải kết luận
- OCR và MarkItDown **là công cụ, không phải mục tiêu**
- RAG chỉ dùng khi **có giá trị ngôn ngữ thật**
---
*Phụ lục này là tài liệu tham chiếu nền tảng khi mở rộng hoặc audit toàn hệ thống.*

View File

@@ -0,0 +1,193 @@
# 11.Appendix-PDF-Inspection-and-TextLayer-Detection.md
> **Phụ lục chiến lược nhận diện PDF (text-based vs scan vs drawing)**.
>
> ⚠️ Phụ lục này **KHÔNG chỉnh sửa** các file 110.
> Mục tiêu: **chuẩn hoá cách hệ thống hiểu PDF trước khi quyết định OCR / MarkItDown**.
>
> Đây là phụ lục then chốt để **không xử lý OCR sai loại PDF**, đặc biệt trong môi trường có nhiều bản vẽ kỹ thuật.
---
## 1. Vì sao cần inspection PDF riêng?
Trong hệ thống doanh nghiệp, `.pdf` là extension **dễ gây hiểu nhầm nhất**:
- PDF có thể là:
- Văn bản thuần (text layer)
- Scan ảnh (image-only)
- Bản vẽ kỹ thuật (vector + text rải rác)
⚠️ **Không được quyết định OCR chỉ dựa trên việc "là PDF"**.
---
## 2. Ba loại PDF cần phân biệt (BẮT BUỘC)
### 2.1 PDF loại 1 Text-based PDF
**Đặc điểm**
- Có text layer thật
- Có thể select/copy text
- Thường sinh ra từ Word, InDesign, LaTeX
**Xử lý**
- ❌ Không OCR
- ✅ Đưa thẳng vào MarkItDown
---
### 2.2 PDF loại 2 Scan / Image-based PDF
**Đặc điểm**
- Không có text layer
- Toàn bộ là ảnh
- Scan từ giấy
**Xử lý**
- ✅ OCR là BẮT BUỘC
- ✅ OCR page-wise
- ✅ Sau OCR mới đưa vào MarkItDown
---
### 2.3 PDF loại 3 Technical Drawing PDF
**Đặc điểm**
- Nội dung chính là hình vẽ kỹ thuật
- Text rải rác (ký hiệu, mã số)
- Có thể có vector + text layer
**Xử lý**
- ❌ Không OCR toàn bộ
- ❌ Không MarkItDown
- ✅ Metadata-only indexing
- ✅ OCR giới hạn (title block) nếu cần
---
## 3. PDF Inspection Flow (Luồng quyết định)
```text
PDF file
Quick inspection
├─ Has text layer?
├─ Text density?
├─ Page structure?
Classify:
- TEXT_PDF
- SCAN_PDF
- DRAWING_PDF
```
---
## 4. Heuristics xác định Text-based PDF
Một PDF được coi là **TEXT_PDF** khi:
- Có text layer trên >70% số trang
- Text density đủ lớn (nhiều hơn nhãn/ký hiệu)
- Không có layout dạng drawing
✅ Ví dụ tiêu biểu
- Quy định
- Hợp đồng
- Hướng dẫn
---
## 5. Heuristics xác định Scan PDF
Một PDF được coi là **SCAN_PDF** khi:
- Không có text layer
- Page rendering = image
- OCR text length = 0 trước OCR
✅ Đây là target chính của OCR tiếng Việt
---
## 6. Heuristics xác định Drawing PDF (RẤT QUAN TRỌNG)
Một PDF bị coi là **DRAWING_PDF** khi:
- Text layer rất ít nhưng:
- Có vector shapes
- Có line dày đặc
- Page ratio lớn (A1, A0)
- Text xuất hiện chủ yếu ở:
- Title block
- Legend
⚠️ Thoả các dấu hiệu trên → **KHÔNG đưa vào OCR/MarkItDown dù có text layer**.
---
## 7. Vì sao Drawing PDF KHÔNG được OCR đại trà
- OCR sinh rất nhiều noise
- Text không mang ý nghĩa ngôn ngữ
- RAG dễ hallucinate nguy hiểm
✅ Nguyên tắc:
> **Drawing PDF chỉ để TRA CỨU, không để ĐỌC bằng AI**.
---
## 8. Quyết định xử lý theo loại PDF
| PDF Type | OCR | MarkItDown | Search | RAG |
|--------|-----|------------|--------|-----|
| TEXT_PDF | ❌ | ✅ | ✅ | ✅ |
| SCAN_PDF | ✅ | ✅ | ✅ | ✅ |
| DRAWING_PDF | ❌ (limited) | ❌ | ✅ (metadata) | ❌ |
---
## 9. OCR Scope áp dụng cho PDF
### Chỉ OCR khi:
- Classified = SCAN_PDF
### OCR giới hạn khi:
- Classified = DRAWING_PDF
- Mục tiêu: title, revision, project code
---
## 10. Logging & Audit bắt buộc
Mỗi PDF phải có log:
```json
{
"pdf_type": "SCAN_PDF",
"decision_reason": "No text layer detected",
"ocr_applied": true
}
```
---
## 11. Lợi ích kiến trúc
- ✅ Không OCR sai PDF
- ✅ Không đưa bản vẽ vào RAG
- ✅ Giảm chi phí OCR
- ✅ Tránh hallucination nguy hiểm
---
## 12. Kết luận phụ lục
- PDF inspection là **bước bắt buộc trước OCR**
- TEXT ≠ SCAN ≠ DRAWING
- OCR và MarkItDown chỉ là công cụ, **không phải đích đến**
---
*Phụ lục này là nền tảng để thiết kế bước tích hợp OCR trong hệ thống.*

View File

@@ -0,0 +1,213 @@
# 12.Appendix-OCR-Integration-Strategy-and-Flow.md
> **Phụ lục tích hợp OCR Giải pháp khả thi, rõ ràng, triển khai được ngay** cho hệ thống SharePoint → Search → RAG.
>
> ⚠️ Nguyên tắc của file này:
> - **Đứng độc lập**: có thể load lại trong session khác và tiếp tục thảo luận
> - **Chọn MỘT giải pháp chính** (không liệt kê mơ hồ nhiều hướng)
> - **Opensource, onprem friendly**, không lockin
> - Thiết kế **mở để nâng cấp** về sau (finetune / cloud nếu cần)
---
## 1. Tóm tắt nhanh quyết định (Executive Summary)
### Giải pháp OCR được chọn
> ✅ **PaddleOCR (Detection) + VietOCR (Recognition)** triển khai onprem
### Vì sao chọn giải pháp này?
- Phù hợp **99% tài liệu tiếng Việt có dấu**
- Đã được cộng đồng Việt Nam sử dụng thực tế
- Hoàn toàn **opensource**
- Không phụ thuộc cloud / API bên ngoài
- Dễ audit, dễ debug, dễ finetune
➡️ Đây là giải pháp **khả thi nhất cho phase PoC → Pilot → Production**.
---
## 2. Vị trí của OCR trong toàn pipeline (nhắc lại để neo tư duy)
```text
File Ingestion
Document Classification (file 10)
PDF Inspection (file 11)
IF SCAN_PDF
→ OCR Layer (file này)
Normalized Text (page-wise)
MarkItDown
Chunking → Search → RAG
```
⚠️ OCR **KHÔNG** đứng độc lập, mà **chỉ là 1 stage có điều kiện**.
---
## 3. OCR Integration Phạm vi áp dụng
OCR **CHỈ được gọi khi**:
- `doc_type = textual_document`
- `pdf_type = SCAN_PDF`
OCR **KHÔNG được gọi khi**:
- Drawing PDF
- Binary / CAD / Excel số liệu
- File pending classification
---
## 4. Kiến trúc OCR chi tiết (Logical Architecture)
```text
OCR Service (microservice)
├── Detector: PaddleOCR (DB / SAST)
├── Recognizer: VietOCR (Transformer)
├── Preprocess:
│ - Deskew
│ - Binarization
│ - Resize
├── Output:
│ - text
│ - page
│ - confidence
```
➡️ OCR được đóng gói dưới dạng **service riêng**, không embed cứng vào ingestion.
---
## 1. Tại Sao Lại Là Phân Tán VLM (Vision-Language Model)?
Trong giai đoạn đầu của PoC, chúng ta đã thử nghiệm kiến trúc cũ: **PaddleOCR** (để bóc khung chữ) kết hợp với **VietOCR** (để dịch tiếng Việt).
Tuy nhiên, phương pháp này đã bộc lộ những điểm yếu chí mạng:
- **PaddleOCR** cực kỳ yếu trong việc nhận diện dấu tiếng Việt (rụng dấu tả tơi).
- **VietOCR (vgg_seq2seq)** bị lỗi "Ảo giác" (Hallucination) sinh ra chữ tiếng Anh rác khi bị cắt ảnh không chuẩn xác.
- Quy trình `Cắt ảnh (Crop) -> Dịch -> Ghép lại` làm đứt gãy cấu trúc tự nhiên (Layout) của văn bản.
Vì vậy, kiến trúc đã được nâng cấp lên chuẩn **Enterprise Distributed AI**:
- Sử dụng mô hình **Vintern-3B** (Vision-Language Model) chạy trên một máy chủ chuyên dụng trong mạng LAN thông qua `llama.cpp` server.
- Hệ thống RAG (WSL) chỉ đóng vai trò là một VLM Client: Gửi ảnh sang máy chủ LAN và nhận về nguyên văn Markdown chuẩn xác, giữ nguyên cấu trúc bảng biểu, tiêu đề, và không bao giờ rớt dấu.
---
## 2. Distributed VLM Integration Flow (Kiến trúc phân tán)
```mermaid
sequenceDiagram
participant P as Pipeline (sync.py)
participant DCE as Classification (DCE)
participant OS as OCR Service (Client)
participant LAN as VLM Server (10.202.50.3)
participant DB as Vector DB (OpenSearch)
P->>DCE: Gửi PDF/Image
DCE-->>P: file_type = "image/scanned_pdf"
P->>OS: process_bytes(pdf_bytes)
rect rgb(20, 50, 100)
note right of OS: VLM Client Logic
OS->>OS: Render trang PDF thành Ảnh (DPI=86)
OS->>OS: Encode Ảnh sang Base64
OS->>LAN: POST /v1/chat/completions (Base64 + Prompt)
end
rect rgb(80, 20, 20)
note right of LAN: GPU/CPU Heavy Lifting
LAN->>LAN: Chạy InternVL2 / Vintern-3B
LAN->>LAN: Trích xuất toàn bộ Text và Bảng biểu
LAN-->>OS: Trả về văn bản chuẩn Markdown
end
OS-->>P: List[OCRPageResult(text, confidence)]
P->>P: Chunking (Semantic)
P->>DB: Indexing
```
---
## 3. Kiến Trúc Modular Data Provider
Để hệ thống hoàn chỉnh ở mức độ cao cấp, chúng tôi đã tái cấu trúc (Refactor) lại tầng Ingestion:
1. **BaseStorageProvider:** Interface trừu tượng hoá việc lấy dữ liệu `fetch_changes()` và tải dữ liệu `download_file()`.
2. **SharePointProvider:** Kế thừa từ BaseStorageProvider, đóng gói toàn bộ logic Graph API.
3. Trong tương lai, chỉ cần viết thêm `GoogleDriveProvider`, `LocalDriveProvider` hoặc `S3Provider` là hệ thống RAG có thể nuốt mọi nguồn dữ liệu mà không cần sửa đổi Core logic.
---
## 4. Tách Biệt Cấu Hình (Decoupled Configuration)
Các thông số siêu nặng của VLM đã được tách biệt hoàn toàn khỏi mã nguồn:
- Thông số kết nối mạng LAN: `VLM_ENDPOINT`
- Thông số tinh chỉnh: `VLM_TEMPERATURE`, `VLM_MAX_TOKENS`
Tất cả được quản lý qua `core/config.py` và file `.env`. Việc đổi máy chủ AI giờ đây chỉ mất 1 giây thay đổi biến môi trường.
---
## 5. Confidence Handling (rất quan trọng cho RAG)
### Nguyên tắc
- OCR < threshold → **KHÔNG đưa vào RAG**
- OCR < threshold → vẫn search keyword + metadata
### Threshold gợi ý
- `confidence ≥ 0.90` → OK cho RAG
- `0.80 0.90` → Search only
- `< 0.80` → Flag review
---
## 10. Logging & Audit OCR
Mỗi OCR job phải log:
```json
{
"file_id": "...",
"page": 5,
"ocr_engine": "PaddleOCR+VietOCR",
"confidence": 0.91
}
```
➡️ Phục vụ:
- audit
- debug
- cải tiến model
---
## 11. Mở rộng tương lai (NHƯNG KHÔNG LÀM NGAY)
✅ Đã được thiết kế sẵn, **không lockin**:
- Finetune VietOCR theo domain
- Thêm GPU để tăng tốc
- Thay recognition engine nếu cần
- Thêm OCR cloud fallback (optional)
➡️ **Không phá pipeline hiện tại**.
---
## 12. Tóm tắt quyết định kỹ thuật
- OCR là **service có điều kiện**, không phải default
- PaddleOCR + VietOCR là **giải pháp chính**
- Onprem, opensource, auditfriendly
- Sẵn sàng cho PoC → Production
---
*Phụ lục này là tài liệu chốt cách tích hợp OCR cho toàn hệ thống.*

View File

@@ -0,0 +1,193 @@
# 13.PoC-Implementation-Checklist.md
> **Checklist triển khai PoC (Proof of Concept)** cho hệ thống tra cứu tài liệu SharePoint → Search → RAG Chat.
>
> ⚠️ Nguyên tắc của checklist này:
> - Dựa **100% trên các quyết định đã chốt trong file 112**
> - Dùng để **triển khai PoC thật**, không phải tài liệu lý thuyết
> - Checklist theo thứ tự **chuẩn kỹ thuật**, làm xong mục trước mới sang mục sau
> - Có thể dùng cho: Tech Lead, Dev, Vendor, AI Agent
---
## 0. Phạm vi PoC (BẮT BUỘC CHỐT TRƯỚC KHI LÀM)
### ✅ Mục tiêu PoC
- Tra cứu tài liệu nội bộ (SharePoint)
- Hỗ trợ **search + RAG chat**
- Đúng quyền người dùng
- Ưu tiên **tài liệu tiếng Việt**
### ❌ Ngoài phạm vi PoC
- Finetune OCR
- Phân tích bản vẽ kỹ thuật bằng AI
- Multitenant phức tạp
---
## 1. Chuẩn bị môi trường
- [ ] Tenant SharePoint test
- [ ] App Registration (Graph API apponly)
- [ ] Server PoC (CPU ≥ 16 cores, RAM ≥ 32GB)
- [ ] Docker / Container runtime
- [ ] OpenSearch cluster (dev size)
---
## 2. Ingestion SharePoint
- [ ] Kết nối Graph API thành công
- [ ] Lấy được site / library metadata
- [ ] Delta query hoạt động
- [ ] Persist delta token
- [ ] Detect create / update / delete file
---
## 3. Document Classification Engine (File 10)
- [ ] Parse extension + MIME type
- [ ] Header byte validation (chống giả extension)
- [ ] Gán `doc_type`
- [ ] Gán `processing_policy`
- [ ] Log lý do classify
---
## 4. PDF Inspection (File 11)
- [ ] Detect text layer PDF
- [ ] Calculate text density
- [ ] Detect vector / drawing layout
- [ ] Classify: TEXT_PDF / SCAN_PDF / DRAWING_PDF
- [ ] Log quyết định inspection
---
## 5. OCR Integration (File 12)
### 5.1 Điều kiện gọi OCR
- [ ] Chỉ OCR khi `SCAN_PDF`
- [ ] Skip DRAWING_PDF
- [ ] Skip nontextual documents
### 5.2 OCR Service
- [ ] PaddleOCR detector chạy ổn định
- [ ] VietOCR recognizer nhận tiếng Việt có dấu
- [ ] OCR pagewise
- [ ] OCR chạy được trên CPU
### 5.3 OCR Output
- [ ] Có page number
- [ ] Có text
- [ ] Có confidence
- [ ] OCR output chuẩn JSON contract
---
## 6. MarkItDown & Normalization
- [ ] Nhận text từ OCR hoặc textPDF
- [ ] Convert sang Markdown
- [ ] Giữ heading / paragraph / list
- [ ] Gắn page marker
---
## 7. Chunking
- [ ] Chunk theo heading / page
- [ ] Token size phù hợp cho search & RAG
- [ ] Gắn metadata: file_id, page, URL
---
## 8. Index & Search (OpenSearch)
- [ ] Mapping chunkfirst
- [ ] Index text field
- [ ] Index metadata field
- [ ] Index ACL
- [ ] Index embedding (nếu dùng)
---
## 9. Permission Enforcement
- [ ] Resolve user identity
- [ ] Resolve group membership
- [ ] Filter search theo ACL
- [ ] Không lộ file user không có quyền
---
## 10. Search Experience
- [ ] Keyword search hoạt động
- [ ] Search trả đúng file & page
- [ ] Highlight nội dung
- [ ] Click mở file gốc
---
## 11. RAG Chat (File 5)
### 11.1 Điều kiện vào RAG
- [ ] Có kết quả search
- [ ] OCR confidence đạt threshold
### 11.2 Prompt & Answer
- [ ] System prompt chặt (no hallucination)
- [ ] Chỉ dùng context search
- [ ] Trả câu trả lời + citation
### 11.3 Fallback
- [ ] Không có dữ liệu → trả lời chuẩn
---
## 12. Logging & Audit
- [ ] Log ingestion
- [ ] Log OCR
- [ ] Log search query
- [ ] Log RAG answer + context
---
## 13. User Validation (PoC Acceptance)
- [ ] User tìm được tài liệu mong muốn
- [ ] User hiểu citation
- [ ] AI không trả lời bịa
- [ ] UX dễ sử dụng
---
## 14. KPI PoC (Đủ/Không đủ)
- [ ] Search latency < 3s
- [ ] OCR Vietnamese readable
- [ ] RAG trả lời đúng phạm vi
- [ ] Không lộ quyền
---
## 15. Quyết định sau PoC
- [ ] Go Pilot
- [ ] Điều chỉnh OCR threshold
- [ ] Thêm loại document
- [ ] Finetune sau (nếu cần)
---
## Kết luận Checklist
- Checklist này hoàn thành → PoC **đã thành công về mặt kỹ thuật**
- Chưa hoàn thành → **không nên lên production**
---
*Tài liệu này là checklist thực thi, không phải tài liệu mô tả.*

View File

@@ -0,0 +1,194 @@
# 14.Project-Bridge-Context-for-New-Chat.md
> Mục tiêu file này: **cầu nối ngữ cảnh** để mở New Chat và tiếp tục dự án mà **không cần attach lại toàn bộ 13 file**.
>
> ⚠️ Lưu ý quan trọng:
> - File này là **bản tóm lược có cấu trúc**, **KHÔNG thay thế** hoàn toàn cho các file 113.
> - Dùng khi giới hạn số file đính kèm thấp.
> - Nếu cần chi tiết kỹ thuật sâu cho một mô-đun, vẫn nên attach thêm file gốc liên quan.
---
## 1. Dự án đang làm là gì?
Xây dựng hệ thống tra cứu tài liệu nội bộ theo pipeline:
```text
SharePoint → Ingestion → Document Classification → PDF Inspection → OCR (có điều kiện) → MarkItDown → Chunking → Search → RAG Chat
```
Mục tiêu:
- Tra cứu nhanh nội dung tài liệu công ty lưu trong SharePoint
- Tìm đúng file, đúng trang, đúng quyền truy cập
- Hỗ trợ Search và RAG Chat có dẫn nguồn
---
## 2. Các quyết định kiến trúc đã CHỐT (không thay đổi)
### 2.1 Phân loại tài liệu là bắt buộc trước xử lý
- Không có one-size-fits-all cho mọi file
- Mỗi file phải đi qua **Document Classification Engine (DCE)** trước
### 2.2 PDF phải được inspect trước OCR
PDF được chia thành 3 loại:
- `TEXT_PDF` → không OCR, đưa thẳng vào MarkItDown
- `SCAN_PDF` → OCR bắt buộc, page-wise
- `DRAWING_PDF` → không OCR đại trà, không MarkItDown, không RAG
### 2.3 Bản vẽ kỹ thuật / CAD / binary không đi vào RAG
- DWG/DXF/IFC/CAD/Binary → metadata search only
- Drawing PDF → metadata + optional title-block OCR, không RAG
### 2.4 OCR chính thức được chọn
- **PaddleOCR (Detection) + VietOCR (Recognition)**
- On-prem, open-source, không lock-in cloud
- OCR chỉ gọi khi:
- `doc_type = textual_document`
- `pdf_type = SCAN_PDF`
### 2.5 RAG là tầng sau Search, có điều kiện
- Search-first, LLM-second
- Không có context tốt → không trả lời
- Trả lời phải có citation
- OCR confidence thấp → không đưa vào RAG
---
## 3. Các file gốc đã tồn tại trước đó
### Nhóm kiến trúc lõi
1. Kiến trúc tổng thể
2. SharePoint ingestion playbook
3. Extraction & normalization playbook
4. OpenSearch index & search playbook
5. RAG chat application playbook
6. Operations / monitoring / governance playbook
### Nhóm review & điều phối
7. Review / double-check / gap analysis
8. End-to-end processing flows bullets
### Nhóm phụ lục kỹ thuật quan trọng
9. Appendix Vietnamese OCR strategy
10. Appendix Document type classification and processing strategy
11. Appendix PDF inspection and text-layer detection
12. Appendix OCR integration strategy and flow
13. PoC implementation checklist
---
## 4. Trạng thái hiện tại của dự án
- Đã chốt kiến trúc end-to-end
- Đã chốt luật xử lý tài liệu
- Đã chốt chiến lược OCR tiếng Việt
- Đã có checklist PoC chi tiết
- Đang chuyển sang giai đoạn **bắt tay triển khai PoC thật**
Trọng tâm hiện tại:
> Tạo / dùng **SharePoint Team Site test** làm nguồn dữ liệu đầu vào cho PoC.
---
## 5. Site SharePoint test dự kiến / khuyến nghị
### Loại site
- **Team site**
- Privacy: Private
### Tên gợi ý
- `SP-RAG-Test`
### Cấu trúc thư mục test khuyến nghị
```text
/Documents
/01-PDF-Text
/02-PDF-Scan
/03-PDF-Drawing
/04-DOCX
/05-XLSX-Textual
/06-XLSX-Structured
/07-CAD-Binary
/99-Pending-Classification
```
### ACL test
- Có ít nhất 1 thư mục/folder restricted để test permission filtering
---
## 6. Thứ tự triển khai PoC đã chốt
1. Tạo SharePoint site test
2. Upload bộ dữ liệu test nhỏ nhưng đủ loại
3. Kiểm tra quyền truy cập khác nhau giữa user
4. Bắt đầu ingestion
5. Chạy document classification
6. Chạy PDF inspection
7. Chỉ OCR cho SCAN_PDF
8. MarkItDown / normalization / chunking
9. Index vào OpenSearch
10. Bật search
11. Chỉ bật RAG sau khi search + ACL + citation ổn
---
## 7. Các ngưỡng / guardrails đã chốt
### OCR confidence
- `>= 0.90` → có thể dùng cho RAG
- `0.80 0.90` → search only
- `< 0.80` → flag review
### Không được làm
- Không OCR drawing PDF đại trà
- Không đưa CAD/binary vào RAG
- Không bỏ qua bước classification/PDF inspection
- Không để AI tự thay đổi kiến trúc đã chốt
---
## 8. Khi mở New Chat, AI cần tuân thủ gì?
### Bắt buộc
1. Không thay đổi các quyết định đã chốt ở trên
2. Không đề xuất đi ngược các guardrails
3. Nếu mở rộng thì chỉ tạo phụ lục mới hoặc ghi rõ là đề xuất mở rộng
4. Tiếp tục đúng ngữ cảnh: **từ SharePoint site test → PoC triển khai**
### Câu mở đầu gợi ý cho New Chat
```text
Tôi đang tiếp tục dự án SharePoint → Search → RAG.
Hãy coi file bridge context này là source of truth tạm thời.
Mục tiêu hiện tại: dùng SharePoint site test làm input cho PoC và đi tiếp đúng theo roadmap đã chốt.
Không thay đổi kiến trúc, không nhảy bước.
```
---
## 9. Gợi ý attach file khi chỉ được add ít file
### Tối thiểu nên attach
1. **File bridge này**
2. `10.Appendix-Document-Type-Classification-and-Processing-Strategy.md`
3. `13.PoC-Implementation-Checklist.md`
### Nếu cần đi sâu OCR
Thay file 13 hoặc attach tiếp ở lượt sau:
- `11.Appendix-PDF-Inspection-and-TextLayer-Detection.md`
- `12.Appendix-OCR-Integration-Strategy-and-Flow.md`
---
## 10. Mục tiêu thảo luận tiếp theo sau khi mở New Chat
Một trong các hướng sau:
- Chuẩn bị dataset test cho SharePoint site
- Map SharePoint site test vào PoC pipeline
- Lập execution plan theo checklist PoC
- Bắt đầu dựng skeleton triển khai kỹ thuật
---
*Kết thúc file bridge. Đây là file cầu nối ngữ cảnh, tối ưu cho trường hợp giới hạn số file đính kèm.*

View File

@@ -0,0 +1,264 @@
# SharePoint Ingestion Tài liệu triển khai tuần tự (Reusable)
> Mục tiêu tài liệu: **Có thể nạp lại bất kỳ lúc nào để tiếp tục đúng hướng**. Viết theo kiểu **triển khai được ngay**, tránh phụ thuộc ngữ cảnh hội thoại.
---
## Mục lục
1. Phạm vi & Mục tiêu
2. Nguyên tắc thiết kế
3. Luồng xử lý tổng thể (End-to-End Flow)
4. Sequence Diagram (Mô tả tuần tự)
5. Thiết kế Ingestion Service
6. Delta Sync & State Management
7. Permission Flattening (ACL)
8. Download & File Lifecycle
9. Orchestration, Retry, Idempotency
10. Thiết kế CSDL (Schema)
11. Internal APIs (Spec)
12. Observability & Ops
13. Roadmap thực thi
---
## 1. Phạm vi & Mục tiêu
- Ingest tài liệu từ **SharePoint Online (Microsoft 365)** bằng **Microsoft Graph API**.
- Phát hiện thay đổi bằng **Delta Query**.
- Thu thập **metadata + quyền truy cập**.
- Đưa file hợp lệ vào pipeline xử lý (OCR/MarkItDown ở phase sau).
- Đảm bảo **permission-aware ngay từ ingestion**.
---
## 2. Nguyên tắc thiết kế
- **App-only authentication** (service-to-service).
- **Delta-first**: không full scan lặp lại.
- **Permission-first**: flatten ACL khi ingest.
- **Idempotent**: chạy nhiều lần cho cùng version → kết quả giống nhau.
- **File gốc là nguồn chân lý** (chỉ lưu bản trích xuất + index).
---
## 3. Luồng xử lý tổng thể (End-to-End)
```text
[Scheduler]
[List Configured Sites]
[List Drives / Libraries]
[Delta Query Items]
[For each Changed Item]
├─ Fetch Metadata
├─ Fetch Permissions (ACL)
├─ Decide Eligibility (whitelist extension/size)
├─ Enqueue Processing Job
└─ Persist State (deltaToken, etag)
```
---
## 4. Sequence Diagram (Mô tả tuần tự)
```text
Scheduler
|
| trigger
v
Ingestion Service
|
| GET sites/drives
v
Microsoft Graph
|
| 200 OK (sites/drives)
v
Ingestion Service
|
| GET delta(items, token)
v
Microsoft Graph
|
| items[] + deltaToken
v
Ingestion Service
|
| For item changed:
| - GET item metadata
| - GET item permissions
| - Persist ingest record
| - Push job to Queue
v
Queue / Pipeline
```
---
## 5. Thiết kế Ingestion Service
### 5.1 Thành phần
- **Auth Module**: OAuth2 client-credentials + certificate.
- **Site/Drive Scanner**: liệt kê phạm vi được cấu hình.
- **Delta Engine**: quản lý deltaToken.
- **Metadata Collector**: chuẩn hóa metadata.
- **ACL Collector**: flatten permission.
- **Job Producer**: đẩy sự kiện sang pipeline.
### 5.2 Công nghệ gợi ý
- Backend: Python (FastAPI) hoặc Node.js
- Queue: Azure Service Bus / RabbitMQ / Redis
- Storage state: PostgreSQL hoặc CosmosDB (metadata)
---
## 6. Delta Sync & State Management
### 6.1 Delta Token
- Mỗi **drive/library** có một `delta_token` riêng.
- Lưu bền vững (DB), không lưu memory.
### 6.2 Logic
```text
If first_run:
call delta without token → snapshot + token
Else:
call delta with token → changes only
```
### 6.3 Event Handling
| Event | Hành động |
|------|----------|
| Created | Full ingest |
| Updated | Re-ingest (new version) |
| Deleted | Soft-delete index |
---
## 7. Permission Flattening (ACL)
### 7.1 Nguyên tắc
- Thu thập **users + groups** ngay khi ingest.
- Expand nested groups **tại ingestion time**.
### 7.2 Schema ACL
```json
{
"users": ["aad-user-id"],
"groups": ["aad-group-id"],
"inherited": true
}
```
### 7.3 Tối ưu
- Cache membership group.
- Refresh định kỳ (daily/weekly).
---
## 8. Download & File Lifecycle
### 8.1 Eligibility Rules
- Whitelist: pdf, docx, pptx, image.
- Size limit (ví dụ ≤ 100MB).
### 8.2 Lifecycle
```text
Download → Process (OCR/MD) → Persist result → Delete local file
```
---
## 9. Orchestration, Retry, Idempotency
### 9.1 Idempotency Key
- `(site_id, drive_id, item_id, etag)`
### 9.2 Retry Strategy
| Error | Strategy |
|------|----------|
| 429 | Exponential backoff |
| Timeout | Retry N lần |
| Permission denied | Log + skip |
---
## 10. Thiết kế CSDL (Schema)
### 10.1 Bảng `ingest_state`
```sql
site_id TEXT
drive_id TEXT
delta_token TEXT
updated_at TIMESTAMP
PRIMARY KEY (site_id, drive_id)
```
### 10.2 Bảng `files`
```sql
item_id TEXT
site_id TEXT
drive_id TEXT
file_name TEXT
etag TEXT
version TEXT
status TEXT
last_processed_at TIMESTAMP
PRIMARY KEY (item_id)
```
### 10.3 Bảng `permissions`
```sql
item_id TEXT
principal_type TEXT -- user|group
principal_id TEXT
```
---
## 11. Internal APIs (Spec)
### POST /ingest/run
- Trigger ingestion cycle.
### POST /ingest/item
- Input: `{ site_id, drive_id, item_id }`
- Output: job_id
### GET /ingest/state
- Trả về deltaToken, health.
---
## 12. Observability & Ops
### Logs (per item)
```json
{ "item_id": "...", "step": "permission", "status": "ok" }
```
### Metrics
- Files/min
- OCR queue length
- Error rate
---
## 13. Roadmap thực thi
### Step 1 (Tuần 12)
- Auth + list sites/drives
- Delta sync cơ bản
### Step 2 (Tuần 3)
- Metadata + ACL flatten
- Queue integration
### Step 3 (Tuần 4)
- Observability
- Hardening & scale
---
*Kết thúc tài liệu ingestion. Có thể tiếp tục với Extraction/OCR hoặc Index/Search ở file tiếp theo.*

View File

@@ -0,0 +1,241 @@
# Extraction & Normalization OCR + MarkItDown Playbook (Reusable)
> Tài liệu này nối tiếp **SharePoint Ingestion Playbook**. Mục tiêu: biến file ingest thành **Markdown sạch, có cấu trúc, có thể search RAG truy vết trang gốc**. Viết để **tái sử dụng lâu dài**, không phụ thuộc session.
---
## Mục lục
1. Vị trí của Extraction trong kiến trúc
2. Nguyên tắc thiết kế
3. Luồng xử lý tổng thể
4. Phân loại tài liệu & chiến lược xử lý
5. OCR Strategy cho tài liệu scan
6. MarkItDown tích hợp & cấu hình
7. Page Mapping & Anchoring (đi tới đúng trang)
8. Normalization & Cleanup
9. Chunking Strategy (chuẩn cho Search & RAG)
10. Output Contract (interface dữ liệu)
11. Error handling & Retry
12. Performance & Scale
13. Checklist triển khai
---
## 1. Vị trí của Extraction trong kiến trúc
```text
Ingestion (file + metadata + ACL)
Extraction Layer (OCR + MarkItDown)
Normalization & Chunking
Index / Search / RAG
```
Extraction **không biết Search**, **không biết User**, chỉ biết:
- Input: file + metadata
- Output: Markdown + page mapping + structural hints
---
## 2. Nguyên tắc thiết kế
1. **Deterministic**: cùng file + version → output giống nhau
2. **Lossless về nội dung**: ưu tiên giữ text hơn làm đẹp
3. **Trang là đơn vị neo (anchor)** đặc biệt với PDF
4. **Tách OCR khỏi Markdown** (để thay engine sau này)
5. **Không embed business logic** vào bước này
---
## 3. Luồng xử lý tổng thể
```text
[Receive File Job]
[Detect File Type]
[If Scan → OCR]
[MarkItDown Convert → Markdown]
[Normalize Markdown]
[Split by Page / Heading]
[Emit Document Units]
```
---
## 4. Phân loại tài liệu & chiến lược xử lý
| Loại | Dấu hiệu | Chiến lược |
|----|--------|-----------|
| PDF scan | Không có text layer | OCR → MD |
| PDF text | Có selectable text | Direct → MD |
| DOCX | Word | Direct → MD |
| PPTX | Slide | Slide-wise MD |
| Image | jpg/png | OCR → MD |
✅ Phân loại phải tự động, **không dựa vào extension duy nhất**.
---
## 5. OCR Strategy
### 5.1 Khi nào OCR?
- PDF không có text layer
- Image-based document
### 5.2 Output OCR yêu cầu tối thiểu
```json
{
"page": 5,
"text": "Nội dung nhận dạng...",
"confidence": 0.92
}
```
### 5.3 Nguyên tắc
- OCR **theo từng trang**
- Không gộp toàn file thành một blob text
---
## 6. MarkItDown tích hợp & cấu hình
### 6.1 Vai trò
- Biến input (PDF/DOCX/image) thành **Markdown có cấu trúc**
### 6.2 Mode sử dụng
- Input: file path hoặc stream
- Output: Markdown + page breaks
### 6.3 Quy ước page break (rất quan trọng)
```markdown
<!-- page:1 -->
# Trang 1
...
<!-- page:2 -->
# Trang 2
```
➡️ Page marker này là **khóa để click mở đúng trang PDF**.
---
## 7. Page Mapping & Anchoring
### 7.1 Mục tiêu
- Người dùng search → click → mở **đúng trang, đúng vị trí**
### 7.2 Cách làm
- Mỗi block Markdown phải mang theo:
```json
{
"file_id": "...",
"page_from": 3,
"page_to": 4,
"sharepoint_url": "...?page=3"
}
```
---
## 8. Normalization & Cleanup
### 8.1 Những việc NÊN làm
- Remove header/footer lặp
- Strip ký tự OCR rác
- Normalize whitespace
- Chuẩn hóa heading
### 8.2 Những việc KHÔNG NÊN làm
- Rewrite nội dung
- Tóm tắt
- Suy diễn
➡️ Bước này **không dùng LLM**.
---
## 9. Chunking Strategy
### 9.1 Thứ tự ưu tiên
1. Heading (##, ###)
2. Trang PDF
3. Đoạn văn
### 9.2 Kích thước gợi ý
- 300800 tokens
- Không cắt giữa câu
### 9.3 Schema chunk
```json
{
"chunk_id": "uuid",
"text": "...",
"file_id": "...",
"page_from": 5,
"page_to": 6,
"section": "Điều 3",
"source_url": "..."
}
```
---
## 10. Output Contract
### 10.1 Đầu ra cho Index Layer
```json
{
"file_id": "...",
"chunks": [ ... ],
"metadata": { ... }
}
```
### 10.2 Tính chất
- Self-contained
- Không cần gọi lại SharePoint
- Có thể re-index lại từ output này
---
## 11. Error handling & Retry
| Lỗi | Xử lý |
|---|------|
| OCR fail | Retry / flag manual |
| File corrupt | Log + skip |
| MarkItDown error | Retry with fallback |
Mỗi file có **processing status riêng**.
---
## 12. Performance & Scale
- OCR là bottleneck → async
- 1 file lớn = nhiều page jobs
- Scale theo số trang, không theo số file
---
## 13. Checklist triển khai
✅ Detect scan vs text
✅ OCR page-wise
✅ Page marker trong Markdown
✅ Chunk có page mapping
✅ Output contract rõ ràng
---
*Kết thúc Extraction & Normalization Playbook. File này nối trực tiếp sang Index/Search.*

View File

@@ -0,0 +1,246 @@
# 4.OpenSearch-Index-Search-Playbook.md
> Tài liệu này kế thừa trực tiếp các file trước (13). Mục tiêu: thiết kế **Index & Search Layer** đảm bảo tra cứu nhanh, đúng quyền, hỗ trợ fulltext, semantic search và RAG về sau. Nội dung viết để **tái sử dụng lâu dài**, có thể nạp lại để tiếp tục triển khai.
---
## Mục lục
1. Vai trò của Index/Search trong pipeline
2. Nguyên tắc thiết kế
3. Kiến trúc logical của Search Layer
4. Thiết kế Index (mapping chi tiết)
5. ACLaware indexing & filtering
6. Fulltext Search
7. Vector & Semantic Search
8. Hybrid Search (khuyến nghị)
9. Highlight, Ranking & Relevance tuning
10. Query contract (API level)
11. Performance & Scale
12. Lifecycle management (update/delete)
13. Checklist triển khai
---
## 1. Vai trò của Index/Search trong pipeline
```text
Extraction & Chunking
Index Layer (OpenSearch)
Search UI / Chat (RAG)
```
Index/Search chịu trách nhiệm:
- Lưu trữ **chunk nội dung + metadata + ACL**
- Trả kết quả **nhanh, chính xác, đúng quyền**
- Cho phép search theo **từ khóa lẫn ngữ nghĩa**
---
## 2. Nguyên tắc thiết kế
1. **Chunkfirst, không filefirst**
2. **Permission filter ở query time nhưng dữ liệu đã chuẩn hóa từ ingestion**
3. **Hybrid search mặc định** (keyword + vector)
4. **Index schema ổn định**, embedding thay đổi được
5. **Reindex được từ output Extraction mà không cần SharePoint**
---
## 3. Kiến trúc logical của Search Layer
```text
OpenSearch Cluster
├── text index
├── vector index (hoặc combined)
├── analyzer (vi, en)
└── ACL filter
```
Có thể:
- Dùng **1 index combined** (text + vector)
- Hoặc **2 index song song** (đơn giản giai đoạn đầu: 1 index)
---
## 4. Thiết kế Index (Mapping)
### 4.1 Document unit
Mỗi document trong index = **1 chunk**.
### 4.2 Mapping gợi ý
```json
{
"mappings": {
"properties": {
"chunk_id": { "type": "keyword" },
"file_id": { "type": "keyword" },
"file_name": { "type": "text" },
"text": {
"type": "text",
"analyzer": "standard",
"search_analyzer": "standard"
},
"embedding": {
"type": "knn_vector",
"dimension": 768
},
"site_id": { "type": "keyword" },
"page_from": { "type": "integer" },
"page_to": { "type": "integer" },
"source_url": { "type": "keyword" },
"permissions": { "type": "keyword" },
"updated_at": { "type": "date" }
}
}
}
```
---
## 5. ACLaware Indexing & Filtering
### 5.1 Nguyên tắc
- Không index public rồi filter payload
- Mỗi chunk mang theo **list principal IDs** (user/group)
### 5.2 Filter tại query
```json
{
"terms": {
"permissions": ["current_user_id", "group_id_1"]
}
}
```
---
## 6. Fulltext Search
Sử dụng khi:
- Tìm chính xác điều khoản, mã số, tên riêng
Ví dụ query:
```json
{
"match": {
"text": "hợp đồng lao động không xác định thời hạn"
}
}
```
---
## 7. Vector & Semantic Search
Sử dụng khi:
- Câu hỏi tự nhiên
- Nội dung diễn đạt khác từ khóa
```json
{
"knn": {
"embedding": {
"vector": [ ... ],
"k": 10
}
}
}
```
---
## 8. Hybrid Search (Khuyến nghị mặc định)
```json
{
"bool": {
"must": [
{
"match": { "text": "chấm dứt hợp đồng" }
}
],
"should": [
{
"knn": {
"embedding": {
"vector": [ ... ],
"k": 10
}
}
}
]
}
}
```
Score cuối = combine(keyword_score, semantic_score)
---
## 9. Highlight, Ranking & Relevance
### 9.1 Highlight
- Highlight ở field `text`
- Trả snippet cho UI
### 9.2 Ranking hints
- Boost theo:
- page proximity
- recency (updated_at)
- heading match
---
## 10. Query Contract (API nội bộ)
### POST /search
Input:
```json
{ "query": "...", "user_id": "...", "groups": ["..."] }
```
Output:
```json
{
"results": [
{ "file_name": "...", "page": 5, "snippet": "...", "url": "..." }
]
}
```
---
## 11. Performance & Scale
- Index theo chunk, không theo file
- Shard theo dữ liệu, không theo tenant sớm
- Cache query phổ biến
---
## 12. Lifecycle Management
| Event | Action |
|------|-------|
| File update | Delete chunks cũ → index lại |
| File delete | Soft delete hoặc remove |
| Reembedding | Update `embedding` field |
---
## 13. Checklist triển khai
✅ Mapping ổn định
✅ ACL filter hoạt động
✅ Hybrid search default
✅ Highlight trả đúng trang
✅ Reindex không cần SharePoint
---
*Kết thúc Index & Search Playbook. File tiếp theo sẽ là RAG / Chat Layer.*

View File

@@ -0,0 +1,242 @@
# 5.RAG-Chat-Application-Playbook.md
> Tài liệu này mô tả **tầng RAG Chat** xây dựng trên Search (file 4). Mục tiêu là:
> - Giúp **AI trả lời đúng có dẫn chứng không hallucinate**
> - Giúp **người dùng cuối dễ hiểu, dễ tin, dễ dùng**
> - Có thể dùng làm **tài liệu tham khảo khi soạn Hướng dẫn sử dụng (User Guide)**
>
> File được viết để **AI agent đọc là triển khai được**, **con người đọc là hiểu và sử dụng được**.
---
## Mục lục
1. RAG Chat là gì trong hệ thống này?
2. Nguyên tắc thiết kế RAG Chat
3. Kiến trúc tổng thể RAG Chat
4. Vai trò của Search trong RAG
5. Luồng xử lý câu hỏi (EndtoEnd)
6. Prompt Strategy (Quan trọng nhất)
7. Context Assembly & Citation
8. Tránh Hallucination & Guardrails
9. Trải nghiệm người dùng (UX Guidelines)
10. Các chế độ Chat khuyến nghị
11. Permission propagation
12. Logging & Explainability
13. Checklist triển khai & Checklist hướng dẫn sử dụng
---
## 1. RAG Chat là gì trong hệ thống này?
**RAG (RetrievalAugmented Generation)** = AI **KHÔNG tự nghĩ**, mà:
1. Tìm dữ liệu liên quan trong hệ thống Search
2. Chỉ dùng dữ liệu đó để trả lời
3. Luôn nói rõ **lấy thông tin từ đâu**
Trong hệ thống này:
- ❌ Chat **không** thay thế Search
- ✅ Chat **dựa hoàn toàn trên Search**
---
## 2. Nguyên tắc thiết kế RAG Chat
1. **Searchfirst, LLMsecond**
2. **Không có dữ liệu → không trả lời**
3. **Trả lời = Nội dung + Dẫn chứng**
4. **Ngôn ngữ rõ ràng, không học thuật thừa**
5. **Người dùng luôn có thể click mở tài liệu gốc**
---
## 3. Kiến trúc tổng thể RAG Chat
```text
User Question
Query Understanding
Search Layer (OpenSearch)
├─ Top K chunks (ACLaware)
Context Assembly
LLM (Answer generation)
Answer + Citations
```
---
## 4. Vai trò của Search trong RAG
Search quyết định:
- AI **được phép biết gì**
- AI **không được phép bịa gì**
Quy tắc:
- LLM **chỉ được dùng context do Search trả về**
- Không cho LLM truy cập internet / training data
---
## 5. Luồng xử lý câu hỏi (EndtoEnd)
```text
[User hỏi]
[Normalize câu hỏi]
[Hybrid Search (keyword + vector)]
[Lọc theo permission user]
[Chọn top K chunks]
[Build context + citation map]
[LLM sinh câu trả lời]
[Trả lời + link tài liệu]
```
---
## 6. Prompt Strategy (Rất quan trọng)
### 6.1 System Prompt (bắt buộc)
```text
Bạn là trợ lý tra cứu tài liệu nội bộ.
Bạn CHỈ được trả lời dựa trên thông tin được cung cấp trong CONTEXT.
Nếu CONTEXT không đủ, hãy trả lời:
"Tôi không tìm thấy thông tin trong các tài liệu hiện có."
Mỗi câu trả lời phải kèm theo nguồn trích dẫn.
```
---
### 6.2 User Prompt Template
```text
CÂU HỎI:
{{user_question}}
CONTEXT:
{{retrieved_chunks}}
```
---
### 6.3 Output Format (khuyến nghị)
```text
TRẢ LỜI NGẮN GỌN:
...
CHI TIẾT:
...
NGUỒN THAM KHẢO:
- Tài liệu A trang 5
- Tài liệu B trang 12
```
➡️ Format này **rất phù hợp để đưa vào User Guide**.
---
## 7. Context Assembly & Citation
### 7.1 Context Assembly
- Giữ đúng thứ tự logic
- Không quá dài (token budget)
- Mỗi chunk có ID và nguồn
### 7.2 Citation Object
```json
{
"chunk_id": "...",
"file_name": "...",
"page": 7,
"url": "..."
}
```
---
## 8. Tránh Hallucination & Guardrails
✅ BẮT BUỘC:
- Nếu không có chunk phù hợp → không trả lời
- Không "suy luận thêm" ngoài context
✅ Câu trả lời chuẩn khi không đủ dữ liệu:
> "Hiện tại tôi không tìm thấy thông tin trong các tài liệu nội bộ để trả lời câu hỏi này."
---
## 9. Trải nghiệm người dùng (UX Guidelines)
### 9.1 Người dùng nên cảm nhận gì?
- AI **đáng tin**
- Nói **giống đồng nghiệp biết tài liệu**, không giống chatbot chung chung
### 9.2 UX khuyến nghị
- Mỗi đoạn trả lời có nút "Mở tài liệu"
- Highlight đoạn liên quan trong PDF
---
## 10. Các chế độ Chat khuyến nghị
| Mode | Mô tả | Đối tượng |
|----|------|----------|
| Tra cứu nhanh | Trả lời ngắn + link | Nhân viên |
| Giải thích | Có diễn giải | Đào tạo |
| So sánh | So nhiều tài liệu | Quản lý |
---
## 11. Permission Propagation
Nguyên tắc:
- Chat **không trả về thứ Search không trả**
- Không lộ tên file tồn tại nếu user không có quyền
---
## 12. Logging & Explainability
Lưu lại:
- Question
- Retrieved chunks
- Answer
- Citation
➡️ Phục vụ audit, cải tiến prompt, training nội bộ
---
## 13. Checklist triển khai & Checklist hướng dẫn sử dụng
### 13.1 Checklist kỹ thuật
✅ Search trước Chat
✅ Prompt chặt chẽ
✅ Citation bắt buộc
✅ Permission endtoend
### 13.2 Checklist cho User Guide
✅ Giải thích AI làm gì / không làm gì
✅ Hướng dẫn đọc citation
✅ Cách phản hồi khi AI không tìm thấy dữ liệu
---
*Kết thúc RAG Chat Playbook. Đây là tầng trên cùng của hệ thống.*

View File

@@ -0,0 +1,241 @@
# 6.Operations-Monitoring-Governance-Playbook.md
> Tài liệu này mô tả **cách vận hành, giám sát và kiểm soát** toàn bộ hệ thống SharePoint → Search → RAG Chat trong môi trường doanh nghiệp.
> Đây là tài liệu **rất quan trọng sau PoC**, đảm bảo hệ thống **bền vững, an toàn, có thể mở rộng và được tin cậy lâu dài**.
>
> File được viết để:
> - IT / Ops / Security đọc là hiểu
> - AI agent đọc là biết cách triển khai monitoring
> - Là nền tảng cho **quy trình vận hành & governance nội bộ**
---
## Mục lục
1. Mục tiêu Operations & Governance
2. Nguyên tắc vận hành
3. Tổng quan các tầng cần giám sát
4. Monitoring chi tiết theo từng tầng
5. KPI & Quality Metrics
6. Alerting & Incident Response
7. Logging & Audit Trail
8. Data Governance & Compliance
9. Model / Prompt Governance
10. User Feedback Loop
11. Backup, Rollback & Disaster Recovery
12. Phân quyền vận hành (Ops Roles)
13. Checklist vận hành định kỳ
---
## 1. Mục tiêu Operations & Governance
Hệ thống không chỉ cần "chạy được", mà phải:
- ✅ Ổn định
- ✅ Đúng dữ liệu
- ✅ Đúng quyền
- ✅ Truy vết được
- ✅ Giải thích được
Mục tiêu cuối cùng:
> **Người dùng tin IT kiểm soát Ban lãnh đạo yên tâm**
---
## 2. Nguyên tắc vận hành
1. **Fail rõ ràng, không fail im lặng**
2. **Mỗi tài liệu đều có lifecycle**
3. **Mỗi câu trả lời đều có log & nguồn**
4. **AI không được vượt quyền dữ liệu**
5. **Có thể rollback bất kỳ tầng nào**
---
## 3. Tổng quan các tầng cần giám sát
```text
[SharePoint]
[Ingestion]
[Extraction / OCR]
[Index / Search]
[RAG Chat]
```
Mỗi tầng phải có:
- Health check
- Metric
- Log
---
## 4. Monitoring chi tiết theo từng tầng
### 4.1 Ingestion Layer
**Theo dõi:**
- Số file quét / phút
- Delta sync success rate
- File fail theo loại lỗi
**Cảnh báo khi:**
- Delta token không cập nhật > N giờ
- Lỗi permission tăng đột biến
---
### 4.2 Extraction / OCR Layer
**Theo dõi:**
- Thời gian OCR / trang
- OCR failure rate
- Queue length
**Cảnh báo khi:**
- OCR latency vượt ngưỡng
- OCR fail liên tục cùng 1 file type
---
### 4.3 Index / Search Layer
**Theo dõi:**
- Query latency (p50/p95)
- Index size
- Search error rate
**Cảnh báo khi:**
- Query > SLA
- Index out-of-sync
---
### 4.4 RAG Chat Layer
**Theo dõi:**
- Số câu hỏi / ngày
- % câu trả lời "không tìm thấy dữ liệu"
- Thời gian phản hồi
**Cảnh báo khi:**
- Error LLM
- Citation missing
---
## 5. KPI & Quality Metrics
### 5.1 KPI kỹ thuật
- Ingestion success rate ≥ 99%
- OCR success rate ≥ 95%
- Search latency ≤ 3s
### 5.2 KPI người dùng
- Query có kết quả hữu ích ≥ X%
- Click vào tài liệu gốc ≥ Y%
---
## 6. Alerting & Incident Response
### 6.1 Nguyên tắc
- Alert phải **actionable**
- Có owner rõ ràng
### 6.2 Incident Flow
```text
Detect → Triage → Mitigate → Root cause → Post-mortem
```
---
## 7. Logging & Audit Trail
### 7.1 Log bắt buộc
- Ingestion log (file-level)
- Search log (query-level)
- Chat log (question, context, answer, citation)
### 7.2 Audit sử dụng khi:
- Khiếu nại kết quả AI
- Compliance / kiểm toán
---
## 8. Data Governance & Compliance
### 8.1 Nguyên tắc dữ liệu
- File gốc không rời SharePoint
- Không lưu dữ liệu ngoài phạm vi cho phép
### 8.2 Retention
- Metadata & log theo chính sách công ty
- Cho phép purge theo yêu cầu
---
## 9. Model / Prompt Governance
### 9.1 Versioning
- Prompt phải có version
- Model phải có version
### 9.2 Thay đổi phải:
- Có test
- Có rollback plan
---
## 10. User Feedback Loop
### 10.1 Thu thập feedback
- Nút "Câu trả lời hữu ích / không hữu ích"
- Comment ngắn
### 10.2 Sử dụng feedback để:
- Điều chỉnh prompt
- Điều chỉnh search ranking
---
## 11. Backup, Rollback & DR
- Backup index định kỳ
- Có thể rebuild index từ Extraction output
- DR plan cho:
- OpenSearch
- Metadata DB
---
## 12. Phân quyền vận hành (Ops Roles)
| Role | Trách nhiệm |
|----|-------------|
| System Admin | Hạ tầng |
| Data Admin | Ingestion/Search |
| AI Admin | Prompt/Model |
| Auditor | Log/Compliance |
---
## 13. Checklist vận hành định kỳ
### Hàng ngày
✅ Ingestion health
✅ OCR queue
### Hàng tuần
✅ Re-index test
✅ Permission sync
### Hàng tháng
✅ Prompt review
✅ Compliance review
---
*Kết thúc Operations & Governance Playbook. Đây là file hoàn thiện hệ thống ở mức enterprise.*

View File

@@ -0,0 +1,130 @@
# 8.EndToEnd-Processing-Flows-Bullets.md
> File này liệt kê **TOÀN BỘ các luồng xử lý cần thiết** để triển khai và mở rộng hệ thống.
> Dạng **gạch đầu dòng**, dùng như **bản đồ tư duy kỹ thuật**, hoặc checklist khi mở rộng.
---
## A. Luồng Ingestion
- Load config site / library
- Authenticate Graph (app-only)
- First full delta snapshot
- Persist delta token
- Poll delta định kỳ
- Detect create / update / delete
- Fetch metadata
- Fetch & flatten permissions
- Decide eligible file
- Emit job downstream
---
## B. Luồng Permission
- Resolve direct users
- Resolve AAD groups
- Expand nested groups
- Cache membership
- Attach ACL to file/chunk
---
## C. Luồng Extraction
- Receive file job
- Detect file type
- Detect scan vs text PDF
- OCR per page (if needed)
- Convert to Markdown
- Insert page markers
- Normalize text
- Remove noise
---
## D. Luồng Chunking
- Split by heading
- Split by page
- Validate token length
- Attach page range
- Attach source URL
---
## E. Luồng Indexing
- Validate mapping version
- Generate embedding
- Attach ACL
- Index chunk
- Remove old chunks (on update)
---
## F. Luồng Search
- Receive query
- Resolve user identity
- Resolve user groups
- Hybrid search
- Apply ACL filter
- Score & rank
- Highlight text
- Return results
---
## G. Luồng RAG Chat
- Receive question
- Decide Search vs Chat
- Retrieve top K chunks
- Build context
- Enforce token budget
- Generate answer
- Attach citations
- Return answer
---
## H. Luồng Feedback
- Collect user feedback
- Store feedback
- Aggregate metrics
- Feed prompt tuning
- Feed ranking tuning
---
## I. Luồng Ops & Monitoring
- Health check all services
- Collect metrics
- Trigger alerts
- Incident handling
- Post-mortem
---
## J. Luồng Governance & Change
- Prompt version change
- Model version change
- Embedding change
- Re-index strategy
- Rollback
---
## Cách sử dụng file này
- Dùng làm checklist triển khai
- Dùng để chia task cho AI agent
- Dùng làm reference mở rộng hệ thống
---
*File này intentionally không chi tiết nó là xương sống logic cho mọi mở rộng sau này.*

View File

@@ -0,0 +1,163 @@
# 9.Appendix-Vietnamese-OCR-Strategy.md
> **Phụ lục chiến lược OCR Tiếng Việt** cho toàn bộ hệ thống SharePoint → Search → RAG.
>
> ⚠️ **LƯU Ý QUAN TRỌNG**
> - File này là **phụ lục độc lập**, **KHÔNG chỉnh sửa** các file 16.
> - Dùng để:
> - Thống nhất nhận thức kỹ thuật về OCR tiếng Việt
> - Làm tài liệu tham chiếu khi triển khai / audit / mở rộng
> - Tránh tranh luận lại từ đầu khi đổi AI agent hoặc dev
---
## 1. Khẳng định phạm vi ngôn ngữ
- **~99% tài liệu là Tiếng Việt (có dấu)**
- Chủ yếu: văn bản hành chính, hợp đồng, quy định, scan nhiều đời
- Yêu cầu:
- Giữ **đúng dấu tiếng Việt**
- Chấp nhận được với search ngữ nghĩa & RAG
➡️ OCR tiếng Việt được coi là **constraint nền**, không phải optional.
---
## 2. Vì sao OCR tiếng Việt khó hơn OCR tiếng Anh?
- Tiếng Việt có:
- Dấu thanh (sắc, huyền, hỏi, ngã, nặng)
- Dấu phụ (â, ê, ô, ă, ơ, ư, đ)
- Sai dấu = **đổi nghĩa hoàn toàn**
- Các engine OCR chung thường:
- Nhận đúng chữ cái
- **Sai hoặc rơi dấu** trong scan mờ
Nghiên cứu về Vietnamese Document Recognition chỉ ra đây là vấn đề cố hữu nhiều năm citeturn12search39.
---
## 3. Đánh giá các engine OCR phổ biến cho tiếng Việt (20252026)
### 3.1 Tesseract (vie.traineddata)
- ✅ Dễ triển khai, chạy CPU
- ❌ Độ chính xác dấu **không ổn định** với scan thực tế
- ❌ Không phù hợp cho văn bản pháp lý, hợp đồng
Kết luận: **KHÔNG đủ** làm engine chính cho hệ thống này citeturn12search43turn12search44.
---
### 3.2 EasyOCR
- ✅ Setup nhanh
- ❌ Nhận dạng tiếng Việt chỉ ở mức trung bình
- ❌ Không tối ưu cho tài liệu nhiều trang
Kết luận: chỉ dùng thử nghiệm, **không dùng production** cho tiếng Việt.
---
### 3.3 PaddleOCR (base model)
- ✅ Text detection rất tốt
- ✅ Xử lý layout, xoay, nghiêng tốt
- ❌ Text recognition tiếng Việt **chưa tối ưu nếu dùng model mặc định**
Được đánh giá cao hơn Tesseract nhưng cần **nâng cấp recognition** citeturn12search43turn12search46.
---
### 3.4 PaddleOCR + VietOCR (Khuyến nghị chính)
**Cấu hình thực tế được cộng đồng Việt Nam sử dụng nhiều nhất**:
```
Text Detection : PaddleOCR (DB / SAST)
Text Recognition : VietOCR (Transformer, tiếng Việt có dấu)
```
Ưu điểm:
- ✅ Nhận dạng tiếng Việt có dấu **tốt nhất trong opensource**
- ✅ Chạy onprem
- ✅ Có thể finetune theo domain
Đây là pipeline được dùng trong nhiều dự án OCR tiếng Việt thực tế citeturn12search36turn12search41.
---
### 3.5 Finetuned PaddleOCR cho tiếng Việt (Advanced)
- Finetune detection + recognition bằng dataset tiếng Việt
- Có thể đạt độ chính xác rất cao cho từng domain (hành chính, y tế…)
Nghiên cứu và repo gần đây cho thấy hiệu quả rõ rệt khi finetune PaddleOCR cho VN citeturn12search52turn12search54.
⚠️ Tuy nhiên:
- Tốn effort huấn luyện
- **KHÔNG cần làm ngay ở phase đầu**
---
## 4. Mức độ chính xác thực tế có thể kỳ vọng
| Chất lượng scan | OCR tiếng Việt tốt |
|---|---|
| Scan rõ, font chuẩn | 9799% |
| Scan nhiều đời | 9095% |
| Scan rất xấu | Không OCR nào cứu hoàn toàn |
➡️ Vì vậy hệ thống **không được phụ thuộc 100% vào OCR**.
---
## 5. OCR Tiếng Việt trong kiến trúc hiện tại (đã được tính trước)
Kiến trúc hệ thống **không giả định OCR hoàn hảo**:
| Vấn đề OCR | Cách kiến trúc xử lý |
|---|---|
| Sai 1 từ | Chunk nhỏ, search vẫn trúng |
| Sai dấu | Search hybrid + semantic |
| OCR fail | File bị đánh cờ, không đưa vào RAG |
| OCR kém | Người dùng mở file gốc |
➡️ Đây là **thiết kế có chủ đích**, không phải workaround.
---
## 6. Chiến lược triển khai OCR tiếng Việt theo phase
### Phase 1 An toàn, triển khai nhanh
- PaddleOCR (Detection) + VietOCR (Recognition)
- OCR pagewise
- Lưu confidence theo trang
### Phase 2 Tối ưu dần
- Tune preprocessing (deskew, binarization)
- Dictionary postprocess tiếng Việt
### Phase 3 Khi thực sự cần
- Finetune PaddleOCR/VietOCR theo domain
---
## 7. Nguyên tắc vận hành bắt buộc
- OCR < threshold → **KHÔNG đưa vào RAG Chat**
- OCR output luôn link về file gốc
- OCR có log & audit
---
## 8. Kết luận phụ lục
- ✅ OCR tiếng Việt **đã được tính đến từ đầu**
- ✅ Có giải pháp **đủ tốt cho production**
- ❌ Không có OCR tiếng Việt "100% đúng cho mọi trường hợp"
- ✅ Kiến trúc đã được thiết kế để **chịu sai có kiểm soát**
---
*Phụ lục này dùng để tham chiếu lâu dài khi nói về OCR tiếng Việt trong hệ thống.*

View File

@@ -0,0 +1,371 @@
# Ghi chú tránh lặp lại sai sót — Entra App + Microsoft Graph app-only cho SharePoint Ingestion
## 1) Tóm tắt sự cố đã gặp
### Hiện tượng
- Lấy token **thành công** bằng `client_credentials`.
- Token có các claim hợp lệ kiểu app-only:
- `aud = https://graph.microsoft.com`
- `idtyp = app`
- Nhưng gọi các API Graph như:
- `GET /sites/{hostname}`
- `GET /sites/{hostname}:/{server-relative-path}`
đều bị **401 Unauthorized**.
### Nguyên nhân gốc
App Registration đã được cấp **Delegated permissions** thay vì **Application permissions**.
Cụ thể lúc xảy ra lỗi, app đang có kiểu quyền như:
- `Files.Read.All`**Delegated**
- `Sites.Read.All`**Delegated**
- `User.Read`**Delegated**
Trong khi luồng đang dùng là:
- **OAuth 2.0 client credentials flow**
- **app-only / daemon / service-to-service**
- **không có user đăng nhập interactive**
=> Kết quả: token app-only **không có `roles`**, nên Microsoft Graph không chấp nhận token cho các API cần application permissions.
---
## 2) Bài học rút ra (phải kiểm tra trước khi test Graph)
### Quy tắc số 1
Nếu dùng **client credentials flow** thì **bắt buộc** phải cấp quyền ở dạng:
- **Microsoft Graph → Application permissions**
**Không dùng Delegated permissions** cho bài toán ingestion app-only.
### Quy tắc số 2
Sau khi sửa permission trong Entra App:
1. Bấm **Grant admin consent**
2. Lấy **token mới hoàn toàn**
3. Decode token và **kiểm tra `roles`** trước khi gọi Graph
### Quy tắc số 3
Nếu token app-only **không có `roles`**, thì **không test Graph tiếp**.
Phải quay lại kiểm tra:
- Permission type có phải **Application** không
- Có phải **Microsoft Graph** không
- Đã **Grant admin consent** chưa
- Có cần đợi propagation vài phút không
---
## 3) Cấu hình đúng cho PoC hiện tại
### Tối thiểu cần có trong Entra App
#### Microsoft Graph → Application permissions
- `Sites.Read.All`
- `Files.Read.All`
### Không cần cho app-only ingestion hiện tại
- `User.Read` (Delegated)
- Interactive login
- Redirect URI cho user login
---
## 4) Checklist fail-fast trước khi test Graph
## Checklist nhanh
- [ ] App dùng **client credentials flow**
- [ ] API permissions nằm dưới **Microsoft Graph**
- [ ] Permission type là **Application**
- [ ]`Sites.Read.All`
- [ ]`Files.Read.All`
- [ ] Đã **Grant admin consent**
- [ ] Đã lấy **token mới** sau khi sửa permission
- [ ] Token decode ra có `roles`
- [ ] `roles` chứa ít nhất:
- `Sites.Read.All`
- `Files.Read.All`
Nếu **một trong các dòng trên fail**, không chạy tiếp phần test Graph site/drive.
---
## 5) Script test hoàn chỉnh (đã thêm guard để tránh lặp lỗi)
> Script này làm đúng 4 việc:
> 1. Lấy token mới
> 2. Decode token
> 3. **Kiểm tra `roles` trước**
> 4. Chỉ khi roles đúng mới test Graph site endpoints
```powershell
$ErrorActionPreference = "Stop"
# ==========================================
# Điền thông tin tại đây
# ==========================================
$TenantId = "<TENANT_ID_GUID>"
$ClientId = "<CLIENT_ID_GUID>"
$ClientSecret = "<CLIENT_SECRET_VALUE>"
$SharePointHost = "285pdg.sharepoint.com"
$SitePath = "/sites/poc_system"
# ==========================================
function Get-GraphToken {
param(
[string]$TenantId,
[string]$ClientId,
[string]$ClientSecret
)
$tokenUrl = "https://login.microsoftonline.com/" + $TenantId + "/oauth2/v2.0/token"
$body = @{
client_id = $ClientId
client_secret = $ClientSecret
scope = "https://graph.microsoft.com/.default"
grant_type = "client_credentials"
}
return Invoke-RestMethod `
-Method Post `
-Uri $tokenUrl `
-ContentType "application/x-www-form-urlencoded" `
-Body $body
}
function Decode-JwtPayload {
param([string]$Jwt)
$parts = $Jwt.Split('.')
if ($parts.Length -lt 2) {
throw "JWT không hợp lệ."
}
$payload = $parts[1]
switch ($payload.Length % 4) {
2 { $payload += '==' }
3 { $payload += '=' }
}
$payload = $payload.Replace('-', '+').Replace('_', '/')
$bytes = [System.Convert]::FromBase64String($payload)
$json = [System.Text.Encoding]::UTF8.GetString($bytes)
return $json | ConvertFrom-Json
}
function Invoke-GraphGet {
param(
[string]$Url,
[string]$AccessToken,
[string]$Label
)
Write-Host ""
Write-Host ("=== " + $Label + " ===") -ForegroundColor Cyan
Write-Host $Url -ForegroundColor DarkGray
$headers = @{
Authorization = "Bearer " + $AccessToken
}
try {
$resp = Invoke-WebRequest `
-Method Get `
-Uri $Url `
-Headers $headers `
-UseBasicParsing
Write-Host "OK" -ForegroundColor Green
Write-Host ("HTTP " + [int]$resp.StatusCode) -ForegroundColor Green
if ($resp.Content) {
$json = $resp.Content | ConvertFrom-Json
$json | ConvertTo-Json -Depth 10
return $json
}
return $null
}
catch {
Write-Host "FAILED" -ForegroundColor Red
Write-Host $_.Exception.Message -ForegroundColor Red
if ($_.Exception.Response -ne $null) {
$resp = $_.Exception.Response
Write-Host ""
Write-Host "Status code:" -ForegroundColor Yellow
try {
Write-Host ([int]$resp.StatusCode)
}
catch {
Write-Host "Không đọc được StatusCode"
}
Write-Host ""
Write-Host "WWW-Authenticate:" -ForegroundColor Yellow
try {
Write-Host $resp.Headers["WWW-Authenticate"]
}
catch {
Write-Host "Không có WWW-Authenticate header"
}
Write-Host ""
Write-Host "Response body:" -ForegroundColor Yellow
try {
$stream = $resp.GetResponseStream()
$reader = New-Object System.IO.StreamReader($stream)
$bodyText = $reader.ReadToEnd()
Write-Host $bodyText
}
catch {
Write-Host "Không đọc được response detail."
}
}
return $null
}
}
# =======================================================
# 1) Lấy token mới
# =======================================================
$tokenResponse = Get-GraphToken `
-TenantId $TenantId `
-ClientId $ClientId `
-ClientSecret $ClientSecret
$accessToken = $tokenResponse.access_token
Write-Host "TOKEN OK" -ForegroundColor Green
Write-Host ("token_type : " + $tokenResponse.token_type)
Write-Host ("expires_in : " + $tokenResponse.expires_in)
# =======================================================
# 2) Decode token + kiểm tra claims quan trọng
# =======================================================
$claims = Decode-JwtPayload -Jwt $accessToken
Write-Host ""
Write-Host "=== TOKEN CLAIMS ===" -ForegroundColor Cyan
Write-Host ("aud : " + $claims.aud)
Write-Host ("appid : " + $claims.appid)
if ($claims.PSObject.Properties.Name -contains "idtyp") {
Write-Host ("idtyp : " + $claims.idtyp)
}
$roles = @()
if ($claims.PSObject.Properties.Name -contains "roles") {
$roles = @($claims.roles)
Write-Host "roles:" -ForegroundColor Yellow
$roles | ForEach-Object { Write-Host (" - " + $_) }
}
else {
Write-Host "roles: <KHÔNG CÓ>" -ForegroundColor Red
}
# =======================================================
# 3) Guard bắt buộc: nếu không có roles đúng thì stop luôn
# =======================================================
$hasSitesRead = $roles -contains "Sites.Read.All"
$hasFilesRead = $roles -contains "Files.Read.All"
if (-not $hasSitesRead) {
Write-Host ""
Write-Host "STOP: Token chưa có role 'Sites.Read.All'." -ForegroundColor Red
Write-Host "=> Kiểm tra lại Microsoft Graph -> Application permissions -> Sites.Read.All -> Grant admin consent." -ForegroundColor Yellow
return
}
if (-not $hasFilesRead) {
Write-Host ""
Write-Host "WARNING: Token chưa có role 'Files.Read.All'." -ForegroundColor Yellow
Write-Host "=> Site test có thể pass, nhưng drive/delta về sau sẽ fail." -ForegroundColor Yellow
}
# =======================================================
# 4) TEST 1 - GET /sites/{hostname}
# =======================================================
$rootByHostUrl = "https://graph.microsoft.com/v1.0/sites/" + $SharePointHost + "?`$select=id,webUrl"
$rootSite = Invoke-GraphGet `
-Url $rootByHostUrl `
-AccessToken $accessToken `
-Label "TEST 1 - GET /sites/{hostname}"
# =======================================================
# 5) TEST 2 - GET /sites/{hostname}:/{server-relative-path}
# =======================================================
$siteRef = $SharePointHost + ":" + $SitePath
$resolveSiteUrl = "https://graph.microsoft.com/v1.0/sites/" + $siteRef + "?`$select=id,displayName,webUrl"
$resolvedSite = Invoke-GraphGet `
-Url $resolveSiteUrl `
-AccessToken $accessToken `
-Label "TEST 2 - GET /sites/{hostname}:/{server-relative-path}"
# =======================================================
# 6) Summary
# =======================================================
Write-Host ""
Write-Host "=== SUMMARY ===" -ForegroundColor Cyan
if ($null -ne $rootSite) {
Write-Host "TEST 1: PASS" -ForegroundColor Green
}
else {
Write-Host "TEST 1: FAIL" -ForegroundColor Red
}
if ($null -ne $resolvedSite) {
Write-Host "TEST 2: PASS" -ForegroundColor Green
}
else {
Write-Host "TEST 2: FAIL" -ForegroundColor Red
}
```
---
## 6) Kỳ vọng đúng sau khi sửa quyền
### Token claim đúng
```text
aud : https://graph.microsoft.com
appid : <app-id>
idtyp : app
roles:
- Sites.Read.All
- Files.Read.All
```
### Test site đúng
- `TEST 1 - GET /sites/{hostname}` → PASS
- `TEST 2 - GET /sites/{hostname}:/{server-relative-path}` → PASS
---
## 7) Ghi chú vận hành nội bộ
### Khi nào được đi tiếp sang ingestion skeleton?
Chỉ khi đạt đủ 3 điều kiện:
1. Token có `roles`
2. `TEST 1` pass
3. `TEST 2` pass
### Nếu token vẫn không có `roles`
- Kiểm tra lại **Type** của permission có phải **Application** không
- Kiểm tra lại permission có nằm dưới **Microsoft Graph** không
- Kiểm tra đã bấm **Grant admin consent** chưa
- Đợi vài phút rồi lấy **token mới** lần nữa
---
## 8) Tên lỗi nội bộ để nhớ
> **Sai lầm đã gặp:**
> “Dùng `client_credentials` nhưng lại cấp **Delegated permissions** trong App Registration.”
### Cách nhớ nhanh
- **App-only** → **Application permissions**
- **Có user login** → **Delegated permissions**