
GUI-MCP 的 5.3 节「模型分发」是整套架构里最实用、也最容易被忽略的一节。它允许agent_loop_config里的caption_config和model_config各自独立配模型图像摘要走低延迟本地模型任务规划走强推理云端模型。如果你也在用 TaoToken 管理 API 通道先到 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_end 创建一把 Key再把这把 Key 填进model_config的api_base和api_key云端规划模型立刻可用而caption_config仍然指向原有本地模型。这样同一套 GUI-MCP 不用改代码逻辑只改配置就完成了本地与云端的模型分发。1. 从 model_config.yaml 看起GUI-MCP 的模型分发到底分了什么1.1 配置分离是分发的前提原文 5.3.1 说得很清楚model_config.yaml是模型配置的总入口它要能同时描述多个模型提供者。本地模型和云端模型都有各自的api_base与api_key而所有代码路径最终都收敛到ask_llm_anything这一个调用接口用model_provider字段决定这次请求走本地还是云端。这就是模型分发在架构层面的基础——没有配置分离就没有后面按功能模块分发模型的可能性。实际改配置时你会发现这个设计带来的好处很具体想换云端模型不用动 GUI-MCP 的 Python 代码只需改 yaml 里的model_provider、api_base、api_key、model_name四个字段。想保留某个任务走本地模型那就让对应模块的model_provider保持local。分发的灵活性完全由配置文件承担这也正是 5.3 节能单独拿出一节来写的原因。1.2 caption_current_screenshot 与 automate_step 读的是两套配置功能层面分发发生在两个函数里caption_current_screenshot负责给当前截图生成图像摘要automate_step负责根据截图和任务信息规划下一个动作。前者读取caption_config.model_config后者读取主model_config。两个函数在同一轮 Agent 循环里都会被执行但读取的配置互不干扰。这里有一个容易踩的坑原文 5.3.3 写了caption_config是可选的如果没配会回退到主model_config。也就是说默认状态下图像摘要和任务规划用的是同一个模型。很多项目跑起来后没有达到「本地摘要 云端规划」的预期原因往往不是代码没实现分发而是 yaml 里根本没有单独写caption_config所有请求都落到了同一个模型上。2. 本地摘要加云端规划为什么需要收拢到一把 Key2.1 多供应商 Key 会吃掉配置分层的好处模型分发解决了「不同任务用不同模型」但没有解决「不同云端模型服务商各自要一套 Key」。如果按原文的扩展方式每接一个云端模型提供者就要在model_config.yaml里新增一组api_base和api_key。这些 Key 分别来自不同平台有的要环境变量有的要文件存储有的有独立控制台和 IP 白名单。等到本地配置里堆了七八个 Key分发的边界又会模糊——改需求时你根本分不清某个请求到底走的是哪套密钥。这也是我建议把云端侧收拢到一个统一 API 通道的原因本地模型仍然走 localhost 的既有服务所有需要上云的模型请求都通过同一把 Key 发出。原文 5.3.3 引用的豆包手机案例也是同样的思路云端模型负责图像与文字理解本地模型负责 OCR、实体识别、Embedding。云端理解这一侧涉及的服务越多统一密钥的价值越明显。2.2 TaoToken 只接管云端这一侧不替代本地模型TaoToken 提供的是统一 API 通道定位是兼容接入。它不负责本地模型推理也不替代 GUI-MCP 原有的本地服务。你只需要把云端模型那一侧的api_base填成 https://taotoken.net/apiapi_key填成从官网创建的同一个 Key本地模型侧保持原样。这样model_config与caption_config之间的分发关系不变只是把原先分散的云端 Key 换成了同一把 TaoToken Key。这么做的好处是「一次创建多处复用」之后不管是给主模型换模型 ID还是在reply_config里增加一个自动回复通道都只需要在 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_end 模型广场确认可用的 ID然后复制到 yaml 里。云端模型供应商切换对 GUI-MCP 完全透明。3. 准备材料注册、创建 Key、确认模型 ID3.1 在官网落地页创建 API Key打开 TaoToken完成注册后进入控制台找到 API Keys 页面创建一把新 Key。创建后立刻复制保存之后不会再次完整显示。本文所有配置示例里的YOUR_API_KEY只是占位符实际使用时要替换成你从 TaoToken 控制台复制下来的真实 Key。有一点值得注意创建 Key 时不要在页面停留太久再复制。部分控制台会在关闭弹窗后只显示脱敏字符串与其事后花时间找 Key不如创建完就存进本地密码管理器。整个过程和你在其他模型平台申请 Key 没有区别只是后续所有云端模型的请求都会统一走这一把 Key。3.2 在模型广场确认当前模型 ID不要在 yaml 里凭记忆填模型名。登录之后打开模型广场找到你计划用于「任务规划」的云端模型 ID记下来。不同时期模型列表会变化所以下文示例中model_name统一写成「以模型广场为准」你替换成实际看到的 ID 即可。图像摘要侧如果继续用本地模型model_name保持原有本地模型名。3.3 记录一张速查表配置前把下面这行信息放在手边避免改 yaml 时来回切页面内容值官网落地页https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endBase URLhttps://taotoken.net/apiAPI KeyYOUR_API_KEYTaoToken 控制台创建模型 ID以 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_end 模型广场当前列表为准注意 Base URL 末尾不要加/v1官网落地页也不能当 API 地址填。网页给人看接口给程序用两者别混。4. 改写 model_config.yamlmodel_config 走 TaoTokencaption_config 留本地4.1 完整配置示例下面是一份可直接修改的model_config.yaml。核心思路主model_config指向 TaoToken 云端模型caption_config保持本地模型。agent_loop_config: task_type: parser_0922_summary # 主模型任务规划走云端强推理模型 model_config: model_name: 以 TaoToken 模型广场为准 model_provider: taotoken api_base: https://taotoken.net/api api_key: YOUR_API_KEY args: temperature: 0.1 top_p: 0.95 frequency_penalty: 0.0 max_tokens: 4096 image_preprocess: is_resize: true target_image_size: [728, 728] max_steps: 400 delay_after_capture: 2 debug: false # 图像摘要模型保持本地低延迟模型 caption_config: model_config: model_name: gelab-zero-4b-preview model_provider: local args: temperature: 0.5 top_p: 0.95 frequency_penalty: 0.0 max_tokens: 512如果你的ask_llm_anything还不认识taotoken这个 provider需要在模型调用层加一个分支当model_provider为taotoken时把请求发到api_base所指向的地址即可。4.2 三个字段决定一次请求的去向配置项model_config任务规划caption_config图像摘要调用函数automate_stepcaption_current_screenshotmodel_providertaotokenlocalapi_basehttps://taotoken.net/api保持原本地服务地址api_keyYOUR_API_KEY保持原配置model_provider决定ask_llm_anything走哪条客户端分支api_base决定请求发到哪个地址api_key决定认证身份。三者组合在一起就构成了 GUI-MCP 的模型分发。任务规划请求发往 TaoToken图像摘要请求发往本地服务两条通道互不相碰。切换模型时优先确认这三个字段是否和目标通道匹配不要只改model_name。4.3 reply_config 的回退逻辑要注意如果你没有在 yaml 里单独写reply_config原文的逻辑是回退到主model_config。也就是说Agent 循环里遇到 INFO 动作需要自动回复时请求也会走 TaoToken 云端模型。如果希望自动回复也走本地可以像caption_config一样单独加一段reply_config把model_provider设成local。这段回退逻辑在实际运行中影响很大。图像摘要、任务规划、自动回复三个通道如果只有主模型配了 TaoToken其余两个都会在缺省时误入云端导致本来想省成本的地方也刷了云端 Token。配完之后把 yaml 完整读一遍确认每一段model_config的model_provider都符合预期。5. 跑一次 ask_agent 验证分发是否生效5.1 最小验证脚本配置改完后重启 MCP server然后用下面的脚本连 localhost:8704 发一条任务import asyncio from fastmcp import Client async def main(): async with Client(http://localhost:8704/mcp) as client: result await client.call_tool( ask_agent, { task: 打开设置并截图, reset_environment: False, kill_app_when_awake: False, max_steps: 1, }, ) print(result) asyncio.run(main())max_steps设为 1 是为了让 Agent 只执行一步就返回不会真的在设备上跑完一整个流程。返回结果里如果包含动作指令说明 MCP server 正常启动配置已被加载。5.2 用日志确认请求去向验证的关键不在返回结果而在日志。观察 MCP server 的运行日志确认以下两点本地模型进程是否收到截图摘要请求。如果caption_current_screenshot确实走了本地你会看到本地模型服务在处理图像输入同时是否出现发往 https://taotoken.net/api 的请求记录。如果任务规划走了 TaoToken这条记录会出现在云端侧日志或 TaoToken 控制台的调用记录里。两条请求各归各的分发就生效了。若所有请求都集中在同一地址说明配置里有一侧没有生效通常是caption_config没被单独配置回退到了主模型。回到第 4 节对照 yaml 检查。6. 分发常见的三种报错6.1 401 UnauthorizedKey 没复制完整或已失效检查model_config.yaml中的api_key是否等于你在控制台复制的真实 Key不要把YOUR_API_KEY占位符原样保留。如果 Key 已经丢失或过期回到 控制台 API Keys 页面重新创建。复制时注意别把末尾的空格或换行带进 yamlYAML 对这类隐形字符很敏感。6.2 400 model_not_found模型 ID 不在模型广场列表中不要凭直觉填模型名也不要沿用旧教程里写死的 ID。回到 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_end 的模型广场按当前列表复制模型 ID再替换 yaml 里的model_name。模型广场的列表会更新凡是提示模型不存在优先去广场核对而不是怀疑 Base URL 写错。6.3 Base URL 多加了 /v1 或填了网页地址这个报错最常见。Base URL 必须是 https://taotoken.net/api末尾不要加/v1官网落地页 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_end 也不能当作 API 地址填进 yaml。两者一个是给人注册和控制台用的网页一个是给程序发请求的接口。如果日志里出现 403 或 404先检查api_base是否被拼成了/api/v1或直接把落地页地址塞了进去。7. 跑通之后去控制台对一下这次调用分发生效后建议先在 TaoToken 模型对话 里用同一把 Key 发一条测试消息确认模型 ID 和 Base URL 都没填错再到 控制台 API Keys 页面核对这把 Key 的调用记录确认 GUI-MCP 的请求确实被记上了。如果之后要长期跑 Agent 循环任务规划每一次都要消耗云端 Token可以打开 Coding Plan 评估套餐是否够用。后面若想把同一把 Key 用到 Claude Code 等工具参考 Claude Code 接入文档 里的环境变量写法即可。分发配置这件事一次改对后续换模型就只是改一行 ID 的事了。