第 9 讲:深度研究员——SLIDERS 与长文档集合

Agentic AI · Lecture 09。个人学习讲义与配套实验,按主题整理并持续修订。

课程源码 ZIP ↓

个人整理的学习笔记,非官方讲义;课程来源与整理说明见课程介绍。配套示例未逐一运行验证。

本篇目录

对应:Stanford CS224V Fall 2026 Lecture 11(11/2 Deep Researcher)。 关于材料来源:2026 年这次课的幻灯片尚未公开。本讲依据:2025 年的幻灯片(Lam & Joshi,Question Answering on Sets of Long Documents — SLIDERS);SLIDERS 论文(Joshi、Shethia、Dao、Lam,SLIDERS: Systematic Reviews via Automated Evidence Synthesis and Reconciliation,arXiv 2604.22294,2026);课程表的描述(问题需要阅读、分析、比较一大批长文档;LLM 的上下文永远不够长;自动设计表结构、建数据库、对账合并)。幻灯片把 SLIDERS 解释为 Scalable Long-Document Integration through Decomposed Extraction and Reconciliation System,论文把它解释为 Systematic Literature Deep Evidence Reconciling System——同一个系统,2026 年的论文把它定位在”系统综述”上。 配套代码:code/lecture09/(只用 Python 标准库;05 号文件可选,需要 anthropic 包和 API 密钥) 预计阅读时间:3 小时左右(含运行代码)


0. 本讲导航

0.1 学完本讲,你应该能够

  1. 解释为什么”把文档全部塞进上下文”和”检索最相关的几块”都不能可靠地回答需要综合一大批长文档的问题。
  2. 说出”分块处理”带来的四个问题(每块里的信息怎样表示、块的边界、缺少全局上下文、怎样把各块的结果合起来),以及 SLIDERS 的对策。
  3. 描述 SLIDERS 的流程:根据问题设计表结构 → 语义分块 → 带上下文的抽取(含相关性闸门)→ 对账合并 → 用 SQL 回答。
  4. 解释对账要处理的三类问题(重复、残缺、冲突),以及”按主键分组”为什么能把比较次数从 O(n2)O(n^2) 降下来。
  5. 说明”证据表”为什么能复用,以及为什么这对系统综述、后续分析特别重要。

0.2 先修知识

知识点用在哪里最低要求
第 2 讲第 1 节深度研究智能体;“访问 / 策展 / 发现”三个层次
第 5 讲第 2 节检索(BM25、稠密检索);检索不到 = 答不出
第 6、7 讲第 3~5 节表结构、SQL、SUQL;用 LLM 处理文本、用数据库做计算
第 1 讲第 2 节多步任务的错误累积(pnp^n)

0.3 本讲地图

第1节  动机:一大批长文档里的知识
第2节  以往的做法:长上下文、训练、分块;分块的四个难题          ← 代码 01
第3节  SLIDERS(一):表结构、语义分块、带上下文的抽取           ← 代码 02
第4节  SLIDERS(二):对账合并                                  ← 代码 03
第5节  评估:论文结果与模拟实验                                 ← 代码 04
第6节  讨论与边界
第7–11节 小结、与项目的关系、练习、延伸阅读、下一讲预告

0.4 本讲的玩具世界

代码 doc_world.py 生成一批虚构的上市公司季度报告(10-Q 风格),每份约 6,000~10,000 个词(真实的 10-Q 约 10 万个 token):封面(含一大段样板文字)→ 资产负债表 → 利润表 → 附注(借款、应付账款、股东权益)→ 管理层讨论与分析(MD&A)→ 很长的、和问题无关的风险因素、法律诉讼、内部控制。里面刻意埋进了幻灯片讲到的几类困难:

困难例子
重复收入在利润表里是 “99,242”(千美元),在 MD&A 里是 “$99.24 million”
单位在别处“(in thousands, except share data)” 只写在表头
冲突附注写”已发行并流通 136,264,372 股”,MD&A 写”加权平均流通股数 132,663,979 股”(30% 的公司没有这条附注,流通股数只在资产负债表的一行里)
歧义一半的公司在资产负债表里只有合并的一行 “Accounts payable and accrued expenses”,单独的”应付账款”在附注里
残缺一半的公司没有直接写”借款总额”,只分别写了短期借款和长期借款
名字的写法封面 “BEACON ENERGY, LLC”,正文 “Beacon Energy”

关于本讲的数字:幻灯片和论文里的真实数字会注明出处;模拟实验的数字都来自 01~04 号代码的实际输出。特别注意:没有真实的 LLM——抽取器用正则表达式找数字(模拟 LLM 的阅读),再按设定的概率犯错(拿了干扰项、读错数字、看串了行、面对无关的块编一行……);长上下文 LLM 的精确度随长度和位置下降,也是设定的公式。参数都写在 sliders.py 的开头。要看的是趋势,不是绝对的数字。


1. 动机:一大批长文档里的知识

1.1 很多重要的问题要读一大批文档

幻灯片第 2 页列了一张图:简历、论文评审、项目申请、财报、PubMed 论文、基因组、药物和蛋白质的资料、新闻、社交媒体、访谈、病历、规章、临床试验……很多问题要综合每一份文档里的信息,才能做出决定、得到统计和趋势:

  • 排名(在全部文档里选出前 n 个):“哪家公司的流通股最多?”
  • 累积、统计、趋势:“这些公司里有几家亏损?平均收入是多少?”
  • 可满足性 / 合规:“哪些试验的入组条件这个病人都满足?“(第 4 讲)
  • 建知识库、发现新知识。

往年的课程项目(幻灯片第 3 页):分析 SEC 的数据做投资决策;分析保险备案;分析防灾减灾计划,寻找资助机会。以保险为例(第 4 页):气候变化大大改变了自然灾害的风险;保险受政府监管,保险公司要提交”费率备案”才能获批——而现在很多备案是先暂时批准的,因为监管机构没有足够的人手去处理这些文档。

