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-0613、gpt-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",并包含name与content。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 要清晰
模型的「是否调用、传什么参数」主要依赖 description 与 parameters 中的描述。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应用架构设计与安全实践