標籤: 多租戶權限

  • 實戰 Agentic RAG 與 Hybrid Search

    實戰 Agentic RAG 與 Hybrid Search

    📌 本文重點

    • 單一檢索策略讓 RAG 在真實場景很容易翻車
    • Hybrid Search 能互補向量與關鍵字的盲點
    • 讓 Agent 負責檢索策略與多輪重試能顯著提升穩定度
    • 不換模型也能透過 eval、Hybrid 與權限控管大幅升級 RAG

    在實際專案裡,多數 RAG 翻車不是因為模型不夠聰明,而是檢索策略太單一:只用向量會被專有名詞和代碼玩死,只用關鍵字又抓不到語義相近的長文件內容。Agentic RAG + Hybrid Search 的組合,重點就是讓「檢索」變成可調度、可重試、可觀測的一級公民,而不是一個寫死的 search(query) 函式。


    重點說明

    1. 為什麼單一檢索在真實專案會翻車?

    常見四種翻車場景:

    1. 長文件 / 手冊
    2. 只用向量:整份手冊被切成很多 chunk,語義太接近,top-k 都很像,但真正要的那一段不一定排前面。
    3. 只用 BM25:查詢句子太口語,關鍵字重疊度不高,直接 miss。

    4. 專有名詞 / 法規條文 / 內部代號

    5. 向量模型常常把 DS-104DS-140 當成類似,專案實際上兩者完全不同。
    6. 法規編號、API 名稱、Ticket ID 等,關鍵字檢索反而更穩

    7. 程式碼、表格、錯誤訊息

    8. 向量對縮排、符號、stack trace 的敏感度很差。
    9. Log ID 或錯誤碼這類「硬字串」,BM25/關鍵字幾乎是必要條件

    10. 跨語言 / 口語查詢

    11. 使用者用自然語言描述問題,文件是正式用語或英文,公司內還混雜縮寫。
    12. 需要先用 LLM 做 query 改寫,再讓向量與 BM25 各自發揮。

    Hybrid Search(向量 + BM25) 的實際好處:

    • 可以 補各自的盲點:專有名詞用 BM25 鎖定,模糊描述用向量補齊。
    • 可以針對不同類型文件設定 權重策略(例如法規 > 內部 wiki > Slack 摘要)。
    • 可以後面用 rerank 模型 做第二次排序,穩定提升回答可靠度。

    💡 關鍵: 單一檢索在長文件與專有名詞場景很容易漏抓關鍵內容,Hybrid Search 能同時顧到語義相似與精確字串匹配,明顯降低 RAG 翻車率。


    2. 讓 Agent 負責檢索策略,而不是把檢索寫死

    典型 Agentic RAG 設計:

    • 一個 Orchestrator Agent(對話主控)
    • 多個 retriever 工具keyword_retrievervector_retrieverhybrid_retrieverlegal_retriever

    Agent 的工作不是「自己產生答案」,而是先判斷:

    1. 要用哪種檢索策略?
    2. 查錯誤碼或 ticket:優先 關鍵字 → 再向量精抽
    3. 問概念解釋:優先 向量 → 再用 BM25 找原始定義
    4. 法規/權威階層:改用 分層 retriever(例如每一層級至少取 1–2 筆)

    5. 要不要改寫 Query?

    6. 第一輪命中文件相關度低時,讓 Agent 自動:

      • 摘出關鍵詞
      • 加上同義詞 / 全名(例如:DSData Steward
      • 限縮 domain(例如:限定 product=core-banking
    7. 多輪重試與合併結果

    8. 第一輪檢索後如果信心不足(例如 top-3 相似度都 < 0.7),
    9. Agent 改寫 query 或更換 retriever,再抓一次,最後合併去重後送入 LLM。

    這樣做的實際好處:

    • 檢索策略可迭代:只要調整工具 / prompt,不必重寫服務架構。
    • 容易在線上 A/B:只換掉 Orchestrator 的 prompt 或 routing 邏輯即可。
    • 可以針對不同客戶 / 部門掛不同的工具組合。

    一個可落地的組合:

    • LLM:OpenAIgpt-4.1)、Anthropicclaude-3.7)皆可
    • 檢索:
    • Elasticsearch:BM25 + dense vector + hybrid score
    • Weaviate / Qdrant:向量 + keyword filter

    簡化架構:

    User → Orchestrator Agent → (tool calls) →
      - keyword_retriever (Elasticsearch BM25)
      - vector_retriever  (Weaviate / ES dense vector)
      - hybrid_retriever  (ES rank_feature / script_score)
    → merge + dedup + rerank → LLM answer
    

    實作範例

    1. Orchestrator Agent Prompt(決定使用哪個 retriever)

    假設用 OpenAI Assistants API 或自行封裝 tools:

    系統指示(Orchestrator):
    你是一個檢索協調代理,負責從多種檢索器取得最相關的企業知識。
    
    - 若使用者詢問:
      - 錯誤碼、ticket ID、法規條號、API 名稱 → 優先使用 **keyword_retriever**。
      - 抽象概念、最佳實踐、流程說明 → 優先使用 **vector_retriever**。
      - 法律 / 合規問題,且需多層級來源 → 使用 **legal_hybrid_retriever**。
    
    流程:
    1. 先決定要呼叫哪些工具(可以多個)。
    2. 若第一輪檢索結果的「來源數量 < 3」或「相關度評估偏低」,
       - 自行改寫查詢(更精簡、加入關鍵字),再重試一次。
    3. 最終將所有檢索結果去重、排序,回傳給後續回答模型。
    禁止自行編造公司內部資料,所有答案必須可追溯到文件片段。
    

    索引 mapping:

    PUT knowledge_base
    {
      "mappings": {
        "properties": {
          "content": { "type": "text" },
          "content_vec": { "type": "dense_vector", "dims": 1536, "index": true },
          "source_type": { "type": "keyword" },   
          "tenant_id": { "type": "keyword" }
        }
      }
    }
    

    簡化版 hybrid 查詢(BM25 + 向量):

    POST knowledge_base/_search
    {
      "size": 20,
      "query": {
        "script_score": {
          "query": {
            "bool": {
              "must": [
                {"match": {"content": "GDPR data retention"}},
                {"term": {"tenant_id": "acme_corp"}}
              ]
            }
          },
          "script": {
            "source": "0.6 * _score + 0.4 * cosineSimilarity(params.q_vec, 'content_vec')",
            "params": {"q_vec": [/* query embedding */]}
          }
        }
      }
    }
    

    關鍵點:

    • BM25 與向量權重(例子中 0.6 / 0.4)要透過線上 A/B 或離線 eval 調整。
    • tenant_id filter 做多租戶權限隔離,非常重要。

    💡 關鍵: 在同一個查詢裡用 script score 同時結合 BM25 分數與 cosine similarity,能控制兩者權重,調整出最適合自己資料分佈的 Hybrid 策略。


    3. Chunking 與 max context 的工程細節

    基本原則:

    • 語義切分(semantic splitting)+ 適度 overlap 為主,而不是死切 512 tokens
    • 避免 chunk 過長導致:
    • 向量語義太混濁,top-k 噪音變高。
    • LLM context 塞滿 retrieval 噪音,回答變模糊。

    實作骨架(pseudo-code):

    from semantic_splitter import split_semantic
    
    def chunk_doc(text: str):
        sections = split_semantic(text, max_chars=1200)
        chunks = []
        overlap = 150  # 字元級 overlap
        for sec in sections:
            if len(sec) <= 1200:
                chunks.append(sec)
            else:
                # 針對長 section 再做 sliding window
                for i in range(0, len(sec), 1200 - overlap):
                    chunks.append(sec[i:i+1200])
        return chunks
    

    max context tokens 的關係:

    • 假設 LLM context 32k,系統 prompt + 對話占 4k,其實留給 RAG 的只有約 28k
    • 若每個 chunk 約 400 tokens,你實際能塞 約 50–60 個 chunk 就爆,但通常 8–16 個 chunk 就夠,更多只會拉高成本與噪音。

    rerank 與去重

    • 先取寬一點的 top_k(例如 30–50),再用輕量 rerank(如 bge-reranker)縮到 8–12 個。
    • 去重邏輯可以用:same doc_id + 高度相似 直接只留一個,減少重複內容浪費 context。

    💡 關鍵: 雖然 context 可能有 32k tokens,但實務上只保留約 8–16 個高質量 chunk,通常就能兼顧成本與效果,塞太多反而害答題品質下滑。


    建議與注意事項

    1. 不要只做 embedding,不做 eval

    常見錯誤流程:

    1. 把全部文件 embed → 塞進向量庫 → 上線。
    2. 發現回答怪怪的 → 開始懷疑模型。

    比較健康的流程:

    1. 先準備一組 標記好的 QA/Eval 集10–50 題也好)。
    2. 對同一組問題,分別跑:
    3. 純 BM25
    4. 純向量
    5. Hybrid + 不同權重
    6. 用簡單指標(hit@k、人工評分)挑一個 baseline,再上線 A/B。

    2. 向量庫維護:重建 / 追加 / 版本化

    • Embedding 模型版本變更 時:
    • 盡量用新 index 重建(kb_v2),舊版保留一段時間做對照。
    • 不要在同一個 index 裡混不同 embedding 模型的向量。
    • 大量文件更新策略:
    • 批次追加新文檔時,要記錄 批次 ID / 資料版本,方便 rollback。
    • 下線文件要標記 is_active=false 或直接 soft delete,避免回答引用過期政策。

    3. 多租戶與權限過濾

    • 在 Elasticsearch / Weaviate 中務必存:tenant_idvisibilityrole 等欄位。
    • 檢索 query 層一定要加:
    "filter": [
      {"term": {"tenant_id": "${current_tenant}"}},
      {"terms": {"visibility": ["public", "internal"]}}
    ]
    
    • 不要指望 LLM 自己遵守權限,權限控制一定要在檢索階段完成。

    4. 線上評測與 A/B 驗證

    簡易做法:

    1. 選一組真實高頻 query(客服 ticket、搜尋 log)。
    2. 設計兩條路線:
    3. A:純向量 RAG
    4. B:Agentic RAG + Hybrid Search
    5. 隨機分流流量,收集:
    6. 使用者是否重問 / 追問率
    7. 是否需要人工接手
    8. CSR / domain expert 的 1–5 分主觀評分

    通常在企業知識庫場景,只要加上 Hybrid Search + Agent 重試,就能看到 10–30% 的 query 成功率提升,而且失誤類型會明顯變少(比較少「答錯法規條」、「引用過期政策」)。


    總結:如果你現在的 RAG 還是「單一向量庫 + top-k 塞給 LLM」,要提升穩定性,不一定要換更大的模型,先把 Hybrid Search 與 Agentic 檢索策略補上,通常是成本最低、效果最直接的升級路線。


    🚀 你現在可以做的事

    • 從現有專案中抽出 10–50 則真實 query,分別用純 BM25、純向量與 Hybrid 跑一次,記錄 hit@k 與人工評分
    • 在現有 RAG 服務前面加一個簡單 Orchestrator,把關鍵字與向量檢索拆成兩個 tool,用 prompt 控制選用策略
    • 在搜尋層加入 tenant_idvisibility 欄位與 filter,先確保權限過濾正確,再進一步調整 Hybrid 權重與 rerank 策略