Cloudflare WorkersでHono+Azure OpenAI Serviceを動かすメモ
前準備
気がむいたら書きます
- Cloudflare Workersのアカウント作成
- Azure OpenAI APIのアカウントとAPIキーの準備
- wranglerなどは既にインストール済
- wrangler loginは既に実施済
雛形プロジェクトの作成
$ npm create cloudflare@latest
using create-cloudflare version 2.2.3
╭ Create an application with Cloudflare Step 1 of 3
│
├ In which directory do you want to create your application?
プロジェクト名を入力。同名のディレクトリが作られる。
│ dir ./my-project
│
╰ What type of application do you want to create?
「Website or web app」→「Hono」を選択。h/jで上下移動できる。
│ type Website or web app
│
├ Which development framework do you want to use?
│ framework Hono
│
╰ Continue with Hono via `npx create-hono@0.2.6 my-project --template cloudflare-workers`
create-hono version 0.2.6
cloned honojs/starter#main to /Users/hnw/src/my-project
✔ Copied project files
╭ Configuring your application for Cloudflare Step 2 of 3
│
├ Installing wrangler A command line tool for building Cloudflare Workers
│ installed via `npm install wrangler --save-dev`
│
├ Adding command scripts for development and deployment
│ added commands to `package.json`
│
╰ Do you want to use git for version control?
ここまで結構待つ。ここでYesにするとローカルリポジトリに勝手にcommitされる。
│ yes git
│
├ Committing new files
│ git commit
│
╰ Application configured
╭ Deploy with Cloudflare Step 3 of 3
│
╰ Do you want to deploy your application?
ここでYesにするといきなりCloudflare Workersにデプロイされて全世界公開される。恐ろしい子…
│ yes deploy via `npm run deploy`
│
├ Logging into Cloudflare checking authentication status
│ logged in
│
├ Selecting Cloudflare account retrieving accounts
│ account ******@***.jp's Account
│
├ Deploying your application
│ deployed via `npm run deploy`
│
├ SUCCESS View your deployed application at https://my-app.******.workers.dev
│
│ Navigate to the new directory cd my-project
│ Run the development server npm run dev
│ Deploy your application npm run deploy
│ Read the documentation https://developers.cloudflare.com/workers
│ Stuck? Join us at https://discord.gg/cloudflaredev
│
├ Waiting for DNS to propagate
│ DNS propagation complete.
│
├ Waiting for deployment to become available
│ deployment is ready at: https://my-app.******.workers.dev
│
├ Opening browser
│
╰ See you again soon!
ブラウザに表示されたページが今デプロイしたアプリケーションです。
デフォルトのWorker名はmy-appになってるので、気に入らなかったらwrangler.toml
を変更しましょう。
Azure OpenAI Service用のライブラリを動かしてみる
Azure OpenAI Serviceを動かすのに、APIに直接アクセスしてもいいのですが、公式ライブラリ @azure/openai を使ってみましょう。
Cloudflare WorkersはJSエンジンとしてNode.jsでなくV8を採用しているため、Node.js用ライブラリが動く保証はないのですが、まあやってみましょう。
$ cd my-project
$ npm install @azure/openai
@azure/openaiが正常動作する前提でコードを書いていきます。
import { Hono } from 'hono'
import { OpenAIClient, AzureKeyCredential } from "@azure/openai"
const messages = [
{ role: "system", content: "あなたは有能なアシスタントです。英語で考えた内容を日本語で猫のように喋ります。" },
{ role: "user", content: "Can you help me?" },
{ role: "assistant", content: "ハイだニャ。なんでも聞くニャ。" },
{ role: "user", content: "What's the best way to train a parrot?" },
];
const app = new Hono()
app.get('/', async (c) => {
const credential = new AzureKeyCredential(c.env!.AZURE_API_KEY as string);
const client = new OpenAIClient(c.env!.ENDPOINT as string, credential);
const deploymentId = "gpt-35-turbo";
const result = await client.getChatCompletions(deploymentId, messages);
for (const choice of result.choices) {
return c.text(`${choice.message?.content}`);
}
return c.text('Hello Hono!')
})
export default app
環境変数っぽい値は.dev.vars
に書いて使います。本ファイルはバージョン管理の対象外です。
ENDPOINT = https://******/
AZURE_API_KEY = ******
上記コードを試しに動かしてみましょう。
$ npm run dev
> dev
> wrangler dev src/index.ts
⛅️ wrangler 3.8.0
------------------
wrangler dev now uses local mode by default, powered by 🔥 Miniflare and 👷 workerd.
To run an edge preview session for your Worker, use wrangler dev --remote
⎔ Starting local server...
[mf:inf] Ready on http://0.0.0.0:8787
[mf:inf] - http://127.0.0.1:8787
[mf:inf] - http://192.168.1.105:8787
⎔ Reloading local server...
[mf:inf] Updated and ready on http://0.0.0.0:8787
[mf:inf] - http://127.0.0.1:8787
[mf:inf] - http://192.168.1.105:8787
Trace: RestError: Error sending request: The 'credentials' field on 'RequestInitializerDict' is not implemented.
at getError (index.js:3318:12)
at FetchHttpClient.sendRequest (index.js:3229:13) {
name: RestError,
code: REQUEST_SEND_ERROR,
statusCode: undefined,
request: PipelineRequestImpl,
response: undefined
...
}
at logConsoleMessage (/Users/hnw/src/my-project/node_modules/wrangler/wrangler-dist/cli.js:127017:25)
at WebSocket2.<anonymous> (/Users/hnw/src/my-project/node_modules/wrangler/wrangler-dist/cli.js:126712:13)
at callListener (/Users/hnw/src/my-project/node_modules/wrangler/wrangler-dist/cli.js:107229:18)
at WebSocket2.onMessage (/Users/hnw/src/my-project/node_modules/wrangler/wrangler-dist/cli.js:107164:13)
at WebSocket2.emit (node:events:526:35)
at Receiver2.receiverOnMessage (/Users/hnw/src/my-project/node_modules/wrangler/wrangler-dist/cli.js:108232:24)
at Receiver2.emit (node:events:514:28)
at Receiver2.dataMessage (/Users/hnw/src/my-project/node_modules/wrangler/wrangler-dist/cli.js:106514:18)
at Receiver2.getData (/Users/hnw/src/my-project/node_modules/wrangler/wrangler-dist/cli.js:106443:21)
at Receiver2.startLoop (/Users/hnw/src/my-project/node_modules/wrangler/wrangler-dist/cli.js:106184:26)
[mf:inf] GET / 500 Internal Server Error (12ms)
はい、エラーが出ました。下記URLによれば、workerdで実装しているfetchの一部機能が未実装のようです。
行儀は悪いんですが、node_modules
以下のファイルを直接編集して2行コメントアウトするとCloudflare Workersでも動くようになります。
const headers = buildFetchHeaders(request.headers);
const { streaming, body: requestBody } = buildRequestBody(request);
const requestInit = {
body: requestBody,
method: request.method,
headers: headers,
signal: abortController.signal,
// credentials: request.withCredentials ? "include" : "same-origin",
// cache: "no-store",
};
Cloudflare Wokersにデプロイ
開発中は.dev.vars
に書いていた値を暗号化してアップロードして使います。
$ npx wrangler secret put ENDPOINT
⛅️ wrangler 3.8.0
------------------
✔ Enter a secret value: … **********************************************************
🌀 Creating the secret for the Worker "my-app"
✨ Success! Uploaded secret ENDPOINT
$ npx wrangler secret put AZURE_API_KEY
⛅️ wrangler 3.8.0
------------------
✔ Enter a secret value: … ********************************************************************************************************************************
🌀 Creating the secret for the Worker "my-app"
✨ Success! Uploaded secret AZURE_API_KEY
ではデプロイしてみましょう。
$ npm run deploy
> deploy
> wrangler deploy --minify src/index.ts
⛅️ wrangler 3.8.0
------------------
Total Upload: 80.74 KiB / gzip: 25.64 KiB
Uploaded my-app (0.96 sec)
Published my-app (0.32 sec)
https://my-app.******.workers.dev
Current Deployment ID: ******
無事アップロードできたので、URLにアクセスしてみましょう。
無事に動きましたね。
リクエストを返すまで15秒くらいかかる(!)んですが、WorkersのCPU timeは5ms程度のようです。
Cloudflare WorkersはCPU timeの制約が厳しいんですが、この程度なら十分動かせそうですね。
まとめ
- Cloudflare Workers上でAzure OpenAI Service用ライブラリを動かしてみた
- ライブラリ @azure/openai は少しだけ修正が必要だった
- workerdがもう少し頑張ってくれたら動くライブラリがかなり増えそう
- Cloudflare Workersでそれなりの規模のNode.jsライブラリを使っても現実的に動くことがわかった
- Node.js用ライブラリを使っても今回のアプリ程度の規模ならfree accountの上限値を超えない模様
- 圧縮後サイズ25.64 KB(上限1MB)
- CPU時間5ms(上限10ms)
Discussion