Skip to content

LongRAG:用長上下文模型重新思考 RAG 的 Chunking 策略

2026年3月15日 1 分鐘
TL;DR 傳統 RAG 把文件切成小 chunks 再檢索,但這造成資訊碎片化。LongRAG 利用 100K+ token 的長上下文模型,檢索更大的文件區段(整個章節甚至整份文件),減少碎片化同時保持檢索效率。
目錄
  1. 小 Chunk 的問題
    1. 資訊碎片化
    2. 邊界上下文丟失
    3. 過度依賴檢索精確度
    4. 語義密度不均
  2. 長上下文模型的機會
    1. 關鍵洞察
    2. 從精確檢索到粗粒度檢索
  3. LongRAG 架構
    1. 傳統 RAG vs LongRAG
    2. 檢索單元的選擇
  4. Chunking 策略重新設計
    1. 策略一:文件層級檢索(Document-level Retrieval)
    2. 策略二:章節層級檢索(Section-level Retrieval)
    3. 策略三:混合策略(Coarse Retrieval + Fine Reading)
    4. 策略比較
  5. 檢索效率考量
    1. 候選數量大幅減少
    2. 精確度 vs 召回率的權衡
    3. 平衡策略
  6. 與傳統 RAG 的比較
    1. 效能比較的具體數據
    2. 成本分析
  7. 實作指南
    1. 章節層級切割器
    2. LongRAG 檢索管線
    3. 完整管線:檢索 + 生成
  8. 適用場景
    1. 特別適合
    2. 不太適合
  9. 限制與挑戰
    1. 1. 需要長上下文 LLM
    2. 2. Token 成本線性增長
    3. 3. 推論延遲增加
    4. 4. Embedding 品質隨文字長度下降
    5. 5. 「Lost in the Middle」問題
    6. 6. 缺乏標準的評估基準
  10. 後續研究怎麼說
  11. 總結
  12. 延伸閱讀
  13. 更新紀錄
  14. 參考資料

🌏 English version

傳統 RAG 的核心假設是:LLM 的 context window 有限,所以我們必須把文件切得很小,只送最相關的片段進去。

這個假設在 2024 年之前是合理的。但主流商用模型的 context window 早已從 4K 級別跨進 10 萬 token 以上的量級(具體數字每季都在變,請直接查各家官方模型頁),當可用上下文多了兩個數量級,RAG 的設計邏輯應該跟著重新算一次帳。

LongRAG 就是這個思路的體現:不要再把文件切成碎片,而是檢索更大的單元,讓長上下文模型自己去理解。

先講結論:這篇談的是一種取捨,不是一個已經勝出的答案。LongRAG 論文發表後,社群對「長上下文是不是讓 RAG 過時」吵了一年多,而且證據往兩個方向都有——文末〈後續研究怎麼說〉一節會把反面證據攤開。


小 Chunk 的問題

傳統 RAG 通常把文件切成 256-512 tokens 的小 chunk。這個做法看似合理,但實際上製造了一系列問題。

資訊碎片化

一段完整的論述被切成多個 chunk 後,每個 chunk 都只有部分資訊。

看這個例子:

原始段落:
「該合約第 12 條規定,甲方需在收到驗收報告後 30 個工作日內完成付款。
若甲方逾期付款,應按每日萬分之五的比率支付違約金。但若逾期原因係
因乙方未提供完整驗收文件所致,甲方不負逾期責任。」

用 128 tokens 的 chunk size 切割:

Chunk 1: 「該合約第 12 條規定,甲方需在收到驗收報告後 30 個工作日內完成付款。」
Chunk 2: 「若甲方逾期付款,應按每日萬分之五的比率支付違約金。」
Chunk 3: 「但若逾期原因係因乙方未提供完整驗收文件所致,甲方不負逾期責任。」

使用者問:「甲方逾期付款要付多少違約金?」

檢索系統可能只找到 Chunk 2。但正確答案需要 Chunk 2 + Chunk 3 ── 因為有例外條款。如果只看到 Chunk 2,LLM 會給出一個看似正確但不完整的回答。

這就是資訊碎片化:每個 chunk 的語義是不完整的,必須跟其他 chunk 組合才能還原完整的意思。

邊界上下文丟失

chunk 的切割邊界往往是任意的。一段跨越邊界的推理鏈會被打斷:

