fix(routing): 消除模型路由链路硬编码不匹配模型名
Some checks failed
CI / Lint & TypeCheck (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
CI / Build Frontend (push) Has been cancelled
CI / Rust Check (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled

summarizer_adapter.rs 和 saas-relay-client.ts 中的 fallback 模型名
(glm-4-flash / glm-4-flash-250414) 在 SaaS relay 中不存在,导致请求被拒绝。
改为未配置时明确报错(fail fast),不再静默使用错误模型。
This commit is contained in:
iven
2026-04-11 23:08:06 +08:00
parent 5fcc4c99c1
commit e1af3cca03
4 changed files with 111 additions and 2 deletions

View File

@@ -9,6 +9,12 @@ tags: [log, history]
> Append-only 操作记录。格式: `## [日期] 类型 | 描述`
## [2026-04-11] fix | 模型路由链路修复 — 消除硬编码不匹配模型
1. summarizer_adapter.rs — "glm-4-flash" 硬编码 fallback → 未配置时明确报错 (fail fast)
2. saas-relay-client.ts — 'glm-4-flash-250414' 硬编码 fallback → 未获取模型时报错
3. Wiki routing.md — 新增完整模型路由文档 (Tauri SaaS Relay 主路径 + 辅助 LLM + Browser 模式)
## [2026-04-11] fix | Skill/MCP 调用链路修复 3 个断点
1. Anthropic Driver ToolResult 格式 — ContentBlock 添加 ToolResult 变体, tool_call_id 不再丢弃

View File

@@ -126,6 +126,100 @@ desktop/src/store/
| 工具 | config-parser/crypto-utils/logger/utils | 10+ |
| Tauri 集成 | safe-tauri/tauri-gateway/secure-storage | 3 |
## 模型路由
### 完整链路 (Tauri SaaS Relay 主路径)
```
前端模型选择
├─ conversationStore.currentModel (用户上次选择的模型)
│ 持久化到 IndexedDB跨会话保留
├─ connectionStore 连接时获取 SaaS 可用模型
│ saasClient.listModels() → [{id: "deepseek-chat"}, {id: "GLM-4.7"}, ...]
│ relayModels[0]?.id 作为 fallback
└─ 最终: preferredModel || fallbackId
kernelClient.setConfig({ model: modelToUse })
kernel_init (Tauri Command)
│ KernelConfigRequest { model, api_key, base_url }
│ base_url = "https://saas-host/api/v1/relay"
│ api_key = SaaS JWT (不是 LLM Key!)
Kernel::boot(config)
│ config.llm.model = modelToUse
│ config.llm.base_url = SaaS relay URL
loop_runner → LLM Driver (OpenAI compatible)
│ POST {base_url}/chat/completions
│ body: { model: modelToUse, messages: [...] }
│ header: Authorization: Bearer {SaaS JWT}
SaaS Relay Handler (handlers.rs)
│ cache.get_model(model_name) → 精确匹配 model_id
│ ⚠️ 无别名解析! "glm-4-flash" ≠ "deepseek-chat"
│ 找不到 → 400 "模型 xxx 不存在或未启用"
Key Pool 轮换
│ priority ASC → last_used_at ASC → cooldown 检查 → RPM/TPM 滑动窗口
真实 LLM API
│ 429 → mark cooldown → 切换 key
│ 5xx → exponential backoff
│ model_group → 跨 Provider 故障转移
响应 → SSE 流式返回 → 前端
```
### 辅助 LLM 调用 (非聊天主路径)
这些 Rust 端组件也通过同一个 relay 发起 LLM 请求:
| 组件 | 文件 | 模型来源 | 触发时机 |
|------|------|----------|----------|
| 记忆摘要 | `summarizer_adapter.rs` | kernel_init 传入的 model | 定期 L0/L1 摘要生成 |
| 记忆提取 | `extraction_adapter.rs` | kernel_init 传入的 model | 中间件触发提取 |
| 管家路由 | ButlerRouter via loop_runner | 同聊天模型 | 聊天中间件链 |
**关键**: `summarizer_adapter.rs``extraction_adapter.rs``kernel_init` 时配置,
使用与聊天相同的 `model``base_url`。未配置时会明确报错,不会静默 fallback 到错误模型。
### SaaS Relay 模型匹配规则
```
前端发送 model: "deepseek-chat"
→ SaaS cache 按 model_id 精确匹配
→ 匹配: cache.models["deepseek-chat"] → 命中
→ 不匹配: cache.models["glm-4-flash"] → null → 400 错误
⚠️ config.toml 中的 [llm.aliases] 仅用于本地 KernelSaaS relay 不解析别名!
```
### Browser 模式模型路由
```
createSaaSRelayGatewayClient(saasUrl, getModel)
│ getModel() 回调 → conversationStore.currentModel || relayModels[0]?.id
chatStream() → saasClient.chatCompletion({ model: getModel() })
│ 未获取到模型时 → onError 报错,不发请求
POST /api/v1/relay/chat/completions → SSE 流
```
## 关联模块
- [[chat]] — 路由决定使用哪种 ChatStream