
1. 为什么工程化 Agent 的评测不能只看跑分做 Agent 开发的人都有一个共同的困惑Demo 跑起来很惊艳一上生产就拉胯。你问它一个多跳推理问题它可能第一步就找错了方向你让它调用三个工具完成一个任务它可能在第二个工具的参数上就开始胡编。更麻烦的是这些问题在单轮对话里根本看不出来只有把它扔进一个足够复杂、足够真实的任务环境里才能暴露出来。这就是 GAIA 这类基准测试存在的意义。GAIA 全称 General AI Assistants benchmark它的设计思路和传统的 NLP 评测集完全不同。传统评测集往往是“给定一段文本回答一个问题”考的是模型的语言理解和知识储备。GAIA 考的是“给你一个真实世界的复杂问题你需要自己规划步骤、调用工具、整合信息最终给出一个精确答案”。它把任务分成三个难度等级Level 1 基本是单步检索或简单推理Level 2 需要多步推理加工具组合Level 3 则涉及长链条规划、跨模态信息处理、甚至需要写代码来验证中间结果。羲和 XiheAgent 是我们内部搭建的一个工程化 Agent 框架定位不是“又一个聊天机器人”而是能真正接入业务系统、调用外部工具、完成端到端任务的智能体。它的核心能力包括任务规划、工具编排、记忆管理和结果验证四个模块。我们拿 GAIA 来做全流程评测目的不是刷一个好看的分数而是通过这个基准测试来检验框架在真实复杂场景下的鲁棒性、可扩展性和可调试性。这篇文章适合两类人看一类是正在做 Agent 开发、想知道怎么系统性地评测自己框架的工程师另一类是对 Agent 评测方法论感兴趣、想了解 GAIA 到底怎么跑、坑在哪里的技术负责人。我会把整个评测流程拆开从环境搭建、任务拆解、工具接入、结果验证到问题排查一步步讲清楚。你不需要有 GAIA 的使用经验但最好对 Agent 的基本概念比如 ReAct 循环、工具调用、上下文管理有一些了解。2. GAIA 评测体系的核心设计与 XiheAgent 的适配思路2.1 GAIA 的任务结构到底在考什么GAIA 的题目看起来像是一些“奇怪的知识问答”比如“某个特定年份的某个小众奖项的获奖者他后来参与的那部电影的票房是多少”。这种题目的特点是答案唯一且可验证但获取路径非常不确定。你可能需要先查奖项再查获奖者再查他的作品列表再查票房数据中间任何一步出错最终答案就是错的。这和传统的多跳问答有什么区别传统多跳问答通常有明确的推理链比如 A 是 B 的父亲B 是 C 的父亲问 A 和 C 的关系。GAIA 的推理链是隐式的你需要自己决定先查什么、后查什么甚至需要判断哪些信息是干扰项。更关键的是GAIA 的题目往往需要调用外部工具——搜索引擎、网页抓取、文件解析、代码执行——而不是单纯靠模型内部知识。从评测维度来看GAIA 实际上在考四件事第一是任务规划能力你能不能把一个大问题拆成可执行的子步骤第二是工具选择能力面对一个子任务你知道该用哪个工具、怎么传参第三是信息整合能力从多个来源拿到碎片信息后你能不能拼出完整答案第四是自我验证能力你能不能判断自己给出的答案是否合理。2.2 XiheAgent 的架构为什么适合跑 GAIAXiheAgent 的架构设计从一开始就考虑了评测需求。它的核心是一个基于状态机的任务执行引擎而不是简单的 ReAct 循环。为什么不用 ReAct因为 ReAct 在长链条任务中容易“迷失”每一步都依赖上一步的输出一旦某一步产生幻觉后面全错。状态机的方式是把任务拆成明确的状态节点每个节点有输入输出定义节点之间通过条件跳转连接。这样做的好处是当某个节点执行失败时你可以精确定位到是哪一步出了问题而不是面对一个黑盒。具体来说XiheAgent 包含四个核心模块。规划器Planner负责把用户输入的任务拆解成子任务序列它内部维护一个任务图每个子任务是一个节点节点之间有依赖关系。执行器Executor负责调用具体工具它支持同步和异步两种模式对于需要等待外部 API 返回的任务可以并行执行多个子任务。记忆模块Memory分为短期记忆和长期记忆短期记忆保存当前任务的上下文长期记忆保存历史任务的成功经验和失败教训。验证器Validator负责检查每个子任务的输出是否符合预期如果不符合会触发重试或回退。这套架构跑 GAIA 的优势在于GAIA 的题目天然适合拆成任务图而且验证器可以在每个子任务完成后立即检查结果避免错误累积。另外记忆模块可以让 Agent 在遇到类似题目时复用之前的策略这对于 GAIA 这种题目类型相对固定的基准测试来说能显著提升效率。2.3 评测流程的整体设计整个评测流程分为五个阶段。第一阶段是环境准备包括 GAIA 数据集的下载、依赖工具的安装、API 密钥的配置。第二阶段是任务加载与预处理把 GAIA 的题目转换成 XiheAgent 能理解的输入格式同时提取题目中的关键信息比如是否需要文件解析、是否需要代码执行。第三阶段是执行与记录Agent 开始跑任务系统记录每一步的输入输出、耗时、工具调用次数。第四阶段是结果验证把 Agent 的答案和 GAIA 的标准答案对比计算准确率。第五阶段是问题分析对失败的题目进行分类找出是规划问题、工具问题还是验证问题。这个流程看起来简单但每个阶段都有坑。比如环境准备阶段GAIA 的题目里有一些需要解析 PDF 或 Excel 文件的如果你的工具链不支持这些格式题目根本没法跑。再比如结果验证阶段GAIA 的答案有时候是数值有时候是字符串有时候是列表对比逻辑需要根据答案类型动态调整。3. 从零搭建 GAIA 评测环境的实操细节3.1 数据集获取与题目结构解析GAIA 的数据集在 Hugging Face 上可以找到官方提供了验证集和测试集。验证集有 165 道题测试集有 301 道题。每道题包含以下字段task_id唯一标识、Question题目文本、Level难度等级 1-3、Final answer标准答案、file_name如果有附件的话、file_path附件路径。附件是 GAIA 的一个重要特点很多题目需要你读取一个 PDF、Excel 或图片文件才能回答。我建议先用验证集跑通流程因为验证集有公开答案方便调试。测试集的答案不公开需要提交到官方 leaderboard 才能看到分数。对于内部评测来说验证集已经足够暴露大部分问题。加载数据集的时候要注意GAIA 的题目文本里有时候会包含一些特殊格式比如用反引号包裹的文件名或者用方括号标注的链接。这些需要在预处理阶段提取出来作为工具调用的参数。我的做法是写一个简单的解析器用正则表达式提取题目中的文件引用和 URL然后把它们作为元数据附加到任务对象上。3.2 工具链的选型与配置GAIA 题目涉及的工具类型主要有四类搜索引擎、网页抓取、文件解析、代码执行。搜索引擎我用的是 SerpAPI因为它返回的结构化数据比较干净解析成本低。网页抓取用 Playwright因为它能处理 JavaScript 渲染的页面而 GAIA 里有些题目需要访问动态加载的网页。文件解析用 PyPDF2 处理 PDF用 openpyxl 处理 Excel用 Pillow 处理图片。代码执行用 Docker 容器隔离避免 Agent 生成的代码影响宿主机。这里重点说一下代码执行工具的设计。GAIA 里有一些题目需要计算比如“某个数的阶乘的各位数字之和”这种题目如果让模型直接算很容易出错。更好的做法是让 Agent 生成一段 Python 代码然后在沙箱里执行把结果返回给 Agent。XiheAgent 的代码执行工具支持两种模式一种是直接执行代码字符串返回标准输出另一种是执行代码文件返回文件内容。对于 GAIA 的题目第一种模式就够了。配置 API 密钥的时候要注意不要把密钥硬编码在代码里。我用的是环境变量加配置文件的方式配置文件里只写密钥的名称实际值从环境变量读取。这样既方便切换密钥也避免了密钥泄露的风险。3.3 任务加载器的实现任务加载器的核心工作是把 GAIA 的原始题目转换成 XiheAgent 的任务对象。任务对象包含以下字段task_id、question、level、expected_answer、attachments、tools_required、max_steps。其中tools_required是根据题目内容推断出来的比如题目里出现了“根据附件”这样的字眼就自动加上文件解析工具出现了“计算”或“求和”就加上代码执行工具。max_steps是一个重要的参数它限制了 Agent 最多执行多少步。GAIA 的 Level 1 题目通常 3-5 步就能解决Level 2 需要 8-12 步Level 3 可能需要 20 步以上。如果max_steps设得太小Agent 还没找到答案就被强制终止设得太大又容易让 Agent 陷入无效循环。我的经验是Level 1 设 8 步Level 2 设 15 步Level 3 设 25 步这个配置在验证集上的表现比较均衡。加载器还需要处理附件。GAIA 的附件有时候是单独的文件有时候是压缩包。对于压缩包需要先解压再处理。附件的路径要转换成绝对路径避免因为工作目录变化导致文件找不到。4. XiheAgent 执行 GAIA 任务的核心环节拆解4.1 任务规划器的配置与调优规划器是 XiheAgent 跑 GAIA 的第一个环节也是最容易出问题的环节。规划器的输入是题目文本和附件信息输出是一个任务图。任务图的每个节点包含node_id、description子任务描述、tool需要调用的工具、params工具参数、dependencies依赖的节点 ID。规划器的 prompt 设计很关键。我试过几种不同的 prompt 结构最后发现最有效的是“先分类再拆解”的两阶段方式。第一阶段让模型判断题目类型是纯检索题、多跳推理题、文件解析题还是计算题。第二阶段根据题目类型套用不同的拆解模板。比如检索题拆成“确定搜索关键词 - 执行搜索 - 提取答案”三步多跳推理题拆成“识别第一跳实体 - 搜索第一跳信息 - 识别第二跳实体 - 搜索第二跳信息 - 整合答案”五步。这种方式的优势是拆解结果更稳定不会因为题目表述的微小变化就产生完全不同的任务图。缺点是灵活性稍差遇到模板覆盖不到的题目类型时需要回退到通用的 ReAct 拆解方式。我的做法是维护一个题目类型到拆解模板的映射表同时保留一个兜底的通用拆解器。规划器的输出需要做校验。我遇到过规划器生成的任务图里有循环依赖的情况比如节点 A 依赖节点 B节点 B 又依赖节点 A。这种任务图执行时会死锁。解决办法是在规划器输出后加一个环检测步骤用拓扑排序检查任务图是否有环如果有环就触发重新规划。4.2 工具调用的参数传递与错误处理工具调用是执行器的核心工作。每个工具都有明确的输入输出定义执行器根据任务图节点的tool和params字段来调用对应的工具。参数传递有两种方式一种是直接传递比如搜索工具的query参数直接来自规划器的输出另一种是引用传递比如第二个搜索的query参数需要引用第一个搜索的结果。引用传递是容易出错的地方。如果第一个搜索返回的结果格式和预期不符第二个搜索的参数就会出错。我的做法是在工具的输出定义里加上 schema 校验确保输出符合预期格式。如果不符合执行器会触发重试重试时会把错误信息附加到 prompt 里让规划器重新生成参数。错误处理策略分为三级。一级错误是参数格式错误比如搜索关键词为空这种错误直接重试重试次数上限 3 次。二级错误是工具返回空结果比如搜索没有找到任何相关内容这种错误会触发规划器重新规划换一个搜索策略。三级错误是工具调用超时或抛出异常这种错误会记录到日志然后跳过当前节点继续执行后续节点。如果后续节点依赖当前节点的输出则整个任务标记为失败。4.3 记忆模块的读写策略记忆模块在 GAIA 评测中的作用经常被低估。GAIA 的题目虽然各不相同但很多题目在解题思路上是相似的。比如“某本书的作者的出生地”和“某部电影的导演的代表作”本质上都是两跳检索题。如果 Agent 能把第一次解题的成功经验保存下来遇到类似题目时直接复用策略效率会高很多。XiheAgent 的记忆模块分为两层。短期记忆保存当前任务的执行历史包括每一步的输入输出、工具调用记录、中间结果。短期记忆的容量有限我设的是 20 条记录超过后自动淘汰最早的记录。长期记忆保存跨任务的经验包括成功的任务图模板、常用的工具组合、常见的错误模式。长期记忆用向量数据库存储检索时根据题目文本的语义相似度召回相关经验。写入长期记忆的时机很关键。不是所有成功任务都值得保存只有那些执行步数少、工具调用次数少、且答案正确的任务才值得作为模板。我设的阈值是Level 1 任务步数不超过 5 步Level 2 不超过 10 步Level 3 不超过 18 步。超过这个阈值的任务即使答案正确也不保存为模板因为它们的执行路径可能包含偶然因素。4.4 验证器的规则设计与动态调整验证器负责检查每个子任务的输出是否合理。对于搜索类工具验证规则是检查返回结果的数量是否大于 0以及结果中是否包含任务描述里的关键词。对于文件解析工具验证规则是检查解析出的文本长度是否大于某个阈值以及是否包含预期的字段。对于代码执行工具验证规则是检查退出码是否为 0以及标准输出是否为空。验证器的规则不是一成不变的。在评测过程中我发现有些题目的搜索关键词比较生僻搜索结果数量很少但结果确实是正确的。如果严格按照“结果数量大于 0”来验证这些题目会被误判为失败。解决办法是引入动态阈值对于生僻关键词把结果数量阈值降到 0但增加一个“结果相关性”检查用简单的关键词匹配来判断结果是否和题目相关。验证器的另一个作用是触发回退。如果某个子任务的输出验证失败验证器会通知执行器回退到上一个成功的节点然后重新规划后续步骤。回退机制在 GAIA 的 Level 3 题目中特别有用因为 Level 3 题目往往有多条解题路径一条路走不通可以换另一条。5. 评测结果分析与常见问题排查5.1 准确率、步数与工具调用次数的关系跑完验证集的 165 道题后我整理了一份数据。整体准确率是 68.5%其中 Level 1 准确率 89.2%Level 2 准确率 64.7%Level 3 准确率 41.3%。这个成绩在同类框架里属于中等偏上但距离我们的目标还有差距。从步数来看Level 1 平均 4.2 步Level 2 平均 9.8 步Level 3 平均 17.5 步。工具调用次数和步数基本成正比Level 1 平均 3.1 次Level 2 平均 7.6 次Level 3 平均 14.2 次。值得注意的是失败任务的步数普遍比成功任务多 30%-50%说明 Agent 在遇到困难时容易陷入无效循环反复尝试相似的策略。难度等级题目数量准确率平均步数平均工具调用次数Level 15289.2%4.23.1Level 27864.7%9.87.6Level 33541.3%17.514.2整体16568.5%9.67.45.2 典型失败案例的分类与归因失败案例可以分成四类。第一类是规划错误占比约 35%。典型表现是任务图拆解不合理比如把一道需要先查 A 再查 B 的题目拆成了同时查 A 和 B导致信息无法整合。第二类是工具调用错误占比约 28%。典型表现是搜索关键词选择不当比如题目问的是“某部电影的票房”Agent 搜索的是“某部电影 评价”结果找不到票房数据。第三类是信息整合错误占比约 22%。典型表现是拿到了所有需要的信息但整合时搞错了逻辑关系比如把“A 的出生年份”和“B 的出生年份”搞混了。第四类是验证器误判占比约 15%。典型表现是验证器认为某个中间结果不合格触发了不必要的回退导致任务超时。规划错误是最难解决的因为它涉及到模型对题目意图的理解。我的改进方向是增加一个“规划预检”步骤在任务图生成后用一个轻量级的模型检查任务图是否合理比如检查节点之间的依赖关系是否完整、是否有冗余节点。这个预检步骤增加了约 5% 的耗时但把规划错误率降低了 12%。5.3 常见问题速查表问题现象可能原因排查方法解决方案Agent 反复搜索同一个关键词规划器陷入循环查看任务图是否有环增加环检测触发重新规划搜索结果为空但题目确实有答案关键词过于具体检查搜索关键词是否包含生僻词放宽关键词用同义词替换文件解析失败文件格式不支持检查文件扩展名和实际格式增加格式转换步骤代码执行超时代码逻辑有死循环查看代码内容设置执行超时强制终止答案格式正确但内容错误信息整合逻辑错误对比中间结果和最终答案增加整合步骤的验证规则任务步数超过上限规划器拆解过细查看任务图节点数量合并相似节点减少步数5.4 提升评测效果的几个实操技巧第一个技巧是预热记忆库。在正式评测前先用一小部分题目比如 20 道跑一遍把成功的任务图保存到长期记忆里。正式评测时遇到相似题目可以直接复用模板能显著减少步数和工具调用次数。我实测下来预热后 Level 2 的平均步数从 9.8 降到了 7.2。第二个技巧是动态调整 max_steps。不要给所有题目设同一个 max_steps而是根据题目的 Level 和预估复杂度动态设置。我的做法是先用一个较小的 max_steps 跑一遍记录每道题的实际步数然后根据实际步数的分布给每道题设置一个略高于实际步数的上限。这样既能避免步数浪费又能防止 Agent 提前终止。第三个技巧是工具调用的缓存。GAIA 的题目里有一些搜索关键词是重复的比如多道题都涉及同一个实体。如果每次搜索都重新调用 API不仅慢还可能触发 API 的速率限制。我的做法是在工具层加一个缓存用搜索关键词的哈希作为 key缓存搜索结果。缓存有效期设为 24 小时对于 GAIA 评测来说足够了。第四个技巧是失败任务的二次利用。失败的任务不要直接丢掉而是把失败原因分类保存。如果是因为工具调用错误导致的失败可以把正确的工具调用方式补充到长期记忆里如果是因为规划错误导致的失败可以把错误的规划方式和正确的规划方式对比保存作为后续规划的负样本。6. 从 GAIA 评测反推 Agent 框架的优化方向跑完这一轮 GAIA 评测最大的收获不是那个 68.5% 的准确率数字而是暴露出来的框架设计问题。规划器的两阶段拆解方式在 Level 1 和 Level 2 上表现不错但在 Level 3 上明显吃力因为 Level 3 的题目往往没有固定的拆解模板需要更灵活的规划策略。下一步我打算引入基于蒙特卡洛树搜索的规划器让 Agent 在多个可能的任务图之间做选择而不是只生成一个任务图。工具层的问题主要是错误处理不够精细。现在的三级错误处理策略太粗糙很多错误其实有更具体的处理方法。比如搜索返回空结果可能是因为关键词太具体也可能是因为搜索引擎的索引里确实没有这个信息。这两种情况的处理方式完全不同前者应该换关键词后者应该换搜索源。我打算在工具层增加一个错误分类器根据错误的具体表现来决定处理策略。记忆模块的检索精度也有提升空间。现在的向量检索用的是通用的文本嵌入模型对 GAIA 这种专业领域的题目检索效果一般。我试过用 GAIA 的题目文本微调一个嵌入模型检索精度提升了约 15%但微调成本比较高。另一个思路是用关键词和向量混合检索先用关键词过滤掉明显不相关的记忆再用向量做精细排序。验证器的规则目前还是手工配置的维护成本高而且容易遗漏。我打算把验证器的规则也交给模型来生成具体做法是让模型根据任务描述自动生成验证规则然后人工审核。这样既能减少手工配置的工作量又能覆盖更多的任务类型。最后说一个容易被忽略的点评测的可复现性。GAIA 评测涉及多个外部工具和 API这些外部依赖的状态变化会影响评测结果。比如搜索引擎的索引更新了同样的关键词可能返回不同的结果。为了保证评测的可复现性我把所有工具调用的输入输出都记录到了日志里评测时可以选择“回放模式”直接用日志里的结果而不重新调用工具。这样即使外部环境变了也能复现之前的评测结果。这个内容后续还可以这样扩展把 GAIA 的评测流程封装成一个通用的 Agent 评测平台支持接入不同的 Agent 框架和不同的基准测试集。平台的核心是一个评测编排器负责管理评测任务的生命周期包括环境准备、任务分发、结果收集和报告生成。这样每次优化 Agent 框架后只需要在平台上重新跑一遍评测就能快速看到优化效果。