·14 min read·BASHCAT 技術團隊·ai-engineering

企業 RAG 知識庫建置指南:架構、切塊、混合搜尋、權限控管與評估

企業 RAG 知識庫從零建置的完整路線:先判斷需不需要 RAG,再拆解文件切塊、中文 embedding、混合搜尋與重排序、文件權限控管、RAGAS 評估,附 RRF 與 pgvector 程式範例和踩坑清單。

#RAG#知識庫#LLM#向量搜尋#混合搜尋#企業 AI

在我們做過的 RAG 專案裡,卡關的原因很少是模型不夠聰明,多半是檢索這一步拿錯了資料。模型拿到錯的段落,就會很有自信地把錯的答案講得頭頭是道;拿到對的段落,回答品質才有基礎可言。

我們幫金融科技客戶做過一套 企業 RAG 知識庫 ,最後平均回應時間壓在 3 秒內,在客戶自己的內部題庫評測中回答準確率為 92%(題庫與評分標準由客戶定義,僅供參考)。回頭看,真正花時間的地方幾乎都在模型之外:文件怎麼切、中文怎麼搜、權限怎麼擋、品質怎麼量。這篇把這些環節按順序攤開來講,附上可以直接拿去用的程式片段,和我們踩過的坑。

大量文件中只有少數段落被挑出來交給模型,這就是 RAG 檢索在做的事

先問一個問題:你真的需要 RAG 嗎?

RAG(Retrieval-Augmented Generation,檢索增強生成)的概念出自 Lewis 等人 2020 年在 NeurIPS 發表的 論文 :先從外部知識庫找出相關段落,再交給語言模型生成答案。它解決的是「模型沒讀過你公司的資料」和「資料會一直更新」這兩件事。

不過現在模型的 context window 已經很大,資料量小的時候,RAG 反而是多此一舉。Anthropic 在 Contextual Retrieval 這篇文章直接建議:知識庫小於 20 萬 token(大約 500 頁)時,可以把整份內容放進 prompt,搭配 prompt caching 降低成本與延遲,不必建檢索系統。

所以第一步先估資料量:

情境 建議做法
一份產品手冊、幾十頁規章,總量小於 20 萬 token 直接放進 prompt,加 prompt caching
上千份文件、每週都有更新 RAG
不同部門、不同職級只能看不同文件 RAG,而且一開始就要設計權限(後面細講)
問題多半是「整體趨勢、主要主題是什麼」這類綜觀型問題 考慮 GraphRAG(後面細講)

RAG 架構全貌:資料怎麼從文件變成答案

一套企業 RAG 可以拆成「離線建索引」和「線上回答」兩條流程:

階段 做什麼 常見工具
1. 收集與解析 從 SharePoint、Google Drive、Confluence、檔案伺服器抓文件,PDF/Word/投影片轉成乾淨文字,同時記下每份文件的權限 Unstructured、Azure Document Intelligence、自寫 parser
2. 切塊(chunking) 把長文件切成幾百 token 的段落,保留標題路徑等 metadata LangChain/LlamaIndex 的 splitter
3. 向量化(embedding) 每個段落轉成向量 BGE-M3、OpenAI、Cohere 等 embedding 模型
4. 建索引 向量索引+全文索引並存 Azure AI Search、pgvector、Qdrant、Elasticsearch
5. 檢索 使用者提問時,用關鍵字與向量各找一批候選 混合搜尋
6. 重排序(rerank) 用更精準的模型把候選重新排序,只留前幾名 Cross-encoder reranker
7. 生成與引用 把段落交給 LLM 回答,並標出來源文件 GPT、Claude、Gemini 等

在我們的專案裡,第 5、6 步對回答品質影響最大,第 1 步的權限設計則決定了這套系統能不能上線。下面依序講。

切塊:別迷信 overlap,也別塞太多段落

切塊(chunking)是最常被當成「設個參數就好」的步驟,偏偏影響很大。

2026 年 1 月一篇系統性比較切塊策略的 論文 (Bennani & Moslonka)在 Natural Questions 上做了端對端評估,結論有幾個很實用:

  • overlap 沒有可量測的幫助,只會增加索引成本。很多教學預設 10–20% overlap,其實可以先拿掉再驗證。
  • 句子切塊是最划算的做法:在論文測試的約 5k token 範圍內,表現和語意切塊(semantic chunking)差不多,成本低很多。
  • 餵給模型的 context 超過約 2.5k token 後品質開始下滑,作者稱為「context cliff」。

