跳转到内容
本站为社区维护的非官方中文翻译,与 Cloudflare, Inc. 无关联。本站不提供账户登录,请勿在任何非官方站点输入您的 Cloudflare 账户信息。官方文档:developers.cloudflare.com

Pi AI

最后更新 查看 MarkdownAgent 设置

agents/models/pi-ai 是面向 Workers AI 与 AI Gateway 的 Pi AI ↗ 提供程序。它与 AI SDK 提供程序 使用相同的 createAI 工厂函数与选项,并返回 Pi AI Model 对象。可与 Pi AI 的 stream 和 complete、Pi Durable ↗、Pi 执行框架,或任何基于 Pi AI Models 注册表构建的框架一起使用。

安装

此提供程序需要 @earendil-works/pi-ai@~1.4.0,这是 agents 的可选 peer dependency:

npm i agents @earendil-works/pi-ai

将 AI 绑定添加到 Wrangler 配置:

{
    "ai": {
        "binding": "AI",
    },
}
[ai]
binding = "AI"

若要在另一个账户中使用网关,或从 Worker 外部调用,请传入 accountId 和 apiToken,而不是 binding。其他设置相同,网关默认值仍为 default:

const ai = createAI({
    accountId: "<ACCOUNT_ID>",
    apiToken: env.CLOUDFLARE_API_TOKEN,
    gateway: "my-gateway",
});

使用 Workers AI Read 和 AI Gateway Run 权限创建 API 令牌。令牌只会发送到 AI Gateway REST API 和 gateway.ai.cloudflare.com。

调用模型

提供程序携带 Pi AI 的入口点,因此不会在全局注册任何内容:

import { createAI } from "agents/models/pi-ai";

export default {
	async fetch(request, env) {
		const ai = createAI({ binding: env.AI });

		const reply = await ai.complete(ai("@cf/zai-org/glm-5.3-flash"), {
			messages: [{ role: "user", content: "Hello", timestamp: Date.now() }],
		});

		// `content` holds text, thinking, and tool call parts.
		const text = reply.content
			.filter((part) => part.type === "text")
			.map((part) => part.text)
			.join("");

		return Response.json({ text });
	},
};
import { createAI } from "agents/models/pi-ai";

export default {
    async fetch(request: Request, env: Env) {
        const ai = createAI({ binding: env.AI });

        const reply = await ai.complete(ai("@cf/zai-org/glm-5.3-flash"), {
            messages: [{ role: "user", content: "Hello", timestamp: Date.now() }],
        });

        // `content` holds text, thinking, and tool call parts.
        const text = reply.content
            .filter((part) => part.type === "text")
            .map((part) => part.text)
            .join("");

        return Response.json({ text });
    },
};

ai.stream() 返回 Pi AI 的 AssistantMessageEvent 流。ai.completeSimple() 与 ai.streamSimple() 接受 Pi AI 的简单选项,例如 reasoning 级别与 maxTokens:

const model = ai("anthropic/claude-opus-5.5");
const context = {
    messages: [{ role: "user", content: "Hi", timestamp: Date.now() }],
};

for await (const event of ai.stream(model, context)) {
    // text_delta, thinking_delta, toolcall_*, done, error
}

await ai.completeSimple(model, context, { reasoning: "low" });

ai.streamFn 是绑定后的 streamSimple,供接受 stream 函数的框架使用,例如 pi-agent-core 的 Agent({ streamFn })。

命名模型

模型有四种命名方式:

import { createAI } from "agents/models/pi-ai";
import { getBuiltinModel } from "@earendil-works/pi-ai/providers/all";

const ai = createAI({ binding: env.AI, id: "my-gateway" });

// 1. A Workers AI model, by its @cf/ id.
ai("@cf/zai-org/glm-5.3-flash");

// 2. An AI Gateway dynamic route, by dynamic/<route>.
ai("dynamic/support");

// 3. A model from Pi AI's Cloudflare AI Gateway catalog, by <provider>/<id>.
ai("anthropic/claude-opus-5.5");
ai("openai/gpt-5.4");

// 4. Any Pi AI model object, from any Pi AI registry.
ai(getBuiltinModel("anthropic", "claude-opus-5-5"));

任何其他字符串都会抛出 TypeError。提供程序不会猜测前缀含义。

动态路由会在你创建它的网关下通过 env.AI.run() 运行,因此请设置该网关的 id。路由会选择模型,并以 chat completions 格式返回响应。它接受与 Workers AI ID 相同的元数据默认值和覆盖项。

目录 ID 使用 AI Gateway 目录中的拼写,例如 anthropic/claude-opus-5.5。Pi AI 自己的列表会按 Anthropic 的方式拼写 Claude ID(claude-opus-5-5),因此提供程序会按目录中的拼写列出它们。供应商注册表中的模型对象则保留供应商自己的拼写。

