当前位置: 首页 » 资讯 » 科技头条 » 正文

伊利诺伊大学领导的研究团队让问答系统聪明了一大截

IP属地 中国·北京 科技行者 时间:2026-05-20 18:29:02


这项由伊利诺伊大学厄巴纳-香槟分校、香港科技大学和德克萨斯农工大学联合开展的研究,于2026年5月发表,论文编号为arXiv:2605.12975v1,研究名称为《PyRAG:面向检索增强生成的可执行多跳推理》。有兴趣深入了解的读者可以通过该编号在arXiv上查询完整论文。

**一个你可能没意识到的日常难题**

你有没有遇到过这样的情况:打开手机里的智能问答助手,问了一个稍微复杂一点的问题,比如"贝多芬和莫扎特谁更长寿",结果它要么给你一堆模糊的废话,要么直接答错?这背后有一个很多人不知道的技术挑战。

现代AI问答系统有一个叫做"检索增强生成"(Retrieval-Augmented Generation,简称RAG)的主流技术路线,意思就是:AI不只靠自己"脑子里"的知识回答,还会先去外部文档库里搜一搜,然后根据搜到的资料来回答。这个思路很聪明,就像你考试前可以查资料一样。对于简单的问题,这套流程表现得相当不错。

但麻烦在于,现实中有大量问题需要"多步推理",也就是说,要先找到A,才能去找B,再把A和B结合起来才能得出答案。比如"贝多芬比莫扎特大多少岁"这个问题,你得先查贝多芬的生年,再查莫扎特的生年,最后做一个减法——三个步骤缺一不可。这类问题叫做"多跳问题",意思是要在信息之间"跳好几步"才能到达终点。

现有的系统在处理这类多跳问题时,就像一个学生边想边写作文,中途容易跑偏、忘了之前写了什么、或者把"亨利二世"和"约翰·威廉·亨利二世"搞混——结果一步走错,后面全乱。这项研究的核心贡献,就是给这个问题找到了一个出人意料又相当优雅的解决方案:让AI用写程序的方式来思考和解决问题。

**一、为什么"边想边说"不靠谱:现有方法的根本缺陷**

现在主流的多跳问答系统,主要靠一种叫"思维链"(Chain-of-Thought)的技术,大概意思是让AI模型一步一步地把推理过程用自然语言写出来,就像做数学题时把演算过程全部写在纸上。另一类方法是"搜索智能体"(Search Agent),它让AI一边思考一边搜索,反复迭代,直到找到答案。

这两种方法看起来挺合理,但有三个致命弱点。

第一个弱点是"中间结果藏在文字里"。当AI用自然语言推理时,它找到的中间信息只是文字叙述的一部分,没有被明确地"存起来"。这就好比你做一道复杂的数学题,把所有演算步骤全部写成一段话,而不是用等号一步一步列式。到了后面,你很难说清楚"x等于几",因为它淹没在文字里了。

第二个弱点是"搜索关键词容易跑偏"。当AI需要根据前一步的结果来搜索下一步时,它生成的搜索词常常出现偏差。研究团队在论文中举了一个经典例子:系统本来应该搜索"约翰·威廉·亨利二世"的出生日期,结果生成了"英格兰亨利二世"作为搜索词,完全找错了人。这种偏移在自然语言推理中几乎不可避免,因为模型很难保证每一次都精确引用上一步的具体信息。

第三个弱点是"自我检查的人和出错的人是同一个"。当AI推理出错时,负责发现错误的还是AI自己,这就像让一个粗心的学生自己批改自己的卷子,往往会把错误也判成对的。现有系统的"自我反思"机制依赖的是模型的主观判断,没有任何客观的外部验证,可靠性相当有限。

这三个问题归根结底,都源于一个根本性的错位:多跳问答本质上是一种一步一步的计算过程,但现有方法却强迫AI用自由流动的自然语言来表达这种结构性很强的计算,就像让你用作文的形式来描述一个程序的执行过程,既费力又容易出错。

**二、灵感来自程序员的思维方式:PyRAG框架的核心思想**

研究团队在观察这个问题时,有一个颇为关键的发现:多跳问答跟写程序有着惊人的相似性。一个程序是怎么运行的?它把一个大任务分解成若干小步骤,每一步的结果用变量存下来,后续步骤可以直接引用前面存的变量,最终汇总出答案。这不就是多跳推理应该做的事情吗?