這篇論文用的是 SPLADE 檢索加 Mistral-8B,換成別的組合數字不一定照搬,但方向很清楚:不要以為塞越多段落給模型越好。

實務上我們會這樣做:

  • 先依文件結構切(標題、章節、條列),再在結構內按句子切到幾百 token。
  • 每個 chunk 都帶 metadata:來源檔名、章節標題路徑、更新日期、權限群組。標題路徑很重要,「第三章 > 退款 > 例外情況」這種上下文,光看段落本身是看不出來的。
  • 表格不要硬切成文字流。拆成「一列一段」並保留表頭,或另外存結構化資料,不然數字會和欄位名稱對不起來。

中文的坑:embedding 與斷詞

台灣企業的文件多半是繁體中文夾雜英文術語,這裡有兩個常被忽略的問題。

embedding 模型要支援多語。例如 BGE-M3 支援 100 多種語言、單段最長 8192 token、MIT 授權,可以自架;而且一個模型同時輸出稠密向量(dense)、稀疏詞彙權重(sparse)和多向量(multi-vector)三種表示,很適合拿來做混合搜尋。選模型時,用下面「建立評估集」那段準備的真實問題測一輪,比看排行榜可靠。

關鍵字搜尋要能正確斷詞。中文沒有空格,預設的分析器常常把整句當成一個詞,搜「退貨流程」可能完全搜不到「退貨的處理流程」。各家的處理方式:

  • Azure AI Search:欄位分析器設為 zh-Hant.microsoft 或 zh-Hant.lucene 。
  • PostgreSQL:內建全文搜尋不會切中文,要另外裝 pg_bigm(二元切詞)或中文斷詞擴充。
  • Elasticsearch/OpenSearch:裝 IK 或 smartcn 這類中文分析器。

混合搜尋+重排序:檢索品質的最大槓桿

關鍵字搜尋與向量搜尋兩路結果合併,再經過重排序只留下最相關的幾筆

純向量搜尋擅長「意思相近但用詞不同」的查詢,卻常漏掉精確字詞。微軟在 Azure AI Search 的混合搜尋文件 講得很直接:產品型號、專業術語、日期、人名這類查詢,關鍵字搜尋表現更好,因為它能抓到完全符合的字;而他們在真實資料與基準資料集上的測試顯示,混合搜尋加上語意重排序,相關性有明顯提升。

企業文件裡充滿料號、法規條號、專案代碼,所以我們的專案預設都用混合搜尋。兩路結果怎麼合併?最常用的是 RRF(Reciprocal Rank Fusion):每份文件的分數 = 它在各路結果中「1 ÷(k + 排名)」的總和。好處是不用把 BM25 分數和向量相似度換算到同一個尺度。下面是可以直接執行的 Python 版本:

from collections import defaultdict

def rrf(result_lists, k=60, top_n=50):
    """Reciprocal Rank Fusion:合併多路檢索結果,k=60 沿用 Cormack 等人 2009 年原始論文的設定"""
    scores = defaultdict(float)
    for results in result_lists:
        for rank, doc_id in enumerate(results, start=1):
            scores[doc_id] += 1.0 / (k + rank)
    return sorted(scores, key=scores.get, reverse=True)[:top_n]

bm25_hits = ["doc7", "doc2", "doc9", "doc4"]    # 關鍵字搜尋結果(依排名)
vector_hits = ["doc2", "doc5", "doc7", "doc1"]  # 向量搜尋結果(依排名)
print(rrf([bm25_hits, vector_hits]))
# ['doc2', 'doc7', 'doc5', 'doc9', 'doc4', 'doc1']

兩路都排得前面的 doc2、doc7 自然浮上來。合併後取前 50 筆左右,交給 reranker(cross-encoder,例如 bge-reranker 系列或雲端的 rerank API)重新打分,最後依 token 預算決定留幾段:每段 300–500 token 的話,3–5 段大約是 1k–2.5k token,剛好在前面那篇論文的 context cliff 以內,適合當起點;再用評估集測試往上加段數有沒有幫助。那個 2.5k 門檻是在特定模型上量到的,你的上限要自己測出來。

這套組合的效果有多大?Anthropic 在 Contextual Retrieval 實驗裡用「前 20 筆沒撈到正確段落的比例」當指標:

做法 檢索失敗率 相對降低
一般 embedding 5.7% -
Contextual Embeddings 3.7% 35%
Contextual Embeddings+Contextual BM25 2.9% 49%
+ 重排序 1.9% 67%

