BFCL 实操指南
更新于 2026-04-23
Agent benchmark 全景 的 §Level 1 “单次 Function Calling” 和 BFCL 小节,以及 BFCLEvalFlow 组件,介绍了 BFCL 在 Agent 能力层级中的定位——从单次 function calling(Level 1)到多轮 tool use、再到 agentic 系统的完整评测标准。本篇聚焦实操:“V1-V4 评测类别体系、AST vs Exec 两种评分机制、Handler 架构与自定义模型接入”。读完应能跑通 BFCL 评测、理解每个类别测什么、知道怎么扩展支持新模型。
1 评测类别体系
BFCL 经过四个主要版本迭代,每版新增一组类别,逐步从”单次 function calling”扩展到”agentic 任务”。
1.1 V1-V4 演进
| 世代 | 新增类别 | 核心能力 |
|---|---|---|
| V1 | simple_python / simple_java / simple_javascript, parallel, multiple, parallel_multiple, irrelevance | 基础 function calling:单次(3 语言)/ 并行 / 多次调用 + 识别无关请求 |
| V2 | live_simple, live_parallel, live_multiple, live_parallel_multiple, live_irrelevance, live_relevance | 社区贡献的真实用户 prompt,测试泛化能力 |
| V3 | multi_turn_base, multi_turn_miss_func, multi_turn_miss_param, multi_turn_long_context | 多轮对话状态追踪:基础 / 缺失函数 / 缺失参数 / 长上下文 |
| V4 | web_search_base, web_search_no_snippet, memory_kv, memory_vector, memory_rec_sum, format_sensitivity | Agent 级评测:搜索工具使用、记忆管理、格式鲁棒性 |
1.2 V4 总分权重分配
V4 总分由各类别加权而成,权重(来自源码 [10, 10, 10, 30, 40])分布:
- 10% — non_live(V1 基础类别)
- 10% — live(V2 类别)
- 10% — irrelevance(V1/V2 的无关识别类别)
- 30% — multi_turn(V3 类别)
- 40% — agentic(V4 搜索 + 记忆类别)
format_sensitivity不计入总分权重,作为独立指标单独报告
V4 大幅提升了 multi_turn 和 agentic 的权重,说明社区共识是”基础 function calling 已基本解决,难点在多轮状态追踪和 agent 任务”。
1.3 关键类别详解
simple_python/simple_java/simple_javascript:给一个函数,正确填参——三种语言。JavaScript/Java 的 AST 评分规则和 Python 有差异(参数命名、默认值处理等)。parallel:多个独立函数调用,顺序无关。multiple:多个函数里选一个正确的,选对 + 填对参数才算通过。parallel_multiple:上两者的组合——从多个候选里选出多个正确的并行调用。irrelevance:给定函数无法回答 query,模型应拒绝调用(返回自然语言解释而非瞎编 function call)。注意类别名是irrelevance而不是relevance。multi_turn_miss_func:对话中途”抽走”某个可用函数,模型需识别并告知用户。multi_turn_miss_param:用户未提供必要参数,模型需主动询问而非乱填默认值。web_search_base/web_search_no_snippet:带 / 不带 snippet 的搜索工具使用。后者更难——模型要自己决定是否再搜一次。memory_kv/memory_vector/memory_rec_sum:三种记忆策略——key-value / vector 检索 / recursive summarization。考察模型在有记忆系统辅助时的 agent 表现。
点击矩阵中任意类别格子查看详细说明和示例 prompt。右侧饼图展示 V4 总分权重分配。
2 数据格式与评分机制
2.1 JSONL 数据结构
每个测试样本一行 JSON:
{
"id": "simple_0",
"question": [{ "role": "user", "content": "Find me the nearest hospital within 5km" }],
"function": [
{
"name": "find_hospital",
"description": "Find nearby hospitals",
"parameters": {
"type": "dict",
"properties": {
"location": { "type": "string" },
"radius": { "type": "integer" }
},
"required": ["location"]
}
}
]
}
两个关键细节:
function[].parameters是原生 JSON 对象,不是字符串——可以直接取字段,不需要json.loads()。- 其
type字段使用"dict"而非 OpenAI 标准的"object"——自定义 handler 传给 OpenAI API 前要做一次转换(BFCL 已内置转换逻辑,但自写 handler 需要注意)。
2.2 AST 评分
AST(Abstract Syntax Tree)评分是 BFCL 的默认评分机制,不实际执行函数,仅对比结构:
- 解析 模型输出为 AST(函数名 + 参数 dict)
- 函数名匹配(容忍 dot-to-underscore 替换——OpenAI/Mistral/Google 会自动把
api.search改成api_search) - 参数完整性:required 参数必须存在,不允许多余参数(超出 schema 的键会判错)
- 类型正确性(含宽容规则:
int → float✓、tuple → list✓) - 值匹配:字符串忽略空格和常见标点差异
AST 的优势:快、不需要真实执行环境、不受外部 API 影响。劣势:结构对但值错(如地名填错国家)检测不到。
2.3 Exec 评分
部分类别(如 rest、一些 executable 类别)使用 Exec 评分:
- 将模型输出转为可执行字符串,如
find_hospital(location="NYC", radius=5) - 实际执行函数调用
- 比较返回值与期望输出
Exec 能发现 AST 漏掉的”参数格式对但执行失败”的情况(如 API 不存在、参数值导致运行时错误)。
2.4 AST vs Exec 典型场景
- AST ✓ + Exec ✓:参数正确且执行结果正确(理想)
- AST ✓ + Exec ✗:参数格式正确但值导致运行时错误(如 API 端点不存在、token 过期)
- AST ✗ + Exec ✓:参数格式不符合 schema 但执行结果碰巧正确(罕见,可能是评分器 bug)
find_hospital(location="New York", radius=5)find_hospital(location="New York", radius=5)组件分三个 case 展示两种评分机制的差异。切换底部按钮可以看到同一份模型输出在 AST / Exec 两种视角下的评分路径。
3 Handler 架构与模型接入
3.1 两种评测模式
BFCL 对模型分两类评测:
- FC(Function Calling)模式:模型原生支持 tool calling(OpenAI、Claude、Gemini 等)。直接通过 API 的
tools参数传入函数定义,模型以结构化形式返回。 - Prompt 模式:模型不支持原生 tool calling。将函数定义序列化为文本塞进 prompt,从模型文本输出中解析函数调用(用 regex 或自定义 parser)。
同一个模型在两种模式下的分数可能差 10-20%——这是报告 BFCL 分数时必须说明的。
3.2 Handler 继承体系
BaseHandler # API 模型基类
├── OpenAIHandler
├── ClaudeHandler
├── MistralHandler
├── GoogleHandler
└── CohereHandler
OSSHandler # 开源模型基类, 继承 BaseHandler
├── 各 OSS 模型 Handler
3.3 核心方法
每个 handler 要实现两个解析方法:
decode_ast(result):原始 API 响应 → 结构化 dict({"name": ..., "arguments": {...}})。用于 AST 评分。decode_execute(result):原始 API 响应 → 可执行字符串(func(a=1, b="x"))。用于 Exec 评分。
3.4 自定义 Handler 四步流程
- 在
model_handler/api_inference/或local_inference/下创建 handler 文件 - 继承
BaseHandler(API)或OSSHandler(本地 / open-source),实现decode_ast和decode_execute - 在
constants/model_config.py注册ModelConfig(name、org、handler class、is_fc_model标志、pricing 等) - 更新
SUPPORTED_MODELS.md和supported_models.py
四步做完,新模型就可以用 bfcl generate --model <your_model> 跑评测了。
4 运行评测与常见坑
4.1 CLI 工作流
# 安装
pip install bfcl-eval
export BFCL_PROJECT_ROOT=/path/to/project
# 生成模型输出 (API 模型)
bfcl generate --model gpt-4o --test-category simple
# 生成模型输出 (开源模型, 用 vllm 后端)
bfcl generate --model meta-llama/Llama-3-8B \
--backend vllm --num-gpus 2
# 评分
bfcl evaluate --model gpt-4o --test-category simple
--test-category 支持单个类别(simple)、多个(simple,parallel)、或整个世代(all)。
API Key 配置:.env 文件放在 $BFCL_PROJECT_ROOT 下,变量名如 OPENAI_API_KEY、ANTHROPIC_API_KEY 等。
4.2 常见坑(5 个)
- Dot-to-underscore 替换:OpenAI / Mistral / Google 等多家 API 会自动把函数名中的
.替换为_(因为底层 tokenizer 或 API schema 不允许)。评分器已处理这个差异,但自己写 handler 时要注意,不要在decode_ast里手动再替换一次,会双重替换导致评分失败。 - Tuple 序列化:JSON 无 tuple 类型,Python
tuple走 JSON 变成list。评分器做了归一化处理,但自定义评分规则时要记得两者视为相等。 type: "dict"vs"object":BFCL 数据集的parameters用"type": "dict",OpenAI 标准是"type": "object"。传给 API 前必须转换。- FC vs Prompt 分数差异显著:同一模型两种模式可能差 10-20%。报告 BFCL 分数必须标明模式。对比别人的分数前先看人家用的是哪种模式。
- V4 权重变化:V4 大幅调整了类别权重(agentic 占 40%)。V4 总分不能直接和 V3 总分比较——它们衡量的不是同一件事。
5 总结
- FC vs Prompt 模式选择:模型原生支持 tool calling 优先用 FC 模式(评分更高、更稳定);不支持的用 Prompt 模式。
- V4 agentic 评测的意义:BFCL 从”能否调函数”升级到”能否完成 agent 任务”——web 搜索、记忆管理、格式鲁棒性都是 agent 能力的核心维度。
- 与其他 Agent benchmark 互补:BFCL 测函数调用精度、GAIA 测端到端任务完成、WebArena 测 Web 交互。三者各管一维,不可互相替代。
想了解 BFCL 在 Agent 能力层级中的定位,回去看 Agent benchmark 全景 §Level 1。想了解 benchmark 整体生态,看 benchmark 生态全景。