更新时间:2026-03-10 GMT+08:00
分享

Function Call

什么是Function Call

工具调用(Tool Calling,Function Call,FC)是一种将大模型与外部工具和API相连的关键功能,作为自然语言与信息接口之间的“翻译官”,它能够将用户的自然语言请求智能地转化为对特定工具或API的调用,从而高效满足用户的特定需求。

工作原理:开发者通过自然语言向模型描述工具的功能和定义,模型在对话过程中自主判断是否需要调用工具。当需要调用时,模型会返回符合要求的工具函数及入参,开发者负责实际调用工具并将结果回填给模型,模型再根据结果进行总结或继续规划子任务。

实现原理

FC特性实现主要包括前处理(serving_chat模块)、后处理模块(tool parser)以及chat_template,前处理模块通过chat_template对用户prompt进行渲染,后处理模块对模型输出进行解析。整体流程如下图所示:

  1. 检测到用户输入中传入工具定义,并开启了auto tool choice选项;
  2. 应用chat template渲染用户输入,将工具信息和用户prompt构造到模型输入中;
  3. 模型执行推理并完成基础的后处理流程;
  4. tool parser对模型输出进行解析,如果模型输出中包含工具调用信息,tool parser会将工具调用信息解析到用户响应中的tool_calls字段中。

支持模型

当前支持Function Call的模型请参见文本生成支持能力。

规格说明

tool choice支持模式

tool choice目前只支持auto(自动识别)和named(指定函数调用)两种模式,不支持required(必选函数调用)模式,详情如下。

模式

支持情况

说明

示例

auto(推荐)

模型自动识别是否需要进行工具调用

"tool_choice": "auto"

named

指定函数调用