第三种和第四种形式会保留 Pi AI 的模型元数据,包括 api、compat、thinkingLevelMap、成本、上下文窗口和最大令牌数。这些元数据决定了向各供应商请求推理的方式。例如,Claude Opus 会收到 thinking: { type: "adaptive" },GPT-5 会收到 reasoning.effort。ai(model) 不会更改你传入的对象。

第三方模型会通过 AI Gateway 路由;网关通过统一计费或存储在网关上的密钥保管凭据。你的 Worker 不会持有供应商密钥。统一计费要求在网关上进行身份验证。

与 Pi 执行框架一起使用

Pi Durable 的 Harness 接受 Pi AI Models 注册表。先在其中一个上注册提供程序,再将 ai() 的模型传给 Pi 执行框架:

import { createModels } from "@earendil-works/pi-ai/models";
import { createAI } from "agents/models/pi-ai";

const ai = createAI({ binding: env.AI });
const models = createModels();
models.setProvider(ai.provider);

// In PiHarness options:
// defaults: { model: ai("@cf/zai-org/glm-5.3-flash") }

// For one session:
await session.setModel(ai("anthropic/claude-opus-5.5"));

Pi 会话只存储模型的提供程序和 ID,然后在 Models 注册表中查找模型。请在此使用 @cf/、dynamic/ 和 <provider>/<id> 形式。这些形式属于你注册的 cloudflare 提供程序 (CLOUDFLARE_PROVIDER_ID)。模型对象会保留其供应商的提供程序 ID,而该注册表不认识此 ID。传递给 ai(model, options) 的选项不会传入会话。请改为在 createAI 上设置这些选项。

如果模型流中断,或在 streamIdleTimeoutMs 指定的时间内没有发送内容,Pi AI 的 isRetryableAssistantError() 会将其视为暂时性错误。Pi harness 会根据重试设置重新尝试此轮,而不是将其判定为失败。

提供程序的模型列表包含 Pi AI 认识的所有 Workers AI 模型,以及 Pi AI 的 AI Gateway 目录中的所有 <provider>/<id>。因此,models.getModel("cloudflare", "anthropic/claude-opus-5.5") 可以解析模型。

缓存、标记与超时请求

网关选项可放在 createAI、模型或调用上。它们可以扁平,也可以嵌套在 gateway 下:

const ai = createAI({ binding: env.AI, id: "prod", cacheTtl: 60 });

const model = ai("anthropic/claude-opus-5.5", {
    cacheTtl: 3600,
    cacheKey: "greeting-v1",
    metadata: { team: "growth" },
    eventId: "turn-17",
    requestTimeoutMs: 30_000,
    retries: { maxAttempts: 3, backoff: "exponential", retryDelayMs: 500 },
    byokAlias: "production",
});

选项与 AI SDK 提供程序的选项相同:id、skipCache、cacheTtl、cacheKey、collectLog、metadata、eventId、requestTimeoutMs、retries、byokAlias、zdr、fallback、headers、sessionAffinity、reasoningEffort 和 chatTemplateKwargs。vendorKey 仅适用于 AI SDK。

当网关为某个提供程序保管多个密钥时,byokAlias 会按别名选择一个已存储密钥。对于目录模型和模型对象,提供程序会将别名作为 cf-aig-byok-alias 发送。zdr 可为统一计费请求启用或停用零数据保留。它仅适用于 Pi AI 网关目录之外的模型对象,因为目录模型不会读取此选项。

Pi AI 自己的调用选项会映射到它们。headers 最后合并,metadata 加入网关元数据,sessionId 设置会话亲和性,reasoning 通过模型自己的 thinkingLevelMap 映射。调用选项优先于模型选项,后者优先于 createAI。

@cf/ 模型还接受 Pi AI 元数据覆盖:name、contextWindow、maxTokens、reasoning、input、cost 与 streamIdleTimeoutMs。Pi AI 未列出的 Workers AI ID 会以 128,000 token 上下文窗口、8,192 输出 token 与零成本解析,因此在你知道真实值时请传入覆盖。

Pi AI 模型是普通数据。每个模型的选项以 symbol 键存储,JSON.stringify 与 structuredClone 会丢弃它们。存储后再读回的模型仍会路由到其厂商,但会丢失选项。加载后请用 ai(model, options) 再次传入。

回退到另一模型

ai(getBuiltinModel("anthropic", "claude-opus-5-5"), {
    fallback: ["@cf/zai-org/glm-5.3-flash"],
});

回退模型可以是 Workers AI ID、动态路由、<provider>/<id> 字符串或模型对象。提供程序会按顺序尝试这些模型。如果某个流在产生任何输出前以 error 结束,就会继续尝试下一个模型。一旦模型产生输出,其响应即为最终结果。

应答消息带有 cloudflare-fallback 诊断,列出失败的尝试,message.model 标识实际应答的模型。

回退模型使用该链的网关选项。以 @cf/ ID 命名的回退模型没有自己的选项,因此也会采用链的 headers、会话亲和性与 Workers AI 选项。它不会采用链的模型元数据,例如 cost 或 contextWindow。

