Long Context 评测
长上下文评测检验模型在长输入中定位、引用和整合信息的能力。这里的「长」通常指接近或超出模型训练时常见输入长度的区间,重点考察信息在输入中位置变化时,模型是否仍能稳定取用。
长上下文能力的评测从「能否检索到」起步:Greg Kamradt 提出的针入草堆 (needle in a haystack) 测试,把一条唯一事实埋进无关文本并让模型找回,成为衡量长上下文的最低门槛。随后 Lost in the Middle 论文用对照实验揭示了「位置」这一关键变量——模型对输入中部的信息利用显著弱于首尾,呈 U 形曲线。在此基础上,LongBench、RULER 与 ∞Bench 等基准把范围扩展到多针检索、跨段聚合与长文档推理,使评测从单一检索走向接近真实的综合使用。
快速开始¶
按长度和信息位置分桶,记录准确率、延迟、成本和截断率;不能只测最大长度。
先确定要评测的长度区间,例如 4K、16K、64K、128K 等,并把题目按长度分桶,而不是只看单一最大长度。对每个桶,再把需要引用的关键信息分别放置在输入的不同位置,例如开头、中部、末尾,得到「长度 x 位置」的二维矩阵。
评测时记录每道题的答案正确率,同时记录端到端延迟、推理成本和是否发生截断。截断率指的是模型因达到上下文上限而丢失尾部信息的比例,它常常比平均准确率更能暴露配置问题。延迟和成本也应按长度分桶,因为长输入下首字延迟 (time to first token) 可能显著增长。
验证方式可以是:对同一个事实,构造「只需检索」和「需要跨段整合」两版问题,确认前者稳定而后者随长度下降,从而判断瓶颈在检索还是在整合。一个把题目按「长度 x 位置」分桶的最小结构如下:
buckets = []
for length in [4000, 16000, 64000, 128000]:
for pos in ["head", "middle", "tail"]:
buckets.append({"length": length, "position": pos, "correct": 0, "total": 0})
验证成功的标准:对同一「长度 x 位置」格,重跑两次得到相同正确率;且随长度增加,首字延迟的增速符合注意力机制的预期量级,未出现异常截断。
方法¶
针入草堆、跨段问答和长文摘要分别覆盖定位与整合。需要防止答案可由短局部线索猜出。
针入草堆 (needle in a haystack) 是基础的定位测试:在大量无关文本中埋入一条唯一事实,让模型回答该事实。它主要测「能否找到」,实现简单,但单独使用会高估能力,因为它不要求模型对多段信息做推理或整合。Lost in the Middle 的结论正是针对这一盲区:即使模型整体上能找到针,其表现也随针的位置呈 U 形,中部信息被正确利用的概率最低。
跨段问答要求答案依赖分散在多处、甚至相互矛盾的信息,例如从多个报告中汇总数字或对同一事件的两种记录做比较,这是更接近真实使用的整合能力测试。长文摘要则考察模型能否在长输入上保持全局结构,同时不遗漏关键点。
构造题目时要避免答案可以由某个短窗口内的局部线索直接猜出,否则评测退化成语义相似题。可以通过让答案依赖两个相距很远的位置,或要求显式引用证据位置来排除这种捷径。
案例¶
将同一事实放入文首、中部、末尾,比较引用正确率。中部显著下降常提示 lost-in-the-middle 问题。
取一段足够长的无关文档,把一条唯一事实(例如一个具体日期或人名)分别放到文档的开头、中部和末尾三个版本中,让模型回答该事实。三个版本其余内容完全一致,仅事实位置不同。一段最小构造逻辑如下:
haystack = "无关文本。" * 4000 # 用无关内容填充到目标长度
needle = "目标的生日是 1997 年 3 月 14 日。"
positions = {
"head": 0,
"middle": len(haystack) // 2,
"tail": len(haystack) - 1,
}
prompts = {p: haystack[:i] + needle + haystack[i:] for p, i in positions.items()}
分别统计三个位置上的正确率。典型现象是首尾较高、中部明显偏低,这被称为 lost-in-the-middle 问题,反映模型对长输入中部信息的注意力衰减。若三个位置差异不大,则说明该模型在这一长度下位置鲁棒性较好。
进一步排查可以改变文档总长度,观察中部正确率是否随长度增长而单调下降;也可以把需要整合的两个事实分别放在首尾,看模型是否能同时取用,以区分「定位」与「整合」两个层面的能力。