「讓 LLM 知道你的私有資料」是 Agentic SaaS 最常見的需求之一。RAG(Retrieval-Augmented Generation)是目前最成熟的解法,但它比 demo 裡看起來複雜得多:選什麼向量庫、怎麼切塊、召回品質如何量測、記憶分幾層管理——每個環節都有工程取捨。
RAG 的基本架構
索引階段(離線)
- 把文件切成小塊(chunks)
- 每個 chunk 用 embedding model 轉成向量
- 把向量和原始文字存入向量資料庫
查詢階段(線上)
- 把用戶問題轉成向量(用相同 embedding model)
- 在向量庫做相似度搜索,取回 top-k 相關 chunks
- 把 chunks 塞進 LLM 的上下文(context)
- LLM 根據這些 retrieved context 回答問題
這個流程看起來簡單,但有四個環節容易出問題:
分塊策略(Chunking)
分塊是 RAG 品質的核心變數,卻是 demo 裡最常被忽略的。
固定大小分塊(Fixed-size,按 token 數切):實作最簡單,但會在句子中間斷開,破壞語意完整性。常用大小 512 tokens,有 50-100 token 的 overlap 減少邊界遺失。
語意分塊(Semantic chunking):用 embedding 相似度判斷語意邊界,同一主題的段落放在同一 chunk。理論上品質更好,但計算成本高、邊界判斷本身也可能出錯。
文件結構分塊(Structural chunking):按 markdown 標題、HTML tag、PDF 段落邊界分塊。在有良好結構的文件(技術文件、法律文件)上效果好;非結構化文字效果有限。
Parent-child 分塊:把文件切成小 child chunks 用於高精度向量搜索,同時保留對應的大 parent chunk 作為 LLM 的實際上下文。Google 的 RAG best practices 文件和 LlamaIndex 均推薦這個模式(這是主張,有大量工程師驗證,但缺乏嚴格對照實驗)。
向量資料庫的選型
主流選項的工程特性:
| 工具 | 特性 | 適用場景 |
|---|---|---|
| pgvector(PostgreSQL extension) | 在現有 Postgres 裡加向量搜索,運維成本低 | 資料量 < 1M 向量,希望用 SQL 做 hybrid search |
| Pinecone | 全托管,無需自建,支援 metadata filtering | 快速上線,不想管基礎建設 |
| Weaviate | 開源,內建 hybrid search(BM25+向量) | 需要語意+關鍵字混合搜索 |
| Qdrant | 開源,高性能,支援 payload filtering | 向量量大、需要複雜 filter |
「用什麼向量庫最好」是個取捨問題,不是技術優劣問題。pgvector 在資料量小、希望減少系統複雜度時是合理選擇;Pinecone 在需要快速驗證時省事;Weaviate/Qdrant 在有 hybrid search 需求時有優勢。
召回品質:Pure Vector 的局限
Pure vector search 的致命弱點是精確比對(exact match)。如果用戶問「LLM01 是什麼」而文件裡只有「Prompt Injection」的段落,向量相似度可能不夠高,即使語意上是同一件事。反之,如果搜索「帳戶」而文件有「account」(不同語言),向量通常能搭橋,但關鍵字搜索不行。
業界普遍的解法是 Hybrid Search:向量搜索和 BM25/TF-IDF 關鍵字搜索結果用 Reciprocal Rank Fusion(RRF)合併排名。這是個工程主張(業界廣泛實作),但「最佳 hybrid 權重」依資料分布和任務性質不同,沒有放諸四海的答案。
記憶的分層架構
RAG 是「知識庫召回」,但一個完整的 Agentic SaaS 還需要更細緻的記憶分層:
In-context memory(上下文記憶) 直接放在 LLM 當前請求的 context window 裡的資訊:system prompt、近期對話、被召回的 chunks。有上限(Claude 200K tokens、GPT-4o 128K),且每 token 都有 API 費用。Context window 再大,也不適合把整個知識庫塞進去(成本和延遲都不可接受)。
Semantic memory(語意記憶/向量召回) 就是 RAG 在做的事:把大量知識存在向量庫,按需搜索取回相關片段。適合「靜態或緩慢變化的知識」(產品文件、FAQ、法規)。
Episodic memory(事件記憶) 用戶的歷史操作、過去的對話摘要、已完成的任務記錄。通常存在結構化資料庫(PostgreSQL)或 KV store,按 user_id 和 session_id 索引。Stanford Generative Agents(Park et al., 2023)用 recency × importance × relevance 三維評分決定哪些歷史事件值得召回——這個框架在學術上是已發表的研究,但工業實作中各家取捨不同。
Procedural memory(程序記憶) Agent 學到的技能、工作流程、已知的工具使用模式。最難實作,目前多以 fine-tuning 或精心設計的 few-shot examples 近似——這個分層的工程實作尚未成熟,業界沒有統一做法。
知識庫的新鮮度問題
RAG 最容易被忽略的問題是:知識庫的索引怎麼跟上資料的變化?
文件更新後,舊的 chunks 仍然在向量庫裡,會被召回並給 LLM 看過時的資訊。常見的工程解法:
- 每個 chunk 記錄
source_doc_id和updated_at;文件更新時刪除舊 chunks 重新索引 - 增量更新比全量重索引效率高,但需要仔細追蹤文件版本
- 重要文件在 prompt 裡標注資訊截止日期,讓 LLM 在回答時有機會判斷是否過時
「知識庫的更新頻率」和「重索引的成本與複雜度」之間的取捨,是 RAG 系統上線後最常被低估的維運問題。
延伸
- 幻覺和 grounding 問題 → 幻覺、Evals 與品質保證
- Context 上限對 RAG 設計的影響 → 限制、取捨與 Demo 不等於 Production
- 記憶分層的更深入討論(另一個專欄)→ AI memory(Agent Memory 架構)
- 全景與閱讀路徑 → AI Agentic SaaS 專欄首頁