论文从另一个角度切入:系统综述(systematic review)是医学、社会科学、政策分析、金融、法律等领域循证研究的基石——针对预先定好的研究问题,从所有符合条件的文档里收集和综合证据。整个过程(定义问题、选文档、抽取证据变量、对账、带出处和附加说明地综合)需要持续的专家判断,非常耗人力:一项基于 PROSPERO 的分析估计,完成并发表一篇系统综述平均需要 67.3 周。

1.2 第 2 讲的”深度研究”有什么不够

第 2 讲的 STORM、各家的 Deep Research 智能体,主要靠 RAG:用向量相似度检索一些段落,再综合。论文指出,这种”检索优先”的做法和系统综述不匹配:技术性的证据往往分散在许多段落和许多文档里;系统综述需要全面地追踪证据和出处,而不只是几段”语义上相似”的文字。结果,RAG 要么漏掉相关的证据,要么检索出多得处理不了的段落。


2. 以往的做法

2.1 长上下文:上下文永远不够长

LLM 的上下文窗口越来越大,“大海捞针”测试的成绩也近乎完美(幻灯片第 5 页)。为什么还不够?

1. 上下文永远不够长(幻灯片第 6 页):长文档很多,一批里的文档也很多。

  • PubMed(截至 2023 年 5 月):2,460 万篇有摘要,2,680 万篇链接到全文,1,090 万篇免费全文;2010~2019 年每年新增约 100 万条记录;3,500 万条引用;
  • SEC 每年有六七十万份报告,每份约 10 万个 token;
  • 一个州的保险备案就有几千份。

代码 01 的演示 1:虚构的季度报告平均约 7,700 个词。128K 的窗口装 10 份没问题;20 份只能看到前 84%;40 份 42%;80 份 21%。

2. 长上下文的精确度不够(幻灯片第 7 页):上下文越长,同样的任务表现越差;注意力在整个上下文窗口里并不均匀(“Lost in the Middle”,Liu 等 2023;Loong 基准,Wang 等 2024)。“大海捞针”被认为比较容易——它只要找到一根针;而且精确度和位置有关。

代码 01 的演示 2(模拟的长上下文 LLM,参数是设定的):

上下文长度开头中间结尾
1 万0.940.840.94
5 万0.840.740.84
10 万0.720.620.72
12.8 万0.650.550.65

3. 出错时既无法解释,也无从改进。幻灯片第 8 页的例子:问 “What is the accounts payable of BIOLARGO, INC.?”(同时给了六家公司的报告),GPT-4.1 回答 “$1,740,000”——那是资产负债表上 “accounts payable and accrued expenses” 那一行(第 271 行);单独的 “accounts payable” 在第 1735 行。第 9 页的例子:给四篇论文,问它们之间的引用关系,GPT 漏掉了好几条参考文献。

代码 01 的演示 3 重现了这个歧义:虚构的 COBALT PAYMENTS, CORP. 资产负债表上只有 “Accounts payable and accrued expenses | 49,340”,附注里写 “Accounts payable were $24,270 thousand”。模拟的长上下文 LLM 选错的概率从 1 万 token 的 18% 升到 12.8 万 token 的 47%。

2.2 训练:提高精确度,但还不够

幻灯片第 15 页介绍了两种”训练”的做法:

  • QwenLong-L1(Wan 等 2025):用现有的基准整理出长上下文的数据集,用强化学习逐步增加上下文的长度(基于规则的验证 + LLM 当评委)。比基础模型好,但没有超过最好的专有 / 开源模型。
  • Cartridges(Eyuboglu 等 2025):在一批文档上”训练”一个 KV 缓存(让模型就这批文档自问自答),之后用这个缓存回答新问题。但比不过把文档完整地放进上下文。

幻灯片第 64 页的结论:训练是为了提高精确度——不成功。

2.3 分块:精确度和可扩展性

分块的做法(幻灯片第 18~20 页):把长文档切成很多块;每块单独交给 LLM 处理;最后把各块的结果合起来,得到答案。它有两个好处:

  • 精确度:每次只处理一块,对局部细节的注意力更集中;
  • 可扩展性:自然地扩展到远远超出模型上下文的文档集合。

两个代表:

  • Chain of Agents(Zhang 等 2024):一个 LLM 处理一块,把”和任务相关的摘要”传给下一个 LLM(连同下一块);最后一个智能体根据最后的摘要综合答案。
  • DocETL(Shankar 等 2024):用户提供一个表示用的表结构;每块由 LLM 输出结构化的数据;用户再提示 LLM 把各块的输出归约(reduce)成答案。

2.4 分块的四个难题

已有的分块方法用 LLM 把所有块的输出综合成最终的答案(幻灯片第 21 页):输出只有几百个 token 时效果不错;有几千个块的输出时就会失败——综合用的上下文太大、不可靠。论文的说法:抽取本身并不能解决”管理证据”的问题,抽出来的记录可能很多、有噪声、重复、残缺或互相冲突,而且常常需要原文的上下文才能理解。

幻灯片第 22 页把分块的难题归纳成两组:

  1. 每一块里的信息用什么表示?
  2. 回答问题分成两步:
    • (a) 一块一块地正确抽取信息:块的边界——块可能不是自足的;缺少全局上下文——单看一块,理解可能不完整;
    • (b) 从抽出的信息里组装出正确的答案:各块是独立抽取的,组装时会遇到什么问题?用什么技术来组装?

2.5 检索也覆盖不全

代码 01 的演示 4:比较题和计数题需要读对每一份文档里的数字。

文档数长上下文:比较 / 计数题的准确率检索 top-8:覆盖到的文档比例
587%100%
1063%79%
2012%40%
4013%19%

