Skip to content

Workers AI 快速上手:用 Worker 发布受保护的模型接口

想给应用增加文本生成能力,直接在浏览器里调用 Cloudflare API 会暴露账户凭据。Workers AI 的 AI binding 让 Worker 从服务端调用模型;浏览器只接触你自己的业务接口。下面从一个 TypeScript Worker 开始,先在本地验证健康检查、拒绝未授权请求和模型调用,再决定是否将接口放到公网。Cloudflare 的入门路径使用同一 binding 和模型。

本教程按北京时间 2026-09-21(UTC 9 月 20 日)核对官方资料,没有登录账户、调用模型或执行远程部署。模型可用性、价格和配额按账户及时间变化,实际操作前查看模型目录价格说明。本地 wrangler dev 的 AI 推理也会访问 Cloudflare 账户并产生用量;/health 和未授权请求不调用模型。

前置条件

  • 一个 Cloudflare 账户和 Node.js 22 或更新版本;项目会安装 Wrangler,不需要全局安装。检查 node --versionnpm --version
  • 允许模型调用的账户计划与足够用量。Workers AI 推理额度和 Worker HTTP 请求额度是两套限制,不能相互抵扣。
  • 一个空的项目目录。以下命令只适用于示例项目,不要覆盖现有 Worker 的配置或 src/index.ts

创建项目与绑定模型

在准备存放新项目的目录运行官方 C3 脚手架:

sh
npm create cloudflare@latest -- hello-ai
cd hello-ai

按提示选择 Hello World exampleWorker onlyTypeScript,暂不部署。生成后确认 src/index.tswrangler.jsonc 存在。在 wrangler.jsonc 原有对象里合并下面的属性,保留脚手架生成的 namemaincompatibility_date 等字段:

jsonc
"ai": {
  "binding": "AI"
}

这里 AI 是代码中 env.AI 的绑定名称,不是 API Token。为了避免公开地址被任意调用,示例将业务密钥作为单独的 Worker Secret;不要把它放进 wrangler.jsonc 的明文 vars。在项目根目录将 src/index.ts 改成:

ts
interface Env {
  AI: Ai;
  APP_API_KEY: string;
}

const model = "@cf/google/gemma-4-26b-a4b-it";

export default {
  async fetch(request, env): Promise<Response> {
    const url = new URL(request.url);
    if (request.method === "GET" && url.pathname === "/health") {
      return Response.json({ ok: true, model });
    }
    if (request.method !== "POST" || url.pathname !== "/chat") {
      return new Response("Not found", { status: 404 });
    }
    if (!env.APP_API_KEY) {
      return Response.json({ error: "Server is not configured" }, { status: 503 });
    }
    if (request.headers.get("Authorization") !== `Bearer ${env.APP_API_KEY}`) {
      return Response.json({ error: "Unauthorized" }, { status: 401 });
    }
    const body = await request.json().catch(() => null) as { prompt?: unknown } | null;
    if (typeof body?.prompt !== "string" || !body.prompt.trim()) {
      return Response.json({ error: "prompt is required" }, { status: 400 });
    }
    if (body.prompt.length > 4000) {
      return Response.json({ error: "prompt is too long" }, { status: 413 });
    }
    try {
      return Response.json(await env.AI.run(model, {
        messages: [{ role: "user", content: body.prompt }],
        chat_template_kwargs: { enable_thinking: false },
      }));
    } catch (error) {
      console.error("Workers AI request failed", error);
      return Response.json({ error: "Model request failed" }, { status: 502 });
    }
  },
} satisfies ExportedHandler<Env>;

根据脚手架生成的 package.json 执行 npm run cf-typegennpx tsc --noEmit;类型生成脚本名称若变动,以当前项目为准。类型检查通过只说明代码与配置在本地匹配,不证明模型调用可用。

本地验收

先在密码管理器中生成并保存一个随机业务密钥。在项目根目录运行下面的命令,再从密码管理器把密钥粘贴到非回显提示中。密钥不会出现在命令历史;写文件的 umask 只在子 shell 生效,不会改变当前终端之后创建文件的权限:

sh
printf 'APP_API_KEY: ' >&2
IFS= read -rs APP_API_KEY
printf '\n' >&2
export APP_API_KEY
(umask 077; printf 'APP_API_KEY="%s"\n' "$APP_API_KEY" > .dev.vars)

