news 2026/9/17 20:44:47

summarize 模型/Provider 解析架构:从共享能力注册表到自动选型与执行链路

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
summarize 模型/Provider 解析架构:从共享能力注册表到自动选型与执行链路

summarize 模型/Provider 解析架构:从共享能力注册表到自动选型与执行链路

【免费下载链接】summarizePoint at any URL/YouTube/Podcast or file. Get the gist. CLI and Chrome Extension.项目地址: https://gitcode.com/GitHub_Trending/summarize/summarize

导读:本文基于 summarize 项目的 docs/model-provider-resolution.md,完整拆解其"模型/Provider 解析"设计:从无依赖的共享能力注册表(provider registry)出发,梳理自动模型选择(auto model selection)、LLM 执行路由(generate-text)、错误整形(error shaping)三层结构的职责边界与调用链。读完你将掌握:新增或修改一个模型 Provider 时应该改哪个文件、自动选型(含 CLI 回退与 OpenRouter 映射)的候选生成逻辑、各 Provider 能力位(文档/流式/视频理解)如何在源码中落地,以及确保这些约束不被破坏的契约测试。

设计目标:减少隐式 Provider 知识

文档开门见山提出了核心目标:reduce implicit provider knowledge(减少隐式的 Provider 知识)。也就是说,Provider 的名称、所需环境变量、默认模型、传输方式、能力位(文档/流式/视频理解)等元数据,不应散落在各处常量、测试或调用分支里,而应收敛到一个单一的、可被多处消费的共享注册表,让"新增一个 Provider"变成"改一处注册表 + 补一个执行实现",而不是在几十个文件里打补丁。

围绕这一目标,系统被划分为四个层次:

  1. 共享能力注册表(src/llm/provider-registry.ts)——元数据的唯一事实来源;
  2. 自动模型选择(src/model-auto.ts)——把规则与能力映射为候选尝试(attempts);
  3. 执行(src/llm/generate-text.ts)——按传输类型分发请求、归一化重试与回退;
  4. 错误整形(error shaping)——能力缺失、模型不可用等错误在正确的位置抛出。

以下各节逐一深入。

共享能力注册表:Provider 元数据的唯一事实来源

文档规定 src/llm/provider-registry.ts 是一个**无依赖(dependency-free)**的注册表,被配置解析、模型解析和运行时能力辅助函数共同消费。它拥有:

  • 每个 Provider 的必需环境变量(required env)
  • CLI 默认模型(CLI default models)
  • 自动 CLI 回退顺序(auto CLI order)
  • 文档支持(document support)
  • 流式支持(streaming support)
  • Provider 名称及其 TypeScript 联合类型
  • 默认端点与传输方式选择

网关 Provider 画像(Gateway Provider Profiles)

注册表中GATEWAY_PROVIDER_PROFILES为每个网关型 Provider 声明了一个GatewayProviderProfile,字段如下(见 src/llm/provider-registry.ts):