所謂 Contextual Retrieval,是在建索引時先讓 LLM 替每個 chunk 寫一兩句「這段在整份文件中講什麼」,再把這句話接在 chunk 前面一起做 embedding 和 BM25。用 prompt caching 的話,Anthropic 估算的一次性成本是每百萬 token 文件 1.02 美元(假設每份文件 8k token、每個 chunk 800 token、每段補 100 token 的說明),實際費用會隨文件長度與模型價格變動。這些數字是 Anthropic 自己的跨領域平均,換到你的資料要重新驗證,但「混合搜尋+重排序」帶來的提升方向,和微軟的結論一致。

權限控管:企業 RAG 最容易出事的地方

只有被授權的資料櫃會和使用者連線,其他文件在檢索階段就被擋下

這是 Demo 和正式上線之間最大的差距。向量資料庫本身不知道「現在是誰在問」,如果檢索時沒過濾權限,實習生問一句「今年的調薪幅度」,模型就可能引用人資的機密簡報。

OWASP 在 2025 年版 LLM 應用十大風險裡,把這類問題獨立成 LLM08:Vector and Embedding Weaknesses ,列出的風險包括:存取控制不足造成資料外洩、多租戶共用向量庫時的跨使用者洩漏、從 embedding 反推原文,以及資料投毒。官方建議的第一條防線,就是使用「具權限意識(permission-aware)的向量與 embedding 儲存」,並嚴格切分資料集。

落地時記住三個原則:

  1. 在檢索階段過濾,不要靠 prompt。在 prompt 裡寫「不要透露機密」沒有用,模型已經看到了。權限要在搜尋時就套上,未授權的段落根本不進 context。
  2. 過濾條件由伺服器端依登入身分產生,絕不接受前端傳來的群組參數。
  3. 權限要跟著來源系統同步。某人被移出群組,索引裡的權限沒更新,就是一個正在發生的洩漏。

以 PostgreSQL+pgvector 為例,每個 chunk 存一欄允許的群組,查詢時帶上群組條件並依距離排序(近似索引實際的執行順序見下方說明):

-- 索引:向量用 HNSW,群組陣列用 GIN
CREATE INDEX ON chunks USING hnsw (embedding vector_cosine_ops);
CREATE INDEX ON chunks USING gin (allowed_groups);

-- ef_search 預設 40,要取 50 筆需調高;pgvector 0.8.0 起支援迭代掃描,避免過濾後結果不足
SET hnsw.ef_search = 100;
SET hnsw.iterative_scan = relaxed_order;

SELECT id, source_file, content
FROM chunks
WHERE allowed_groups && $1::text[]       -- 使用者所屬群組,由伺服器端依登入身分帶入
ORDER BY embedding <=> $2::vector        -- 餘弦距離
LIMIT 50;

這裡有個細節:pgvector 的近似索引(HNSW、IVFFlat)是先掃索引、再套過濾條件,權限很分散時可能撈不到足夠的結果,所以要開啟 0.8.0 加入的 iterative scan。relaxed_order 的結果不保證嚴格依距離排序,需要嚴格順序時改用 strict_order,或在外層查詢再排序一次;反正後面還會經過 reranker,多數情況用 relaxed 即可。另外,迭代掃描有上限(hnsw.max_scan_tuples,預設 20,000),權限極度分散時仍可能不足 50 筆;上線前用 EXPLAIN 確認規劃器實際用的是 HNSW 還是 GIN 索引。用 Azure AI Search 的話,正式推出的做法是 security filters(以使用者或群組 ID 做字串比對的安全性篩選);直接用 Microsoft Entra 身分比對 ADLS Gen2 的 ACL/RBAC、SharePoint 權限與 Purview 敏感度標籤的原生功能,截至 2026 年 10 月都還在預覽,細節見 官方文件層級存取說明 。

怎麼知道 RAG 有沒有變好?建立評估集

沒有評估,每次調參數都是憑感覺。我們的經驗做法是先準備 50–100 題「真實使用者會問的問題+標準答案+應該引用的文件」,每次改切塊、換模型、調 top-k 都跑一輪。

指標可以用開源框架 Ragas 的四個核心指標,分數越高越好:

指標 量什麼 分數低代表
Context Precision 撈回來的段落中,相關的比例與排序 檢索雜訊太多
Context Recall 回答所需的資訊有沒有被撈到(需要標準答案) 檢索漏掉關鍵段落
Faithfulness 回答的每個說法是否都有段落支持 模型在「腦補」
Response Relevancy 回答是否切題 答非所問

