このCloudflare Workers AIチュートリアルでは、機械学習モデルをCloudflareのグローバルエッジネットワーク上で直接デプロイし実行する方法を解説します。Cloudflare Workers AI を使用すれば、複雑なGPUサーバー群を構築・運用することなく、大規模言語モデル(LLMs)の実行、テキスト翻訳、画像生成、音声書き起こしをエンドユーザーの物理的に近い場所で実行できます。以下では、Wranglerの構成、fetchハンドラの記述、Llamaモデルの稼働、およびエッジでのAPIコストの最適化について順を追って解説します。

TL;DR

  • AIモデルをサーバーレスで実行する:Cloudflare Workers AIが基盤となるGPUインフラを管理するため、開発者はアクティブな計算処理時間に対してのみ料金を支払います。
  • wrangler.tomlでバインディングを設定する:APIキーを管理することなく、WorkerをAIバインディングに直接リンクできます。
  • fetchハンドラを記述する:ユーザーからのリクエストを受け取り、モデルを実行し、JSONレスポンスを処理します。
  • 最適化されたモデルを選択する:Cloudflareのカタログ(Llama 3、Whisper、Stable Diffusionなど)から、速度と精度のバランスが取れたモデルを選択します。
  • リミットとクォータの管理:本番環境での不正利用や大量のトークン消費による想定外のコスト高騰からAPIエンドポイントを保護します。

なぜAIモデルをエッジで実行するのか?

従来、アプリケーションにAI機能を統合するには、外部API(OpenAIなど)を呼び出すか、高価なクラウドサーバーを借りてオープンソースモデルを自前で稼働させる必要がありました。

外部APIの呼び出しは、ネットワークレイテンシとデータプライバシーの懸念を伴います。一方、自前のGPUサーバーの運用は、保守作業が煩雑でスケーラビリティにも課題がありました。Cloudflare Workers AIは、このジレンマを解消します。本プラットフォームは、Cloudflareのグローバルネットワーク全体に配置されたGPU上でオープンソースモデルをホストします。作成したコードは軽量なWorkerとして動作し、ユーザーの近くでほぼゼロに近いレイテンシでモデルを実行します。基本的なエッジ構造の構築については、Cloudflare Workersを使用したサーバーレスAPIの構築ガイド を参照してください。


前提条件

作業を開始する前に、以下が準備されていることを確認してください。

  • Cloudflareアカウント(Workersが有効になっていること)。無料プランには毎日のインフェレンス(推論)無料枠が含まれており、本ガイドを進めるには十分な量です。
  • Node.js 18以降がローカルにインストールされていること(開発ツールやローカル開発サーバーの実行に必要)。
  • Wrangler(Workers CLI)がインストールされ、認証されていること。 npm install -g wranglerでインストールし、wrangler loginを実行してアカウントと連携します。
  • JavaScriptの基本知識およびWorkerの基盤となるfetchリクエスト/レスポンスモデルの理解。

何もない状態から開始する場合は、create-cloudflare(C3)ツールを使ってプロジェクトのひな形を作成します。デプロイ準備の整ったWorker、wrangler.toml、および適切なcompatibility_dateが生成されます。

1npm create cloudflare@latest my-edge-ai
2cd my-edge-ai

プロンプトが表示されたら、“Hello World” Workerテンプレートを選択します。これにより、次のステップでAIバインディングを追加するためのクリーンな開始点が得られます。


ステップ1:wrangler.tomlの構成

AIモデルにアクセスするには、まずプロジェクトの構成ファイルでAIバインディングを定義する必要があります。

wrangler.toml(またはwrangler.json)を開き、以下のブロックを追加します。

1[ai]
2binding = "AI"

このバインディングにより、Workerコード内で環境引数(env.AI)を介してAIサービスが利用可能になります。APIキーの管理、エンドポイントの構成、接続文字列の処理などは不要です。Wranglerは、デプロイ時に認証を自動的に処理します。

このプロジェクトの完全なwrangler.tomlは次のようになります。

1name = "my-edge-ai"
2main = "src/index.js"
3compatibility_date = "2025-01-01"
4
5[ai]
6binding = "AI"

compatibility_dateは重要です。これは実行時の動作バージョンを固定するためのもので、将来プラットフォームに変更があった場合でも、Workerの動作が勝手に変わるのを防ぎます。これがないと、デプロイ時に構成エラーで失敗します。これは初回のデプロイで非常によくあるエラーの一つです。


ステップ2:Workerコードの記述

バインディングが構成されたら、fetchハンドラからAIサービスを呼び出すことができます。以下の例では、ユーザーのプロンプトを含むJSONペイロードを受け取り、Llama 3を使用してテキスト生成を行う方法を示します。

 1export default {
 2  async fetch(request, env) {
 3    if (request.method !== "POST") {
 4      return new Response("Method not allowed", { status: 405 });
 5    }
 6
 7    try {
 8      const { prompt } = await request.json();
 9      if (!prompt) {
10        return Response.json({ error: "Missing prompt" }, { status: 400 });
11      }
12
13      // Call the model using the AI binding
14      const response = await env.AI.run("@cf/meta/llama-3-8b-instruct", {
15        prompt: prompt,
16        max_tokens: 256
17      });
18
19      return Response.json(response);
20    } catch (err) {
21      return Response.json({ error: err.message }, { status: 500 });
22    }
23  }
24};