长上下文的准确率大约是”读对一个数字的概率”的 N 次方(第 1 讲的 pnp^n),超出窗口的文档根本看不到;检索只取前 8 块,文档一多,大部分文档一块也没被检索到。论文报告的真实情况:在 BrowseComp+ 上,BM25 和 LongRAG 平均只检索到相关文档的 10.4% 和 12.5%;57% 和 49% 的问题,一份相关的文档都没检索到。


3. SLIDERS(一):表结构、语义分块、带上下文的抽取

3.1 总体思路:把文本变成数据库

SLIDERS 对四个难题的回答(幻灯片第 23 页):

难题SLIDERS 的对策
每一块里的信息用什么表示?表示成一张表里的行,表结构根据问题自动生成
块的边界:块可能不是自足的语义分块
缺少全局上下文带上下文的抽取
怎样组装答案?会遇到什么问题?发现了重复、残缺……用对账处理;最后用 SQL 组装

流程(幻灯片第 25 页):

问题 ──► 设计表结构
              │
一大批长文档 ──► 语义分块 + 带上下文的抽取 ──► 原始表(每块抽出零行或多行)
                                                   │
                                             对账合并 ──► 对账后的表 ──► 数据库
                                                                          │
                                             问题 ──► 语义解析(SUQL)──► 执行 ──► 最终答案

这又是计算思维:LLM 只做它可靠的事(读一小块、按说明抽出几个值、判断几条证据哪条可信),数据库做它擅长的事(排序、比较、计数、平均)。第 7 讲的 SUQL 让”在数据库上回答”这一步也能处理文本列。

论文把流程写成四个阶段:发现证据变量(设计表结构)→ 把证据穷尽地抽进证据表 → 证据对账 → 基于证据表综合答案。注意”穷尽”:SLIDERS 逐块处理每一份文档,而不是靠向量或关键词检索去挑——这正是它和 RAG 最大的区别。

3.2 根据问题设计表结构

LLM 根据问题和文档集合的描述生成表结构(幻灯片第 28~30 页):

  • 表:名字、说明;
  • 每一列:名字、说明、类型、单位、比例、规范化规则。

幻灯片的例子:问题 “Which company has the highest ‘Total Shares Outstanding’?” 生成的表 SharesOutstanding,说明是”每家公司财报里报告的流通股总数,规范化为报告期末的股数”;三列:company_name(str)、period_end_date(str,规范化为 YYYY-MM-DD)、total_shares_outstanding(float,单位”股”,说明里还列了常见的说法:“shares outstanding""common shares outstanding""total shares issued and outstanding”)。

为什么要规范化(第 31 页)?为了比较和聚合:统一单位、比例、数据类型,让各块独立抽出的值可以放在一起比较(论文举例:货币换算、日期格式)。

代码 02 的演示 1 打印了本讲的两张表结构(流通股数、借款)。

幻灯片第 32 页的讨论:

  • 自动设计表结构对单个问题效果很好;
  • 也可以为多个问题一起设计,摊薄抽取的成本;
  • 领域专家可以改进表结构——因为它是看得懂的;
  • 可以处理任意多的文档;用 SUQL 支持跨文档的聚合和比较。

论文的形式化:给定问题 qq 和文档的元数据 MM,生成一组证据变量 Δ(q,M)={δ1,…,δm}\Delta(q, M) = \{\delta_1, \dots, \delta_m\},每个 δ=⟨vn,d,τ,u,ν,ι⟩\delta = \langle vn, d, \tau, u, \nu, \iota \rangle:变量名、语义说明、数据类型、可选的单位、规范化规则、填写这个变量的指令。证据变量是强类型的,这样才能做选择、聚合、过滤、比较。而且不只限于结构化的数据:为了回答开放式的问题,SLIDERS 也包含自由文本的变量,保存和问题相关的全部原文摘录。

3.3 语义分块

幻灯片第 34~37 页:嵌入式检索用的块是固定大小的。对长文档问答行不行?

  • 第 1 块:没有文档标题(这是哪篇论文?);引言的最后一句被随意切断;
  • 第 2 块:没有文档标题;不知道属于哪一节;句子不完整;
  • 更糟的:表格被切开。“Net Cash Provided by Investing Activities 是多少?“——只看后半截表格,读到的是 “$977”;表头在上一块里,单位其实是”百万”。

对策:语义驱动的分块,创造出自足的块(第 38~40 页):用开源工具 Docling 把 PDF 转成 Markdown;一个基于 LLM 的标注器给每一行加行号,按页处理,用几个”技能”(翻页、记录、表格开始行、表格结束行、表格附注、章节标题行)标出结构;再把文档切成长度相近的块,约束是不能切开任何段落和表格。

代码 02 的演示 2:一份虚构财报,固定分块(每 400 词)切成 19 块,语义分块 12 块。固定分块的第 0 块在资产负债表中间结束(“Goodwill | 79,355 |”),第 1 块从 “19,975” 开始——表头在上一块里。从第 1 块单独抽取,应付账款读成了 16,636∗∗,真实值是∗∗16,636**,真实值是 **16,636,000(理由一栏写着 “unit not stated”)。语义分块把整张表格放在一块里,并记下了标题、章节和表头。

3.4 带上下文的抽取

动机(幻灯片第 42 页):脱离上下文的片段很难理解——标题、章节、版式……所以给每一块附上:文档标题、文档说明、相关的章节标题层级、页码。抽取器拿到这一块和表结构,输出 JSON:结果表里的一行(第 43 页)。

代码 02 的演示 3:30 份文档,三张表(流通股数、应付账款、净利润),四种组合:

分块上下文抽出的行归对公司值正确
固定不带20840%81%
固定带208100%81%
语义不带20850%94%
语义带208100%94%
  • 不带上下文时,利润表、附注这些块里没有公司名,抽取器只能瞎猜(或者留空)——大量的行归错了公司;
  • 固定分块即使附上了文档标题,也看不到被切走的表头——单位错了;
  • 两者都用上,两个问题都解决了。剩下 6% 的错误来自抽取器本身(拿了干扰项、读错数字),留给对账去处理。

