第十二章 智能体性能评估 在前面的章节中,我们构建了 HelloAgents 框架的核心功能,实现了多种智能体范式、工具系统、记忆机制和强化学习训练等。在构建智能体系统时,我们还需要解决一个核心问题:如何客观地评估智能体的性能? 具体来说,我们需要回答以下问题:
智能体是否具备预期的能力?
在不同任务上的表现如何?
与其他智能体相比处于什么水平?
本章将为 HelloAgents 增加性能评估系统(Evaluation System) 。我们将深入理解智能体评估的理论基础,并实现评估的工具。
12.1 智能体评估基础 12.1.1 为何需要智能体评估 我们现在的 SimpleAgent,它已经具备了强大的推理和工具调用能力。让我们看一个典型的使用场景:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 from hello_agents import SimpleAgent, HelloAgentsLLMfrom hello_agents.tools import SearchTool llm = HelloAgentsLLM() system_prompt = """你是一个AI助手,可以使用搜索工具来获取最新信息。 当需要搜索信息时,请使用以下格式: [TOOL_CALL:search:搜索关键词] 例如: - [TOOL_CALL:search:最新AI新闻] - [TOOL_CALL:search:Python编程教程] 请在回答问题前先使用搜索工具获取最新信息。""" agent = SimpleAgent(name="AI助手" , llm=llm, system_prompt=system_prompt) agent.add_tool(SearchTool()) response = agent.run("最新的AI技术发展趋势是什么?" )print (f"\n回答:{response} " )
这个智能体能正常工作,但我们面临一个核心问题:如何客观地评估它的性能?当我们优化提示词或更换 LLM 模型后,如何知道是否真的有改进?在部署到生产环境前,如何保证智能体的可靠性?这些问题都需要通过系统化的评估来解决。
智能体评估的核心价值在于提供标准化的方法来衡量智能体的能力。通过评估,我们可以用具体的数字指标量化智能体的表现,客观比较不同设计方案的优劣,及时发现智能体在特定场景下的弱点,并向用户证明智能体的可靠性。
与传统软件测试不同,智能体评估面临着独特的挑战。首先是输出的不确定性,同一问题可能有多个正确答案,很难用简单的对错来判断。其次是评估标准的多样性,不同任务需要不同的评估方法,工具调用需要检查函数签名,问答任务需要评估语义相似度。最后是评估成本的高昂,每次评估都需要大量的 API 调用,成本可能达到数百元甚至更多。
为了应对这些挑战,学术界和工业界提出了多个标准化的评估基准(Benchmark) 。这些基准提供了统一的数据集、评估指标和评分方法,使我们能够在相同的标准下评估和对比不同的智能体系统。
12.1.2 主流评估基准概览 智能体评估领域已经涌现出多个具有影响力的基准测试。下面介绍一些主流的评估基准和指标:
(1)工具调用能力评估
工具调用是智能体的核心能力之一。智能体需要理解用户意图,选择合适的工具,并正确构造函数调用。相关的评估基准包括:
BFCL (Berkeley Function Calling Leaderboard) [1] :UC Berkeley 推出,包含 1120+测试样本,涵盖 simple、multiple、parallel、irrelevance 四个类别,使用 AST 匹配算法评估,数据集规模适中,社区活跃。
ToolBench [2] :清华大学推出,包含 16000+真实 API 调用场景,覆盖真实世界的复杂工具使用场景。
API-Bank [3] :Microsoft Research 推出,包含 53 个常用 API 工具,专注于评估智能体对 API 文档的理解和调用能力。
(2)通用能力评估
评估智能体在真实世界任务中的综合表现,包括多步推理、知识运用、多模态理解等能力:
GAIA (General AI Assistants) [4] :Meta AI 和 Hugging Face 联合推出,包含 466 个真实世界问题,分为 Level 1/2/3 三个难度级别,评估多步推理、工具使用、文件处理、网页浏览等能力,使用准精确匹配(Quasi Exact Match)算法,任务真实且综合性强。
AgentBench [5] :清华大学推出,包含 8 个不同领域的任务,全面评估智能体的通用能力。
WebArena [6] :CMU 推出,评估智能体在真实网页环境中的任务完成能力和网页交互能力。
(3)多智能体协作评估
评估多个智能体协同工作的能力:
ChatEval [7] :评估多智能体对话系统的质量。
SOTOPIA [8] :评估智能体在社交场景中的互动能力。
自定义协作场景 :根据具体应用场景设计的评估任务。
(4)常用评估指标
不同基准使用不同的评估指标,常见的包括:
准确性指标 :Accuracy(准确率)、Exact Match(精确匹配)、F1 Score(F1 分数),用于衡量答案的正确性。
效率指标 :Response Time(响应时间)、Token Usage(Token 使用量),用于衡量执行效率。
鲁棒性指标 :Error Rate(错误率)、Failure Recovery(故障恢复),用于衡量容错能力。
协作指标 :Communication Efficiency(通信效率)、Task Completion(任务完成度),用于衡量协作效果。
12.1.3 HelloAgents 评估体系设计 考虑到学习曲线和实用性,本章将重点介绍以下评估场景:
BFCL :评估工具调用能力
选择理由:数据集规模适中,评估指标清晰,社区活跃
适用场景:评估智能体的函数调用准确性
GAIA :评估通用 AI 助手能力
选择理由:任务真实,难度分级,综合性强
适用场景:评估智能体的综合问题解决能力
数据生成质量评估 :评估 LLM 生成数据质量
选择理由:通过这个案例可以完整体验如何使用 Agent 创造数据,评估数据的完整演示。
适用场景:评估生成的训练数据、测试数据的质量
评估方法:LLM Judge、Win Rate、人工验证
通过这三个评估场景,我们将构建一个完整的评估体系,如图 12.1 展示了我们的评估系统构建思路。
图 12.1 HelloAgents 评估体系架构图
12.1.4 本章学习目标与快速体验 让我们先看看第十二章的学习内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 hello_agents/ ├── evaluation/ │ └── benchmarks/ │ ├── bfcl/ │ │ ├── dataset.py │ │ ├── evaluator.py │ │ ├── metrics.py │ │ └── ast_matcher.py │ ├── gaia/ │ │ ├── dataset.py │ │ ├── evaluator.py │ │ ├── metrics.py │ │ └── quasi_exact_match.py │ └── data_generation/ │ ├── dataset.py │ ├── llm_judge.py │ └── win_rate.py └── tools/builtin/ ├── bfcl_evaluation_tool.py ├── gaia_evaluation_tool.py ├── llm_judge_tool.py └── win_rate_tool.py
对于这一章的内容,学习目标是掌握应用评估工具的能力。让我们先准备好开发环境:
1 2 3 4 5 6 7 8 pip install "hello-agents[evaluation]==0.2.7" export HF_TOKEN="your_huggingface_token" pip install "numpy==1.26.4" bfcl-eval
在接下来的章节中,我们将深入学习每种评估方法的详细用法和介绍。
12.2 BFCL:工具调用能力评估 12.2.1 BFCL 基准介绍 BFCL (Berkeley Function Calling Leaderboard) 是由加州大学伯克利分校推出的函数调用能力评估基准[1] 。在智能体系统中,工具调用(Tool Calling)是核心能力之一。智能体需要完成以下任务:
理解任务需求 :从用户的自然语言描述中提取关键信息
选择合适工具 :从可用工具集中选择最适合的工具
构造函数调用 :正确填写函数名和参数
处理复杂场景 :支持多函数调用、并行调用等高级场景
BFCL 基准包含四个评估类别,难度递增。从最基础的单函数调用(Simple)开始,逐步增加到需要调用多个函数的场景(Multiple),再到需要并行调用多个函数的复杂场景(Parallel),最后是需要判断是否需要调用函数的场景(Irrelevance)。这四个类别覆盖了智能体在实际应用中可能遇到的各种工具调用场景,如表 12.1 所示:
表 12.1 BFCL 基准中的四个评估类别
BFCL 的评估流程遵循标准的基准测试流程:首先加载数据集并选择评估类别,然后运行智能体获取预测结果,接着将预测结果解析为抽象语法树(AST),最后通过 AST 匹配算法判断预测是否正确。整个流程会遍历所有测试样本,最终计算出准确率等评估指标并生成评估报告。完整的评估流程如图 12.2 所示:
图 12.2 BFCL 评估流程图
(1)BFCL 数据集结构
BFCL 数据集采用 JSON 格式,每个测试样本包含以下字段:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 { "id" : "simple_001" , "question" : "What's the weather like in Beijing today?" , "function" : [ { "name" : "get_weather" , "description" : "Get the current weather for a location" , "parameters" : { "type" : "object" , "properties" : { "location" : { "type" : "string" , "description" : "The city name" } } , "required" : [ "location" ] } } ] , "ground_truth" : [ { "name" : "get_weather" , "arguments" : { "location" : "Beijing" } } ] }
关键字段说明:
question: 用户的自然语言请求
function: 可用的函数列表(包含函数签名和描述)
ground_truth: 标准答案(期望的函数调用)
(2)AST 匹配说明
BFCL 使用AST 匹配(Abstract Syntax Tree Matching) 作为核心评估算法,因此下文可以了解一下评估的策略。
BFCL 使用抽象语法树(AST)进行智能匹配,而不是简单的字符串匹配。AST 匹配的核心思想是:将函数调用解析为语法树,然后比较树的结构和节点值 。
给定预测的函数调用 $P$ 和标准答案 $G$,AST 匹配函数定义为:
$$ \text{AST_Match}(P, G) = \begin{cases} 1 & \text{if } \text{AST}(P) \equiv \text{AST}(G) \ 0 & \text{otherwise} \end{cases} $$
其中 $\text{AST}(x)$ 表示将函数调用解析为抽象语法树,$\equiv$ 表示语法树等价。
两个语法树等价需要满足三个核心条件:函数名必须完全一致(精确匹配),参数键值对集合相等(忽略顺序),以及每个参数的值在语义上等价(例如 2+3 等价于 5)。在具体的匹配过程中,函数名匹配要求字符串精确匹配,例如 get_weather 和 get_temperature 被视为不同的函数。参数匹配则使用 AST 进行智能比较,允许参数顺序不同(f(a=1, b=2) 等价于 f(b=2, a=1)),允许等价表达式(f(x=2+3) 等价于 f(x=5)),也允许不同的字符串表示(f(s="hello") 等价于 f(s='hello'))。对于多函数调用的场景,匹配算法要求调用相同数量的函数,每个函数调用都必须匹配,但调用顺序可以不同(使用集合匹配)。
AST 匹配示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 预测: get_weather(city="Beijing" , unit="celsius" ) 标准: get_weather(unit="celsius" , city="Beijing" ) 结果: ✅ 匹配成功 预测: calculate(x=2 +3 ) 标准: calculate(x=5 ) 结果: ✅ 匹配成功 预测: get_temperature(city="Beijing" ) 标准: get_weather(city="Beijing" ) 结果: ❌ 匹配失败 预测: get_weather(city="Shanghai" ) 标准: get_weather(city="Beijing" ) 结果: ❌ 匹配失败
(3)BFCL 评估指标
BFCL 使用以下指标评估智能体性能:
1. 准确率 (Accuracy)
准确率是最核心的指标,定义为 AST 匹配成功的样本比例:
$$ \text{Accuracy} = \frac{1}{N} \sum_{i=1}^{N} \text{AST_Match}(P_i, G_i) $$
其中:
$N$ 是总样本数
$P_i$ 是第 $i$ 个样本的预测结果
$G_i$ 是第 $i$ 个样本的标准答案
$\text{AST_Match}(P_i, G_i) \in {0, 1}$ 是 AST 匹配函数
2. AST 匹配率 (AST Match Rate)
与准确率相同,强调使用 AST 匹配算法:
$$ \text{AST Match Rate} = \text{Accuracy} $$
3. 分类准确率 (Category-wise Accuracy)
对于每个类别 $c \in {\text{simple}, \text{multiple}, \text{parallel}, \ldots}$,计算该类别的准确率:
$$ \text{Accuracy}c = \frac{1}{|D_c|} \sum {i \in D_c} \text{AST_Match}(P_i, G_i) $$
其中 $D_c$ 是类别 $c$ 的样本集合,$|D_c|$ 是该类别的样本数。
4. 加权准确率 (Weighted Accuracy)
考虑不同类别的难度权重:
$$ \text{Weighted Accuracy} = \sum_{c} w_c \cdot \text{Accuracy}_c $$
其中 $w_c$ 是类别 $c$ 的权重,满足 $\sum_c w_c = 1$。
5. 错误率 (Error Rate)
未能正确调用函数的样本比例:
$$ \text{Error Rate} = 1 - \text{Accuracy} = \frac{1}{N} \sum_{i=1}^{N} (1 - \text{AST_Match}(P_i, G_i)) $$
指标解释:
Accuracy = 1.0 :所有样本都完全正确
Accuracy = 0.8 :80%的样本正确,20%的样本错误
Accuracy = 0.0 :所有样本都错误
分类准确率示例:
1 2 3 4 5 6 7 simple_accuracy = 0.95 multiple_accuracy = 0.82 parallel_accuracy = 0.68 weighted_accuracy = (0.95 + 0.82 + 0.68 ) / 3 = 0.817
(4)BFCL 官方评估工具
BFCL 提供官方 CLI 工具进行评估:
1 2 3 4 5 6 7 pip install bfcl bfcl evaluate \ --model-result-path ./results.json \ --test-category simple_python
使用官方评估工具的优势在于:它使用官方的 AST 匹配算法,评估结果与排行榜完全一致,支持所有 BFCL v4 类别,并且能够自动生成详细的评估报告。
12.2.2 获取 BFCL 数据集 BFCL 数据集可以通过以下方式获取:
方法 1:从官方 GitHub 仓库克隆(推荐)
这是最可靠的方式,可以获取完整的数据集和 ground truth:
1 2 3 4 5 6 7 8 9 10 11 git clone https://github.com/ShishirPatil/gorilla.git temp_gorillacd temp_gorilla/berkeley-function-call-leaderboardls bfcl_eval/data/ls bfcl_eval/data/possible_answer/
推荐这种方式的原因是:它包含完整的 ground truth(标准答案),数据格式与官方评估工具完全一致,可以直接使用官方评估脚本,并且支持 BFCL v4 最新版本。
方法 2:使用 HelloAgents 加载官方数据
克隆仓库后,使用 HelloAgents 加载数据:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 from hello_agents.evaluation import BFCLDataset dataset = BFCLDataset( bfcl_data_dir="./temp_gorilla/berkeley-function-call-leaderboard/bfcl_eval/data" , category="simple_python" ) data = dataset.load()print (f"✅ 加载了 {len (data)} 个测试样本" )print (f"✅ 加载了 {len (dataset.ground_truth)} 个ground truth" )
这个加载器的工作原理是:首先从bfcl_eval/data/加载测试数据,然后从bfcl_eval/data/possible_answer/加载 ground truth,接着自动合并测试数据和 ground truth,最后保留原始 BFCL 数据格式。其中 BFCL v4 数据集类别可以在表 12.2 查看。
表 12.2 BFCL 基准中的四个评估类别
当然也可以通过代码查看可用类别:
1 2 3 4 categories = dataset.get_available_categories()print (f"支持的类别: {categories} " )
12.2.3 在 HelloAgents 中实现 BFCL 评估 现在让我们看看如何在 HelloAgents 框架中实现 BFCL 评估。我们提供了三种使用方式:
方式 1:使用 BFCLEvaluationTool(推荐)
这是最简单的方式,一行代码完成评估、报告生成和官方评估:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 from hello_agents import SimpleAgent, HelloAgentsLLMfrom hello_agents.tools import BFCLEvaluationTool llm = HelloAgentsLLM() agent = SimpleAgent(name="TestAgent" , llm=llm) bfcl_tool = BFCLEvaluationTool() results = bfcl_tool.run( agent=agent, category="simple_python" , max_samples=5 )print (f"准确率: {results['overall_accuracy' ]:.2 %} " )print (f"正确数: {results['correct_samples' ]} /{results['total_samples' ]} " )
运行输出:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 ============================================================ BFCL一键评估 ============================================================ 配置: 评估类别: simple_python 样本数量: 5 智能体: TestAgent ============================================================ 步骤1: 运行HelloAgents评估 ============================================================ ✅ BFCL数据集加载完成 数据目录: ./temp_gorilla/berkeley-function-call-leaderboard/bfcl_eval/data 类别: simple_python 样本数: 400 Ground truth数: 400 🔧 开始 BFCL 评估... 进度: 1/5 进度: 5/5 ✅ BFCL 评估完成 总体准确率: 100.00% simple_python: 100.00% (5/5) 📊 评估结果: 准确率: 100.00% 正确数: 5/5 ============================================================ 步骤2: 导出BFCL格式结果 ============================================================ ✅ BFCL格式结果已导出 输出文件: ./evaluation_results/bfcl_official/BFCL_v4_simple_python_result.json ============================================================ 步骤3: 运行BFCL官方评估 ============================================================ ✅ 结果文件已复制到: ./result/Qwen_Qwen3-8B/BFCL_v4_simple_python_result.json 🔄 运行命令: bfcl evaluate --model Qwen/Qwen3-8B --test-category simple_python --partial-eval ============================================================ BFCL官方评估结果 ============================================================ 📊 评估结果汇总: Model,Overall Acc,simple_python Qwen/Qwen3-8B,100.00,100.00 🎯 最终结果: 准确率: 100.00% 正确数: 5/5 ============================================================ 步骤4: 生成评估报告 ============================================================ 📄 报告已生成: ./evaluation_reports/bfcl_report_20251011_005938.md 准确率: 100.00% 正确数: 5/5
自动生成的 Markdown 报告:
评估完成后,会自动生成一份详细的 Markdown 报告,包含:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 # BFCL评估报告 **生成时间** : 2025-10-11 00:59:38## 📊 评估概览 - **智能体** : TestAgent- **评估类别** : simple_python - **总体准确率** : 100.00% - **正确样本数** : 5/5 ## 📈 详细指标 ### 分类准确率 - **simple_python** : 100.00% (5/5) ## 📝 样本详情 | 样本ID | 问题 | 预测结果 | 正确答案 | 是否正确 | |--------|------|----------|----------|----------| | simple_ python_0 | Find the area of a triangle... | [{'name': 'calculate_ triangle_area'...}] | [{'function_ name': {'base': [10]...}}] | ✅ | | simple_python_ 1 | Calculate the factorial of 5... | [{'name': 'calculate_factorial'...}] | [{'function_ name': {'number': [5]}}] | ✅ | ...## 📊 准确率可视化 准确率: ██████████████████████████████████████████████████ 100.00%## 💡 建议 - ✅ 表现优秀!智能体在工具调用方面表现出色。
方式 2:使用一键评估脚本
适合命令行快速评估,在这一章配套的代码案例里,我们提供了04_run_bfcl_evaluation.py,支持直接命令行调用测评:
1 2 3 4 5 6 7 8 python chapter12/04_run_bfcl_evaluation.py --category simple_python --samples 10 python examples/04_run_bfcl_evaluation.py \ --category simple_python \ --samples 10 \ --model-name "Qwen/Qwen3-8B"
脚本支持三个参数:--category指定评估类别(默认 simple_python),--samples指定评估样本数(默认 5,0 表示全部),--model-name指定模型名称用于 BFCL 官方评估(默认 Qwen/Qwen3-8B)。
方式 3:直接使用 Dataset 和 Evaluator
适合需要自定义评估流程的场景:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 from hello_agents import SimpleAgent, HelloAgentsLLMfrom hello_agents.evaluation import BFCLDataset, BFCLEvaluator llm = HelloAgentsLLM() agent = SimpleAgent(name="TestAgent" , llm=llm) dataset = BFCLDataset( bfcl_data_dir="./temp_gorilla/berkeley-function-call-leaderboard/bfcl_eval/data" , category="simple_python" ) data = dataset.load() evaluator = BFCLEvaluator( dataset=dataset, category="simple_python" , evaluation_mode="ast" ) results = evaluator.evaluate(agent, max_samples=10 )print (f"准确率: {results['overall_accuracy' ]:.2 %} " )print (f"正确数: {results['correct_samples' ]} /{results['total_samples' ]} " ) evaluator.export_to_bfcl_format( results, output_path="./evaluation_results/my_results.json" )
通过以上三种方式,我们可以根据不同的需求选择合适的评估方法。如果只是想快速了解智能体的表现,使用 BFCLEvaluationTool 的一键评估最为便捷;如果需要批量评估或集成到 CI/CD 流程,使用命令行脚本更加合适;如果需要深度定制评估流程或集成到自己的系统中,直接使用 Dataset 和 Evaluator 提供了最大的灵活性。
12.2.4 BFCL 官方评估工具集成 前面我们学习了如何使用 HelloAgents 内置的评估功能。实际上,BFCLEvaluationTool已经自动集成了 BFCL 官方评估工具 ,让你能够获得权威的、可对比的评估结果。
整个评估流程包括四个步骤:首先从 BFCL v4 数据集加载测试数据,然后使用 HelloAgents 运行评估获取智能体的预测结果,接着将结果导出为 BFCL 官方格式(JSONL),最后使用官方评估脚本计算最终分数。这个流程确保了评估结果与 BFCL 排行榜完全一致,如图 12.3 所示:
图 12.3 Helloagents 载入 BFCL 评估过程
使用`BFCLEvaluationTool`时,官方评估会自动运行 (默认启用):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 from hello_agents import SimpleAgent, HelloAgentsLLMfrom hello_agents.tools import BFCLEvaluationTool llm = HelloAgentsLLM() agent = SimpleAgent(name="TestAgent" , llm=llm) bfcl_tool = BFCLEvaluationTool() results = bfcl_tool.run( agent=agent, category="simple_python" , max_samples=5 , model_name="Qwen/Qwen3-8B" )
工具会自动执行完整的评估流程:首先运行 HelloAgents 评估获取预测结果,然后将结果导出为 BFCL 格式并保存到evaluation_results/bfcl_official/目录,接着复制结果文件到result/{model_name}/目录以符合官方评估工具的要求,随后运行 BFCL 官方评估命令计算分数,最后显示官方评估结果并生成 Markdown 格式的评估报告。
官方评估输出示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ============================================================ 步骤3: 运行BFCL官方评估 ============================================================ ✅ 结果文件已复制到: ./result/Qwen_Qwen3-8B/BFCL_v4_simple_python_result.json 🔄 运行命令: bfcl evaluate --model Qwen/Qwen3-8B --test-category simple_python --partial-eval ============================================================ BFCL官方评估结果 ============================================================ 📊 评估结果汇总: Model,Overall Acc,simple_python Qwen/Qwen3-8B,100.00,100.00 🎯 最终结果: 准确率: 100.00% 正确数: 5/5
如果你想手动控制评估流程,可以禁用自动官方评估:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 results = bfcl_tool.run( agent=agent, category="simple_python" , max_samples=5 , run_official_eval=False )import subprocess subprocess.run([ "bfcl" , "evaluate" , "--model" , "Qwen/Qwen3-8B" , "--test-category" , "simple_python" , "--partial-eval" ])
你也可以手动生成报告:
1 2 3 4 5 6 7 8 9 10 11 results = bfcl_tool.run(agent, category="simple_python" , max_samples=5 ) report = bfcl_tool.generate_report( results, output_file="./my_reports/custom_report.md" )print (report)
12.2.5 核心组件实现细节 在前面的小节中,我们学习了如何使用 BFCL 评估工具。现在让我们深入了解 HelloAgents 评估系统的核心组件是如何实现的。理解这些实现细节不仅能帮助你更好地使用评估系统,还能让你根据自己的需求进行定制和扩展。
(1)BFCLDataset:数据集加载器
BFCLDataset 负责加载和管理 BFCL 数据集:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 class BFCLDataset : """BFCL数据集加载器""" def __init__ (self, category: str = "simple" , local_data_path: Optional [str ] = None ): self.category = category self.local_data_path = local_data_path self.data = [] def load (self ) -> List [Dict [str , Any ]]: """加载数据集""" if self.local_data_path: return self._load_from_local() return self._load_from_huggingface()
因为 BFCL 的数据集就在官方的仓库内,所以这里建议的方式是直接在本地 clone 一份进行测评。当找不到时才到 huggingface 进行加载。
(2)BFCLEvaluator:评估执行器
BFCLEvaluator 负责执行评估流程。它的核心是evaluate()方法,该方法协调整个评估过程:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 class BFCLEvaluator : """BFCL评估器""" def evaluate (self, agent: Any , max_samples: Optional [int ] = None ) -> Dict [str , Any ]: """执行评估""" results = [] for item in self.dataset[:max_samples]: prompt = self._build_prompt(item) response = agent.run(prompt) predicted_calls = self._extract_function_calls(response) is_correct = self._compare_calls(predicted_calls, item["ground_truth" ]) results.append({ "id" : item["id" ], "prediction" : predicted_calls, "ground_truth" : item["ground_truth" ], "is_correct" : is_correct }) return {"results" : results, "total_samples" : len (results)}
这个评估器的设计包含三个核心要点:首先是提示词构造,需要将数据集中的问题和函数定义转换为智能体可理解的提示词;其次是函数调用提取,需要从智能体的响应中提取函数调用,并支持多种格式(JSON、代码块等);最后是 AST 匹配,使用抽象语法树进行函数调用对比,这比简单的字符串匹配更准确。
让我们看看函数调用提取的实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 def _extract_function_calls (self, response: str ) -> List [Dict [str , Any ]]: """从响应中提取函数调用 支持多种格式: 1. JSON格式:{"name": "func", "arguments": {...}} 2. 代码块格式:```python\nfunc(arg1=val1)\n``` 3. 纯文本格式:func(arg1=val1) """ calls = [] try : json_match = re.search(r'\{.*\}' , response, re.DOTALL) if json_match: data = json.loads(json_match.group()) if isinstance (data, dict ) and "name" in data: calls.append(data) elif isinstance (data, list ): calls.extend(data) except json.JSONDecodeError: pass code_blocks = re.findall(r'```(?:python)?\n(.*?)\n```' , response, re.DOTALL) for code in code_blocks: parsed_calls = self._parse_python_calls(code) calls.extend(parsed_calls) return calls
(3)BFCLMetrics:指标计算器
BFCLMetrics 负责计算各种评估指标:
1 2 3 4 5 6 7 8 9 10 11 12 class BFCLMetrics : """BFCL指标计算器""" def compute_metrics (self, results: List [Dict [str , Any ]] ) -> Dict [str , Any ]: """计算所有指标""" return { "accuracy" : self._compute_accuracy(results), "ast_match_rate" : self._compute_ast_match_rate(results), "parameter_accuracy" : self._compute_parameter_accuracy(results), "f1_score" : self._compute_f1_score(results), "category_statistics" : self._compute_category_stats(results) }
AST 匹配的实现 :
AST 匹配是 BFCL 评估的核心技术。它比简单的字符串匹配更智能,能够识别语义等价的函数调用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 def _ast_match (self, pred_call: Dict , true_call: Dict ) -> bool : """使用AST匹配函数调用 AST匹配的优势: 1. 忽略参数顺序:func(a=1, b=2) 等价于 func(b=2, a=1) 2. 识别等价表达式:2+3 等价于 5 3. 忽略空格和格式差异 """ if pred_call.get("name" ) != true_call.get("name" ): return False pred_args = self._args_to_ast(pred_call.get("arguments" , {})) true_args = self._args_to_ast(true_call.get("arguments" , {})) return ast.dump(pred_args) == ast.dump(true_args)def _args_to_ast (self, args: Dict [str , Any ] ) -> ast.AST: """将参数字典转换为AST节点""" code = f"func({', ' .join(f'{k} ={repr (v)} ' for k, v in args.items())} )" tree = ast.parse(code) return tree.body[0 ].value
(4)工具化封装:BFCLEvaluationTool
最后,我们将这些组件封装成一个 Tool,让它可以被智能体直接调用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 class BFCLEvaluationTool (Tool ): """BFCL评估工具""" def __init__ (self, local_data_path: Optional [str ] = None ): super ().__init__( name="bfcl_evaluation" , description="评估智能体的工具调用能力" ) self.dataset = None self.evaluator = None self.metrics_calculator = BFCLMetrics() def run (self, parameters: Dict [str , Any ] ) -> str : """执行评估""" self.dataset = BFCLDataset(...) self.evaluator = BFCLEvaluator(...) results = self.evaluator.evaluate(...) metrics = self.metrics_calculator.compute_metrics(...) return json.dumps(results, ensure_ascii=False )
这个工具的设计遵循三个核心原则:首先继承 Tool 基类以遵循 HelloAgents 的工具规范,确保与框架的无缝集成;其次进行严格的参数验证,检查必需参数并提供友好的错误提示,提升用户体验;最后对结果进行格式化,返回 JSON 字符串以便于解析和展示。通过这种模块化的设计,我们实现了一个既易用又灵活的评估系统,用户可以直接使用高层的 Tool 接口快速完成评估,也可以深入到底层组件进行定制以满足特殊需求。
12.2.6 扩展与优化建议 通过前面的学习,我们已经掌握了如何使用 HelloAgents 进行 BFCL 评估。需要注意的是,我们目前的实现是基于 SimpleAgent 的简单复现,主要完成了 BFCL 评估的基础功能。在实际应用中,BFCL 基准包含多个难度级别和场景,要在排行榜上获得更高的分数,还需要进一步的优化和扩展。
(1)当前实现的局限性
我们当前的 SimpleAgent 实现主要聚焦于评估流程的搭建,在工具调用能力上还有提升空间。SimpleAgent 使用自定义的工具调用格式[TOOL_CALL:tool_name:parameters],这种格式需要 LLM 主动学习和使用,在复杂场景下的表现可能不如使用原生函数调用(Function Calling)的智能体。此外,我们目前只测试了 simple_python 等基础类别,对于 multiple、parallel、irrelevance 等更复杂的场景,还需要针对性的优化。
(2)提升 BFCL 分数的方向
要进一步提升 BFCL 评估分数,可以从以下几个方向入手。首先是优化智能体的工具调用能力,可以考虑使用支持原生函数调用的 LLM(如 GPT-4、Claude 等),或者改进提示词让 LLM 更好地理解工具调用格式。其次是扩展工具库,BFCL 测试中涉及各种类型的函数,可以根据测试数据集的特点,预先实现常用的工具类型,提高智能体的工具覆盖率。第三是针对不同难度级别设计不同的策略,例如在 multiple 场景下需要智能体能够规划多步骤的工具调用序列,在 parallel 场景下需要识别可以并行执行的工具调用,在 irrelevance 场景下需要判断是否真的需要调用工具。
(3)实践建议
对于想要在 BFCL 上取得更好成绩的开发者,建议采用以下实践策略。首先,从 simple 类别开始,确保基础的单函数调用能够稳定工作,这是后续优化的基础。然后,逐步测试 multiple、parallel 等更复杂的类别,分析失败案例,找出智能体的薄弱环节。在优化过程中,可以参考 BFCL 排行榜上的高分模型,学习它们的设计思路和优化技巧。同时,建议使用官方评估工具进行验证,确保优化后的结果与排行榜标准一致。
这里总结一些评估时可以进一步处理的建议:
1. 渐进式评估
从小样本开始,逐步增加样本数:
1 2 3 4 5 6 7 8 9 10 results_quick = bfcl_tool.run(agent, category="simple_python" , max_samples=5 )if results_quick['overall_accuracy' ] > 0.8 : results_medium = bfcl_tool.run(agent, category="simple_python" , max_samples=50 )if results_medium['overall_accuracy' ] > 0.8 : results_full = bfcl_tool.run(agent, category="simple_python" , max_samples=0 )
2. 多类别评估
评估不同难度的任务:
1 2 3 4 5 6 categories = ["simple_python" , "multiple" , "parallel" , "irrelevance" ]for category in categories: print (f"\n评估类别: {category} " ) results = bfcl_tool.run(agent, category=category, max_samples=10 ) print (f"准确率: {results['overall_accuracy' ]:.2 %} " )
3. 对比评估
对比不同配置的智能体:
1 2 3 4 5 6 7 8 9 10 11 12 agent1 = SimpleAgent(name="Agent-Default" , llm=llm) results1 = bfcl_tool.run(agent1, category="simple_python" , max_samples=10 ) agent2 = SimpleAgent(name="Agent-Optimized" , llm=llm) results2 = bfcl_tool.run(agent2, category="simple_python" , max_samples=10 )print (f"默认配置准确率: {results1['overall_accuracy' ]:.2 %} " )print (f"优化配置准确率: {results2['overall_accuracy' ]:.2 %} " )
如果你的评估结果很好,可以考虑提交到 BFCL 官方排行榜!
步骤 1:准备提交材料
模型描述文档
评估结果文件(所有类别)
模型访问方式(API 或开源链接)
步骤 2:提交到 GitHub
访问 BFCL 官方仓库,按照说明提交 Pull Request:
步骤 3:等待审核
BFCL 团队会审核你的提交,验证结果的准确性。审核通过后,你的模型将出现在官方排行榜上!
12.3 GAIA:通用 AI 助手能力评估 12.3.1 GAIA 基准介绍 GAIA (General AI Assistants) 是由 Meta AI 和 Hugging Face 联合推出的评估基准,专注于评估 AI 助手的通用能力 [2] 。与 BFCL 专注于工具调用不同,GAIA 评估的是智能体在真实世界任务中的综合表现。
GAIA 的设计理念是:真实世界的问题往往需要多种能力的综合运用 。一个优秀的 AI 助手不仅需要调用工具,还需要:
多步推理 :将复杂问题分解为多个子问题
知识运用 :利用内置知识和外部知识库
多模态理解 :处理文本、图片、文件等多种输入
网页浏览 :从互联网获取最新信息
文件操作 :读取和处理各种格式的文件
(1)GAIA 数据集结构
了解 GAIA 的评估理念后,让我们深入了解 GAIA 数据集的具体结构。GAIA 包含 466 个精心设计的真实世界问题,这些问题按照复杂度和所需推理步骤分为三个难度级别,从简单的零步推理任务到需要多步复杂推理的困难任务,全面覆盖了智能体在实际应用中可能遇到的各种场景,如表 12.3 所示:
表 12.3 GAIA 数据集难度级别分布
关于 GAIA 数据集的样本示例可以参考下面的代码片段:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 { "task_id" : "gaia_001" , "Question" : "What is the total population of the top 3 most populous cities in California?" , "Level" : 2 , "Final answer" : "12847521" , "file_name" : "" , "file_path" : "" , "Annotator Metadata" : { "Steps" : [ "Search for most populous cities in California" , "Get population data for top 3 cities" , "Sum the populations" ] , "Number of steps" : 3 , "How long did this take?" : "5 minutes" , "Tools" : [ "web_search" , "calculator" ] } }
关键字段说明:
Question: 问题描述
Level: 难度级别(1-3)
Final answer: 标准答案(可能是数字、文本或文件)
file_name/file_path: 附件文件(如果有)
Annotator Metadata: 标注者提供的元数据(推理步骤、所需工具等)
(2)准精确匹配介绍
GAIA 使用准精确匹配(Quasi Exact Match) 评估算法,这是 GAIA 官方定义的评估标准。该算法的核心思想是:先对答案进行归一化处理,然后进行精确匹配 。
给定预测答案 $A_{\text{pred}}$ 和标准答案 $A_{\text{true}}$,准精确匹配函数定义为:
$$ \text{Quasi_Exact_Match}(A_{\text{pred}}, A_{\text{true}}) = \begin{cases} 1 & \text{if } \mathcal{N}(A_{\text{pred}}) = \mathcal{N}(A_{\text{true}}) \ 0 & \text{otherwise} \end{cases} $$
其中 $\mathcal{N}(\cdot)$ 是归一化函数,根据答案类型应用不同的规则。
归一化函数根据答案类型应用不同的规则。对于数字类型,需要移除逗号分隔符(1,000 → 1000)和单位符号($100 → 100,50% → 50),例如"$1,234.56"归一化为"1234.56"。对于字符串类型,需要转换为小写("Apple" → "apple")、移除冠词("the apple" → "apple")、移除多余空格("hello world" → "hello world")和移除末尾标点("hello." → "hello"),例如"The United States"归一化为"united states"。对于列表类型,需要按逗号分隔元素,对每个元素应用字符串归一化,按字母顺序排序后重新连接,例如"Paris, London, Berlin"归一化为"berlin,london,paris"。
归一化示例:
1 2 3 4 5 6 7 8 9 10 11 原始答案: "$1,234.56" 归一化后: "1234.56" 原始答案: "The United States of America" 归一化后: "united states of america" 原始答案: "Paris, London, Berlin" 归一化后: "berlin, london, paris"
(3)GAIA 评估指标
GAIA 使用以下指标评估智能体性能:
1. 精确匹配率 (Exact Match Rate)
精确匹配率是 GAIA 的核心指标,定义为准精确匹配成功的样本比例:
$$ \text{Exact Match Rate} = \frac{1}{N} \sum_{i=1}^{N} \text{Quasi_Exact_Match}(A_{\text{pred},i}, A_{\text{true},i}) $$
其中:
$N$ 是总样本数
$A_{\text{pred},i}$ 是第 $i$ 个样本的预测答案
$A_{\text{true},i}$ 是第 $i$ 个样本的标准答案
$\text{Quasi_Exact_Match}(\cdot, \cdot) \in {0, 1}$ 是准精确匹配函数
2. 分级准确率 (Level-wise Accuracy)
对于每个难度级别 $\ell \in {1, 2, 3}$,计算该级别的准确率:
$$ \text{Accuracy}\ell = \frac{1}{|D_\ell|} \sum {i \in D_\ell} \text{Quasi_Exact_Match}(A_{\text{pred},i}, A_{\text{true},i}) $$
其中 $D_\ell$ 是难度级别 $\ell$ 的样本集合,$|D_\ell|$ 是该级别的样本数。
3. 难度递进下降率 (Difficulty Progression Drop Rate)
衡量智能体在难度增加时的性能衰减:
$$ \text{Drop Rate}_{\ell \to \ell+1} = \frac{\text{Accuracy}\ell - \text{Accuracy} {\ell+1}}{\text{Accuracy}_\ell} $$
$\text{Drop Rate}_{1 \to 2}$:从 Level 1 到 Level 2 的下降率
$\text{Drop Rate}_{2 \to 3}$:从 Level 2 到 Level 3 的下降率
4. 平均推理步骤数 (Average Reasoning Steps)
评估智能体完成任务所需的平均步骤数:
$$ \text{Avg Steps} = \frac{1}{N_{\text{correct}}} \sum_{i \in \text{Correct}} \text{steps}_i $$
其中 $N_{\text{correct}}$ 是正确回答的样本数,$\text{steps}_i$ 是第 $i$ 个样本的推理步骤数。
指标解释:
Exact Match Rate = 1.0 :所有样本都完全正确
Exact Match Rate = 0.5 :50%的样本正确,50%的样本错误
Drop Rate = 0.3 :难度增加导致准确率下降 30%
Drop Rate = 0.0 :难度增加不影响准确率(理想情况)
评估示例:
假设我们评估了 10 个样本,结果可以参考表 12.4 所示:
表 12.4 GAIA 数据集难度级别分布
如果要计算这个案例的指标的话,可以参考下面的 Python 脚本。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 total_samples = 10 correct_samples = 7 exact_match_rate = correct_samples / total_samples = 0.70 level_1_correct = 3 level_1_total = 3 level_1_accuracy = 3 / 3 = 1.00 level_2_correct = 2 level_2_total = 3 level_2_accuracy = 2 / 3 = 0.67 level_3_correct = 2 level_3_total = 4 level_3_accuracy = 2 / 4 = 0.50 drop_rate_1_to_2 = (1.00 - 0.67 ) / 1.00 = 0.33 drop_rate_2_to_3 = (0.67 - 0.50 ) / 0.67 = 0.25 print (f"精确匹配率: {exact_match_rate:.2 %} " ) print (f"Level 1准确率: {level_1_accuracy:.2 %} " ) print (f"Level 2准确率: {level_2_accuracy:.2 %} " ) print (f"Level 3准确率: {level_3_accuracy:.2 %} " ) print (f"Level 1→2 下降率: {drop_rate_1_to_2:.2 %} " ) print (f"Level 2→3 下降率: {drop_rate_2_to_3:.2 %} " )
结果分析:
整体表现 :70%的精确匹配率,表现良好
难度敏感性 :从 Level 1 到 Level 2 下降 33%,说明智能体在中等难度任务上有明显衰减
能力边界 :Level 3 准确率为 50%,说明智能体在复杂任务上仍有提升空间
下降率越大,说明智能体在处理复杂任务时的能力衰减越明显。
(4)GAIA 官方系统提示词
GAIA 要求使用特定的系统提示词,确保模型输出符合评估格式:
1 2 3 4 5 6 7 8 9 GAIA_SYSTEM_PROMPT = """You are a general AI assistant. I will ask you a question. Report your thoughts, and finish your answer with the following template: FINAL ANSWER: [YOUR FINAL ANSWER]. YOUR FINAL ANSWER should be a number OR as few words as possible OR a comma separated list of numbers and/or strings. If you are asked for a number, don't use comma to write your number neither use units such as $ or percent sign unless specified otherwise. If you are asked for a string, don't use articles, neither abbreviations (e.g. for cities), and write the digits in plain text unless specified otherwise. If you are asked for a comma separated list, apply the above rules depending of whether the element to be put in the list is a number or a string."""
GAIA 对答案格式有严格的要求:答案必须以FINAL ANSWER: [答案]的格式给出;对于数字类型的答案,不使用逗号分隔符和单位符号;对于字符串类型的答案,不使用冠词和缩写;对于列表类型的答案,使用逗号分隔并按字母顺序排列。
12.3.2 获取 GAIA 数据集 重要提示 :GAIA 是受限数据集(Gated Dataset) ,需要先在 HuggingFace 上申请访问权限。
步骤 1:申请访问权限
访问 https://huggingface.co/datasets/gaia-benchmark/GAIA
点击”Request access”按钮
填写申请表单(通常会在几秒内批准)
获取你的 HuggingFace Token:https://huggingface.co/settings/tokens
步骤 2:配置环境变量
在.env文件中添加你的 HuggingFace Token:
1 2 HF_TOKEN=hf_your_token_here
方法 1:使用 HelloAgents 自动下载(推荐)
HelloAgents 会自动处理 GAIA 数据集的下载和缓存:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 from hello_agents.evaluation import GAIADatasetimport os os.environ["HF_TOKEN" ] = "hf_your_token_here" dataset = GAIADataset( dataset_name="gaia-benchmark/GAIA" , split="validation" , level=1 ) items = dataset.load()print (f"加载了 {len (items)} 个测试样本" )
工作原理 :
首次运行时,使用snapshot_download下载整个数据集到./data/gaia/
数据集包含 114 个文件(问题、图片、PDF 等材料)
后续使用直接从本地加载,速度很快
数据集目录结构 :
1 2 3 4 5 6 7 8 9 10 ./data/gaia/ ├── 2023 / │ ├── validation/ │ │ ├── metadata.jsonl (165 个问题) │ │ ├── *.png , *.pdf , *.csv , *.xlsx (附件文件) │ └── test/ │ ├── metadata.jsonl (301 个问题) │ └── ... (附件文件) ├── GAIA.py └── README.md
方法 2:手动下载
如果你想手动下载数据集:
1 2 3 4 5 6 7 8 9 10 11 12 13 from huggingface_hub import snapshot_downloadimport os os.environ["HF_TOKEN" ] = "hf_your_token_here" snapshot_download( repo_id="gaia-benchmark/GAIA" , repo_type="dataset" , local_dir="./data/gaia" , token=os.getenv("HF_TOKEN" ) )
查看数据集统计 :
1 2 3 4 5 6 7 stats = dataset.get_statistics()print (f"总样本数: {stats['total_samples' ]} " )print (f"级别分布: {stats['level_distribution' ]} " )
12.3.3 在 HelloAgents 中实现 GAIA 评估 与 BFCL 类似,我们提供两种评估方式,推荐使用方式 1 。
方式 1:使用 GAIAEvaluationTool 一键评估
这是最简单的方式,自动完成数据集下载、评估执行、结果导出和报告生成:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 from hello_agents import SimpleAgent, HelloAgentsLLMfrom hello_agents.tools import GAIAEvaluationTool GAIA_SYSTEM_PROMPT = """You are a general AI assistant. I will ask you a question. Report your thoughts, and finish your answer with the following template: FINAL ANSWER: [YOUR FINAL ANSWER]. YOUR FINAL ANSWER should be a number OR as few words as possible OR a comma separated list of numbers and/or strings. If you are asked for a number, don't use comma to write your number neither use units such as $ or percent sign unless specified otherwise. If you are asked for a string, don't use articles, neither abbreviations (e.g. for cities), and write the digits in plain text unless specified otherwise. If you are asked for a comma separated list, apply the above rules depending of whether the element to be put in the list is a number or a string.""" llm = HelloAgentsLLM() agent = SimpleAgent( name="TestAgent" , llm=llm, system_prompt=GAIA_SYSTEM_PROMPT ) gaia_tool = GAIAEvaluationTool() results = gaia_tool.run( agent=agent, level=1 , max_samples=5 , export_results=True , generate_report=True )print (f"精确匹配率: {results['exact_match_rate' ]:.2 %} " )print (f"部分匹配率: {results['partial_match_rate' ]:.2 %} " )print (f"正确数: {results['exact_matches' ]} /{results['total_samples' ]} " )
运行结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 ============================================================ GAIA一键评估 ============================================================ 配置: 智能体: TestAgent 难度级别: 1 样本数量: 5 ============================================================ 步骤1: 运行HelloAgents评估 ============================================================ 正在从HuggingFace下载: gaia-benchmark/GAIA 📥 下载GAIA数据集... ✓ 数据集下载完成 ✓ 加载了 165 个样本 ✅ GAIA数据集加载完成 数据源: gaia-benchmark/GAIA 分割: validation 级别: 1 样本数: 53 🌟 开始 GAIA 评估... 样本数量: 5 进度: 5/5 ✅ GAIA 评估完成 精确匹配率: 80.00% 部分匹配率: 80.00% ============================================================ 步骤2: 导出GAIA格式结果 ============================================================ ✅ GAIA格式结果已导出 输出文件: evaluation_results\gaia_official\gaia_level1_result_20251011_012648.jsonl 样本数: 5 包含推理轨迹: True 📄 提交说明已生成: evaluation_results\gaia_official\SUBMISSION_GUIDE_20251011_012648.md ============================================================ 步骤3: 生成评估报告 ============================================================ 📄 报告已生成: evaluation_reports\gaia_report_20251011_012648.md ============================================================ 🎯 最终结果 ============================================================ 精确匹配率: 80.00% 部分匹配率: 80.00% 正确数: 4/5
评估完成后会自动生成三类文件:首先是 GAIA 格式结果文件(evaluation_results/gaia_official/gaia_level1_result_*.jsonl),采用 JSONL 格式(每行一个 JSON 对象),可直接用于提交到 GAIA 排行榜;其次是提交说明文件(evaluation_results/gaia_official/SUBMISSION_GUIDE_*.md),包含详细的提交步骤、结果文件格式说明和注意事项;最后是评估报告(evaluation_reports/gaia_report_*.md),包含评估结果摘要、详细指标、样本详情和可视化图表。
注意 :如果你发现生成的评估结果不理想(例如准确率较低),这是正常现象。虽然 Level 1 是一步推理任务,但仍然需要智能体具备工具调用能力(如搜索引擎、计算器等)才能正确回答问题。我们当前使用的 SimpleAgent 主要用于演示评估流程,在工具调用能力上还有提升空间。
方式 2:使用 Dataset + Evaluator(灵活定制)
如果需要更细粒度的控制,可以直接使用底层组件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 from hello_agents.evaluation import GAIADataset, GAIAEvaluator dataset = GAIADataset(level=1 ) items = dataset.load()print (f"加载了 {len (items)} 个样本" ) evaluator = GAIAEvaluator(dataset=dataset, level=1 ) results = evaluator.evaluate(agent, max_samples=5 ) evaluator.export_to_gaia_format( results, "gaia_results.jsonl" , include_reasoning=True )
生成的评估报告(gaia_report_*.md)可参考下面的文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 # GAIA评估报告 **生成时间** : 2025-10-11 01:26:48## 📊 评估概览 - **智能体** : TestAgent- **难度级别** : 1- **总样本数** : 2- **精确匹配数** : 1- **部分匹配数** : 1- **精确匹配率** : 50.00%- **部分匹配率** : 50.00%## 📈 详细指标 ### 分级准确率 - **Level 1** : 50.00% 精确 / 50.00% 部分 (1/2)## 📝 样本详情(前10个) | 任务ID | 级别 | 预测答案 | 正确答案 | 精确匹配 | 部分匹配 | |--------|------|----------|----------|----------|----------| | e1fc63a2-da7a-432f-be78-7c4a95598703 | 1 | 24000 | 17 | ❌ | ❌ | | 8e867cd7-cff9-4e6c-867a-ff5ddc2550be | 1 | 3 | 3 | ✅ | ✅ |## 📊 准确率可视化 精确匹配: █████████████████████████░░░░░░░░░░░░░░░░░░░░░░░░░ 50.00% 部分匹配: █████████████████████████░░░░░░░░░░░░░░░░░░░░░░░░░ 50.00%## 💡 建议 - ⚠️ 表现一般,需要改进。- 💡 建议检查工具使用和多步推理能力。
**生成的 GAIA 格式结果(gaia_level1_result_*.jsonl):
1 2 { "task_id" : "e1fc63a2-da7a-432f-be78-7c4a95598703" , "model_answer" : "24000" , "reasoning_trace" : "24000" } { "task_id" : "8e867cd7-cff9-4e6c-867a-ff5ddc2550be" , "model_answer" : "3" , "reasoning_trace" : "3" }
12.3.4 提交结果到 GAIA 官方排行榜 使用 GAIAEvaluationTool 运行评估后,会在evaluation_results/gaia_official/目录下生成提交所需的文件和详细的提交说明。
GAIA 格式结果文件**:gaia_level1_result_*.jsonl
1 2 { "task_id" : "xxx" , "model_answer" : "答案" , "reasoning_trace" : "推理过程" } { "task_id" : "yyy" , "model_answer" : "答案" , "reasoning_trace" : "推理过程" }
提交说明文件 :SUBMISSION_GUIDE_*.md
打开自动生成的SUBMISSION_GUIDE_*.md文件,里面包含完整的提交指南:
具体来说,打开浏览器,访问:
1 https:// huggingface.co/spaces/g aia-benchmark/leaderboard
如图 12.4 所示,提交表单中填写信息即可:
图 12.4 BFCL 评估流程图
提交前,可以手动检查生成的 JSONL 文件:
1 2 3 4 5 6 7 8 9 10 import jsonwith open ("evaluation_results/gaia_official/gaia_level1_result_*.jsonl" , "r" ) as f: for line in f: result = json.loads(line) print (f"Task ID: {result['task_id' ]} " ) print (f"Answer: {result['model_answer' ]} " ) print (f"Reasoning: {result['reasoning_trace' ]} " ) print ("-" * 50 )
12.3.5 核心组件实现细节 GAIA 评估系统的实现与 BFCL 类似,但针对通用能力评估有一些特殊的设计。
(1)GAIADataset:支持多模态的数据加载器
GAIA 数据集的特殊之处在于它包含多模态数据(文本、文件、图片等):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 class GAIADataset : """GAIA数据集加载器 支持从HuggingFace加载GAIA数据集(受限数据集) """ def __init__ ( self, level: Optional [int ] = None , split: str = "validation" , local_data_dir: Optional [str ] = None ): self.level = level self.split = split self.local_data_dir = local_data_dir or "./data/gaia" self.data = [] def load (self ) -> List [Dict [str , Any ]]: """加载数据集""" items = self._load_from_huggingface() if self.level: items = [item for item in items if item.get("level" ) == self.level] self.data = items return items def _load_from_huggingface (self ) -> List [Dict [str , Any ]]: """从HuggingFace下载GAIA数据集""" from huggingface_hub import snapshot_download import json repo_id = "gaia-benchmark/GAIA" local_dir = snapshot_download( repo_id=repo_id, repo_type="dataset" , local_dir=self.local_data_dir, local_dir_use_symlinks=False ) data_file = Path(local_dir) / "2023" / self.split / "metadata.jsonl" items = [] with open (data_file, 'r' , encoding='utf-8' ) as f: for line in f: item = json.loads(line) items.append(self._standardize_item(item)) return items
(2)GAIAEvaluator:实现 GAIA 官方评估算法
GAIA 的评估使用准精确匹配(Quasi Exact Match) 算法,需要特殊的答案归一化和匹配逻辑:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 class GAIAEvaluator : """GAIA评估器 实现GAIA官方的准精确匹配(Quasi Exact Match)评估算法 """ def evaluate (self, agent: Any , max_samples: Optional [int ] = None ) -> Dict [str , Any ]: """执行评估""" dataset_items = self.dataset.load() if max_samples: dataset_items = dataset_items[:max_samples] results = [] for i, item in enumerate (dataset_items, 1 ): prompt = self._build_prompt(item["question" ], item) response = agent.run(prompt) predicted_answer = self._extract_answer(response) normalized_pred = self._normalize_answer(predicted_answer) normalized_truth = self._normalize_answer(item["final_answer" ]) exact_match = (normalized_pred == normalized_truth) results.append({ "task_id" : item["task_id" ], "predicted" : predicted_answer, "expected" : item["final_answer" ], "exact_match" : exact_match, "level" : item.get("level" , 0 ) }) return self._format_results(results)
GAIA 使用特定的归一化规则来处理不同类型的答案:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 def _normalize_answer (self, answer: str ) -> str : """标准化答案字符串(GAIA官方标准化规则) 规则: 1. 数字:移除逗号分隔符和单位符号 2. 字符串:移除冠词、转小写、移除多余空格 3. 列表:逗号分隔,按字母顺序排序 """ if not answer: return "" answer = answer.strip() if ',' in answer: parts = [self._normalize_single_answer(p.strip()) for p in answer.split(',' )] parts.sort() return ',' .join(parts) else : return self._normalize_single_answer(answer)def _normalize_single_answer (self, answer: str ) -> str : """标准化单个答案(不包含逗号的答案)""" answer = answer.strip().lower() articles = ['the' , 'a' , 'an' ] words = answer.split() if words and words[0 ] in articles: words = words[1 :] answer = ' ' .join(words) answer = answer.replace('$' , '' ).replace('%' , '' ).replace('€' , '' ).replace('£' , '' ) answer = re.sub(r'(\d),(\d)' , r'\1\2' , answer) answer = ' ' .join(answer.split()) answer = answer.rstrip('.,;:!?' ) return answer
GAIA 要求模型输出格式为FINAL ANSWER: [答案]:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 def _extract_answer (self, response: str ) -> str : """从响应中提取答案(GAIA格式) GAIA要求答案格式为:FINAL ANSWER: [答案] """ final_answer_pattern = r'FINAL ANSWER:\s*(.+?)(?:\n|$)' match = re.search(final_answer_pattern, response, re.IGNORECASE | re.MULTILINE) if match : answer = match .group(1 ).strip() answer = answer.strip('[]' ) return answer answer_patterns = [ r'答案[::]\s*(.+)' , r'最终答案[::]\s*(.+)' , r'Final answer[::]\s*(.+)' , r'Answer[::]\s*(.+)' , ] for pattern in answer_patterns: match = re.search(pattern, response, re.IGNORECASE) if match : return match .group(1 ).strip() lines = response.strip().split('\n' ) for line in reversed (lines): line = line.strip() if line and not line.startswith('#' ): return line return response.strip()
评估完成后,可以导出为 GAIA 官方要求的 JSONL 格式:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 def export_to_gaia_format ( self, results: Dict [str , Any ], output_path: Union [str , Path], include_reasoning: bool = True ) -> None : """导出为GAIA官方格式(JSONL) GAIA要求的格式: {"task_id": "xxx", "model_answer": "答案", "reasoning_trace": "推理过程"} """ output_path = Path(output_path) output_path.parent.mkdir(parents=True , exist_ok=True ) with open (output_path, 'w' , encoding='utf-8' ) as f: for result in results.get("detailed_results" , []): entry = { "task_id" : result["task_id" ], "model_answer" : result["predicted" ] } if include_reasoning: entry["reasoning_trace" ] = result.get("response" , result["predicted" ]) f.write(json.dumps(entry, ensure_ascii=False ) + '\n' )
(3)GAIAEvaluationTool:一键评估工具
GAIAEvaluationTool 封装了完整的评估流程,提供一键评估功能:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 class GAIAEvaluationTool (Tool ): """GAIA评估工具 提供一键评估功能: 1. 运行HelloAgents评估 2. 导出GAIA格式结果 3. 生成评估报告 4. 生成提交说明 """ def run ( self, agent: Any , level: Optional [int ] = None , max_samples: Optional [int ] = None , local_data_dir: Optional [str ] = None , export_results: bool = True , generate_report: bool = True ) -> Dict [str , Any ]: """执行GAIA一键评估""" results = self._run_evaluation(agent, level, max_samples, local_data_dir) if export_results: self._export_results(results) if generate_report: self.generate_report(results) return results
GAIAEvaluationTool 会自动生成评估报告:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 def generate_report ( self, results: Dict [str , Any ], output_file: Optional [Union [str , Path]] = None ) -> str : """生成评估报告""" report = f"""# GAIA评估报告 **生成时间**: {datetime.now().strftime("%Y-%m-%d %H:%M:%S" )} ## 📊 评估概览 - **智能体**: {results.get("agent_name" , "Unknown" )} - **难度级别**: {results.get("level_filter" ) or '全部' } - **总样本数**: {results.get("total_samples" , 0 )} - **精确匹配数**: {results.get("exact_matches" , 0 )} - **精确匹配率**: {results.get("exact_match_rate" , 0 ):.2 %} ## 📈 详细指标 ### 分级准确率 {self._format_level_metrics(results.get("level_metrics" , {} ))}## 📝 样本详情(前10个) {self._format_sample_details(results.get("detailed_results" , [])[:10 ])} ## 📊 准确率可视化 {self._format_visualization(results.get("exact_match_rate" , 0 ))} ## 💡 建议 {self._format_suggestions(results.get("exact_match_rate" , 0 ))} """ if output_file is None : output_dir = Path("./evaluation_reports" ) output_dir.mkdir(parents=True , exist_ok=True ) output_file = output_dir / f"gaia_report_{datetime.now().strftime('%Y%m%d_%H%M%S' )} .md" with open (output_file, 'w' , encoding='utf-8' ) as f: f.write(report) return report
12.4 数据生成质量评估 在 AI 系统开发中,高质量的训练数据是系统性能的基础。本节介绍如何使用 HelloAgents 框架评估生成数据的质量,以 AIME(美国数学邀请赛)[9] 风格的数学题目生成为例。
AIME 是美国数学协会(MAA)主办的中等难度数学竞赛,介于 AMC 10/12 和美国数学奥林匹克(USAMO)之间。AIME 题目具有鲜明的特点:每道题的答案都是 0 到 999 之间的整数,题目涵盖代数、几何、数论、组合、概率等多个数学领域,需要多步推理但不涉及高深理论,难度适中(相当于 AIME 第 6-9 题的水平)。这些特点使得 AIME 题目成为评估数学题目生成质量的理想基准:答案格式统一便于自动化评估,题目难度适中适合大规模生成。我们使用 HuggingFace 上的TianHongZXY/aime-1983-2025数据集作为参考,该数据集包含从 1983 年到 2025 年的 900 多道 AIME 真题,为我们的生成和评估提供了丰富的参考样本。
12.4.1 评估方法概述 在数据生成质量评估中,我们采用三种互补的评估方法:LLM Judge、Win Rate 和人工打分。选择这三种方法有两个重要原因。首先,从方法论角度来看,这些是当前智能体领域常用的自动化测评方案,也是许多学术论文中的主流做法,具有广泛的认可度和实践基础。其次,从适用性角度来看,这三种方法天然适合我们的评估场景:LLM Judge 和 Win Rate 用于评估题目生成质量(从正确性、清晰度、难度匹配等维度进行多维度评估),而人工打分用于评估答案生成质量(通过人类专家验证答案的准确性),这种分工非常合理且易于理解。
下面我们详细介绍这三种评估方法的具体实现。整个案例的实现流程如图 12.5 所示:
图 12.5 数据生成质量评估流程图
(1)LLM Judge 评估
设计动机 :在数据生成质量评估中,我们需要对大量生成的题目进行快速、一致的质量评估。传统的人工评估虽然准确,但成本高、效率低,难以应对大规模数据生成的需求。LLM Judge 通过使用大语言模型作为评委,可以自动化地从多个维度评估生成数据的质量,不仅大幅提升评估效率,还能保持评估标准的一致性。更重要的是,LLM Judge 可以提供详细的评分理由和改进建议,帮助我们理解生成数据的优缺点,为后续优化提供方向。
在我们的实现中,LLM Judge 从四个关键维度评估 AIME 题目的质量:
表 12.5 LLM Judge 评估 AIME 题目的维度
有了四个维度的评分后,我们需要将这些评分汇总成整体的评估指标。我们定义了三个关键指标来衡量生成题目的质量水平:
评估指标 :
1. 平均分(Average Score) :计算所有题目在四个维度上的平均得分,反映生成题目的整体质量水平。 $$ \text{Average Score} = \frac{1}{N} \sum_{i=1}^{N} \frac{\sum_{d=1}^{4} S_{i,d}}{4} $$
2. 及格率(Pass Rate) :统计平均分达到 3.5 分及以上的题目比例,反映生成题目的基本质量保障。
$$ \text{Pass Rate} = \frac{|{i : \text{Score}_i \geq 3.5}|}{N} $$
3. 优秀率(Excellent Rate) :统计平均分达到 4.5 分及以上的题目比例,反映生成题目的高质量占比。
$$ \text{Excellent Rate} = \frac{|{i : \text{Score}_i \geq 4.5}|}{N} $$
其中:
$N$ 是评估的题目总数
$S_{i,d}$ 是第 $i$ 个题目在第 $d$ 个维度的得分(1-5 分)
$\text{Score}_i$ 是第 $i$ 个题目的平均分(四个维度得分的平均值)
这三个指标从不同角度反映生成质量:平均分给出整体水平,及格率保证基本质量,优秀率衡量高质量产出能力。
(2)Win Rate 评估
设计动机 :虽然 LLM Judge 可以提供多维度的绝对评分,但我们还需要一个相对评估指标来衡量生成题目与真题的质量差距。Win Rate 评估通过成对对比的方式,让 LLM 直接判断生成题目和真题哪个更好,这种相对比较比绝对评分更符合人类的判断习惯,也更容易发现生成题目的相对优势和劣势。理想情况下,如果生成题目的质量接近真题,Win Rate 应该在 50%左右(即生成题目和真题各有 50%的胜率)。这个指标简单直观,可以快速判断生成系统的整体质量水平。
在我们的实现中,Win Rate 评估通过以下图 12.6 所示流程进行评估:
图 12.6 数据生成质量评估流程图
在成对对比评估中,每次比较会产生三种可能的结果:生成题目获胜(Win)、真题获胜(Loss)或平局(Tie)。我们通过统计这三种结果的比例来评估生成题目的质量:
评估指标 :
1. 胜率(Win Rate) :生成题目被判定为更好的比例,反映生成题目相对于真题的优势。
$$ \text{Win Rate} = \frac{\text{Wins}}{\text{Total Comparisons}} $$
2. 败率(Loss Rate) :真题被判定为更好的比例,反映生成题目相对于真题的劣势。
$$ \text{Loss Rate} = \frac{\text{Losses}}{\text{Total Comparisons}} $$
3. 平局率(Tie Rate) :两者被判定为质量相当的比例,反映生成题目与真题的相似程度。
$$ \text{Tie Rate} = \frac{\text{Ties}}{\text{Total Comparisons}} $$
其中,Total Comparisons 是总的对比次数,Wins、Losses 和 Ties 分别是生成题目获胜、失败和平局的次数。这三个指标满足:Win Rate + Loss Rate + Tie Rate = 100%。
理想结果 :Win Rate ≈ 50%(说明生成质量接近真题)。如果 Win Rate 显著低于 50%,说明生成题目质量不如真题,需要优化生成策略;如果 Win Rate 显著高于 50%,可能说明生成题目在某些方面超越了真题,或者评估标准存在偏差。
(3)人工验证
设计动机 :尽管 LLM Judge 和 Win Rate 可以自动化评估题目质量,但对于数学题目这种需要严格逻辑推理的内容,人工验证仍然是不可或缺的。特别是在评估答案生成质量时,需要人类专家验证答案的准确性、解答步骤的完整性和数学推理的严密性。此外,人工验证还可以发现自动化评估可能遗漏的问题,如题目的创新性、趣味性等主观因素。为了提高人工验证的效率和体验,我们开发了基于 Gradio 的 Web 界面,让验证者可以方便地浏览题目、评分、标注状态和添加评论,大大降低了人工验证的门槛。
在我们的实现中,人工验证通过以下步骤进行:
阅读题目、答案、解答
评分(1-5 分):正确性、清晰度、难度匹配、完整性
标注状态:
✅ approved(通过)
❌ rejected(拒绝)
🔄 needs_revision(需修改)
添加评论
12.4.2 系统架构 数据生成与评估系统采用模块化设计:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 data_generation/ ├── aime_generator.py # AIME题目生成器 ├── human_verification_ui.py # 人工验证界面 ├── run_complete_evaluation.py # 完整评估流程 │ ├── generated_data/ # 生成的数据 │ ├── aime_generated_XXXXXX.json │ └── generation_report_XXXXXX.md │ └── evaluation_results/ # 评估结果 └── XXXXXX/ ├── llm_judge/ ├── win_rate/ └── comprehensive_report.md
系统包含四个核心组件:首先是 AIMEGenerator(题目生成器),使用 HelloAgents 框架生成 AIME 风格题目,支持批量生成和进度保存,并能自动处理 API 速率限制;其次是 LLMJudgeTool(LLM Judge 评估工具),提供 4 维度质量评估,自动生成 JSON 结果和 Markdown 报告;第三是 WinRateTool(Win Rate 评估工具),通过成对对比评估计算胜率、败率和平局率;最后是 HumanVerificationUI(人工验证界面),基于 Gradio Web 界面,支持评分和状态标注。
12.4.3 AIME 题目生成器实现 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 class AIMEGenerator : """AIME Problem Generator""" def __init__ ( self, llm: HelloAgentsLLM = None , delay_seconds: float = 1.0 , use_reference_examples: bool = True , reference_dataset: str = "TianHongZXY/aime-1983-2025" ): self.llm = llm or HelloAgentsLLM() self.agent = SimpleAgent( name="AIME Generator" , llm=self.llm, system_prompt="You are a professional mathematics competition problem designer." ) self.delay_seconds = delay_seconds self.use_reference_examples = use_reference_examples if use_reference_examples: dataset = load_dataset(reference_dataset, split="test" ) self.reference_examples = list (dataset)
我们的目标是生成类似风格的数据集,所以从 900+道 AIME 真题(1983-2025)中随机选择参考样例
生成提示词设计(英文):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 GENERATION_PROMPT = """You are a professional mathematics competition problem designer, skilled in creating AIME (American Invitational Mathematics Examination) style problems. 【Reference Example】(For style reference only, please generate a completely different problem) Problem: {example_problem} Answer: {example_answer} AIME Problem Characteristics: 1. Answer: An integer between 0 and 999 2. Topics: Algebra, Geometry, Number Theory, Combinatorics, Probability, etc. 3. Style: Requires multi-step reasoning, but no advanced theory 4. Difficulty: Medium to hard (similar to AIME problems 6-9) Please generate a **completely different** AIME-style mathematics problem, including: 1. Problem statement (clear and complete, different from the reference) 2. Answer (an integer between 0 and 999, different from the reference) 3. Detailed solution (including all reasoning steps) 4. Topic classification (Algebra/Geometry/Number Theory/Combinatorics/Probability) Please output in the following JSON format: { "problem": "Problem statement in English", "answer": 123, "solution": "Detailed solution steps in English", "topic": "Algebra" } """
我们选择使用英文生成题目有四个重要原因:首先是与 AIME 真题保持一致(AIME 是英文竞赛,生成英文题目更合理),其次是确保评估的公平性(LLM Judge 评估时英文 vs 英文更公平),第三是便于国际化(英文题目可以被更广泛使用),最后是避免翻译问题(不需要担心中英文翻译的准确性)。
批量生成实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 def generate_and_save (self, num_problems: int = 30 , output_dir: str = "data_generation/generated_data" ): """Generate and save problems with intelligent delay""" for file in os.listdir(output_dir): if file.startswith("checkpoint_" ) and file.endswith(".json" ): os.remove(os.path.join(output_dir, file)) with tqdm(total=num_problems, desc="Generating AIME problems" , unit="problem" ) as pbar: last_call_time = 0 for i in range (num_problems): if last_call_time > 0 : elapsed = time.time() - last_call_time if elapsed < self.delay_seconds: wait_time = self.delay_seconds - elapsed time.sleep(wait_time) start_time = time.time() problem = self.generate_single() last_call_time = time.time() generation_time = last_call_time - start_time pbar.set_postfix({ "topic" : problem.get('topic' , 'N/A' ), "answer" : problem.get('answer' , 'N/A' ), "time" : f"{generation_time:.1 f} s" }) pbar.update(1 ) return generated_data_path
LaTeX 数学公式支持:
生成的 AIME 题目包含 LaTeX 数学公式(如 $\frac{a}{b}$、$\sqrt{x}$),需要特殊处理 JSON 解析:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 def _parse_response (self, response: str ) -> Dict [str , Any ]: """解析LLM响应(支持LaTeX数学公式)""" import re if "```json" in response: json_str = response.split("```json" )[1 ].split("```" )[0 ].strip() else : json_str = response.strip() try : problem_data = json.loads(json_str) except json.JSONDecodeError: fixed_json_str = re.sub(r'(?<!\\)\\(?!["\\/bfnrtu])' , r'\\\\' , json_str) problem_data = json.loads(fixed_json_str) return problem_data
LaTeX 公式中的反斜杠(如 \frac、\sqrt)在 JSON 中是非法的转义字符,会导致解析失败:
1 Invalid \escape : line 4 column 185 (char 375 )
通过正则表达式将未转义的反斜杠替换为双反斜杠,使其在 JSON 中合法。
12.4.4 LLM Judge 评估工具 LLM Judge 工具使用 LLM 作为评委,对生成的题目进行多维度评估。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 class LLMJudgeTool (Tool ): """LLM Judge评估工具""" def run (self, params: Dict [str , Any ] ) -> str : """运行LLM Judge评估""" gen_dataset = AIDataset(dataset_type="generated" , data_path=params["generated_data_path" ]) gen_problems = gen_dataset.load() ref_dataset = AIDataset(dataset_type="real" , year=2025 ) ref_problems = ref_dataset.load() evaluator = LLMJudgeEvaluator(llm=self.llm, judge_model=params.get("judge_model" , "gpt-4o" )) results = evaluator.evaluate_batch(gen_problems, max_samples=params.get("max_samples" )) evaluator.export_results(results, result_file) self._generate_report(results, report_file) return json.dumps({"status" : "success" , "metrics" : results["metrics" ]})
评估提示词 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 EVALUATION_PROMPT = """请评估以下AIME数学题目的质量。 题目: {problem} 答案:{answer} 解答: {solution} 请从以下4个维度评分(1-5分): 1. <strong>正确性 (Correctness)</strong>:数学逻辑是否正确,答案是否准确 2. <strong>清晰度 (Clarity)</strong>:问题表述是否清晰,解答是否易懂 3. <strong>难度匹配 (Difficulty Match)</strong>:难度是否符合AIME标准(中等偏难) 4. <strong>完整性 (Completeness)</strong>:解答步骤是否完整,是否包含必要的推理 请按以下JSON格式输出: { "correctness": 5, "clarity": 4, "difficulty_match": 4, "completeness": 5, "comments": "评价理由" } """
评估报告示例 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 # LLM Judge评估报告 ## 总体评分 - <strong > 平均总分</strong > : 4.2/5.0- <strong > 通过率</strong > : 85.0% (≥3.5分)- <strong > 优秀率</strong > : 40.0% (≥4.5分)## 各维度评分 | 维度 | 平均分 | 评级 | |------|--------|------| | 正确性 | 4.3/5.0 | 良好 ⭐⭐⭐⭐ | | 清晰度 | 4.1/5.0 | 良好 ⭐⭐⭐⭐ | | 难度匹配 | 4.0/5.0 | 良好 ⭐⭐⭐⭐ | | 完整性 | 4.4/5.0 | 良好 ⭐⭐⭐⭐ |
12.4.5 Win Rate 评估工具 Win Rate 工具通过成对对比评估生成数据相对于真题的质量。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 class WinRateTool (Tool ): """Win Rate评估工具""" def run (self, params: Dict [str , Any ] ) -> str : """运行Win Rate评估""" gen_dataset = AIDataset(dataset_type="generated" , data_path=params["generated_data_path" ]) gen_problems = gen_dataset.load() ref_dataset = AIDataset(dataset_type="real" , year=2025 ) ref_problems = ref_dataset.load() evaluator = WinRateEvaluator(llm=self.llm, judge_model=params.get("judge_model" , "gpt-4o" )) results = evaluator.evaluate_win_rate(gen_problems, ref_problems, num_comparisons=params.get("num_comparisons" )) evaluator.export_results(results, result_file) self._generate_report(results, report_file) return json.dumps({"status" : "success" , "metrics" : results["metrics" ]})
AIDataset 负责加载生成数据和 AIME 真题数据,支持两种数据类型:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 class AIDataset : """AI数据集加载器 支持两种数据类型: 1. generated: 生成的数据(JSON格式) 2. real: AIME真题(从HuggingFace加载) """ def __init__ ( self, dataset_type: str = "generated" , data_path: Optional [str ] = None , year: Optional [int ] = None ): self.dataset_type = dataset_type self.data_path = data_path self.year = year def load (self ) -> List [Dict [str , Any ]]: """加载数据集""" if self.dataset_type == "generated" : return self._load_generated_data() elif self.dataset_type == "real" : return self._load_real_data() def _load_real_data (self ) -> List [Dict [str , Any ]]: """从HuggingFace加载AIME 2025真题""" from huggingface_hub import snapshot_download repo_id = "math-ai/aime25" local_dir = snapshot_download( repo_id=repo_id, repo_type="dataset" ) data_file = list (Path(local_dir).glob("*.jsonl" ))[0 ] data = [] with open (data_file, 'r' , encoding='utf-8' ) as f: for line in f: if line.strip(): data.append(json.loads(line)) problems = [] for idx, item in enumerate (data): problem = { "problem_id" : item.get("id" , f"aime_2025_{idx} " ), "problem" : item.get("problem" , "" ), "answer" : item.get("answer" , "" ), "solution" : item.get("solution" , "" ), } problems.append(problem) return problems
我们选择只使用 AIME 2025 数据集有四个原因:首先是数据的时效性(2025 年是最新的 AIME 竞赛数据),其次是简化维护(只维护一个数据集,代码更简洁),第三是格式统一(JSONL 格式,字段名统一为小写),最后是代表性充分(30 道题目足以评估生成质量)。
对比提示词 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 COMPARISON_PROMPT = """请比较以下两个AIME数学题目的质量,判断哪个更好。 【题目A - 生成题目】 问题:{problem_a} 答案:{answer_a} 解答:{solution_a} 【题目B - AIME真题】 问题:{problem_b} 答案:{answer_b} 解答:{solution_b} 请从以下方面比较: 1. 数学逻辑的严谨性 2. 问题表述的清晰度 3. 难度的合理性 4. 解答的完整性 请按以下JSON格式输出: { "winner": "A" 或 "B" 或 "Tie", "reason": "判断理由" } """
评估报告示例 :
1 2 3 4 5 6 7 8 9 10 11 12 13 # Win Rate评估报告 ## 胜率统计 | 指标 | 数值 | 百分比 | |------|------|--------| | 生成数据胜出 | 9次 | 45.0% | | AIME真题胜出 | 8次 | 40.0% | | 平局 | 3次 | 15.0% |<strong > Win Rate</strong > : 45.0% ✅ <strong > 良好</strong > : 生成数据质量接近参考数据(差距<10%)。
12.4.6 人工验证界面 使用 Gradio 创建 Web 界面,支持人工验证生成的题目。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 class HumanVerificationUI : """人工验证界面""" def launch (self, share: bool = False ): """启动Gradio界面""" with gr.Blocks(title="AIME题目人工验证" ) as demo: gr.Markdown("# 🎯 AIME题目人工验证系统" ) with gr.Row(): with gr.Column(scale=2 ): problem_text = gr.Textbox(label="问题描述" , lines=5 , interactive=False ) answer_text = gr.Textbox(label="答案" , interactive=False ) solution_text = gr.Textbox(label="解答过程" , lines=10 , interactive=False ) with gr.Column(scale=1 ): correctness_slider = gr.Slider(1 , 5 , value=3 , step=1 , label="正确性" ) clarity_slider = gr.Slider(1 , 5 , value=3 , step=1 , label="清晰度" ) difficulty_slider = gr.Slider(1 , 5 , value=3 , step=1 , label="难度匹配" ) completeness_slider = gr.Slider(1 , 5 , value=3 , step=1 , label="完整性" ) status_radio = gr.Radio( choices=["approved" , "rejected" , "needs_revision" ], value="approved" , label="状态" ) verify_btn = gr.Button("✅ 提交验证" , variant="primary" ) demo.launch(share=share, server_name="127.0.0.1" , server_port=7860 )
使用方法 :
1 2 3 4 5 python data_generation/human_verification_ui.py data_generation/generated_data/aime_generated_XXXXXX.json http://127.0.0.1:7860
最终效果可以参考图 12.7 所示,对于题目的正确性,最好人工打标 Review:
图 12.7 AIME 试题人工验证页面
验证流程 :
浏览器打开验证界面
阅读题目、答案、解答
从 4 个维度评分(1-5 分)
选择验证状态(approved/rejected/needs_revision)
添加评论(可选)
点击”提交验证”
查看下一题
验证结果保存 :
验证结果自动保存为 <data_path>_verifications.json:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 { "gen_aime_1" : { "problem_id" : "gen_aime_1" , "scores" : { "correctness" : 5 , "clarity" : 4 , "difficulty_match" : 4 , "completeness" : 5 } , "total_score" : 4.5 , "status" : "approved" , "comments" : "题目质量很好,逻辑严谨" , "verified_at" : "2025-01-10T12:00:00" } }
12.4.7 完整评估流程 将所有评估方法整合到一个完整的流程中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 def run_complete_evaluation ( num_problems: int = 30 , delay_seconds: float = 3.0 ): """ 运行完整评估流程 Args: num_problems: 生成题目数量 delay_seconds: 每次生成之间的延迟(秒),避免API速率限制 """ generator = AIMEGenerator(delay_seconds=delay_seconds) generated_data_path = generator.generate_and_save( num_problems=num_problems, output_dir="data_generation/generated_data" ) timestamp = datetime.now().strftime("%Y%m%d_%H%M%S" ) evaluation_dir = f"data_generation/evaluation_results/{timestamp} " os.makedirs(evaluation_dir, exist_ok=True ) os.makedirs(os.path.join(evaluation_dir, "llm_judge" ), exist_ok=True ) os.makedirs(os.path.join(evaluation_dir, "win_rate" ), exist_ok=True ) llm = HelloAgentsLLM() llm_judge_result = None try : llm_judge_tool = LLMJudgeTool(llm=llm) llm_judge_result_json = llm_judge_tool.run({ "generated_data_path" : generated_data_path, "reference_year" : 2025 , "max_samples" : num_problems, "output_dir" : os.path.join(evaluation_dir, "llm_judge" ), "judge_model" : "gpt-4o" }) llm_judge_result = json.loads(llm_judge_result_json) except Exception as e: print (f"❌ LLM Judge评估失败: {e} " ) win_rate_result = None try : win_rate_tool = WinRateTool(llm=llm) win_rate_result_json = win_rate_tool.run({ "generated_data_path" : generated_data_path, "reference_year" : 2025 , "num_comparisons" : min (num_problems, 20 ), "output_dir" : os.path.join(evaluation_dir, "win_rate" ), "judge_model" : "gpt-4o" }) win_rate_result = json.loads(win_rate_result_json) except Exception as e: print (f"❌ Win Rate评估失败: {e} " ) comprehensive_report_path = None if llm_judge_result or win_rate_result: comprehensive_report_path = os.path.join(evaluation_dir, "comprehensive_report.md" ) report = generate_comprehensive_report( generated_data_path, llm_judge_result, win_rate_result ) with open (comprehensive_report_path, 'w' , encoding='utf-8' ) as f: f.write(report) return { "generated_data_path" : generated_data_path, "llm_judge_result" : llm_judge_result, "win_rate_result" : win_rate_result, "comprehensive_report_path" : comprehensive_report_path }
运行方法 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 python data_generation/run_complete_evaluation.py 30 python data_generation/run_complete_evaluation.py 30 3.0
输出示例 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 ================================================================================ 🚀 AIME数据生成与评估完整流程 ================================================================================ 配置信息: - 生成题目数量: 30 - API延迟: 3.0秒/题 - 生成参考数据: TianHongZXY/aime-1983-2025(900+道题) - 评估参考: AIME 2025真题 ================================================================================ 📝 步骤1: 生成AIME题目 ================================================================================ 📚 加载AIME真题数据集: TianHongZXY/aime-1983-2025 ✓ 已加载 963 道参考题目 🎯 开始生成AIME题目 目标数量: 30 生成模型: gpt-4o 延迟设置: 3.0秒/题 生成AIME题目: 100%|██████████| 30/30 [01:30<00:00, 3.00s/题, 主题=Algebra, 答案=123, 耗时=3.0s] ✅ 步骤1完成!生成数据保存在: data_generation/generated_data/aime_generated_20250110_120000.json 🎯 步骤2.1: LLM Judge评估 (vs AIME 2025) ✅ LLM Judge评估完成! 平均总分: 4.2/5.0 通过率: 85.0% 🏆 步骤2.2: Win Rate评估 (vs AIME 2025) ✅ Win Rate评估完成! Win Rate: 45.0% ================================================================================ 📊 步骤3: 生成综合报告 ================================================================================ ✅ 综合报告已保存: data_generation/evaluation_results/20250110_120000/comprehensive_report.md ================================================================================ 🎉 完整评估流程完成! ================================================================================ 📁 输出文件: - 生成数据: data_generation/generated_data/aime_generated_20250110_120000.json - 评估结果目录: data_generation/evaluation_results/20250110_120000 - LLM Judge报告: data_generation/evaluation_results/20250110_120000/llm_judge/llm_judge_report_20250110_120000.md - Win Rate报告: data_generation/evaluation_results/20250110_120000/win_rate/win_rate_report_20250110_120000.md - 综合报告: data_generation/evaluation_results/20250110_120000/comprehensive_report.md 💡 下一步: 1. 查看综合报告: data_generation/evaluation_results/20250110_120000/comprehensive_report.md 2. 运行人工验证: python data_generation/human_verification_ui.py data_generation/generated_data/aime_generated_20250110_120000.json
12.4.8 综合评估报告 系统自动生成综合评估报告,汇总所有评估结果。以下是示例报告:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 # AIME数据生成与评估综合报告 ## 1. 基本信息 - <strong > 生成时间</strong > : 2025-01-10 12:00:00- <strong > 生成题目数量</strong > : 30- <strong > 参考AIME年份</strong > : 2025## 2. 数据生成统计 ### 主题分布 | 主题 | 数量 | 占比 | |------|------|------| | 代数 | 10 | 33.3% | | 几何 | 8 | 26.7% | | 数论 | 7 | 23.3% | | 组合 | 3 | 10.0% | | 概率 | 2 | 6.7% |## 3. LLM Judge评估结果 ### 总体评分 - <strong > 平均总分</strong > : 4.2/5.0- <strong > 通过率</strong > : 85.0% (≥3.5分)- <strong > 优秀率</strong > : 40.0% (≥4.5分)### 各维度评分 | 维度 | 平均分 | 评级 | |------|--------|------| | 正确性 | 4.3/5.0 | 良好 ⭐⭐⭐⭐ | | 清晰度 | 4.1/5.0 | 良好 ⭐⭐⭐⭐ | | 难度匹配 | 4.0/5.0 | 良好 ⭐⭐⭐⭐ | | 完整性 | 4.4/5.0 | 良好 ⭐⭐⭐⭐ |## 4. Win Rate评估结果 ### 胜率统计 | 指标 | 数值 | 百分比 | |------|------|--------| | 生成数据胜出 | 9次 | 45.0% | | AIME真题胜出 | 8次 | 40.0% | | 平局 | 3次 | 15.0% |<strong > Win Rate</strong > : 45.0% ✅ <strong > 良好</strong > : 生成数据质量接近参考数据(差距<10%)。## 5. 综合结论 基于LLM Judge和Win Rate两种评估方法的结果:1. <strong > LLM Judge评估</strong > : 生成数据的平均质量为 <strong > 4.2/5.0</strong > 2. <strong > Win Rate评估</strong > : 生成数据相对于AIME 2025真题的胜率为 <strong > 45.0%</strong > ✅ <strong > 结论</strong > : 生成数据质量<strong > 优秀</strong > ,达到或超过AIME真题水平。可以用于实际应用。## 6. 改进建议 - ✅ 继续保持当前的生成策略- ✅ 可以考虑增加生成数量- ✅ 建议进行人工验证以确保质量## 7. 下一步行动 1. <strong > 人工验证</strong > : 运行 `python data_generation/human_verification_ui.py <data_path>` 进行人工验证2. <strong > 查看详细结果</strong > : - LLM Judge详细报告 - Win Rate详细报告3. <strong > 数据使用</strong > : 如果质量满意,可以将生成的数据用于训练或测试
基于实际使用经验,总结以下内容:
在数据生成方面,应该使用合适的延迟时间(2-3 秒)避免 API 速率限制,启用检查点保存以避免中断损失,先小批量测试(10 个)确认无问题后再大批量生成,并定期检查生成质量及时调整提示词。在评估策略上,建议结合 LLM Judge 和 Win Rate 两种方法,其中 LLM Judge 用于绝对质量评估,Win Rate 用于相对质量对比,人工验证用于最终质量把关。质量标准方面,建议 LLM Judge 平均分达到 4.0/5.0 以上,Win Rate 达到 45%以上(接近 50%),通过率达到 80%以上,人工验证通过率达到 90%以上。在迭代优化过程中,应根据评估结果调整生成提示词,分析低分题目的共同问题,参考高分题目的优点,持续改进生成策略。
通过本节的学习,我们掌握了如何使用 HelloAgents 框架进行数据生成质量评估,包括 LLM Judge 评估、Win Rate 评估和人工验证三种方法。这套完整的评估体系可以确保生成数据的高质量,为 AI 系统的训练和测试提供可靠的数据支持。
对于 LLM Judge 和 Win Rate 评估,HelloAgents 也进行了工具集成,并提供了完整的示例代码。如果你对这两种评估方法的具体实现细节感兴趣,同样可以参考示例代码。
12.5 本章小结 在本章中,我们为 HelloAgents 框架构建了一个完整的性能评估系统。让我们回顾一下学到的核心内容:
(1)评估体系概览
我们建立了一个三层评估体系,全面覆盖智能体的不同能力维度。首先是工具调用能力评估(BFCL),专注于评估智能体的函数调用准确性,包含 simple、multiple、parallel、irrelevance 四个类别,使用 AST 匹配技术进行精确评估。其次是通用能力评估(GAIA),评估智能体的综合问题解决能力,包含三个难度级别共 466 个真实世界问题,关注多步推理、工具使用、文件处理等能力。第三是数据生成质量评估(AIME),评估 LLM 生成数据的质量,使用 LLM Judge 和 Win Rate 两种方法,支持人工验证和综合报告生成,确保生成数据达到参考数据的质量标准。
(2)核心技术要点
在技术实现上,我们采用了六个核心技术要点。首先是模块化设计,评估系统采用三层架构:数据层(Dataset 负责数据加载和管理)、评估层(Evaluator 负责执行评估流程)和指标层(Metrics 负责计算各种评估指标)。其次是工具化封装,所有评估功能都封装成 Tool,可以被智能体直接调用、集成到工作流中或通过统一接口使用。第三是 AST 匹配技术,使用抽象语法树匹配函数调用,比简单字符串匹配更智能,能够忽略参数顺序、识别等价表达式和忽略格式差异。第四是多模态支持,GAIA 评估支持文本问题、附件文件和图片输入等多模态数据。第五是 LLM Judge 评估,使用 LLM 作为评委评估生成数据质量,提供多维度评分(正确性、清晰度、难度匹配、完整性)、自动化评估流程、详细评估报告,并支持自定义评估维度和标准。第六是 Win Rate 对比评估,通过成对对比评估生成质量(生成数据 vs 参考数据),由 LLM 判断哪个更好并计算胜率统计,接近 50%表示质量相当。
(3)扩展方向
基于本章的评估系统,你可以在四个方向上进行扩展。首先是添加新的评估基准,可以参考 BFCL 和 GAIA 的实现模式,实现 Dataset、Evaluator、Metrics 三个组件,并封装成 Tool 供使用。其次是自定义评估指标,在 Metrics 类中添加新的指标计算方法,根据具体应用场景设计指标。第三是集成到 CI/CD 流程,在代码提交时自动运行评估,设置性能阈值防止性能退化,生成评估报告并归档。第四是扩展数据生成评估,支持更多数据类型(代码、对话、文档等),添加更多评估维度(创新性、多样性等),集成更多参考数据集,支持多模型对比评估。
恭喜你完成了第十二章的学习! 🎉
评估是智能体开发的重要环节,它让我们能够:
客观衡量智能体的能力
发现和修复问题
持续改进系统
在下一章中,我们将探讨如何将 HelloAgents 框架应用于实际项目中。
继续加油! 💪
习题
提示 :部分习题没有标准答案,重点在于培养学习者对智能体性能评估的综合理解和实践能力。
本章介绍了多个智能体评估基准。请分析:
在 12.1.2 节中介绍了 BFCL、GAIA、AgentBench 等评估基准。请对比 BFCL 和 GAIA:它们分别评估智能体的哪些核心能力?为什么 BFCL 使用 AST 匹配算法,而 GAIA 使用准精确匹配(Quasi Exact Match)?这两种评估方法各有什么优缺点?
假设你要构建一个”智能客服系统”,需要评估以下能力:(1)理解用户意图的准确性;(2)调用后台 API 的正确性;(3)回答的友好性和专业性;(4)处理异常情况的鲁棒性。请为每个能力选择或设计合适的评估指标和方法。
在 12.1.1 节中提到,智能体评估面临”输出不确定性”、”评估标准多样性”、”评估成本高昂”三大挑战。请针对每个挑战提出具体的解决方案,并分析方案的可行性和局限性。
BFCL(Berkeley Function Calling Leaderboard)是评估工具调用能力的重要基准。基于 12.2 节的内容,请深入思考:
提示 :这是一道动手实践题,建议实际操作
在 12.2.3 节的 AST 匹配算法中,我们通过比较抽象语法树来判断函数调用是否正确。请分析:为什么 AST 匹配比简单的字符串匹配更合适?在什么情况下 AST 匹配可能会产生误判(假阳性或假阴性)?如何改进 AST 匹配算法来提高准确性?
BFCL 数据集包含 simple、multiple、parallel、irrelevance 四个类别。请为每个类别设计 2-3 个新的测试样本,要求能够测试智能体在该类别下的边界情况或容易出错的场景。
请基于 12.2.4 节的代码,扩展 BFCL 评估器,添加以下功能:(1)支持评估工具调用的执行顺序(对于有依赖关系的多个工具调用);(2)评估工具调用的效率(如是否使用了最少的调用次数);(3)生成详细的错误分析报告(如哪些类型的错误最常见)。
GAIA(General AI Assistants)评估智能体的综合能力。基于 12.3 节的内容,请完成以下扩展实践:
提示 :这是一道动手实践题,建议实际操作
在 12.3.2 节中介绍了 GAIA 的三个难度级别(Level 1/2/3)。请分析:这三个级别在任务复杂度、所需能力、评估标准等方面有什么差异?如果要设计 Level 4(超高难度),应该包含什么类型的任务?
GAIA 使用”准精确匹配”算法来评估答案的正确性。请分析:这种方法如何处理答案的多样性(如”42”、”四十二”、”42.0”都应该被认为是正确的)?在什么情况下准精确匹配可能不够用?请设计一个更智能的答案匹配算法,能够处理语义等价的答案。
请基于 12.3.4 节的代码,实现一个”自定义 GAIA 评估集”:选择一个特定领域(如医疗、法律、金融),设计 10 个真实世界问题,并实现完整的评估流程。要求问题涵盖不同难度级别,并提供标准答案和评分标准。
LLM Judge 是使用大语言模型进行评估的新兴方法。基于 12.4 节的内容,请深入分析:
在 12.4.2 节中,我们使用 GPT-4 作为评判者来评估智能体的回答质量。请分析:LLM Judge 相比传统的规则匹配或指标计算有什么优势?它存在哪些潜在的偏见或局限性(如对某些回答风格的偏好、对长度的敏感性)?
LLM Judge 的评分标准设计至关重要。请为以下三个不同的评估场景设计详细的评分标准(包括评分维度、权重、示例):(1)代码生成质量评估;(2)创意写作质量评估;(3)技术文档质量评估。
在 12.4.3 节中提到,可以使用多个 LLM Judge 进行”评审团”式评估。请设计一个”多评委评估系统”:使用 3-5 个不同的 LLM(如 GPT-4、Claude、Qwen)作为评委,如何聚合它们的评分?如何处理评委之间的分歧?如何检测和过滤异常评分?
智能体评估的实践应用需要考虑多个方面。请思考:
在实际项目中,评估往往需要在”评估成本”和”评估质量”之间权衡。请设计一个”分层评估策略”:(1)快速评估(低成本,用于日常开发迭代);(2)标准评估(中等成本,用于版本发布前);(3)全面评估(高成本,用于重大更新或对外发布)。每层应该包含哪些评估项目?如何设计评估流程?
智能体的性能可能随时间变化(如依赖的外部 API 变化、用户需求变化)。请设计一个”持续评估系统”:能够定期自动运行评估,监控智能体性能的变化趋势,并在性能下降时及时告警。这个系统应该包含哪些组件?如何设计告警规则?
评估结果需要以清晰的方式呈现给不同的受众(如开发者、产品经理、用户)。请设计一个”评估报告生成系统”:能够根据受众类型自动生成不同详细程度的报告。开发者报告应该包含哪些技术细节?产品经理报告应该突出哪些业务指标?用户报告应该如何简化和可视化?
参考文献 [1] Patil, S. G., Zhang, T., Wang, X., & Gonzalez, J. E. (2023). Gorilla: Large Language Model Connected with Massive APIs. arXiv preprint arXiv:2305.15334.
[2] Qin, Y., Liang, S., Ye, Y., Zhu, K., Yan, L., Lu, Y., … & Sun, M. (2023). ToolLLM: Facilitating Large Language Models to Master 16000+ Real-world APIs. arXiv preprint arXiv:2307.16789.
[3] Li, M., Zhao, Y., Yu, B., Song, F., Li, H., Yu, H., … & Li, Y. (2023). Api-bank: A comprehensive benchmark for tool-augmented llms. arXiv preprint arXiv:2304.08244.
[4] Mialon, G., Dessì, R., Lomeli, M., Nalmpantis, C., Pasunuru, R., Raileanu, R., … & Scialom, T. (2023). GAIA: a benchmark for General AI Assistants. arXiv preprint arXiv:2311.12983.
[5] Liu, X., Yu, H., Zhang, H., Xu, Y., Lei, X., Lai, H., … & Zhang, D. (2023). AgentBench: Evaluating LLMs as Agents. arXiv preprint arXiv:2308.03688.
[6] Zhou, S., Xu, F. F., Zhu, H., Zhou, X., Lo, R., Sridhar, A., … & Neubig, G. (2023). WebArena: A Realistic Web Environment for Building Autonomous Agents. arXiv preprint arXiv:2307.13854.
[7] Chan, C. M., Chen, W., Su, Y., Yu, J., Xue, W., Zhang, S., … & Liu, Z. (2023). ChatEval: Towards Better LLM-based Evaluators through Multi-Agent Debate. arXiv preprint arXiv:2308.07201.
[8] Zhou, X., Zhu, H., Mathur, L., Zhang, R., Yu, H., Qi, Z., … & Neubig, G. (2023). SOTOPIA: Interactive Evaluation for Social Intelligence in Language Agents. arXiv preprint arXiv:2310.11667.
[9] Mathematical Association of America. (2024). American Invitational Mathematics Examination (AIME). Retrieved from https://www.maa.org/math-competitions/invitational-competitions/aime