记忆生成的多模型路由
记忆生成的多模型路由:Claude-Mem 的具体实现
学习目标
本章聚焦 Claude-Mem 如何为记忆生成任务路由到不同的 LLM 提供商。建议先阅读前置知识,下文直接聚焦具体落地方案。
前置知识
本章涉及多模型适配的通用架构,建议先阅读:
- 多模型适配架构 — 统一抽象层与故障转移
项目实践
三 Provider 架构
Worker Service 中实现了三个 LLM Provider:
| Provider | 源文件 | API |
|---|---|---|
| ClaudeProvider | ClaudeProvider.ts (~20KB) | Anthropic Messages API |
| GeminiProvider | GeminiProvider.ts (~20KB) | Google Gemini API |
| OpenRouterProvider | OpenRouterProvider.ts (~20KB) | OpenRouter 统一 API |
三个 Provider 遵循相同的接口约定:
generateObservation(input)— 生成观察generateSummary(input)— 生成会话摘要- 返回统一格式的结构化输出
错误分类系统
每个 Provider 实现了独立的错误分类函数:
classifyClaudeError(error) → ProviderErrorClassclassifyGeminiError(error) → ProviderErrorClassclassifyOpenRouterError(error) → ProviderErrorClass错误分类定义了统一的处理策略:
| 错误类型 | 处理策略 |
|---|---|
| 速率限制 | 等待后重试 |
| 上下文窗口超限 | 截断输入后重试 |
| 认证失败 | 记录错误,跳过 |
| 服务器错误 | 重试 |
限流与重试
RateLimitStore(src/services/worker/RateLimitStore.ts)管理每个 Provider 的速率限制状态:
- 跟踪剩余 token 数和重置时间
- 在接近限制时主动减速
- 支持 Redis 持久化(多 Worker 场景)
retry.ts 实现了指数退避重试策略:
retry(fn, { maxRetries: 3, baseDelay: 1000, maxDelay: 30000 })Provider 选择
Provider 的选择通过 Worker 的配置管理:
- 用户可在
settings.json中配置首选模型 - 不同场景(观察生成 vs 摘要生成)可使用不同模型
- 当首选模型不可用时,故障转移到可用模型
多模型路由的收益
| 场景 | 使用的模型 | 原因 |
|---|---|---|
| 高质量观察生成 | Claude (Opus/Sonnet) | 最佳的理解和归纳能力 |
| 成本敏感场景 | Gemini | 更低的 per-token 成本 |
| 模型不可用时 | OpenRouter | 作为故障转移的第三方代理 |
问题与规避
不同模型的输出格式差异
问题:不同模型的 XML 生成质量不同,可能影响解析成功率。
规避:解析器(src/sdk/parser.ts)使用宽松的正则匹配,容忍格式差异。同时,每个 Provider 在调用时使用特定的系统提示来引导输出格式。
设计取舍
为什么在 Worker 中实现多模型而非 Hook 层?
记忆生成是 AI 密集型的,需要调用 LLM API,而 Hook 层是轻量级的 shell 脚本:
- Worker 层:有 Express HTTP 服务、完整的 TypeScript 运行时、Provider 抽象
- Hook 层:仅负责事件捕获和数据转发
这种分层确保了关注点分离:Hook 层做数据采集,Worker 层做 AI 处理。