このシンプルな構造により、テキスト要約ツール、感情分析ツール、コンテンツ生成ツールなどを構築できます。これらの機能をデータベースと連携させたい場合は、サーバーレスSQLデータベースにバインドできます。詳細はCloudflare D1データベース構築ガイド を参照してください。

チャットメッセージ形式の使用

promptフィールドは一問一答の補完には便利ですが、対話型モデルは構造化されたmessages配列を使用する方が最適に動作します。これにより、モデルのトーンを定義するシステムインストラクションを設定し、それをユーザーの入力と明確に区別できます。

 1const messages = [
 2  { role: "system", content: "You are a concise technical assistant." },
 3  { role: "user", content: prompt }
 4];
 5
 6const response = await env.AI.run("@cf/meta/llama-3-8b-instruct", {
 7  messages,
 8  max_tokens: 512
 9});
10
11// Text models return the generated text on the `response` property
12return Response.json({ answer: response.response });

テキスト生成モデルの出力はresponseフィールド内にラップされているため、生成されたテキストは最上位レベルではなくresponse.responseにあることに注意してください。これは、生オブジェクトを出力して想定と異なる構造に戸惑う、初心者にありがちな落とし穴です。


適切なモデルの選択

Cloudflareのカタログには数十のモデルが含まれており、適切なモデルの選択は速度、品質、およびコストのトレードオフです。モデルが小さければ応答は速くリソース消費も少なくなりますが、大規模なモデルの方が優れた推論が可能です(ただしリクエストごとのコストは高くなります)。以下の表は、一般的なテキスト生成モデルの比較です。

モデル主な用途相対的な速度相対的なコスト
@cf/meta/llama-3-8b-instruct一般的なチャット、要約高速
@cf/meta/llama-3.1-70b-instruct複雑な推論、長文回答低速
@cf/mistral/mistral-7b-instruct-v0.2軽量な指示、ドラフト作成高速
@cf/meta/llama-guard-3-8bコンテンツのモデレーションと分類高速

大原則として、まずはLlama 3 8B Instructなどの8Bモデルから始めることをお勧めします。要約、分類、チャットワークロードの大部分を、70Bモデルの数分の一のレイテンシとコストで処理できます。評価テストを行って、より小型のモデルでは品質が明らかに不足していると判断された場合にのみ、より大きなモデルに移行してください。


ステップ3:ユーザー体験を向上させるレスポンスのストリーミング

チャットアプリケーションにおいて、回答全体が生成されるのを待ってから画面に表示する方式は、ユーザー体験を損なう原因になります。

AIバインディングを構成して、生成されたトークンを逐次ストリーミング出力させることができます。これを行うには、リクエストオプションでstream: trueを渡します。WorkerはReadableStreamを返し、これをブラウザクライアントに直接転送することで、応答性の高い対話型チャットインターフェースを作成できます。このエッジランタイムのアプローチと従来のクラウドホスティングの比較については、Cloudflare WorkersとAWS Lambdaの比較 を参照してください。

以下は、完全なストリーミングハンドラの例です。パースされたJSONを返す代わりに、ストリームを適切なcontent-typeでクライアントに直接転送し、ブラウザがServer-Sent Eventsとして消費できるようにします。

 1export default {
 2  async fetch(request, env) {
 3    const { prompt } = await request.json();
 4
 5    const stream = await env.AI.run("@cf/meta/llama-3-8b-instruct", {
 6      prompt,
 7      max_tokens: 512,
 8      stream: true
 9    });
10
11    return new Response(stream, {
12      headers: { "content-type": "text/event-stream" }
13    });
14  }
15};

非ストリーミング版との主な違いはレスポンスそのものです。ストリームを直接new Response()に渡し、content-typetext/event-streamに設定します。ストリームをResponse.json()にラップしてしまうと正しくシリアライズされず、クライアントは空のレスポンスを受け取ることになります。


Workerのテストとデプロイ

バインディングとハンドラを設定したら、デプロイする前にローカル環境でWorkerを実行します。

1npx wrangler dev

推論はローカルマシンではなくCloudflareのGPU上で動作するため、ローカル開発中であってもAIバインディングはネットワーク経由でクラウドにアクセスします。Wranglerはこの接続を自動で処理しますが、ローカルでのテスト実行にもインターネット接続と有効なログインセッションが必要になります。

wrangler devの実行中にcurlでテストリクエストを送信します。

1curl -X POST http://localhost:8787 \
2  -H "Content-Type: application/json" \
3  -d '{"prompt": "Summarise the benefits of edge computing in one sentence."}'

出力結果に問題がなければ、グローバルネットワークにデプロイします。

