- Thêm audit/sync_audit.py: Ghi lịch sử sync vào audit/sync_log.json
- Thêm API endpoints: /sync/history, /sync/history/{run_id}
- Frontend: Nút 'Lịch sử đồng bộ' + panel expand chi tiết từng file
- Sửa frontend served từ backend (http://localhost:8000)
- Cập nhật DEPLOYMENT_GUIDE với hướng dẫn chạy localhost
- Cập nhật ARCHITECTURE_MAP: Phase 8 hoàn thành
405 lines
11 KiB
Markdown
405 lines
11 KiB
Markdown
# 🚀 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.
|
|
|
|
---
|
|
|
|
## 0. Chạy hệ thống trên Localhost
|
|
|
|
### Yêu cầu
|
|
- Python 3.10+ với venv đã cài dependencies
|
|
- Docker (cho OpenSearch)
|
|
- Azure AD App Registration đã cấu hình
|
|
|
|
### Các bước khởi động
|
|
|
|
```bash
|
|
# 1. Khởi động OpenSearch
|
|
docker-compose up -d opensearch
|
|
|
|
# 2. Khởi động Backend (serves cả API + Frontend)
|
|
source venv/bin/activate
|
|
python3 api/main.py
|
|
|
|
# 3. Mở trình duyệt
|
|
# http://localhost:8000
|
|
```
|
|
|
|
### Truy cập
|
|
|
|
| URL | Mô tả |
|
|
|-----|-------|
|
|
| `http://localhost:8000` | Frontend (Login + Chat) |
|
|
| `http://localhost:8000/docs` | Swagger API Documentation |
|
|
| `http://localhost:8000/health` | Health check |
|
|
| `http://localhost:8000/auth/login` | SSO Azure AD redirect |
|
|
|
|
### Đăng nhập
|
|
- **SSO:** Bấm "Đăng nhập Microsoft SSO" → đăng nhập bằng tài khoản Microsoft 365
|
|
- **Email:** Nhập email bất kỳ (fallback, không cần password)
|
|
|
|
---
|
|
|
|
## 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 ✅ ĐÃ CẤU HÌNH
|
|
|
|
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` (thêm khi có domain)
|
|
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
|
|
|
|
- [x] Azure AD App Registration đã cấu hình đúng permissions
|
|
- [x] Client Secret còn hạn sử dụng
|
|
- [x] Redirect URI đã thêm cho localhost (`http://localhost:8000/auth/callback`)
|
|
- [x] ID tokens đã bật (implicit grant)
|
|
- [ ] Redirect URI cho production domain (khi có domain thật)
|
|
- [ ] 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.*
|