Workers AI 与 AI Gateway

要点

  • 上一篇我们自己写了限流、用量统计、流式转发来搭 AI 网关
  • Workers AI 提供 50+ 开源模型,覆盖文本生成、文本嵌入(把文字变成向量,后面 RAG 章节会详细讲)、语音识别、图像生成等
  • AI Gateway 的定位更像「反向代理 + 中间件平台」
  • 回到第 18 篇那个「自己写限流 + 自己写用量统计」的网关
  • | 场景 | 选哪个 |

内容

1. Cloudflare 的两条 AI 路线

上一篇我们自己写了限流、用量统计、流式转发来搭 AI 网关。其实 Cloudflare 自己也提供了两套 AI 产品,直接长在 Workers 旁边,不用额外部署。

先区分它们:

产品你要做的事
Workers AI在 Cloudflare 自己的 GPU 节点上直接跑开源模型(Llama、Mistral、Qwen、Whisper、Flux……)
AI Gateway代理你调用第三方 LLM(OpenAI / Anthropic / Gemini / Workers AI / Replicate),顺手做缓存、限流、分析

前者是「让 Cloudflare 帮你跑模型」;后者是「让 Cloudflare 在你和模型之间加一层」。两件事不冲突,真实项目里经常一起用。

这一篇分别讲清楚它们怎么用,最后把上一篇的网关改造一遍,看看 AI Gateway 能省掉多少代码。

2. Workers AI:在边缘跑开源模型

Workers AI 提供 50+ 开源模型,覆盖文本生成、文本嵌入(把文字变成向量,后面 RAG 章节会详细讲)、语音识别、图像生成等。用 binding 的方式挂到 Worker 上,像调函数一样调用。

几个常用的模型 ID:

任务模型 ID
文本生成(中等)@cf/meta/llama-3.1-8b-instruct
文本生成(大)@cf/meta/llama-3.1-70b-instruct
推理能力@cf/qwen/qwen3-30b-a3b-fp8
文本嵌入(768 维)@cf/baai/bge-base-en-v1.5
文本嵌入(1024 维)@cf/baai/bge-large-en-v1.5
语音转文字@cf/openai/whisper
图像生成@cf/black-forest-labs/flux-1-schnell

模型 ID 的命名规律很清晰:@cf/<提供方>/<模型名>

2.1 绑定 AI

wrangler.jsonc 里加上:

// wrangler.jsonc
{
 
  "ai": {
 
    "binding": "AI"
 
  }
 
}

只需要一个 binding 名称,不需要 ID。Workers AI 不像 KV/D1 那样一个账号下可以开多个实例——它是账号级的统一服务,一个 binding 就够了。

2.2 在 Hono 里调用

// src/index.ts
import { Hono } from 'hono'
 
type Bindings = {
 
  AI: Ai  // Cloudflare Workers 内置的全局类型,不需要额外 import
 
}
 
const app = new Hono<{ Bindings: Bindings }>()
 
// 文本生成
 
app.post('/generate', async (c) => {
 
  const { prompt } = await c.req.json()
 
  const result = await c.env.AI.run('@cf/meta/llama-3.1-8b-instruct', {
 
    messages: [
 
      { role: 'system', content: '你是一个中文技术写作助手。' },
 
      { role: 'user', content: prompt },
 
    ],
 
  })
 
  return c.json(result)
 
})
 
export default app

c.env.AI.run(modelId, input) 就是 Workers AI 的核心调用方式。input 的结构取决于模型类型:文本模型传 &#123; messages: [...] &#125;(和 OpenAI 很像),嵌入模型传 &#123; text: ['要嵌入的文本'] &#125;,图像生成传 &#123; prompt: '一只猫' &#125;

2.3 流式输出

文本模型支持 SSE 流式,加一个 stream: true 就行。Workers AI 返回的流本身就是标准 SSE 格式,用 Hono 的 streamText 原样透传即可:

// src/index.ts
import { streamText } from 'hono/streaming'
 
app.post('/generate-stream', async (c) => {
 
  const { prompt } = await c.req.json()
 
  const stream = await c.env.AI.run('@cf/meta/llama-3.1-8b-instruct', {
 
    messages: [{ role: 'user', content: prompt }],
 
    stream: true,
 
  })
 
  return streamText(c, async (textStream) => {
 
    const reader = (stream as ReadableStream).getReader()
 
    const decoder = new TextDecoder()
 
    while (true) {
 
      const { done, value } = await reader.read()
 
      if (done) break
 
      // Workers AI 流式输出就是标准的 SSE 格式,原样写回去就行
 
      await textStream.write(decoder.decode(value, { stream: true }))
 
    }
 
  })
 
})

