AI 智能体与函数调用:为 LLM 构建工具

AI2026-09-25TryQuickToolBox

你正在构建一个需要获取实时数据、执行计算或与外部 API 交互的 AI 智能体。但如何弥合 LLM 文本生成与实际代码执行之间的鸿沟?函数调用(也称为工具使用)就是答案。它让 LLM 请求特定操作,由你的代码执行这些操作。本指南将带你了解如何为 AI 智能体设计、实现和调试函数调用。

什么是函数调用?

函数调用是一种机制,LLM 可以输出结构化请求来调用你定义的函数。模型不再生成自由文本,而是返回包含函数名和参数的 JSON 对象。然后你的应用程序执行该函数,并将结果反馈给模型。这使智能体能够执行文本生成之外的操作,例如查询数据库、发送邮件或调用 API。

OpenAI、Anthropic 和 Google 等主要 LLM 提供商都支持函数调用。核心思路一致:你描述可用的工具,模型决定何时使用它们,你负责处理执行。

为 LLM 设计工具

设计良好的工具对于可靠的智能体行为至关重要。遵循以下原则:

示例:天气工具

以下是一个简单的 JSON schema 格式工具定义,常用于 OpenAI 的 API:

{
  "name": "get_weather",
  "description": "Get the current weather for a given city",
  "parameters": {
    "type": "object",
    "properties": {
      "city": {
        "type": "string",
        "description": "The city name, e.g., San Francisco"
      },
      "unit": {
        "type": "string",
        "enum": ["celsius", "fahrenheit"],
        "description": "Temperature unit"
      }
    },
    "required": ["city"]
  }
}

实现函数调用:分步指南

让我们使用 OpenAI 的 API 构建一个最小的智能体循环(该模式也适用于其他提供商)。

1. 定义你的工具

创建工具 schema 列表以及函数名称到实际 Python 函数的映射。

import json
import openai

# Tool schemas
tools = [
    {
        "type": "function",
        "function": {
            "name": "get_weather",
            "description": "Get current weather for a city",
            "parameters": {
                "type": "object",
                "properties": {
                    "city": {"type": "string"},
                    "unit": {"type": "string", "enum": ["celsius", "fahrenheit"]}
                },
                "required": ["city"]
            }
        }
    }
]

# Actual functions
def get_weather(city: str, unit: str = "celsius") -> dict:
    # In reality, call a weather API
    return {"city": city, "temperature": 22, "unit": unit, "condition": "sunny"}

# Map names to functions
function_map = {
    "get_weather": get_weather
}

2. 创建智能体循环

智能体循环向 LLM 发送消息,检查工具调用,执行它们,并重复直到模型返回最终答案。

def run_agent(user_message: str):
    messages = [{"role": "user", "content": user_message}]
    
    while True:
        response = openai.ChatCompletion.create(
            model="gpt-4",
            messages=messages,
            tools=tools,
            tool_choice="auto"
        )
        
        message = response.choices[0].message
        messages.append(message)
        
        # If no tool calls, return the content
        if not message.get("tool_calls"):
            return message["content"]
        
        # Execute each tool call
        for tool_call in message.tool_calls:
            function_name = tool_call.function.name
            arguments = json.loads(tool_call.function.arguments)
            
            if function_name in function_map:
                result = function_map[function_name](**arguments)
            else:
                result = {"error": f"Unknown function: {function_name}"}
            
            # Append tool result to messages
            messages.append({
                "role": "tool",
                "tool_call_id": tool_call.id,
                "content": json.dumps(result)
            })

此循环持续进行,直到 LLM 生成不带工具调用的响应,表明它已获得足够的信息。

3. 处理错误和边缘情况

真实世界的智能体必须处理:

可靠智能体的最佳实践

函数调用支持对比

提供商 功能名称 格式
OpenAI Function Calling JSON Schema
Anthropic Tool Use JSON Schema
Google Function Calling OpenAPI Schema

高级模式

随着智能体的成长,考虑以下模式:

调试函数调用

当出现问题时,检查:

使用日志记录完整的消息历史和工具调用。通常,问题在于预期参数与实际参数不匹配。

常见问题

函数调用和工具使用有什么区别?

它们指的是同一个概念。OpenAI 称之为“函数调用”,而 Anthropic 使用“工具使用”。两者都允许 LLM 请求执行外部函数。

我可以将函数调用与开源模型一起使用吗?

可以,一些开源模型如 Llama 3.1 支持函数调用,LangChain 等框架提供了抽象。然而,支持程度各异,你可能需要微调或使用特定的提示格式。

如何防止 LLM 调用危险函数?

切勿直接暴露危险函数。使用允许列表、验证输入并实施权限检查。对于敏感操作,在执行前需要人工确认。

准备好构建你自己的 AI 智能体了吗?从定义一个简单的工具并测试智能体循环开始。如需更多开发者工具,请查看我们的 JSON Formatter 来调试工具调用负载。