Function Call 完全指南:让大模型从“聊天”到“行动”

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

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


📌 为什么需要 Function Call?

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

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


一、Function Call 完整流程

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


二、详细步骤与代码实现

2.1 定义函数及 JSON Schema

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

python 复制代码
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,并传入函数定义

python 复制代码
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 处理函数调用并执行实际函数

python 复制代码
# 如果模型决定调用函数
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 完整封装示例(可直接运行)

python 复制代码
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 Call LLM 主动请求调用外部函数的机制
JSON Schema 函数的"说明书",描述名称、参数、类型
tool_choice 控制模型是否/何时调用函数(auto / none / 强制指定)
多次调用 模型可在一个回答中请求多个函数,需依次执行并返回结果

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

相关推荐
!chen1 小时前
Oracle Deep Data Security (Deep Sec) 初体验
数据库·oracle·ffmpeg
淘矿人1 小时前
Claude助力前端开发
java·数据库·git·python·sql·spring·database
weixin_444012931 小时前
Go语言GORM怎么做分页_Go语言GORM分页查询教程【实用】
jvm·数据库·python
hanbr2 小时前
Qt:事件处理与绘图详解
开发语言·数据库·qt
weixin_444012932 小时前
Go语言怎么防SQL注入_Go语言SQL注入防护教程【深入】
jvm·数据库·python
爱编程的小新☆2 小时前
Langchain4j对话记忆
数据库·缓存·持久化存储·langchain4j
m0_470857642 小时前
C#怎么实现蓝牙设备搜索_C#如何开发Bluetooth应用【指南】
jvm·数据库·python
曦夜日长2 小时前
Linux系统篇,开发工具(三):文件翻译的思路重构、库的深入理解、文件链接时区别与细节
linux·数据库·重构
2303_821287382 小时前
在 Go 中声明包级全局 Map 的正确方法
jvm·数据库·python