File size: 13,823 Bytes
dd37e97
9515000
 
e1361f5
 
9515000
e1361f5
dd37e97
e1361f5
b55a0b9
238cf71
b55a0b9
238cf71
b55a0b9
238cf71
b55a0b9
238cf71
b55a0b9
238cf71
b55a0b9
 
 
 
238cf71
b55a0b9
238cf71
07ac3fd
 
 
 
238cf71
b55a0b9
238cf71
b55a0b9
 
07ac3fd
 
b55a0b9
238cf71
b55a0b9
238cf71
b55a0b9
 
238cf71
07ac3fd
 
 
 
 
 
b55a0b9
238cf71
b55a0b9
238cf71
b55a0b9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
238cf71
 
b55a0b9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
238cf71
b55a0b9
238cf71
b55a0b9
238cf71
b55a0b9
 
 
 
 
 
 
 
 
238cf71
 
b55a0b9
238cf71
b55a0b9
238cf71
b55a0b9
238cf71
b55a0b9
 
 
 
 
 
 
238cf71
 
b55a0b9
238cf71
b55a0b9
 
 
 
 
 
 
 
 
 
 
 
 
238cf71
b55a0b9
238cf71
b55a0b9
 
 
238cf71
b55a0b9
238cf71
b55a0b9
 
 
 
 
 
238cf71
 
b55a0b9
238cf71
b55a0b9
238cf71
b55a0b9
 
 
 
 
 
 
238cf71
b55a0b9
238cf71
b55a0b9
238cf71
b55a0b9
238cf71
b55a0b9
 
 
 
 
 
 
 
238cf71
b55a0b9
238cf71
b55a0b9
238cf71
b55a0b9
 
 
 
 
238cf71
 
b55a0b9
 
 
 
 
 
 
 
 
 
238cf71
 
b55a0b9
 
 
 
 
 
 
 
 
 
 
 
 
 
238cf71
b55a0b9
238cf71
b55a0b9
 
 
 
 
238cf71
b55a0b9
238cf71
b55a0b9
238cf71
b55a0b9
 
 
 
 
 
238cf71
b55a0b9
238cf71
b55a0b9
 
238cf71
b55a0b9
 
 
 
238cf71
b55a0b9
 
 
 
 
238cf71
 
b55a0b9
238cf71
b55a0b9
 
 
 
 
 
 
238cf71
b55a0b9
238cf71
b55a0b9
238cf71
b55a0b9
 
 
 
 
 
 
 
238cf71
b55a0b9
238cf71
b55a0b9
 
 
 
 
 
 
 
 
 
 
238cf71
b55a0b9
 
 
 
238cf71
b55a0b9
238cf71
b55a0b9
238cf71
b55a0b9
 
 
 
238cf71
b55a0b9
238cf71
b55a0b9
238cf71
 
b55a0b9
 
 
238cf71
b55a0b9
 
238cf71
b55a0b9
 
 
238cf71
b55a0b9
 
 
 
 
 
 
 
 
 
238cf71
 
b55a0b9
 
 
 
238cf71
b55a0b9
 
238cf71
 
b55a0b9
238cf71
b55a0b9
 
 
 
238cf71
b55a0b9
238cf71
 
b55a0b9
 
 
 
 
238cf71
 
b55a0b9
238cf71
b55a0b9
238cf71
b55a0b9
 
 
238cf71
b55a0b9
 
 
238cf71
b55a0b9
238cf71
b55a0b9
 
 
 
238cf71
b55a0b9
238cf71
b55a0b9
 
 
238cf71
 
 
 
 
b55a0b9
 
 
 
238cf71
b55a0b9
 
 
238cf71
b55a0b9
 
 
238cf71
b55a0b9
07ac3fd
 
b55a0b9
07ac3fd
238cf71
 
 
 
 
 
 
 
b55a0b9
238cf71
 
 
b55a0b9
238cf71
b55a0b9
238cf71
b55a0b9
238cf71
 
b55a0b9
238cf71
 
b55a0b9
238cf71
b55a0b9
 
238cf71
b55a0b9
238cf71
b55a0b9
 
 
238cf71
caa1332
 
b55a0b9
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
---
title: 銀髮餐桌助手
emoji: 🥄
colorFrom: blue
colorTo: green
sdk: docker
app_port: 7860
---

# 銀髮餐桌助手 - RAG 系統

