推理提供商文档

使用推理提供者进行函数调用

Hugging Face's logo
加入 Hugging Face 社区

并获得增强的文档体验

开始使用

使用推理提供者进行函数调用

函数调用使语言模型能够通过生成基于用户输入的结构化函数调用来与外部工具和 API 进行交互。此功能允许您构建可以执行诸如检索实时数据、进行计算或与外部服务交互等操作的 AI Agent。

当您提供一个经过微调以使用带有函数描述的工具的语言模型时,它可以根据用户请求决定何时调用这些函数,执行它们,并将结果整合到自然语言响应中。例如,您可以构建一个助手来获取实时天气数据以提供准确的响应。

本指南假设您拥有 Hugging Face 帐户和访问令牌。您可以在 huggingface.co 创建免费帐户,并从您的 设置页面 获取令牌。

定义函数

第一步是实现您希望模型调用的函数。我们将使用一个简单的天气函数示例,该函数返回给定位置的当前天气。

一如既往,我们将首先初始化我们的推理客户端的客户端。

openai
huggingface_hub

在 OpenAI 客户端中,我们将使用 base_url 参数来指定我们希望用于请求的提供者。

import json
import os

from openai import OpenAI

# Initialize client
client = OpenAI(
    base_url="https://router.huggingface.co/v1",
    api_key=os.environ["HF_TOKEN"],
)

我们可以将函数定义为一个执行简单任务的 Python 函数。在这种情况下,该函数将返回当前天气,其格式为字典,包含位置、温度和状况。

# Define the function
def get_current_weather(location: str) -> dict:
    """Get weather information for a location."""
    # In production, this would call a real weather API
    weather_data = {
        "San Francisco": {"temperature": "22°C", "condition": "Sunny"},
        "New York": {"temperature": "18°C", "condition": "Cloudy"},
        "London": {"temperature": "15°C", "condition": "Rainy"},
    }
    
    return weather_data.get(location, {
        "location": location,
        "error": "Weather data not available"
    })

现在我们需要定义函数模式,该模式向语言模型描述我们的天气函数。此模式告诉模型函数期望哪些参数以及函数的作用。


# Define the function schema
tools = [
    {
        "type": "function",
        "function": {
            "name": "get_current_weather",
            "description": "Get current weather for a location",
            "parameters": {
                "type": "object",
                "properties": {
                    "location": {
                        "type": "string", 
                        "description": "City name"
                    },
                },
                "required": ["location"],
            },
        },
    },
]

该模式是一种 JSON Schema 格式,它描述了函数的作用、其参数以及哪些参数是必需的。描述有助于模型了解何时调用函数以及如何调用它。

在聊天中处理函数

函数在典型的聊天完成对话中起作用。模型将根据用户输入决定何时调用它们。

user_message = "What's the weather like in San Francisco?"

messages = [
    {
        "role": "system",
        "content": "You are a helpful assistant with access to weather data."
    },
    {"role": "user", "content": user_message}
]

# Initial API call with tools
response = client.chat.completions.create(
    model="deepseek-ai/DeepSeek-R1-0528",
    messages=messages,
    tools=tools,
    tool_choice="auto" # Let the model decide when to call functions
)

response_message = response.choices[0].message

tool_choice 参数用于控制模型何时调用函数。在这种情况下,我们使用 auto,这意味着模型将决定何时调用函数(0 次或多次)。下面我们将详细介绍 tool_choice 和其他参数。

接下来,我们需要检查模型响应中是否调用了任何函数。如果调用了,我们需要执行该函数并将结果添加到对话中,然后再将最终响应发送给用户。


# Check if model wants to call functions
if response_message.tool_calls:
    # Add assistant's response to messages
    messages.append(response_message)

    # Process each tool call
    for tool_call in response_message.tool_calls:
        function_name = tool_call.function.name
        function_args = json.loads(tool_call.function.arguments)

        # Execute the function
        if function_name == "get_current_weather":
            result = get_current_weather(function_args["location"])
            
            # Add function result to messages
            messages.append({
                "tool_call_id": tool_call.id,
                "role": "tool",
                "name": function_name,
                "content": json.dumps(result),
            })

    # Get final response with function results
    final_response = client.chat.completions.create(
        model="deepseek-ai/DeepSeek-R1-0528",
        messages=messages,
    )

    return final_response.choices[0].message.content
