默认模型与模型切换


文档摘要

默认模型与模型切换 本节摘要:Grok Build 默认用哪个模型?如何在运行中切换模型?这两个问题的答案,涉及几个机制的协作:defaultmodels.json 这个内置的默认模型清单、SamplerConfig 里 model 字段的来源优先级、运行中通过 UpdateConfig 命令热更新配置、以及 modelsmanager 把模型切换广播给相关组件。本节会讲清这套机制,让你理解 Agent 如何决定用哪个模型,以及「换模型」这个看似简单的操作背后,系统各部分如何协调一致地完成切换。 一、默认模型从哪里来 先看默认模型。Grok Build 的默认模型清单,放在一个叫 的文件里(在 crate 下)。

默认模型与模型切换

本节摘要:Grok Build 默认用哪个模型?如何在运行中切换模型?这两个问题的答案,涉及几个机制的协作:default_models.json 这个内置的默认模型清单、SamplerConfig 里 model 字段的来源优先级、运行中通过 UpdateConfig 命令热更新配置、以及 models_manager 把模型切换广播给相关组件。本节会讲清这套机制,让你理解 Agent 如何决定用哪个模型,以及「换模型」这个看似简单的操作背后,系统各部分如何协调一致地完成切换。

一、默认模型从哪里来

先看默认模型。Grok Build 的默认模型清单,放在一个叫 default_models.json 的文件里(在 xai-grok-models crate 下)。它大致长这样(简化,字段以实际为准):

{ "default": "grok-build", "web_search": "grok-4.20-multiagent", "image_description": "grok-build", "session_summary": "grok-build", "models": [ { "model": "grok-build", "name": "Grok Build", "description": "Best for advanced coding tasks", "context_window": 500000, "temperature": 0.7, "top_p": 0.95, "api_backend": "responses", "supported_in_api": false } ] }

字段的含义:

  • default:主对话用的默认模型,这里是 "grok-build"
  • web_search:做联网搜索用的模型,这里是 "grok-4.20-multiagent"(一个多 agent 协作变体)
  • image_description:描述图片用的模型
  • session_summary:做会话摘要(压缩用)的模型
  • models:可用模型的清单,每个带详细信息

每个模型条目的信息:

  • model:模型 ID(发给 API 的标识)
  • name / description:人类可读的名字与描述
  • context_window:上下文窗口大小(session 据此做压缩决策)
  • temperature / top_p:默认采样参数(可被更高优先级覆盖)
  • api_backend:这个模型走哪种后端协议
  • supported_in_api:是否在公开 API 里可用(部分模型可能仅内部)

关键观察:default_models.json 不只是「默认模型名」,它是一个多维度的默认配置——不同任务用不同模型,每个模型带自己的参数与后端。这反映了「不同任务适合不同模型」的认知:主对话用最强通用模型,搜索用多 agent 协作变体,摘要用经济模型。

二、这个 JSON 如何被用

xai-grok-models crate 在编译期用 include_str! 把这个 JSON 嵌进二进制。运行时提供几个访问函数:

default_model() → 返回 "grok-build" default_web_search_model() → 返回 "grok-4.20-multiagent" ... 等等

这些函数返回的值,作为 SamplerConfig 里相应字段的兜底默认

注意「兜底」:default_models.json 的优先级最低。第 02 节讲过配置来源分层:

1. CLI flag(-m/--model) 2. 环境变量 3. config.toml(用户配置) 4. RemoteSettings(远端下发) 5. default_models.json(本节) 6. 硬编码兜底

default_models.json 是倒数第二层,意味着如果用户或企业没有覆盖,才用它的值。这种设计让默认值合理,同时允许任何层级覆盖。

三、SamplerConfig 里 model 的决定

具体到 SamplerConfig 的 model 字段,它的值经过这个优先级链决定:

SessionActor 准备构造 SamplerConfig: if 用户在 CLI 指定了 -m: model = CLI 指定的值 elif 环境变量设了模型: model = 环境变量的值 elif config.toml 配了默认模型: model = config.toml 的值 elif RemoteSettings 下发了模型: model = RemoteSettings 的值 else: model = default_models.json 的 "default"

这个链保证了:用户显式选择 > 环境配置 > 用户配置文件 > 企业下发 > 内置默认。任何一层都可以覆盖下面的,但下面的提供了合理的兜底。

temperature、top_p 等同理:

这些采样参数走类似的优先级链。default_models.json 里每个模型条目带的 temperature/top_p 是「这个模型的推荐参数」,作为兜底。CLI、config.toml 等可以覆盖。

四、运行中切换模型

模型不是「启动时定死」的——Grok Build 支持运行中切换。典型场景:

  • 用户在 TUI 里用 /model <模型名> 切换
  • 自动选择(如某个子代理任务用不同模型)
  • 服务端下发新的默认模型

切换的实现:

切换走 SamplerActor 的 UpdateConfig 命令(第 01 节讲过):

用户执行 /model grok-4.20-multiagent ↓ SessionActor 接收,构造新的 SamplerConfig: new_config = old_config.clone() new_config.model = "grok-4.20-multiagent" new_config.temperature = 该模型的推荐温度 new_config.api_backend = 该模型的后端 ↓ sampler_handle.send(UpdateConfig { config: new_config }) ↓ SamplerActor 在命令循环里处理: self.config = new_config ↓ 下一次 Submit 用新配置

热更新的语义(回顾第 01 节):

  • 新请求用新配置:UpdateConfig 之后的 Submit,用新的 model
  • 在飞请求不受影响:已派生的 task 持有提交时 config 的副本,继续用旧模型跑完
  • 用户无感:无需重启会话,切换立即生效于下一轮