(这里用了”公共随机数”:同一块里的同一个数字”会不会被读错”在四种组合下是一样的,所以四行之间的差别只来自分块和上下文——代码 README 记录了为什么要这样做。)

3.5 相关性闸门:LLM 喜欢编

幻灯片第 44~45 页:给四篇论文、问引用关系,表结构是”源论文、关系类型、目标论文”。抽取器生成了一条参考文献——这一块里没有,也不在给定的四篇论文里。

LLM 在两种情况下喜欢”编”:给它的文字里没有有用的信息(这在分块之后很常见——大部分块和问题无关);要求它输出一个 JSON 对象(论文:输出格式逼着模型”符合”表结构)。

对策:相关性闸门。先用一个轻量的 LLM 判断这一块相不相关:不相关就输出空,相关才交给抽取器(论文的定义:EE(qe,c,mc,Δ)EE(q_e, c, m_c, \Delta) 只在闸门 R(⋅)R(\cdot) 通过时才调用抽取器)。

代码 02 的演示 4(30 份文档、397 块,流通股数这张表):

便宜的调用贵的调用编出来的行
有闸门3971183
没有闸门039794(其中 46 行连引用也是编的)

闸门省下了约 70% 的”贵”的调用,编出来的行从 94 降到 3。

3.6 抽取时还要输出什么

为了支持后面组装答案(幻灯片第 46 页),抽取器除了按表结构输出 JSON,还要输出:

  • 原文引用(quote):这个值来自哪句话;
  • 选这个值的理由(rationale);
  • 信息是不是明确写出的(explicit)。

论文的形式化:证据表里的每一条证据 z=⟨c,mc,{eδj}⟩z = \langle c, m_c, \{e_{\delta_j}\} \rangle,每个条目 e=⟨v,p,γ⟩e = \langle v, p, \gamma \rangle——规范化之后的值、支持它的原文片段、把片段和值联系起来的理由。代码 03 的演示 1 展示了一家公司的原始行,例如:

total_shares_outstanding   154,733,966  [explicit] “; 154,733,966 shares issued and outstanding”
total_shares_outstanding   154,733,966  [explicit] “154,733,966 shares of common stock were issu…”
total_shares_outstanding   146,866,505  [weighted] “weighted average number of shares outstandin…”
total_shares_outstanding    48,744,275  [explicit] “”          ← 闸门误判之后编出来的一行,没有引用

这些附加信息就是第 4 节”该信哪一行”的依据。


4. SLIDERS(二):对账合并

4.1 为什么需要对账

各块是独立抽取的,必然带来副作用(幻灯片第 48 页):

  • 重复的信息(overlapping):同一个值在几块里都出现;
  • 残缺的信息(partial):一个值的几个组成部分分散在不同的块里;
  • 冲突的信息(conflicting):不同的块给出不同的值。

论文还强调了规模:文档很多时,证据表可能大到放不进 LLM 的上下文,或者放进去了推理也不可靠。所以对账不只是”清洗”,也是把一大张原始表压缩成可以直接回答问题的形式。

4.2 三种操作

做法(幻灯片第 49 页):对每一类问题,(1) 先让 LLM 推理出问题是什么;(2) 再用 SQL 生成对账后的表。幻灯片的例子:

类型例子SQL
重复“运营和管理费用”在第 2、8、11 块里分别是 2,979,692、2,979,692、2.97 millionSELECT DISTINCT …(去重)
残缺第 3 块和第 4 块各有净亏损的一部分SELECT SUM(net_loss), * FROM NetLoss
冲突(时间)bAbILong 基准:“Sandra is in the kitchen”(第 2 块),“Sandra is in the bathroom”(第 26 块)——Sandra 在哪?ORDER BY page_number DESC LIMIT 1(以后面的为准)
冲突(含义)第 1 块”已发行并流通 50,251,933 股”,第 8 块”加权平均流通股数 49,458,023 股”根据引用和理由:保留明确写在资产负债表里的 50,251,933

最后一个例子里,抽取时留下的理由起了决定作用:附注 11(b) 明确报告了流通股数;MD&A 给的是加权平均股数。对账的 LLM 读到这两条理由,选了前者。

4.3 按主键分组:从 O(n2)O(n^2) 到 ∑∣g∣2\sum |g|^2

论文的关键做法:如果有 nn 条证据,直接两两比较需要 O(n2)O(n^2) 次——证据表很大时做不到。借鉴数据库的键(判断哪些行描述的是同一个对象),SLIDERS 为当前问题选一组主键变量(财务问题可能是”公司 + 财年”,临床问题可能是”干预 + 人群 + 结局 + 时间点”),规范化每个键的值(解决别名、统一单位和日期……),然后按规范化之后的键分组,只在组内比较。比较次数降到 ∑gO(∣g∣2)\sum_{g} O(|g|^2)。

组内,对账智能体决定怎样处理:重复的合并;互补的整合;冲突的对照出处和理由检查;有意义的差别保留下来,而不是硬塞成一个值;还解决不了的标记为未解决。然后用 SQL 操作证据表,生成对账后的表——保留原来的出处、摘录和理由。

代码 03 的演示 3:

'BEACON ENERGY, LLC' → 键 'beacon energy'
'Beacon Energy LLC'  → 键 'beacon energy'
'Beacon Energy'      → 键 'beacon energy'

shares  :94 行;两两比较 4,371 次 → 组内比较 99 次;压缩比 3.13
results :123 行;两两比较 7,503 次 → 组内比较 180 次;压缩比 4.10

论文表 10:对账在 WikiCeleb100 和 FinQ100 上的压缩最大,分别是 1.98 倍和 4.51 倍。

