【学习记录】Function Call 完全指南:让大模型从“聊天”到“行动”

Function Call(函数调用)是大语言模型从“只会聊天”升级为“能行动”的核心机制。它让 LLM 能够主动请求调用外部工具——查询实时天气、操作数据库、发送邮件、执行计算……本文从原理到代码,带你完整掌握 Function Call 的全链路开发。


📌 为什么需要 Function Call?

痛点说明Function Call 解决方案
知识截止LLM 训练数据有截止日期调用实时天气、股票、新闻 API
无法执行计算复杂的数学、单位换算容易出错调用计算器、单位转换函数
不能操作数据库无法查询或更新私有数据库调用数据库查询函数,返回结构化结果
不能执行业务逻辑无法发送邮件、创建工单调用业务 API,完成实际操作
需要确定性输出LLM 自由生成的字段名不固定强制通过函数签名返回严格结构的 JSON

一句话:Function Call = 让 LLM 拥有手脚


一、Function Call 完整流程

外部函数/API系统/应用程序大语言模型User外部函数/API系统/应用程序大语言模型Useralt[需要调用函数][不需要调用函数]用户提问发送提示词 + 可用函数定义判断是否需要调用函数返回函数调用 JSON执行实际函数返回执行结果发送函数结果基于结果生成自然语言回答最终回复直接生成回答最终回复

二、详细步骤与代码实现

2.1 定义函数及 JSON Schema

在系统中预先定义可被调用的函数,并用 JSON Schema 描述其功能、参数、必填项。

import json
from openai import OpenAI

# 模拟一个查询天气的真实函数
def get_current_weather(latitude: float, longitude: float):
    """实际可替换为真实 API 请求"""
    return f"当前坐标 ({latitude}, {longitude}) 的温度是 22°C,晴天"

# 定义函数的 JSON Schema(OpenAI 格式)
tools = [
    {
        "type": "function",
        "function": {
            "name": "get_current_weather",
            "description": "获取指定经纬度的当前天气",
            "parameters": {
                "type": "object",
                "properties": {
                    "latitude": {
                        "type": "number",
                        "description": "纬度,范围 -90 到 90"
                    },
                    "longitude": {
                        "type": "number",
                        "description": "经度,范围 -180 到 180"
                    }
                },
                "required": ["latitude", "longitude"],
                "additionalProperties": False
            },
            "strict": True
        }
    }
]

2.2 调用 LLM,并传入函数定义

client = OpenAI(api_key="your-api-key")

messages = [
    {"role": "user", "content": "北京今天的天气怎么样?"}
]

# 第一次调用:模型判断是否需要调用函数
response = client.chat.completions.create(
    model="gpt-4o",
    messages=messages,
    tools=tools,                    # 提供可用函数
    tool_choice="auto"              # 让模型自动决定是否调用
)

message = response.choices[0].message

2.3 处理函数调用并执行实际函数

# 如果模型决定调用函数
if message.tool_calls:
    tool_call = message.tool_calls[0]
    function_name = tool_call.function.name
    arguments = json.loads(tool_call.function.arguments)
    
    # 根据函数名执行对应的 Python 函数
    if function_name == "get_current_weather":
        result = get_current_weather(**arguments)
    
    # 将函数执行结果以 tool 消息追加到对话历史
    messages.append(message)                   # 添加模型的 function call 消息
    messages.append({
        "role": "tool",
        "tool_call_id": tool_call.id,
        "content": str(result)
    })
    
    # 第二次调用:让模型基于函数结果生成最终回答
    second_response = client.chat.completions.create(
        model="gpt-4o",
        messages=messages,
        tools=tools,
        tool_choice="auto"
    )
    final_answer = second_response.choices[0].message.content
    print(final_answer)
else:
    # 模型直接回答
    print(message.content)

2.4 完整封装示例(可直接运行)

import json
from openai import OpenAI

