在本教程中,你将构建一个利用 OpenAI 函数调用 ↗功能的项目,该功能适用于 OpenAI 最新的 Chat Completions API 模型。
函数调用功能允许 AI 模型根据输入智能决定何时调用函数,并以 JSON 格式响应以匹配函数签名。你将使用函数调用功能,让模型确定包含与用户消息相关信息的网站 URL,检索该网站的文本内容,最后返回由实时 Web 数据支撑的模型最终响应。
- 如何使用 OpenAI 的函数调用功能。
- 在 Cloudflare Worker 中集成 OpenAI API。
- 使用 Cheerio 获取和处理网站内容。
- 在 JavaScript 中处理 API 响应和函数调用。
- 使用 Wrangler 将 API 密钥存储为密钥(secret)。
所有教程都假设你已经完成了快速入门指南,该指南帮助你设置 Cloudflare Workers 账户、C3 ↗ 和 Wrangler。
在命令行中创建 Worker 项目:
npm create cloudflare@latest -- openai-function-calling-workersyarn create cloudflare openai-function-calling-workerspnpm create cloudflare@latest openai-function-calling-workers进行设置时,请选择以下选项:
- 对于 What would you like to start with?,选择
Hello World example。 - 对于 Which template would you like to use?,选择
Worker only。 - 对于 Which language do you want to use?,选择
JavaScript。 - 对于 Do you want to use git for version control?,选择
Yes。 - 对于 Do you want to deploy your application?,选择
No(部署前我们还会做一些修改)。
进入新的 openai-function-calling-workers Worker 项目:
cd openai-function-calling-workers在 openai-function-calling-workers 目录中,找到 src/index.js 文件。本教程的大部分配置都在此文件中进行。
你还需要 OpenAI 账户和 API 密钥。若尚未拥有,请创建新的 OpenAI 账户 ↗并创建 API 密钥 ↗以继续本教程。请妥善保存 API 密钥以便后续使用。
Worker 项目创建完成后,向 OpenAI 发起第一次请求。你将使用 OpenAI Node 库与 OpenAI API 交互。在本项目中,你还将使用 Cheerio 库处理网站的 HTML 内容。
npm i openai cheerioyarn add openai cheeriopnpm add openai cheeriobun add openai cheerio现在,在 index.js 中定义 Worker 的结构:
export default {
async fetch(request, env, ctx) {
// Initialize OpenAI API
// Handle incoming requests
return new Response("Hello World!");
},
};在 export default 上方,添加 openai 和 cheerio 的导入:
import OpenAI from "openai";
import * as cheerio from "cheerio";在 fetch 函数内,实例化 OpenAI 客户端:
async fetch(request, env, ctx) {
const openai = new OpenAI({
apiKey: env.OPENAI_API_KEY,
});
// Handle incoming requests
return new Response('Hello World!');
},使用 wrangler secret put 设置 OPENAI_API_KEY。此密钥的值是你在 OpenAI 仪表板中先前创建的 API 密钥:
npx wrangler secret put <OPENAI_API_KEY>对于本地开发,在 Worker 项目中创建新的 .dev.vars 文件并添加以下行。请将 OPENAI_API_KEY 替换为你自己的 OpenAI API 密钥:
OPENAI_API_KEY = "<YOUR_OPENAI_API_KEY>"现在,向 OpenAI Chat Completions API ↗ 发起请求:
export default {
async fetch(request, env, ctx) {
const openai = new OpenAI({
apiKey: env.OPENAI_API_KEY,
});
const url = new URL(request.url);
const message = url.searchParams.get("message");
const messages = [
{
role: "user",
content: message ? message : "What's in the news today?",
},
];
const tools = [
{
type: "function",
function: {
name: "read_website_content",
description: "Read the content on a given website",
parameters: {
type: "object",
properties: {
url: {
type: "string",
description: "The URL to the website to read",
},
},
required: ["url"],
},
},
},
];
const chatCompletion = await openai.chat.completions.create({
model: "gpt-4o-mini",
messages: messages,
tools: tools,
tool_choice: "auto",
});
const assistantMessage = chatCompletion.choices[0].message;
console.log(assistantMessage);
//Later you will continue handling the assistant's response here
return new Response(assistantMessage.content);
},
};查看传递给 OpenAI 的参数:
- model:你希望 OpenAI 用于此请求的模型。本例中使用
gpt-4o-mini。 - messages:包含对话中所有消息的数组。最初你提供用户消息,之后添加模型响应。用户消息的内容来自请求 URL 的
message查询参数,或默认的 "What's in the news today?"。 - tools:包含 AI 模型可用操作的数组。本例中只有一个工具
read_website_content,用于读取给定网站的内容。- name:函数名称。本例中为
read_website_content。 - description:简短描述,让模型了解函数用途。可选,但有助于模型选择工具。
- parameters:描述函数的 JSON Schema 对象。本例中请求包含必需属性
url的对象响应。
- name:函数名称。本例中为
- tool_choice:此参数技术上可选,因为默认值为
auto。表示 OpenAI 可以返回函数调用或普通消息响应。
现在需要定义 tools 数组中引用的 read_website_content 函数。read_website_content 函数获取给定 URL 的内容,并使用 cheerio 库从 <p> 标签中提取文本:
在 index.js 文件的 export default 块上方添加以下代码:
async function read_website_content(url) {
console.log("reading website content");
const response = await fetch(url);
const body = await response.text();
let cheerioBody = cheerio.load(body);
const resp = {
website_body: cheerioBody("p").text(),
url: url,
};
return JSON.stringify(resp);
}在此函数中,你接收 OpenAI 返回的 URL,使用 JavaScript 的 Fetch API ↗ 拉取网站内容并提取段落文本。接下来需要确定何时调用此函数。
接下来,需要处理 OpenAI API 的响应,检查是否包含函数调用。若存在函数调用,应在 Worker 中执行对应函数。注意 assistant 可能请求多次函数调用。
按如下方式修改 export default 块内的 fetch 方法:
// ... your previous code ...
if (assistantMessage.tool_calls) {
for (const toolCall of assistantMessage.tool_calls) {
if (toolCall.function.name === "read_website_content") {
const url = JSON.parse(toolCall.function.arguments).url;
const websiteContent = await read_website_content(url);
messages.push({
role: "tool",
tool_call_id: toolCall.id,
name: toolCall.function.name,
content: websiteContent,
});
}
}
const secondChatCompletion = await openai.chat.completions.create({
model: "gpt-4o-mini",
messages: messages,
});
return new Response(secondChatCompletion.choices[0].message.content);
} else {
// this is your existing return statement
return new Response(assistantMessage.content);
}通过检查 tool_calls 属性,判断 assistant 消息是否包含函数调用。由于 AI 模型默认可以调用多个函数,你需要循环处理所有可能的函数调用并将其添加到 messages 数组。每次 read_website_content 调用都会执行你先前定义的 read_website_content 函数,并将 OpenAI 生成的 URL 作为参数传递。 `
需要 secondChatCompletion 以提供由你从各函数调用检索到的数据支撑的响应。最后一步是部署 Worker。
运行 npx wrangler dev 测试代码,并在浏览器中打开提供的 URL。现在将显示 OpenAI 使用检索到的 Web 数据实时信息生成的响应。
要部署应用,运行 npx wrangler deploy 命令:
npx wrangler deploy现在可以在 <YOUR_WORKER>.<YOUR_SUBDOMAIN>.workers.dev 预览 Worker。访问此 URL 将显示 OpenAI 的响应。可选地,添加 message URL 参数以编写自定义消息:例如 https://<YOUR_WORKER>.<YOUR_SUBDOMAIN>.workers.dev/?message=What is the weather in NYC today?。
要继续使用 Workers 和 AI,请参阅如何将 LangChain 与 Cloudflare Workers 结合使用 ↗或如何使用 Cloudflare Workers 构建 ChatGPT 插件 ↗。
如有疑问、需要帮助或想分享你的项目,请加入 Cloudflare 开发者社区 Discord ↗,与其他开发者和 Cloudflare 团队交流。