4.4 不同的语料需要不同的操作

代码 03 的演示 2(30 份文档):

表原始行对账后去重合并解决冲突丢掉的行
流通股数9430320293
应付账款39300072
借款13430521543
收入和净利润1233057033

流通股数以”解决冲突”为主(明确的值 vs 加权平均),借款需要”合并”(短期 + 长期),收入和净利润以”去重”为主(利润表和 MD&A 各一次;“99,242 千美元”和”$99.24 million”只差四舍五入,算作同一个值,保留更精确的那个)。“丢掉的行”是对照出处时发现对不上的(编出来的)和不知道属于哪家公司的。

论文图 7 有同样的观察:财务和法律的语料以”解决冲突”为主;WikiCeleb100 需要更多的”合并”(同一个名人的信息分散在不同的章节);Loong 的论文语料以”去重”为主。

4.5 对照出处

本讲的对账规则按这个顺序排优先级(sliders.py 的 reconcile):和自己引用的原文对得上的 > 对不上的(读错了);明确写着的 > 干扰项(加权平均、合并的);单位明确的 > 单位不明的;出现次数多的 > 少的。

“和原文对得上”这一条很有用:一个被多读了一个 0 的数字(原文引用写着 135,647,685,值却是 1,356,476,850),在”比较流通股数”时会变成全场最大。代码 03 的演示 4 统计:30 份文档的四张表一共 390 行原始数据,有 9 行和自己引用的原文对不上。练习 4 会看到,去掉这一条检查,40 份文档的比较题准确率从 0.93 降到 0.73。但它只在出现冲突时才会被触发——只有一个出处的数字读错了,仍然会漏过去(演示 4 的失败分析)。

4.6 不对账会怎样

代码 03 的演示 4(同样的抽取结果,每家公司每一列直接取第一次抽到的值):

  • “借款最少的公司”:没有直接写借款总额的公司,不合并就没有这一列——选错了;
  • “有几家公司亏损”:标准答案 20,不对账数出 40——同一家公司的不同写法(“BEACON ENERGY, LLC” 和 “Beacon Energy”)被当成了两家。

4.7 在数据库上回答

最后,把自然语言的问题语义解析成 SQL(SUQL),在对账后的表上执行(幻灯片第 57 页):

SELECT company_name, total_shares_outstanding FROM SharesOutstanding
ORDER BY total_shares_outstanding DESC LIMIT 1;

幻灯片的例子里,三家公司分别是 50,251,933、170,000、5,934,917 股,答案是 AIM ImmunoTech Inc.。论文的说法:对账后的表可能仍然包含大量的文本摘录,所以合成答案的智能体用证据变量检索出一个有限的证据上下文,逐条检查摘录是否支持要做的推断,再生成带引用、带附加说明(缺失的信息、未解决的分歧、仍有歧义的证据)的答案。而且这张证据表还能回答后续的问题。


5. 评估

5.1 2025 年幻灯片里的初步结果

两个”长上下文问答”基准(每道题的文档都能装进 LLM 的上下文,幻灯片第 59 页):

  • FinanceBench:金融问答,150 道题,约 9.5 万个 token;
  • Loong:三个领域(金融、法律、学术论文),中英两种语言,四类问题(聚光灯、比较、聚类、推理链),1,600 道题,最长 25 万个 token。
模型做法FinanceBenchLoong
GPT-4o直接推理78.6753.58
Gemini 1.5 Pro直接推理—55.36
GPT-4.1直接推理84.0077.23
SLIDERS分块90.6778.34

幻灯片的注:“SLIDERS 能处理装不进 LLM 上下文的一大批长文档。“错误分析发现:Loong 里有好几个标注错误,FinanceBench 里也有几个;对问题的理解不同,答案也可能不同(幻灯片第 61 页)。第 62 页的例子:BIOLARGO 的应付账款,GPT 和标注的标准答案都是 1,740——都选了合并的那一行。(第 5、7 讲刚见过:评估方法本身需要验证。)

5.2 论文:超出上下文的基准

论文在三个”系统综述式”的任务上评估:

  • BrowseComp+:深度研究基准,考察能不能识别和综合分散在多份文档里的证据;
  • WikiCeleb100(新):2025 年 11 月到 2026 年 1 月浏览量最高的 100 位名人的维基百科文章(390 万 token);研究问题是”音乐、电影、内容创作、其他四个行业里,谁出道的年龄最小?“,要从全部 100 篇文章里抽出生日、出道日期和行业;另有 21 个相关的后续问题;
  • FinQ100(新):随机选的 100 家 SEC 上市公司最近的 10-Q(3,600 万 token),25 个问题;研究问题是”哪家公司的长期借款最少?“——更难,因为很多报告没有直接写,要从上下文推断。

论文表 1:

做法工作 / 推理模型BC+WCFQ
BM25– / GPT-4.120.6731.415.00
LongRAG– / GPT-4.128.6743.2028.87
GraphRAG– / GPT-4.1成本过高48.59成本过高
DocETLGPT-4.1 / GPT-4.1成本过高54.26成本过高
RLMGPT-5-mini / GPT-580.0059.8028.00
SLIDERSGPT-4.1-mini / GPT-4.190.0078.9155.22
SLIDERSQwen3.5 122B / Qwen3.5 122B–76.9260.18

(GraphRAG 和 DocETL 在超过 600 万 token 的 BC+ 和 FQ 上成本过高。RLM 是”递归语言模型”:递归地分解任务。)