更重要的是,有一类专门用于写代码的AI模型,它们被训练来维护变量、控制程序流程、保证每一步的输入输出都严格对应。这类模型的"思维方式"天然契合多跳推理的需求。

基于这个观察,研究团队提出了PyRAG框架。PyRAG的核心主张是:与其让AI用自然语言"讲述"推理过程,不如让AI"写出"一个真正可以被计算机运行的Python程序,然后实际执行这个程序,用执行结果作为答案。

这个思路一旦确立,很多原本棘手的问题就迎刃而解了。中间结果不再淹没在文字里,而是以变量的形式明确存储,随时可以引用。搜索词不会跑偏,因为程序里写的就是f"当{director}出生时"——直接引用了前面步骤存储的确切值。错误不再靠AI自己来发现,而是由计算机的编译器和运行环境来检测:程序出了语法错误,机器会直接报告"第3行有语法错误",这是一个客观、确定、无争议的反馈信号,远比AI自己猜"我好像哪里说错了"要可靠得多。

**三、三个角色分工合作:PyRAG的具体工作流程**

PyRAG内部由三个相互配合的"智能代理"组成,可以把它们理解为一个小型团队里的三个不同角色。

第一个角色叫做"分解代理",负责把原始问题拆解成若干个独立的小问题。比如对于"谁更老,杰德·霍耶还是约翰·威廉·亨利二世"这个问题,分解代理会把它拆成"杰德·霍耶是什么时候出生的"和"约翰·威廉·亨利二世是什么时候出生的"两个子问题。每个子问题都是可以单独通过一次搜索来回答的简单问题,这是整个流程的基础。

第二个角色叫做"规划代理",这是整个框架的核心。它接收原始问题和子问题列表,然后生成一段完整的Python代码。这段代码调用两个工具函数:一个是retrieve(搜索),负责从文档库里取回相关资料;另一个是answer(回答),负责根据取回的资料给出简短答案。规划代理生成的代码会把每一步的答案存进一个变量,下一步搜索时直接使用这个变量的值,从根本上杜绝了"关键词跑偏"的问题。

第三个角色叫做"回答代理",它每次被调用时,拿到一个具体的子问题和相关文档,输出一个简短的回答,比如"1973年12月7日"。这个角色的职责单一,专注于从给定的文档中提取信息,不需要同时处理多步骤的推理。

三个代理的分工使得整个推理过程结构清晰、各司其职。当Python程序真正被执行时,系统会一行一行地运行代码,每次搜索和回答都留下明确的记录,最终汇总出答案。整个过程像一本账本,每一笔都清清楚楚。

**四、两个"自我修复"机制:让系统在出错时自动纠正**

PyRAG最令人称道的地方之一,是它不需要额外训练,就能实现两种自动纠错机制,这两种机制都直接源于"执行程序"这个设计本身。

第一种叫做"编译器驱动的自我修复"。当规划代理生成的Python代码出现语法错误或者运行时错误时,Python解释器会给出具体的错误信息,比如"第3行语法错误:无效的语法"或者"第7行NameError:变量docs1未定义"。这些错误信息是精确的、客观的、机器生成的,不含任何主观猜测的成分。规划代理拿到这个错误信息后,可以针对性地修改代码,然后重新执行,最多尝试三次。这个过程类似于程序员调试代码时的工作流:看报错→改代码→再运行。整个纠错循环不需要任何额外的训练,只需要让错误信号从执行环境流回到规划代理即可。

第二种叫做"执行驱动的自适应检索"。在某些步骤中,回答代理可能因为搜回来的文档不够,无法给出确定的答案,这时它会输出"unknown"(未知)或者"cannot answer"(无法回答)这样的特定词语,相当于一个明确的"我没找到"信号。系统检测到这个信号后,会自动把这一步的搜索范围扩大,将搜索返回的文档数量从默认的5篇增加到10篇,然后重新执行这一步的搜索和回答。换句话说,系统发现证据不足时,会主动扩大搜索范围,而不是稀里糊涂地把"未知"当成真实答案传递下去。