class FunctionCallAgent:
    def __init__(self, api_key: str, model: str = "gpt-4o"):
        self.client = OpenAI(api_key=api_key)
        self.model = model
        self.functions = {}          # 存储函数名 -> 实际函数
        self.tools = []              # 存储 JSON Schema

    def register_function(self, func, schema: dict):
        """注册一个可调用函数"""
        func_name = func.__name__
        self.functions[func_name] = func
        self.tools.append({
            "type": "function",
            "function": schema
        })

    def chat(self, user_message: str) -> str:
        messages = [{"role": "user", "content": user_message}]
        
        response = self.client.chat.completions.create(
            model=self.model,
            messages=messages,
            tools=self.tools,
            tool_choice="auto"
        )
        
        msg = response.choices[0].message
        
        if msg.tool_calls:
            messages.append(msg)
            for tool_call in msg.tool_calls:
                func_name = tool_call.function.name
                args = json.loads(tool_call.function.arguments)
                if func_name in self.functions:
                    result = self.functions[func_name](**args)
                    messages.append({
                        "role": "tool",
                        "tool_call_id": tool_call.id,
                        "content": str(result)
                    })
            
            final = self.client.chat.completions.create(
                model=self.model,
                messages=messages,
                tools=self.tools
            )
            return final.choices[0].message.content
        else:
            return msg.content

# 使用示例
def get_stock_price(symbol: str):
    """模拟获取股价"""
    prices = {"AAPL": 175.32, "GOOGL": 138.45, "TSLA": 245.60}
    return prices.get(symbol.upper(), "未知")

stock_schema = {
    "name": "get_stock_price",
    "description": "获取美股实时股价",
    "parameters": {
        "type": "object",
        "properties": {
            "symbol": {"type": "string", "description": "股票代码,如 AAPL"}
        },
        "required": ["symbol"],
        "additionalProperties": False
    },
    "strict": True
}

agent = FunctionCallAgent(api_key="your-key")
agent.register_function(get_stock_price, stock_schema)

print(agent.chat("苹果公司今天的股价是多少?"))

三、函数定义的关键要素(JSON Schema)

字段说明示例
name函数名称,须与代码函数名一致"get_current_weather"
description告诉模型该函数的作用,影响决策准确性"获取指定位置的天气"
parameters.type固定为 "object"
parameters.properties列出每个参数的名称、类型、描述{"latitude": {"type": "number"}}
parameters.required必填参数列表["latitude", "longitude"]
additionalProperties设为 false 增强严格性false
strict要求模型严格遵循 schema(部分 API 支持)true

四、常见应用场景

场景函数示例
实时信息查询天气、股票、新闻、汇率
数学计算计算器、方程求解、单位换算
数据库操作查询 SQL、插入记录、生成报表
第三方 API发送邮件、创建日历事件、发短信
业务逻辑预订机票、计算运费、库存检查
代码执行运行 Python 代码、解析表达式

五、注意事项

  1. 函数参数命名:要与 JSON Schema 中完全一致,否则 LLM 生成的可能无法匹配。
  2. 结果长度:函数返回的内容不宜过长(建议 < 1000 token),否则模型可能截断或混淆。
  3. 错误处理:如果函数执行失败,应返回明确的错误信息,模型会据此告知用户。
  4. 多次调用:一个请求中可以包含多个 tool_calls,需循环处理并返回多个结果。
  5. 不同 API 的差异
    • OpenAI:使用 tools 参数,函数调用返回 tool_calls
    • Anthropic Claude:使用 tools,返回 tool_use
    • 国产模型(DeepSeek、Qwen、智谱)也支持类似格式,略有差异。

🎯 总结

核心概念说明
Function CallLLM 主动请求调用外部函数的机制
JSON Schema函数的“说明书”,描述名称、参数、类型
tool_choice控制模型是否/何时调用函数(auto / none / 强制指定)
多次调用模型可在一个回答中请求多个函数,需依次执行并返回结果

Function Call 是构建 AI Agent 的核心基础设施。它将大语言模型从“嘴炮”升级为“实干家”——不仅能说,还能做。掌握它,你就能构建出能查天气、订机票、操作数据库的真正智能体。

更多推荐