概述

OpenAI 在 6 月 13 日更新引入了一项令人兴奋的新功能叫Function calling

什么是函数调用 Function calling?

在 Function calling 出现前,大模型存在诸多短板。一方面,实时信息获取能力不足,像天气、股票价格这类动态数据难以掌握,知识更新也不够及时,依赖预训练和增量训练,新信息难以及时融入;另一方面,与外部工具协同性差,难以调用专业工具执行复杂任务,对于涉及多步骤和多模块协作的任务以及精确指令,完成效果欠佳 ,这些限制了大模型在复杂场景下的应用。

Function calling 允许大模型 LLM 在生成响应时,能够识别并执行特定的函数或 API 调用,以获取额外的信息或调用工具执行特定的任务。

工作原理

Function calling 的工作原理是让大模型能够识别需要调用外部工具或函数来处理任务,并将相关信息传递给外部工具,待工具处理完成后再将结果返回给大模型进行整合和输出。

de65c5d5-88cb-4523-ba88-d7357ecb5450.webp

以查询天气为例,假设用户输入“广州的天气怎么样?”。仅靠 ChatGPT API 本身是无法直接回答天气问题的。但借助 Function calling,我们可以声明一个以地名为参数的函数,返回该地区的天气情况。

使用 Function calling 实现天气查询

为了使用 Function calling 功能,我们需要准备一个 Node.js 项目,并安装 OpenAI 提供的 API 库。以下是具体步骤:

创建 package.json 文件

在项目根目录下创建一个 package.json 文件,内容如下:

{
"dependencies": {
"openai": "3.3.0"
}
}

安装依赖

运行以下命令来安装所需的库:

npm install

安装完成之后,我们将编写一个 Node.js 脚本,利用 Function calling 查询天气。以下是完整的代码示例:

function-calling.js 文件内容:

const OpenAI = require("openai");
const axios = require("axios"); // 用于发送 HTTP 请求
const OPENAI_API_KEY = "xxx";
// 从环境变量 OPENAI_API_KEY 中读取 API 密钥并进行设置
const openai = new OpenAI({
baseURL: "https://api.chatanywhere.tech/v1",
apiKey: OPENAI_API_KEY,
});
// 以 JSON Schema 格式定义 Function calling 的目标函数
const functions = [
{
name: "get_current_weather",
description: "获取指定地名的天气",
parameters: {
type: "object",
properties: {
location: {
type: "string",
description: "要获取天气的地名",
},
},
required: ["location"],
},
},
];
const GAO_DE_API_KEY = "xxx";
// https://restapi.amap.com/v3/weather/weatherInfo?key=【你的_API_KEY】8&city=110000&extensions=all
// 定义 Function calling 目标函数的主体
const functions_body = {
// 定义一个获取指定地名天气的函数
async get_current_weather(args) {
const { location } = JSON.parse(args);
try {
// 先通过地理编码接口获取城市编码
const geocodeResponse = await axios.get(
`https://restapi.amap.com/v3/geocode/geo?address=${encodeURIComponent(location)}&key=${GAO_DE_API_KEY}`
);
if (geocodeResponse.data.status === "1") {
const adcode = geocodeResponse.data.infocode;
// 使用城市编码获取天气信息
const weatherResponse = await axios.get(
`https://restapi.amap.com/v3/weather/weatherInfo?city=${adcode}&key=${GAO_DE_API_KEY}&extensions=base`
);
if (weatherResponse.data.status === "1" && weatherResponse.data.lives.length > 0) {
const weather = weatherResponse.data.lives[0].weather;
return JSON.stringify({ location, weather });
}
}
return JSON.stringify({ location, weather: "无法获取天气信息" });
} catch (error) {
return JSON.stringify({ location, weather: "获取天气信息时出错" });
}
},
};
// 定义调用 API 的函数
async function requestAPI(messages) {
console.log(messages);
const response = await openai.chat.completions.create({
model: "gpt-3.5-turbo",
messages,
functions,
});
console.log(response.choices[0].message);
const message = response.choices[0].message;
messages.push(message);
// 如果是 Function calling,将函数的执行结果添加到消息中并再次调用 API
if (message.function_call) {
const name = message.function_call.name;
const content = await functions_body[name](message.function_call.arguments); // 注意这里是异步调用
messages.push({ role: "function", name, content });
await requestAPI(messages);
}
}
// 定义主函数
async function main() {
// 从命令行参数中获取提示
const prompt = process.argv[2];
// 调用 API
const messages = [{ role: "user", content: prompt }];
await requestAPI(messages);
// 显示消息
console.log(messages[messages.length - 1].content);
}
// 执行主函数
main();

运行程序

完成代码编写后,可以通过命令行运行程序并测试其功能。以下是一些测试用例及其结果:

$ node function-calling.js '请告诉我广州的天气。'

可以看到输出结果为:

function-calling-result

使用 Function calling 时的注意事项

虽然 Function calling 功能强大,但在使用时需要注意一些安全问题。由于 Function calling 从用户输入的提示中提取信息,这些信息本质上属于系统外部的输入。如果不加以处理,可能会引入安全漏洞。

例如,如果用户输入类似“请告诉我 <script> 的天气。”的内容,Function calling 会提取地名为“<script>”。如果将这个值直接用于 Web 应用程序或数据库处理,可能会导致 XSS 攻击或 SQL 注入等安全问题。因此,在实际应用中,必须对提取的信息进行适当的处理,如 HTML 编码或使用预处理语句。


总结

Function calling 是 OpenAI API 的一项强大功能,它可以根据用户输入的提示提取关键信息,并调用相应的函数来完成复杂的任务。通过本文的示例,我们展示了如何利用 Function calling 查询天气。然而,需要注意的是,使用 Function calling 时必须考虑安全性,避免引入已知的漏洞。

在实际开发中,开发者可以充分发挥想象力,利用 Function calling 实现更多有趣的功能,例如安排会议、查询股票信息等。希望本文能帮助你更好地理解和使用 Function calling 功能。