silver / README.md
Song
readme
07ac3fd
---
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 認證
- 向量資料庫連接使用服務層級密鑰
---
**重要提醒**:本系統僅提供營養建議,無法替代專業醫療諮詢。如有健康問題,請諮詢專業醫師。