- Workers AI の仕組み — サーバーレス GPU、モデルカタログ、3 つの呼び出し方法
- ai バインディングの設定と
env.AI.run()による LLM 呼び出し - SSE(Server-Sent Events)によるストリーミング応答の実装
- テキスト埋め込み・画像生成・音声認識モデルの使いどころ
- ニューロン課金の考え方と無料枠(10,000 ニューロン/日)
Workers AI の仕組み — サーバーレス GPU とモデルカタログ
Workers AI は、Cloudflare のグローバルネットワーク上に配備された GPU で機械学習モデルを実行するサービスです。GPU の調達・スケーリング・保守はすべて Cloudflare 側が担い、開発者はモデル ID と入力を渡すだけで推論結果を受け取れます。使った分だけ支払う従量課金で、Free プランでも無料枠の範囲で使い始められます。KV や R2 と同じく「バインディングを 1 つ足せばインフラが手に入る」体験が、GPU 推論にもそのまま当てはまるのがこの章の主題です。
呼び出し方法は 3 つあります。
| 方法 | 概要 | 向いている場面 |
|---|---|---|
| Workers バインディング | Worker のコードから env.AI.run() で直接呼ぶ | アプリに AI 機能を組み込む(本章の主役) |
| REST API | API トークンを付けて api.cloudflare.com の HTTPS エンドポイントを叩く | Cloudflare 外のサーバーやスクリプトから使う |
| ダッシュボード | テンプレート(LLM Chat App)から AI アプリを作成し、ブラウザ上で編集・デプロイする | コードを書かずにまず動かす |
実行できるモデルはモデルカタログとして整理されています。50 を超えるオープンソースモデルが提供されており(2026-08 時点のカタログ表示では 81 モデル)、タスクタイプごとに分類されています。
| タスクタイプ | 代表モデル | 用途 |
|---|---|---|
| Text Generation | @cf/meta/llama-3.1-8b-instruct-fast、@cf/openai/gpt-oss-120b | チャット・文章生成・要約 |
| Text Embeddings | @cf/baai/bge-m3、@cf/pfnet/plamo-embedding-1b | 意味検索・RAG・分類 |
| Text-to-Image | @cf/black-forest-labs/flux-1-schnell | 画像生成 |
| Automatic Speech Recognition | @cf/openai/whisper-large-v3-turbo | 音声の文字起こし・翻訳 |
| Text-to-Speech | @cf/deepgram/aura-1 | テキスト読み上げ |
| Translation | @cf/meta/m2m100-1.2b | 多言語翻訳 |
モデル ID は @cf/(Cloudflare ホスト)や @hf/ などの接頭辞 + 提供元 + モデル名で構成されます。各モデルの詳細ページには、コンテキストウィンドウ(入出力トークン数の上限)・単価・入出力パラメータの一覧が載っているので、採用前に必ず確認してください。
AI バインディングと env.AI.run()
Worker から Workers AI を使うには、AI バインディングを設定します。wrangler.jsonc に次の 1 ブロックを足すだけです(wrangler.toml なら [ai] セクションに binding = "AI")。
{
"ai": {
"binding": "AI" // Worker 内で env.AI として利用可能になる
}
}
バインディングの実体は env.AI オブジェクトで、中心となるメソッドは env.AI.run() です。第 1 引数にモデル ID、第 2 引数に入力オブジェクトを渡します。
const answer = await env.AI.run("@cf/meta/llama-3.1-8b-instruct-fast", {
prompt: "What is the origin of the phrase 'Hello, World'",
});
テキスト生成モデルへの入力には 2 つの形式があります。上の prompt は「unscoped プロンプト」で、単発の質問を投げる最短の書き方です。推奨されるのは「scoped プロンプト」、つまり messages 配列でロール付きの会話を渡す形式です。モデルごとに異なるチャットテンプレートの差異は Workers AI が吸収してくれます。
const answer = await env.AI.run("@cf/meta/llama-3.1-8b-instruct-fast", {
messages: [
{ role: "system", content: "you are a professional computer science assistant" },
{ role: "user", content: "what is WASM?" },
{ role: "assistant", content: "WASM (WebAssembly) is a binary instruction format..." },
{ role: "user", content: "does Python compile to WASM?" },
],
});
- system — AI の人格やルールを定義する。「日本語で答える」のような制約はここに書く
- user — ユーザーからの質問・発話
- assistant — AI 側の過去の応答。会話履歴の再現や出力形式のヒントに使う(非対応モデルもある)
テキスト生成モデルの主なオプションパラメータは次のとおりです(@cf/meta/llama-3.1-8b-instruct-fast の例、2026-08 時点)。
| パラメータ | 既定値 | 説明 |
|---|---|---|
max_tokens | 256 | 生成する最大トークン数 |
temperature | 0.6 | 出力のランダム性(0〜5、高いほど多様) |
top_p / top_k | — | 候補トークンの絞り込みによる多様性の調整 |
seed | — | 再現性のための乱数シード |
stream | false | true にすると結果を SSE で逐次返す |
stream: true を指定すると、env.AI.run() は完成した文字列の代わりにストリームを返します。これをそのまま Response の body にして content-type: text/event-stream を付ければ、生成されたそばからクライアントに届くチャット UI 的な体験を実現できます。LLM の全文生成を待ってから返すとユーザーの体感待ち時間が長くなるため、対話的な用途ではストリーミングが定石です。実装はハンズオン 11-2 で行います。
stream: true が縮めるのは処理時間ではなく体感待ち時間です。テキスト以外のタスク — 埋め込み・画像生成・音声認識
テキスト埋め込み
テキスト埋め込み(text embeddings)は、文章を数値ベクトルに変換するタスクです。意味が近い文章はベクトル空間上でも近くに配置されるため、キーワード一致に頼らない意味検索・レコメンド・RAG の土台になります。多言語対応の @cf/baai/bge-m3(コンテキストウィンドウ 60,000 トークン)や、Preferred Networks 製の日本語特化モデル @cf/pfnet/plamo-embedding-1b が利用できます。入力は text キーに文字列または文字列の配列を渡し、結果はレスポンスの data 配列(文章ごとのベクトル)として返ります。
run() にまとめるのは往復を減らす工夫であって、比較が成立する条件ではありません。画像生成
Text-to-Image モデルはプロンプトから画像を生成します。@cf/black-forest-labs/flux-1-schnell は 120 億パラメータの高速モデルで、prompt(最大 2,048 文字)と steps(拡散ステップ数、既定 4・最大 8)を受け取り、Base64 エンコードされた画像を返します。
const response = await env.AI.run("@cf/black-forest-labs/flux-1-schnell", {
prompt: "a cyberpunk lizard",
});
// response.image は Base64 文字列。data URI としてそのまま <img src> に使える
const dataURI = `data:image/jpeg;charset=utf-8;base64,${response.image}`;
音声認識
Automatic Speech Recognition(ASR)タスクでは @cf/openai/whisper-large-v3-turbo が使えます。音声データを渡すと文字起こし結果(text)に加えて、字幕にそのまま使える WebVTT 形式(vtt)や単語数も返ります。task パラメータで文字起こし(transcribe)と翻訳(translate)を切り替えられ、language で音声の言語を指定できます。料金は音声 1 分あたり $0.0005 です(2026-08 時点)。
埋め込みをベクトルデータベース Vectorize に保存して LLM と組み合わせると、自前ドキュメントに基づいて回答する RAG が構築できます(公式チュートリアル)。これは次章のテーマです。
ニューロン課金と無料枠
Workers AI の課金単位はニューロン(Neuron)です。ニューロンはモデルの種類をまたいで AI の出力を測る Cloudflare 独自の単位で、リクエストの処理に必要な GPU 計算量を表します。ドキュメント上は「1M 入力トークンあたり $◯◯」のようにモデルごとのトークン単価が併記されていますが、裏側の請求はニューロンで行われます(2026-08 時点、以下同)。
- 無料枠 — 誰でも 1 日あたり合計 10,000 ニューロンまで無料。毎日 00:00 UTC(日本時間 9:00)にリセットされる
- 超過分 — Workers Paid プラン(月 $5〜)では無料枠を超えた分が $0.011 / 1,000 ニューロンで課金される。Free プランのままでは超過分は実行できずエラーになる
- 一部のフロンティアモデル(
@cf/moonshotai/kimi-k2.6など)は有料の課金手段(Workers Paid または AI Gateway のプリペイドクレジット)が必須
モデル単価の例を挙げます。同じ「テキスト生成」でもモデル規模で 1 桁以上変わることが分かります。
| モデル | 入力単価 | 出力単価 |
|---|---|---|
@cf/meta/llama-3.2-1b-instruct | $0.027 / 1M トークン | $0.201 / 1M トークン |
@cf/meta/llama-3.1-8b-instruct-fp8-fast | $0.045 / 1M トークン | $0.384 / 1M トークン |
@cf/meta/llama-3.3-70b-instruct-fp8-fast | $0.293 / 1M トークン | $2.253 / 1M トークン |
@cf/baai/bge-m3(埋め込み) | $0.012 / 1M トークン | — |
@cf/openai/whisper-large-v3-turbo(ASR) | $0.0005 / 音声 1 分 | — |
使用量とは別にレート制限もあります。既定はタスクタイプ単位で、Text Generation は毎分 300 リクエスト、Text Embeddings は毎分 3,000 リクエスト、ASR と Text-to-Image は毎分 720 リクエストです(モデルごとの個別制限もあり)。ニューロンの消費量はダッシュボードの Workers AI ページで確認できます。
AI バインディングを設定した Worker で、POST された質問に日本語で答えるチャット API を作ります。所要時間は約 15 分です。
無料枠の消費に注意:Workers AI は wrangler dev によるローカル開発でも Cloudflare アカウント上の GPU でモデルを実行するため、無料枠(10,000 ニューロン/日)を消費します。この章のハンズオン程度なら無料枠内に収まりますが、ループでの連続実行は避けてください。
- 新しい Worker プロジェクトを作成する。テンプレートは
Hello World example→Worker only→TypeScriptを選び、デプロイの質問にはNoと答える
npm create cloudflare@latest -- workers-ai-chat
cd workers-ai-chat
wrangler.jsoncの末尾に AI バインディングを追加する(前節のとおり"ai": { "binding": "AI" })src/index.tsを次の内容に置き換える。system ロールで「日本語で答える」制約を与え、既定値 256 では日本語の回答が途切れやすいのでmax_tokensを 512 に引き上げている
export interface Env {
AI: Ai;
}
export default {
async fetch(request, env): Promise<Response> {
if (request.method !== "POST") {
return new Response('POST で JSON {"message": "..."} を送ってください', {
status: 405,
});
}
const { message } = (await request.json()) as { message: string };
const answer = await env.AI.run("@cf/meta/llama-3.1-8b-instruct-fast", {
messages: [
{
role: "system",
content:
"あなたは Cloudflare に詳しいアシスタントです。必ず日本語で、簡潔に答えてください。",
},
{ role: "user", content: message },
],
max_tokens: 512,
});
return Response.json(answer);
},
} satisfies ExportedHandler<Env>;
npx wrangler devで起動し(初回はログインを求められる)、別ターミナルから質問を送る
curl http://localhost:8787 -X POST \
-H "Content-Type: application/json" \
-d '{"message": "Cloudflare Workers とは何ですか?"}'
# 期待される出力(response の文面は実行ごとに変わる)
{"response":"Cloudflare Workers は、Cloudflare のグローバルネットワーク上で
JavaScript や TypeScript のコードを実行できるサーバーレス実行環境です。..."}
日本語の回答が JSON で返れば成功です。npx wrangler deploy すれば、この API はそのまま workers.dev の URL で世界中から呼べるようになります。
11-1 のチャット API を、生成結果を逐次返すストリーミング型に改造します。所要時間は約 10 分です。
src/index.tsのenv.AI.run()呼び出しと return 部分を次のように変更する。stream: trueを足し、返り値のストリームをそのままResponseの body にする
const stream = await env.AI.run("@cf/meta/llama-3.1-8b-instruct-fast", {
messages: [
{
role: "system",
content:
"あなたは Cloudflare に詳しいアシスタントです。必ず日本語で、簡潔に答えてください。",
},
{ role: "user", content: message },
],
max_tokens: 512,
stream: true,
});
return new Response(stream, {
headers: { "content-type": "text/event-stream" },
});
npx wrangler devを起動したまま、curl の-N(バッファリング無効)オプションを付けて呼び出す
curl -N http://localhost:8787 -X POST \
-H "Content-Type: application/json" \
-d '{"message": "エッジコンピューティングの利点を 3 つ教えてください"}'
# 期待される出力:data: で始まる SSE イベントが少しずつ流れてくる
data: {...} ← 生成されたテキストの断片
data: {...}
...(生成が終わるとストリームが閉じる)
全文を待たずに最初の 1 文字目が届き始めることを確認してください。ブラウザ側では EventSource や fetch のリーダーで受け取れば、ChatGPT 風の「文字が流れてくる」UI になります。
多言語埋め込みモデル @cf/baai/bge-m3 で日本語文書のベクトルを作り、質問文とのコサイン類似度で並べ替える最小の意味検索を作ります。所要時間は約 15 分です。
- 新しい Worker プロジェクト
workers-ai-searchを 11-1 と同じ手順で作成し、AI バインディングを設定する src/index.tsを次の内容に置き換える。質問と文書をまとめて 1 回のrun()でベクトル化しているのがポイント
export interface Env {
AI: Ai;
}
const docs = [
"Workers AI はサーバーレス GPU で AI モデルを実行するサービスです",
"R2 はエグレス無料のオブジェクトストレージです",
"D1 は SQLite ベースのサーバーレスデータベースです",
];
function cosine(a: number[], b: number[]): number {
let dot = 0, na = 0, nb = 0;
for (let i = 0; i < a.length; i++) {
dot += a[i] * b[i];
na += a[i] * a[i];
nb += b[i] * b[i];
}
return dot / (Math.sqrt(na) * Math.sqrt(nb));
}
export default {
async fetch(request, env): Promise<Response> {
const q =
new URL(request.url).searchParams.get("q") ?? "GPU で推論したい";
const { data } = (await env.AI.run("@cf/baai/bge-m3", {
text: [q, ...docs],
})) as { data: number[][] };
const [qv, ...dv] = data;
const ranked = docs
.map((text, i) => ({ text, score: cosine(qv, dv[i]) }))
.sort((x, y) => y.score - x.score);
return Response.json({ query: q, results: ranked });
},
} satisfies ExportedHandler<Env>;
npx wrangler devで起動し、クエリを変えながら呼び出す
curl "http://localhost:8787/?q=画像などのファイルを安く保存したい"
# 期待される出力(score の値は一例):R2 の文書が最上位に来る
{"query":"画像などのファイルを安く保存したい","results":[
{"text":"R2 はエグレス無料のオブジェクトストレージです","score":0.62},
...]}
キーワードが一致していなくても意味の近い文書が上位に来ることを確認してください。文書数が増えたら、この総当たり計算を次章の Vectorize に置き換えます。
Worker を介さず、curl から REST API で直接モデルを実行します。CI やローカルスクリプトから使うときの形です。所要時間は約 10 分です。
- ダッシュボードの Workers AI ページを開き、Use REST API を選択する
- Create a Workers AI API Token からトークンを作成してコピーする(自分でカスタムトークンを作る場合は
Workers AI - ReadとWorkers AI - Editの両権限が必要) - 同じ画面の Get Account ID からアカウント ID をコピーする
- 取得した 2 つの値でエンドポイント
/accounts/{account_id}/ai/run/{model}を呼び出す
curl https://api.cloudflare.com/client/v4/accounts/<YOUR_ACCOUNT_ID>/ai/run/@cf/meta/llama-3.1-8b-instruct-fast \
-H "Authorization: Bearer <YOUR_API_TOKEN>" \
-d '{ "messages": [{ "role": "user", "content": "Cloudflare Workers を一言で説明して" }] }'
# 期待される出力
{
"result": { "response": "Cloudflare Workers は..." },
"success": true,
"errors": [],
"messages": []
}
<YOUR_ACCOUNT_ID> と <YOUR_API_TOKEN> は手順 2〜3 でコピーした値に置き換えます。応答本体が result に包まれるのがバインディング経由との違いです。なお Workers AI は OpenAI 互換エンドポイント(.../ai/v1/chat/completions と .../ai/v1/embeddings)も提供しており、OpenAI SDK の baseURL を差し替えるだけで既存コードから利用できます。
つまずきポイント
ローカル開発でも課金される — wrangler dev のローカルモードでも、モデルの実行は常に Cloudflare アカウント上の GPU にアクセスします。ニューロンの無料枠を消費し、レート制限にもカウントされるので、開発中のループ実行やベンチマークには注意してください。
日本語の回答が途中で切れる — テキスト生成の max_tokens は既定 256 です。長めの回答を求めるなら max_tokens: 512 のように明示的に増やしてください。上限はモデルのコンテキストウィンドウ(各モデルページに記載。llama-3.1-8b-instruct-fast は 128,000 トークン)を超えられません。
429 エラーが返ってくる — 無料枠 10,000 ニューロン/日を使い切ると、エラーコード 3036(HTTP 429)で失敗します。00:00 UTC のリセットを待つか Workers Paid プランへアップグレードしてください。使用量に余裕があるのに 429 になる場合は、タスクタイプごとのレート制限(Text Generation は毎分 300 リクエスト等)に当たっている可能性があります。
「No such model」エラーとモデルの廃止 — モデル ID は @cf/meta/... の接頭辞まで含めて正確に書かないとエラーコード 5007(No such model)になります。またカタログのモデルには Deprecated(廃止予定)マークが付くことがあり、たとえば @cf/meta/llama-3.1-8b-instruct は 2026-05-30 付で Deprecated 扱いです。採用前にモデルページで状態を確認し、古いチュートリアルのモデル ID を鵜呑みにしないでください。
理解度チェック
Q1. Worker から Workers AI を使うために wrangler.jsonc に追加する設定は?
"ai": { "binding": "AI" } です。これで Worker 内から env.AI(binding に指定した名前)が使えるようになり、env.AI.run(モデルID, 入力) で推論を実行できます。
Q2. scoped プロンプト(messages 配列)の system ロールは何のために使う?
AI の人格・ルール・振る舞いを定義するために使います。「必ず日本語で答える」のような制約は user メッセージではなく system メッセージに書くのが定石です。user は実際の質問、assistant は AI 側の過去の応答を表します。
Q3. LLM の応答をストリーミングで返すために必要な 2 つの変更は?
env.AI.run() の入力に stream: true を指定することと、返ってきたストリームを body にした Response に content-type: text/event-stream ヘッダーを付けて返すことです。結果は SSE(Server-Sent Events)として逐次配信されます。
Q4. Workers AI の無料枠と、超過した場合の挙動は?
1 日あたり 10,000 ニューロンまで無料で、毎日 00:00 UTC にリセットされます(2026-08 時点)。Free プランで超過するとエラー(コード 3036、HTTP 429)になり、Workers Paid プランなら超過分が $0.011 / 1,000 ニューロンで課金されます。
Q5. Cloudflare の外から Workers AI のモデルを実行する REST API エンドポイントの形式は?
https://api.cloudflare.com/client/v4/accounts/{account_id}/ai/run/{model} に、API トークンを Authorization: Bearer ヘッダーで付けて POST します。応答は result キーに包まれて返ります。OpenAI 互換の /ai/v1/chat/completions エンドポイントも利用できます。
まとめと次章へ
- Workers AI は Cloudflare のグローバルネットワーク上のサーバーレス GPU で、50 を超えるオープンソースモデル(LLM・埋め込み・画像・音声など)を実行できる
- Worker からは
"ai": { "binding": "AI" }のバインディング 1 つで接続でき、env.AI.run(モデルID, 入力)が基本形。プロンプトはmessages(scoped)推奨 stream: true+text/event-streamで SSE ストリーミング応答になり、チャット UI の体感が大きく向上する- 埋め込みモデル(
@cf/baai/bge-m3等)は意味検索・RAG の土台。画像生成や音声認識も同じrun()の作法で呼べる - 課金はニューロン単位。無料枠 10,000 ニューロン/日、超過は Workers Paid で $0.011 / 1,000 ニューロン(2026-08 時点)。ローカル開発でも消費される
次章では、この章で作った埋め込みをベクトルデータベース Vectorize に保存し、自前のドキュメントに基づいて回答する RAG パイプラインを構築します。