官方 Secret 说明,在 .gitignore 中忽略 .dev.vars*.env*,提交前用 git status 确认没有纳入版本控制。不要同时在 .dev.vars.env 中放同一份本地密钥。运行 npx wrangler dev;登录正确的 Cloudflare 账户后,终端通常会给出 http://localhost:8787。模型推理仍走远端。

在另一个终端测试不消耗模型用量的两条路径:

sh
curl -i http://localhost:8787/health
curl -i -X POST http://localhost:8787/chat \
  -H 'Content-Type: application/json' \
  -d '{"prompt":"未授权请求"}'

预期依次为 HTTP 200(含模型 ID)和 401。上面的命令已经把同一随机值导出为当前终端的 APP_API_KEY;若打开了新终端,则从密码管理器通过同样的非回显 read 步骤恢复它,不要把实际值写进命令历史或文档。发送一次授权请求:

sh
curl -i -X POST http://localhost:8787/chat \
  -H "Authorization: Bearer ${APP_API_KEY}" \
  -H 'Content-Type: application/json' \
  -d '{"prompt":"用一句话介绍 Workers AI"}'

预期为 HTTP 200 和模型结果;只有这条请求会调用模型。若得到 502,查看 Wrangler 终端的上游错误,再核对模型目录、账户额度与错误说明;若得到 503,先检查当前环境的 Secret。完成后停止开发服务器,检查账户的 Workers AI 用量。

部署与回退

只有确认本地验收和模型成本后,才在自己的 Cloudflare 账户中运行以下命令。这些命令会创建或更新远程资源;本篇编写过程中没有执行。

sh
npx wrangler whoami
npx wrangler deploy
npx wrangler secret put APP_API_KEY

wrangler whoami 用来确认账户;未登录时先执行 npx wrangler login。部署返回 https://hello-ai.<子域名>.workers.dev 一类地址。代码首次部署时没有远程 Secret,POST /chat 应返回 503。运行 secret put 后,在 Wrangler 的交互提示中从密码管理器粘贴本地测试所用的同一随机值;该命令会立即部署新版本,不要将密钥作为 CLI 参数。当前终端的 APP_API_KEY 保持不变,因此可以用远程地址重复 /health、无授权 /chat、有授权 /chat 的 200/401/200 验收。Secret 文档明确了本地与远端的差异。验收结束执行 unset APP_API_KEY;这只清除当前 shell 变量,不会删除 .dev.vars 或远端 Secret。

生产接口还需要真实用户身份、按用户限流、请求体大小限制、费用告警与日志脱敏。单个共享业务密钥只适合试用,不能替代多用户鉴权。若新版本有问题,先通过 Worker 的 Deployments 回退到上一个正常版本并重复三项验收;不要用删除 Worker 代替回滚。

试用结束时选择一个明确状态:

  • 继续保留服务:远端 Secret 保留在 Worker,随机值继续由密码管理器管理;删除不再需要的本地 .dev.vars,执行 unset APP_API_KEY,并为共享密钥安排轮换。
  • 停止模型接口:运行 npx wrangler secret delete APP_API_KEY 并确认部署新版本,然后验证远端 POST /chat 返回 503;再删除本地 .dev.vars 并执行 unset APP_API_KEY。若整个 Worker 都不再需要,按Pages 与 Workers 安全退役教程先处理流量入口、日志和外围资源,再删除脚本。

secret delete 会立即部署新版本;执行前确认目标账户与 Worker。删除本地文件或清除 shell 变量都不会自动撤销远端 Secret,远端 503 才是本教程中模型接口已停用的成功信号。

常见问题

现象检查点
本地运行仍有推理用量wrangler dev 的 AI binding 仍访问云端;先只测 /health 和 401 分支。
/chat 返回 401 或 503分别核对客户端业务密钥、当前环境是否配置 APP_API_KEY
模型调用返回 502查看 Wrangler 日志、模型 ID、账户计划、额度与上游状态;不要把原始错误回显给客户端。
远程端点被滥用立即限制入口、轮换业务密钥并检查用量;再补用户级鉴权和限流。

如果只需要后端脚本调用模型、不打算公开自己的 API,可改用官方 REST 路径;不要将 Cloudflare API Token 放进浏览器。已经有 Worker 的项目只需合并 AI binding、Secret 和路由逻辑,不必另建一份 Hello World。

参考资料

全部公开文章由同一个站点构建和发布。