模型角色架构:按职责分工的多模型调度
模型角色架构:按职责分工的多模型调度
学习目标
本章要解决的核心问题:当一个 AI 编程助手需要同时处理对话、代码补全、文件编辑、向量嵌入等多种任务时,如何让每种任务都使用最合适的模型?
你将学到:
- Continue 的
selectedModelByRole设计:六种模型角色的分工策略 - 模型角色的声明与路由机制
- 角色降级与 fallback 策略
- 为什么不是”一个模型搞定所有事”
前置知识
本章涉及多模型提供商的统一抽象,建议先阅读:
下文假设你已理解模型提供商的统一抽象层(BaseLLM),直接聚焦 Continue 的角色分工方案。
项目实践
六种模型角色
Continue 在配置中将模型分为六种角色(定义在 @continuedev/config-yaml 的 ModelRole 枚举中):
| 角色 | 用途 | 典型模型选择 | 性能要求 |
|---|---|---|---|
chat | 对话、代码解释、Agent 推理 | Claude Sonnet/Opus、GPT-4 | 高智能,中等速度 |
edit | 行内代码编辑(Edit 模式) | Claude Sonnet、GPT-4o | 高智能,快速响应 |
apply | 代码应用(执行编辑操作) | 与 edit 类似,可单独配置 | 中高智能 |
autocomplete | 行内自动补全 | Codestral、Starcoder2 | 低延迟,高吞吐 |
embed | 文本嵌入(向量化) | text-embedding-3-small、Nomic | 高吞吐,低成本 |
rerank | 检索结果重排 | Cohere Rerank、Jina | 高准确率 |
声明方式
在 Continue 的配置中,一个模型可以担任多个角色:
models: - name: claude-sonnet-4-20250514 provider: anthropic roles: - chat - edit
- name: codestral-latest provider: mistral roles: - autocomplete
- name: text-embedding-3-small provider: openai roles: - embed关键数据结构是 selectedModelByRole,在配置加载时构建:
interface SelectedModelByRole { chat: ILLM | null; edit: ILLM | null; apply: ILLM | null; autocomplete: ILLM | null; embed: ILLM | null; rerank: ILLM | null;}路由机制
配置加载时,getModelByRole() 函数遍历所有声明的模型,按角色分类:
加载所有模型 ↓遍历每个模型的 roles[] 数组 ↓将模型实例填入 selectedModelByRole[role] ↓如果同一角色有多个模型,取最后一个(用户可覆盖) ↓各处通过 config.selectedModelByRole.chat 等访问消费端示例
不同子系统自动获取对应角色的模型:
- Chat 面板:
config.selectedModelByRole.chat - Autocomplete 引擎:
config.selectedModelByRole.autocomplete - RAG 管线:
config.selectedModelByRole.embed+config.selectedModelByRole.rerank - Edit 模式:
config.selectedModelByRole.edit - Apply 操作:
config.selectedModelByRole.apply(回退到 edit → chat)
降级策略
当某角色没有配置专用模型时:
- chat 缺失:使用 modelsByRole.chat 中的第一个
- edit/apply 缺失:回退到 chat 模型
- autocomplete 缺失:该功能不可用(需要专用低延迟模型)
- embed 缺失:RAG 管线跳过向量检索,仅使用 FTS
- rerank 缺失:跳过重排步骤,直接使用检索结果
问题与规避
陷阱 1:autocomplete 用了大型模型导致延迟过高
现象:用户在打字时补全请求需要 3-5 秒才返回。
原因:autocomplete 角色配置了 Claude Opus 或 GPT-4 等重型模型。
规避:autocomplete 角色应选择专门优化过的代码补全模型(如 Codestral、Starcoder2),这些模型针对低延迟(<500ms)和高吞吐优化。
陷阱 2:embed 角色缺失导致 RAG 功能降级
现象:@codebase 搜索结果只有全文匹配,没有语义搜索。
原因:没有配置 embed 角色的模型。
规避:配置一个嵌入模型(如 OpenAI text-embedding-3-small),或使用本地 Ollama 的 nomic-embed-text。
陷阱 3:多角色模型的 Token 竞争
现象:同一个模型同时担任 chat 和 edit 角色,在高频使用下触发速率限制。
规避:如果有速率限制,为 edit 角色单独配置一个模型,分流请求。
设计取舍
为什么选角色分工而非全局单一模型
| 方案 | 优势 | 代价 |
|---|---|---|
| 单一模型 | 配置简单,无需选择 | autocomplete 延迟高,embed 任务浪费 Token,总成本更高 |
| 角色分工 | 每任务用最优模型,成本低,体验好 | 配置稍复杂,需要用户理解不同角色的用途 |
Continue 选择角色分工,因为不同任务的模型需求差异巨大:autocomplete 需要 200ms 内响应,chat 需要最强的推理能力,embed 需要的是批量向量化能力——没有一个模型能同时在这三个维度都是最优的。
为什么不是按”提供商”而是按”角色”组织
另一种设计是按提供商组织(如 anthropic: {...}, openai: {...}),然后自动分配角色。Continue 选择按角色声明,因为:
- 用户能精确控制哪个模型做什么
- 支持同一提供商的不同模型担任不同角色
- 配置意图明确,易于调试
替代方案:自动模型路由
一些系统(如 LangChain 的 model router)根据任务自动选择模型。Continue 没有采用这种方式,因为:
- 编程场景的角色是固定的(对话=chat、补全=autocomplete),不需要动态判断
- 静态角色路由更透明、更可预测
- 减少一层决策延迟