# 能力路由规则文档 (CAPABILITY_ROUTING.md) > **谁敢改这些文件的任何一行前,必须通读本文档。** > 更新日期: 2026-07-28 | 维护人: Senior Developer --- ## 一、核心原则 ``` ✅ 所有路由路径最终汇聚到 capability_registry.resolve_auto_model ✅ 文本/推理/视觉/工具能力必须指向有 "text" capabilities 的模型 ✅ 图像/视频/语音能力在有明确意图时才触发(不会误判普通对话) ✅ 新增能力类型必须在 CAPABILITY_TYPES 注册,否则路由不可见 ``` ## 二、路由路径 (谁在什么时候决定用哪个模型) | 入口 | 文件 | 行号 | 决策逻辑 | 出错表现 | |------|------|------|----------|---------| | 前台用户对话 | chat_service.py | 2730 | `intent = detect_media_intent(req.content)` → 媒体意图 → 图像/视频/语音模型 | 普通对话被误判走图像 | | 前台 Auto 模式 | chat_service.py | 2750 | `ai_model = resolved or resolve_auto_model("text", db)` → 无意图时回退文本 | 无法对话 | | defensive guard | chat_service.py | 2898-2905 | 模型有 image/video 能力但用户无媒体意图 → 强制 resolve_auto_model("text") | 被 guard 修复后走 text | | 后台 "按能力默认模型" 页 | admin/models.py | 495 | `get_capability_defaults(db)` → 读 site_settings JSON → 填到 UI dropdown | 页面不显示默认模型 | | 后台 模型测试 (connect) | admin/models.py | 870-954 | `_detect_model_type(capabilities)` → 按 cap 分类测试 | 测试走错端点 | | 关键词检测 | chat_media.py | 97-157 | `detect_media_intent(text)` → 基于关键词白名单 | 词库不全导致误判/漏判 | | 模糊创作意图 | chat_media.py | 200-240 | `detect_ambiguous_creative_intent(text)` → 无媒体词但有创作动词 | 提示不准确 | | 前端能力下拉 | admin/Models.tsx | 534-559 | `lockedCapDefaults` → 动态锁定 is_default=true 模型到 text/thinking | 显示错误的锁定模型 | | 前端模型下拉 (前台) | ChatPage.tsx | 1486-1498 | `model.capabilities` → cap badge 显示 | 多显示/少显示 badge | | 模型变更 API | admin/models.py | 670-672 | `is_default` 切换 | 旧默认模型未解除锁定 | ## 三、能力定义 (唯一真相源) ```python # capability_registry.py lines 17-35 CAPABILITY_TYPES = [ {"id": "text", "label": "文本对话", "desc": "文本生成与多轮对话"}, {"id": "thinking", "label": "推理思考", "desc": "深度推理 / 思维链"}, {"id": "vision", "label": "视觉理解", "desc": "图片 / 多模态理解"}, {"id": "tool", "label": "工具调用", "desc": "Function Calling"}, {"id": "image", "label": "图像生成", "desc": "文生图"}, {"id": "video", "label": "视频生成", "desc": "文生视频"}, {"id": "audio", "label": "语音合成", "desc": "TTS 文字转语音"}, {"id": "asr", "label": "语音识别", "desc": "ASR 语音转文字"}, {"id": "ocr", "label": "OCR识别", "desc": "图片文字识别"}, {"id": "embedding", "label": "嵌入向量", "desc": "文本向量化"}, {"id": "rerank", "label": "重排序", "desc": "语义重排"}, ] TEXT_FAMILY = {"text", "thinking", "vision", "tool"} # 回退到 is_default 模型 ``` ## 四、媒体意图关键词白名单 (chat_media.py) ### 图像触发词 (```image_kw```) ``` 图片/图像/插画/海报/照片/头像/壁纸/漫画/表情包/logo/图标 画一张/画张/画一只/画只/画个/画幅 生成图片/生成一张/生成一幅/生成图/图像生成 帮我画/给我画/请画/绘制/作画/ai绘画/ai画图 画画/画一下/画出来/生成个图 帮我生成图片/帮我生成图像/给我生成图片 来一张图片/画一张图片/画一幅/画一副 ``` ### 视频触发词 (```video_kw```) ``` 视频/短片/影片/动画视频 做个视频/生成视频/视频生成 生成一个视频/制作一个视频/帮我做视频/制作视频 生成短片/做短片/制作短片/一段短片 一段视频/来段视频/拍个视频/做段视频 ``` ### 语音触发词 (```audio_kw```) ``` 语音/配音/朗读/播报/念一段/有声/tts/音频/生成语音 读一下/念一下/语音合成 ``` ### 不触发的语句 ``` 疑问句(?结尾或含 吗/呢/怎么/如何/能否/可以吗/会不会) 已有明确文本形式(文案/文章/诗/代码/总结/翻译/报告/PPT) ``` ## 五、修改检查清单 每次修改上述任何文件的代码,必须: - [ ] 重新跑 `tests/test_regression_r4.py` (30 条用例,含 detect_media_intent 19 个边界) - [ ] 调用 `GET /app/api/health/bug-audit` 确认 healthy=true (16 项检查) - [ ] 手动测试一条普通文字(如"你好")→ 必须走 text 模型 - [ ] 手动测试一条图像指令(如"画一只猫")→ 必须走 image 模型 - [ ] 修改关键词白名单 → 同步更新本文档 §四 - [ ] 新增能力类型 → 同步更新本文档 §三 + capability_registry.py CAPABILITY_TYPES ## 六、回归防护网 | 层级 | 机制 | 触发时机 | |------|------|---------| | pre-commit | bug-audit API + Python syntax | git commit | | pre-push | bug-audit + pytest + vitest | git push | | unit test | test_regression_r4.py (30 cases) | pytest | | runtime guard | chat_service.py defensive guard | 每次用户请求 | | bug-audit API | /api/health/bug-audit (16 checks) | 手动/CI |