三个观察:

  1. 证据越长、越分散,SLIDERS 的优势越大。在 BrowseComp+ 上比最强的基线 RLM 高 10 个点;token 数从约 600 万增加到 1,100 万,SLIDERS 一直保持在 90% 左右,RLM 波动更大、最后更低;需要 10 份以上文档的证据时,SLIDERS 仍是 100%,RLM 降到 70% 左右。
  2. 可复用的证据表支持后续分析。基线没有证据表,每个后续问题都要从头再来;SLIDERS 用同一张表回答。FinQ100 上,能跑完的基线最好是 28.87,SLIDERS 是 60.18(Qwen3.5)。用开源模型 Qwen3.5-122B-A10B 做全部组件,SLIDERS 在 WC 和 FQ 上也超过了所有基于 GPT-4.1 的基线——说明这套框架不依赖某个专有模型。
  3. 证据表越大,对账越重要(论文表 2)。在 BrowseComp+ 上,证据表能放进 LLM 的上下文,“直接把表交给答题的模型”(Direct table)得到 87.33,只比完整的系统低 2.67 个点;但在 WC 和 FQ 上表太大,去掉对账,WC 从 78.91 降到 60.50,FQ 从 55.22 降到 35.81。

5.3 论文:上下文装得下的基准

为了和只能处理上下文以内的方法比较,论文还在 FinanceBench(单份文档,≤36.3 万 token)、Loong(约 11 份文档、≤30 万 token)、Oolong(Oolong-Synth,25.6 万 token:要先给每个数据点分类,再聚合成一个全局的答案)上做了评估(论文表 3):

做法模型FBLoongOolong平均
BM25GPT-4.162.6754.3511.3242.78
直接推理(Base LM)GPT-4.182.0076.7445.5668.10
DocETLGPT-4.163.3375.0349.0062.45
Chain of AgentsGPT-4.1-mini / GPT-4.171.3054.4617.1147.62
RLMGPT-5-mini / GPT-575.3372.6451.4266.46
SLIDERSGPT-4.1-mini / GPT-4.189.6778.5764.6777.64
SLIDERSQwen3.5 122B82.1075.7068.0075.27

即使文档装得下,证据表也能提高准确率:SLIDERS 平均比最强的基线(GPT-4.1 直接推理)高 9.54 个点。提升最大的是 Oolong——每道题都要把许多局部的推理聚合成一个全局的答案,正是”每条证据都重要、而且分散”的情形。消融(论文图 6a)显示每个阶段都有贡献:例如在 Oolong 上去掉分块抽取,从 64.67 降到 40.00。

5.4 模拟实验

代码 04 在 30 个实例上比较(每个实例 10 份虚构的季度报告、5 道题;和 Loong 一样,每道题都给出全部文档):

做法聚光灯:流通股数聚光灯:应付账款比较:股数最多比较:借款最少聚合:亏损几家平均
长上下文(128K)50%57%53%40%100%60%
检索 top-860%23%0%0%0%17%
SLIDERS100%93%87%93%93%93%
− 语义分块(改用固定分块)100%47%90%73%93%81%
− 带上下文的抽取93%40%70%67%47%63%
− 相关性闸门100%97%90%93%93%95%
− 对账100%60%67%20%0%49%
  • 长上下文的”亏损几家”是 100%:模拟里读错数字只会让大小出错,不会改变正负号。真实的 LLM 在这类计数题上也会出错(Oolong 正是考这个)。
  • 检索:块里常常没有公司名、没有表头,比较题需要的十份文档覆盖不全。
  • 伤害最大的消融是”不对账”(重复、冲突、名字的不同写法都留在表里)和”不带上下文”(行归错了公司);固定分块主要伤害应付账款(表格被切开)。
  • 去掉闸门,准确率反而略高(95% 对 93%):闸门偶尔会把相关的块判成不相关(模拟里 3%);编出来的行大多在对账时因为”出处对不上”被丢掉了。闸门的价值在于省下约 70% 的”贵”的调用(第 3.5 节),以及不依赖后面那道防线。这是”纵深防御”——两道防线都挡同一类问题时,单独去掉一道看不出差别。

文档越来越多(演示 2;比较题和聚合题):

文档数约多少词长上下文检索 top-8SLIDERS− 对账
53.9 万82%10%98%47%
107.8 万73%0%95%32%
2015.7 万23%0%100%20%
4031.4 万10%0%93%17%
8063.2 万0%0%73%0%

长上下文、检索和不对账的 SLIDERS 都随文档数下降;完整的 SLIDERS 基本保持,到 80 份时降到 73%(5 个实例、15 道题里错了 4 道)——文档越多,“只出现在一处、又被读错了”的数字越可能落在关键的公司上(下面的失败分析)。

证据表的复用(演示 3):一批 40 份文档。建三张表,每张都要对 516 块各做一次便宜的闸门调用,再对一两百个相关的块做抽取;之后四个后续问题(亏损公司的平均收入、收入最高的公司、借款超过 1.5 亿的有几家、流通股数的中位数)全部答对,不需要任何新的读文档调用——只要把问题翻译成 SQL。长上下文则每个问题都要重新读 30 万个词(而窗口只有 12.8 万)。

SLIDERS 错在哪里(演示 4,150 道题里答错 10 道):在表上推理出错(SQL 写错了)6 道;只有一个出处的数字读错了 3 道;闸门漏掉了相关的块 1 道。论文的失败分析有相似的结构:BrowseComp+ 的 15 个失败里,8 个出在”在证据表上推理”,5 个是没有找到全部相关的文档;精确的计数和数值问题仍然很难——要正确地给边界情况分类、去重、规范化、再聚合。


6. 讨论与边界

6.1 什么时候 SLIDERS 不划算

论文的失败分析第一条:对较短的上下文,SLIDERS 会带来不必要的开销。在 Loong 的中文分类子集上,文档通常不到 1.6 万 token,任务是预测标签而不是综合分散的证据——证据变量、抽取、对账的好处很有限。先问问自己:问题需要综合多少份文档、多少条证据?

6.2 SLIDERS 在系统综述流程里的位置

