OpenAI Function Calling 构建 AI 助手完整指南

## 背景介绍

在人工智能快速发展的今天,大语言模型(LLM)已经具备了强的自然语言理解和生成能力。然而,单纯依靠语言模型本身,我们很难让它执行具体的操作任务,比如查询数据库、调用外部API、发送邮件或者操作文件系统。这就是 Function Calling(函数调用)技术出现的背景。

Function Calling 是 OpenAI 在 2023 年推出的重要功能,它允许 GPT 模型在生成回复的过程中,根据用户需求主动调用预定义的函数,并结合函数返回的结果来生成最终答案。这种机制改变了 AI 应用的开发范式,让我们能够构建真正有用的 AI 助手,而不仅仅是会话机器人。

想象一下,用户说”帮我查一下北京今天的天气”,传统的做法是我们需要在程序里预先判断用户意图,然后手动调用天气 API。但有了 Function Calling,模型会自动识别需要调用天气查询函数,获取返回的天气数据后,再用自然语言组织成用户能看懂的回复。整个过程对开发者来说几乎是透明的。

这篇文章将带你从零开始,构建一个完整的 AI 助手,能够调用多种工具函数来完成复杂任务。我们会涵盖环境配置、函数定义、调用、结果处理等完整流程,并提供可以直接运行的 Python 代码示例。

## 问题描述

在实际开发中,我们经常遇到这样的困境:用户想要的是执行某个具体操作,而不仅仅是获取信息。比如用户说”帮我订一张下周二的机票”或者”把这份报告发到市场部邮箱”,这类需求要求 AI 能够与外部系统进行交互。

传统的解决方案是采用意图识别加规则匹配的方式:先训练一个意图分类模型,判断用户想要什么操作,然后根据意图调用对应的 API。这种方式有几个明显的缺点。意图分类模型需要大量标注数据来训练,标注和训练成本都很高。规则方式很难处理模糊或多意图的情况,用户说”帮我看看这个月的销售数据,再发给老板”这样包含多个操作的需求,规则系统很难优雅地处理。最关键是,每次增加新的功能,都需要重新训练模型或者编写大量规则代码,扩展性很差。

Function Calling 的出现解决了这些问题。它利用大语言模型强的理解能力,自动识别用户需求并选择合适的函数来调用。开发者只需要定义好函数签名和描述,模型就能理解函数的用途并在适当的时候触发调用。这种方式的扩展性也非常好,新增功能只需要定义新的函数即可,无需修改核心逻辑。

## 详细步骤

### 步骤一:环境准备

我们需要安装必要的 Python 包。创建一个新的 Python 项目,然后安装 OpenAI 的 Python SDK:

“`bash
pip install openai python-dotenv
“`

接下来,在项目根目录创建一个 `.env` 文件,配置你的 OpenAI API 密钥:

“`
OPENAI_API_KEY=sk-your-api-key-here
“`

为了更好地管理配置,我们创建一个 `config.py` 文件:

“`python
import os
from dotenv import load_dotenv

load_dotenv()

# OpenAI API 配置
OPENAI_API_KEY = os.getenv(“OPENAI_API_KEY”)
MODEL_NAME = “gpt-4o” # 使用 GPT-4o 模型,支持最新的 Function Calling 特性
“`

### 步骤二:定义工具函数

Function Calling 的核心是定义工具函数。我们需要使用 JSON Schema 格式来描述函数的参数,这样模型才能理解每个函数的用途和参数要求。

下面定义几个常用的工具函数:天气查询、计算器和日历查询:

“`python
tools = [
{
“type”: “function”,
“function”: {
“name”: “get_weather”,
“description”: “获取指定城市的天气信息”,
“parameters”: {
“type”: “object”,
“properties”: {
“city”: {
“type”: “string”,
“description”: “城市名称,如北京、上海、东京”
},
“unit”: {
“type”: “string”,
“enum”: [“celsius”, “fahrenheit”],
“description”: “温度单位,摄氏度或华氏度”,
“default”: “celsius”
}
},
“required”: [“city”]
}
}
},
{
“type”: “function”,
“function”: {
“name”: “calculate”,
“description”: “执行数学计算”,
“parameters”: {
“type”: “object”,
“properties”: {
“expression”: {
“type”: “string”,
“description”: “数学表达式,如 2+2、sqrt(16)、5**3”
}
},
“required”: [“expression”]
}
}
},
{
“type”: “function”,
“function”: {
“name”: “get_calendar_events”,
“description”: “获取日历事件”,
“parameters”: {
“type”: “object”,
“properties”: {
“date”: {
“type”: “string”,
“description”: “日期,格式为 YYYY-MM-DD”
}
},
“required”: [“date”]
}
}
}
]
“`

