长上下文与长文本处理:当文档比窗口还长怎么办
长上下文与长文本处理:当文档比窗口还长怎么办
“256K 上下文”听起来很美,但真把一本 30 万字的书塞进去,模型可能答不准、钱包先瘪了。理解长上下文的成本与边界,是工程落地的必修课。
一、上下文窗口不是免费午餐
- KV Cache 随长度平方级增长:注意力计算复杂度约 O(n²),上下文翻倍,算力与显存远不止翻倍。
- 按 token 计费:长上下文 = 高成本,尤其输入比输出贵得多时。
- 注意力稀释:信息越多,模型越难聚焦关键句。研究反复证明,把答案藏在超长文本中段,准确率会明显下降。
结论:能用短上下文解决的,别上长上下文。
二、长文档处理的四条路
方案A 切分+检索(RAG):长文档 → 切块 → 只取相关块 → 喂模型
方案B Map-Reduce :长文档 → 分块各自摘要 → 合并摘要再答
方案C 滑动窗口 :窗口滑动阅读,逐段提取,最后整合
方案D 真长上下文 :直接全量塞入(仅适合<窗口且需全局推理)
三、Map-Reduce 摘要(最实用)
把“读完整本书再总结”拆成“每章先摘要,再摘要摘要”:
def map_reduce_summarize(chapters, llm):
# Map:每章独立摘要
chapter_summaries = [llm.summarize(c) for c in chapters]
# Reduce:合并摘要
while len(chapter_summaries) > 1:
merged = []
for i in range(0, len(chapter_summaries), 2):
pair = chapter_summaries[i:i+2]
merged.append(llm.summarize("\n".join(pair)))
chapter_summaries = merged
return chapter_summaries[0]
这比一次性塞全书更省、更准,也是多数“长文总结”产品的底层逻辑。
四、滑动窗口 vs RAG
- 滑动窗口:适合“按顺序理解”的任务(如代码逐文件阅读),但容易丢失跨窗口的长期依赖。
- RAG:适合“找关键信息”的任务(如“合同里违约金条款在哪”),按需检索,成本最低。
实战常组合:先用 RAG 召回候选块,再放进长上下文做精细推理。
五、工程建议
- 设上限:单次调用输入 token 设硬上限(如 32K),超限走分块。
- 压缩历史:对话 Agent 把早期轮次摘要成一条,避免无限增长(WCode 正是这么做的)。
- 按需加载:先让小模型判定“哪段相关”,再让大模型精读。
- 评测注意力:关键事实放在开头或结尾(首因/近因效应),别埋中段。
长上下文是能力,不是银弹。会用“短而准”永远优于“长而糊”。
下一篇做一道灵魂选择题:微调还是 RAG?