2.4 为什么选 Workers AI

跟直接调 OpenAI 比,Workers AI 的优势在于:

  1. 延迟低:模型跑在 Cloudflare 的边缘节点上,Worker 调模型走内网,省掉了到第三方 API 的公网往返
  2. 按量计费:不需要自己维护 GPU,也没有月租,用多少算多少
  3. 有免费额度:每天 10,000 个「Neurons」(Cloudflare 的推理计量单位),个人项目基本够用

限制也很明显:模型都是开源的,没有 GPT-4o / Claude Opus 这种顶级闭源模型。要用那些还是得走 AI Gateway。

3. AI Gateway:给第三方 LLM 调用加一层

AI Gateway 的定位更像「反向代理 + 中间件平台」。你原来怎么调 OpenAI,把请求地址换一下,自动获得:

  • 缓存:相同 prompt 在 TTL 内直接返回,不再花 token
  • 限流:按请求数或 token 数限速,防止失控的调用
  • 分析:Dashboard 里看每个请求、token 消耗、延迟、错误率
  • 重试与降级:模型超时或 429 自动重试、切换到备用模型
  • 日志:完整的 prompt + response 记录(可关,有隐私需求时)

支持的模型提供方:OpenAI、Anthropic、Google Gemini、Workers AI、Replicate、Groq、DeepSeek 等。

3.1 创建 Gateway

在 Cloudflare Dashboard → AI → AI Gateway 里点「Create Gateway」,给它起个名字(比如 my-gateway)。创建完你会拿到两个东西:

  • account_id(账号 ID)
  • gateway_id(你刚起的那个名字)

然后 Gateway 的访问端点就是:

// code.ts
https://gateway.ai.cloudflare.com/v1/{account_id}/{gateway_id}/

后面加上具体提供方路径,比如 openai/chat/completionsanthropic/v1/messages

3.2 把现有 OpenAI 调用接进去

openai 官方 SDK 为例,改动量最小:

// src/lib/openai.ts
import OpenAI from 'openai'
 
export function createOpenAI(env: {
 
  OPENAI_API_KEY: string
 
  CF_ACCOUNT_ID: string
 
  CF_GATEWAY_ID: string
 
  CF_API_TOKEN: string  // Cloudflare API Token,在 Dashboard 的 My Profile → API Tokens 里创建
 
}) {
 
  return new OpenAI({
 
    apiKey: env.OPENAI_API_KEY,
 
    // 把 baseURL 指到 Cloudflare Gateway 的 /compat 端点
 
    baseURL: `https://gateway.ai.cloudflare.com/v1/${env.CF_ACCOUNT_ID}/${env.CF_GATEWAY_ID}/compat`,
 
    // 加一个 Cloudflare 的 token 用于识别账号
 
    defaultHeaders: {
 
      'cf-aig-authorization': `Bearer ${env.CF_API_TOKEN}`,
 
    },
 
  })
 
}

只改了两行:baseURL 指到 gateway,defaultHeaderscf-aig-authorization。你的调用代码(client.chat.completions.create(...))完全不用动。

3.3 统一入口:同一个端点调多家

/compat 端点是 AI Gateway 的「OpenAI 协议兼容层」。你可以用同一套代码同时调 OpenAI、Anthropic、Gemini——只要在 model 字段里带上前缀:

// src/routes/chat.ts
const messages = [{ role: 'user', content: '你好' }] as const
 
// 走 OpenAI
 
await openai.chat.completions.create({
 
  model: 'openai/gpt-4o-mini',
 
  messages,
 
})
 
// 走 Anthropic,同一个 SDK
 
await openai.chat.completions.create({
 
  model: 'anthropic/claude-haiku-4-5',
 
  messages,
 
})
 
// 走 Workers AI
 
await openai.chat.completions.create({
 
  model: 'workers-ai/@cf/meta/llama-3.1-8b-instruct',
 
  messages,
 
})

对后端来说这相当实用——前端只需要告诉后端「用哪个模型」,后端完全不用管具体对接哪家 SDK。

4. 用 AI Gateway 改造第 18 篇的网关

回到第 18 篇那个「自己写限流 + 自己写用量统计」的网关。大部分能力 AI Gateway 自带,我们把重叠的部分卸掉。