注意,每个函数的 description 非常重要,模型会根据这个描述来决定是否调用该函数。描述应该清晰说明函数的功能和参数含义。

### 步骤三:实现函数执行逻辑

定义了函数之后,我们需要实现真正的执行逻辑。创建一个 `functions.py` 文件:

“`python
import json
import math
from datetime import datetime

def get_weather(city: str, unit: str = “celsius”) -> str:
“””获取天气信息(模拟实现)”””
# 实际应用中,这里应该调用真实的天气 API
weather_data = {
“北京”: {“condition”: “晴”, “temperature”: 22},
“上海”: {“condition”: “多云”, “temperature”: 25},
“东京”: {“condition”: “小雨”, “temperature”: 18},
“纽约”: {“condition”: “晴”, “temperature”: 28}
}

city_weather = weather_data.get(city, {“condition”: “未知”, “temperature”: 0})
temp = city_weather[“temperature”]

if unit == “fahrenheit”:
temp = temp * 9/5 + 32
unit_str = “°F”
else:
unit_str = “°C”

return f”{city}今天天气{city_weather[‘condition’]},温度{temp}{unit_str}”

def calculate(expression: str) -> str:
“””执行数学计算”””
try:
# 安全计算:只允许基本的数学运算
allowed_names = {
“sqrt”: math.sqrt,
“sin”: math.sin,
“cos”: math.cos,
“tan”: math.tan,
“log”: math.log,
“abs”: abs,
“pow”: pow,
“pi”: math.pi,
“e”: math.e
}

result = eval(expression, {“__builtins__”: {}}, allowed_names)
return f”计算结果:{expression} = {result}”
except Exception as e:
return f”计算错误:{str(e)}”

def get_calendar_events(date: str) -> str:
“””获取日历事件(模拟实现)”””
# 实际应用中,这里应该调用日历 API
events_db = {
“2026-04-18”: [“上午:团队周会”, “下午:项目评审”],
“2026-04-19”: [“全天:客户拜访”],
“2026-04-20″: []
}

events = events_db.get(date, [])
if not events:
return f”{date} 没有安排日程”

event_list = “\n”.join([f”- {event}” for event in events])
return f”{date} 的日程安排:\n{event_list}”

# 函数映射表
FUNCTIONS = {
“get_weather”: get_weather,
“calculate”: calculate,
“get_calendar_events”: get_calendar_events
}

def execute_function(function_name: str, arguments: dict) -> str:
“””执行函数调用”””
if function_name not in FUNCTIONS:
return f”错误:未找到函数 {function_name}”

func = FUNCTIONS[function_name]

try:
result = func(**arguments)
return result
except Exception as e:
return f”函数执行错误:{str(e)}”
“`

### 步骤四:构建助手核心逻辑

现在,我们要把所有部分组合在一起,构建一个能够自动处理函数调用的助手:

“`python
from openai import OpenAI
import json

client = OpenAI(api_key=OPENAI_API_KEY)

class FunctionCallingAgent:
def __init__(self, tools: list, functions: dict):
self.tools = tools
self.functions = functions
self.messages = []

# 系统提示词,定义助手的行为
self.system_prompt = “””你是一个有用的AI助手,可以帮助用户完成各种任务。
当用户的问题需要获取额外信息或执行操作时,你可以使用提供的工具函数。
请根据用户的需求,合理使用工具来完成任务。”””

self.messages.append({
“role”: “system”,
“content”: self.system_prompt
})

def chat(self, user_input: str) -> str:
“””处理用户输入并返回回复”””
# 添加用户消息
self.messages.append({
“role”: “user”,
“content”: user_input
})

# 第一次调用:让模型决定是否需要调用函数
response = client.chat.completions.create(
model=MODEL_NAME,
messages=self.messages,
tools=self.tools,
tool_choice=”auto”
)

assistant_message = response.choices[0].message
self.messages.append(assistant_message)

# 检查是否需要调用函数
if assistant_message.tool_calls:
# 依次执行所有函数调用
for tool_call in assistant_message.tool_calls:
function_name = tool_call.function.name
arguments = json.loads(tool_call.function.arguments)

print(f”\n[调用函数] {function_name}”)
print(f”[参数] {arguments}”)

# 执行函数
function_result = execute_function(function_name, arguments)
print(f”[结果] {function_result}\n”)

# 将函数结果添加到对话中
self.messages.append({
“role”: “tool”,
“tool_call_id”: tool_call.id,
“content”: function_result
})

# 第二次调用:基于函数结果生成最终回复
final_response = client.chat.completions.create(
model=MODEL_NAME,
messages=self.messages
)

final_message = final_response.choices[0].message.content
self.messages.append({
“role”: “assistant”,
“content”: final_message
})

return final_message
else:
# 无需调用函数,直接返回回复
return assistant_message.content

def reset(self):
“””重置对话历史”””
self.messages = [{
“role”: “system”,
“content”: self.system_prompt
}]
“`