字段含义
requiredEnv该 Provider 必需的模型环境变量名(如OPENAI_API_KEY
execution传输类型:simple/google/anthropic/openai-http/openai-compatible
supportsDocuments是否支持文档附件
supportsStreaming是否支持流式输出
supportsVideoUnderstanding是否支持视频理解
defaultBaseUrl默认端点(可被配置覆盖)
forceChatCompletions是否强制走 Chat Completions 协议(而非 Responses 协议)

当前 9 个网关 Provider 的完整画像(源码原文):

ProviderrequiredEnvexecutionDocumentsStreamingVideodefaultBaseUrl / 备注
xaiXAI_API_KEYsimple
openaiOPENAI_API_KEYopenai-http
googleGEMINI_API_KEYgoogle
anthropicANTHROPIC_API_KEYanthropic
zaiZ_AI_API_KEYopenai-compatiblehttps://api.z.ai/api/paas/v4,强制 Chat Completions
nvidiaNVIDIA_API_KEYopenai-compatiblehttps://integrate.api.nvidia.com/v1,强制 Chat Completions
minimaxMINIMAX_API_KEYopenai-compatiblehttps://api.minimax.io/v1,强制 Chat Completions
github-copilotGITHUB_TOKENopenai-httphttps://models.github.ai/inference,强制 Chat Completions
ollamaOLLAMA_BASE_URLopenai-compatiblehttp://localhost:11434/v1,强制 Chat Completions

这里有一个值得注意的细节:openaigithub-copilot都走openai-http执行类型,但后者被标记为forceChatCompletions: true,且默认端点指向 GitHub Models;而zai/nvidia/minimax/ollamaopenai-compatible,同样强制 Chat Completions。supportsVideoUnderstanding目前只有googletrue,这正是自动选型时"视频内容只投递到具备视频理解能力的 Provider"这一策略的数据来源。

CLI Provider 画像与自动回退顺序

除网关 API 外,系统还支持调用本机安装的 CLI 二进制(Claude CLI、Codex CLI、Gemini CLI 等),它们由CLI_PROVIDER_PROFILES描述(src/llm/provider-registry.ts):

ProviderrequiredEnvdefaultModelpathEnvmissingBinaryLabel / installLabel
claudeCLI_CLAUDEsonnetCLAUDE_PATHClaude CLI
codexCLI_CODEXnullCODEX_PATHCodex CLI
geminiCLI_GEMINIflashGEMINI_PATHGemini CLI
agentCLI_AGENTautoAGENT_PATHCursor Agent CLI
openclawCLI_OPENCLAWmainOPENCLAW_PATHOpenClaw CLI
opencodeCLI_OPENCODEnullOPENCODE_PATHOpenCode CLI
copilotCLI_COPILOTnullCOPILOT_PATHGitHub Copilot CLI
agyCLI_AGYnullAGY_PATHAntigravity CLI /agy
piCLI_PInullPI_PATHpiCLI

DEFAULT_AUTO_CLI_ORDER定义了自动回退时的默认探测顺序:claude → gemini → codex → agent → openclaw → opencode → copilot。源码注释特别说明:agypi有意被排除在默认自动回退顺序之外,用户必须显式通过--cli agy--model cli/agy等方式主动启用(src/llm/provider-registry.ts)。

运行时别名与能力面的组合

文档强调:注册表负责元数据,而src/llm/provider-profile.ts负责运行时环境变量别名与客户端配置src/llm/provider-capabilities.ts则把两者组合成统一的能力面(combined capability surface)导出。从源码看,provider-profile.ts中的envHasRequiredKey处理了多套环境变量别名(src/llm/provider-profile.ts):

  • GEMINI_API_KEY缺省时,GOOGLE_GENERATIVE_AI_API_KEYGOOGLE_API_KEY任一存在即视为可用;
  • Z_AI_API_KEY缺省时,ZAI_API_KEY也可用;
  • GITHUB_TOKENresolveGitHubModelsApiKey解析;
  • OLLAMA_BASE_URL恒为真(本地服务,无需校验密钥)。

resolveRequiredEnvForModelId则负责从任意模型 ID(cli/...openclaw/...openrouter/...provider/model)反推出所需的环境变量名。provider-capabilities.ts作为一个纯 re-export 层,把注册表与 profile 的能力统一暴露给model-autogenerate-text消费。

自动模型选择:从规则到候选尝试

文档定义 src/model-auto.ts 的职责为:

  • 解析自动规则(resolve auto rules)
  • 前置追加 CLI 候选(prepend CLI candidates)
  • 在安全前提下把原生候选映射到 OpenRouter(map native candidates to OpenRouter when safe)
  • 产出带必需环境变量与传输方式的尝试列表(emit attempts with required env + transport)

同时给出明确边界:保持"选型聚焦",不要在model-auto里加 Provider 专属能力分支,除非注册表无法表达。

第一步:规则候选解析

规则本身定义在 src/model-auto-rules.ts 的DEFAULT_RULES中。规则按输入类型(video/image/website/youtube/text/file)分组,when匹配输入类型,命中后返回candidates列表;website/youtube/text还额外支持按 token 分档的bands

  • promptTokens ≤ 50_000google/gemini-3-flashopenai/gpt-5-minianthropic/claude-sonnet-4-5
  • promptTokens ≤ 200_000:同上
  • 更大输入:追加xai/grok-4-fast-non-reasoning
  • video:仅google/gemini-3-flashgoogle/gemini-2.5-flash-lite-preview-09-2025(与注册表中 google 支持视频理解一致)
  • 兜底规则:gemini-3-flashgpt-5-miniclaude-sonnet-4-5grok-4-fast-non-reasoning

这些默认规则可通过配置文件覆盖:model配置为{ "mode": "auto", "rules": [...] }时使用自定义规则,否则回落默认规则(见 src/config/model.ts 与resolveRuleCandidates)。配置解析器还会校验bandstoken.min/token.max非负且min ≤ max,并禁止同一规则同时声明candidatesbands

第二步:前置 CLI 候选

src/model-auto-cli.ts 的prependCliCandidates决定是否以及在哪些 CLI Provider 前置于 API 候选:

  • 若配置显式给出cli.enabled列表,则以该列表为准(cli.autoFallback/ 旧名cli.magicAuto的自动回退此时不生效);
  • 否则按resolveCliAutoFallbackConfig解析出的顺序(默认DEFAULT_AUTO_CLI_ORDER)探测,且默认onlyWhenNoApiKeys: true——即只有在没有任何 API 密钥配置时才启用 CLI 自动回退(hasAnyApiKeysConfigured检查 OPENAI/GEMINI/ANTHROPIC/XAI/OPENROUTER/Z_AI 等密钥);
  • 上一次成功过的 CLI Provider 会被优先提到最前(prioritizeCliProvider),形成"粘性"回退体验;
  • 候选 ID 形如cli/claude/sonnetcli/gemini/flash,未指定模型时使用DEFAULT_CLI_MODELS

配置解析层会拒绝cli.<provider>.enabled这种写法(提示改用cli.enabled),并强制cli.autoFallback与旧名cli.magicAuto二选一(见 src/config/sections.ts)。

第三步:OpenRouter 映射与尝试生成

buildAutoModelAttempts(src/model-auto.ts)是核心循环,对每个候选执行:

  1. 视频过滤:当输入需要视频理解(requiresVideoUnderstanding)时,跳过 OpenRouter/CLI 候选以及所有非视频理解能力的原生模型 ID;
  2. 显式前缀识别cli/...走 CLI 传输,openrouter/...走 OpenRouter 传输(透传openrouterProvidersFromEnv),其余走原生(native)传输;
  3. 密钥校验:CLI 候选检查cliAvailability,网关候选检查envHasKey,缺密钥直接跳过;
  4. token 预算过滤:借助 LiteLLM 目录(resolveLiteLlmMaxInputTokensForModelId),若promptTokens > maxIn则跳过该候选;
  5. 成本估算estimateCostUsd结合输入/输出 token 与 LiteLLM 单价估算,并写入debug字段;
  6. OpenRouter 回退:当OPENROUTER_API_KEY存在且不需要视频理解时,尝试把原生provider/model映射为 OpenRouter 的author/model。映射采用"精确byId匹配 → 唯一 slug 匹配 → 忽略标点后的 slug 匹配"三级策略(如xaix-aigrok-4-1-fastgrok-4.1-fast这类差异),歧义时宁可跳过;OpenRouter 模型索引按进程懒加载缓存,测试可注入固定列表;
  7. 去重:按transport + openrouter 标志 + userModelId + providers组合去重后返回有序的AutoModelAttempt[]

每个AutoModelAttempt携带transport: "native" | "openrouter" | "cli"userModelIdllmModelIdrequiredEnvopenrouterProvidersforceOpenRouterdebug字符串,成为后续执行层的直接输入。

执行链路:按 execution 类型分发

src/llm/generate-text.ts 的generateTextWithModelId职责为:解析请求的模型 ID、校验输入形状、路由到 Provider 传输、归一化重试/回退。源码显示它先parseGatewayStyleModelId拆出providermodel,再根据注册表中的execution类型分支:

execution分发目标关键实现
simplexAIcompleteSimple+resolveXaiModel,校验XAI_API_KEY
googleGooglecompleteGoogleText,校验GEMINI_API_KEY(含别名)
anthropicAnthropiccompleteAnthropicText,校验ANTHROPIC_API_KEY
openai-httpOpenAI / GitHub CopilotcompleteOpenAiText+resolveOpenAiClientConfig
openai-compatiblezai / nvidia / minimax / ollamaresolveOpenAiCompatibleClientConfigForProvider+completeSimpleText

模型 ID 规范化

在执行之前,模型 ID 已由 src/llm/model-id.ts 的normalizeGatewayStyleModelId规范化:无前缀写法按启发式推断(grok-*→xai、gemini-*→google、claude-*→anthropic、其余→openai);历史别名(grok-4.1-fast-non-reasoningxai/grok-4-fast-non-reasoning)与 Anthropic 短别名(claude-sonnet-4claude-sonnet-4-0)被映射到 API 可接受的 ID;github-copilot前缀走resolveGitHubCopilotBackendModelId;未知 Provider 前缀会抛出带可用前缀清单的错误。契约测试 tests/provider-registry.contract.test.ts 专门验证了zai/nvidia/minimax/github-copilot/ollama等 Provider 的无前缀裸名必须报 "Unknown model",防止用户误把 Provider 名当模型名使用。

重试、回退与超时

执行层围绕maxRetriestimeoutMs做了多层防御:

  • 超时:每次尝试新建AbortController+setTimeoutAbortError被归一化为 "LLM request timed out after Xms";
  • 文档回退maybeGenerateDocumentText失败时可通过retryWithModelId递归切换到其他模型;
  • Google 空摘要回退:检测isGoogleEmptySummaryError后切换到resolveGoogleEmptyResponseFallbackModelId指定的模型重试;
  • GPT-5 token 上限重试shouldRetryGpt5WithoutTokenCap命中时移除maxOutputTokens重新发起;
  • Anthropic 访问错误归一化normalizeAnthropicModelAccessError把模型访问错误转换成用户可读信息;
  • 通用重试isRetryableLlmError+ 指数退避(computeRetryDelayMs)+onRetry通知回调。

值得注意的是,Provider 专属的 SDK/HTTP 细节被隔离在 src/llm/providers/* 目录下(如anthropic.tsgoogle.tsopenai.tsminimax.ts),generate-text.ts只做路由与归一化,这与文档"Provider-specific SDK/http details belong undersrc/llm/providers/*"的规定一一对应。

错误整形:错误应该在正确的层抛出

文档给出三条错误整形原则,源码中均有对应实现:

  1. 访问/模型可用性归一化保持 Provider 本地:只有当错误确实 Provider 专属时才在其执行实现内处理(如 Anthropic 的normalizeAnthropicModelAccessError);
  2. 通用能力错误来自共享注册表:如envHasRequiredKey校验失败、resolveOpenAiCompatibleClientConfigForProvider抛出的 "Missing XXX_API_KEY for provider/... model",都源自注册表/profile 层,保证所有调用方得到一致的错误文案;
  3. 不支持的功应当在建立传输之前抛出:如 src/llm/model-id.ts 对未知 Provider 前缀在解析阶段即报错,CLI 缺失时formatMissingCliModelError会在构造客户端之前给出 "Install ... or set ..." 的安装指引(missingBinaryLabel/installLabel/pathEnv均来自注册表)。

配置面隔离:legacy apiKeys 与 base-URL 白名单

文档特别强调"配置层面的白名单保持分离":新增一个模型 Provider 绝不能隐式扩大 legacyapiKeys名称集合或 Provider base-URL 配置面

  • legacy API 密钥映射集中在 src/config/legacy-api-keys.ts 的LEGACY_API_KEY_ENV_MAPopenaiOPENAI_API_KEYnvidiaNVIDIA_API_KEYminimaxMINIMAX_API_KEYanthropicANTHROPIC_API_KEYgoogleGEMINI_API_KEYxaiXAI_API_KEYopenrouterOPENROUTER_API_KEYzaiZ_AI_API_KEY,以及apify/firecrawl/fal/groq/assemblyai/elevenlabs等非模型用途密钥);
  • 契约测试验证了对deepgramollamagithub-copilot等未列入 legacy 名单的 Provider 写入apiKeys会报 "unknown apiKeys provider"(tests/provider-registry.contract.test.ts);
  • 同一测试还验证了parseCliProviderparseRequestedModelIdparseCliConfigresolveOpenAiCompatibleClientConfigForProvider对每个 CLI Provider / 兼容 Provider 的默认行为(默认模型、默认 base URL、强制 Chat Completions 等),形成"注册表与配置/解析器一致"的契约保障。

维护规则:新增或修改 Provider 的操作手册

文档最后给出三条工程纪律,是参与本项目开发时的第一手操作指南:

  1. 能力只加一次,两处消费:在注册表中声明能力后,model-auto(选型)与generate-text(执行)都从注册表读取,不复制分支;
  2. Provider 环境变量别名集中管理:所有别名(如 Google 三键、Z_AI 双键)收敛在provider-profile.tsenvHasRequiredKey,避免各处散落各自的判断逻辑;
  3. 默认 CLI 模型改动只进注册表:不要散落到测试或常量文件,否则契约测试与自动选型会产生漂移。

对照实现可以给出一个清晰的改动检查清单:

  • 新增网关 Provider:先在 src/llm/provider-registry.ts 的GATEWAY_PROVIDER_PROFILES添加画像(requiredEnv/execution/能力位/defaultBaseUrl/forceChatCompletions),再视execution类型在 src/llm/providers 补执行实现,最后确认 legacyapiKeys与 base-URL 配置面不需要(也不应)隐式扩展;
  • 新增 CLI Provider:在CLI_PROVIDER_PROFILES注册 requiredEnv/defaultModel/pathEnv 等,并按需加入DEFAULT_AUTO_CLI_ORDER(或有意排除、要求显式启用);
  • 调整自动选型:优先修改DEFAULT_RULES(src/model-auto-rules.ts)或通过model: { mode: "auto", rules: [...] }配置覆盖,而不是在执行层加分支;
  • 修改默认模型/顺序:一律改注册表,随后运行 tests/provider-registry.contract.test.ts 与 tests/llm.provider-capabilities.test.ts 验证契约未破坏。

小结

summarize 的模型/Provider 解析是一条"注册表 → 选型 → 执行"的单向依赖链:provider-registry.ts用一张无依赖的表承载全部 Provider 元数据;provider-profile.tsprovider-capabilities.ts在其上叠加运行时别名与能力面;model-auto.ts(连同model-auto-rules.tsmodel-auto-cli.ts)把规则、密钥、token 预算与 OpenRouter/CLI 回退编译成有序的尝试列表;generate-text.ts再按execution类型分发到 src/llm/providers 的具体实现,并在统一的重试/超时/回退框架下归一化结果与错误。这套设计把"隐式 Provider 知识"压到最低——新增 Provider 只需改注册表与对应执行实现,其余层通过契约测试保证一致性。对于想扩展模型生态或自定义自动选型策略的开发者,以上文件与测试即是完整的操作地图。

【免费下载链接】summarizePoint at any URL/YouTube/Podcast or file. Get the gist. CLI and Chrome Extension.项目地址: https://gitcode.com/GitHub_Trending/summarize/summarize

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/17 20:44:24

Java+Python双栈智能体开发:AI应用落地与工程化实战

去年年底有个做仓储系统的朋友问我&#xff0c;他们公司想上智能体开发&#xff0c;手里是一个两个 Java 后端加一个写 Python 算法的配置&#xff0c;问我这个组合够不够。我说够&#xff0c;但前提是这几个人得能互相看懂对方的代码——这句话后来成了我做这门 AI 应用与智能…

作者头像 李华
网站建设 2026/9/17 20:40:57

PointNet实战:从数据加载到分类跑通的完整路径

1. 这不是“又一个点云教程”&#xff0c;而是一份能让你真正动手跑通PointNet的实战手记我带过三届校企联合培养的点云方向实习生&#xff0c;也帮五家工业检测初创公司搭过点云处理流水线。每次新人上来第一句话都是&#xff1a;“PointNet到底怎么跑起来&#xff1f;”——不…

作者头像 李华
网站建设 2026/9/17 20:40:39

Debian服务器安装1Panel面板:从系统准备到首次登录完整教程

最近几个月&#xff0c;我身边跑 Debian 服务器的朋友讨论最多的管理面板&#xff0c;已经从传统的 LNMP 一键包换成了 1Panel。这个开源面板用 Go 语言开发&#xff0c;把服务器里的网站、数据库、容器、计划任务和监控统一收进一个 Web 界面&#xff0c;装好之后&#xff0c;…

作者头像 李华