读取网关元数据

每条 assistant 消息都有带有其响应网关详情的 cloudflare 诊断:

const message = await ai.complete(model, context);
const cloudflare = message.diagnostics?.find(
    (d) => d.type === "cloudflare",
)?.details;
// { model, gateway, provider?, specifier?, logId?, eventId?, cacheStatus?,
//   step?, traceId?, runId? }

失败的请求以 error 事件结束流。其消息带有包含 status、code 与 logId 的 cloudflare-error 诊断。onResponse 会收到每个请求的状态与头。

网关自身的失败(例如缺失网关或未付费账户)会变成 CloudflareAIError。来自厂商的错误会按厂商发送的原样返回。

恢复中断的流

通过绑定发送的目录模型或动态路由流在连接断开后会恢复。无需进行任何配置。

AI Gateway 会在 cf-aig-run-id 标头中为每次流式运行命名,并保留其事件。如果连接断开,提供程序会通过绑定重新连接,并从最后一个完整事件开始重放该运行。流会继续传输,不会丢失或重复内容。

如果单个流中断 5 次,或网关不再保留该运行,提供程序就会放弃恢复。运行结束后,网关会保留运行信息几分钟。中止调用后不会恢复。Workers AI @cf/ 流以及目录之外的模型对象没有运行 ID,因此不会恢复。运行 ID 会显示在 cloudflare 诊断信息的 runId 中。

请求如何路由

提供程序会通过 AI 绑定路由每个请求,或通过 HTTP 和账户 ID、API 令牌路由:

模型 api 通过绑定 使用账户 ID 和令牌
@cf/ 模型和动态路由 cloudflare-ai env.AI.run(),带 Cloudflare 兼容层 AI Gateway REST API,并使用相同的兼容层
来自 Pi AI 网关目录的 Anthropic 模型 anthropic-messages env.AI.run() 将请求发送到 AI Gateway,使用 Anthropic Messages 格式 REST API 的 /ai/v1/messages,使用相同格式
来自 Pi AI 网关目录的 OpenAI 模型 openai-responses env.AI.run() 将请求发送到 AI Gateway,使用 OpenAI Responses 格式 REST API 的 /ai/v1/responses,使用相同格式
任何其他模型对象,例如 Anthropic、OpenAI 或 Groq 其自身的 api 绑定的 fetch 会请求 AI Gateway 的供应商原生端点 gateway.ai.cloudflare.com,即供应商原生端点

来自 Pi AI Cloudflare AI Gateway 目录的模型会使用其目录 ID,通过 env.AI.run() 以模型原生格式运行。AI Gateway 不会进行转换,因此 Pi AI 自身的流处理程序会读取响应。网关会选择提供程序,并通过统一计费或存储在网关上的密钥计费。

任何其他模型对象都会通过绑定的 fetch 请求 AI Gateway 的供应商原生端点。提供程序会根据模型 baseUrl 的主机名确定网关提供程序。Pi AI 自带的转换器会构建供应商请求正文,Pi AI 则解析供应商的响应流。

无论采用哪种方式,供应商凭据都不会离开 Worker。提供程序绝不会重写模型的 api、provider 或 id,因此推理签名和加密推理条目可在下一轮继续使用。

提供程序支持以下四种 api 值路由:cloudflare-ai、anthropic-messages、openai-responses 和 openai-completions。Pi AI 多个注册表中的模型使用其他值,目前无法路由,包括 mistral-conversations、google-generative-ai、google-vertex、amazon-bedrock、azure-openai-responses 和 openai-codex。此类模型的流会以 error 事件结束,并指出其 api。如果 AI Gateway 没有为模型 baseUrl 的主机名提供程序,模型流也会如此结束。

在 openai-completions 线路上,提供程序仅以 OpenAI 的 reasoning_effort 发送推理。若模型的 compat.thinkingFormat 是其他值(例如 deepseek、qwen 或 openrouter),其推理级别会被丢弃。消息上的 cloudflare-compat 诊断会记录该丢弃。若需要该厂商的思考格式,请使用 Pi AI 自己的提供程序。

reasoningEffort 与 chatTemplateKwargs 是 Workers AI 选项。在第三方模型上它们会被丢弃,并记录在 cloudflare-compat 诊断中。请改用 Pi AI 的 reasoning 级别。

生成图像

图像生成使用 Workers AI 模型:

const images = ai.images("@cf/black-forest-labs/flux-1-schnell", { steps: 8 });
const result = await ai.generateImages(images, {
    input: [{ type: "text", text: "A red bicycle" }],
});

flux-1-schnell 只接受 prompt 与 steps。对它而言,width、height、seed、guidance 与 negativePrompt 会被丢弃,并列在 cloudflare-compat 诊断中。目录中的其他图像模型接受所有这些选项。

相关资源

这篇文档对您有帮助吗?