论文强调 SLIDERS 是补充而不是替代:审阅者可以先用常规的检索、引文追踪和高召回的检索圈出一大批可能符合条件的文档,再在筛过(或部分筛过)的语料上用 SLIDERS 建证据表。这样把”可扩展的、基于检索的初筛”和”更贵的证据综合”分开。证据表是一个可审计的中间产物:审阅者可以检查抽出的摘录、修改证据变量、检查对账的决定、提出后续问题,而不用重新处理整个语料。

6.3 可解释、可改进

回到 2.1 节的第三个问题:长上下文出错时无法解释、无从改进。SLIDERS 的每一步都看得见:表结构可以改;每一行都有原文引用和理由;对账的每个决定都有记录;最后的答案来自一条 SQL。出错时可以定位到是哪一块、哪一步——这和第 4 讲”可问责”的要求一脉相承。

6.4 本讲模拟的边界

  • 抽取器是正则表达式 + 设定的错误率,不是 LLM。真实的 LLM 会犯模拟里没有的错误(例如误解表格的结构、把上一年的数字当成今年的),也能处理模拟里没有的说法。
  • 对账规则是固定的优先级;真实的 SLIDERS 用一个 LLM 智能体阅读每组证据、写代码完成对账,能处理”有意义的差别”(例如不同的研究报告了不同的效果,应该都保留并加上说明)。
  • 季度报告是虚构的、高度规整的;真实的 PDF 有扫描质量、复杂的版式、跨页的表格——这正是 Docling 和 LLM 标注器要解决的问题。

7. 本讲小结

  1. 很多重要的问题要综合一大批长文档(排名、统计、趋势、合规、系统综述)。LLM 的上下文永远不够长;即使够长,精确度也随长度和位置下降,出错时无法解释。检索只取几块,覆盖不全。训练(QwenLong-L1、Cartridges)还不能解决问题。
  2. 分块提高精确度和可扩展性,但带来四个难题:每块里的信息怎样表示、块的边界、缺少全局上下文、怎样组装答案。
  3. SLIDERS 把文本变成数据库:根据问题设计表结构(类型、单位、规范化规则);语义分块(不切开段落和表格);带上下文的抽取(标题、章节、表头;原文引用、理由、是否明确;相关性闸门挡住”编”);对账(按规范化的主键分组,组内去重、合并残缺的信息、对照出处和理由解决冲突);最后用 SQL / SUQL 回答。
  4. 论文结果:BrowseComp+ 90.00(RLM 80.00)、WikiCeleb100 78.91、FinQ100 55.2260.18;600 万到 1100 万 token 之间保持在 90% 左右;去掉对账在大表上掉 1819 个点;即使文档装得下,平均也比 GPT-4.1 直接推理高 9.54 个点。
  5. 证据表可以复用:后续问题直接查表,不用再读文档;它也是一个可审计、可修改的中间产物。

8. 与项目的关系

  • 你的问题需要综合多少份文档?如果只是一两份短文档,直接问 LLM 也许就够了;如果是几十上百份,考虑”先建表、再查询”。
  • 先设计表结构:把问题拆成需要的变量(列),写清楚类型、单位、常见的说法、规范化规则。让领域专家看一看——他们往往知道”这个数字在财报的哪里、有几种写法”。
  • 分块时不要切开表格和段落,并把文档标题、章节、表头交给抽取器。抽取时要求原文引用和理由,并加一个相关性闸门。
  • 一定要做对账,而且对账要对照出处。统计一下原始表里有多少重复、冲突、残缺——这本身就是对你的数据的一次体检。
  • 评估时检查标准答案(Loong、FinanceBench 里都发现了标注错误),把”系统错了”和”标注错了”分开。

9. 练习

练习 1(设计表结构)。问题:“和去年同期相比,哪家公司的收入增长最快?“本讲的 QuarterlyResults 表结构(收入、净利润)够用吗?需要加什么列?对账时要注意什么?

参考思路

不够:需要去年同期的收入。虚构财报的利润表有两列(“Three months ended March 31, 2024 | 2023”),所以加一列 revenue_prior_year(单位 USD,说明里写清楚”上一年同一季度,利润表的第二列”),或者把表改成”每家公司每个期间一行”、主键是(公司,期间)。增长率不要让 LLM 算,在 SQL 里算:(revenue - revenue_prior_year) / revenue_prior_year。对账时要注意:主键里要有期间,否则今年和去年的收入会被当成”冲突”;MD&A 里”收入增长了 x%“这类话也可以作为一个旁证(另一列),用来检查算出的增长率。

练习 2(动手改代码:干扰项)。把 sliders.py 里 EXTRACT["p_take_distractor"](只有加权平均股数 / 合并的应付账款时,把它当成答案的概率)改成 0 和 1,看 04 号文件演示 1 里 SLIDERS 和”不对账”在”比较:股数最多""聚光灯:应付账款”两列的变化。有什么出乎意料的地方?

参考答案

实测(30 个实例,股数最多 / 应付账款):

p_take_distractorSLIDERS不对账
077% / 93%67% / 93%
0.6(默认)87% / 93%67% / 60%
193% / 93%70% / 47%

“不对账”符合预期:干扰项拿得越多,应付账款越容易错(第一次抽到的可能是合并的那一行)。出乎意料的是 SLIDERS:干扰项拿得越多,“股数最多”反而越准。原因在本讲的对账规则:只有出现冲突(同一家公司有两个以上不同的值)时,才会对照出处检查。一个被多读了一个 0 的流通股数,如果没有别的行和它冲突,就会原样留下、变成”最多”;而加权平均股数那一行恰好制造了冲突,触发了检查,读错的值就被识破了。这说明”只在冲突时检查”是一个弱点——练习 4 和代码 README 的小实验 5 会继续讨论:对每一行都对照出处,比依赖”碰巧有冲突”可靠。

