metadata
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
- 本地資料夾
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)
RAG 服務是系統的核心模組,負責文檔處理和向量搜索。
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)
聊天服務整合 RAG 能力,提供 AI 對話功能。
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)
設置 pgvector 擴展和文檔表結構。
文檔處理流程
流程步驟
┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ 載入文檔 │───►│ 文檔分塊 │───►│ 向量化 │───►│ 存入資料庫 │
│ Loader │ │ Chunker │ │ Embedding │ │ Storage │
└─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘
1. 文檔載入
支援多種文檔載入器:
# PDF 載入
loader = PyPDFLoader(str(file_path))
documents = loader.load()
# Markdown 載入
loader = UnstructuredMarkdownLoader(str(file_path))
documents = loader.load()
2. 文檔分塊
使用 RecursiveCharacterTextSplitter 進行智慧分塊:
- chunk_size:1000 字元
- chunk_overlap:200 字元重疊
- is_separator_regex:false(使用純文字分隔)
每個區塊包含以下元數據:
chunk.metadata = {
"source": "文件路徑",
"file_name": "檔案名稱",
"chunk_id": "唯一識別碼"
}
3. 向量化
使用 OpenAI Embeddings 模型將文本轉換為向量:
embeddings = OpenAIEmbeddings(
model="azure-text-embedding-3-large",
openai_api_key=api_key
)
# 支援 LiteLLM 相容端點
向量維度:3072
4. 向量存儲
存入 Supabase pgvector 向量資料庫:
vector_store = SupabaseVectorStore(
client=supabase_client,
embedding=embeddings,
table_name="documents",
query_name="match_documents"
)
相似性搜索
基本搜索
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
帶分數的搜索
async def get_relevant_documents_with_scores(
self,
query: str,
k: int = 8,
score_threshold: float = 0.7
) -> List[Document]:
"""執行帶分數閾值的相似性搜索"""
分頁搜索
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 分鐘)優化效能:
@cache_result(document_cache, "rag_documents", ttl=1800)
async def get_relevant_documents(self, query: str, k: int = 8):
...
AI 對話整合
對話流程
- 接收用戶問題
- 檢索相關文檔(k=6)
- 獲取用戶健康檔案
- 格式化上下文資訊
- 組合系統提示詞
- 串流回應生成
系統提示詞
system_prompt = """你是「銀髮餐桌助手」,專為台灣銀髮族設計的AI營養飲食顧問助手。
角色定位:
- 溫暖、耐心、專業的營養飲食顧問
- 專門為台灣銀髮族(65歲以上)提供飲食建議
- 熟悉台灣在地食材、飲食文化和生活習慣
核心原則:
1. 嚴格遵循台灣衛福部(MOHW)的營養指導原則
2. 僅提供營養建議,絕不進行醫療診斷
3. 針對銀髮族的特殊營養需求
4. 考慮台灣在地飲食文化"""
上下文整合
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 聊天界面 |
聊天請求範例
curl -X POST "http://localhost:8000/api/chat" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"message": "請問銀髮族應該如何補充蛋白質?",
"profile_id": "uuid-string"
}'
知識庫載入請求
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 並填入以下配置:
# 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
安裝依賴
# 創建虛擬環境
python -m venv venv
source venv/bin/activate # Linux/Mac
# 或 venv\Scripts\activate # Windows
# 安裝依賴
pip install -r requirements.txt
資料庫設置
# 設置 pgvector 和文檔表
python setup_rag_db.py
啟動服務
# 啟動 FastAPI 服務
python app.py
# 或使用 uvicorn
uvicorn app:app --reload --host 0.0.0.0 --port 8000
載入知識庫
知識庫會在服務啟動時自動載入,或可手動觸發:
# 通過 API
curl -X POST "http://localhost:8000/rag/load"
# 或直接運行
python -m rag
測試 RAG 系統
python -m rag
python -m chat_service
訪問應用
- API 文檔: http://localhost:8000/api/docs
- Gradio 聊天界面: http://localhost:8000/
- 健康檢查: http://localhost:8000/health
故障排除
常見問題
pgvector 擴展未啟用
CREATE EXTENSION IF NOT EXISTS vector;向量維度不匹配
- 確保 embedding 向量維度為 3072
- 檢查資料庫表結構:
embedding vector(3072)
SupabaseVectorStore 兼容性問題
- 系統已內建手動 RPC 回退機制
- 使用
match_documents函數直接執行相似性搜索
知識庫載入失敗
- 檢查 Hugging Face Dataset 網路連接
- 確認 Dataset
pcreem/dietinstruction存在且有檔案 - 檢查
backend/data/目錄存在且包含文件 - 確認文件格式為支援的類型(.md, .pdf, .txt)
調試模式
# 啟用詳細日誌
export LOG_LEVEL=DEBUG
python app.py
# 或使用 uvicorn
uvicorn app:app --reload --log-level debug
監控與日誌
日誌配置
系統使用 Python 標準日誌庫:
LOG_LEVEL=INFO # DEBUG, INFO, WARNING, ERROR
健康檢查
GET /health- 服務健康狀態檢查- 返回服務狀態、版本信息和資料庫連接狀態
安全考量
- 知識庫搜索無需認證(匿名用戶也可使用)
- 用戶健康檔案相關操作需要 JWT 認證
- 向量資料庫連接使用服務層級密鑰
重要提醒:本系統僅提供營養建議,無法替代專業醫療諮詢。如有健康問題,請諮詢專業醫師。