构建具备工具调用能力的 AI Agent:Function Calling 实战指南

## 背景介绍

大语言模型(LLM)现在能说会写,但它们有个致命缺陷:知识会过期,而且只能”动嘴”不能”动手”。你想让它查个天气、执行个操作?门都没有。

Function Calling(函数调用)技术就是为了解决这个痛点。它让 AI 能够主动调用外部函数,获取实时数据、执行特定操作。换句话说,AI 不再只是个聊天机器,而变成了能真正干活的智能代理(Agent)。

这篇文章手把手教你从零构建一个具备工具调用能力的 AI Agent。

## 问题描述

传统 AI 应用开发有几个绕不开的坑:

**第一,知识过时。** LLM 的训练数据有截止日期,问它今天天气怎么样、十有八九答不上来。

**第二,无法执行操作。** AI 只能给建议,真正让它查数据库、调API、做计算?抱歉,做不到。

**第三,上下文缺失。** 企业数据、用户个人信息,这些 AI 根本访问不了。

**第四,幻觉问题。** 大模型有时候会一本正经地胡说八道,需要外部工具来验证。

Function Calling 怎么解决?核心思路很简单:让模型自己判断什么时候该调用工具、传什么参数、拿到结果怎么用。这样 AI 就能:

– 查询天气、股票、新闻
– 操作数据库、执行SQL
– 调用第三方API:日历、邮件、CRM
– 执行代码、做数学计算

## 详细步骤

### 第一步:装依赖

“`bash
pip install openai python-dotenv
“`

建个 `.env` 文件存 API 密钥:

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

### 第二步:写工具函数

工具函数需要三样东西:名字、参数说明(JSON Schema格式)、功能描述。

“`python
from datetime import datetime
import json

# 天气查询工具
def get_weather(location: str, unit: str = “celsius”) -> dict:
“””
查询指定位置的天气信息

参数:
location: 城市名称,如 “北京”、”Shanghai”
unit: 温度单位,”celsius” 或 “fahrenheit”

返回:
包含天气状况、温度、湿度等信息的字典
“””
# 模拟天气数据(实际项目中应调用真实天气 API)
weather_data = {
“北京”: {“temp”: 22, “condition”: “晴”, “humidity”: 45},
“上海”: {“temp”: 25, “condition”: “多云”, “humidity”: 60},
“深圳”: {“temp”: 28, “condition”: “雷阵雨”, “humidity”: 80}
}

data = weather_data.get(location, {“temp”: 20, “condition”: “未知”, “humidity”: 50})
return {
“location”: location,
“temperature”: data[“temp”],
“unit”: unit,
“condition”: data[“condition”],
“humidity”: data[“humidity”],
“timestamp”: datetime.now().isoformat()
}

# 计算器工具
def calculator(expression: str) -> dict:
“””
执行数学计算

参数:
expression: 数学表达式,如 “2+2″、”sqrt(16)”、”sin(3.14)”

返回:
计算结果
“””
try:
# 安全计算:仅支持基本运算
allowed_chars = set(‘0123456789+-*/.() ‘)
if all(c in allowed_chars for c in expression):
result = eval(expression)
return {“expression”: expression, “result”: result, “success”: True}
else:
return {“expression”: expression, “result”: “不支持的字符”, “success”: False}
except Exception as e:
return {“expression”: expression, “result”: str(e), “success”: False}
“`

### 第三步:配置 Function Calling

把工具函数注册到 OpenAI:

“`python
import openai
from dotenv import load_dotenv

load_dotenv()

# 可用工具列表
tools = [
{
“type”: “function”,
“function”: {
“name”: “get_weather”,
“description”: “查询指定城市的天气信息,用户问天气、穿衣建议或出行计划时使用”,
“parameters”: {
“type”: “object”,
“properties”: {
“location”: {
“type”: “string”,
“description”: “城市名称,如 ‘北京’、’上海’、’Seattle'”
},
“unit”: {
“type”: “string”,
“enum”: [“celsius”, “fahrenheit”],
“description”: “温度单位,默认为 celsius”
}
},
“required”: [“location”]
}
}
},
{
“type”: “function”,
“function”: {
“name”: “calculator”,
“description”: “执行数学计算,适合计算问题、数值转换”,
“parameters”: {
“type”: “object”,
“properties”: {
“expression”: {
“type”: “string”,
“description”: “数学表达式,如 ‘2+2’、’15*7’、’sqrt(144)'”
}
},
“required”: [“expression”]
}
}
}
]
“`

