2.9 OpenAI Function Calling函数调用完整实现教程

1 阅读4分钟

2.9 OpenAI Function Calling函数调用完整实现教程

一、Function Calling概述

Function Calling允许GPT模型在推理过程中决定是否调用外部函数,并将函数返回结果纳入后续生成。这实现了LLM与数据库、API、计算器等外部工具的集成,是构建智能体(Agent)的基础能力。


二、调用流程

sequenceDiagram
    participant U as 用户
    participant M as GPT
    participant F as 外部函数

    U->>M: "北京今天天气怎么样?"
    M->>M: 判断需调用 get_weather
    M->>F: get_weather(city="北京")
    F->>M: "晴,20-28℃"
    M->>U: "北京今天晴,气温20-28℃。"

三、完整实现代码

"""
OpenAI Function Calling 完整示例
运行: pip install openai python-dotenv
"""

import json
import os
from dotenv import load_dotenv
from openai import OpenAI

load_dotenv()
client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))

# 1. 定义可调用的函数
def get_weather(city: str) -> str:
    """模拟天气查询"""
    data = {"北京": "晴,20-28℃", "上海": "多云,22-30℃", "广州": "雷阵雨,25-32℃"}
    return data.get(city, "暂无该城市天气数据")

# 2. 定义函数描述(供模型理解)
functions = [
    {
        "name": "get_weather",
        "description": "获取指定城市的天气信息",
        "parameters": {
            "type": "object",
            "properties": {
                "city": {"type": "string", "description": "城市名称,如北京、上海"}
            },
            "required": ["city"]
        }
    }
]

def chat_with_tools(user_query: str) -> str:
    messages = [{"role": "user", "content": user_query}]
    
    # 3. 首次调用,可能触发 function_call
    response = client.chat.completions.create(
        model="gpt-3.5-turbo-0613",
        messages=messages,
        functions=functions,
        function_call="auto"
    )
    
    msg = response.choices[0].message
    
    if msg.function_call:
        name = msg.function_call.name
        args = json.loads(msg.function_call.arguments)
        # 4. 执行实际函数
        if name == "get_weather":
            result = get_weather(args["city"])
        else:
            result = "未知函数"
        
        # 5. 将结果返回给模型,生成最终回复
        messages.append(msg)
        messages.append({"role": "function", "name": name, "content": result})
        
        follow = client.chat.completions.create(
            model="gpt-3.5-turbo-0613",
            messages=messages,
            functions=functions,
            function_call="auto"
        )
        return follow.choices[0].message.content
    
    return msg.content

if __name__ == "__main__":
    print(chat_with_tools("上海今天天气怎么样?"))
    print(chat_with_tools("你好"))  # 无需调用函数,直接回复

四、关键参数说明

参数说明
functions函数描述列表,模型据此判断是否调用
function_call"auto"自动判断;"none"不调用;或指定函数名强制调用

注意:需使用支持Function Calling的模型,如gpt-3.5-turbo-0613gpt-4等。


五、多函数与复杂参数

functions = [
    {
        "name": "get_weather",
        "description": "获取天气",
        "parameters": {
            "type": "object",
            "properties": {"city": {"type": "string"}},
            "required": ["city"]
        }
    },
    {
        "name": "search",
        "description": "搜索信息",
        "parameters": {
            "type": "object",
            "properties": {
                "query": {"type": "string"},
                "limit": {"type": "integer", "description": "返回条数,默认5"}
            },
            "required": ["query"]
        }
    }
]

六、function_call的响应结构

6.1 解析function_call

msg = response.choices[0].message
if msg.function_call:
    name = msg.function_call.name
    arguments = msg.function_call.arguments  # JSON字符串
    args_dict = json.loads(arguments)

6.2 将结果返回给模型

必须使用role="function",并包含namecontent。content为字符串,若为复杂对象需json.dumps。

6.3 循环调用

模型可能连续多次调用不同函数。需循环:调用API → 若有function_call则执行 → 将结果追加到messages → 再次调用,直至无function_call。


七、常见问题

问题原因解决
模型不调用函数描述模糊、用户意图与函数不匹配细化description、增加示例
参数解析失败arguments非合法JSON捕获json.loads异常,将错误信息返回模型
函数执行超时外部API慢设置超时,超时后将错误信息返回模型

八、与《大模型应用开发极简入门》第2.8/2.9节的对应

本书第2章「其他OpenAI API和功能」中,Function Calling 被列为工具调用、外部 API 集成的核心能力(第2版新增)。本节与之一一对应:调用流程对应「模型决定是否调用外部函数、将结果纳入生成」;完整实现代码对应书中代码模板中的 Function Calling 示例(如 get_weather);关键参数、多函数、循环调用对应「工具调用、外部 API 集成」的落地细节。第5章 LangChain Agent、第6章智能客服等都会依赖 Function Calling,本节是后续 Agent 与工具集成的基础。


九、函数描述的编写技巧

9.1 description 要清晰

模型的「是否调用、传什么参数」主要依赖 descriptionparameters 中的描述。description 应一句话说明「在什么情况下用这个函数」「输入是什么、输出是什么」,便于模型在用户意图与函数之间正确匹配。

9.2 parameters 的 required 与类型

required 列出必填参数;properties 中可为每个参数写 description,帮助模型填对参数。类型使用 JSON Schema(string、integer、boolean、array、object),避免模型传错类型。

9.3 避免函数过多

函数列表过长会占用上下文并增加模型「选错」的概率。一般 5–10 个核心工具即可;若工具很多,可分组或通过 Router 先选类别再暴露子集。


十、安全与权限

10.1 执行前校验

在真正执行被调用的函数前,应对参数做校验(如城市名白名单、数值范围),避免模型因理解偏差传入危险参数(如 SQL 注入、命令执行)。

10.2 权限边界

Function Calling 可调用内部 API、数据库,需遵循最小权限原则:仅暴露业务必需的能力,且对敏感操作做二次确认或权限检查。书中 2.9 小结中的「API 核心参数、调用模板、常见问题速查」在本节以参数说明、完整代码与常见问题表的形式呈现,便于快速开发与排查。新项目若需接入天气、数据库、计算器等能力,优先采用本节模式即可与后续第 5 章 Agent、第 6 章智能客服无缝衔接。


十一、小结

掌握 Function Calling,即可将 GPT 与业务 API、数据库、计算器无缝集成,为构建 Agent、智能客服、自动化工具奠定基础。下一章将介绍 LLM 应用架构与安全实践。


下一节预告:第三章 LLM应用架构设计与安全实践