跳转到内容

02-Mem0 的 Provider 工厂模式与可扩展架构

Mem0 的 Provider 工厂模式与可扩展架构

学习目标

本章分析 Mem0 如何通过 Factory 模式管理 5 类 Provider、80+ 个实现。你将了解:

  • 工厂模式的注册表设计与动态加载机制
  • Base Class 抽象接口的设计原则
  • 新增 Provider 的标准流程(3 步)
  • 配置转换与兼容性处理

前置知识

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

下文假设你已理解 Provider 模式的基本概念,直接聚焦 Mem0 的具体实现。

项目实践

5 类 Provider 概览

类别数量Factory 类抽象基类
LLMs24LlmFactorybase_llm.py
Vector Stores30VectorStoreFactorybase.py
Embeddings15EmbedderFactorybase_embedder.py
Graph Stores4(无独立 Factory)base.py
Rerankers5RerankerFactorybase_reranker.py

Factory 注册表设计

LlmFactory 使用字典作为注册表:

# 伪代码
class LlmFactory:
provider_to_class = {
"ollama": ("mem0.llms.ollama.OllamaLLM", OllamaConfig),
"openai": ("mem0.llms.openai.OpenAILLM", OpenAIConfig),
"anthropic": ("mem0.llms.anthropic.AnthropicLLM", AnthropicConfig),
# ... 24 种 Provider
}

注册表包含两个映射:

  1. 类路径字符串"mem0.llms.openai.OpenAILLM" —— 通过 importlib.import_module 动态加载
  2. 配置类OpenAIConfig —— 用于验证和转换配置参数

动态加载与实例化

# 伪代码
def create(cls, provider_name, config=None, **kwargs):
class_type, config_class = cls.provider_to_class[provider_name]
llm_class = load_class(class_type) # importlib 动态加载
# 配置转换
if isinstance(config, dict):
config = config_class(**config)
elif isinstance(config, BaseLlmConfig):
# 基础配置转换为 Provider 专用配置
config_dict = {
"model": config.model,
"temperature": config.temperature,
# ...
}
config = config_class(**config_dict)
return llm_class(config)

关键设计

  • 配置转换支持三种输入:None(使用默认)、dictBaseLlmConfig
  • BaseLlmConfig 到 Provider 专用配置的转换,实现了向后兼容
  • **kwargs 允许在创建实例时传入额外参数

Provider 扩展流程

添加新 LLM Provider 只需 3 步:

1. 创建 mem0/llms/new_provider.py
└── 继承 base.py 的抽象类(如 BaseLLM)
└── 实现 generate_response() 方法
2. 创建/使用配置类
└── 继承 BaseLlmConfig 或使用专用配置类
3. 注册到工厂
└── 在 factory.py 的 provider_to_class 中添加条目

同样的流程适用于 Embedding、Vector Store 和 Reranker。

Memory 初始化中的 Provider 使用

Memory.__init__() 通过 Factory 创建所有 Provider 实例:

# 伪代码
class Memory:
def __init__(self, config: MemoryConfig):
self.embedding_model = EmbedderFactory.create(
self.config.embedder.provider,
self.config.embedder.config,
self.config.vector_store.config, # 传给向量存储配置(用于特殊场景)
)
self.vector_store = VectorStoreFactory.create(
self.config.vector_store.provider,
self.config.vector_store.config,
)
self.llm = LlmFactory.create(
self.config.llm.provider,
self.config.llm.config,
)
if config.reranker:
self.reranker = RerankerFactory.create(...)

每个 Provider 的配置都通过 MemoryConfig 的 Pydantic 模型传入,确保类型安全。

运行时 Provider 注册

LlmFactory.register_provider() 支持运行时注册:

@classmethod
def register_provider(cls, name, class_path, config_class=None):
if config_class is None:
config_class = BaseLlmConfig
cls.provider_to_class[name] = (class_path, config_class)

这允许第三方扩展在不修改 Mem0 源码的情况下注册自定义 Provider。

问题与规避

问题对策
动态加载失败(类路径错误)importlib.import_moduleModuleNotFoundError,提示清晰的错误信息
配置转换失败Pydantic 验证失败抛出 ValidationError,包含具体字段错误
Provider 方法签名不一致Base Class 定义抽象方法,子类必须实现
新增 Provider 未注册create() 方法抛出 ValueError: Unsupported provider

设计取舍

为什么用字典注册表而非装饰器?

优势

  • 注册表集中在 factory.py 中,一目了然
  • 支持运行时注册(register_provider 方法)
  • 类路径字符串支持懒加载(只在 create() 时才 import)

代价

  • 新增 Provider 需要修改 factory.py(除非用 register_provider
  • 装饰器方案可以自动注册,更”魔法”

为什么 LLM 有独立 Factory 而 Graph Store 没有?

LLM 有 24 种 Provider,且配置转换逻辑复杂(需要支持 BaseLlmConfig 到 Provider 专用配置的转换)。Graph Store 只有 4 种 Provider,且使用方式简单(直接在 MemoryConfig 中配置),不需要独立的 Factory。

参考来源

  • Mem0 源码:mem0/utils/factory.py
  • Mem0 AGENTS.md:新增 Provider 指南