长上下文评估 本节摘要:Gemini 3 Pro 标称 1000 万 token 上下文,但在 100 万 token 时,8 针 MRCR 掉到 26.3%——标称不等于可用,长上下文评估告诉你所发布的模型的真实容量。你有一份 200 页合同,模型声称百万 token 上下文,你贴进去问「解约条款是什么」,它却从封面页作答——因为解约条款埋在 12 万 token 深处,过了模型真正注意的范围。这是 2026 的上下文容量鸿沟:规格书写 100 万或 1000 万,现实说可用只有 6070%,且「可用」取决于任务——单针检索在前沿模型上接近满分到标称上限;多跳/聚合在多数模型上过约 12.8 万就骤降;对分散事实的推理是最先失败的任务。
本节摘要:Gemini 3 Pro 标称 1000 万 token 上下文,但在 100 万 token 时,8 针 MRCR 掉到 26.3%——标称不等于可用,长上下文评估告诉你所发布的模型的真实容量。你有一份 200 页合同,模型声称百万 token 上下文,你贴进去问「解约条款是什么」,它却从封面页作答——因为解约条款埋在 12 万 token 深处,过了模型真正注意的范围。这是 2026 的上下文容量鸿沟:规格书写 100 万或 1000 万,现实说可用只有 6070%,且「可用」取决于任务——单针检索在前沿模型上接近满分到标称上限;多跳/聚合在多数模型上过约 12.8 万就骤降;对分散事实的推理是最先失败的任务。本节命名各基准(NIAH、RULER、LongBench v2、MRCR、NoLiMa、HELMET、BABILong)各自测什么,教你为领域搭一个自定义针测试,并指出该报的两个数:检索有效长度与推理有效长度——后者通常只有标称窗口的 2550%。
对应原课程:Phase 5 · Lesson 28 ·
long-context-evaluation(原英文phases/05-nlp-foundations-to-advanced/28-long-context-evaluation/docs/en.md)。前置依赖:第 13 节(问答系统)、第 23 节(分块策略)。
阅读完本节,你应当能够:
你有一份 200 页合同。模型声称百万 token 上下文。你贴进去问:「解约条款是什么?」模型答了——却从封面页答,因为解约条款埋在 12 万 token 深处,过了模型真正注意的范围。
这是 2026 的上下文容量鸿沟。规格书写 100 万或 1000 万,现实说可用只有 60~70%,且「可用」取决于任务。
长上下文评估测的就是这几条轴。本节命名各基准、各自测什么,以及如何为领域搭一个自定义针测试。
💡 给你的规格书两个数:检索有效与推理有效。通常推理有效是标称窗口的 25~50%。
见 code/main.py。骨架:
def build_haystack(filler_text, needle, depth_ratio, total_tokens): if not (0.0 <= depth_ratio <= 1.0): raise ValueError(f"depth_ratio must be in [0, 1], got {depth_ratio}") if total_tokens <= 0: raise ValueError(f"total_tokens must be positive, got {total_tokens}") filler_tokens = tokenize(filler_text) needle_tokens = tokenize(needle) if not filler_tokens: raise ValueError("filler_text produced no tokens") # 重复填充文直到足够长以填满草堆主体。 body_len = max(total_tokens - len(needle_tokens), 0) while len(filler_tokens) < body_len: filler_tokens = filler_tokens + filler_tokens filler_tokens = filler_tokens[:body_len] insert_at = min(int(body_len * depth_ratio), body_len) haystack = filler_tokens[:insert_at] + needle_tokens + filler_tokens[insert_at:] return " ".join(haystack) def score_niah(model, haystack, question, expected): answer = model.complete(f"Context: {haystack}\nQ: {question}\nA:", max_tokens=50) return 1 if expected.lower() in answer.lower() else 0
扫 depth_ratio ∈ {0, 0.25, 0.5, 0.75, 1.0} × total_tokens ∈ {1k, 4k, 16k, 64k},绘热力图。那就是你目标模型的 NIAH 卡。
def build_multi_needle(filler, needles, total_tokens): depths = [0.1, 0.4, 0.7] chunks = [filler[:int(total_tokens * 0.1)]] for depth, needle in zip(depths, needles): chunks.append(needle) next_chunk = filler[int(total_tokens * depth): int(total_tokens * (depth + 0.3))] chunks.append(next_chunk) return " ".join(chunks)
像「三个魔法词分别是什么?」这样的问题要求检索全部三个。单针成功预测不了多针成功。
haystack = """X1 = 42. ... (填充) ... X2 = X1 + 10. ... (填充) ... X3 = X2 * 2.""" question = "What is X3?"
答案要求链三步赋值。前沿模型在 128k 上常掉到 50~70% 准确率。
from datasets import load_dataset longbench = load_dataset("THUDM/LongBench-v2") def eval_model_on_longbench(model, subset="single-doc-qa"): tasks = [x for x in longbench["test"] if x["task"] == subset] correct = 0 for x in tasks: answer = model.complete(x["context"] + "\n\nQ: " + x["question"], max_tokens=20) if normalize(answer) == normalize(x["answer"]): correct += 1 return correct / len(tasks)
按类别报准确率。聚合分数藏住大的任务级差异。
2026 的栈:
| 情形 | 基准 |
|---|---|
| 快速健全检查 | 自定义 NIAH,3 深度 × 3 长度 |
| 生产模型选型 | RULER(13 任务)在你目标长度 |
| 真实世界 QA 质量 | LongBench v2 单文档 QA 子集 |
| 多跳推理 | BABILong 或自定义变元追踪 |
| 对话 / 对话型 | MRCR 8 针在你目标长度 |
| 模型升级回归 | 固定的内部 NIAH + RULER 套件,每个新模型都重跑 |
💡 生产经验法则:在你目标长度上跑过 NIAH + 一个推理任务之前,绝不要信任一个上下文窗口。
保存为 outputs/skill-long-context-eval.md:
--- name: long-context-eval description: Design a long-context evaluation battery for a given model and use case. version: 1.0.0 phase: 5 lesson: 28 tags: [nlp, long-context, evaluation] --- Given a target model, target context length, and use case, output: 1. Tests. NIAH depth × length grid; RULER multi-hop; custom domain task. 2. Sampling. Depths 0, 0.25, 0.5, 0.75, 1.0 at each length. 3. Metrics. Retrieval pass rate; reasoning pass rate; time-to-first-token; cost-per-query. 4. Cutoff. Effective retrieval length (90% pass) and effective reasoning length (70% pass). Report both. 5. Regression. Fixed harness, rerun on every model upgrade, surface deltas. Refuse to trust a context window from the model card alone. Refuse NIAH-only evaluation for any multi-hop workload. Refuse vendor self-reported long-context scores as independent evidence.
下一节,我们进入全章的收尾——「对话状态跟踪」,看任务型对话系统如何用槽位与信念状态在多轮间记住用户的意图,这也是本 NLP 章的最后一节。