深入解析Prompt-Engineering-Guide中的OpenAI函数调用技术
前言
在现代AI应用开发中,将大语言模型(LLM)与外部工具和API集成是一个关键能力。OpenAI的函数调用(Function Calling)功能为这一需求提供了优雅的解决方案。本文将基于Prompt-Engineering-Guide项目中的函数调用示例,深入剖析这一技术的实现原理和应用场景。
函数调用基础概念
函数调用允许大语言模型智能地决定何时以及如何调用开发者定义的外部函数。这一功能的核心价值在于:
- 将自然语言转换为结构化API调用
- 实现LLM与外部系统的无缝集成
- 构建更加强大和实用的AI应用
环境准备与基础设置
首先需要配置OpenAI API环境:
import os
import openai
import json
from dotenv import load_dotenv
load_dotenv()
openai.api_key = os.environ['OPENAI_API_KEY']
定义一个通用的获取模型响应的函数:
def get_completion(messages, model="gpt-3.5-turbo-1106", temperature=0,
max_tokens=300, tools=None, tool_choice=None):
response = openai.chat.completions.create(
model=model,
messages=messages,
temperature=temperature,
max_tokens=max_tokens,
tools=tools,
tool_choice=tool_choice
)
return response.choices[0].message
定义示例函数
我们以一个获取天气的函数为例:
def get_current_weather(location, unit="fahrenheit"):
"""获取指定位置的当前天气"""
weather = {
"location": location,
"temperature": "50",
"unit": unit,
}
return json.dumps(weather)
函数定义与描述
关键点在于如何向模型描述这个函数:
tools = [
{
"type": "function",
"function": {
"name": "get_current_weather",
"description": "获取指定位置的当前天气",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "城市和州,例如:San Francisco, CA",
},
"unit": {
"type": "string",
"enum": ["celsius", "fahrenheit"]},
},
"required": ["location"],
},
},
}
]
注意:函数描述(description)和参数描述非常重要,它们直接决定了模型如何理解和使用这个函数。
函数调用流程
- 用户发起天气查询:
messages = [
{
"role": "user",
"content": "伦敦的天气怎么样?"
}
]
- 模型决定调用函数:
response = get_completion(messages, tools=tools)
print(response)
- 解析函数参数并执行:
args = json.loads(response.tool_calls[0].function.arguments)
weather_data = get_current_weather(**args)
控制函数调用行为
OpenAI API提供了多种控制函数调用的方式:
-
自动模式(默认):模型自行决定是否调用函数
get_completion(messages, tools=tools, tool_choice="auto")
-
强制不调用:确保模型不使用任何函数
get_completion(messages, tools=tools, tool_choice="none")
-
强制调用特定函数:确保模型调用指定函数
get_completion(messages, tools=tools, tool_choice={"type": "function", "function": {"name": "get_current_weather"}})
并行函数调用
OpenAI API支持在单次交互中调用多个函数:
messages = [
{
"role": "user",
"content": "伦敦和Belmopan未来几天的天气如何?"
}
]
response = get_completion(messages, tools=tools)
模型会同时为两个地点生成函数调用请求。
构建完整对话流程
一个完整的函数调用对话流程包括以下步骤:
- 用户提问
- 模型决定调用函数
- 执行函数获取结果
- 将结果返回给模型
- 模型生成最终响应
实现代码示例:
# 1. 用户提问
messages = [{"role": "user", "content": "波士顿的天气怎么样?"}]
# 2. 模型决定调用函数
assistant_message = get_completion(messages, tools=tools, tool_choice="auto")
assistant_message = json.loads(assistant_message.model_dump_json())
# 3. 执行函数获取结果
weather = get_current_weather(
json.loads(assistant_message["tool_calls"][0]["function"]["arguments"])
)
# 4. 将结果返回给模型
messages.append({
"role": "tool",
"tool_call_id": assistant_message["tool_calls"][0]["id"],
"name": assistant_message["tool_calls"][0]["function"]["name"],
"content": weather
})
# 5. 模型生成最终响应
final_response = get_completion(messages, tools=tools)
print(final_response.content)
最佳实践与注意事项
- 清晰的函数描述:确保函数和参数的描述准确清晰
- 错误处理:考虑函数调用失败的情况
- 安全性:验证和清理函数输入
- 性能优化:避免不必要的函数调用
- 用户体验:设计自然的对话流程
结语
OpenAI的函数调用功能为构建强大的AI应用提供了重要基础。通过本文的讲解,您应该已经掌握了函数调用的核心概念和实现方法。在实际应用中,可以根据需求灵活组合这些技术,构建出更加智能和实用的AI系统。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考