Chunk A 結尾:「...因此,我們採用了 Transformer 架構。具體來說,」
Chunk B 開頭:「我們使用了 6 層 encoder 搭配旋轉位置編碼(RoPE),」

Chunk B 缺少了「為什麼採用 Transformer」的上下文。如果使用者問「為什麼選擇這個架構?」,單獨的 Chunk B 無法回答。

過度依賴檢索精確度

小 chunk 意味著大量候選片段。一個 10 萬字的中文文件約 15 萬 token,用 512 tokens 切割大約產生 300 個 chunk。檢索系統必須從幾百個候選中精確找到最相關的 3-5 個。

這對檢索的要求極高:

  • embedding 必須準確捕捉每個小 chunk 的語義
  • 排序必須精確,因為 top-3 和 top-10 的差距可能就是「有答案」和「沒答案」
  • 多跳推理(答案分散在多個 chunk)幾乎不可能做好

小 chunk 把「理解」的壓力全部轉移到了「檢索」上。而檢索從來就不是完美的。

語義密度不均

不同段落的語義密度差異很大。一段法律條文 512 tokens 裡可能包含 5 個重要觀點,而一段背景介紹 512 tokens 裡可能只有 1 個。固定大小的 chunk 無法反映這種差異。


長上下文模型的機會

2023 到 2025 年間,主流 LLM 的 context window 從數千 token 一路衝到數十萬、甚至百萬 token 等級。這裡不列模型對照表——這種表格三個月就過期,而且各家的「上限」與「實際還能用得好的長度」根本是兩回事。要查當下數字,看各家官方模型文件即可;要判斷能不能真的塞那麼多,看下面的〈後續研究怎麼說〉。

真正改變的是 RAG 的根本權衡:

以前:context window 是稀缺資源 → 必須精確檢索 → 小 chunk → 高檢索壓力。

現在:context window 充裕 → 可以放更多內容 → 大 chunk → 把壓力從檢索轉移到理解。

關鍵洞察

長上下文模型擅長在大量文字中找到相關資訊。needle-in-a-haystack(NIAH)測試顯示,即使在 10 萬 token 等級的 context 中,好的模型也能準確找到嵌入其中的特定事實。

這意味著:我們不需要完美的檢索,只需要足夠好的檢索。 把大致相關的內容丟給 LLM,讓它自己找答案。

但這個洞察後來被大幅修正過。NIAH 之所以看起來漂亮,有一部分是因為「針」和問題之間有字面重疊,模型可以靠字串比對抄捷徑。2025 年的 NoLiMa 基準把字面重疊拿掉、要求模型靠語義關聯去定位,結果 13 個宣稱支援 128K 以上的模型裡,有 11 個在 32K 就掉到短文本基線的一半以下;連表現最好的 GPT-4o 都從 99.3% 掉到 69.7%。所以「檢索夠好就行」這句話成立的區間,比 NIAH 分數看起來的要窄。

從精確檢索到粗粒度檢索

傳統 RAG 的心態是:「只給 LLM 最相關的片段,不要浪費 token。」

LongRAG 的心態是:「給 LLM 足夠的上下文,讓它自己判斷哪些相關。」

這不是退步,而是利用模型能力的進步。與其花大量工程投入去完善檢索(更好的 embedding、更精確的 reranking、更聰明的 query expansion),不如善用模型本身的理解能力。


LongRAG 架構

LongRAG 的核心設計很簡單:加大檢索粒度

傳統 RAG vs LongRAG

傳統 RAG:
┌──────────┐     ┌──────────────────────────────────────┐
│          │     │  文件 A                                │
│  Query   │     │  ┌─────┐┌─────┐┌─────┐┌─────┐...     │
│          │     │  │ c1  ││ c2  ││ c3  ││ c4  │        │
│          │     │  │512t ││512t ││512t ││512t │        │
│          │     │  └─────┘└─────┘└─────┘└─────┘        │
└────┬─────┘     └──────────────────────────────────────┘

     │ 向量搜尋                   從數百個 chunk 中
     │ (top-k=5)                 精確找到 5 個

┌─────┐┌─────┐┌─────┐┌─────┐┌─────┐
│ c2  ││ c17 ││ c43 ││ c8  ││ c91 │   ← 可能漏掉關鍵片段
└─────┘└─────┘└─────┘└─────┘└─────┘

     ▼  送入 LLM (~2,500 tokens)