1npx wrangler deploy

WranglerがWorkerをアップロードし、*.workers.devのURLを返します。これでエンドポイントが世界中のすべてのCloudflareデータセンターで有効になり、リクエストは自動的にユーザーに最も近い拠点にルーティングされます。


よくある落とし穴とトラブルシューティング

エッジで推論機能を初めてデプロイする際に、開発チームが直面しやすい問題がいくつかあります。事前に対処法を知っておくことで、デバッグ時間を大幅に短縮できます。

  • Cannot read properties of undefined (reading 'run')env.AIバインディングが未定義です。これはほぼ確実にwrangler.toml[ai]ブロックが不足しているか、ファイルを編集した後にwrangler devを再起動(または再デプロイ)していないことが原因です。バインディング名が完全一致しているか確認してください。
  • No such model または run時の400エラー:モデル識別子が間違っています。モデル名は大文字・小文字を区別し、フルパス(例:@cf/meta/llama-3-8b-instruct)を含める必要があります。記憶に頼らず、モデルカタログからコピーしてください。
  • ストリームレスポンスが空、または文字化けする:ストリームをnew Response(stream, ...)ではなくResponse.json()経由で返してしまっています。ストリームはシリアライズせずにそのまま転送する必要があります。
  • 高負荷時の容量制限や429エラー:モデルが一時的に過負荷状態にあるか、アカウントの制限に達しています。バックオフ付きの短いリトライ処理を追加し、突発的なバーストトラフィックにはより小型のモデルの使用を検討してください。
  • 回答が途中で切れるmax_tokensが低すぎるため、回答が途中で停止しています。上限を引き上げてください。ただし、値を大きくするとレイテンシとコストの両方が上昇することに留意してください。

リクエストがエラーを返さずに無言で失敗する場合は、テストリクエストを送信しながらnpx wrangler tailでライブログを監視してください。デプロイされたWorkerからの実行時エラーやconsole.logの出力がストリーミングされ、何が返されたかを素早く確認できます。


本番環境のコストとセキュリティの最適化

Workers AIは極めて高いコスト効率を誇りますが、本番環境で推論を動かすには適切な管理が不可欠です。

  • レート制限の適用:クライアントによるエンドポイントの呼び出し頻度を制限します。GPUの計算コストは使用量に応じてスケールするためです。
  • プロンプトのクレンジング:インジェクション攻撃を防ぎ、モデルの出力がブランドガイドラインに沿うように、入力を検証・フィルタリングします。
  • コンテキストサイズを絞る:プロンプト履歴は短く保ちます。リクエストごとに膨大なコンテキストバッファを送信すると、処理されるトークンコストが増大します。

コンテキスト管理の具体的な手法については、OpenAI APIチャットボット構築ガイド を参照してください。


主なポイント

  • Cloudflare Workers AIは、GPUインフラの保守不要で、オープンソースモデルへのサーバーレスアクセスを提供します。
  • wrangler.toml[ai]バインディングブロックを追加するだけで、アクセスを設定できます。
  • fetchハンドラを記述することで、テキスト生成、翻訳、画像処理タスクをエッジで直接処理できます。
  • モバイルやチャット体験を向上させるには、stream: trueを設定してトークンのストリーミングを有効化します。
  • 本番環境のエンドポイントを保護するために、レート制限と入力値の検証を実装します。

エッジでのAIアプリケーション構築

信頼性の高いAI統合を構築するには、サーバーレスアーキテクチャに関する深い知識が必要です。Mecanikは、AIインテグレーション開発サービス およびOpenAI API連携開発サービス を通じて、カスタムのAPI設計と実装を専門に行っています。コストとユーザー体験を最適化し、シームレスにスケールするエッジネイティブなツールを構築します。プロジェクトのご相談は、お気軽に当社までお問い合わせください。


よくある質問(FAQ)

Cloudflare Workers AIとは何ですか? CloudflareのグローバルなGPUネットワーク上で機械学習モデル(テキスト生成、翻訳、音声テキスト変換、画像生成など)を実行できるサーバーレスプラットフォームです。

Workers AIを使用するのにAPIキーは必要ですか? いいえ。wrangler.tomlファイルでAIバインディングを宣言すれば、Cloudflareが内部で認証処理を管理するため、コードからはenv.AIを介して直接サービスを利用できます。

Cloudflare Workers AIで利用できるモデルには何がありますか? Meta Llama、Mistral、OpenAI Whisper、Stable Diffusionなどの主要なオープンソースモデルがホストされており、カタログは定期的に更新されています。

Workers AIからのテキスト回答をストリーミングできますか? はい。env.AI.run呼び出しのパラメータでstream: trueを設定することで、Workerは標準のReadableStreamを返し、ブラウザにテキストを順次ストリーミングできます。

Workers AIの料金体系はどのようになっていますか? テキストモデルの場合は処理されたトークン数、その他のモデルの場合は計算処理時間に基づいて課金される、従量課金制(ペイアズユーゴー)のコスト効率の良い料金モデルを採用しています。