跳转到内容

记忆生成的多模型路由

记忆生成的多模型路由:Claude-Mem 的具体实现

学习目标

本章聚焦 Claude-Mem 如何为记忆生成任务路由到不同的 LLM 提供商。建议先阅读前置知识,下文直接聚焦具体落地方案。

前置知识

本章涉及多模型适配的通用架构,建议先阅读:

项目实践

三 Provider 架构

Worker Service 中实现了三个 LLM Provider:

Provider源文件API
ClaudeProviderClaudeProvider.ts (~20KB)Anthropic Messages API
GeminiProviderGeminiProvider.ts (~20KB)Google Gemini API
OpenRouterProviderOpenRouterProvider.ts (~20KB)OpenRouter 统一 API

三个 Provider 遵循相同的接口约定:

  • generateObservation(input) — 生成观察
  • generateSummary(input) — 生成会话摘要
  • 返回统一格式的结构化输出

错误分类系统

每个 Provider 实现了独立的错误分类函数:

classifyClaudeError(error) → ProviderErrorClass
classifyGeminiError(error) → ProviderErrorClass
classifyOpenRouterError(error) → ProviderErrorClass

错误分类定义了统一的处理策略:

错误类型处理策略
速率限制等待后重试
上下文窗口超限截断输入后重试
认证失败记录错误,跳过
服务器错误重试

限流与重试

RateLimitStoresrc/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 处理。

参考来源