这两种机制的共同特点是:它们都依赖于程序执行过程中产生的客观信号,而不是依赖AI模型主观地"感觉自己是否答对了"。这一点在可靠性上有质的差别。

**五、实验验证:五个基准测试的全面评估**

为了验证PyRAG的效果,研究团队在五个被广泛使用的问答基准数据集上进行了全面测试,分别是PopQA、HotpotQA、2WikiMultihopQA、MuSiQue和Bamboogle。这五个数据集覆盖了从简单单跳问题到复杂多跳问题的各种类型,其中后三个专门设计用来测试系统的多步推理能力。评估指标使用的是"精确匹配率"(Exact Match,简称EM),意思是预测答案必须和标准答案完全匹配才算正确,这是一个相当严格的评判标准。

研究团队把测试分为两种设置。第一种是"无训练"设置,也就是不对模型做任何额外训练,直接使用现成的预训练模型来运行PyRAG。在这种设置下,以Qwen2.5-7B-Instruct模型为基础,PyRAG的平均精确匹配率达到了30.8%,比最基础的单步RAG方法提升了11.8个百分点。在Bamboogle这个专门测试组合推理能力的数据集上,提升幅度高达25.5个百分点,从16%跳升到41.5%。在另一个多跳测试集2WikiMultihopQA上,提升了14.5个百分点。这说明PyRAG的优势在越复杂的多跳场景中越明显。当换用更大的Qwen2.5-72B-Instruct模型时,PyRAG的平均精确匹配率进一步提升到40.9%,在Bamboogle上的绝对提升达到23.9个百分点。

第二种是"强化学习训练"设置,研究团队还用强化学习的方式进一步微调了PyRAG,得到PyRAG-RL版本。在Qwen2.5-7B模型上,PyRAG-RL达到了39.2%的平均精确匹配率,在所有7B规模的模型中表现最佳或并列最佳。在2WikiMQA上达到49.4%,在Bamboogle上达到46.1%,均是同规模模型中的最高分。此外,研究团队还在Qwen3-4B和LLaMA-3.1-8B两种不同的模型架构上验证了PyRAG-RL的效果,结果一致显示出相比直接使用强化学习训练的普通RAG方法,PyRAG-RL分别提升了10.9和11.9个百分点,说明PyRAG的结构化规划设计确实能稳定地带来性能提升,不依赖于特定的模型架构。

**六、拆解实验:每个零件贡献了多少**

研究团队还设计了一组消融实验,目的是搞清楚PyRAG的性能提升究竟来自哪里,每个设计决策各自贡献了多少。

实验从最基础的单步RAG出发,依次加入分解、规划、执行三个环节,观察每次添加新组件后性能的变化。结果非常清晰:仅仅加入"问题分解"这一步,就能在HotpotQA等数据集上带来小幅但稳定的提升,说明把复杂问题拆成小问题本身就是有意义的。在此基础上加入"结构化规划"(即生成程序,但还不实际执行),性能进一步提升,说明把推理步骤组织成有明确顺序和依赖关系的计划,即使只是作为一种提示结构,也有帮助。而最大的跳跃发生在加入"实际执行"这一步之后,性能再次显著提升。这说明真正让Python程序运行起来,把中间结果实实在在地计算和存储,是整个框架中最关键的一个环节。

另一组有趣的对比实验研究了模型类型的影响。研究团队分别用普通的指令微调模型和专门的代码模型来充当规划代理,在普通RAG框架下做对比,发现两种模型的表现几乎没有差别——代码模型并不比普通模型更擅长做普通RAG。但换到PyRAG框架下,代码模型的优势就显现出来了,尤其在难度较高的多跳数据集上,代码模型比普通模型高出数个百分点。这个发现说明一个很重要的道理:工具的优势只有在合适的使用方式下才能发挥出来。代码模型擅长的是程序化推理,如果让它去做自由形式的文字推理,它的特长就被浪费了;只有在需要它真正写程序的场景下,它的能力才能充分体现。这意味着模型能力和推理框架必须配套设计,不能割裂来看。

**七、效率与失败:系统的代价和短板在哪里**

当然,PyRAG并不是没有代价的。研究团队也坦诚地分析了系统的效率和失败模式。

