企業導入 RAG,真正困難的往往不是模型
企業 RAG 多租戶架構的核心,是建立可驗證的租戶隔離、權限控制與資料處理流程。模型能力決定回答上限,但資料邊界、稽核能力與營運可靠性,才決定系統能否進入正式環境。
當系統從概念驗證走向正式營運,企業必須回答幾個更務實的問題:不同客戶的資料如何安全隔離?大型文件如何避免拖慢前端?模型或前端載具更換時,是否需要重建整套系統?權限控制是否只依賴應用程式碼?
Headless 架構將後端定位為可重複使用的資料與 AI 服務。不同前端透過標準 API 使用相同的知識庫、權限與檢索能力,使企業能在不重建後端的情況下擴充新的使用介面。
Headless RAG 的整體架構是什麼?
Headless RAG 是以統一 API 連接多種前端、租戶驗證、企業資料與模型服務的架構。它把前端體驗與後端知識能力分離,但仍由共用治理層控制身分、權限、稽核與資料範圍。
PROCESS MAP
Headless RAG 多租戶整體架構
多種前端透過統一 API 進入身分驗證與租戶治理層,再由 RLS 與混合檢索連接企業知識及模型服務。
- 01STEP
前端載具
企業網站、App、LINE 機器人與企業內部系統
- 02STEP
Headless API
JWT/API Key 驗證、tenant_id、RBAC 與稽核
- 03STEP
資料與檢索
物件儲存、Queue、PostgreSQL RLS、pgvector 與混合檢索
- 04STEP
生成與回應
LLM 生成、引用來源、Request ID 與 SSE 串流
多租戶資料架構有哪些選擇?
多租戶架構主要分為 Shared Schema、Schema-per-tenant 與 Database-per-tenant。企業應依資料敏感度、客製化程度、租戶規模、備份需求與營運成本選擇隔離層級。
DECISION TABLE
多租戶資料架構比較
隔離強度越高,通常也會增加升級、維運與基礎設施成本。
| 評估項目 | Shared Schema + RLS | Schema-per-tenant | Database-per-tenant |
|---|---|---|---|
| 實作方式 | 共用資料表,以 tenant_id 區分 | 同一資料庫,每租戶一個 Schema | 每租戶一個獨立資料庫 |
| 隔離程度 | 中至高,取決於 RLS | 高 | 最高 |
| 統一升級 | 最容易 | 租戶增加後較複雜 | 最複雜 |
| 基礎設施成本 | 低 | 中 | 高 |
| 大量租戶擴展 | 最適合 | 中等 | 成本較高 |
| 單租戶備份還原 | 較複雜 | 中等 | 最清楚 |
| 適用情境 | SaaS、SMB、標準化服務 | 中大型企業、欄位客製化 | 高法遵、資料主權、大型企業 |
如何選擇隔離模式?
DECISION TABLE
隔離模式選擇指南
先從商業與法遵條件判斷,再決定資料隔離層級。
| 企業最重視的條件 | 優先評估方案 | 主要原因 |
|---|---|---|
| 快速推出 SaaS MVP | Shared Schema + RLS | 結構統一、成本較低、容易擴展 |
| 支援大量 SMB | Shared Schema + RLS | 避免每個租戶建立獨立基礎設施 |
| 每家客戶有不同欄位 | Schema-per-tenant | 保留較高的結構彈性 |
| 獨立備份與還原 | Database-per-tenant | 資料生命週期邊界最清楚 |
| 跨國資料落地 | 獨立資料庫或獨立部署 | 較容易配合區域資料主權政策 |
PostgreSQL RLS 如何建立租戶隔離?
PostgreSQL Row-Level Security 可依目前資料庫 Session 的租戶條件,自動限制可讀寫的資料列。即使應用程式漏寫 tenant_id 過濾條件,資料庫仍能提供額外防線。
1CREATE EXTENSION IF NOT EXISTS vector;23CREATE TABLE knowledge_chunks (4 id UUID PRIMARY KEY DEFAULT gen_random_uuid(),5 tenant_id UUID NOT NULL,6 document_id UUID NOT NULL,7 content TEXT NOT NULL,8 embedding vector(1536),9 created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()10);1112ALTER TABLE knowledge_chunks ENABLE ROW LEVEL SECURITY;13ALTER TABLE knowledge_chunks FORCE ROW LEVEL SECURITY;1415CREATE POLICY tenant_select_policy16ON knowledge_chunks FOR SELECT17USING (18 tenant_id = NULLIF(19 current_setting('app.current_tenant_id', true), ''20 )::uuid21);2223CREATE POLICY tenant_insert_policy24ON knowledge_chunks FOR INSERT25WITH CHECK (26 tenant_id = NULLIF(27 current_setting('app.current_tenant_id', true), ''28 )::uuid29);
後端完成身分驗證後,應在同一筆 Transaction 中執行 SET LOCAL app.current_tenant_id = '租戶 UUID';。SET LOCAL 的作用範圍只存在於目前 Transaction,可降低連線池重複使用時殘留租戶設定的風險。
RLS 能防止什麼?不能取代什麼?
DECISION TABLE
PostgreSQL RLS 的能力邊界
RLS 提供資料列級防線,但它依賴正確的 Transaction 範圍與資料庫角色設計。
| 控制項目 | RLS 可處理 | 仍需其他機制 |
|---|---|---|
| 資料列存取限制 | 可以 | Policy 測試與最小權限 |
| 應用程式漏寫 tenant_id | 可降低風險 | 每筆請求在同一 Transaction 設定 SET LOCAL |
| 連線池與 Session 變數 | 不可以自動處理 | 明確 Transaction、SET LOCAL 與實際 pool 模式測試 |
| BYPASSRLS/superuser | 不可以 | Runtime role 必須為 NOSUPERUSER、NOBYPASSRLS |
| 表擁有者預設繞過 | 不一定 | Runtime role 非 owner;必要時 FORCE ROW LEVEL SECURITY |
| JWT 真偽驗證 | 不可以 | API Gateway/後端驗證 |
| 檔案儲存隔離 | 不可以 | Bucket Path 與 Storage Policy |
| Queue 工作隔離 | 不可以 | Job Payload 與 Worker 權限 |
| Cache Key 隔離 | 不可以 | 租戶化 Cache Key |
| LLM Prompt 外洩 | 不可以 | Prompt 組裝與輸出治理 |
RLS 上線時,連線池與角色權限要如何避免失效?
RLS Policy 不會自行建立可信任的租戶範圍。每個請求都必須在同一筆資料庫 Transaction 中設定 tenant_id,並以不具繞過權限的 runtime role 執行後續讀寫與檢索。
1BEGIN;2SET LOCAL app.current_tenant_id = 'tenant-uuid';34-- 所有 tenant-scoped 讀寫與向量檢索都在同一筆 Transaction 中5SELECT id, content6FROM knowledge_chunks7ORDER BY embedding <=> :query_embedding8LIMIT 8;910COMMIT;
SET LOCAL 僅在目前 Transaction 有效;在 Transaction 外執行會產生警告且不生效。因此不能用跨請求的 session SET 取代這個界線,也不能把設定 tenant_id 與實際查詢拆到不同的 Transaction。
PgBouncer 的 transaction pooling 並非必然不安全,但應用程式必須以明確 Transaction 包住 SET LOCAL 與所有查詢。statement pooling 禁止多敘述 Transaction,不能承載此模式;驗證時必須以正式環境相同的 pool mode 進行跨租戶負向測試。
superuser 與具有 BYPASSRLS 的角色會繞過 RLS;表擁有者預設也會繞過,除非啟用 FORCE ROW LEVEL SECURITY。實務上應讓 application runtime 使用非 owner、NOSUPERUSER、NOBYPASSRLS 的獨立角色,並僅授與必要的資料表權限。
Headless RAG API 應如何設計?
Headless API 應保持無狀態,並由伺服器根據可信任憑證解析租戶與權限。tenant_id 不應由前端自行指定或覆寫。
文件上傳 API
1POST /api/v1/documents2Authorization: Bearer <access_token>3Content-Type: multipart/form-data
1{2 "document_id": "d3b07384-d113-4956-a5cc-9c60012443d3",3 "status": "processing",4 "message": "文件已排入解析與索引流程"5}
對話與檢索 API
1POST /api/v1/chat/completions2Authorization: Bearer <access_token>3Content-Type: application/json
1{2 "messages": [3 {4 "role": "user",5 "content": "公司的特休制度如何計算?"6 }7 ],8 "stream": true9}
企業應用不應只回傳模型答案,也應提供引用文件、文件版本、更新時間、Request ID,以及找不到依據或權限不足時的明確狀態。
文件如何進入 RAG 知識庫?
文件建立流程應採非同步設計,避免解析、OCR、切片與向量化占用原始 HTTP Request。
PROCESS MAP
知識庫文件建立流程
上傳請求與耗時的解析、切片及向量化工作解耦,避免前端等待。
- 01STEP
上傳與驗證
檢查格式、大小、身分、tenant_id 與權限。
- 02STEP
安全儲存與排程
原始文件寫入租戶隔離儲存,工作送入 Queue。
- 03STEP
解析與切片
Worker 執行 OCR、版面解析,依文件結構建立可追溯片段。
- 04STEP
向量化
呼叫 Embedding 服務,保留模型版本與來源 Metadata。
- 05STEP
RLS 安全寫入
設定租戶 Session,寫入文字、向量並更新處理狀態。
文件切片不能只設定每段500字
DECISION TABLE
不同文件類型的切片策略
切片應沿用文件原有結構,並保存可追溯的版本與來源資訊。
| 文件類型 | 建議切片依據 | 必須保留的 Metadata |
|---|---|---|
| FAQ | 一組問題與答案 | 類別、產品、版本 |
| 規章制度 | 條、項、款及標題層級 | 生效日、版本、權責部門 |
| 合約 | 條款與附件結構 | 版本、當事人、有效期間 |
| 產品手冊 | 章節、功能與操作步驟 | 型號、軟體版本、頁碼 |
| 會議紀錄 | 議題、決議與待辦 | 日期、出席者、負責人 |
Embedding 模型更換時,向量維度要如何演進?
vector(1536) 是固定維度的資料契約,不是可任意替換模型的預設值。若新版模型輸出不同維度,現有欄位與其近似索引無法直接相容;只記錄 model name 或 version 並不足以完成遷移。
DECISION TABLE
向量維度與模型遷移策略
模型版本、向量維度、索引與查詢切換必須一起設計。
| 策略 | 適用情境 | 必要控制 |
|---|---|---|
| 新版 embeddings table | 維度或模型語意空間改變 | 平行寫入、重新向量化、建立新版索引後再切換讀取 |
| 新版 vector 欄位 | 同一 chunk 表需要短期雙軌 | 新舊欄位各自維護維度、索引與回滾時間窗 |
| 未限制維度的 vector 欄位 | 多模型長期共存 | 每個維度以 model filter 搭配 partial/expression index;不可混用比較 |
| 直接覆寫既有欄位 | 沒有舊版查詢或可接受停機 | 先完成全量 re-embedding、索引重建與回滾備份 |
1-- 範例:新版模型輸出 1024 維,採獨立的 v2 embeddings table2CREATE TABLE knowledge_chunk_embeddings_v2 (3 id UUID PRIMARY KEY DEFAULT gen_random_uuid(),4 tenant_id UUID NOT NULL,5 chunk_id UUID NOT NULL,6 embedding_model TEXT NOT NULL,7 embedding vector(1024) NOT NULL,8 created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()9);1011CREATE INDEX CONCURRENTLY knowledge_chunk_embeddings_v2_hnsw12ON knowledge_chunk_embeddings_v213USING hnsw (embedding vector_cosine_ops);
使用者提問時,RAG 如何完成檢索?
一次完整查詢會經過身分驗證、租戶限制、混合檢索、內容排序、模型生成與引用回傳。
PROCESS MAP
使用者提問與 RAG 檢索流程
每次查詢都先確立身分與租戶邊界,再進行檢索、生成與稽核。
- 01STEP
驗證請求
解析 Token 中的 tenant_id、user_id 與 scope。
- 02STEP
限制資料範圍
Transaction 內設定租戶 Session,由 PostgreSQL RLS 隔離。
- 03STEP
混合檢索與排序
結合向量、關鍵字、Metadata Filter 與 Reranking。
- 04STEP
組裝與生成
合併系統規則、企業知識與問題後交由 LLM 生成。
- 05STEP
串流與稽核
透過 SSE 回傳答案和引用,記錄模型、延遲與 Request ID。
為什麼繁體中文企業知識庫適合混合檢索?
繁體中文企業資料同時包含語意、專有名詞、型號、法規條號與精確數字,因此通常比純向量搜尋更需要混合檢索。
DECISION TABLE
企業知識檢索能力比較
混合檢索同時處理語意相近與必須精準命中的企業詞彙。
| 能力 | 純向量搜尋 | 關鍵字搜尋 | 混合檢索 |
|---|---|---|---|
| 理解語意近似 | 強 | 弱至中 | 強 |
| 產品型號 | 可能不穩定 | 強 | 強 |
| 法規條號 | 可能不穩定 | 強 | 強 |
| 同義詞 | 強 | 需建立字典 | 強 |
| 精確數字 | 較弱 | 強 | 強 |
| Metadata 權限 | 可搭配 | 可搭配 | 必須搭配 |
大量刪除與租戶下線後,如何維護向量索引?
完整刪除租戶資料是合規與資料生命週期的必要能力,但大量刪除也會改變向量索引的工作負載。特別是 HNSW,在高頻刪除後應把索引大小、查詢延遲、召回率與 VACUUM 時間納入營運監控,而不是只確認資料列已刪除。
DECISION TABLE
向量索引維運檢核
大量刪除、模型遷移與高頻更新都應有可排程的索引維運流程。
| 事件或訊號 | 維運動作 | 驗證指標 |
|---|---|---|
| 租戶下線或大量刪除 | 分批刪除並安排索引與統計資訊維護 | table/index size、刪除完成率、查詢延遲 |
| HNSW VACUUM 時間拉長 | 先 REINDEX INDEX CONCURRENTLY,再 VACUUM (ANALYZE) | 維護窗口、磁碟餘裕、寫入影響 |
| 召回率或延遲惡化 | 以精確搜尋抽樣比對近似搜尋 | Recall、p95 latency、hnsw.ef_search 或 ivfflat.probes |
| 高頻增刪的租戶 | 評估分區或獨立 table/index | 熱租戶對其他租戶的召回與速度影響 |
1-- 依維護窗口與容量計畫執行;先重建 HNSW,再清理 dead tuples2REINDEX INDEX CONCURRENTLY knowledge_chunks_embedding_hnsw;3VACUUM (ANALYZE) knowledge_chunks;
企業 RAG 上線前應檢查什麼?
企業不能只用 Demo 回答看起來合理作為上線標準。至少應完成以下檢查:
常見問題 FAQ
1. 什麼是企業 RAG 多租戶架構?
企業 RAG 多租戶架構,是讓多家企業共用同一套 RAG 應用,同時隔離各自文件、向量、權限與查詢結果的系統設計。隔離範圍應涵蓋資料庫、物件儲存、Queue、快取、日誌與模型輸入。
2. PostgreSQL 適合建立 RAG 應用嗎?
PostgreSQL 適合許多中小型至中大型 RAG 應用,因為它能同時管理結構化資料、Metadata、全文搜尋、交易一致性與 pgvector。是否需要專用向量資料庫,仍應依向量規模、查詢延遲與營運複雜度評估。
3. PostgreSQL RLS 是什麼?
PostgreSQL RLS 是資料列級安全性機制,可依目前資料庫 Transaction 內的租戶條件限制可讀寫資料列。它能降低應用程式漏寫租戶過濾條件的風險,但必須搭配明確 Transaction、最小權限 runtime role 與連線池模式測試,不能單靠 Policy 視為完整隔離。
4. Shared Schema 會造成資料外洩嗎?
Shared Schema 本身不必然造成資料外洩。主要風險來自錯誤的權限設定、過高的資料庫角色、未設定租戶範圍或缺乏負向測試。RLS、最小權限與跨租戶測試可降低風險。
5. 什麼情況不適合使用 Shared Schema?
當客戶需要獨立備份、區域資料落地、不同 Schema、高度客製化或嚴格法遵時,應評估 Schema-per-tenant、Database-per-tenant 或完全獨立部署。
6. 為什麼文件向量化需要非同步處理?
文件解析、OCR、切片與 Embedding 可能需要數秒至數分鐘。採用 Queue 與背景 Worker,可避免 API 逾時,也更容易處理重試、失敗復原及狀態追蹤。
7. RAG 文件應該切成多大?
沒有適用所有文件的固定切片大小。切片應依標題層級、段落語意、條款結構及實際問題設計,再透過召回率與答案正確率測試調整。
8. 什麼是混合檢索?
混合檢索結合向量搜尋、關鍵字搜尋、Metadata Filter 與 Reranking,同時處理語意問題與產品型號、法規名稱、條號及精確數值。
9. RAG 可以完全避免 AI 幻覺嗎?
不可以。RAG 能提供較可靠的企業知識依據,但仍可能受到檢索失敗、文件過期、Prompt 設計與模型生成錯誤影響。正式系統應提供引用來源、拒答條件與人工覆核機制。
10. Headless RAG 的商業價值是什麼?
Headless RAG 將知識檢索與生成能力轉成標準 API,讓網站、App、通訊機器人與內部系統共用相同的資料、權限與治理機制。
11. Embedding 模型更換後需要重新向量化嗎?
通常需要。不同 Embedding 模型可能同時改變語意空間與向量維度;固定維度欄位例如 vector(1536) 無法直接寫入不同維度的向量。除了記錄模型名稱與版本,還應規劃新版欄位或新版 embeddings table、平行索引、重新向量化及讀取切換。
12. 如何判斷企業 RAG 可以正式上線?
至少應完成租戶隔離、連線池 Transaction 範圍、BYPASSRLS/owner 權限、文件版本、真實問題集、引用正確率、拒答、效能、向量維度遷移與大量刪除後索引維運測試,不能只依 Demo 的回答觀感判斷。
結論:架構決策不是選出唯一技術答案
對多數 SaaS 型 RAG 產品而言,Headless API、Shared Schema、PostgreSQL RLS、pgvector 與非同步工作流程,可以形成具成本效率的起始架構。但當企業具有資料主權、獨立備份、客製 Schema、區域部署或高法遵需求時,系統仍可能需要升級隔離層級。
企業 RAG 從技術展示走向商業產品,關鍵不只是模型回答得多流暢,而是整套系統能否安全隔離、穩定營運、持續演進,並為每一個答案提供可信任的資料依據。