练习 3(动手改代码:块的大小)。把 fixed_chunks 的默认 size 从 400 改成 200 和 1000,运行 04 号文件演示 1 的”改用固定分块”那一行。应付账款的准确率怎样变化?那为什么不干脆用很大的块?

参考答案

实测(平均 / 应付账款):200 词:79% / 40%;400 词:81% / 47%;1000 词:92% / 93%。块越大,表格越不容易被切开,单位丢失的情况越少。但块大了有代价:(1) 每块里的无关内容多了,抽取器的注意力分散——这正是分块要解决的”长上下文精确度下降”;(2) 检索时块越大,排序越粗;(3) 无论多大,固定的边界总会在某处切开某张表格——问题没有消失,只是变少了。语义分块直接按结构切,不需要在”大”和”小”之间取舍。

练习 4(动手改代码:对照出处)。让 sliders.py 里的 quote_consistent 总是返回 True(相当于对账时不再检查”值和引用的原文对不对得上”),在 10 份文档(30 个实例)和 40 份文档(10 个实例)上比较 SLIDERS 的准确率。

参考答案

实测:10 份文档的平均准确率从 93.3% 降到 90.7%;40 份文档的比较题和聚合题从 93.3% 降到 73.3%。文档越多,越可能有某个数字被读错;在”比较”题里,一个大了十倍的读错的值会直接变成答案。对照出处是一个几乎不花成本的检查(程序就能做),却挡住了一类很致命的错误。这也解释了为什么 SLIDERS 要求抽取时必须给出原文引用:没有引用,对账就无从核对。

练习 5(思考:什么时候不用 SLIDERS)。论文说,SLIDERS 在 Loong 的中文分类子集上带来了”不必要的开销”。从成本和准确率两个角度,说说你怎样决定一个任务该用长上下文、RAG 还是 SLIDERS。

参考思路

看三件事:(1) 证据有多分散:答案只在一两处(“聚光灯”)→ RAG 或长上下文就够;要综合每一份文档(比较、计数、趋势)→ 需要穷尽地抽取;(2) 总长度:装得进窗口、而且不长 → 长上下文最简单;远超窗口 → 只能分块;(3) 会不会有后续问题:一次性的问题,建表的成本摊不薄;一个研究问题加几十个后续问题 → 证据表的复用让 SLIDERS 很划算。另外,“预测一个标签”这类任务(Loong 的分类子集)本来就不需要综合分散的证据,SLIDERS 的流程只增加了出错的环节和成本。

练习 6(思考:冲突一定要消除吗)。在系统综述里,两项研究对同一种干预报告了不同的效果。对账时应该”选一个”吗?SLIDERS 的论文怎样说?这和第 5 讲的语料库不一致有什么联系?

参考思路

不应该。要区分两种”冲突”:一种是抽取或表述造成的(读错、加权平均 vs 期末数、单位不同)——同一个事实,应该选出正确的那个;另一种是真实的分歧(不同的研究、不同的人群、不同的时间点)——两个值都对,只是条件不同。论文说,对账要”保留有意义的差别,而不是硬塞成一个值”,还解决不了的要标记为未解决,最后的答案要写出”未解决的分歧”这样的附加说明。关键是主键:如果主键里有”研究 / 人群 / 时间点”,真实的分歧就落在不同的组里,根本不会被当成冲突。第 5 讲的 CLAIRE 也是同样的态度:维基百科内部的矛盾,回答时应该说明分歧,而不是悄悄选一个。


10. 延伸阅读

课程相关

  • Joshi、Shethia、Dao、Lam. SLIDERS: Systematic Reviews via Automated Evidence Synthesis and Reconciliation. arXiv 2604.22294, 2026. 代码:github.com/stanford-oval/sliders;网站:sliders.genie.stanford.edu
  • Liu 等. Lost in the Middle: How Language Models Use Long Contexts. TACL 2024.
  • Wang 等. Leave No Document Behind: Benchmarking Long-Context LLMs with Extended Multi-Doc QA(Loong). EMNLP 2024.
  • Islam 等. FinanceBench: A New Benchmark for Financial Question Answering. 2023.

分块与长上下文

  • Zhang 等. Chain of Agents: Large Language Models Collaborating on Long-Context Tasks. NeurIPS 2024.
  • Shankar 等. DocETL: Agentic Query Rewriting and Evaluation for Complex Document Processing. 2024.
  • Wan 等. QwenLong-L1: Towards Long-Context Large Reasoning Models with Reinforcement Learning. 2025.
  • Eyuboglu 等. Cartridges: Lightweight and General-Purpose Long Context Representations via Self-Study. 2025.
  • Docling(IBM 的开源文档转换工具):github.com/docling-project/docling

下一讲

  • Joshi 等. Controllable and Reliable Knowledge-Intensive Task-Oriented Conversational Agents with Declarative Genie Worksheets. ACL 2025. arXiv 2407.05674.

11. 下一讲预告

第 5~9 讲的智能体都在回答问题:从文本、数据库、知识图谱、一大批文档里找答案。很多真实的应用还要完成任务:订餐厅、提交工单、选课、开账户——要向用户收集信息、遵守规则、在合适的时候执行有副作用的动作。第 10 讲讲 Genie Worksheet:

  • 为什么只给 LLM 一堆可以调用的函数(“函数调用”)不够:加拿大航空的聊天机器人承诺了不存在的折扣、Cursor 的客服编造了一条政策;
  • 对话树、对话状态机这些传统做法为什么太死板;
  • Genie Worksheet:一种声明式的规格语言——开发者只写”愉快的路径”(像填网页表单),运行时系统处理各种”不愉快的路径”(用户插话提问、改主意、拒绝回答);形式化的对话状态;LLM 只负责语义解析和生成回复,下一步做什么由程序决定;
  • 真实用户的评估:任务完成率从 21.8% 提高到 82.8%。
← 返回课程目录