else:
    return response_message.content

工作流程很简单:使用您的工具进行初始 API 调用,检查模型是否要调用函数,如果需要则执行它们,将结果添加到对话中,并获取用户的最终响应。

我们已经处理了模型要调用函数且函数确实存在的情况。但是,模型可能会尝试调用不存在的函数,因此我们也需要考虑这一点。我们也可以使用 strict 模式来处理这种情况,我们稍后会介绍。

多个函数

您可以为更复杂的助手定义多个函数。

# Define multiple functions
def get_current_weather(location: str) -> dict:
    """Get current weather for a location."""
    return {"location": location, "temperature": "22°C", "condition": "Sunny"}

def get_weather_forecast(location: str, date: str) -> dict:
    """Get weather forecast for a location."""
    return {
        "location": location,
        "date": date,
        "forecast": "Sunny with chance of rain",
        "temperature": "20°C"
    }

# Function registry
AVAILABLE_FUNCTIONS = {
    "get_current_weather": get_current_weather,
    "get_weather_forecast": get_weather_forecast,
}

# Multiple tool schemas
tools = [
    {
        "type": "function",
        "function": {
            "name": "get_current_weather",
            "description": "Get current weather for a location",
            "parameters": {
                "type": "object",
                "properties": {
                    "location": {"type": "string", "description": "City name"}
                },
                "required": ["location"],
            },
        },
    },
    {
        "type": "function",
        "function": {
            "name": "get_weather_forecast",
            "description": "Get weather forecast for a location",
            "parameters": {
                "type": "object",
                "properties": {
                    "location": {"type": "string", "description": "City name"},
                    "date": {"type": "string", "description": "Date in YYYY-MM-DD format"},
                },
                "required": ["location", "date"],
            },
        },
    },
]

response = client.chat.completions.create(
    model="deepseek-ai/DeepSeek-R1-0528",
    messages=messages,
    tools=tools,
    tool_choice="auto"
)

我们已经定义了多个函数并将它们添加到了工具列表中。模型将根据用户输入决定何时调用它们。我们还可以使用 tool_choice 参数强制模型调用特定函数。

我们可以像处理单个函数示例一样处理工具执行。这次使用 elif 语句来处理不同的函数。

# execute the response
response_message = response.choices[0].message

# check if the model wants to call functions
if response_message.tool_calls:
    # process the tool calls
    for tool_call in response_message.tool_calls:
        function_name = tool_call.function.name
        function_args = json.loads(tool_call.function.arguments)

        # execute the function
        if function_name == "get_current_weather":
            result = get_current_weather(function_args["location"])
        elif function_name == "get_weather_forecast":
            result = get_weather_forecast(function_args["location"], function_args["date"])

        # add the result to the conversation
        messages.append({
            "tool_call_id": tool_call.id,
            "role": "tool",
            "name": function_name,
            "content": json.dumps(result),
        })

    # get the final response with function results
    final_response = client.chat.completions.create(
        model="deepseek-ai/DeepSeek-R1-0528",
        messages=messages,
    )

    return final_response.choices[0].message.content
else:
    return response_message.content

🎉 您已经构建了一个功能齐全的助手,它可以调用多个函数来获取天气数据!

其他配置

让我们看看使用推理提供者进行函数调用的其他配置选项,以充分利用其功能。

提供者选择

您可以指定使用哪个推理提供者以更好地控制性能和成本。这在函数调用中会很有用,可以减少模型响应中的方差。

openai
huggingface_hub

在 OpenAI 客户端中,您可以通过将提供者 ID 附加到模型参数上来指定要用于请求的提供者,如下所示:

# The OpenAI client automatically routes through Inference Providers
# You can specify provider preferences in your HF settings
client = OpenAI(
    base_url="https://router.huggingface.co/v1",
    api_key=os.environ["HF_TOKEN"],
)

