cloudflare-workers-ai について
Cloudflare Workers AI を使うアプリ開発者向けのリファレンススキルです。モデル呼び出しや本番運用のパターンに加え、AI Gateway、制限、エラー処理を扱います。
主な機能
- 01テキスト生成とストリーミング
- 02埋め込み・画像・ビジョンモデルの呼び出し
- 03モデル選択とパラメーターの解説
- 04AI Gateway の連携パターン
- 05制限・監視・エラー処理
活用シーン
- 01Worker にテキストや画像生成を追加
- 02埋め込みを RAG フローで利用
- 03AI Gateway 経由でリクエストを記録・キャッシュ
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ jackspace/ claudeskillz --skill cloudflare-workers-aiインストール後、Claude Code で/cloudflare-workers-aiを入力して読み込まれたか確認します。
同梱ファイルREADME.mdSKILL.json
詳細
Cloudflare Workers AI - 完全リファレンス
Cloudflare Workers AI を使用して AI 搭載アプリケーションを構築するための、本番環境対応のナレッジドメインです。
ステータス:本番環境対応 ✅ 最終更新日:2025-10-21 依存関係:cloudflare-worker-base(Worker のセットアップ用) 最新バージョン:[email protected]、@cloudflare/[email protected]
目次
クイックスタート(5 分)
1. AI バインディングを追加
wrangler.jsonc:
{
"ai": {
"binding": "AI"
}
}
2. 最初のモデルを実行
export interface Env {
AI: Ai;
}
export default {
async fetch(request: Request, env: Env): Promise<Response> {
const response = await env.AI.run('@cf/meta/llama-3.1-8b-instruct', {
prompt: 'What is Cloudflare?',
});
return Response.json(response);
},
};
3. ストリーミングを追加(推奨)
const stream = await env.AI.run('@cf/meta/llama-3.1-8b-instruct', {
messages: [{ role: 'user', content: 'Tell me a story' }],
stream: true, // Always use streaming for text generation!
});
return new Response(stream, {
headers: { 'content-type': 'text/event-stream' },
});
ストリーミングを使う理由
- 大きなレスポンスがメモリにバッファリングされるのを防ぎます
- 最初のトークンが届くまでの時間を短縮します
- 長文コンテンツのユーザーエクスペリエンスが向上します
- Worker のタイムアウト問題を回避できます
Workers AI API リファレンス
env.AI.run()
AI モデルの推論を実行します。
シグネチャ:
async env.AI.run(
model: string,
inputs: ModelInputs,
options?: { gateway?: { id: string; skipCache?: boolean } }
): Promise<ModelOutput | ReadableStream>
パラメーター:
model(string、必須)- モデル ID(例:@cf/meta/llama-3.1-8b-instruct)inputs(object、必須)- モデル固有の入力options(object、任意)- 追加オプションgateway(object)- AI Gateway の設定id(string)- Gateway IDskipCache(boolean)- AI Gateway のキャッシュをスキップします
戻り値:
- 非ストリーミング:
Promise<ModelOutput- JSON レスポンス - ストリーミング:
ReadableStream- サーバー送信イベントのストリーム
テキスト生成モデル
入力形式:
{
messages?: Array<{ role: 'system' | 'user' | 'assistant'; content: string }>;
prompt?: string; // Deprecated, use messages
stream?: boolean; // Default: false
max_tokens?: number; // Max tokens to generate
temperature?: number; // 0.0-1.0, default varies by model
top_p?: number; // 0.0-1.0
top_k?: number;
}
出力形式(非ストリーミング):
{
response: string; // Generated text
}
例:
const response = await env.AI.run('@cf/meta/llama-3.1-8b-instruct', {
messages: [
{ role: 'system', content: 'You are a helpful assistant.' },
{ role: 'user', content: 'What is TypeScript?' },
],
stream: false,
});
console.log(response.response);
テキスト埋め込みモデル
入力形式:
{
text: string | string[]; // Single text or array of texts
}
出力形式:
{
shape: number[]; // [batch_size, embedding_dimensions]
data: number[][]; // Array of embedding vectors
}
例:
const embeddings = await env.AI.run('@cf/baai/bge-base-en-v1.5', {
text: ['Hello world', 'Cloudflare Workers'],
});
console.log(embeddings.shape); // [2, 768]
console.log(embeddings.data[0]); // [0.123, -0.456, ...]
画像生成モデル
入力形式:
{
prompt: string; // Text description
num_steps?: number; // Default: 20
guidance?: number; // CFG scale, default: 7.5
strength?: number; // For img2img, default: 1.0
image?: number[][]; // For img2img (base64 or array)
}
出力形式:
- バイナリ画像データ(PNG/JPEG)
例:
const imageStream = await env.AI.run('@cf/black-forest-labs/flux-1-schnell', {
prompt: 'A beautiful sunset over mountains',
});
return new Response(imageStream, {
headers: { 'content-type': 'image/png' },
});
ビジョンモデル
入力形式:
{
messages: Array<{
role: 'user' | 'assistant';
content: Array<{ type: 'text' | 'image_url'; text?: string; image_url?: { url: string } }>;
}>;
}
例:
const response = await env.AI.run('@cf/meta/llama-3.2-11b-vision-instruct', {
messages: [
{
role: 'user',
content: [
{ type: 'text', text: 'What is in this image?' },
{ type: 'image_url', image_url: { url: 'data:image/png;base64,iVBOR...' } },
],
},
],
});
モデル選択ガイド
テキスト生成(LLM)
| モデル | 最適な用途 | レート制限 | サイズ |
|---|---|---|---|
@cf/meta/llama-3.1-8b-instruct | 汎用、高速 | 300/min | 8B |
@cf/meta/llama-3.2-1b-instruct | 超高速、単純なタスク | 300/min | 1B |
@cf/qwen/qwen1.5-14b-chat-awq | 高品質、複雑な推論 | 150/min | 14B |
@cf/deepseek-ai/deepseek-r1-distill-qwen-32b | コーディング、技術コンテンツ | 300/min | 32B |
@hf/thebloke/mistral-7b-instruct-v0.1-awq | 高速、効率的 | 400/min | 7B |
テキスト埋め込み
| モデル | 次元数 | 最適な用途 | レート制限 |
|---|---|---|---|
@cf/baai/bge-base-en-v1.5 | 768 | 汎用 RAG | 3000/min |
@cf/baai/bge-large-en-v1.5 | 1024 | 高精度検索 | 1500/min |
@cf/baai/bge-small-en-v1.5 | 384 | 高速、低ストレージ使用量 | 3000/min |
画像生成
| モデル | 最適な用途 | レート制限 | 速度 |
|---|---|---|---|
@cf/black-forest-labs/flux-1-schnell | 高品質、フォトリアリスティック | 720/min | 高速 |
@cf/stabilityai/stable-diffusion-xl-base-1.0 | 汎用 | 720/min | 中速 |
@cf/lykon/dreamshaper-8-lcm | 芸術的、スタイライズされた画像 | 720/min | 高速 |
ビジョンモデル
| モデル | 最適な用途 | レート制限 |
|---|---|---|
@cf/meta/llama-3.2-11b-vision-instruct | 画像理解 | 720/min |
@cf/unum/uform-gen2-qwen-500m | 高速な画像キャプション生成 | 720/min |
一般的なパターン
パターン 1:履歴を使ったチャット補完
app.post('/chat', async (c) => {
const { messages } = await c.req.json<{
messages: Array<{ role: string; content: string }>;
}>();
const response = await c.env.AI.run('@cf/meta/llama-3.1-8b-instruct', {
messages,
stream: true,
});
return new Response(response, {
headers: { 'content-type': 'text/event-stream' },
});
});
パターン 2:RAG(検索拡張生成)
// Step 1: Generate embeddings
const embeddings = await env.AI.run('@cf/baai/bge-base-en-v1.5', {
text: [userQuery],
});
const vector = embeddings.data[0];
// Step 2: Search Vectorize
const matches = await env.VECTORIZE.query(vector, { topK: 3 });
// Step 3: Build context from matches
const context = matches.matches.map((m) => m.metadata.text).join('\n\n');
// Step 4: Generate response with context
const response = await env.AI.run('@cf/meta/llama-3.1-8b-instruct', {
messages: [
{
role: 'system',
content: `Answer using this context:\n${context}`,
},
{ role: 'user', content: userQuery },
],
stream: true,
});
return new Response(response, {
headers: { 'content-type': 'text/event-stream' },
});
パターン 3:Zod による構造化出力
import { z } from 'zod';
const RecipeSchema = z.object({
name: z.string(),
ingredients: z.array(z.string()),
instructions: z.array(z.string()),
prepTime: z.number(),
});
app.post('/recipe', async (c) => {
const { dish } = await c.req.json<{ dish: string }>();
const response = await c.env.AI.run('@cf/meta/llama-3.1-8b-instruct', {
messages: [
{
role: 'user',
content: `Generate a recipe for ${dish}. Return ONLY valid JSON matching this schema: ${JSON.stringify(RecipeSchema.shape)}`,
},
],
});
// Parse and validate
const recipe = RecipeSchema.parse(JSON.parse(response.response));
return c.json(recipe);
});
パターン 4:画像生成と R2 ストレージ
app.post('/generate-image', async (c) => {
const { prompt } = await c.req.json<{ prompt: string }>();
// Generate image
const imageStream = await c.env.AI.run('@cf/black-forest-labs/flux-1-schnell', {
prompt,
});
const imageBytes = await new Response(imageStream).bytes();
// Store in R2
const key = `images/${Date.now()}.png`;
await c.env.BUCKET.put(key, imageBytes, {
httpMetadata: { contentType: 'image/png' },
});
return c.json({
success: true,
url: `https://your-domain.com/${key}`,
});
});
AI Gateway の統合
AI Gateway は、AI リクエストのキャッシュ、ログ記録、分析を提供します。
セットアップ:
const response = await env.AI.run(
'@cf/meta/llama-3.1-8b-instruct',
{ prompt: 'Hello' },
{
gateway: {
id: 'my-gateway', // Your gateway ID
skipCache: false, // Use cache
},
}
);
メリット:
- ✅ コスト追跡 - リクエストごとのニューロン使用量を監視します
- ✅ キャッシュ - 重複する推論コストを削減します
- ✅ ログ記録 - AI リクエストをデバッグして分析します
- ✅ レート制限 - 保護をさらに強化します
- ✅ 分析 - リクエストのパターンとパフォーマンスを把握します
ゲートウェイログへのアクセス:
const gateway = env.AI.gateway('my-gateway');
const logId = env.AI.aiGatewayLogId;
// Send feedback
await gateway.patchLog(logId, {
feedback: { rating: 1, comment: 'Great response' },
});
レート制限と料金
レート制限(1 分あたり)
| タスクの種類 | デフォルトの上限 | 備考 |
|---|---|---|
| テキスト生成 | 300/min | 一部の高速モデル:400-1500/min |
| テキスト埋め込み | 3000/min | BGE-large:1500/min |
| 画像生成 | 720/min | すべての画像モデル |
| ビジョンモデル | 720/min | 画像理解 |
| 翻訳 | 720/min | M2M100、Opus MT |
| 分類 | 2000/min | テキスト分類 |
| 音声認識 | 720/min | Whisper モデル |
料金(ニューロンベース)
無料プラン:
- 1 日あたり 10,000 ニューロン
- 毎日 00:00 UTC にリセットされます
有料プラン:
- 1,000 ニューロンあたり $0.011
- 1 日あたり 10,000 ニューロンを含みます
- 無料割り当てを超えても使用量は無制限です
料金例:
| モデル | 入力(100 万トークン) | 出力(100 万トークン) |
|---|---|---|
| Llama 3.2 1B | $0.027 | $0.201 |
| Llama 3.1 8B | $0.088 | $0.606 |
| BGE-base の埋め込み | $0.005 | 該当なし |
| Flux 画像生成 | 約 $0.011/画像 | 該当なし |
本番環境へのデプロイ前チェックリスト
デプロイ前
- コスト追跡とログ記録のために AI Gateway を有効化 します
- すべてのテキスト生成エンドポイントに ストリーミングを実装 します
- 指数バックオフによる レート制限の再試行を追加 します
- トークン上限エラーを防ぐために 入力の長さを検証 します
- 適切なタイムアウトを設定 します(Workers:CPU のデフォルトは 30 秒、最大 5 分)
- Cloudflare ダッシュボードで ニューロン使用量を監視 します
- モデルが利用できない場合やレート制限時の エラー処理をテスト します
- プロンプトインジェクションを防ぐために 入力のサニタイズを追加 します
- ブラウザーから使用する場合は CORS を設定 します
- スケールを計画 します。必要に応じて有料プランにアップグレードします
エラー処理
async function runAIWithRetry(
env: Env,
model: string,
inputs: any,
maxRetries = 3
): Promise<any> {
let lastError: Error;
for (let i = 0; i < maxRetries; i++) {
try {
return await env.AI.run(model, inputs);
} catch (error) {
lastError = error as Error;
const message = lastError.message.toLowerCase();
// Rate limit - retry with backoff
if (message.includes('429') || message.includes('rate limit')) {
const delay = Math.pow(2, i) * 1000; // Exponential backoff
await new Promise((resolve) => setTimeout(resolve, delay));
continue;
}
// Other errors - throw immediately
throw error;
}
}
throw lastError!;
}
監視
app.use('*', async (c, next) => {
const start = Date.now();
await next();
// Log AI usage
console.log({
path: c.req.path,
duration: Date.now() - start,
logId: c.env.AI.aiGatewayLogId,
});
});
OpenAI 互換性
Workers AI は OpenAI 互換のエンドポイントをサポートしています。
OpenAI SDK の使用:
import OpenAI from 'openai';
const openai = new OpenAI({
apiKey: env.CLOUDFLARE_API_KEY,
baseURL: `https://api.cloudflare.com/client/v4/accounts/${env.CLOUDFLARE_ACCOUNT_ID}/ai/v1`,
});
// Chat completions
const completion = await openai.chat.completions.create({
model: '@cf/meta/llama-3.1-8b-instruct',
messages: [{ role: 'user', content: 'Hello!' }],
});
// Embeddings
const embeddings = await openai.embeddings.create({
model: '@cf/baai/bge-base-en-v1.5',
input: 'Hello world',
});
エンドポイント:
/v1/chat/completions- テキスト生成/v1/embeddings- テキスト埋め込み
Vercel AI SDK の統合
npm install workers-ai-provider ai
import { createWorkersAI } from 'workers-ai-provider';
import { generateText, streamText } from 'ai';
const workersai = createWorkersAI({ binding: env.AI });
// Generate text
const result = await generateText({
model: workersai('@cf/meta/llama-3.1-8b-instruct'),
prompt: 'Write a poem',
});
// Stream text
const stream = streamText({
model: workersai('@cf/meta/llama-3.1-8b-instruct'),
prompt: 'Tell me a story',
});
制限の概要
| 機能 | 上限 |
|---|---|
| 同時リクエスト数 | ハードリミットなし(レート制限は適用されます) |
| 入力トークンの最大数 | モデルによって異なります(通常 2K-128K) |
| 出力トークンの最大数 | モデルによって異なります(通常 512-2048) |
| ストリーミングチャンクのサイズ | 約 1 KB |
| 画像サイズ(出力) | 約 5 MB |
| リクエストのタイムアウト | Workers のタイムアウトが適用されます(デフォルト 30 秒、CPU の最大値 5 分) |
| 1 日あたりの無料ニューロン数 | 10,000 |
| レート制限 | 「レート制限と料金」セクションを参照してください |
参考資料
コメント
Markdown 対応