跳转到内容

输入关键词开始搜索文档。

模型

最后更新 查看 Markdown 源文件

每个智能体同时只由一个 LLM 驱动,通过 useModel() 声明——这是 Flue 中唯一的必需 hook。本指南涵盖选择模型、调优调用方式、更改何时生效、提供提供商凭据,以及连接 Flue 开箱即用不认识的提供商。

声明模型

在你的智能体函数体内使用模型说明符字符串调用 useModel():

src/agents/triage.ts
'use agent';
import { useModel } from '@flue/runtime';

export function TriageAgent() {
  useModel('anthropic/claude-sonnet-4-6');
  return '调查报告的问题并推荐下一步操作。';
}

useModel() 是一个声明,而非客户端:它不返回任何东西,你永远不需要构造 SDK 对象或通过智能体代码传递 API 密钥。你命名模型;Flue 拥有连接、认证、流式传输和重试。

两条规则:

  • 该调用是必需的。 没有 useModel() 调用的智能体渲染无法启动。
  • 每次渲染只调用一次。 一个智能体有一个模型。参数 可以在不同渲染之间变化(更多内容见下文),但调用本身不能消失或重复。

该调用可以放在智能体体内或体内的自定义 hook 中。唯一不能使用的地方是子智能体渲染——委托的模型在其 useSubagent() 定义上设置,未设置时继承父模型。参见子智能体。

模型说明符

模型说明符是 'provider-id/model-id' 格式的纯字符串。第一个 / 之前的所有内容命名提供商;其余是提供商自己的模型 ID,其中可能包含斜杠:

  • anthropic/claude-sonnet-4-6 ——提供商 anthropic,模型 claude-sonnet-4-6
  • openai/gpt-5.5 ——提供商 openai,模型 gpt-5.5
  • openrouter/moonshotai/kimi-k2.6 ——提供商 openrouter,模型 moonshotai/kimi-k2.6
  • cloudflare/@cf/moonshotai/kimi-k2.6 ——提供商 cloudflare,模型 @cf/moonshotai/kimi-k2.6

Flue 根据运行时注册的提供商解析说明符。默认情况下,这是来自 Pi 的完整内置集合,包含了主要提供商——anthropic、openai、google、amazon-bedrock、google-vertex、groq、mistral、xai、deepseek、cerebras、together、fireworks、openrouter 等。每个提供商的目录条目包含模型的线协议、端点、上下文窗口大小、输出令牌限制、费用率、推理支持和接受的输入模态。该元数据决定了压缩何时触发、思考级别是否到达线路,以及模型是否可以接受图像。

要只包含你实际使用的提供商,在 flue() 插件配置中列出它们——生成的服务器入口随后只导入这些工厂,其他任何内容都不会进入构建:

vite.config.ts
flue({ providers: ['anthropic', 'openai'] });

设置了 providers 列表后,命名任何其他提供商的说明符在解析时会失败——该列表是穷尽的,因此在 Cloudflare 目标上,当你的智能体使用 cloudflare/... 模型时,请包含 'cloudflare'。省略该字段以保留完整集合。参见提供商 API 参考了解确切语义。

未知的说明符会快速失败:运行在发送任何请求之前就因未解析的提供商和模型 ID 而报错。要教会 Flue 一个内置提供商不服务的说明符——本地模型、代理、全新发布——请自行注册提供商;参见自定义提供商。

在 Cloudflare 目标上,还有一个额外的内置提供商 ID:cloudflare/... 模型说明符在 Workers AI 上运行,完全不需要 API 密钥。

模型推理强度

useModel() 接受一个选项对象作为第二个参数,包含两个字段:thinkingLevel 和 compaction。

useModel('anthropic/claude-opus-4-6', {
  thinkingLevel: 'high',
  compaction: { keepRecentTokens: 16000 },
});

thinkingLevel 设置智能体模型调用的默认推理强度:'off'、'minimal'、'low'、'medium'、'high'、'xhigh' 或 'max'。未设置时,运行时使用 'medium'。

更高的级别以延迟和令牌为代价增加推理深度;'off' 完全禁用扩展思考。该值是_默认值_:个别操作可以覆盖它——子智能体定义可以固定自己的 thinkingLevel,编程式的 harness.prompt(...) 调用接受每次操作一个。

思考只对标记为支持推理的模型到达线路。目录模型已携带该标志,但如果你注册自定义提供商并跳过其 reasoning 元数据,转发的 thinkingLevel 会被静默丢弃。参见自定义提供商。

压缩

智能体对话可能比任何上下文窗口都长。当对话接近模型的限制时,Flue 自动压缩它:较旧的历史被折叠成摘要,而最近的消息保持原文,对话继续。compaction 选项调优该行为:

useModel('anthropic/claude-opus-4-6', {
  compaction: {
    // 提前或延后触发:当已用令牌超过 contextWindow - reserveTokens 时运行压缩。
    // 默认:模型感知,≤ 20000。
    reserveTokens: 30000,
    // 多少最近的历史保持原文。默认:8000。
    keepRecentTokens: 16000,
    // 使用比会话运行的模型更便宜的模型进行摘要。
    model: 'anthropic/claude-haiku-4-5',
  },
});

所有三个字段都是可选的;每个都覆盖模型感知的默认值。设置 compaction.model 将摘要卸载到更便宜的模型。

传递 compaction: false 禁用_阈值_压缩——自动触发器。溢出恢复和显式的 harness.compact() 调用在对话不再适合时仍然会压缩。完整的字段参考在 CompactionConfig。

在对话中途更改模型

智能体函数在每次模型调用之前重新渲染,useModel() 每次都会再次运行——因此说明符可以是计算的,而非常量。一个常见的模式是升级,其中持久状态将智能体从便宜的模型移到强大的模型:

src/agents/reviewer.ts
'use agent';
import { useModel, usePersistentState, useTool } from '@flue/runtime';

export function Reviewer() {
  const [escalated, setEscalated] = usePersistentState('escalated', false);
  useModel(escalated ? 'anthropic/claude-opus-4-6' : 'anthropic/claude-haiku-4-5');

  useTool({
    name: 'escalate_review',
    description: '当更改太复杂无法快速审查时升级。',
    async run() {
      setEscalated(true);
      return '已升级。更强的模型将接手。';
    },
  });

  return '审查提议的更改并留下可操作的反馈。';
}

模型、思考级别和压缩设置是提交范围的:运行时在智能体唤醒以处理已接受的输入(一次_提交_——参见持久性)时读取它们一次。运行中途重新渲染计算的不同值会锁存并在_下一次_提交时生效,而非在当前提交的中途。在上面的例子中,触发 escalate_review 的响应在便宜的模型上完成;对话的下一条消息在强大的模型上运行。

dispatch(...) 或 HTTP 接口上没有每消息的模型参数:模型选择属于智能体函数。

提供商凭据

模型提供商通过 API 密钥认证,运行时从环境解析它们——你的智能体代码永远不处理它们。

本地开发

将密钥放在项目根目录的 .env 文件中,使用每个提供商期望的变量名:

.env
ANTHROPIC_API_KEY="sk-ant-..."
OPENAI_API_KEY="sk-..."
GEMINI_API_KEY="..."

anthropic 读取 ANTHROPIC_API_KEY,openai 读取 OPENAI_API_KEY,google 读取 GEMINI_API_KEY,groq 读取 GROQ_API_KEY——该模式在所有提供商中适用(参见 Pi 的提供商文档 了解完整列表)。两个本地入口点都为你加载文件,shell 导出的值始终优先于文件值:

  • flue run 加载项目根目录的 .env;传递 --env <path> 选择一个替代文件。
  • vite dev 加载 Vite 的标准文件集:.env、.env.local、.env.<mode>、.env.<mode>.local。

不要提交 .env 文件。

部署环境

部署后的服务器只读取真实环境——没有 .env 加载:

  • Node.js ——通过主机的密钥机制将密钥作为进程环境变量提供。参见 Node.js 目标——环境和密钥。
  • Cloudflare ——将每个密钥添加为 Worker 密钥(npx wrangler secret put ANTHROPIC_API_KEY);在本地,.dev.vars 扮演 .env 的角色。参见 Cloudflare 部署指南。

当环境变量约定不适合时——一个有自己凭据的网关、一个在代码中给你值的密钥管理器——在自定义提供商上声明凭据:提供商的 auth.apiKey.resolve() 返回你的代码产生的任何东西,并且它每次请求运行,因此轮换凭据也可以工作。

自定义提供商

提供商是 Pi 自己的对象,Flue 直接接受它们:用 Pi 的 createProvider()(或任何提供商工厂)构建一个,并在 app.ts 的模块顶层、任何智能体运行之前交给 setProvider()。由于你的代码现在直接导入 Pi,请将其添加到项目的依赖中:npm install @earendil-works/pi-ai。注册按提供商的 id 键控,每次调用替换该 ID 的先前提供商——包括内置的,因此覆盖 anthropic 只需在该 ID 下注册你自己的提供商。一个放置注意事项:flue run 只加载智能体模块,不加载 app.ts——当智能体也必须在 flue run 下工作时,请将注册放在智能体模块中。

任何 OpenAI 或 Anthropic 兼容的端点都可以工作。这是一个本地 Ollama 服务器:

src/app.ts
import { createProvider, envApiKeyAuth } from '@earendil-works/pi-ai';
import { openAICompletionsApi } from '@earendil-works/pi-ai/api/openai-completions.lazy';
import { setProvider } from '@flue/runtime';

