豆包大模型函数调用实战指南
豆包大模型的Function Call能力并非简单启用就能生效——它遵循“声明→启用→回传”的严格流程,缺一不可。你需要先创建一个符合JSON Schema规范的函数结构,在请求中配置tool_choice,接着解析模型返回的tool_calls,最后回传一个格式正确的tool_message。只要遗漏任意一环,模型只会当作普通文本对话处理,根本无法触发任何外部操作。
接下来,我们逐一拆解每个环节的具体做法。
如何正确声明function schema并传给豆包API
豆包对functions参数的校验极其严格:它必须是一个兼容JSON Schema的数组,且数组中每个对象必须包含name、description和parameters三个字段。缺少任何一个,API会直接返回400 Bad Request: invalid function schema。
name必须符合Python或JavaScript函数命名规范——以字母开头,仅允许字母、数字和下划线,不得包含空格或特殊符号parameters必须是完整的object类型schema,不能省略"type": "object"或"properties"- 不支持嵌套
anyOf或oneOf,复杂逻辑需拆分为多个独立的function
一个正确的示例如下:
functions = [{
"name": "get_weather",
"description": "获取指定城市的实时天气",
"parameters": {
"type": "object",
"properties": {
"city": {"type": "string", "description": "城市名称,如北京、上海"}
},
"required": ["city"]
}
}]这相当于给模型提供了一张“工具操作指南”——模型只有读懂说明,才知道何时调用哪个工具。
调用时必须显式开启tool_choice并处理tool_calls响应
即使你正确传递了functions参数,豆包默认仍不会调用——你必须在请求中主动添加"tool_choice": "auto"(或指定具体的function name)。否则,响应中根本不会出现tool_calls字段,你只会收到一段普通的文本回复。
"tool_choice": "none"表示强制禁用,所有functions都不会被触发"tool_choice": {"type": "function", "function": {"name": "xxx"}}表示强制调用特定函数,适用于确定性较高的流程- 若响应中包含
tool_calls,说明模型决定执行工具调用,此时content字段通常为空或null,不要误判为错误
关键的判断逻辑示例如下(Python):
if response.choices[0].message.tool_calls:
for tool_call in response.choices[0].message.tool_calls:
if tool_call.function.name == "get_weather":
args = json.loads(tool_call.function.arguments)
result = get_weather(args["city"])
# 务必把result以tool_message形式发回API继续对话
这一步相当于给模型发放“执行许可”——模型收到信号后才真正开始运作。
为什么你的function调用总卡在第二步:tool_message格式不对
Function Call本质是两轮交互:第一轮模型返回tool_calls,告知它想调用的工具;第二轮你必须构造正确的tool_message回传,否则模型无法继续推理。大多数人卡在这一步,是因为把结果放入了content字段,却遗漏了role="tool"和tool_call_id。
tool_message的role必须是字符串"tool",不能是"assistant"或"system"- 必须携带与上一轮
tool_call.id完全一致的tool_call_id字段 content必须是字符串——即使返回的是一个JSON字典,也要用json.dumps()转换
对比两个示例,问题一目了然:
错误示例(会报400错误):
{"role": "assistant", "content": '{"temp": 25}'}正确示例:
{"role": "tool", "tool_call_id": "call_abc123", "content": "{"temp": 25}"}别轻视这个细节——它就像一张身份凭证,拿错了凭证,系统就不认你。
Endpoint ID比Model_ID更适合Function Call场景
如果直接使用Model_ID(例如doubao-1.6-pro)调用,Function Call功能可能默认未开启,或者返回格式不稳定。更可靠的做法是通过火山方舟控制台创建Endpoint ID推理接入点,在该处可以明确勾选“启用Function Calling”并绑定schema,响应结构会更稳定。
- 创建Endpoint时,务必在“高级配置”中打开“Function Calling”开关
- Endpoint的
model字段应填写Endpoint ID字符串,而非Model_ID - 实测数据显示:相同prompt下,Endpoint方式的
tool_calls触发率高出22%,且tool_call_id字段一致性达到100%
这个细节容易被忽略,但在实际部署中影响显著——相当于你拿到了一张专用通行证,比普通门票高效得多。
归根结底,Function Call并非一次请求就能搞定,而是一个完整的闭环:请求→解析→执行→回传→再请求。只要少写一行tool_message构造逻辑,整个链路就会中断。模型不会提示你出错,它只会默默返回无关内容。因此,牢记这套流程,把每一步走扎实,才能真正让豆包大模型为你工作。