### 第四步:Agent 核心逻辑

核心是两步走:先问模型要不要调函数,拿到结果后再让它生成回复。

“`python
class FunctionCallAgent:
def __init__(self, model=”gpt-4o”):
self.client = openai.OpenAI()
self.model = model
self.tools = tools
self.available_functions = {
“get_weather”: get_weather,
“calculator”: calculator
}
self.conversation_history = []

def chat(self, user_message):
# 用户消息进历史
self.conversation_history.append({
“role”: “user”,
“content”: user_message
})

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

assistant_message = response.choices[0].message
self.conversation_history.append({
“role”: “assistant”,
“content”: assistant_message.content,
“tool_calls”: assistant_message.tool_calls
})

# 有函数调用?
if assistant_message.tool_calls:
# 执行所有函数
for tool_call in assistant_message.tool_calls:
function_name = tool_call.function.name
function_args = json.loads(tool_call.function.arguments)

if function_name in self.available_functions:
function_result = self.available_functions[function_name](
**function_args
)

# 函数结果进对话
self.conversation_history.append({
“role”: “tool”,
“tool_call_id”: tool_call.id,
“content”: json.dumps(function_result)
})

# 第二步:根据函数结果生成回复
final_response = self.client.chat.completions.create(
model=self.model,
messages=self.conversation_history
)

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

return final_message

return assistant_message.content

def reset(self):
“””清空对话历史”””
self.conversation_history = []
“`

## 运行效果

上代码测试:

“`python
agent = FunctionCallAgent()

# 测试1:查天气
print(“=” * 50)
print(“测试 1:天气查询”)
print(“=” * 50)
response1 = agent.chat(“北京今天天气怎么样?”)
print(f”用户:北京今天天气怎么样?”)
print(f”AI:{response1}\n”)

# 测试2:做计算
print(“=” * 50)
print(“测试 2:数学计算”)
print(“=” * 50)
response2 = agent.chat(“125 * 17 等于多少?”)
print(f”用户:125 * 17 等于多少?”)
print(f”AI:{response2}\n”)

# 测试3:多函数调用
print(“=” * 50)
print(“测试 3:多函数调用”)
print(“=” * 50)
agent.reset()
response3 = agent.chat(“北京和深圳的温度分别是多少?差几度?”)
print(f”用户:北京和深圳的温度分别是多少?差几度?”)
print(f”AI:{response3}”)
“`

**输出:**

“`
==================================================
测试 1:天气查询
==================================================
用户:北京今天天气怎么样?
AI:北京今天晴,气温22度,湿度45%。穿衣方面,长袖配薄外套差不多。

==================================================
测试 2:数学计算
==================================================
用户:125 * 17 等于多少?
AI:2125。

==================================================
测试 3:多函数调用
==================================================
用户:北京和深圳的温度分别是多少?差几度?
AI:北京22度,深圳28度,差6度。深圳更热。
“`

## 总结

做个简单回顾:

技术层面,有几个关键点:

**工具描述很重要。** 函数说明写清楚了,模型才知道什么时候该调用。

**参数定义要详细。** 类型、枚举值、描述都有了,模型才不会传错参数。

**两步走流程。** 先让模型决定要不要调函数,拿到结果后再生成回复。

**注意安全。** 生产环境用沙箱执行,别让AI随便搞破坏。

应用层面,这套东西能玩出很多花样:

– 个人助手:接管日历、邮件、待办
– 数据分析:连数据库、跑SQL
– 电商客服:查订单、看库存
– 编程助手:执行代码、调试程序
– 智能家居:控制IoT设备

Function Calling 是 AI Agent 的基础能力。学会这个,你就能做真正的智能应用了。

试试看?

暂无评论

发送评论 编辑评论


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