┌──────────────────────────────┐
│  LLM 基於碎片化的上下文回答   │
└──────────────────────────────┘


LongRAG:
┌──────────┐     ┌──────────────────────────────────────┐
│          │     │  文件 A                                │
│  Query   │     │  ┌──────────────┐┌──────────────┐     │
│          │     │  │  Section 1   ││  Section 2   │     │
│          │     │  │  (~6,000t)   ││  (~8,000t)   │     │
│          │     │  └──────────────┘└──────────────┘     │
└────┬─────┘     └──────────────────────────────────────┘

     │ 向量搜尋                   從少量區段中
     │ (top-k=3)                 找到大致相關的

┌──────────────┐┌──────────────┐┌──────────────┐
│  Section 2   ││  Section 5   ││  Section 11  │  ← 完整語義單元
└──────────────┘└──────────────┘└──────────────┘

     ▼  送入 LLM (~20,000 tokens)
┌──────────────────────────────┐
│  LLM 基於完整上下文回答       │
└──────────────────────────────┘

兩者的根本差異:

  • 傳統 RAG:數百個小 chunk → 精確檢索 → 碎片化上下文 → LLM 拼湊答案
  • LongRAG:數十個大區段 → 粗粒度檢索 → 完整上下文 → LLM 直接理解

檢索單元的選擇

LongRAG 的「大 chunk」不是隨便把小 chunk 拼起來。它使用文件本身的結構作為切割邊界:

檢索單元大小範圍適用場景
段落群組1,000-3,000 tokens結構不明確的文件
章節(Section)3,000-10,000 tokens有標題結構的文件
子文件(Sub-doc)10,000-30,000 tokens長文件中的獨立章
整份文件30,000-100,000 tokens短到中等長度的獨立文件

關鍵原則:切割邊界應對齊語義邊界,而不是固定的 token 數。


Chunking 策略重新設計

LongRAG 不是「不切 chunk」,而是「切得更聰明」。以下是三種主要策略。

策略一:文件層級檢索(Document-level Retrieval)

最極端的做法:每份文件就是一個檢索單元。

索引結構:
Document A → 一個 embedding (代表整份文件的語義)
Document B → 一個 embedding
Document C → 一個 embedding
...

檢索:找到最相關的 1-3 份文件,全文送入 LLM。

優點

  • 完全不需要 chunking
  • 零資訊碎片化
  • 實作最簡單

缺點

  • 單份文件可能超過 context window
  • 一個 embedding 難以代表整份長文件的所有主題
  • 檢索精度最低(文件層級太粗了)

適用場景

  • 文件庫中每份文件都相對短(< 30K tokens)
  • 每份文件主題單一,不太會一份文件涵蓋多個不相關主題
  • 文件數量不多(< 1000 份)

策略二:章節層級檢索(Section-level Retrieval)

按文件的章節結構切割,每個章節是一個檢索單元。

索引結構:
Document A / Section 1 → 一個 embedding
Document A / Section 2 → 一個 embedding
Document A / Section 3 → 一個 embedding
Document B / Section 1 → 一個 embedding
...

檢索:找到最相關的 2-5 個章節,組合送入 LLM。

優點

  • 保持語義完整性(章節通常是完整的論述單元)
  • 檢索粒度適中,比文件層級精確
  • 利用文件本身的結構,不需要人工判斷切割點

缺點

  • 需要文件有明確的章節結構(標題、目錄等)
  • 章節大小差異可能很大(有的章 500 tokens,有的 20,000 tokens)
  • 跨章節的引用關係仍會丟失

適用場景

  • 技術文件、學術論文、法律文件
  • 有 Markdown/HTML 標題結構的文件
  • 單份文件有多個可獨立理解的主題

策略三:混合策略(Coarse Retrieval + Fine Reading)

這是 LongRAG 最推薦的做法:兩階段架構

第一階段 - 粗粒度檢索:
  用章節/文件層級的 embedding 找到大致相關的區段

第二階段 - 細粒度閱讀:
  LLM 在大區段中找到精確的答案

等效於:
  傳統 RAG 的 "retriever + reader"
  但 retriever 變粗了,reader 變強了

