在企業級 RAG 系統中,光靠 語意檢索 常常還不夠。因為在真實業務場景下,文件不僅有「內容」,還有大量 結構化屬性(Metadata),例如:
這些元數據能成為 預過濾條件,在檢索階段就縮小範圍,大幅提升精準度。
使用者問「2024 年的財報」,若沒過濾,系統可能還會返回 2019、2020 的財報。
先過濾「財務部 + 2024」,再檢索,索引範圍立刻縮小。
不同角色只能看到允許的文件,必須在檢索前就過濾。
設計 Schema 時要兼顧 檢索效率 與 業務靈活性。
通常有兩種結合方式:
先用元數據過濾候選文件,再進行語意檢索。
-- 範例:先過濾再檢索
WHERE type = "法務文件"
AND year = 2024
AND access_level IN ("public", "internal")
→ Vector Search on filtered subset
優點:
先用語意檢索取 Top-K,再依 Metadata 過濾。
Vector Search → Top-100 candidates
→ Filter by metadata: department = "財務"
→ Final Top-10 results
優點:
企業常用「前置過濾」,因為可以直接減少 ANN 檢索範圍,效能更好。
按 Metadata(如部門、年份)建立分片索引,減少單次檢索範圍。
索引結構:
├─ 財務部_2024/ (財務部2024年文件)
├─ 法務部_2024/ (法務部2024年文件)
└─ 客服部_FAQ/ (客服FAQ文件)
常見過濾條件(例如「2024 財務報告」)可快取檢索結果。
針對常用的 Metadata 組合建立複合索引:
-- 複合索引範例
CREATE INDEX idx_dept_year_type
ON documents (department, year, document_type)
檢索法律條文時,必須過濾「國家 / 年份 / 條文類型」。
# 法務文件檢索範例
filters = {
"document_type": "法規",
"country": "台灣",
"year": {"gte": 2020},
"status": "有效"
}
不同客戶群組(VIP / 普通)使用不同 FAQ 範圍。
# 客服知識庫權限過濾
user_level = get_user_level(user_id)
filters = {
"document_type": "FAQ",
"access_level": {"in": ["public", user_level]}
}
依「專案代號 + 版本號」過濾,避免 LLM 拿到舊版本文件。
# 研發文件版本控制
filters = {
"project_code": "PROJ-2024-AI",
"version": {"gte": "v2.0"},
"status": "latest"
}
def get_accessible_filters(user_id, base_filters):
user_permissions = get_user_permissions(user_id)
# 根據用戶權限動態調整過濾條件
if "confidential" not in user_permissions:
base_filters["access_level"] = {"ne": "confidential"}
return base_filters
避免過濾過於嚴格而漏掉相關文件,建議:
過濾策略選擇:Pre-filtering 可能漏掉相關文件,Post-filtering 可能影響效能。如何找到最適合的平衡點?
元數據演進管理:當業務需求變化時,如何平滑地更新元數據 Schema 而不影響線上服務?