このチュートリアルでは、OpenAI の最新 Chat Completions API モデルで使える OpenAI の function calling ↗ 機能を活用するプロジェクトを作ります。
function calling を使うと、AI モデルは入力に応じて関数を呼ぶべきかを判断し、関数のシグネチャに合わせた JSON で応答できます。function calling を使い、ユーザーのメッセージに関連する情報があるウェブサイトの URL をモデルに決めさせ、そのサイトのテキストを取得し、リアルタイムの Web データを踏まえた最終応答を返す流れを作ります。
- OpenAI の function calling の使い方
- Cloudflare Worker への OpenAI API の組み込み
- Cheerio を使ったウェブサイト本文の取得と処理
- JavaScript での API 応答と function call の扱い
- Wrangler で API キーを secrets として保存する方法
すべてのチュートリアルは、Cloudflare Workers アカウント、C3 ↗、および Wrangler のセットアップが完了している前提です。セットアップは Get started ガイド で行います。
コマンドラインで 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 API とのやり取りには OpenAI の Node ライブラリを使います。このプロジェクトでは、ウェブサイトの HTML を処理するために Cheerio ライブラリも使います。
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 を追加します。
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 を設定します。この secret の値は、先ほど 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です。function call か通常のメッセージ応答のどちらも、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 の応答を処理し、function call が含まれているかを確認します。function call がある場合は、Worker 内の対応する関数を実行します。アシスタントは複数の function call を要求する場合があります。
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);
}アシスタントメッセージに function call があるかは、tool_calls プロパティで確認します。AI モデルはデフォルトで複数の関数を呼べるため、想定される function call をループして messages 配列に追加します。各 read_website_content の呼び出しは、先ほど定義した read_website_content 関数を実行し、OpenAI が生成した URL を引数として渡します。
secondChatCompletion は、各 function call で取得したデータを踏まえた応答を返すために必要です。最後のステップは、Worker のデプロイです。
npx wrangler dev を実行し、表示された URL をブラウザーで開いてコードを確認します。取得した Web データのリアルタイム情報を使った、OpenAI の応答が表示されます。
アプリケーションをデプロイするには、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?
このチュートリアルの完成コードは GitHub ↗ を参照してください。
Workers と AI の続きは、LangChain と Cloudflare Workers を一緒に使うガイド ↗ や、Cloudflare Workers で ChatGPT プラグインを作る方法 ↗ を参照してください。
質問がある場合、サポートが必要な場合、プロジェクトを共有したい場合は、Discord ↗ の Cloudflare Developer コミュニティに参加し、ほかの開発者や Cloudflare チームとつながってください。