--- 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 " \ -H "Content-Type: application/json" \ -d '{ "message": "請問銀髮族應該如何補充蛋白質?", "profile_id": "uuid-string" }' ``` ### 知識庫載入請求 ```bash curl -X POST "http://localhost:8000/rag/load" \ -H "Authorization: Bearer " ``` ## 快速開始 ### 前置要求 - 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 認證 - 向量資料庫連接使用服務層級密鑰 --- **重要提醒**:本系統僅提供營養建議,無法替代專業醫療諮詢。如有健康問題,請諮詢專業醫師。