AutoIndex:面向检索的学习式文档表示程序 AutoIndex: Learning Representation Programs for Retrieval
用智能体搜索可执行的文档表示程序,固定BM25下8个检索任务召回率平均提升8.4%
前置知识
BM25 与 MaxP 聚合
BM25 是基于词频 TF、逆文档频率 IDF 与文档长度归一化的经典稀疏检索打分函数,本文固定使用 bm25s 库($k_1=1.5, b=0.75$,Lucene 实现)。MaxP 聚合指把一篇文档所有索引块的得分取最大值作为文档得分:$S_\theta(q,d)=\max_{c\in f_\theta(d)} R(q,c)$,即任何一个块命中即可代表整篇文档参与排序。
论文中检索器、排序规则和索引后端全部冻结,所有性能提升都必须通过改变块的内容与组织、经由这两个固定机制产生。不理解 BM25 对分词、长度、词频的敏感性,就无法理解学到的程序(如 LaTeX 剥离、字段复重)为什么有效。
Recall@100 与 nDCG@10
Recall@100 衡量 gold 文档是否出现在检索结果 top-100 中,反映关键证据有没有被找到;nDCG@10 衡量 gold 文档在 top-10 中的排序位置质量,对位置折损敏感。本文的优化目标 $J(\theta)$ 取验证集 Recall@100,nDCG@10 作为参考指标。
论文全部主表、消融和迭代曲线都围绕这两个指标展开,且二者偶有冲突(如 TipOfTongue 召回上升但 nDCG@10 下降 3.5%),是理解实验结论和局限的关键。
检索增强生成(RAG)
RAG 先用检索器从外部语料中找相关文档,再交给 LLM 阅读并生成答案。检索质量是整条流水线的上限:漏掉的证据无法在生成阶段恢复,因此召回率对下游问答是主导性信号。
这是作者选择 Recall@100 而非 nDCG@10 作为优化目标的核心理由——推理器可以从排序瑕疵中恢复,却无法凭空造出缺失的证据;也界定了本文成果的落地场景。
LLM 智能体与程序合成
LLM 智能体是能调用工具、多步推理并产出可执行产物的模型系统;程序合成指让模型生成满足目标函数的代码,配合沙箱执行和客观评测指标形成可验证的反馈回路,只保留确实改进指标的候选。
AutoIndex 本质上就是两个智能体驱动的迭代程序搜索:分析代理用只读工具诊断检索失败,代码代理生成候选 Preprocessor 类,候选经真实建索引与评测后被筛选。
文档切块与索引增强
切块把长文档分成固定长度(如 512 BERT token)的单元供索引;索引增强方法(如 Doc2Query 生成扩展查询、添加摘要或重写)在建索引前改写文档以改善词面匹配。统一切块可能膨胀候选池、偏移 IDF,反而损害检索。
它们是本文对比的基线和要替代的手工预处理空间。理解其失效模式(CRUMB 统一切分语料使 LegalQA 的 Recall@100 从全文 55.1 跌至 22.4)是把握论文动机的前提。
研究动机
构建检索系统(尤其 RAG 流水线)时,文档必须先被表示成可索引单元——文本块、附加上下文、归一化字段、元数据等,这些选择直接决定哪些词面线索被保留、每个单元携带多少上下文。但现有系统普遍把这一步当作静态基础设施:人工设定 chunk 大小、重叠窗口、归一化规则和元数据模板后便不再优化。检索模型研究专注于改进匹配函数(稀疏、稠密、混合、late-interaction),RAG 优化方法搜索检索器、重排序器与提示词的组合,二者都没有把语料表示本身当作学习对象。代价在 CRUMB 基准上清晰可见:固定 BM25 下 CodeRetrieval 的 Recall@100 仅 4.7%,TheoremRetrieval 仅 8.5%,SetOpEntity 仅 25.7%;LaTeX 密集文档中重复的数学标记会膨胀块长、稀释真正用于匹配的自然语言词;而 CRUMB 官方统一的 512-token 切分语料反而大幅掉点,LegalQA 从全文的 55.1 跌到 22.4,TipOfTongue 从 25.0 跌到 5.8,说明一刀切的预处理无法适配异构任务。
本文的目标是本文的目标是把文档表示从手工预处理升级为一个显式的、可自动优化的目标:给定语料、种子验证查询和一个固定不变的检索器(BM25),自动搜索可执行的表示程序——即把原始文档映射为索引单元的 Python 代码,使验证集检索质量最大化。约束条件非常严格:检索器、排序规则(MaxP)和索引后端全部冻结,不微调检索模型、不更新嵌入、不使用任何在线反馈;学习到的程序只在建索引阶段执行一次,线上检索时不再调用 LLM。这样任何性能差异都可干净地归因于表示程序本身。作者希望证明索引应当作为独立的优化目标,并展示该优化能在 CRUMB 的 8 个异构任务上全面超越静态全文基线,其中平均 Recall@100 相对提升 8.4%。
与已有工作不同的是,本文的独特切入是把检索索引视为代码优化问题。与 Doc2Query、RL-Index、Document Optimization 等索引增强方法学习某个固定类型的变换模型(查询生成器或文档重写器)不同,AutoIndex 搜索的是完整的可执行程序空间,可以对文档做切片、清洗、复重、重组,表达力严格更大。与用 LLM 逐文档做语义切分的方法相比,AutoIndex 避免了每篇文档一次 LLM 调用的高昂成本:LLM 只出现在离线搜索阶段,产出的代码上线后零模型开销。与 RAG 流水线优化(搜索检索器/重排器/提示词组合)相比,它把优化对象换成检索之前的表示程序,并在检索器固定的前提下隔离出表示这一单一变量,使因果归因干净可信。此外,通过失败诊断驱动的迭代程序搜索,它把自适应切分从网格调参升级为有证据、有历史约束、以真实索引评测为反馈的系统化搜索。
核心方法
直觉上,AutoIndex 像一位自动化检索工程师:先诊断当前索引在哪些验证查询上失败、为何失败,再修改预处理代码,重建索引、跑验证集,只保留变好的版本,如此反复五轮。形式化地,设 $\theta$ 为表示程序,$f_\theta$ 为文档到索引单元的映射 $f_\theta(d)=\{c_1,\dots,c_k\}$,每单元保留源文档标识符;固定检索器 $R$ 对单元打分,MaxP 聚合到文档级 $S_\theta(q,d)=\max_{c\in f_\theta(d)} R(q,c)$。目标 $J(\theta)$ 取验证集 Recall@100,是黑盒:候选只能经执行 $f_\theta$、重建索引、评测来评估。每轮执行更新策略 $\theta^{(t+1)}=\pi(\theta^{(t)}, H^{(t)}, s^{(t)})$,$s^{(t)}$ 为诊断摘要,$H^{(t)}$ 为记录已评估程序及 $\Delta J$ 的搜索历史。配置:5 轮迭代、每轮 $N=4$ 候选、阈值 $\Delta J \ge 10^{-5}$、超时 15 分钟;骨干为 qwen3-coder(3 种子)与 Claude Sonnet 4.6(2 种子)。
核心创新是三点耦合。第一,把表示定义为代码而非配置:块数量、清洗规则、字段复重、文档重组全部由程序决定,搜索空间远大于 chunk 大小等超参网格。第二,诊断与生成分离的双代理设计:分析代理持有一套只读工具 $\mathcal{T}_A=\{\text{bm25\_retrieve}, \text{read\_file}, \text{grep\_search}\}$,把候选查询分入锚点(Anchors)、召回违例(Recall Violations)、小边际正例(Small-Margin Positives)三类各 5 条,用具体检索行为产出有证据的结构化摘要;代码代理只消费摘要与历史,上下文不被长文档污染——这与早期单代理只看聚合指标时只能瞎猜、假设偏向通用预处理技巧形成鲜明对照。第三,搜索历史 $H^{(t)}$ 充当软先验:代码代理能记起上一轮全局样板清理曾导致回归,从而转向窄的、阈值门控的手术式修改。选出的程序在索引时执行,检索期零 LLM 开销,且由于检索器冻结,收益可完全归因于表示。
方法步骤详情
流程分六步。①准备:每个 split 查询按 1:2 划分验证/评测集,检索器固定为 bm25s v0.2.14($k_1=1.5, b=0.75$,Lucene),初始程序为全文基线。②分析诊断:从验证集抽取分层查询(锚点=旧程序命中而当前不能;召回违例=当前不在 top-$k$;小边际正例=在 top-$k$ 不在 top-1,$\bar{k}=1$,每类 5 条),分析代理用 bm25_retrieve 查看索引返回块、read_file 读原文、grep_search 定位术语,最多 5 步,输出摘要 $s^{(t)}$。③候选生成:代码代理以 $\theta^{(t)}, s^{(t)}, H^{(t)}$ 为条件一次生成 $N=4$ 个完整 Preprocessor 类,doc_id 逐字保留。④评估:候选在沙箱执行(超时 15 分钟)建新索引,计算 $\Delta J_i = J(\theta_i^{(t+1)})-J(\theta^{(t)})$,保留 $\Delta J_i \ge 10^{-5}$ 者为 $A^{(t)}$。⑤选择:若 $|A^{(t)}|>1$,LLM 尝试合成融合程序,仅当胜过最佳个体才采纳;$A^{(t)}=\emptyset$ 则 incumbent 不变。⑥收尾:5 轮后最优程序在评测集上只评一次。
技术新颖性
技术新颖性体现在四个方面。其一,可验证程序搜索的对象从检索器或流水线组件换成检索之前的表示程序,评测必须真实重建索引,优化信号不可伪造,这在 agentic program optimization 文献中是新的应用对象。其二,分析代理的证据链设计:强制同时调查失败与成功案例(避免破坏现有有效信号)、要求每个失败模式至少 3 个具体例子、警惕只影响 1 条验证查询的噪声假设,把失败分析从自由发挥变成受控诊断。其三,学习到的行为本身非平凡:TipOfTongue 上把 Plot 段重复 3 次、Cast 段重复 2 次的块内字段复重,实质是用表示层手段近似 BM25F 的字段加权思想而不修改打分函数;StackExchange 上 LaTeX 剥离仅在文档含超过 10 处 LaTeX 片段时激活,这一阈值门控直接源自搜索历史中全局清理曾致回归的教训。其四,候选合成机制允许把多个通过验证的变换合并成一个程序,且只有真正更优才采纳,避免盲目堆叠。
实验结果
主实验(qwen3-coder、开启搜索历史、5 轮、3 种子):8/8 任务 Recall@100 全部提升,平均 30.1→32.6(相对 +8.4%),nDCG@10 23.4→25.3(+8.3%);最大增益为 SetOpEntity(R@100 +30.5%,25.7→33.5;nDCG@10 +43.6%)、LegalQA(+10.4%/+42.5%)、TheoremRetrieval(+19.2%/+27.3%);仅 TipOfTongue nDCG@10 −3.5%、PaperRetrieval nDCG@10 −0.7% 回退。对比 CRUMB 统一 512-token 切分语料:LegalQA +171.8%、TipOfTongue +361.4%。换用 Claude Sonnet 4.6(2 种子)趋势一致:7/8 split 正向,平均 +6.8% R@100、+6.6% nDCG@10,TheoremRetrieval nDCG@10 +69.9%。消融(Table 3):完整版 8/8 正向;仅 1 轮迭代 3/8;去搜索历史 5/8;去分析代理 6/8 但幅度缩水。初步稠密实验:StackExchange 上复用学到的表示使 Qwen3-Embedding-0.6B 的 R@100 从 0.7391 升至 0.8741(+18.3%)。成本:每运行约 41.3 万/34.4 万 token,LLM 墙钟约 754s/488s(Sonnet/qwen3-coder)。
查看结构化数据
| 任务 | 指标 | 本文 | 基线 | 提升 |
|---|---|---|---|---|
| CRUMB 8 任务平均(qwen3-coder) | Recall@100 | 32.6 | 30.1(BM25 全文基线) | +8.4%(相对提升,8/8 任务全部正向) |
| CRUMB 8 任务平均(qwen3-coder) | nDCG@10 | 25.3 | 23.4(BM25 全文基线) | +8.3%(6/8 任务正向) |
| SetOpEntity | Recall@100 | 33.5 ± 5.8 | 25.7(BM25 全文) | +30.5%(全文最大召回增益) |
| LegalQA | nDCG@10 | 23.4 ± 8.3 | 16.4(BM25 全文) | +42.5%(最大 nDCG 增益) |
| TipOfTongue(对比 CRUMB 统一 512-token 切分) | Recall@100 | 26.7 ± 1.1 | 5.8(Passage Corpus) | +361.4% |
| TheoremRetrieval(Claude Sonnet 4.6 骨干) | nDCG@10 | 0.9(单种子) | 0.5(BM25 全文) | +69.9% |
| CRUMB 8 任务平均(Claude Sonnet 4.6 骨干) | Recall@100 | 32.1 | 30.1(BM25 全文) | +6.8%(7/8 split 正向) |
| StackExchange 稠密检索(Qwen3-Embedding-0.6B) | Recall@100 | 0.8741 | 0.7391(复用前) | +18.3%(表示程序跨检索器迁移的初步证据) |
局限与改进
作者承认的局限:优化目标仅验证 Recall@100 且检索器固定为 BM25,迭代预算只有 5 轮、种子仅 2-3 个,收益收敛的可靠性未知;召回与 nDCG、延迟、索引体积、预处理成本之间如何权衡未探索;与稠密、混合、learned sparse、late-interaction、重排序系统的交互仅有一个单 split 的初步实验。我补充几点观察:其一,若干 split 的验证集极小(PaperRetrieval 26 条、TheoremRetrieval 25 条、StackExchange 39 条),$\Delta J \ge 10^{-5}$ 的接受阈值在小样本下缺乏统计意义,选中程序可能只是拟合了验证噪声;其二,学到的程序包含语料特定硬编码(如 TipOfTongue 程序写死英文段名 'Plot'/'Cast'),换语言或换域即失效,泛化性存疑;其三,每个候选都要全量重建索引并评测 10,000 候选块召回,语料规模增大后开销线性上涨;其四,TipOfTongue nDCG@10 下降 3.5% 说明纯召回目标会牺牲排序质量,对重排序敏感的场景需谨慎。
独立分析的弱点
独立分析出的弱点及改进方向:(1) 单指标选择(纯 Recall@100)导致 TipOfTongue nDCG@10 下降 3.5%——可改为多目标验收,例如要求 nDCG 降幅不超过 $\epsilon$ 或用帕累托支配关系筛选候选;(2) 小验证集上的阈值接受在统计上脆弱——可引入 bootstrap 置信区间或序贯显著性检验,仅当提升显著才采纳;(3) 候选评估必须重建全量索引,扩展性差——可先在采样子语料上粗筛(论文脚注已提及但未实现),或用 Hyperband 式早停逐级放大评估预算;(4) 生成程序存在域硬编码与正则脆弱性(LaTeX 剥离正则可能误伤合法的 $ 数学内容)——可引入程序不变式检查与固定回归测试集;(5) 分析代理最多 5 步工具调用,可能漏掉长尾失败模式——可按查询簇自适应分配诊断预算;(6) 搜索仅在 5 轮、每轮 4 候选的极小预算下进行,与网格搜索、贝叶斯优化等经典黑盒优化方法的公平对比缺失,无法判断智能体搜索的真实相对效率。
未来方向
作者提出的方向包括:程序迁移,把学到的表示程序直接应用于未见数据集;自适应程序,让程序在新语料上先做轻量校准再建索引;优化器迁移,把 AutoIndex 流程先调优后冻结,跨多数据集多领域评测;以及更系统的稠密、混合、learned sparse、late-interaction 与重排序评测和预算感知的近似评估策略。基于本文成果还可延伸:把表示程序与 BM25 超参($k_1, b$)联合优化,检验表示与匹配函数是否存在协同增益;面向下游 RAG 端到端指标(答案质量、幻觉率)而非检索中间指标设定目标函数;学习跨任务共享的通用表示算子库,使新语料只需少量组合搜索即可起步;在目标函数中加入索引体积与建索引延迟正则,逼近工业部署约束;以及把搜索历史 $H^{(t)}$ 升级为可泛化的经验库,支持跨语料检索历史失败模式、加速新任务收敛。
复现评估
复现条件较好:代码已在 github.com/auto-index/autoindex 开源,query_splits.json 公开,CRUMB 基准可下载。复现细节充分:附录 A.2 给出关键实现(bm25s v0.2.14、$k_1=1.5$、$b=0.75$、Lucene、MaxP 聚合、每查询 10,000 候选块、doc_id 运行时哈希防作弊),A.4 完整放出两个代理的最终提示词,A.5 列出各 split 查询划分(如 legal_qa 2284/4569、paper_retrieval 26/53),A.6 附带两个生成程序的完整源码。算力适中:单次运行约 34-41 万 LLM token、LLM 墙钟 488-754 秒,另加 5 轮 × 4 候选的索引重建与评测时间;需要 qwen3-coder 或 Claude Sonnet 4.6 的 API 访问。难点在于按附录重建工程脚手架(沙箱执行、分层查询采样、MaxP 评测协议);种子仅 2-3 个且部分 split 方差较大(LegalQA ±6.0),复现数值可能波动,总体评估为中等工作难度。
论文图表
nDCG@10 主结果表:平均 23.4→25.3(+8.3%),LegalQA +42.5%、SetOpEntity +43.6%、TheoremRetrieval +27.3%,但 TipOfTongue −3.5%、PaperRetrieval −0.7% 出现小幅回退。选择过程只看验证 Recall@100。
它与 Table 1 互补,揭示单目标优化的代价:排序质量在个别任务上被牺牲。理解这张表才能完整评估方法的收益边界,也直接引出局限性讨论。