Dify 自架實戰 · 架構補充

Dify RAG 雙庫實戰架構:知識庫怎麼存、怎麼查

RAG 最適合配一張圖。這頁把 Dify 知識庫的真實架構畫清楚:它其實存「兩個庫」(Postgres 文字 + Weaviate 向量),建庫與查詢怎麼跨兩庫,以及 RAG 對話流程裡最容易漏、卻是命脈的那一條「上下文」線。全部照真實自架環境整理。

🗄️ 雙庫架構:文字一個庫、向量一個庫

flowchart TB
  subgraph BUILD["建庫(上傳當下,做一次)"]
    DOC["📄 文件
PDF / Word / Excel"] --> CH["切塊 chunk"] --> EM["bge-m3
算成向量"] end EM --> PG[("🗄️ Postgres
document_segments
文字 content + index_node_id")]:::pg EM --> WV[("🧭 Weaviate
1024 維向量 + doc_id")]:::wv subgraph QUERY["查詢(每次提問)"] Q["🙋 問題"] --> QE["bge-m3 算向量"] --> SR["找最近 top-k → doc_id"] end WV -.同一把 id.-> SR SR -->|"用 id 回撈文字"| PG PG -->|"content 當小抄"| LLM["🤖 LLM
照文件回答 + 附出處"]:::r classDef pg fill:#e5e9f0,stroke:#475569,color:#1e293b classDef wv fill:#fef3c7,stroke:#d97706,color:#78350f classDef r fill:#dcfce7,stroke:#16a34a,color:#14532d

Postgres 存真正的文字(內容真相來源)、Weaviate 存向量(語意搜尋),靠 index_node_id ↔ doc_id 對應。查到向量卡片,再回文字庫拿內容 —— 像「按語意排的索引卡」找到「圖書館的書」。

🔌 向量庫是可插拔的:pgvector vs 專用庫

pgvector(一個庫)專用向量庫(Weaviate / Qdrant / Milvus)
架構向量 + 文字同在 Postgres向量獨立一個服務
運維✅ 簡單,一個 DB 顧到底多一個服務要顧
規模 / 效能中小量夠用大量、高並發、ANN 進階功能強
切換方式VECTOR_STORE=pgvector / weaviate / qdrant…(一個環境變數)
適合單位內用、量可控多租戶、要極致檢索效能

同一套 RAG 邏輯,底層向量庫是可抽換的零件。這台 demo 用 Weaviate;要跟既有系統統一也可改成 pgvector(需重建索引)。

🎭 RAG 對話流程:同一題,三個答案

flowchart TB
  Q(["🙋 非營利幼兒園費用?"]):::q
  R["🔎 知識檢索
(TEST 知識庫)"]:::proc C{"LLM 的『上下文』
接了知識檢索嗎?"}:::dec A1["❌ 沒接 + 無約束
用舊知識亂編
『以中國大陸為例…』"]:::bad A2["⚠️ 加『禁止編造』但上下文空
『文件裡查不到』"]:::warn A3["✅ 上下文接 result
『每月 3,000 元』+ 出處"]:::good Q --> R --> C C -->|沒接| A1 C -->|接了但沒給內容| A2 C -->|接上 result| A3 classDef q fill:#dcfce7,stroke:#16a34a,color:#14532d classDef proc fill:#dbeafe,stroke:#2563eb,color:#17335e classDef dec fill:#ede9fe,stroke:#7c3aed,color:#4c1d95 classDef bad fill:#fdecea,stroke:#c0392b,color:#7f1d1d classDef warn fill:#fff3e0,stroke:#a85a00,color:#7c2d12 classDef good fill:#dcfce7,stroke:#16a34a,color:#14532d
命脈:Dify chatflow 的結構是 開始 → 知識檢索 → LLM → 回覆。最容易漏的坑是——知識檢索撈到了,但 LLM 節點的「上下文」欄位是空的,撈回的塊沒進 LLM 的 prompt。把 LLM 的「上下文」設成「知識檢索 / result」,那條線才通。沒接就「查不到」甚至亂編;接上才「照文件答 + 附出處」。

🧱 這台知識庫的真實組成

存哪存什麼
Postgres · datasets知識庫(名稱、索引方式 high_quality、embedding = bge-m3)
Postgres · documents每份文件(狀態、字數、切了幾塊)
Postgres · document_segments每一塊:content 文字 + position + tokens + index_node_id + hit_count
Weaviate · Vector_index_<dataset>每一塊的 1024 維向量 + doc_id(= index_node_id)+ text 副本

hit_count 就是「檢索次數」的來源——每塊被撈到幾次,DB 有記,是驗證「真的走了檢索」的鐵證。

一句話心法:RAG 不難,難在順序——先驗檢索(命中測試看分數),再接生成(上下文接知識檢索)。撈對 + 接上,才有「照文件答、還附出處」的可信 agent;機密文件則要 embedding 與聊天模型「兩個都本機」。

📚 回課綱總表 →