推理提供商文档

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

Hugging Face's logo
加入 Hugging Face 社区

并获得增强的文档体验

开始使用

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

函数调用使语言模型能够通过根据用户输入生成结构化的函数调用,从而与外部工具和 API 进行交互。这一能力允许您构建 AI 代理,使其能够执行诸如检索实时数据、进行计算或与外部服务交互等操作。

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

本指南假设您已拥有 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"
    })

现在我们需要定义函数模式(schema),以便向语言模型描述我们的天气函数。该模式会告知模型该函数预期的参数及其功能。


# 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 selects the fastest available provider
+     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 函数,而不调用任何其他函数。

严格模式

使用严格模式以确保函数调用完全符合您的 schema。这有助于防止模型使用意外参数调用函数,或调用不存在的函数。

# 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
        },
    },
]

严格模式确保函数参数与您的 schema 完全匹配:不允许出现额外属性,必须提供所有必填参数,并且严格执行数据类型。

并非所有提供商都支持严格模式。您可以查阅提供商的文档以确认其是否支持严格模式。

流式响应

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

# 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

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

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

后续步骤

现在您已经了解了如何使用推理提供商 (Inference Providers) 进行函数调用,您可以开始构建自己的智能体 (Agents) 和助手了!不妨尝试以下一些想法:

  • 尝试使用较小的模型以获得更快的响应速度并降低成本
  • 构建一个能够获取实时数据的智能体
  • 使用推理模型构建一个能够利用外部工具进行推理的智能体
在 GitHub 上更新

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