# 修复 LLM API 404 错误 ## 问题描述 用户在对话时收到错误: ``` Chat failed: LLM error: API error 404 Not Found: {"error":{"message":"The requested resource was not found","type":"resource_not_found_error"}} ``` ## 根因分析 ### 1. 模型别名未被解析(主要原因) **数据流问题:** - 前端 `chatStore.ts:194` 默认模型是 `'glm-5'` - 配置文件 `config.toml:131` 定义了别名映射 `"glm-5" = "zhipu/glm-4-plus"` - **但是后端 `kernel.rs` 没有解析这个别名**,直接把 `'glm-5'` 发送给API - 智谱API不认识 `'glm-5'`,返回404 ### 2. 模型ID格式问题 配置文件使用带provider前缀的格式 `"zhipu/glm-4-plus"`,但: - 智谱API只认识 `"glm-4-plus"`(不带前缀) - `openai.rs:140` 直接传递模型ID,不做任何处理 ### 3. 多处配置不一致 | 位置 | 默认Provider | 默认Model | |------|-------------|-----------| | `config.rs:84-88` | `"qwen"` | `"qwen-plus"` | | `config.toml:115-116` | `"zhipu"` | `"glm-4-plus"` | | `chatStore.ts:194` | - | `'glm-5'` (别名) | | `loop_runner.rs:38` | - | `"claude-sonnet-4-20250514"` (硬编码) | ### 4. Kimi Base URL错误 `config.rs:92` 使用 `https://api.kimi.com/coding/v1`,正确应该是 `https://api.moonshot.cn/v1` ## 修复方案 ### 修复1: 在Kernel中添加模型别名解析 **文件**: `crates/zclaw-kernel/src/kernel.rs` 在 `send_message` 和 `send_message_stream` 方法中,解析模型别名: ```rust // 在 send_message 方法中,约第119行 // 添加模型别名解析函数 fn resolve_model_alias(model: &str, aliases: &HashMap) -> String { aliases.get(model).map(|s| s.as_str()).unwrap_or(model).to_string() } // 然后在确定模型后,检查是否是别名 let model = resolve_model_alias(model, &self.config.model_aliases); ``` ### 修复2: 在KernelConfig中添加模型别名配置 **文件**: `crates/zclaw-kernel/src/config.rs` 1. 添加模型别名字段: ```rust /// Model aliases (e.g., "glm-5" -> "zhipu/glm-4-plus") #[serde(default)] pub model_aliases: HashMap, ``` 2. 修正Kimi Base URL: ```rust fn default_kimi_base_url() -> String { "https://api.moonshot.cn/v1".to_string() // 修正 } ``` ### 修复3: 在OpenAIDriver中规范化模型ID **文件**: `crates/zclaw-runtime/src/driver/openai.rs` 在 `build_api_request` 方法中,去除provider前缀: ```rust fn normalize_model_id(model: &str) -> String { // 如果模型ID包含 "/",取最后一部分 // 例如 "zhipu/glm-4-plus" -> "glm-4-plus" if model.contains('/') { model.split('/').last().unwrap_or(model).to_string() } else { model.to_string() } } ``` ### 修复4: 统一默认配置 **文件**: `crates/zclaw-kernel/src/config.rs` 将默认provider和model改为与config.toml一致: ```rust fn default_provider() -> String { "zhipu".to_string() } fn default_model() -> String { "glm-4-plus".to_string() } ``` ### 修复5: 移除loop_runner.rs中的硬编码默认值 **文件**: `crates/zclaw-runtime/src/loop_runner.rs` 第38行的硬编码模型应该移除,使用传入的配置: ```rust // 移除硬编码,改为空字符串或从配置获取 model: String::new(), // 必须通过 with_model() 设置 ``` ## 关键文件 | 文件 | 修改内容 | |------|----------| | [config.rs](crates/zclaw-kernel/src/config.rs) | 添加model_aliases字段、修正Kimi URL、统一默认配置 | | [kernel.rs](crates/zclaw-kernel/src/kernel.rs) | 添加模型别名解析逻辑 | | [openai.rs](crates/zclaw-runtime/src/driver/openai.rs) | 添加模型ID规范化(去除provider前缀) | | [loop_runner.rs](crates/zclaw-runtime/src/loop_runner.rs) | 移除硬编码默认模型 | ## 问题场景确认 用户使用**智谱 GLM** 模型时遇到404错误: - 前端默认 `currentModel: 'glm-5'` - 配置别名 `"glm-5" = "zhipu/glm-4-plus"` - 后端未解析别名,直接发送 `'glm-5'` 给API - 智谱API返回404 ## 验证步骤 1. **单元测试** ```bash cargo test -p zclaw-kernel --lib config::tests cargo test -p zclaw-runtime --lib driver::openai::tests ``` 2. **集成测试** ```bash cargo test -p zclaw-kernel ``` 3. **手动验证(智谱GLM)** - 启动桌面应用:`pnpm start:dev` - 在"模型与API"设置中配置智谱API Key - 选择 `glm-5` 或 `glm-4-plus` 模型 - 发送消息,验证不再出现404错误 - 检查日志确认: - 模型别名 `'glm-5'` 被解析为 `'zhipu/glm-4-plus'` - provider前缀被去除,发送给API的是 `'glm-4-plus'` ## 实现顺序 1. **config.rs** - 添加model_aliases字段和修正Kimi URL 2. **openai.rs** - 添加模型ID规范化函数 3. **kernel.rs** - 添加别名解析逻辑 4. **loop_runner.rs** - 移除硬编码 5. **测试验证**