流程

  1. 建立索引時,用章節層級切割(3,000-10,000 tokens)
  2. 檢索時,取 top-k=3-5 個章節(共約 15,000-50,000 tokens)
  3. 將這些章節組合成一個大 context,送入長上下文 LLM
  4. LLM 在大 context 中找到精確答案

優點

  • 結合了粗檢索的高召回率和 LLM 的精確理解
  • 不需要完美的檢索(因為 LLM 會幫你過濾無關內容)
  • 適應性強,不同文件可以用不同的切割粒度

策略比較

維度文件層級章節層級混合策略
切割粒度整份文件3K-10K tokens3K-10K tokens
索引大小最小中等中等
檢索精度中 + LLM 補償
上下文完整度最高
Token 消耗最高中高中高
實作複雜度最低中高
適用模型1M context100K+ context100K+ context

檢索效率考量

大 chunk 改變了檢索系統的效能特徵。

候選數量大幅減少

同一個語料庫:

傳統 RAG (512 tokens/chunk):
  10 萬字文件 × 100 份 = ~30,000 個 chunk
  向量搜尋空間:30,000 個向量

LongRAG (章節層級, ~5,000 tokens/section):
  10 萬字文件 × 100 份 = ~8,000 個章節
  向量搜尋空間:8,000 個向量

候選數量減少 10 倍,直接帶來:

  • 更快的向量搜尋:HNSW 等 ANN 演算法在較小的索引上更快
  • 更低的儲存成本:更少的向量 = 更少的記憶體和磁碟空間
  • 更簡單的索引維護:新增/刪除文件時,需要更新的向量更少

精確度 vs 召回率的權衡

大 chunk 天然有更高的召回率(因為每個 chunk 涵蓋更多內容),但精確度可能降低(因為 chunk 中有更多無關內容)。

小 chunk (512 tokens):
  ✓ 精確度高 — 每個 chunk 主題集中
  ✗ 召回率低 — 答案可能被切到相鄰 chunk
  ✗ 需要更精確的檢索

大 chunk (5,000 tokens):
  ✗ 精確度低 — chunk 內可能有無關內容
  ✓ 召回率高 — 答案更可能在被選中的 chunk 內
  ✓ 容錯性高,檢索不完美也能找到答案

平衡策略

幾種降低大 chunk 精確度損失的方法:

1. 多層級索引

同時維護章節層級和段落層級的 embedding,先用章節層級檢索縮小範圍,再用段落層級排序。

2. 摘要 Embedding

不用整個章節的文字做 embedding,而是先用 LLM 產生章節摘要,用摘要做 embedding。摘要更濃縮、語義密度更高,embedding 品質更好。

3. 多向量表示

一個章節產生多個 embedding(例如章節摘要 + 章節中每個段落的首句),任一命中都視為該章節相關。

4. 後處理排序

檢索到大 chunk 後,用 cross-encoder 或 LLM 對 chunk 內的段落做二次排序,優先展示最相關的部分。


與傳統 RAG 的比較

以下是 LongRAG 和傳統 RAG 在各個維度的具體比較:

維度傳統 RAGLongRAG
Chunk 大小256-512 tokens3,000-100,000 tokens
索引中的向量數多(每份文件數百個)少(每份文件數個到數十個)
檢索精確度高(每個 chunk 主題集中)中(chunk 內有混合主題)
上下文連貫性低(碎片化)高(完整語義單元)
Token 消耗/query低(~2K-5K tokens)高(~15K-50K tokens)
推論延遲較低較高(更多 token 要處理)
檢索延遲較高(大索引)較低(小索引)
多跳推理能力弱(需要多次檢索)強(大上下文自然涵蓋)
對檢索品質的依賴極高中等
LLM 要求任何模型需要長上下文模型
每次查詢成本較低較高
建置複雜度高(需要精細的 chunking + reranking)低(粗粒度切割即可)

效能比較的具體數據

先把論文真正報的數字講清楚,因為這組數字常被引錯。

檢索端(NQ / HotpotQA,Wikipedia):

LongRAG 把相關文件合併成 4K token 的檢索單元,NQ 的語料單元數從 2,200 萬降到 60 萬。論文的原話是:answer recall@1 從 DPR 的 52% 提升到 71%;HotpotQA 則是語料從 500 萬降到 50 萬單元,recall@2 從 47% 提升到 72%。

