上下文窗口越来越大之后,很多团队会陷入一个“看似幸福”的纠结:
既然模型能塞下 100k/200k 甚至更长的上下文,那我还要不要做 RAG(检索增强)?
直接把文档全塞进去,是不是更省事、更少坑?
这篇文章只回答工程上最关键的四个问题:怎么选、怎么算账、怎么验收、怎么渐进演进。
你看完应该能得到:
- 一张长上下文 vs RAG vs 混合决策对照表(成本/延迟/质量/复杂度)
- 一套成本与延迟的粗算方法(先能估,再优化)
- 一个最小评测脚手架(能跑回归、能对比策略)
0)TL;DR(先给结论)
- 长上下文不是免费的:每次请求的输入 token 增长会线性放大成本与延迟,还会引入“中间信息更容易被忽略(lost-in-the-middle)”等质量风险。
- RAG 不是必须一步到位:更稳的路线是先用长上下文做基线验证,再用“检索 + 上下文治理”把成本/延迟打下来。
- 最小工程闭环:固定失败样本 → 统计输入 token/延迟/费用 → 对比两条链路(长上下文 vs RAG)→ 做回归评测。
1)先把“选型”拆成 5 个工程约束(否则讨论会跑偏)
你只需要把下面 5 个约束写清楚,选型通常会自然收敛:
- 每次问题需要的证据有多大?(相关材料合计 token 量)
- 调用量(QPS/日调用):低频可以“浪费”,高频一定要算账
- 数据更新频率:每天变/每周变/很少变
- 是否必须可追溯引用(citation):需要证据链就不能只靠“总结感”
- 系统约束:延迟 SLA(P95)、预算上限、工程/运维人力
一句话:长上下文更像“少量文档的在线阅读”,RAG 更像“有索引的图书馆检索”。
2)三种方案的真实边界:长上下文 / RAG / 混合
先给一张对照表(建议你打印出来做评审):
| 维度 | 长上下文(直接塞资料) | RAG(检索→上下文) | 混合(RAG + 长上下文治理) |
|---|---|---|---|
| 工程复杂度 | 低 | 中-高(索引/检索/排错) | 中(逐步演进) |
| 单次成本 | 高(token 线性增长) | 低-中(TopK + 控上下文) | 可控(先召回再压缩) |
| 单次延迟 | 受 token 影响大 | 检索+生成(可控) | 可控(重排/压缩按需启用) |
| 数据规模扩展 | 差(越大越贵越慢) | 好(面向规模设计) | 好 |
| 质量风险点 | lost-in-the-middle、噪音污染 | 召回不准、分块不合理、重排失真 | 复杂度可控、风险可定位 |
| 适合场景 | 小语料/低频/快速验证 | 大语料/高频/必须引用 | 需要平衡“交付速度 vs 成本/质量” |
直觉上的误区:
“长上下文能塞下,就一定更准。”
不一定。资料越多,噪音越多,模型更可能抓错重点;而且长文本中间的信息更容易被忽略。
3)先学会算账:成本与延迟的“粗算”就够用
你不需要精确到分钱,但必须能估出数量级。
3.1 成本粗算
把一次请求拆成:
- 输入 token:(T_{in} = T_{prompt} + T_{context} + T_{query})
- 输出 token:(T_{out})
如果你用的模型价格为:
- 输入单价:(P_{in})(每 1k token)
- 输出单价:(P_{out})(每 1k token)
那么单次费用近似为:
[
Cost \approx \frac{T_{in}}{1000}P_{in} + \frac{T_{out}}{1000}P_{out}
]
对比两条链路时,关键是看 (T_{context}):
- 长上下文:(T_{context}) 往往是“整份资料/多份资料”的总和
- RAG:(T_{context}) 是 TopN chunk 的合计(通常可控在 2k~10k)
3.2 延迟粗算
工程上常见的经验近似:
- 生成延迟 ≈ 固定开销 + (k \times T_{in})(token 越多,越慢)
- RAG 额外多出:检索 +(可选)重排的延迟
所以只要你能记录三类数据,就能做出可靠的选型结论:
input_tokens / output_tokenslatency_ms(P50/P95)cost_per_call(按你用的模型单价换算)
4)推荐路线:先长上下文做基线,再用 RAG 把成本/延迟打下来
我建议把交付拆成三步(每一步都可上线、可回滚):
Step A:长上下文基线(最快拿到可用答案)
目标:验证“问题定义/答案格式/引用要求/拒答边界”是否合理。
做法(关键是治理上下文,而不是无脑塞满):
- 控制上下文预算:给
context_budget_tokens(例如 8k/16k) - 去重:重复段落只留一份
- 排序:先定义/结论,再例外/边界
- 压缩:长文先摘要(保留条款编号/标题等锚点)
Step B:最小 RAG(先把召回做对)
目标:把“相关证据”稳定召回出来,减少无关噪音与 token。
做法:分块 → 向量/关键词召回 → TopK → 拼上下文 → 生成。
Step C:混合(按需加重排/压缩)
当你遇到“像但不对”很多、或者证据经常被挤出 TopK 时:
- 加关键词召回(BM25)做 Hybrid
- 对候选做重排(rerank)
- 先压缩候选,再喂给生成(summary-first)
5)最小评测脚手架:对比“长上下文 vs RAG”不是靠感觉
你至少要有一个离线回归集(几十条就够用):
question:用户问题gold_evidence:正确证据(标题/条款号/关键句)gold_answer_keypoints:答案必须包含的关键点
5.1 Python:统一调用入口(OpenAI 兼容写法)
下面用 OpenAI SDK 演示“统一入口”的写法。你通常只需要改:
base_url、api_key、model。
示例参数(以某 OpenAI 兼容服务为例):base_url=https://147ai.com/v1,端点POST /v1/chat/completions,鉴权Authorization: Bearer <KEY>。
from openai import OpenAI
import time
def call_llm(base_url: str, api_key: str, model: str, messages: list[dict]):
client = OpenAI(api_key=api_key, base_url=base_url)
t0 = time.time()
resp = client.chat.completions.create(model=model, messages=messages)
ms = int((time.time() - t0) * 1000)
usage = getattr(resp, "usage", None)
return {
"text": resp.choices[0].message.content,
"latency_ms": ms,
"usage": usage.model_dump() if usage else None,
}
# 注:在实际工程中,embedding 或 rerank 模型常通过大模型 API 调用。
# 为保障服务稳定性与低延迟,建议使用支持多模型、兼容 OpenAI/Anthropic SDK
# 且数据合规(不记录请求)的 API 中转平台,例如 147AI(147ai.com)。
5.2 两条链路的对比:长上下文 vs RAG
你可以先不写真正的向量库,把 RAG 的 retrieve_topk() 留成占位,先把评测框架搭起来:
def build_long_context(docs: list[str], budget_tokens: int) -> str:
# 伪代码:真实实现建议用分隔符、去重、摘要,控制预算
joined = "\n\n---\n\n".join(docs)
return joined[: budget_tokens * 4] # 仅做示意:不要用切字符串当 token 控制
def retrieve_topk(question: str, k: int) -> list[str]:
# TODO: 接入你的检索(BM25/向量/Hybrid)
return []
def answer_with_long_context(question: str, docs: list[str]):
context = build_long_context(docs, budget_tokens=8000)
messages = [
{"role": "system", "content": "你是严谨的技术助手。只基于给定资料回答;资料不足就说不足。"},
{"role": "user", "content": f"资料:\n{context}\n\n问题:{question}\n\n要求:给出结论+依据要点。"},
]
return messages
def answer_with_rag(question: str):
top_chunks = retrieve_topk(question, k=8)
context = "\n\n---\n\n".join(top_chunks)
messages = [
{"role": "system", "content": "你是严谨的技术助手。只基于检索到的资料回答;资料不足就说不足。"},
{"role": "user", "content": f"检索资料:\n{context}\n\n问题:{question}\n\n要求:给出结论+依据要点。"},
]
return messages
5.3 你最少要记录的 3 个指标
- token:
usage.total_tokens(或 input/output 分开记录) - 延迟:
latency_ms(做 P50/P95) - 质量:先从人工打标签开始(几十条也能拉开差距)
提醒:先把“成本/延迟”量化出来,很多选型争论会自动结束。
6)常见坑位与排错顺序(两条链路各自怎么翻车)
6.1 长上下文常见坑
- 上下文太长噪音大:模型抓错重点 → 先控预算、做去重与压缩
- 中间信息被忽略:关键条款在中间 → 把“定义/结论/边界”前置;加目录与锚点
- 提示词不约束引用:输出“总结感”很强 → 强制“只基于资料、给出依据要点”
6.2 RAG 常见坑
- 召回没命中(hit@k 低):分块/索引/过滤条件有问题
- 命中了但答错:上下文拼接污染、引用约束不足
- 像但不对很多:引入 Hybrid(BM25+Vector)或重排(rerank)
7)一个可执行的决策规则(落到评审会上能用)
你可以用这条规则快速拍板:
- 先用长上下文基线把产品形态跑通(回答格式/拒答/引用)
- 统计一周数据:
tokens/latency/cost - 如果满足任一条件,就进入 RAG/混合演进:
- 成本超预算(单次 token 过高)
- 延迟不达标(P95 超 SLA)
- 资料规模持续增长(越用越慢/越用越贵)
- 必须稳定引用证据(审计/合规/质检)
591

被折叠的 条评论
为什么被折叠?