在效率方面,研究团队统计了处理一个问题平均需要调用多少次大语言模型。最简单的单步RAG每个问题只需要一次调用,而Search-R1这类迭代式搜索代理平均需要约2.8次调用。PyRAG平均需要3.7次调用,其中分解和规划被合并为一次调用,其余是各子问题的回答调用,加上约5%的情况触发编译器自我修复、约20%的情况触发自适应扩大检索范围。PyRAG-RL版本则降到了平均3.1次调用,因为经过强化学习训练后的模型生成的计划更准确,需要修复和扩充的情况更少。研究团队认为这种调用次数的增加是合理的代价,因为每次调用都有明确的分工,整体的"准确率换调用次数"的性价比优于无结构的迭代式搜索。

在失败模式方面,研究团队手工分析了100个在HotpotQA上答错的案例,得出了几个重要结论。约一半的失败案例根源在于检索系统没有找到正确的文档,也就是说,即使PyRAG的推理框架没有问题,检索器也没能把正确资料取回来——这是整个系统中最大的单一瓶颈,而且这个问题不在PyRAG的设计范畴内,需要改进检索技术本身来解决。第二大失败原因是"中间错误传播",一个子步骤给出了不确定的答案,后续步骤直接把这个不确定的答案当成真实信息继续使用,导致错误像滚雪球一样越滚越大。第三类是回答代理拒绝回答,即使程序执行成功,最终的汇总步骤也没能给出答案。而真正由程序本身出错导致的失败只占约5%,说明规划代理生成的代码质量总体可靠。

在程序错误内部,最常见的不是语法错误或运行时崩溃,而是一种更微妙的"Unknown Error":程序运行完了没有报错,但回答代理输出了"unknown"这个哨兵词,因为它没能从检索到的文档中提取出有用的信息。这本质上是回答代理无法充分利用检索结果的问题,而非Python层面的错误。真正的运行时异常(ValueError、TypeError、IndexError、NameError等)合在一起只占程序错误的不到20%,通常都可以追溯到对检索返回字符串格式的错误假设。

研究团队还指出了几个值得在未来改进的方向。"哨兵值脆弱性"是其中之一:当前的自适应检索机制靠字符串匹配来识别"unknown"这个词,一旦这个哨兵词被误当成真实内容传递到下一步,错误就会静默传播。更健壮的设计应该引入结构化的返回类型或者有校准的置信度信号。"欠分解"问题也值得关注:有时规划代理生成的代码语法完全正确,但只调用了一次retrieve,对于需要多步推理的问题来说这相当于跳过了推理链,而这种情况不会触发任何编译器错误,只能通过额外的复杂性估计或辅助约束来发现。

**八、论文展示的具体案例:理论走向实践**

论文中提供了多个具体的执行案例,让人能直观感受到PyRAG在实践中的工作方式。

有一个成功案例是关于"2014 S/S专辑是一个韩国男团的出道专辑,这个男团是由谁成立的"这个问题。PyRAG生成的程序先搜索"2014 S/S出道韩国男团",得到答案WINNER;然后用变量group存下这个答案,接着搜索"哪家公司成立了WINNER",得到YG Entertainment;最后汇总输出YG Entertainment。整个过程变量引用准确,没有任何跑偏。

另一个成功案例展示了自适应检索机制。问题是"除了那位出生于1990年的Force India车手,还有哪位墨西哥一级方程式赛车手曾经登上领奖台"。系统在尝试查询"Force India 1990年出生的车手"时,第一次只搜了5篇文档,回答代理返回了"unknown"。系统随即触发自适应检索,把搜索范围扩大到10篇,这次成功找到了足够信息,最终正确回答了问题。

还有一个有趣的案例展示了PyRAG处理布尔逻辑问题的方式。问题是"Freakonomics和In the Realm of the Hackers是否都是美国纪录片"。生成的程序用一个循环对两部影片分别查询"是否是纪录片"和"是否是美国的",构成一个2×2的网格。最后用Python的all()函数判断所有条件是否同时满足,直接在代码层面解决了布尔与的问题,而不是让回答代理来做这个多条件判断。结果两部影片各有一个条件不满足,程序返回"no",正确。

