模型路由:自定义映射、通配符优先级与预设策略
你在客户端里写的 model,不一定等于 Antigravity Tools 最终请求上游时用的“物理模型”。模型路由做的事很简单:把“对外稳定的模型名”映射成“对内真正要用的模型”,并把结果放进响应头 X-Mapped-Model 里,方便你确认是否走到了预期路径。
学完你能做什么
- 在 UI 里配置
proxy.custom_mapping(精确映射 + 通配符映射) - 说清楚一条规则到底是怎么被命中的(精确 > 通配符 > 默认映射)
- 一键应用预设规则,快速兼容 OpenAI/Claude 客户端
- 用
curl -i验证X-Mapped-Model,定位“为什么没按我想的路由”
你现在的困境
- 你希望客户端一直写
gpt-4o,但上游想稳定落到某个 Gemini 模型 - 你有一堆版本化模型名(例如
gpt-4-xxxx),不想每次都手动加映射 - 你看到请求成功了,但不确定到底跑的是哪个物理模型
什么时候用这一招
- 你要给团队提供一个“固定对外模型集合”,屏蔽上游模型变动
- 你想把多种 OpenAI/Claude 模型名统一路由到少数几个高性价比模型
- 你在排障 401/429/0 token 时,需要确认映射后的实际模型
🎒 开始前的准备
- 你已经能启动本地反代,并能从外部请求跑通(建议先完成 启动本地反代并接入第一个客户端(/healthz + SDK 配置))
- 你知道怎么用
curl -i看响应头(上一课里用过X-Mapped-Model)
这节课里两个关键词
custom_mapping:你的“自定义规则表”,键是客户端传入的模型名(或通配符 pattern),值是最终要用的模型名(来源:src/types/config.ts)。- 通配符
*:用于批量匹配模型名(例如gpt-4*),匹配实现是区分大小写的(来源:src-tauri/src/proxy/common/model_mapping.rs)。
核心思路
后端在处理请求时,会先算出一个 mapped_model:
- 先看
custom_mapping有没有精确命中(key 完全等于model) - 再尝试通配符命中:选“非
*字符更多”的规则(更具体的规则优先) - 都没命中,再走系统默认映射(例如一些 OpenAI/Claude 模型别名到内部模型的映射)
这个 mapped_model 会被写入响应头 X-Mapped-Model(至少 OpenAI handler 会这样做),你用它就能确认“我写的 model 最后变成了什么”。
热更新语义(不用重启)
当反代服务正在运行时,前端调用 update_model_mapping 会让后端立刻把 custom_mapping 写入内存的 RwLock,同时也会保存到持久化配置里(来源:src-tauri/src/commands/proxy.rs;src-tauri/src/proxy/server.rs)。
跟我做
第 1 步:在 API Proxy 页找到“模型路由”卡片
为什么 模型路由的配置入口就在 UI 里;你不需要手动编辑配置文件。
打开 Antigravity Tools -> API Proxy 页面,往下滚动。
你应该看到:一个标题类似“模型路由中心”的卡片,右上角有两个按钮:"应用预设映射"和"重置映射"(来源:src/pages/ApiProxy.tsx)。
第 2 步:加一条“精确映射”(最可控)
为什么 精确映射优先级最高,适合“我就要这一个模型名落到这一个物理模型”。
在“添加映射”区域:
- Original 填你要对外暴露的模型名,比如
gpt-4o - Target 从下拉里选一个目标模型,比如
gemini-3-flash
点击 Add。
你应该看到:映射列表里出现 gpt-4o -> gemini-3-flash,并弹出保存成功提示。
第 3 步:加一条“通配符映射”(批量覆盖)
为什么 当你有一堆版本化模型名时(例如 gpt-4-turbo、gpt-4-1106-preview),用通配符能省掉很多重复配置。
再添加一条映射:
- Original:
gpt-4* - Target:
gemini-3-pro-high
你应该看到:列表里出现 gpt-4* -> gemini-3-pro-high。
规则优先级的“坑位”
当 gpt-4o 同时满足精确规则 gpt-4o 和通配符规则 gpt-4* 时,后端会先走精确命中(来源:src-tauri/src/proxy/common/model_mapping.rs)。
第 4 步:一键应用预设规则(快速兼容)
为什么 如果你主要目的是“快速适配常见 OpenAI/Claude 模型名”,预设能帮你直接填好一批通配符规则。
点击 "应用预设映射"。
你应该看到:列表里新增多条规则,包含类似下面这些(来源:src/pages/ApiProxy.tsx):
{
"gpt-4*": "gemini-3-pro-high",
"gpt-4o*": "gemini-3-flash",
"gpt-3.5*": "gemini-2.5-flash",
"o1-*": "gemini-3-pro-high",
"o3-*": "gemini-3-pro-high",
"claude-3-5-sonnet-*": "claude-sonnet-4-5",
"claude-3-opus-*": "claude-opus-4-5-thinking",
"claude-opus-4-*": "claude-opus-4-5-thinking",
"claude-haiku-*": "gemini-2.5-flash",
"claude-3-haiku-*": "gemini-2.5-flash"
}第 5 步:用 X-Mapped-Model 验证路由是否生效
为什么 你想确认“配置写进去了”,更想确认“请求真的按这条规则走了”。最省事的办法就是看 X-Mapped-Model。
curl -i http://127.0.0.1:8045/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-4o",
"messages": [{"role": "user", "content": "hi"}]
}'$resp = Invoke-WebRequest "http://127.0.0.1:8045/v1/chat/completions" -Method Post -ContentType "application/json" -Body '{
"model": "gpt-4o",
"messages": [{"role": "user", "content": "hi"}]
}'
$resp.Headers["X-Mapped-Model"]你应该看到:响应头里有 X-Mapped-Model: ...。如果你在第 2 步把 gpt-4o 精确映射到了 gemini-3-flash,这里就应该能看到对应值(响应头写入见 src-tauri/src/proxy/handlers/openai.rs)。
第 6 步:需要回到“纯默认映射”时,重置 custom_mapping
为什么 你在排障时,往往希望先排除“自定义规则的影响”。把 custom_mapping 清空,是最直接的回退手段。
点击 "重置映射"。
你应该看到:映射列表清空;之后再请求时,如果没有命中自定义规则,就会走系统默认映射(来源:src/pages/ApiProxy.tsx;src-tauri/src/proxy/common/model_mapping.rs)。
检查点 ✅
- [ ] 你能在 UI 里新增/删除
custom_mapping规则 - [ ] 你能解释清楚:精确规则为什么会压过通配符规则
- [ ] 你能用
curl -i或 PowerShell 读到X-Mapped-Model
踩坑提醒
| 场景 | 你可能会怎么做(❌) | 推荐做法(✓) |
|---|---|---|
| 通配符没生效 | 写了 GPT-4* 期待匹配 gpt-4-turbo | 用小写 gpt-4*;后端通配符匹配是区分大小写的 |
| 两条通配符都能命中 | 同时写 gpt-* 和 gpt-4*,不确定会走哪条 | 让更具体的规则更“长”,确保它的非 * 字符更多 |
| 规则看起来对,但还是没变 | 只看响应 body,不看响应头 | 用 curl -i 确认 X-Mapped-Model(这是后端显式回传的结果) |
| 两条规则“同样具体” | 写了两条通配符,非 * 字符数量一样 | 避免这种配置;源码注释说明这种情况下结果依赖 HashMap 遍历顺序,可能不稳定(来源:src-tauri/src/proxy/common/model_mapping.rs) |
本课小结
proxy.custom_mapping是你控制“对外模型名 → 物理模型”的主入口- 后端路由优先级是:精确命中 > 通配符命中(更具体优先)> 系统默认映射
X-Mapped-Model是最可靠的验证手段,排障时优先看它
下一课预告
下一课会继续看 配额治理:Quota Protection + Smart Warmup 的组合打法(对应章节:
advanced-quota)。
附录:源码参考
点击展开查看源码位置
更新时间:2026-01-23
| 功能 | 文件路径 | 行号 |
|---|---|---|
配置字段:proxy.custom_mapping(前端类型) | src/types/config.ts | 6-20 |
UI:写入/重置/预设(调用 update_model_mapping) | src/pages/ApiProxy.tsx | 371-475 |
| UI:模型路由卡片(应用预设映射 / 重置映射 / 列表与添加表单) | src/pages/ApiProxy.tsx | 1762-1931 |
后端命令:热更新并持久化 custom_mapping | src-tauri/src/commands/proxy.rs | 344-365 |
服务端状态:custom_mapping 用 RwLock<HashMap<..>> 保存 | src-tauri/src/proxy/server.rs | 16-53 |
| 路由算法:精确 > 通配符(更具体优先)> 默认映射 | src-tauri/src/proxy/common/model_mapping.rs | 180-228 |
通配符匹配:支持多 *,且区分大小写 | src-tauri/src/proxy/common/model_mapping.rs | 134-178 |
请求中计算 mapped_model(示例:OpenAI handler) | src-tauri/src/proxy/handlers/openai.rs | 154-159 |
| --- | --- | --- |
关键函数:
resolve_model_route(original_model, custom_mapping):模型路由主入口(见src-tauri/src/proxy/common/model_mapping.rs)