想象一家高端家政公司要招聘 AI 管家。考官不会光听候选人“我很能干”的自夸,而是设计一套标准化实操试卷:主人在电话里吩咐“帮我查一下明天北京的天气,顺便订一家附近的餐厅”,管家必须在几秒内从工具架上选对工具、填好操作单。这套试卷的权威版本,就是 BFCL——Berkeley Function Calling Leaderboard。它由加州大学伯克利分校团队设计,专门评价大模型“调用函数”这门手艺的标准化考场。函数调用值得单独评测,因为它是大模型从“聊天机器”进化为“能干活的 Agent”的关键跃迁:只有准确输出机器可执行的调用指令,模型才能真正帮用户订机票、查天气、操作数据库。BFCL 把这件事变成可以量化比较的分数,让模型开发者像看考试成绩单一样,快速知道自家的 AI 管家有几斤几两。
对 AI 从业者而言,掌握 BFCL 的评测方法论,等于掌握了一套给 Agent 能力“体检”的标准工具,能直接用于模型选型、Prompt 调优和上线前的质量关卡。
可视化演示
本节配有交互动效(进入视口后自动加载,约 3KB)。
什么是BFCL
假设你是家政考评委员会主席,要评出“年度最佳 AI 管家”。你不会只问管家“你会不会干活”,而是设计一个标准操作间:一面墙上挂满工具——查天气的、订机票的、发邮件的。主人说出需求后,管家要在几秒内把选中的工具编号和填写好的操作单交上来。BFCL 就是这套标准操作间的数字化版本,它由加州大学伯克利分校团队开源维护,全称 Berkeley Function Calling Leaderboard,专注回答一个问题:面对真实用户请求,哪个大模型能最准确地选出函数、填对参数?
所谓“函数调用”,是模型输出一段结构化指令(通常用 JSON 表示),描述“调用哪个函数、传入什么参数”,而不是直接执行代码。真正执行由外部系统完成。BFCL 把这项能力拆解成一个个可自动判分的测试用例:每个用例包含一段用户请求、一组可用函数定义、一份标准答案(golden answer)。
评测时,模型先看到“工具清单”——函数名、参数 schema 和说明——再看到用户请求,最后输出函数调用 JSON。评测系统将模型输出与标准答案比对,统计准确率:
回到考评中心:准确率就像“管家在所有模拟任务中一次做对的比例”。80% 的准确率意味着十次吩咐里有两次挑错工具或填错参数——这在真实家庭里可能就是一次失败的订餐。
- 测试用例总数 NBFCL 所用测试集的总题数,是所有累计求和的分母。
- 模型预测值 ŷᵢ第 i 道题中,模型输出的函数调用结果,包含函数名与参数。
- 标准答案 yᵢ人工确认或程序化生成的第 i 道题的最优函数调用。
- 指示函数 I(·)括号内条件成立时取 1,否则取 0,用来标记单题答对与否。
- 求和平均把所有题目的正确标记加起来,再除以 N,得到整体准确率。
评测任务分类
考评中心不会只考一种场景。主人有时只提一个需求(“帮我查天气”),有时给一串选择(“明天开会,帮我订合适的会议室”),有时会在对话里追加条件(“哦对了,座位要靠窗”),有时还要同时做好几件事(“订机票的同时帮我预约接机”)。BFCL 的考题分门别类,覆盖这些真实调用模式。
对应到技术上,BFCL 的任务分类大致包括:单函数调用(SF)、多函数选择(MF)、多轮对话函数调用(MFC)、并行函数调用(PFC)等。无论哪类,一次函数调用的核心都是一个二元组:函数名 f 和参数字典 a:
多函数选择考察的是“信息筛选”:候选函数定义里存在干扰项,模型必须依据用户意图选出正确的那一个,而不是所有看起来相关的都调用。多轮任务则模拟真实对话:第二轮请求可能引用第一轮的结果,比如“刚才查的那家餐厅,帮我订位”,模型需要记住前文中的实体信息。并行调用允许模型一次输出多个函数调用,评测系统会分别与对应标准答案比对。
主人吩咐得越复杂,管家要对的号入座的工具就越多。BFCL 把“简单吩咐”“选择困难”“追加条件”“一人多用”全部纳入考纲,就是为了筛出真正能应对真实生活的全能管家。
- 函数名 fⱼ决定“用哪个工具”,是最基本的选择正确性判据。
- 参数字典 aⱼ由若干键值对组成,如“城市=北京、日期=明天”。
- 基本解析整个调用 cⱼ 由函数名和参数共同决定,缺一不可。
评分标准
考卷交上来了,怎么判分?考评委员会有三道工序:第一道看操作单上工具编号和填写内容是否跟标准答案一模一样;第二道看格式虽不同但本质是否相同——比如“城市:北京”和“北京:城市”填反了顺序,只要意思一样就不算错;第三道更狠,直接把操作单交给工具试一下,看工具能不能按这张单子跑起来。
对应 BFCL 的三层评分:精确匹配(Exact Match)、AST 匹配(Abstract Syntax Tree Match)和可执行检查(Executable Check)。精确匹配要求字符串级完全一致,最严格也最脆弱;AST 匹配把函数调用解析成语法树,允许键顺序、空格等不影响语义的差异;可执行检查则进一步调用真实或模拟函数,根据返回结果判断是否正确。
AST 匹配是 BFCL 最具特色的判分方式。它将模型输出和标准答案分别解析为抽象语法树,比较两棵树是否结构等价:
可执行检查则模拟“工具真实运行”的环境,会校验参数类型合法性、函数是否存在等,比 AST 更贴近工程上线时“到底能不能调通”的诉求。
三道工序对应三种严格程度。现实团队上线 Agent 时,最该优先关注可执行检查:因为哪怕 AST 全对,只要真实工具报错,这次调用在业务上就是失败的。
{"name": "get_weather", "arguments": {"city": "北京", "date": "明天"}},AST 匹配不在意 JSON 里键的书写顺序,只要语义结构一致就判对;可执行检查则会真去执行这个函数,验证返回结果。- 模型输出 c待判分的函数调用,通常是 JSON 对象。
- 标准答案 c\*题库中预设的正确调用,用于对照。
- AST 等价两个函数调用解析后的语法树结构完全一致。
- 分段判定等价取 1,不等价取 0,体现非此即彼的判分逻辑。
数据集构建
一套公平的考卷怎么出?考评中心的出题组不会闭门造车。他们走进真实家庭,采集“主人平时最常吩咐的事情”,再把相近的吩咐合成变体——“查天气”衍生出“查北京天气”“查三天后上海天气”,最后请几个老管家审一遍,确保每题答案唯一、工具确实用得上。
BFCL 的数据集构建遵循类似思路:从真实 API 场景中抽取函数定义(如天气、日历、出行类 API),构造用户请求和标准函数调用。为保证规模,还会用程序自动生成多种写法;同时安排人工检查,剔除函数定义含糊、答案有歧义的题目。
评估一个数据集好不好,可以看它对“可用函数空间”的覆盖程度。一个简单的覆盖率指标是:测试集中出现的唯一函数数量与总用例数之比
覆盖率越高,说明题库涉及的函数越多样,越不容易让模型靠背题蒙混过关。构建时还要严格避免测试集泄漏——若某道题恰好出现在预训练语料中,模型的“高分”就可能是记忆而非能力。
好的考卷应该像真实生活一样丰富多变。题库的多样性和防泄漏设计,决定了 BFCL 的分数到底测的是“能力”还是“记忆”,这也是所有评测基准设计中最容易被忽视却最致命的一环。
- 唯一函数集合 F_test测试集中出现的不重复函数名总数。
- 总用例集合 C_test测试集中所有题目的数量。
- 覆盖率 Coverage两者之比,衡量工具类型在题目中的丰富程度。
模型表现对比
考卷改完,榜单揭晓。主办方把各家管家的成绩张贴在墙上:头部选手稳定领先,操作规范、几乎不挑错工具;一批后起之秀紧随其后,但偶尔会在复杂任务上手忙脚乱,尤其在“选择困难”题上失分最多。
BFCL 的公开结果呈现相似图景:闭源模型(如 GPT-4 系列、Claude 系列)在函数调用准确率上整体领先,开源模型(如 Qwen、Llama)经过针对性训练后快速追赶。进一步分析错误类型会发现,许多模型的主要失分点不在参数填写的精度,而在“函数选择”本身——也就是选错了工具。
比较模型差距时,常用相对差距来消除基准线影响:
譬如最佳模型准确率 92%,某个模型 80%,则其相对差距约 13%,意味着每 100 次调用比最佳模型多错约 12 次。值得注意的是,跨模型对比时,参数量、指令微调和函数调用专项训练都会影响结果,分数差异首先要归因于训练目标而非模型架构。
成绩单的意义不仅是排名,更是指出“哪类家务最值得培训”——当所有管家都在函数选择上集体翻车,模型的开发方向就应该往“理解意图、匹配工具”上倾斜,而不是一味堆参数。
- 最佳模型准确率 Acc_best榜单最高分,作为对比基准。
- 模型准确率 Acc_model被评估模型的分数。
- 相对差距 Δ最佳分数减去模型分数,再除以最佳分数,得到百分比形式的差距。
局限与启示
再完美的考卷也有盲区。考场里管家面对的是一张纸上的文字吩咐,但真实生活里主人可能会打断、会纠正、会反悔;考场里的工具是静止的,而真实工具会报错、会超时、会返回意外结果。静态考卷考不出管家在这些突发状况下的临场应变。
BFCL 这类静态评测的局限正在于此:模型输出被一次性判分,无法在交互中修正,也无法验证“多轮试探”后的最终效果。因此业界开始探索动态评测,让模型在模拟环境中真实地调用工具、观察结果、调整策略,并最终衡量任务完成率:
对 RAG 与 Agent 评测而言,BFCL 提供了三条可复用的方法论:其一,把“能力”拆成可自动判分的原子任务;其二,评分要分层次——精确匹配、结构匹配、可执行验证缺一不可;其三,测试集必须重视防泄漏,任何一题的泛化能力都要经得起“训练集里没有见过”的检验。同时也要意识到,函数调用准确率高,不代表 Agent 整体就可靠,还需要评估工具调用后的规划、容错与多步完成任务的能力。
考卷帮我们筛掉了不会干活的管家,但真正优秀的管家还要在“现场突发状况”中证明自己。BFCL 是一块坚实的起跳板,而评测的下一站,是让 AI 走进会反馈、会变化的真实世界。
- 任务总数 T动态评测中布置的完整任务数量。
- 任务完成标记第 t 个任务是否成功完成,成功记 1。
- 任务完成率成功任务数除以总任务数,衡量模型在真实交互环境中的最终效果。
AI 应用场景
搭建 Agent 工具调用的回归测试线
阶段:评测与质量保障
解决的问题:企业 Agent 频繁调用内部 API,一次参数写错可能导致下单失败、数据错乱。传统靠人工 review 日志,效率低且无法在发版前预警。用 BFCL 风格的结构化测试集,每次改动 Prompt 或函数 schema 都自动跑一遍,能快速发现调用退化。
具体案例:某电商客服 Agent 接入订单查询 API 时,团队从历史对话中抽取 200 条真实请求,构造“用户问题 + 函数定义 + 标准调用”三元组,用 AST 匹配与可执行校验做回归,上线前堵住 12 处参数类型错误。
模型选型前的函数调用能力基线
阶段:模型选型与能力基线
解决的问题:团队在闭源模型与开源模型之间犹豫,没有量化依据。BFCL 的公开排行榜可作为初步筛选信号,帮助团队在花成本接 API 之前先淘汰函数调用能力明显不足的模型。
具体案例:某 AI 原生创业公司对比 Qwen2.5、Llama3.1 和商业模型时,参考 BFCL 分数选定主模型,再配合自建的 20 个业务 API 用例做二次验证,最终选型周期从两周缩短到三天。
Python 演示
"""BFCL 精简评测器: 对模型输出的函数调用进行评分"""import astfrom typing import Any, Callable, Dict, List # 测试题库: 每个用例包含用户请求与标准函数调用GOLDEN_CASES = [ { "question": "帮我查一下明天北京的天气, 并预订一家附近的餐厅", "functions": [ {"name": "get_weather", "arguments": {"city": "北京", "date": "明天"}}, {"name": "reserve_restaurant", "arguments": {"city": "北京", "meal": "晚餐"}}, ], }, { "question": "给Alice发一封邮件, 告诉她会议改到下午3点", "functions": [ {"name": "send_email", "arguments": {"to": "alice@example.com", "content": "会议改到下午3点"}}, ], },] def predict_calls(model: Callable[[str], List[Dict[str, Any]]], question: str) -> List[Dict[str, Any]]: """调用模型获得预测的函数调用列表""" return model(question) def json_dump(obj: Any) -> str: """将参数序列化为稳定字符串, 键按字母排序""" if isinstance(obj, dict): pairs = sorted(obj.items()) return "{" + ",".join(f'"{k}":{json_dump(v)}' for k, v in pairs) + "}" if isinstance(obj, str): return '"' + obj + '"' return str(obj) def ast_match(pred: Dict[str, Any], gold: Dict[str, Any]) -> bool: """用 AST 比较两个调用是否结构等价""" if pred.get("name") != gold.get("name"): return False try: p_tree = ast.dump(ast.parse(json_dump(pred.get("arguments", {})))) g_tree = ast.dump(ast.parse(json_dump(gold.get("arguments", {})))) return p_tree == g_tree except SyntaxError: return False def evaluate(model: Callable[[str], List[Dict[str, Any]]], cases: List[Dict[str, Any]]) -> Dict[str, float]: total = len(cases) ast_correct = 0 exec_correct = 0 for case in cases: preds = predict_calls(model, case["question"]) golds = case["functions"] if len(preds) != len(golds): continue ast_ok = True exec_ok = True for pred, gold in zip(preds, golds): if not ast_match(pred, gold): ast_ok = False args = pred.get("arguments", {}) if not isinstance(args.get("city", None), str): exec_ok = False if ast_ok: ast_correct += 1 if exec_ok: exec_correct += 1 return { "total": total, "ast_accuracy": ast_correct / max(total, 1), "exec_accuracy": exec_correct / max(total, 1), } def dummy_model(question: str) -> List[Dict[str, Any]]: """模拟一个表现一般的模型: 答对第一题, 第二题函数名写错""" if "天气" in question: return [ {"name": "get_weather", "arguments": {"city": "北京", "date": "明天"}}, {"name": "reserve_restaurant", "arguments": {"city": "北京", "meal": "晚餐"}}, ] return [{"name": "send_msg", "arguments": {"to": "alice@example.com", "content": "会议改到下午3点"}}] if __name__ == "__main__": result = evaluate(dummy_model, GOLDEN_CASES) print(f"评测用例数: {result['total']}") print(f"AST 匹配准确率: {result['ast_accuracy']:.2f}") print(f"可执行检查准确率: {result['exec_accuracy']:.2f}")
GOLDEN_CASES = [...]定义标准答案题库,每道题包含用户请求和期望的函数调用列表。def ast_match(pred, gold):定义 AST 判分函数,先检查函数名,再比较参数树结构。ast.dump(ast.parse(json_dump(...)))把参数字典解析成语法树后再序列化比较,键顺序不影响结果。len(preds) != len(golds)函数调用数量都对不上,说明模型连该调用几个工具都没搞清楚。if ast_ok: ast_correct += 1单个用例的所有函数调用全部匹配,才累计正确数。args.get("city", None)模拟“参数值能否通过类型校验”的可执行检查。dummy_model` 第二题返回 `send_msg故意把send_email写错,展示“函数选择错误”如何被扣分。
常见误区
误区函数调用是不是就是让 AI 自己写一段 Python 代码然后运行?如果是这样,那评测函数调用不就是评测写代码吗?
正解函数调用是模型输出结构化的“调用指令”(函数名 + 参数),真正执行由应用框架完成。类比管家填操作单,而不是管家自己抄起电话打。BFCL 判的是“指令对不对”,不是“代码能不能跑”。
为何常见:很多教程用代码示例展示函数调用,学习者容易把“输出指令”和“执行代码”混为一谈。
误区BFCL 上排名第一的模型,拿来做 Agent 肯定最靠谱,直接选它就完事了。
正解BFCL 测的是单次函数调用的静态能力,而真实 Agent 还需要检索、规划、多步决策、错误恢复。就像一个管家考试满分,不代表他真能应付家里水管爆了。选型时应把 BFCL 当基线,再结合自建业务场景回归。
为何常见:排行榜给人“分数 = 效果”的直观联想,忽略了评测边界。
误区多轮函数调用就是把单轮题目重复几遍吧,模型只要每轮都输出调用就行。
正解BFCL 的多轮任务强调上下文依赖。用户第一轮查了某家餐厅,第二轮说“帮我订那家”,模型必须在第二轮调用中包含第一轮的实体信息。这考察的是记忆和上下文利用,而不是简单拼接。
为何常见:多轮对话在其它测评里常见,容易想当然套用,忽略了 BFCL 的多轮特指函数调用中的状态追踪。
误区AST 匹配很宽松吧?参数值随便写,函数名差不多对就行?
正解AST 匹配只容忍键顺序、空白等不影响语义的表示层差异。函数名写错、参数值错误、参数缺失(如该传“城市”却传“日期”)都会被判错。它比字符串精确匹配宽松,但比“人工看个大概”严格得多。
为何常见:看到“结构等价”容易理解为“差不多就行”,其实 AST 比较依然基于严格的语法树等价。
面试题
Q1. BFCL 主要评测大模型的哪项能力?
- A.文本生成流畅程度
- B.函数调用与参数填写的准确性← 正确答案
- C.图像识别与分割效果
- D.模型推理时的响应延迟
答案:B。BFCL(Berkeley Function Calling Leaderboard)专注评测模型能否正确选择函数并填写参数。文本流畅度、图像识别、响应延迟都不是它的考察对象,就像管家考评只看“会不会派工具干活”,不看你说话快慢。
Q2. 函数调用的标准输出形态是?
- A.一段自然语言解释
- B.一段可执行的Python代码
- C.结构化的JSON调用指令← 正确答案
- D.一个包含响应头的网页
答案:C。函数调用指模型输出“函数名 + 参数”的结构化 JSON(如 {"name":"get_weather","arguments":{"city":"北京"}}),由外部系统执行。自然语言无法被机器直接执行,Python 代码属于代码生成而非函数调用,网页响应更是无关。
Q3. 下列哪些属于 BFCL 的评测任务类型?
- A.单函数调用← 正确答案
- B.多函数选择← 正确答案
- C.多轮对话调用← 正确答案
- D.模型预训练阶段
答案:ABC。BFCL 覆盖单函数、多函数选择、多轮对话、并行调用等。预训练不是评测任务,而是模型训练环节,对应选项 D 完全无关。前三项都是考场中出现的“考题类型”。
Q4. 关于 BFCL 的 AST 匹配,下列说法正确的是?
- A.函数名写错也能判对
- B.比较两个调用的语法结构等价← 正确答案
- C.参数键的顺序不同不影响结果← 正确答案
- D.依赖模型输出字符串完全一致
答案:BC。AST 匹配先将调用解析成语法树再比较结构,函数名属于结构关键信息,写错会判错,故 A 错;它不要求字符串完全一致,故 D 错。B 和 C 正确展现了 AST 匹配“结构等价、忽略表示层差异”的特点。
Q5. BFCL 中的“可执行检查”主要验证什么?
- A.远程服务器的网络延迟
- B.函数调用能否真实运行且结果合理← 正确答案
- C.JSON 字符串格式是否美观
- D.模型输出的文本长度达标
答案:B。可执行检查会让函数真实运行(或模拟运行),校验参数类型、函数是否存在以及结果是否合理。它比 AST 更贴近“上线能不能调通”。网络延迟、格式美观、文本长度都与“调用是否正确”无关。
Q6. 构建 BFCL 风格测试集时,最应避免的问题是?
- A.测试用例与预训练数据重叠← 正确答案
- B.题目数量太多
- C.函数定义过于详细
- D.用户请求全部使用英文
答案:A。若测试题出现在预训练语料中,模型的高分可能来自记忆而非泛化能力,即“数据泄漏”问题。题目多、定义细、语言统一都是可控的设计选择,但泄漏会从根本上摧毁评测的可信度,正如考题提前泄露给考生,考试就失去了意义。
Q7. 相比开放式文本问答,BFCL 评测的最大优势在于?
- A.完全依赖人工评审
- B.可结构化且自动判分← 正确答案
- C.每轮随机更换题目
- D.只关注生成速度快慢
答案:B。函数调用的输出是结构化 JSON,于是可以采用精确匹配、AST 匹配、可执行检查自动判分,客观且可复现。开放式问答往往需要人工主观打分。随机换题影响公平性,速度也不是正确性指标。
Q8. 多轮函数调用评测重点考察模型的什么能力?
- A.上下文记忆与状态追踪← 正确答案
- B.单次输出的文本长度
- C.图像数据的预处理
- D.训练时使用的学习率
答案:A。多轮任务要求模型记住前文提到的实体并应用到后续调用,比如“订刚才那家餐厅”,必须把“刚才那家”还原成具体的餐厅 ID。这项能力直接决定 Agent 能否支持真实的多步对话,与输出长度、图像处理、学习率无关。
Q9. BFCL 评测结果给 Agent 开发带来的启示有哪些?
- A.函数定义要写清参数描述← 正确答案
- B.高分模型并非完全可靠← 正确答案
- C.还需结合自建场景回归← 正确答案
- D.无需关注调用成本问题
答案:ABC。BFCL 的结果显示函数 schema 越清晰,模型越不容易选错;但排行榜分数不代表真实业务全通过,仍需自建回归。成本始终是上线考量因素,D 明显错误。三条启示分别对应定义、选型、回归三个环节。
Q10. 在函数调用中,“函数选择错误”最典型的例子是?
- A.想查天气却调用发邮件← 正确答案
- B.参数类型写成了字符串
- C.推理过程耗费时间过长
- D.返回内容包括多余标点
答案:A。函数选择错误指模型在多个候选工具中挑错对象,例如把 get_weather 输出成 send_email。参数类型错误属于“参数精度”问题,耗时与标点不属于正确性范畴。类比管家在工具墙上抓错了工具,拿打电话的流程去查天气。