大家好,我是吴师兄。
在 Agent 相关的面试题里,有一道极其关键、但很多人答不好的问题:
“你们的 Function Call 是怎么训练的?训练数据怎么构建的?”
为什么面试官喜欢问这题?
因为 真实落地的 Agent 系统,一定绕不开训练数据: 如果没有自己的数据集,就只能依赖模型的“自然能力”, 但自然能力只在 demo 里好看,一上生产就会乱跑。
反过来,一个工程师如果能讲清楚:
-
为什么需要训练?
-
用什么样的数据?
-
怎么构建?
-
怎么迭代?
-
怎么评估?
那么基本可以确定: 不是玩概念,而是真的做过项目。
这一篇,我们就按照实际工程体系,把这道题拆开说清楚。
为什么 Function Call 需要训练?
原因一句话就能讲明白:
“通用大模型不会天然理解你的业务工具。”
例如你给模型 6 个函数:
-
search_flights
-
book_flight
-
search_hotels
-
book_hotel
-
get_weather
-
get_user_profile
看起来很清晰,但对模型来说 它不知道你系统的默认逻辑,也不知道你业务的最佳流程。
所以没有训练的模型会出现各种行为:
-
选错工具
-
函数名拼错
-
参数格式不对
-
数字 / 日期解析错误
-
忽略工具,直接用自然语言回答
-
幻觉生成 tool call
-
多轮信息缺失
这些都是生产系统里最常见的 badcase。
因此,Function Call 想稳定,必须加训练数据来“打磨模型的习惯”。
训练数据的目标是什么?
很多人以为任务叫“Function Call”,目标就只有一个:
“让模型调用正确的工具。”
但这是不完整的。
一个真实的 FC 训练集,通常要同时教给模型 4 种能力:
① 工具选择能力(Tool Selection)
模型要学会: 什么场景选什么工具,什么场景不选工具。
② 参数绑定能力(Argument Filling)
能正确解析用户自然语言里的参数:
-
时间(“明天”“本周六”)
-
城市(“魔都”→上海)
-
数字(“三天”→3)
-
隐式信息(用户偏好、历史记忆)
③ 格式化能力(JSON / Schema)
很多模型“工具选对了”,但 JSON 拼错了: 缺引号、少括号、值类型错误…
训练集要让它习惯按 schema 生成。
④ 多轮上下文能力(Multi-turn)
例如:
Turn1:
“想去北京玩几天。”
Turn2:
“下周一出发。”
Turn3:
“帮我查机票。”
训练集必须告诉模型: 如何利用记忆 / 上下文补全参数。
Function Call 的训练数据应该长什么样?
这一部分是“决胜分区”。
能讲清楚训练样本的结构,就是“做过”和“没做过”的分界线。
一般包括三个部分:
① 正样本(Positive Examples)
告诉模型: “遇到这种 query,你应该这么调用工具。”
例如:
User: 帮我查一下明天从上海到北京的机票。 Assistant: { "tool": "search_flights", "args": { "origin": "上海", "destination": "北京", "date": "2023-10-30" } }
覆盖常规场景。
② 负样本(Negative Examples)
告诉模型: “这种不能使用工具,或者你之前的行为是错的。”
例如:
用户问闲聊:
“北京最近冷吗?”
负样本要标注:
Assistant: (不给工具调用) 北京未来三天的天气较冷...
或者:
用户问:
“给我来一份天气订票。”
那负样本应该告诉模型:
-
这类混合意图需要先澄清
-
不能直接调用任何工具
③ 难例(Hard Cases)
这是训练数据中最关键的一部分。
例如:
-
需要 CoT 推理才能找到参数
-
需要多轮记忆才能补全信息
-
用户输入模糊,需要澄清
-
错误示例 → 正确修正示例
-
JSON 类型容易错的样本
-
模糊地名、口语表达、方言
例如:
User: 帮我查一下后天魔都飞帝都的机票。 Assistant (tool_call): { "tool": "search_flights", "args": { "origin": "上海", "destination": "北京", "date": "2023-10-31" } }
用了:
-
俗称识别
-
日期解析
-
参数抽取
这类样本越多,模型越稳。
训练数据从哪里来?(四种来源)
一般包括四类来源,面试时说这段可以直接加分
① 合成数据(Synthetic Data)——最重要
用模板 / LLM 自动生成大量样本。
比如:
“帮我查 / 查询 / 看一下 … 明天 / 后天 … 上海 → 北京 … 的航班”
组合参数之后形成成千上万条数据。
对于低资源业务场景,合成数据占比可以达到 70% 以上。
② 真实对话日志(Real Logs)
如果系统已经上线,那么真实日志是最宝贵的训练源:
-
用户真实表达
-
隐式信息非常多
-
包含大量歧义
尤其是 badcase,整个训练集的灵魂就在这里。
③ 规则生成的边界样本(Rule-based Hard Cases)
用于强化:
-
日期边界(跨月、模糊日期)
-
模糊表达(“明早”“后天晚上”)
-
用户错别字、不完整句子
-
tool schema 边界值
-
参数缺失、参数冲突
这些用 LLM 自动生成也可以。
④ Badcase 驱动(Error-driven)样本
每次模型调用失败,就把失败场景反向加入训练集。
比如:
badcase:
search_flights(date="tomorrow")
但 origin 缺失
那么训练集应该补一条:
User: 明天飞北京的机票 Assistant: 请问您从哪个城市出发?
这就是“数据闭环”。
训练集的规模与比例怎么控制?
比较通用的比例搭配:
-
正样本:60%
-
难例:30%
-
负样本:10%
对成熟系统来说,难例比例会逐渐提高,因为边界错误会越来越多。
样本规模一般取决于工具数量和业务复杂度:
-
简单业务:几千条
-
中等复杂度(航旅、电商):1–5 万条
-
多轮 Agent(企业级助手):10 万条以上
你在面试中说这个区间,基本属于“深度选手”了。
训练应该怎么做?(两种路径)
这部分面试官也会问。
① 轻训:LoRA / Adapter(最常见)
只在工具调用能力上做微调。
训练快、成本低、效果稳定。
适合:
-
少量工具
-
智能助手类 Agent
-
需要频繁迭代的项目
② 重训:Supervised Fine-tuning + Preference Optimization
适合:
-
工具多
-
参数复杂
-
强流程型 Agent(比如金融类)
-
需要严格避免幻觉
一般会采用:
-
SFT:学“正确行为”
-
DPO / ORPO:惩罚错误行为,增强可控性
面试官会很喜欢听的一段话(你可以背)
“我们的 Function Call 训练集分三种:正样本、负样本和难例。
正样本教模型工具的标准调用方式;
难例覆盖用户模糊表达、多轮上下文、参数歧义;
负样本用于告诉模型哪些场景不能调用工具。
全部样本通过合成数据、真实日志和 Badcase 驱动构建,形成持续闭环。
最终训练采用 LoRA,使模型在我们业务的工具使用上具备高度稳定性。”
这一段 面试官听了就知道你不是“看文档的”,而是“做过工程的”。
结语
Function Call 的训练不是“有没有做”, 而是 有没有体系、有没有闭环、有没有从错误中迭代出来的结果。
没有训练的 Agent,只会在 demo 里看起来很聪明;
真正稳定的系统,背后一定是大量带标注的数据和不断优化的 badcase 流水线。
也是在训练营的多个 Agent 实战项目里,我们用同样的方法做到:
-
工具调用准确率从 62% → 94%
-
JSON 结构错误下降 80%
-
参数缺失类错误下降到个位数
-
多轮对话成功率显著提升
这些经验,也是后面这系列文章能够写得扎实的原因。

