- RAG(知識庫)= 讓 agent 從「查網路 / 憑記憶」變成「查你自己的文件」。
- 第一個關卡:RAG 需要 embedding 模型,Groq 沒有 → 用本機 bge-m3。
- 它其實存兩個庫:Postgres 存文字、Weaviate 存向量,靠一把 id 對應(不是 pgvector 也行,向量庫可插拔)。
- 最重要的一課:RAG chatflow 裡「知識檢索 → LLM 上下文」那條線沒接上,就會「查不到」甚至亂編;接上才會照文件答、還附出處。
- 鐵律:先單獨驗檢索(命中測試看分數),別等 agent 答完才發現撈錯。機密文件 → embedding + 聊天模型「兩個都本機」。
系列上一篇,我們讓 agent 學會「查網路」。這一篇更進一步:讓它查你自己的文件 —— 這就是 RAG(檢索增強生成),在 Dify 裡叫「知識庫」。我拿一批真的幼兒園招生文件(還混了幾份公司內部檔)實測,把「怎麼用、存在哪、怎麼驗、最容易漏的那條線」一次講清楚。
RAG 一句話 + 第一個關卡
RAG 分兩階段:建庫(上傳文件 → 切塊 → 算成向量存起來)、查詢(問題也算成向量 → 找語意最近的幾塊 → 塞給模型當小抄)。第一個關卡馬上來:「算成向量」需要一個 embedding 模型,而 Groq 只有聊天模型、沒有 embedding。所以要先掛本機 bge-m3(在模型供應商加一個「Text Embedding」型的模型,別選成 LLM)。這也是為什麼 RAG 幾乎一定會用到本機模型。
先驗檢索:命中測試(RAG 最重要的紀律)
建好庫、上傳文件(Dify 連 PDF / Word / Excel 都能解析切塊),先別急著接 agent。用知識庫的「命中測試」直接驗檢索:輸入一個「答案只在文件裡」的問題,看它撈回哪幾塊、相似度多少。
| 問題 | 撈回的塊 | 分數 |
|---|---|---|
| 非營利幼兒園費用 | 「非營利…第1胎每月 3,000元」 | 0.62 ✅ |
| 招生對象幾歲 | 「招收對象:2足歲至未滿3歲」 | 0.64 ✅ |
bge-m3 的向量分數落在 0.4~0.7 算健康命中(遠高於雜訊底 0.3)。為什麼要先單獨驗檢索?因為如果檢索就撈錯,後面 agent 答錯,你會誤以為是模型笨——其實是根本沒撈到對的內容。先把「檢索」這一段驗對,再談生成。
存在哪?其實是「兩個庫」
很多人以為 RAG 就一個向量庫。實際上 Dify 存兩個地方,靠一把 id 對應:

- Postgres(內容的真相來源):
document_segments存每一塊的實際文字 content + position + tokens +index_node_id(連向量的鑰匙)+ hit_count(被檢索幾次)。 - Weaviate(語意搜尋專用):每個知識庫一個 collection,存 1024 維向量 +
doc_id(= Postgres 的 index_node_id)。
為什麼拆兩個?Postgres 擅長存文字與關聯、但不會做向量相似搜尋;Weaviate 專做向量搜尋、但不適合當內容真相來源。所以:Postgres 當「圖書館的書」,Weaviate 當「按語意排的索引卡」——查到卡片(doc_id)再回圖書館拿書(content)。
VECTOR_STORE 環境變數切換,支援 weaviate / qdrant / milvus / pgvector / chroma…。設 pgvector 就把向量塞進 Postgres 擴充、跟文字同一個庫(運維簡單、中小量夠);獨立向量庫(如 Weaviate)則在大規模、高並發下更能撐。同一套 RAG 邏輯,底層向量庫可換。
最重要的一課:「上下文」那條線
在 Dify 用 chatflow 做 RAG,結構是 開始 → 知識檢索 → LLM → 回覆。同一題「非營利幼兒園費用」,我親眼看到三個階段——差別只在一條線接了沒:
| 階段 | 答案 | 原因 |
|---|---|---|
| 上下文沒接、無約束 | 🚫「以中國大陸為例…保教費」 | 用腦內舊知識亂編 |
| 加 SYSTEM「禁止編造」 | ⚠️「文件裡查不到」 | 不編了,但上下文還空 |
| 上下文接知識檢索 result | ✅「每月 3,000 元」+ 出處 | LLM 拿到撈回的塊,照文件答 |
最容易漏的坑:知識檢索撈到了,但 LLM 節點的「上下文」欄位是空的 —— 撈回的塊躺在檢索節點的輸出裡,沒被交給 LLM。查後端就看得死死的:LLM 收到的 prompt 裡根本沒有那塊文字。把 LLM 節點的「上下文」設成「知識檢索 / result」,那條線才通,撈回的內容才會進 prompt。這條線,就是 RAG chatflow 的命脈。
-- 驗證:LLM 到底有沒有拿到撈回的內容?看它收到的 prompt
-- 沒接上下文時:prompt 裡找不到「3,000」→ 撈了等於沒撈
-- 接上後:那塊「每月 3,000元」進了 prompt → 才答得出來
-- 而被檢索命中的塊,hit_count 會累加(DB 有記)
機密文件:整條鏈都要本機
我故意在庫裡混了公司內部文件。這裡有個容易忽略的洩漏點:embedding 用本機 bge-m3,索引階段安全;但如果回答的聊天模型是雲端(如 Groq),檢索到的機密塊會被塞進 prompt 送上雲。所以對機密資料的鐵律是:embedding 和聊天模型「兩個都要本機」(bge-m3 + 本機 qwen),資料主權才完整——這正是「為什麼要本機 RAG」的實戰理由。附帶一提:一個知識庫別混太多不相關領域,否則檢索會互相干擾,真上線要「一領域一庫」。
延伸閱讀:Dify 自架實戰 #1:五道牆與後端架構、地端 Agentic RAG:斷網怎麼上線、真實手冊 RAG 一日實戰:15 個坑。
發佈留言