Skip to content

CRAG:檢索失敗時,自動放寬條件重試

2026年3月12日 1 分鐘
TL;DR 過濾條件太嚴格導致零結果?CRAG 自動放寬過濾條件重試,比讓 LLM 用通用知識瞎猜好多了。

RAG 系統的一個靜默失敗模式:過濾條件過嚴,沒有候選文件通過,但 pipeline 繼續跑,LLM 只能用通用知識回答

使用者問「龍洞有沒有 5.14 的路線」,系統正確提取了 crag_id = longtunggrade_numeric ≥ 140,但龍洞根本沒有這個難度的路線,搜尋零結果。如果系統直接把空 context 送給 LLM,有兩種糟糕的結果:

  1. LLM 誠實說「沒有相關資料」→ 正確但體驗差(其實應該說龍洞沒有 5.14)
  2. LLM 用通用知識幻覺出一個回答 → 不準確

CRAG(Corrective RAG)的解法:檢測到零結果時,自動放寬過濾條件重試搜尋

放寬策略

過濾條件有輕重之分。位置過濾(岩場、地區)通常是使用者的核心需求,不能隨便移除;但難度過濾、類型過濾有時是副條件,放寬它們更合理。

放寬的順序:

原始過濾:{ crag_id: 'longtung', grade_numeric: { gte: 140 }, route_type: 'sport' }
    ↓ 零結果
Step 1:移除 grade_numeric 過濾
    { crag_id: 'longtung', route_type: 'sport' }
    ↓ 仍然零結果
Step 2:移除 route_type 過濾
    { crag_id: 'longtung' }
    ↓ 有結果 → 繼續

位置過濾(crag_idarea_idregion)保留到最後,因為使用者問「龍洞」就是要龍洞的資訊,不能因為零結果就去找其他岩場的資料。

實作細節

async function hybridSearchWithCRAG(ctx: PipelineContext): Promise<SearchResult[]> {
  let filter = buildFilter(ctx);
  let results = await hybridSearch(ctx.queryVector, filter);

  // 零結果且有可放寬的條件
  if (results.length === 0 && ctx.cragRetryCount < 1) {
    ctx.cragRetryCount++;

    // 移除難度過濾,保留位置
    const relaxedFilter = removeGradeFilter(filter);
    results = await hybridSearch(ctx.queryVector, relaxedFilter);

    // 記錄到 trace
    ctx.trace.retrieval.crag_triggered = true;
    ctx.trace.retrieval.relaxed_filter = relaxedFilter;
  }

  return results;
}

cragRetryCount < 1 確保最多重試一次。不設上限的話,理論上可以一直放寬到無過濾,但這可能帶回完全不相關的結果,反而更糟。

與 Agentic RAG 的差異

CRAG 是規則型的修正,在 pipeline 內自動執行,不需要 LLM 決策。Agentic RAG 是 LLM 主動評估是否要重新檢索並改寫查詢。兩者的定位不同:

CRAGAgentic RAG
觸發條件零結果LLM 評估 context 不足
決策主體規則LLM
適用場景過濾太嚴需要多跳推理
延遲成本低(多一次搜尋)高(多次 LLM 呼叫)

CRAG 解決的是「根本沒東西」的問題,Agentic RAG 解決的是「有東西但不夠好」的問題。

為什麼是放寬而不是擴大範圍

另一個思路是「沒結果就去外部知識庫搜尋(如 Wikipedia)」。CRAG 原始論文也有這個設計(Web Search fallback)。但在攀岩社群的場景,使用者問的問題通常是關於特定岩場和路線,外部搜尋引入的通用攀岩知識反而可能誤導,不如誠實說「這個岩場沒有這個難度的路線」,輔以相近的資訊。

放寬過濾比引入外部知識在語義上更一致,結果也更可控。

整體來說

CRAG 是 RAG pipeline 的安全網,成本低(多一次搜尋),卻能防止系統在邊緣情況下靜默失敗。搭配 LLM-as-Judge 的 Groundedness 評分,即使放寬後取到的文件相關性較低,Judge 也會降低 groundedness 分數,讓系統加上適當的免責聲明。防禦是多層的,CRAG 是第一層。


參考資料