setProvider(
  createProvider({
    id: 'ollama',
    // 无密钥本地服务器;使用 envApiKeyAuth('...', ['MY_KEY']) 处理真实密钥。
    auth: { apiKey: { name: 'Ollama (keyless)', resolve: async () => ({ auth: {} }) } },
    models: [
      {
        id: 'llama3.1:8b',
        name: 'Llama 3.1 8B (local)',
        api: 'openai-completions',
        provider: 'ollama',
        baseUrl: 'http://localhost:11434/v1',
        reasoning: false,
        input: ['text'],
        cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
        contextWindow: 128000,
        maxTokens: 8192,
      },
    ],
    api: openAICompletionsApi(),
  }),
);
src/agents/local-assistant.ts
useModel('ollama/llama3.1:8b');

提供商声明其模型,运行时信任该元数据:reasoning: false 意味着 thinkingLevel 被静默丢弃,input: ['text'] 意味着附加的图像被替换为”(image omitted)“占位符,contextWindow: 0 读作未知,因此阈值压缩无法启用。

将内置提供商路由到网关或代理是同样的操作——在内置的 ID 下注册你自己的提供商,用你的端点和凭据复用其目录模型:

src/app.ts
import { createProvider } from '@earendil-works/pi-ai';
import { anthropicMessagesApi } from '@earendil-works/pi-ai/api/anthropic-messages.lazy';
import { anthropicProvider } from '@earendil-works/pi-ai/providers/anthropic';
import { setProvider } from '@flue/runtime';

setProvider(
  createProvider({
    id: 'anthropic',
    auth: {
      apiKey: {
        name: 'Gateway key',
        resolve: async () => ({ auth: { apiKey: process.env.GATEWAY_KEY } }),
      },
    },
    models: anthropicProvider()
      .getModels()
      .map((model) => ({ ...model, baseUrl: 'https://gateway.example.com/anthropic' })),
    api: anthropicMessagesApi(),
  }),
);

智能体的说明符(anthropic/claude-sonnet-4-6)不会改变;费用、上下文窗口和能力元数据从目录中随行。当你需要时,Pi 的提供商协议可以走得更远——OAuth、动态模型发现、通过 api 字段的自定义线协议——所有内容都记录在 Pi 的提供商指南 中。Flue 自己的契约在提供商 API 参考中。

Cloudflare Workers AI(仅限 Cloudflare)

在 Cloudflare 目标上,cloudflare 提供商 ID 会自动注册,并在 Workers AI 上运行模型——无需 API 密钥,无需外部账户;授权和计费跟随 Worker,包括 Workers AI 定价和每日免费配额:

src/agents/assistant.ts
export function Assistant() {
  useModel('cloudflare/@cf/moonshotai/kimi-k2.6');
  return '帮助用户解决他们的问题。';
}

在项目的 Wrangler 配置中声明提供商使用的 AI 绑定:

wrangler.jsonc
{
  "$schema": "./node_modules/wrangler/config-schema.json",
  "ai": {
    "binding": "AI",
  },
}

cloudflare/ 之后的所有内容作为模型 ID 传递给 env.AI.run(...)。这可以是 Workers AI 模型 ID(如 @cf/moonshotai/kimi-k2.6),或绑定支持的 AI Gateway 模型 ID(如 openai/gpt-5.5),当 Worker 应通过 Cloudflare 的网关路径访问该模型时——cloudflare/openai/gpt-5.5 通过 Cloudflare 计费,而纯 openai/gpt-5.5 使用 Flue 的直接 OpenAI 提供商及其 API 密钥。

默认情况下,每个 cloudflare/... 调用都通过 Cloudflare 的 AI Gateway 路由,在仪表板中开箱即用地提供缓存、日志记录和预算控制。要定向到特定的网关、调优缓存和日志记录,或选择退出,请在 app.ts 中自行注册 cloudflare 提供商——你的注册优先于生成的默认值:

src/app.ts
import { setProvider } from '@flue/runtime';
import { cloudflareBindingProvider } from '@flue/runtime/cloudflare/workers-ai';
import { env } from 'cloudflare:workers';

setProvider(
  cloudflareBindingProvider({
    binding: env.AI,
    gateway: { id: 'my-gateway', cacheTtl: 300, metadata: { tenant: 'acme' } },
    // ...或 gateway: false 完全绕过 AI Gateway。
  }),
);

Cloudflare 的模型接口也可以从任何目标通过两个普通目录提供商访问:cloudflare-workers-ai/...(URL 支持的 Workers AI)和 cloudflare-ai-gateway/...(URL 支持的 AI Gateway),两者都像其他托管提供商一样用 CLOUDFLARE_API_KEY 认证。参见 Cloudflare 目标指南 了解目标的完整模型故事。

后续步骤

  • 智能体 Hooks API ——完整的 useModel() 契约、ThinkingLevel 和 CompactionConfig。
  • 提供商 API ——providers 配置、setProvider() 和 cloudflareBindingProvider()。
  • 子智能体 ——为委托提供自己的模型和思考级别。
  • 持久性 ——什么是提交以及中断的模型工作如何恢复。
  • 可观测性 ——检查模型调用、令牌使用和提供商诊断。