失败案例同样有启示价值。有一个失败案例中,回答代理在查询"谁是Force India 1990年出生的车手"时,返回了"Pedro Rodríguez and Sergio Pérez"这样包含多人的字符串,而不是一个干净的单人名字。这个不规整的答案被传入下游步骤,导致后续推理出错。这说明回答代理的输出格式标准化仍有改进空间。另一个失败案例更为典型:一个子步骤返回了"unknown",但下游步骤没有识别出这是哨兵词,而是把"unknown"当成了一个真实地名拿去搜索,结果找到了一个不相关地方的人口数据,最终给出了错误答案。还有一个程序层面的类型错误案例:回答代理返回了"LeBron James, Dwight Howard, Chris Webber..."这样一个逗号分隔的字符串,程序直接用for循环迭代这个字符串,但Python迭代字符串会一个字符一个字符地遍历,于是程序触发了400多次搜索,每次搜的是"L"、"e"、"B"这样单个字母,自然什么有用信息都找不到。修复只需要一行代码:把字符串用逗号分割成真正的列表。这个错误在自由文字推理中会被淹没在文字里根本无法定位,但在可执行的程序里,执行记录一目了然地暴露了问题所在。

说到底,PyRAG做的事情可以用一句话概括:它把AI回答复杂问题的过程,从"一篇流水账作文"变成了"一段可以运行的程序"。这个看似简单的转变,解决了三个在自然语言推理框架下几乎无解的顽固问题:中间结果看不见摸不着、搜索关键词容易跑偏、错误靠AI自己发现不可靠。

这项研究的意义不止于性能数字的提升。它揭示了一个更深层的设计原则:当我们想让AI做某类特定任务时,选择正确的"思维框架"和选择正确的"模型"同样重要,甚至可能更重要。代码模型在普通RAG下和普通模型差不多,但在PyRAG下却能明显更好——这说明模型的潜力和使用方式必须配合,否则就是把一把精密的手术刀拿来当菜刀用。

这对普通用户意味着什么?意味着未来你问智能助手那些复杂的多步骤问题时,它出错的概率会更低,而且出了错也更容易找到原因、更容易修正。你不再需要担心它把"约翰·威廉·亨利二世"和"英格兰亨利二世"搞混,因为在程序里,变量就是变量,不会自己变成别的东西。

当然,研究也坦诚地指出了未来还需要解决的问题:检索系统的召回率是最大的瓶颈,哨兵词的脆弱性需要更健壮的设计,回答代理的上下文利用能力还有提升空间。这些方向每一个都是值得继续深挖的课题。

有兴趣深入了解技术细节的读者,可以通过arXiv:2605.12975查询完整论文,研究团队也公开了代码和数据,地址在论文中可以找到。

Q&A

Q1:PyRAG和普通RAG问答系统的区别是什么?

A:普通RAG只做一次搜索然后直接回答,遇到需要多步推理的复杂问题容易出错。PyRAG的区别在于它让AI先写出一段Python程序,把推理过程分解成若干步骤,每步的结果存为变量供后续步骤使用,最后执行这段程序得出答案。这样中间结果有明确存储、搜索关键词不会跑偏,出错时也能得到计算机给出的客观错误信息来帮助纠正。

Q2:PyRAG在哪些问题上提升最明显?

A:PyRAG在需要多步组合推理的问题上提升最明显,比如需要先查A再查B最后比较A和B的问题。在Bamboogle和2WikiMultihopQA这两个专门测试组合推理的数据集上,无训练版本的PyRAG相比基础RAG方法分别提升了25.5和14.5个百分点。对于简单的单跳问题,PyRAG也没有明显退步。

Q3:PyRAG最常见的错误原因是什么?

A:根据研究团队的失败案例分析,最大的问题来自检索系统本身,约一半的错误是因为搜索没有找到正确的文档,这不是PyRAG能直接解决的。第二大问题是中间步骤返回了不确定答案,但这个不确定的信息被后续步骤当成真实信息继续使用,导致错误传播。真正由程序代码本身出错导致的失败只占约5%。

免责声明:本网信息来自于互联网,目的在于传递更多信息,并不代表本网赞同其观点。其内容真实性、完整性不作任何保证或承诺。如若本网有任何内容侵犯您的权益,请及时联系我们,本站将会在24小时内处理完毕。