"tool_choice": {"type": "function", "function": {"name": "get_weather"}

required

×

提示模型必须进行函数调用

"tool_choice": "required"

支持处理模式

模式

支持情况

说明

流式输出适配

支持流式输出,逐步获取工具调用信息,提升响应效率。

多轮工具调用

当用户需求需要多次调用工具时,维护对话历史上下文,逐轮处理工具调用和结果回填。建议回填结果与模型输出保持一致。

特性兼容性

Function Call已有关键特性兼容性如下表。

特性

兼容

说明

兼容报错行为

Reasoning Outputs

支持思维链模型输出深度思考内容,Function Call场景下关闭深度思考内容输出,可以提高Function Call运行效率,同时避免某些模型reasoning_content中的异常返回影响结果解析。

Qwen3:支持关闭思维链。

-

基本使用流程

  1. 定义工具

    FC通过json格式定义tools字段的方式向模型提供可用工具。tools包含工具名称、描述、参数定义等信息。

    定义工具函数

    def get_weather(location: str, unit: str):
        return f"Getting the weather for {location} in {unit}..."
    • 假设在代码中定义了一个名为get_weather的工具函数,用于获取指定地点的天气信息。
      • location:表示天气查询的地点,必选。
      • unit:表示函数返回结果的温度单位,可选。
    • 注意:此用例只是模拟的天气查询场景,实际应用中需要调用真实的天气查询API。

    定义Tools

    "tools": [{
        "type": "function",
        "function": {
            "name": "get_weather",
            "description": "Get the current weather in a given location",
            "parameters": {
                "type": "object",
                "properties": {
                    "location": {"type": "string", "description": "City and state, e.g., 'San Francisco, CA'"},
                    "unit": {"type": "string", "enum": ["celsius", "fahrenheit"]}
                },
                "required": ["location"]
            }
        }
    }]
    • tools列表类型,其中每个元素代表一个可调用的工具函数。这里定义了一个名为get_weather的工具。
    • type:工具的类型,这里是固定值function,表示这是一个可调用工具函数。
    • function:函数对象,用于定义工具函数的详细信息,如名称、描述和参数。
      • name:函数名称,在这里为get_weather。
      • description:函数描述,解释该函数应用信息。
      • parameters:函数所需参数,这里是一个对象,包含location 和unit两个属性。
        • location:地点的位置信息,参数类型为string。
        • unit:温度单位,参数类型为枚举string,候选值为celsius或fahrenheit。
        • required:指定必须的参数,这里location是必须的。
  2. 发起请求

    在请求中提供用户问题和工具,模型会根据问题自动识别并返回需要调用的工具及参数。

    from openai import OpenAI
    import httpx
    
    import json
    client = OpenAI(base_url="https://api.modelarts-maas.com/openai/v1", api_key="MAAS_API_KEY", http_client=httpx.Client(verify=False))  # 把MAAS_API_KEY替换成已获取的API Key
    
    messages = [{"role": "user", "content": "What's the weather like in San Francisco?"}]
    tools = [
        {
            //参见步骤1中定义的tools
        }
    ]
    
    response = client.chat.completions.create(
        
        model="deepseek-v3.2",
        messages=messages ,
        tools=tools,
        tool_choice="auto"
    )

  3. 调用外部工具

    根据模型返回的工具和参数信息,调用对应的外部工具或API,获取工具的实际执行结果。

    # 解析模型返回的工具调和参数信息
    tool_call = response.choices[0].message.tool_calls[0].function
    # 工具名称
    tool_name = tool_call.function.name
    #根据工具名称执行对应工具
    if tool_name == "get_weather":
        # 提取的用户参数
        arguments = json.loads(tool_call.function.arguments)
        # 调用工具
        tool_result = get_weather(**arguments)
    • 从模型返回的tool_calls中获取模型调用的工具列表。
    • 根据工具名称执行对应工具。如当工具名称是get_weather时,则提取用户参数并调用get_weather函数获取工具执行结果。
  4. 回填执行结果并生成最终回复
    将工具执行结果以role=tool的消息形式回填给模型,模型根据结果生成最终回复。
    messages.append(completion.choices[0].message)
    messages.append({
        "role": "tool",
        "tool_call_id": tool_call.id,
        "content": tool_result
        "name": tool_name
    })
    # 调用模型生成最终回复
    final_response = client.chat.completions.create(
        model="deepseek-v3.2",
        messages=messages ,
        tools=tools,
        tool_choice="auto"
    )
    print(final_response.choices[0].message.content)

完整代码示例

from openai import OpenAI
import httpx
import json
api_key = "MAAS_API_KEY"  # 把MAAS_API_KEY替换成已获取的API Key
client = OpenAI(base_url="https://api.modelarts-maas.com/openai/v1", api_key=api_key, http_client=httpx.Client(verify=False))
def get_weather(location: str, unit: str):
    return f"Getting the weather for {location} in {unit}..."
tool_functions = {"get_weather": get_weather}
tools = [{
    "type": "function",
    "function": {
        "name": "get_weather",
        "description": "Get the current weather in a given location",
        "parameters": {
            "type": "object",
            "properties": {
                "location": {"type": "string", "description": "City and state, e.g., 'San Francisco, CA'"},
                "unit": {"type": "string", "enum": ["celsius", "fahrenheit"]}
            },
            "required": ["location", "unit"]
        }
    }
}]
response = client.chat.completions.create(
    model="deepseek-v3.2",
    messages=[{"role": "user", "content": "What's the weather like in San Francisco?"}],
    tools=tools,
    tool_choice="auto"
)
tool_call = response.choices[0].message.tool_calls[0].function
print(f"Function called: {tool_call.name}")
print(f"Arguments: {tool_call.arguments}")
print(f"Result: {get_weather(**json.loads(tool_call.arguments))}")

Example output:

Function called: get_weather
Arguments: {"location": "San Francisco, CA", "unit": "fahrenheit"}
Result: Getting the weather for San Francisco, CA in fahrenheit...

Prompt最佳实践

Function Call的性能很大程度上依赖于所使用模型本身的推理能力,用户需要通过合理的任务定义prompt配合清晰明确的工具函数定义实现高效的工具调用,使用时应该遵从以下原则:

  1. 任务定义简单直接,避免输入和任务无关的多余信息,避免造成对模型的信息干扰;
  2. 模型推理具有随机性,能用代码完成的任务就不要调用大模型;

以下是一些典型的错误示例和修正示范:

类别

问题

错误示例

改正后示例

函数定义

函数命名不规范,功能描述不清晰

{
    "type": "function",
    "function": {
        "name": "func1",
        "description": "功能函数"
    }
}
{
    "type": "function",
    "function": {
        "name": "CreateTask",
        "description": "当需要为用户新建工作项时,此工具将创建工作项,并返回工作项ID"
    }
}

参数定义

格式定义冗余,包含重复信息

{
    "time": {
        "type": "object",
        "description": "城市",
        "properties": {
            "city": {
                "description": "城市"
            }
        }
    }
}
{
    "time": {
        "type": "string",
        "description": "城市"
    }
}

包含非必要入参(包含固定值等)

{
    "time": {
        "type": "object",
        "description": "城市",
        "properties": {
            "city": {
                "description": "固定传杭州即可"
            }
        }
    }
}

如果函数入参非必要,比如为固定值。这种情况应该移除相关入参,直接由代码处理。

prompt

任务描述复杂,导致无意义增加工具调用轮次

System prompt:

你正在与用户Marvin沟通,你需要先查询用户ID,再通过ID为用户创建工作项……

System prompt:

你正在与用户Marvin(ID=123)沟通,你可以通过用户ID为用户创建工作项……

任务定义包含模糊信息,模型无法区分

System prompt:

可以通过ID查找用户,并获得用户的任务ID

此处两个ID无法明确区分,导致模型可能混用。

System prompt:

每个用户具有唯一的用户ID;每个工作项有对应的工作项ID。可以通过用户ID查找用户信息,并获取用户的所有工作项ID

任务定义与工具函数无法match

查询天气工具函数入参要求传入查询地点和指定日期。

prompt:

查询北京的天气

任务定义缺失日期信息,会导致模型无法调用函数或者输入日期为缺省值导致调用结果异常。

prompt:

查询北京2025年7月30日的天气

格式冲突

system prompt定义的某种返回格式与Function Call要求的格式冲突,导致工具函数调用失败。

去除导致函数调用异常的格式内容。

异常处理

JSON格式容错机制

对于轻微不合法的JSON格式,可尝试使用json-repair库进行容错修复。

import json_repair
 
invalid_json = '{"location": "北京", "unit": "摄氏度"}'
valid_json = json_repair.loads(invalid_json)

工具调用异常

因prompt输入和工具函数定义导致模型无法正确调用工具函数的场景,建议按照最佳实践部分的内容进行prompt调优和函数定义优化。

模型返回异常

Function Call功能依赖模型能力实现,因大模型幻觉等原因,可能出现模型返回结果不符合预期,导致一定的工具调用失败概率。

如果某场景下调用失败率较低,可以通过设置重试机制进行可靠性加固。

常见问题

  • 使用Function Call功能时,只调用1个函数,为什么会出现返回多个函数调用的情况?

    模型自主判断调用函数次数,通常与prompt语义不明确或工具函数定义模糊有关,建议参考最佳实践部分内容优化prompt输入和工具函数定义。

  • 使用Function Call功能时,配置max_tokens后为什么无法解析tool_calls?

    max_tokens配置过小可能会导致模型输出截断,无法正常解析出tool_calls内容,需要合理配置max_tokens大小。

  • 如何判断模型是否需要调用函数

    模型会根据用户问题结合工具定义和tool_choice字段自主判断,若返回结果中包含tool_calls字段,则表示需要调用工具。

  • 使用Function Call功能时,如果在请求中的System Prompt设置了输出格式,为什么有时会输出特殊标签token,导致无法解析tool_calls?

    这一般是由于System Prompt设置的格式未遵循模型所要求的格式规范。建议参考相关最佳实践,对prompt进行优化调整。

相关文档