注意這是 recall@1 / recall@2,不是「top-5 vs top-4 的命中率」——這兩者常被混為一談。論文的主張是「只取極少數(少於 8 個)長單元就有很強的檢索表現」,而不是「同樣 top-k 下大 chunk 比較好」。

生成端:

不需要任何訓練,LongRAG 在 NQ 拿到 62.7 EM、HotpotQA 拿到 64.3 EM,論文說這與「完整微調過的 SoTA」相當。主表用的 reader 是當時的 GPT-4o(論文另外比較了六個 reader)。在非 Wikipedia 的資料集上,Qasper F1 從 22.5% 提升到 25.9%、MultiFieldQA-en 從 51.2% 提升到 57.5%。

關鍵原因是召回率的改善:傳統小 chunk 檢索經常漏掉包含答案的片段,大單元更容易把答案涵蓋進去。

成本分析

這裡不列價格表——各家 API 的單價變動太快,任何寫死的數字都會過期。要算實際金額請直接查官方定價頁

真正穩定的是比例

傳統 RAG 每次查詢:
  檢索:5 chunks × 512 tokens ≈ 2,600 input tokens

LongRAG 每次查詢:
  檢索:3 sections × 6,000 tokens ≈ 18,000 input tokens

input token 量約 7 倍。

由於絕大多數 RAG 查詢的成本由 input token 主導(output 通常只有幾百 token),這個比例大致就是成本比例。實務上有兩個修正項會把差距拉小:prompt caching(同一批章節被重複命中時,快取讀取的單價遠低於原價)與批次處理折扣——如果你的流量型態吃得到,先量一次再下結論。

這個權衡是否值得,取決於應用場景。對法律、醫療、金融等高價值查詢,數倍成本換取更準確完整的答案通常合理。對低價值的日常高頻問答,傳統 RAG 明顯更經濟。


實作指南

以下是一個完整的 LongRAG 檢索管線實作,使用 TypeScript。

章節層級切割器

interface Section {
  id: string;
  documentId: string;
  title: string;
  content: string;
  tokenCount: number;
  embedding: number[];
  metadata: { level: number; position: number };
}

/**
 * 按章節結構切割文件,而非固定 token 數。
 * 超過 maxTokens 的章節遞迴往下一層標題切割;
 * 太小的相鄰章節自動合併。
 */