client.chat.completions.create(
-     model="deepseek-ai/DeepSeek-R1-0528", # automatically select provider based on hf.co/settings/inference-providers
+     model="deepseek-ai/DeepSeek-R1-0528:novita", # manually select Novita
+     model="deepseek-ai/DeepSeek-R1-0528:hyperbolic", # manually select Hyperbolic
      ...
)

通过切换提供者,您可以看到模型响应的变化,因为每个提供者使用不同的模型配置。

每个推理提供者都有不同的功能和性能特征。您可以在 推理提供者 部分找到有关每个提供者的更多信息。

工具选择选项

您可以使用 tool_choice 参数来控制何时调用哪些函数。

tool_choice 参数用于控制模型何时调用函数。在大多数情况下,我们使用 auto,这意味着模型将决定何时调用函数(0 次或多次)。

# Let the model decide (default)
response = client.chat.completions.create(
    model="deepseek-ai/DeepSeek-R1-0528",
    messages=messages,
    tools=tools,
    tool_choice="auto"  # Model decides when to call functions
)

但是,在某些用例中,您可能希望强制模型调用函数,以便它永远不会基于自己的知识进行回复,而只基于函数调用结果进行回复。

# Force the model to call at least one function
response = client.chat.completions.create(
    model="deepseek-ai/DeepSeek-R1-0528",
    messages=messages,
    tools=tools,
    tool_choice="required"  # Must call at least one function
)

这对于简单的函数效果很好,但如果您有更复杂的函数,您可能希望使用 tool_choice 参数来强制模型至少调用一次特定函数。

openai
huggingface_hub

例如,假设您的助手的唯一工作是提供给定位置的天气。您可能希望强制模型调用 get_current_weather 函数,而不调用任何其他函数。

# Force a specific function call
response = client.chat.completions.create(
    model="deepseek-ai/DeepSeek-R1-0528",
    messages=messages,
    tools=tools,
    tool_choice={
        "type": "function",
        "function": {"name": "get_current_weather"}
    }
)

在这里,我们强制模型调用 get_current_weather 函数,而不调用任何其他函数。

严格模式

使用严格模式可确保函数调用严格遵循您的模式。这有助于防止模型使用意外的参数调用函数,或调用不存在的函数。

# Define tools with strict mode
tools = [
    {
        "type": "function",
        "function": {
            "name": "get_current_weather",
            "description": "Get current weather for a location",
            "parameters": {
                "type": "object",
                "properties": {
                    "location": {"type": "string", "description": "City name"},
                },
                "required": ["location"],
+                "additionalProperties": False,  # Strict mode requirement
            },
+            "strict": True,  # Enable strict mode
        },
    },
]

严格模式确保函数参数与您的模式完全匹配:不允许有其他属性,必须提供所有必需的参数,并且数据类型受到严格强制。

并非所有提供者都支持严格模式。您可以查看提供者的文档,了解它是否支持严格模式。

流式响应

启用流式传输以实时响应函数调用。这有助于向用户显示模型的进度,或更有效地处理长时间运行的函数调用。

# Enable streaming with function calls
stream = client.chat.completions.create(
    model="deepseek-ai/DeepSeek-R1-0528",
    messages=messages,
    tools=tools,
    tool_choice="auto",
    stream=True  # Enable streaming
)

# Process the stream
for chunk in stream:
    if chunk.choices[0].delta.tool_calls:
        # Handle tool call chunks
        tool_calls = chunk.choices[0].delta.tool_calls
    
    if chunk.choices[0].delta.content:
        # Handle content chunks
        content = chunk.choices[0].delta.content

流式传输允许您在响应到达时处理它们,向用户显示实时进度,并更有效地处理长时间运行的函数调用。

并非所有提供者都支持流式传输。您可以查看提供者的文档,了解它是否支持流式传输,或者您可以参考此 动态模型兼容性表

后续步骤

现在您已经了解了如何使用推理提供者进行函数调用,您可以开始构建自己的 Agent 和助手了!为什么不尝试一些这些想法:

  • 尝试使用小型模型以获得更快的响应和更低的成本
  • 构建一个可以获取实时数据的 Agent
  • 使用推理模型构建一个可以与外部工具进行推理的 Agent
在 GitHub 上更新

© . This site is unofficial and not affiliated with Hugging Face, Inc.