這四個指標拆開看,就能分辨問題出在檢索還是生成,不會一律怪模型。另外要提醒,這些指標本身由 LLM 判讀,也會有誤差,關鍵題目仍要人工抽查。

進階選項:什麼時候用 GraphRAG?

一般 RAG 擅長「某條規定怎麼寫」這種精確問題,但遇到「這一年客訴的主要原因有哪些」這種要綜觀整個資料集的問題,只撈幾段文字是答不好的。

微軟研究院的 GraphRAG 論文 針對這類「全域理解」問題,先用 LLM 從文件抽出實體與關係建成知識圖譜,再分群寫摘要。在約百萬 token 的資料集上,它在回答的完整性與多樣性都明顯優於一般 RAG。代價是建索引時要大量呼叫 LLM,成本和時間都高很多。

我們的建議是:先把基本的混合搜尋+重排序做好,確認使用者真的大量在問綜觀型問題,再考慮 GraphRAG,不要一開始就上。

技術選型:用雲端服務還是自架?

方案 適合情境 優點 要注意
Azure AI Search 已在用 Microsoft 365/Azure 的企業 混合搜尋、語意重排序、繁中分析器都內建,權限可用 security filters 費用隨索引規模與重排序用量增加;Entra 原生 ACL 仍在預覽
PostgreSQL+pgvector 已有 Postgres、資料量中等、想自己掌控 向量、全文、權限過濾都在同一個資料庫,SQL 就能寫 中文全文搜尋要自己裝擴充,重排序要另外接
專用向量資料庫(Qdrant、Weaviate、Pinecone 等) 向量量體大、需要高吞吐 向量檢索效能與功能完整 權限資料要和來源系統同步,架構多一個元件

我們的經驗是:中小型專案從 pgvector 起步最快,資料、權限、應用都在同一個 Postgres 裡,維運簡單;已經全面使用 Microsoft 生態系的企業,直接用 Azure AI Search 能省下大量整合工作;向量量體大、對吞吐有要求時再考慮專用向量資料庫,我們的金融科技案例就是用 Pinecone。

踩坑清單

  • 掃描檔 PDF 沒做 OCR:解析出來是空白,知識庫等於少了一塊。上線前先統計每份文件抽出的文字量,抓出異常的檔案。
  • 同一份規章有好幾個版本:舊版和新版一起被撈到,模型會混著回答。建索引時就要標版本與生效日,檢索時優先新版。
  • 只測自己想得到的問題:開發者問的問題和第一線同事問的差很多。評估集一定要收真實提問。
  • 回答沒有引用來源:使用者無法驗證,就不敢用。每個回答都要附上原始文件連結和段落。
  • 一次塞 50 段給模型:成本變高,品質反而下降(還記得前面的 context cliff)。重排序後只留真正相關的。

常見問題

RAG 和微調(fine-tuning)差在哪?該選哪個? RAG 是在回答時查資料,適合會更新、需要引用來源的知識;微調是改變模型本身的行為與語氣,不適合用來塞大量會變動的事實。以企業知識庫問答來說,通常選 RAG;兩者也可以並用。

建一套企業 RAG 知識庫要多久? 資料來源單純、權限簡單的 POC 大約幾週可以做出來;要串多個資料來源、處理文件權限、建立評估集並上線,通常要以月計算。我們的金融科技案例從需求到上線約 6 個月。

資料可以不上雲嗎? 可以。embedding 可以用 BGE-M3 這類開源模型自架,向量庫用 pgvector 或 Qdrant 架在內網,生成模型也能選本地部署的開源模型,代價是要自己負責硬體與維運。

一定要用 LangChain 或 LlamaIndex 嗎? 不一定。框架能加快開發,我們的金融科技案例也用了 LangChain。重點是不論用不用框架,檢索、權限、評估這些核心邏輯都要自己看得懂、測得到,出問題時才追得到原因。

結語:先把檢索做對

在我們的經驗裡,企業 RAG 的成敗主要取決於模型之外的工程:文件解析、切塊、混合搜尋、重排序、權限、評估。這些沒做好,換再強的模型也救不了撈錯資料的檢索。

如果你正在評估導入企業知識庫,或手上的 RAG POC 卡在準確率、權限或效能,歡迎參考我們的 企業 RAG 知識庫案例 ,或直接透過 聯絡頁 、LINE @141clxra 跟我們聊聊需求。

參考資料

更多工作室筆記。