function splitBySection(
  document: { id: string; content: string },
  maxTokens = 8000,
  minTokens = 500,
): Section[] {
  const lines = document.content.split('\n');
  const sections: Section[] = [];
  let currentTitle = '';
  let currentContent: string[] = [];
  let level = 1;
  let idx = 0;

  function flush() {
    if (!currentContent.length) return;
    const content = currentContent.join('\n');
    const tokens = estimateTokens(content);
    sections.push({
      id: `${document.id}_s${idx}`,
      documentId: document.id,
      title: currentTitle,
      content,
      tokenCount: tokens,
      embedding: [],
      metadata: { level, position: idx++ },
    });
    currentContent = [];
  }

  for (const line of lines) {
    const m = line.match(/^(#{1,6})\s+(.+)/);
    if (m) {
      flush();
      level = m[1].length;
      currentTitle = m[2].trim();
      currentContent = [line];
    } else {
      currentContent.push(line);
    }
  }
  flush();

  // 合併太小的相鄰章節
  return sections.reduce<Section[]>((merged, section) => {
    const prev = merged[merged.length - 1];
    if (prev && prev.tokenCount < minTokens) {
      prev.content += '\n\n' + section.content;
      prev.tokenCount += section.tokenCount;
    } else {
      merged.push({ ...section });
    }
    return merged;
  }, []);
}

function estimateTokens(text: string): number {
  const zh = (text.match(/[\u4e00-\u9fff]/g) || []).length;
  const en = text.replace(/[\u4e00-\u9fff]/g, '').split(/\s+/).length;
  return Math.ceil(zh * 1.5 + en * 1.3);
}

LongRAG 檢索管線

import { cosineSimilarity, generateEmbedding } from './utils';

interface RetrievalResult {
  sections: Section[];
  totalTokens: number;
  query: string;
}

interface LongRAGConfig {
  topK: number;            // 檢索多少個章節
  maxContextTokens: number; // 最大 context tokens
  minRelevanceScore: number; // 最低相關性分數
}

/**
 * LongRAG 的核心檢索邏輯。
 * 與傳統 RAG 的差異:
 * 1. 檢索單元是章節(數千 tokens),不是小 chunk(數百 tokens)
 * 2. top-k 較小(3-5),因為每個結果已經很大
 * 3. 有 token budget 控制,避免超過 LLM 的 context window
 */
async function retrieveSections(
  query: string,
  index: Section[],  // 每個 section 已有 embedding
  config: LongRAGConfig = { topK: 5, maxContextTokens: 50000, minRelevanceScore: 0.3 },
): Promise<RetrievalResult> {
  const queryEmbedding = await generateEmbedding(query);

  // 計算相似度 → 過濾 → 排序
  const scored = index
    .map((section) => ({
      section,
      score: cosineSimilarity(queryEmbedding, section.embedding),
    }))
    .filter((item) => item.score >= config.minRelevanceScore)
    .sort((a, b) => b.score - a.score);

  // 在 token budget 內選擇 top-k 章節
  const selected: Section[] = [];
  let totalTokens = 0;

  for (const item of scored) {
    if (selected.length >= config.topK) break;
    if (totalTokens + item.section.tokenCount > config.maxContextTokens) continue;
    selected.push(item.section);
    totalTokens += item.section.tokenCount;
  }

  // 按原始位置排序(保持閱讀順序)
  selected.sort((a, b) => {
    if (a.documentId !== b.documentId) return a.documentId.localeCompare(b.documentId);
    return a.metadata.position - b.metadata.position;
  });

  return { sections: selected, totalTokens, query };
}

完整管線:檢索 + 生成

/**
 * LongRAG 完整管線:切割 → 索引 → 檢索 → 生成回答
 */
async function longRAGPipeline(
  documents: { id: string; content: string }[],
  query: string,
) {
  // Step 1: 章節切割
  const allSections = documents.flatMap((doc) => splitBySection(doc, 8000, 500));

  // Step 2: 檢索(假設 sections 已有 embedding)
  const retrieval = await retrieveSections(query, allSections, {
    topK: 4, maxContextTokens: 40000, minRelevanceScore: 0.25,
  });

  // Step 3: 組裝 context 並生成回答
  const context = retrieval.sections
    .map((s, i) => `=== 來源 ${i + 1}: ${s.title} ===\n${s.content}`)
    .join('\n---\n\n');

  const answer = await callLLM({
    // 模型 ID 從設定注入,別寫死在程式碼裡——它會過期
    model: process.env.LONG_CONTEXT_MODEL!,
    system: `根據參考資料回答問題。引用來源編號,資料不足時明確說明。`,
    messages: [{ role: 'user', content: `參考資料:\n${context}\n\n問題:${query}` }],
    maxTokens: 1000,
  });

  return {
    answer,
    sources: retrieval.sections.map((s) => ({ documentId: s.documentId, title: s.title })),
    tokensUsed: retrieval.totalTokens,
  };
}

適用場景

LongRAG 不是萬能的。以下是它特別適合和不適合的場景。

特別適合

1. 長篇法律文件

法律條文的特點是:條款之間有大量交叉引用,一個條款的意義取決於其他條款的上下文。傳統 RAG 把合約切成小 chunk 後,這些交叉引用全部斷裂。LongRAG 保留整個章節甚至整份合約,讓 LLM 看到完整的條款關係。

使用者問:「如果承包商延遲交付,業主可以終止合約嗎?」

傳統 RAG 可能只找到:
  「延遲交付超過 30 天,業主有權終止合約。」

LongRAG 會找到整個「終止條款」章節,包含:
  - 延遲交付的定義
  - 30 天寬限期
  - 不可抗力的例外
  - 終止前的書面通知要求
  - 終止後的結算方式

2. 學術論文

論文的方法論、實驗設計和結果分析通常分散在不同章節,但彼此密切相關。LongRAG 可以一次檢索整個「Method + Experiments」區段,讓 LLM 理解方法和結果之間的因果關係。

3. 技術手冊與 API 文件

技術概念通常需要完整的上下文才能理解。一個 API endpoint 的行為可能取決於認證設定、rate limit 政策、錯誤碼定義等分散在不同章節的資訊。大 chunk 讓這些散落的資訊更容易被一次檢索到。

4. 多跳推理查詢

當答案需要綜合多個段落的資訊時,LongRAG 天然優勢:

問:「公司在哪些情況下可以不支付年終獎金?」

需要綜合:
  - 年終獎金計算辦法(第 4 章)
  - 員工考核標準(第 7 章)
  - 特殊例外條款(第 12 章)

LongRAG 更可能把這三個章節都檢索到。

5. 上下文連貫性重於精確度的場景

客服知識庫、產品 FAQ、政策手冊 ── 這些場景中,給使用者一個完整、連貫的回答比精確引用某個段落更重要。LongRAG 的大上下文讓 LLM 能生成更流暢、更完整的回答。

不太適合

1. 極大規模語料庫的精確事實查詢

如果你的語料庫有上百萬份文件,使用者只是在找一個具體的數字或日期,傳統 RAG 的小 chunk + 精確檢索更高效。LongRAG 在這種場景下會消耗大量不必要的 token。

2. 低延遲要求的場景

LongRAG 送入 LLM 的 token 數大約是傳統 RAG 的 7–8 倍(上面那組配置算出來是 7 倍,換個 chunk 大小會浮動),推論延遲也會相應增加。對於需要毫秒級回應的場景(如即時搜尋建議),這可能不可接受。

3. 成本敏感的高頻查詢

每次查詢消耗 15K-50K input tokens,如果每天有上萬次查詢,token 成本會非常可觀。


限制與挑戰

1. 需要長上下文 LLM

LongRAG 的前提是 LLM 能處理大量 input tokens。如果你的模型只有 8K-16K 的 context window,LongRAG 的大 chunk 根本放不進去。

今天商用 API 與較新的開源權重模型大多已宣稱支援 10 萬 token 以上,這個限制比 2024 年鬆了很多。但「宣稱支援」不等於「用得好」——見前面 NoLiMa 的結果,以及 Databricks 那份跨 20 個模型的 RAG 長上下文研究:只有少數最新的模型能在 64K 以上維持穩定準確度。真正的限制不是放不放得進去,而是放進去之後模型還抓不抓得到。

2. Token 成本線性增長

更多的 input tokens 直接意味著更高的 API 成本,而且是線性的。同樣不列單價(會過期),只看量級:如果每天 10,000 次查詢,傳統 RAG 每次約 3K input tokens、LongRAG 約 25K,那就是每天 3,000 萬 vs 2.5 億 token 的差距——同一個單價乘下去,年化差距是好幾個數量級的金額。

在大流量場景下這個差距不可忽視,也是後面 Self-Route 那類「用路由把便宜路徑留給簡單問題」的做法之所以有價值的原因。

3. 推論延遲增加

LLM 的推論時間大致與 input tokens 成正比。25K tokens 的處理時間約是 3K tokens 的 5-8 倍。在使用者體驗敏感的場景(如聊天機器人),這個延遲可能不可接受。

緩解策略

  • 使用 streaming 回應,讓使用者看到第一個 token 的時間不變
  • 快取熱門查詢的結果
  • 對不需要長上下文的簡單查詢,退回傳統 RAG

4. Embedding 品質隨文字長度下降

現有的 embedding 模型在處理長文字時,語義表示的品質會下降。一段 5,000 tokens 的文字可能涵蓋多個主題,而單一個 embedding 向量難以同時捕捉所有主題。(各家 embedding 模型的最大輸入長度差異很大,選型前查官方文件;別假設它吃得下你的整個章節。)

緩解策略

  • 用摘要 embedding(前面實作的方法)
  • 用 ColBERT 風格的多向量表示
  • 用多個 embedding 表示一個章節

5. 「Lost in the Middle」問題

研究顯示,LLM 在處理長 context 時,對中間段落的注意力較弱(相對於開頭和結尾)。如果關鍵資訊正好在長 context 的中間位置,LLM 可能會忽略它。

緩解策略

  • 把最相關的章節放在 context 的開頭和結尾
  • 在 prompt 中明確提醒 LLM 注意所有章節
  • 限制總 context 長度,不要無限制地塞入內容

6. 缺乏標準的評估基準

傳統 RAG 有成熟的評估框架(Precision@K、Recall@K、MRR 等),但 LongRAG 的評估更困難。因為檢索單元大小不同,直接比較 Precision@K 不公平。目前還沒有針對 LongRAG 場景的標準化評估基準。


後續研究怎麼說

LongRAG 是 2024 年 6 月的技術報告。之後這一年多,「長上下文 vs RAG」被反覆測過,結論並不一致——這節把幾個關鍵的擺在一起,因為只讀 LongRAG 的摘要很容易得到過度樂觀的印象。

支持「長上下文贏」的那一側: Google 的 Self-Route 研究(EMNLP 2024 industry track)在多個公開資料集上比較 RAG 與長上下文 LLM,結論是「資源充足時,長上下文的平均表現持續優於 RAG」——但同一篇也直說 RAG 的成本優勢是明確的,因此他們提出 Self-Route:讓模型自己判斷該走 RAG 還是長上下文,在維持接近長上下文品質的同時大幅降低計算成本。這其實就是本文結尾要講的「混合策略」,只是有了實驗背書。

反對的那一側,而且直接針對 LongRAG 的核心假設: 〈In Defense of RAG in the Era of Long-Context Language Models〉(2024/09)主張「極長的 context 會稀釋對相關資訊的注意力,反而讓答案品質下降」。他們提出 OP-RAG(order-preserve RAG,保留檢索片段在原文中的順序),發現答案品質隨檢索 chunk 數量增加會先升後降,形成倒 U 形曲線——存在一個甜蜜點,用遠少於長上下文的 token 就能得到更好的答案。這與「塞越多越好」正面衝突。

另一組實證: Databricks 的〈Long Context RAG Performance of LLMs〉跨 20 個開源與商用模型、把總 context 從 2K 拉到 128K(可行時到 2M),結論是:檢索更多文件確實能提升表現,但只有少數最新的模型能在 64K 以上維持穩定準確度,而且長上下文有各自不同的失效模式。

還有基準本身的問題: 前面提過的 NoLiMa(ICML 2025)指出,NIAH 這類測試被字面重疊灌了水;拿掉字面線索之後,長上下文的衰退比大家以為的嚴重得多。

怎麼讀這些互相打架的結果?我的整理是:

  • 「大 chunk 提高召回率」這件事站得住——LongRAG 的檢索端數字(recall@1 從 52% 到 71%)是實打實的。
  • 「所以把大 chunk 全塞進去讓模型自己挑」則是有條件成立:條件是你的模型在該長度上真的沒退化,而且答案不需要靠非字面的語義關聯去定位。
  • 「長上下文讓 RAG 過時」是最站不住的一個版本。OP-RAG 的倒 U 曲線與 Self-Route 的成本結論都指向同一件事:檢索仍然值得做,只是最佳粒度和最佳 top-k 要靠實測找,不是靠公式。

順帶一提的命名地雷: 2024 年有兩篇不同的論文都叫 LongRAG。本文談的是 Jiang et al. 的 arXiv:2406.15319(long retriever + long reader)。另一篇是 Zhao et al. 的 arXiv:2410.18050(EMNLP 2024 Main),做的是長文件 QA 的雙視角 RAG 系統,架構完全不同。看到有人引用 LongRAG 時,先確認是哪一篇。


總結

LongRAG 的核心洞察很簡單:當 LLM 的理解能力夠強、context window 夠大時,不需要把所有壓力都放在檢索上。

傳統 RAG 在小 context window 時代的設計是合理的:精確切割、精確檢索、只給 LLM 最必要的資訊。但這個策略的代價是資訊碎片化和對檢索精確度的過度依賴。

LongRAG 重新分配了這個壓力:

  • 檢索:從「精確找到最相關的小片段」變成「大致找到相關的大區段」
  • 理解:從「基於碎片化上下文拼湊答案」變成「在完整上下文中理解並回答」

這不是要取代傳統 RAG,而是在長上下文模型普及的今天,提供了另一個有效的設計選擇。根據你的文件特性、查詢類型、成本預算和延遲要求,選擇最適合的策略。

最務實的做法可能是混合策略:對簡單查詢用傳統 RAG 節省 token,對複雜查詢切換到 LongRAG 提升品質。一個 query classifier 就能做到這件事——Self-Route 的實驗結果基本上就是這個做法的背書:讓模型自己判斷該走哪條路,成本大幅下降而品質接近純長上下文。


延伸閱讀

更新紀錄

  • 2026-08-19:對照官方文件逐篇查證翻新,移除易腐內容,並收進「RAG 技法大全」系列

參考資料