本文件描述銀髮餐桌助手的 RAG(Retrieval-Augmented Generation)系統架構與實作細節。

## RAG 系統概述

銀髮餐桌助手採用 RAG 技術為台灣銀髮族(65歲以上)提供智能營養飲食諮詢服務。RAG 系統透過檢索相關知識庫文檔,增強 AI 回應的準確性和可靠性,確保所有營養建議基於權威來源。

### 核心功能

- **知識檢索**:基於用戶問題從知識庫中檢索相關文檔
- **相似性搜索**:使用向量嵌入實現語義級相似性匹配
- **文檔增強生成**:將檢索到的文檔作為上下文,提升 AI 回應品質
- **個人化回應**:結合用戶健康檔案提供客製化建議

## 知識庫來源

知識庫內容托管在 **Hugging Face Dataset**- **Dataset**: [pcreem/dietinstruction](https://huggingface.co/datasets/pcreem/dietinstruction)
- 本地資料夾 `backend/data/` 用於存放下載的檔案
- 系統啟動時會自動從 Hugging Face 下載知識庫檔案

### 主要文檔

| 文件 | 內容 |
|------|------|
| `每日飲食指南手冊.pdf` | 衛福部每日飲食指南 |
| `高齡營養飲食質地衛教手冊.pdf` | 高齡者飲食質地指導 |
| `慢性病飲食原則.md` | 糖尿病、高血壓、高脂血症等慢性病飲食指南 |

### 文檔格式支援

- **Markdown (.md)**:主要知識庫格式
- **PDF (.pdf)**:支援 PDF 文件載入

### 自動下載機制

RAG 服務啟動時會檢查本地 `backend/data/` 資料夾:
- 若資料夾不存在或為空,自動從 Hugging Face Dataset 下載知識庫
- 若已有檔案,則使用本地版本

所有文檔經過處理後存入向量資料庫,供相似性搜索使用。

## 系統架構流程圖

```
┌─────────────────┐     ┌─────────────────┐     ┌─────────────────┐
│   User Query    │────►│   Chat Service  │────►│   RAG Service   │
│   (問題輸入)    │     │   (聊天服務)    │     │   (RAG服務)     │
└─────────────────┘     └────────┬────────┘     └────────┬────────┘
                                 │                      │
                                 │                      ▼
                                 │            ┌─────────────────┐
                                 │            │   Embeddings    │
                                 │            │   (向量化)      │
                                 │            └────────┬────────┘
                                 │                      │
                                 │                      ▼
                                 │            ┌─────────────────┐
                                 │            │  Supabase       │
                                 │            │  pgvector       │
                                 │            │  (向量資料庫)   │
                                 │            └────────┬────────┘
                                 │                      │
                                 │                      ▼
                                 │            ┌─────────────────┐
                                 │            │   Similarity    │
                                 │            │   Search        │
                                 │            │   (相似性搜索)  │
                                 │            └────────┬────────┘
                                 │                      │
                                 │                      ▼
                                 │            ┌─────────────────┐
                                 │            │ Relevant Docs   │
                                 │            │ (相關文檔)      │
                                 │            └────────┬────────┘
                                 │                      │
                                 ▼                      ▼
                        ┌─────────────────┐     ┌─────────────────┐
                        │   LLM Response  │◄────│   Context       │
                        │   (AI回應)      │     │   Integration   │
                        └─────────────────┘     └─────────────────┘
```

## 核心組件說明

### RAG 服務 ([`rag.py`](backend/rag.py))

RAG 服務是系統的核心模組,負責文檔處理和向量搜索。

```python
class RAGService:
    """RAG service for document management and similarity search."""
    
    def __init__(self):
        # 初始化 OpenAI 向量化模型
        self.embeddings = OpenAIEmbeddings(...)
        # 初始化 Supabase 向量存儲
        self.vector_store = SupabaseVectorStore(...)
        # 初始化文檔分塊器
        self.text_splitter = RecursiveCharacterTextSplitter(
            chunk_size=1000,
            chunk_overlap=200
        )
```

### 聊天服務 ([`chat_service.py`](backend/chat_service.py))

聊天服務整合 RAG 能力,提供 AI 對話功能。

```python
class ChatService:
    """Chat service for AI-powered conversations with RAG integration."""
    
    def __init__(self):
        # 初始化 LLM 模型
        self.llm = ChatOpenAI(...)
        # 整合 RAG 服務
        self.rag_service = get_rag_service()
```

### 資料庫設置 ([`setup_rag_db.py`](backend/setup_rag_db.py))

設置 pgvector 擴展和文檔表結構。

## 文檔處理流程

### 流程步驟

```
┌─────────────┐    ┌─────────────┐    ┌─────────────┐    ┌─────────────┐
│   載入文檔   │───►│   文檔分塊   │───►│   向量化     │───►│   存入資料庫 │
│   Loader    │    │   Chunker   │    │ Embedding   │    │   Storage   │
└─────────────┘    └─────────────┘    └─────────────┘    └─────────────┘
```

### 1. 文檔載入

支援多種文檔載入器:

```python
# PDF 載入
loader = PyPDFLoader(str(file_path))
documents = loader.load()

# Markdown 載入
loader = UnstructuredMarkdownLoader(str(file_path))
documents = loader.load()
```

### 2. 文檔分塊

使用 [`RecursiveCharacterTextSplitter`](backend/rag.py:66) 進行智慧分塊:

- **chunk_size**:1000 字元
- **chunk_overlap**:200 字元重疊
- **is_separator_regex**:false(使用純文字分隔)

每個區塊包含以下元數據:

```python
chunk.metadata = {
    "source": "文件路徑",
    "file_name": "檔案名稱",
    "chunk_id": "唯一識別碼"
}
```

### 3. 向量化

使用 OpenAI Embeddings 模型將文本轉換為向量:

```python
embeddings = OpenAIEmbeddings(
    model="azure-text-embedding-3-large",
    openai_api_key=api_key
)
# 支援 LiteLLM 相容端點
```

向量維度:**3072**

### 4. 向量存儲

存入 Supabase pgvector 向量資料庫:

```python
vector_store = SupabaseVectorStore(
    client=supabase_client,
    embedding=embeddings,
    table_name="documents",
    query_name="match_documents"
)
```

## 相似性搜索

### 基本搜索

```python
async def get_relevant_documents(self, query: str, k: int = 8) -> List[Document]:
    """執行相似性搜索檢索相關文檔"""
    results = await self.vector_store.asimilarity_search(query, k=k)
    return results
```

### 帶分數的搜索

```python
async def get_relevant_documents_with_scores(
    self, 
    query: str, 
    k: int = 8, 
    score_threshold: float = 0.7
) -> List[Document]:
    """執行帶分數閾值的相似性搜索"""
```

### 分頁搜索

```python
async def get_relevant_documents_paginated(
    self, 
    query: str,
    page: int = 1,
    page_size: int = 10,
    score_threshold: Optional[float] = None
) -> Dict[str, Any]:
    """執行分頁相似性搜索"""
```

### 搜索結果快取

系統使用文檔快取機制(TTL: 30 分鐘)優化效能:

```python
@cache_result(document_cache, "rag_documents", ttl=1800)
async def get_relevant_documents(self, query: str, k: int = 8):
    ...
```

## AI 對話整合

### 對話流程

1. 接收用戶問題
2. 檢索相關文檔(k=6)
3. 獲取用戶健康檔案
4. 格式化上下文資訊
5. 組合系統提示詞
6. 串流回應生成

### 系統提示詞

```python
system_prompt = """你是「銀髮餐桌助手」,專為台灣銀髮族設計的AI營養飲食顧問助手。

角色定位:
- 溫暖、耐心、專業的營養飲食顧問
- 專門為台灣銀髮族(65歲以上)提供飲食建議
- 熟悉台灣在地食材、飲食文化和生活習慣

核心原則:
1. 嚴格遵循台灣衛福部(MOHW)的營養指導原則
2. 僅提供營養建議,絕不進行醫療診斷
3. 針對銀髮族的特殊營養需求
4. 考慮台灣在地飲食文化"""
```

### 上下文整合

```python
def format_context_information(self, user_context, relevant_docs) -> str:
    """格式化用戶上下文和相關文檔"""
    # 組合用戶背景資訊
    # 組合相關營養指南文檔
    return formatted_context
```

## API 端點

### RAG 相關端點

| 端點 | 方法 | 說明 |
|------|------|------|
| `/api/chat` | POST | AI 聊天諮詢(含 RAG) |
| `/rag/load` | POST | 載入知識庫 |
| `/rag/search` | GET | 相似性搜索 |
| `/rag/count` | GET | 獲取文檔數量 |
| `/rag/clear` | DELETE | 清除知識庫 |
| `/` | GET | Gradio 聊天界面 |

### 聊天請求範例

```bash
curl -X POST "http://localhost:8000/api/chat" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "message": "請問銀髮族應該如何補充蛋白質?",
    "profile_id": "uuid-string"
  }'
```

### 知識庫載入請求

```bash
curl -X POST "http://localhost:8000/rag/load" \
  -H "Authorization: Bearer <token>"
```

## 快速開始

### 前置要求

- Python 3.8+
- PostgreSQL 13+(通過 Supabase,啟用 pgvector)
- Supabase 專案
- OpenAI API Key 或 LiteLLM API Key

### 環境變數配置

複製 `.env.example``.env` 並填入以下配置:

```bash
# Supabase Configuration
SUPABASE_URL=your_supabase_project_url
SUPABASE_SERVICE_ROLE_KEY=your_supabase_service_role_key

# Database URL for pgvector (Supabase PostgreSQL)
DATABASE_URL=postgresql+asyncpg://postgres:[YOUR_PASSWORD]@db.[YOUR_PROJECT_ID].supabase.co:5432/postgres

# OpenAI Configuration (or LiteLLM)
OPENAI_API_KEY=your_openai_api_key
OPENAI_BASE_URL=your_openai_base_url  # Optional, for LiteLLM/Azure

# Or use LiteLLM directly
LITELLM_API_KEY=your_litellm_api_key
LITELLM_BASE_URL=https://your-litellm-endpoint/

# Server Configuration
HOST=0.0.0.0
PORT=8000
```

### 安裝依賴

```bash
# 創建虛擬環境
python -m venv venv
source venv/bin/activate  # Linux/Mac
# 或 venv\Scripts\activate  # Windows

# 安裝依賴
pip install -r requirements.txt
```

### 資料庫設置

```bash
# 設置 pgvector 和文檔表
python setup_rag_db.py
```

### 啟動服務

```bash
# 啟動 FastAPI 服務
python app.py

# 或使用 uvicorn
uvicorn app:app --reload --host 0.0.0.0 --port 8000
```

### 載入知識庫

知識庫會在服務啟動時自動載入,或可手動觸發:

```bash
# 通過 API
curl -X POST "http://localhost:8000/rag/load"

# 或直接運行
python -m rag
```

### 測試 RAG 系統

```bash
python -m rag
python -m chat_service
```

### 訪問應用

- **API 文檔**: http://localhost:8000/api/docs
- **Gradio 聊天界面**: http://localhost:8000/
- **健康檢查**: http://localhost:8000/health

## 故障排除

### 常見問題

1. **pgvector 擴展未啟用**
   ```sql
   CREATE EXTENSION IF NOT EXISTS vector;
   ```

2. **向量維度不匹配**
   - 確保 embedding 向量維度為 3072
   - 檢查資料庫表結構:`embedding vector(3072)`

3. **SupabaseVectorStore 兼容性問題**
   - 系統已內建手動 RPC 回退機制
   - 使用 `match_documents` 函數直接執行相似性搜索

4. **知識庫載入失敗**
   - 檢查 Hugging Face Dataset 網路連接
   - 確認 Dataset `pcreem/dietinstruction` 存在且有檔案
   - 檢查 `backend/data/` 目錄存在且包含文件
   - 確認文件格式為支援的類型(.md, .pdf, .txt)

### 調試模式

```bash
# 啟用詳細日誌
export LOG_LEVEL=DEBUG
python app.py

# 或使用 uvicorn
uvicorn app:app --reload --log-level debug
```

## 監控與日誌

### 日誌配置

系統使用 Python 標準日誌庫:

```bash
LOG_LEVEL=INFO  # DEBUG, INFO, WARNING, ERROR
```

### 健康檢查

- `GET /health` - 服務健康狀態檢查
- 返回服務狀態、版本信息和資料庫連接狀態

## 安全考量

- 知識庫搜索無需認證(匿名用戶也可使用)
- 用戶健康檔案相關操作需要 JWT 認證
- 向量資料庫連接使用服務層級密鑰

---

**重要提醒**:本系統僅提供營養建議,無法替代專業醫療諮詢。如有健康問題,請諮詢專業醫師。