### 步骤五:运行助手

创建主程序来运行我们的助手:

“`python
def main():
# 初始化助手
agent = FunctionCallingAgent(tools=tools, functions=FUNCTIONS)

# 测试用例
test_cases = [
“北京今天天气怎么样?”,
“帮我计算一下 2 的 10 次方是多少”,
“今天有什么日程安排吗?”,
“帮我查一下上海的天气,然后用中文告诉我”,
“2026-04-20有会议吗?”
]

for i, test_case in enumerate(test_cases, 1):
print(f”\n{‘=’*50}”)
print(f”[测试 {i}] 用户:{test_case}”)
print(“=”*50)

response = agent.chat(test_case)
print(f”[回复] {response}”)

# 每个测试后重置对话
agent.reset()

if __name__ == “__main__”:
main()
“`

## 运行结果

运行上述代码,你会看到类似以下的输出:

“`
==================================================
[测试 1] 用户:北京今天天气怎么样?
==================================================

[调用函数] get_weather
[参数] {‘city’: ‘北京’, ‘unit’: ‘celsius’}
[结果] 北京今天天气晴,温度22°C

[回复] 北京今天天气晴朗,气温22°C。非常适合外出活动,记得涂抹防晒霜哦!
==================================================
[测试 2] 用户:帮我计算一下 2 的 10 次方是多少
==================================================

[调用函数] calculate
[参数] {‘expression’: ‘2**10’}
[结果] 计算结果:2**10 = 1024

[回复] 2 的 10 次方等于 1024。这是一个很常用的数字,1024 字节正好是 1KB。
==================================================
[测试 3] 用户:今天有什么日程安排吗?
==================================================

[调用函数] get_calendar_events
[参数] {‘date’: ‘2026-04-18’}
[结果] 2026-04-18 的日程安排:
– 上午:团队周会
– 下午:项目评审

[回复] 今天是4月18日,你的日程安排如下:
– 上午:团队周会
– 下午:项目评审

看起来今天会比较忙碌,记得提前准备周会材料!
“`

从运行结果可以看出,助手能够准确理解用户意图,自动选择合适的函数进行调用,并在获取结果后生成自然流畅的回复。整个过程完全自动化,开发者无需编写意图识别逻辑。

## 总结

通过本文的学习,你已经掌握了如何使用 OpenAI 的 Function Calling 功能来构建 AI 助手。我们详细介绍了从环境配置、函数定义、函数执行到助手构建的完整流程,并提供了可以直接运行的代码示例。

Function Calling 技术的核心优势在于它将大语言模型的理解能力与外部系统的执行能力很好结合。开发者不需要训练复杂的意图识别模型,只需要定义好函数签名和描述,模型就能自动完成剩余的工作。这种开发范式大大降低了 AI 应用的开发门槛,提高了开发效率。

在实际应用中,你可以根据业务需求定义各种类型的函数,比如数据库查询、API 调用、文件操作、邮件发送等。函数的数量和复杂度可以根据实际需求灵活调整,助手能够自动处理多函数调用的场景。

Function Calling 也有一些需要注意的点。首先是函数描述的质量,清晰准确的函数描述能够帮助模型更好地理解函数用途。其次是函数执行的安全性,实际应用中要对函数调用进行权限控制和错误处理。最后是成本控制,每次函数调用都会产生额外的 token 消耗,需要在产品设计中加以考虑。

希望这篇文章能够帮助你在 AI 应用开发中更好地利用 Function Calling 技术。如果你对此感兴趣,可以进一步探索如何结合向量数据库实现 RAG(检索增强生成),或者构建多助手协作系统,这些都是当前 AI 开发领域的热门方向。

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