Function Calling
Function Calling(函数调用)是大语言模型的一项强大功能,允许模型根据用户输入自动调用预定义的函数,从而实现与外部系统、API 和工具的集成。
概述
Function Calling 使模型能够:
- 理解何时需要调用函数
- 提取函数所需的参数
- 生成结构化的函数调用
- 处理函数返回结果
工作原理
- 函数定义:定义可用的函数及其参数
- 意图识别:模型判断是否需要调用函数
- 参数提取:从用户输入中提取函数参数
- 函数执行:执行函数调用
- 结果处理:模型处理函数返回结果并生成回复
基本用法
定义函数
python
import openai
import json
client = openai.OpenAI(
api_key="your_api_key",
base_url="https://realmrouter.cn/v1"
)
# 定义函数
functions = [
{
"name": "get_weather",
"description": "获取指定城市的天气信息",
"parameters": {
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "城市名称"
},
"unit": {
"type": "string",
"enum": ["celsius", "fahrenheit"],
"description": "温度单位"
}
},
"required": ["city"]
}
}
]基本函数调用
python
response = client.chat.completions.create(
model="gpt-4",
messages=[
{
"role": "user",
"content": "北京今天天气怎么样?"
}
],
functions=functions,
function_call="auto"
)
# 检查是否需要调用函数
if response.choices[0].message.function_call:
function_call = response.choices[0].message.function_call
function_name = function_call.name
function_args = json.loads(function_call.arguments)
print(f"调用函数: {function_name}")
print(f"参数: {function_args}")
# 执行函数(这里用模拟函数)
if function_name == "get_weather":
result = get_weather(function_args["city"], function_args.get("unit", "celsius"))
# 将函数结果返回给模型
second_response = client.chat.completions.create(
model="gpt-4",
messages=[
{"role": "user", "content": "北京今天天气怎么样?"},
response.choices[0].message, # 模型的函数调用消息
{
"role": "function",
"name": function_name,
"content": json.dumps(result)
}
]
)
print(second_response.choices[0].message.content)实际函数实现
python
def get_weather(city, unit="celsius"):
"""模拟天气API调用"""
# 这里应该是实际的API调用
weather_data = {
"北京": {"temp": 25, "condition": "晴朗", "humidity": 60},
"上海": {"temp": 28, "condition": "多云", "humidity": 70},
"广州": {"temp": 32, "condition": "阴天", "humidity": 80}
}
if city in weather_data:
data = weather_data[city]
if unit == "fahrenheit":
data["temp"] = data["temp"] * 9/5 + 32
return {
"city": city,
"temperature": data["temp"],
"unit": unit,
"condition": data["condition"],
"humidity": data["humidity"]
}
else:
return {"error": "城市未找到"}高级功能
多函数调用
python
functions = [
{
"name": "get_weather",
"description": "获取天气信息",
"parameters": {
"type": "object",
"properties": {
"city": {"type": "string", "description": "城市名称"}
},
"required": ["city"]
}
},
{
"name": "get_stock_price",
"description": "获取股票价格",
"parameters": {
"type": "object",
"properties": {
"symbol": {"type": "string", "description": "股票代码"},
"exchange": {"type": "string", "description": "交易所"}
},
"required": ["symbol"]
}
},
{
"name": "send_email",
"description": "发送邮件",
"parameters": {
"type": "object",
"properties": {
"to": {"type": "string", "description": "收件人邮箱"},
"subject": {"type": "string", "description": "邮件主题"},
"body": {"type": "string", "description": "邮件内容"}
},
"required": ["to", "subject", "body"]
}
}
]
response = client.chat.completions.create(
model="gpt-4",
messages=[
{
"role": "user",
"content": "帮我查一下北京的天气,然后发送邮件给user@example.com告诉他天气情况"
}
],
functions=functions,
function_call="auto"
)流式函数调用
python
def stream_function_call(client, messages, functions):
stream = client.chat.completions.create(
model="gpt-4",
messages=messages,
functions=functions,
function_call="auto",
stream=True
)
function_call_data = {}
current_function = None
for chunk in stream:
delta = chunk.choices[0].delta
if delta.function_call:
if delta.function_call.name:
current_function = delta.function_call.name
function_call_data[current_function] = {"arguments": ""}
if delta.function_call.arguments:
function_call_data[current_function]["arguments"] += delta.function_call.arguments
elif delta.content:
print(delta.content, end="", flush=True)
return function_call_data
# 使用示例
messages = [{"role": "user", "content": "现在几点了?"}]
function_calls = stream_function_call(client, messages, functions)并行函数调用
python
response = client.chat.completions.create(
model="gpt-4",
messages=[
{
"role": "user",
"content": "同时查一下北京、上海、广州的天气"
}
],
functions=functions,
function_call="auto"
)
# 处理多个函数调用
if response.choices[0].message.function_call:
# 并行执行多个函数调用
import concurrent.futures
def execute_function_call(function_call):
function_name = function_call.name
function_args = json.loads(function_call.arguments)
if function_name == "get_weather":
return get_weather(function_args["city"])
# 其他函数...
# 如果有多个函数调用,可以并行执行
# 这里简化处理,实际可能需要解析多个函数调用实际应用场景
1. 数据库查询
python
functions = [
{
"name": "query_database",
"description": "查询数据库信息",
"parameters": {
"type": "object",
"properties": {
"table": {"type": "string", "description": "表名"},
"conditions": {"type": "object", "description": "查询条件"},
"limit": {"type": "integer", "description": "返回数量限制"}
},
"required": ["table"]
}
}
]
def query_database(table, conditions=None, limit=10):
"""实际数据库查询函数"""
# 实现数据库查询逻辑
pass2. API 集成
python
functions = [
{
"name": "create_calendar_event",
"description": "创建日历事件",
"parameters": {
"type": "object",
"properties": {
"title": {"type": "string", "description": "事件标题"},
"start_time": {"type": "string", "description": "开始时间"},
"end_time": {"type": "string", "description": "结束时间"},
"attendees": {"type": "array", "items": {"type": "string"}, "description": "参与者"}
},
"required": ["title", "start_time", "end_time"]
}
}
]
def create_calendar_event(title, start_time, end_time, attendees=None):
"""调用日历API创建事件"""
# 实现日历API调用
pass3. 文件操作
python
functions = [
{
"name": "read_file",
"description": "读取文件内容",
"parameters": {
"type": "object",
"properties": {
"filepath": {"type": "string", "description": "文件路径"},
"encoding": {"type": "string", "description": "文件编码"}
},
"required": ["filepath"]
}
},
{
"name": "write_file",
"description": "写入文件内容",
"parameters": {
"type": "object",
"properties": {
"filepath": {"type": "string", "description": "文件路径"},
"content": {"type": "string", "description": "文件内容"},
"encoding": {"type": "string", "description": "文件编码"}
},
"required": ["filepath", "content"]
}
}
]最佳实践
1. 函数设计原则
python
# 好的函数定义
good_function = {
"name": "search_products",
"description": "搜索产品信息,支持按类别、价格范围等条件筛选",
"parameters": {
"type": "object",
"properties": {
"category": {
"type": "string",
"description": "产品类别,如:电子产品、服装、食品等"
},
"min_price": {
"type": "number",
"description": "最低价格(可选)"
},
"max_price": {
"type": "number",
"description": "最高价格(可选)"
},
"sort_by": {
"type": "string",
"enum": ["price", "rating", "sales"],
"description": "排序方式"
}
},
"required": ["category"]
}
}
# 避免的函数定义
bad_function = {
"name": "do_something",
"description": "做一些事情",
"parameters": {
"type": "object",
"properties": {
"data": {"type": "object", "description": "数据"}
}
}
}2. 错误处理
python
def safe_function_call(client, messages, functions, max_retries=3):
for attempt in range(max_retries):
try:
response = client.chat.completions.create(
model="gpt-4",
messages=messages,
functions=functions,
function_call="auto"
)
if response.choices[0].message.function_call:
function_call = response.choices[0].message.function_call
function_name = function_call.name
function_args = json.loads(function_call.arguments)
# 验证参数
if not validate_function_args(function_name, function_args):
raise ValueError(f"无效的函数参数: {function_args}")
# 执行函数
result = execute_function(function_name, function_args)
return {
"success": True,
"result": result,
"function_call": function_call
}
else:
return {
"success": True,
"content": response.choices[0].message.content
}
except Exception as e:
if attempt < max_retries - 1:
time.sleep(2 ** attempt)
continue
else:
return {
"success": False,
"error": str(e)
}3. 性能优化
python
# 缓存函数结果
from functools import lru_cache
@lru_cache(maxsize=100)
def cached_get_weather(city, unit="celsius"):
"""带缓存的天气查询"""
return get_weather(city, unit)
# 批量函数调用
def batch_function_calls(calls):
"""批量执行函数调用"""
with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor:
futures = []
for call in calls:
future = executor.submit(execute_function, call["name"], call["args"])
futures.append(future)
results = []
for future in concurrent.futures.as_completed(futures):
try:
result = future.result()
results.append(result)
except Exception as e:
results.append({"error": str(e)})
return results限制和注意事项
- 函数数量限制:单次请求中定义的函数数量有限制
- 参数复杂度:过于复杂的参数结构可能影响识别准确率
- 执行时间:函数执行时间会影响整体响应时间
- 安全性:确保函数调用的安全性,避免执行恶意代码
- 错误处理:妥善处理函数执行失败的情况
调试和测试
python
def test_function_calling():
"""测试函数调用功能"""
test_cases = [
{
"input": "北京今天天气怎么样?",
"expected_function": "get_weather",
"expected_args": {"city": "北京"}
},
{
"input": "帮我查一下AAPL的股价",
"expected_function": "get_stock_price",
"expected_args": {"symbol": "AAPL"}
}
]
for case in test_cases:
response = client.chat.completions.create(
model="gpt-4",
messages=[{"role": "user", "content": case["input"]}],
functions=functions,
function_call="auto"
)
if response.choices[0].message.function_call:
function_call = response.choices[0].message.function_call
assert function_call.name == case["expected_function"]
# 更多断言...
print(f"测试通过: {case['input']}")
# 运行测试
test_function_calling()