之前需要自己写的(第 18 篇)

  • 限流中间件(用 KV 做固定窗口)
  • 用量统计(每次请求后写 KV)
  • 重试逻辑(没写)
  • 缓存(没写)
  • 日志(只有 console.log

改造后

// src/routes/chat.ts
import { Hono } from 'hono'
 
import OpenAI from 'openai'
 
import { streamSSE } from 'hono/streaming'
 
import type { AppEnv } from '../types'
 
const chat = new Hono<AppEnv>()
 
chat.post('/v1/chat/completions', async (c) => {
 
  const body = await c.req.json()
 
  const client = new OpenAI({
 
    apiKey: c.env.OPENAI_API_KEY,
 
    baseURL: `https://gateway.ai.cloudflare.com/v1/${c.env.CF_ACCOUNT_ID}/${c.env.CF_GATEWAY_ID}/openai`,
 
    defaultHeaders: {
 
      'cf-aig-authorization': `Bearer ${c.env.CF_API_TOKEN}`,
 
      // 用自定义 header 打标签,方便在 Dashboard 区分
 
      'cf-aig-metadata': JSON.stringify({
 
        userId: c.get('apiKeyId'),
 
      }),
 
    },
 
  })
 
  const stream = await client.chat.completions.create({
 
    ...body,
 
    stream: true,
 
  })
 
  return streamSSE(c, async (sseStream) => {
 
    for await (const chunk of stream) {
 
      await sseStream.writeSSE({
 
        data: JSON.stringify(chunk),
 
        event: 'message',
 
      })
 
    }
 
    await sseStream.writeSSE({ data: '[DONE]', event: 'message' })
 
  })
 
})
 
export default chat

比第 18 篇少了大概 80 行代码,而且功能更全:缓存、限流、重试、token 统计、延迟分布、错误归类,都能在 Cloudflare Dashboard 里看到。

4.1 在 Dashboard 里配限流和缓存

AI Gateway 的配置都在 Dashboard 点两下:

  • Caching:打开开关,设 TTL(比如 1 小时),相同 prompt 在 TTL 内免费返回
  • Rate Limiting:按 IP 或自定义 header 限速,可以配多条规则
  • Logs:默认记录请求和响应,可以关(有用户隐私顾虑时)
  • Fallbacks:主模型 5xx 时自动切到备用模型

这些不用写代码,在 Dashboard 点开关配就行。自己用 KV 写限流、用 KV 记用量完全可以,但如果 AI Gateway 自带的能力已经够用,就没必要重复造。

4.2 cf-aig-metadata:给每个请求打标签

上面代码里 cf-aig-metadata 那一行值得单独提一下。你可以往里塞任意 JSON,字段会出现在 Dashboard 的日志里,方便过滤和统计:

// src/routes/chat.ts
defaultHeaders: {
 
  'cf-aig-authorization': `Bearer ${c.env.CF_API_TOKEN}`,
 
  'cf-aig-metadata': JSON.stringify({
 
    userId: c.get('apiKeyId'),
 
    feature: 'chat',
 
    plan: 'pro',
 
  }),
 
}

后续你想查「pro 用户这一周花了多少 token」「chat 功能的 p95 延迟是多少」,都能直接在 Dashboard 过滤。

5. 两条路线怎么选

场景选哪个
要跑开源模型、对成本极度敏感Workers AI
离线/隐私场景,数据不能出 CloudflareWorkers AI
需要 GPT-4o / Claude Opus 这种顶级模型第三方 SDK + AI Gateway
既要顶级模型,又要缓存、限流、日志第三方 SDK + AI Gateway
多模型路由(根据任务切不同模型)AI Gateway 的 /compat 端点
嵌入、语音、图像这类常规 AI 任务Workers AI

更常见的其实是两个一起用:核心对话走第三方顶级模型(通过 AI Gateway),embedding、分类、语音这些轻量任务走 Workers AI。

6. 小结

两条路线各管各的:

  • Workers AI:在边缘跑开源模型,c.env.AI.run(modelId, input) 一行搞定
  • AI Gateway:给第三方 LLM 调用加代理,缓存、限流、日志在 Dashboard 里配
  • 实际项目里经常一起用——重活(核心对话)走第三方顶级模型通过 Gateway,轻活(嵌入、分类)走 Workers AI

上一篇自己写了几十行的限流和用量统计,用 AI Gateway 可以直接省掉。什么时候用平台自带的能力、什么时候自己写,取决于你需要多细粒度的控制。