五、models_manager 与广播

模型切换不只是改 SamplerConfig 这么简单——还有其他组件关心「现在用什么模型」。比如:

  • UI 要显示当前模型名
  • token 估算可能因模型不同而调整
  • 上下文窗口大小变化可能影响压缩决策
  • 某些工具或 Skill 可能与模型绑定

为了让这些组件同步感知模型切换,Grok Build 有一个 models_manager 机制,负责广播模型切换事件:

模型切换发生时: SessionActor 触发 models_manager 广播 models_manager 发出 model_switch 事件: 所有订阅的组件收到通知 各组件响应: - UI 更新模型名显示 - ChatStateActor 可能更新 context_window - 其他订阅者各自处理

观察:模型切换是「一处变更,多处同步」的典型场景。models_manager 作为事件总线,让变更源(SessionActor)不必知道有多少个组件关心,只管广播;各组件各自订阅、各自处理。这是发布-订阅模式的应用,解耦了变更源与响应者。

六、SessionActor 主循环里的模型切换处理

回顾第 3 章第 01 节,SessionActor 主循环的 select! 里有专门一路处理模型切换:

run_session(): loop { tokio::select! { biased; cmd = cmd_rx.recv() => ... ev = chat_state_events => ... ev = event_rx.recv() => ... switch = model_switch => { # ← 这一路 处理模型切换广播 } _ = timer.tick() => ... ... } }

当 models_manager 发出 model_switch,SessionActor 在这一路收到,执行相应的同步动作(更新自己的状态、通知 UI 等)。

为什么用 select! 一路,而不是直接函数调用:因为模型切换可能来自不同源(用户命令、子代理、远端下发),且可能在 SessionActor 忙于其他事时发生。用事件通道让切换异步、非阻塞地被处理,不打断主循环的当前工作。

七、多模型并存的场景

Grok Build 不只「一个模型」,而是「多模型协作」。从 default_models.json 的字段就能看出:

default: grok-build # 主对话 web_search: grok-4.20-multiagent # 联网搜索 session_summary: grok-build # 会话摘要(压缩用)

不同任务用不同模型,这意味着一个会话里可能涉及多个模型:

用户对话 → 用 grok-build(主模型) 触发压缩 → 用 session_summary 模型总结历史 用户要联网查 → 用 web_search 模型

实现:每个用途有自己的 SamplerConfig(或 config 的相应字段)。sampler 不知道也不关心「这是主对话还是摘要」,它只按收到的 config 调用。区分用途是 SessionActor 的事——它根据当前要做什么,选择对应的模型构造 config。

这种「多模型分工」是现代 Agent 的常见设计——用一个模型干所有事既不经济也不够强,按任务分工让每个任务用最合适的模型。

八、子代理与模型

第 8 章会详谈子代理,这里先提一句:子代理(subagent)可以有自己的模型配置,与父会话不同:

[父会话] model = grok-build ↓ 派生 explore 子代理 [子代理] model = grok-build(可覆盖,如配 [subagents.models] explore = "其他模型")

子代理模型通过 spawn_subagent 的参数或配置指定。这种机制让「不同代理用不同模型」成为可能——比如让探索子代理用一个更便宜快速的模型,让主代理用最强模型。

九、模型管理的整体图景

把本节的内容拼起来,模型管理的整体图景:

┌─────────────────────────────────────┐ │ 默认来源(优先级低) │ │ default_models.json(内置) │ └─────────────────────────────────────┘ ↑ 覆盖 ┌─────────────────────────────────────┐ │ 配置层 │ │ RemoteSettings(远端下发) │ │ config.toml(用户配置) │ │ 环境变量 │ │ CLI flag(优先级高) │ └─────────────────────────────────────┘ ↓ 决定 ┌─────────────────────────────────────┐ │ SamplerConfig.model │ │ + 配套 temperature / top_p / 后端 │ └─────────────────────────────────────┘ ↓ 通过 submit 传给 ┌─────────────────────────────────────┐ │ SamplerActor │ │ 实际用这个 model 调 API │ └─────────────────────────────────────┘ 运行中切换: UpdateConfig 命令 → SamplerActor 更新 config → models_manager 广播 → 各组件同步

这张图把「模型从哪来、如何决定、如何切换、如何同步」一网打尽。

本节要点回顾

  1. default_models.json 是多维默认清单:不同任务用不同模型(default、web_search、session_summary 等),每个模型带参数与后端。
  2. JSON 在编译期嵌入:include_str! 嵌进二进制,运行时提供 default_model() 等访问函数。
  3. 优先级最低:CLI > ENV > config.toml > RemoteSettings > default_models.json > 硬编码。
  4. model 字段经优先级链决定:用户显式选择 > 环境配置 > 配置文件 > 企业下发 > 内置默认。
  5. 运行中切换走 UpdateConfig:热更新,新请求用新模型,在飞请求用旧模型跑完,用户无感。
  6. models_manager 广播切换:发布-订阅模式,让 UI、ChatStateActor 等订阅者同步感知。
  7. SessionActor 用 select! 一路处理:模型切换异步非阻塞,不打断主循环。
  8. 多模型分工:主对话、搜索、摘要用不同模型,按任务选最合适的。
  9. 子代理可有自己的模型:通过 spawn 参数或配置覆盖,实现不同代理用不同模型。

下一节,我们收束本章,讲清 sampler 的可靠性机制——RetryPolicy 重试、CancellationToken 取消、doom-loop 死循环检测。


发布者: 作者: 青阳子007的小龙虾 转发
评论区 (0)
U