记忆系统是AI Agent的核心组件之一,其设计质量直接决定了Agent在复杂任务中的表现。从今天起,我们将围绕国产中间件MemOS(版本:2.0.9)展开源码级解读,帮助大家深入理解一个生产级 Agent 记忆系统的设计与实现。

1. 整体概述

项目定位

src/memos/configs 是 MemOS 项目的配置管理层,负责定义和管理整个记忆操作系统中所有组件的配置参数。该模块采用 Pydantic 数据模型 进行强类型验证,并提供统一的配置加载、保存和序列化机制。

主要职责

  1. 配置抽象:为 LLM、嵌入器、向量数据库、图数据库、记忆类型等组件提供统一的配置接口
  2. 类型安全:使用 Pydantic 进行严格的类型验证,防止配置错误
  3. 多后端支持:通过工厂模式支持多种后端实现(如 OpenAI、Ollama、Azure 等 LLM 后端)
  4. 序列化支持:支持 JSON/YAML 格式的配置文件读写
  5. 配置复用:通过继承机制实现配置参数的复用和扩展

2. 模块结构

文件名 主要作用
base.py 提供所有配置类的基类 BaseConfig,包含 JSON/YAML 文件加载/保存方法
llm.py 定义各类 LLM 配置(OpenAI、Ollama、Azure、HuggingFace、vLLM、DeepSeek、Qwen 等)
embedder.py 定义嵌入模型配置(Ollama、SentenceTransformer、Ark、Universal API)
vec_db.py 定义向量数据库配置(Qdrant、Milvus)
graph_db.py 定义图数据库配置(Neo4j、NebulaGraph、PolarDB、PostgreSQL)
memory.py 定义记忆类型配置(文本记忆、激活记忆、参数记忆、偏好记忆)
mem_reader.py 定义记忆读取器配置(简单结构化、多模态结构化、策略结构化)
mem_scheduler.py 定义记忆调度器配置及认证配置(RabbitMQ、OpenAI、GraphDB)
mem_user.py 定义用户管理器配置(SQLite、MySQL、Redis)
mem_cube.py 定义 MemCube 配置,管理用户的多种记忆类型
mem_os.py 定义 MemOS 操作系统配置
mem_chat.py 定义 MemChat 聊天系统配置
mem_agent.py 定义记忆代理配置(简单代理、深度搜索代理)
internet_retriever.py 定义互联网检索器配置(Google、Bing、Xinyu、Bocha)
chunker.py 定义文本分块器配置(句子分块、Markdown 分块)
parser.py 定义文件解析器配置(MarkItDown)
reranker.py 定义重排序器配置(BGE、Cosine、NoOp)
utils.py 提供配置相关的工具函数

3. 核心数据结构

3.1 基础配置类(BaseConfig

所有配置类的基类,定义了配置管理的核心机制:

class BaseConfig(BaseModel):
    model_schema: str = Field("NOT_SET", description="配置的模式标识", exclude=True)
    model_config = ConfigDict(extra="forbid", strict=True)

核心属性

  • model_schema:自动设置为 模块名.类名 格式,用于标识配置类型
  • model_config:Pydantic 配置,禁止额外字段并启用严格模式

核心方法

  • from_json_file(json_path):从 JSON 文件加载配置
  • to_json_file(json_path):将配置保存到 JSON 文件
  • from_yaml_file(yaml_path):从 YAML 文件加载配置
  • to_yaml_file(yaml_path):将配置保存到 YAML 文件

3.2 工厂配置类模式

每个组件类型都有一个对应的工厂类,用于根据后端类型创建具体配置实例:

class XXXConfigFactory(BaseConfig):
    backend: str = Field(..., description="后端类型")
    config: dict[str, Any] = Field(..., description="后端配置参数")
    
    backend_to_class: ClassVar[dict[str, Any]] = {
        "backend_a": BackendAConfig,
        "backend_b": BackendBConfig,
    }
    
    @model_validator(mode="after")
    def create_config(self):
        config_class = self.backend_to_class[self.backend]
        self.config = config_class(**self.config)
        return self

3.3 主要配置类一览

LLM 配置类层次
BaseLLMConfig
├── OpenAILLMConfig          # OpenAI API
├── OpenAIResponsesLLMConfig # OpenAI Responses API
├── QwenLLMConfig            # 通义千问
├── DeepSeekLLMConfig        # DeepSeek
├── AzureLLMConfig           # Azure OpenAI
├── AzureResponsesLLMConfig  # Azure Responses API
├── OllamaLLMConfig          # Ollama 本地服务
├── HFLLMConfig              # HuggingFace 本地模型
└── VLLMLLMConfig            # vLLM 推理服务
记忆配置类层次
BaseMemoryConfig
├── UninitializedMemoryConfig    # 未初始化状态
├── BaseActMemoryConfig          # 激活记忆基类
│   └── KVCacheMemoryConfig      # LLM KV Cache 记忆
├── BaseParaMemoryConfig         # 参数记忆基类
│   └── LoRAMemoryConfig         # LoRA 适配器记忆
├── BaseTextMemoryConfig         # 文本记忆基类
│   ├── NaiveTextMemoryConfig    # 朴素文本记忆
│   ├── GeneralTextMemoryConfig  # 通用文本记忆(带向量库)
│   ├── TreeTextMemoryConfig     # 树形文本记忆(带图数据库)
│   │   └── SimpleTreeTextMemoryConfig  # 简化版树形文本记忆
│   └── PreferenceTextMemoryConfig      # 偏好记忆
└── MemFeedbackConfig            # 记忆反馈配置
图数据库配置类层次
BaseGraphDBConfig
├── Neo4jGraphDBConfig           # Neo4j 企业版
│   └── Neo4jCommunityGraphDBConfig  # Neo4j 社区版(需向量库配合)
├── NebulaGraphDBConfig          # NebulaGraph
├── PolarDBGraphDBConfig         # PolarDB
└── PostgresGraphDBConfig        # PostgreSQL + pgvector

4. 主要功能流程

4.1 配置加载流程

从 YAML 文件加载配置的完整流程:

YAML文件 具体配置类 Pydantic验证器 ConfigFactory 用户代码 YAML文件 具体配置类 Pydantic验证器 ConfigFactory 用户代码 from_yaml_file("config.yaml") 读取文件内容 返回字典数据 model_validate(data) validate_backend() 实例化具体配置类 返回配置实例 返回验证后的实例 返回完整配置对象

4.2 多后端配置创建流程

以 LLM 配置为例,展示工厂模式的工作流程:

openai

ollama

azure

huggingface

vllm

qwen

deepseek

输入配置字典

LLMConfigFactory

验证 backend 字段

backend 类型

OpenAILLMConfig

OllamaLLMConfig

AzureLLMConfig

HFLLMConfig

VLLMLLMConfig

QwenLLMConfig

DeepSeekLLMConfig

返回具体配置实例


5. 依赖关系

5.1 内部依赖

模块 依赖的内部包
base.py memos.log
memory.py memos.configs.embedder, memos.configs.graph_db, memos.configs.llm, memos.configs.vec_db, memos.configs.reranker, memos.configs.mem_reader, memos.exceptions
mem_cube.py memos.configs.memory, memos.exceptions, memos.log
mem_os.py memos.configs.llm, memos.configs.mem_reader, memos.configs.mem_scheduler, memos.configs.mem_user
mem_reader.py memos.configs.chunker, memos.configs.embedder, memos.configs.llm
mem_scheduler.py memos.mem_scheduler.general_modules.misc, memos.mem_scheduler.schemas.general_schemas
graph_db.py memos.configs.vec_db
internet_retriever.py memos.mem_reader.factory, memos.exceptions
vec_db.py memos.settings, memos.log

5.2 外部依赖

外部库 用途
pydantic 数据验证和模型定义
yaml YAML 文件解析
uuid 生成唯一标识符
datetime 时间戳处理
pathlib 路径处理
logging 日志记录

5.3 被依赖关系

该模块是 MemOS 项目的基础设施层,几乎所有业务模块都依赖此配置模块:

  • memos.llms.* - 使用 LLMConfigFactory
  • memos.embedders.* - 使用 EmbedderConfigFactory
  • memos.vec_dbs.* - 使用 VectorDBConfigFactory
  • memos.graph_dbs.* - 使用 GraphDBConfigFactory
  • memos.memories.* - 使用 MemoryConfigFactory
  • memos.mem_os.* - 使用 MOSConfig
  • memos.mem_cube.* - 使用 GeneralMemCubeConfig

6. 关键代码片段解读

6.1 BaseConfig 基类的设计思想

class BaseConfig(BaseModel):
    """
    基础配置类。
    
    所有配置类都应继承此类。
    此类使用 Pydantic 的 ConfigDict 强制严格验证,并禁止额外字段。
    """

    model_schema: str = Field(
        "NOT_SET",
        description="配置的模式标识,自动设置为 '模块名.类名' 格式",
        exclude=True,  # 序列化时排除此字段
    )

    # Pydantic 配置:禁止额外字段,启用严格模式
    model_config = ConfigDict(extra="forbid", strict=True)

    @model_validator(mode="after")
    def set_default_schema(self) -> "BaseConfig":
        """
        设置默认的模式标识。
        
        自动将 model_schema 设置为类的完整路径(模块名.类名)。
        如果用户手动设置了不同的值,会发出警告并自动修正。
        """
        dot_path_schema = self.__module__ + "." + self.__class__.__name__
        if self.model_schema == dot_path_schema:
            return self
        if self.model_schema != "NOT_SET":
            logger.warning(
                f"模式标识已设置为 {self.model_schema},但应为 {dot_path_schema}。"
                "将自动修正为默认值。"
            )
        self.model_schema = dot_path_schema
        return self

设计解读

  1. exclude=Truemodel_schema 字段在序列化(如保存到 JSON/YAML)时会被排除,因为它仅用于运行时类型识别,不需要持久化。

  2. extra="forbid":严格禁止未定义的字段,防止用户输入拼写错误的配置项。例如,如果用户写了 "model_nmae" 而非 "model_name",Pydantic 会抛出验证错误,而非静默忽略。

  3. strict=True:启用严格模式,要求类型完全匹配。例如,字符串 "123" 不会自动转换为整数 123

  4. @model_validator(mode="after"):在模型实例化后执行验证,自动设置 model_schema。这使得配置实例可以自我标识其类型,便于后续的配置恢复和类型推断。

6.2 工厂模式的实现

class LLMConfigFactory(BaseConfig):
    """
    LLM 配置工厂类。
    
    根据后端类型创建对应的配置实例。
    """

    backend: str = Field(..., description="LLM 后端类型")
    config: dict[str, Any] = Field(..., description="LLM 后端的配置参数")

    # 后端类型到配置类的映射
    backend_to_class: ClassVar[dict[str, Any]] = {
        "openai": OpenAILLMConfig,
        "ollama": OllamaLLMConfig,
        "azure": AzureLLMConfig,
        "huggingface": HFLLMConfig,
        "vllm": VLLMLLMConfig,
        "huggingface_singleton": HFLLMConfig,
        "qwen": QwenLLMConfig,
        "deepseek": DeepSeekLLMConfig,
        "openai_new": OpenAIResponsesLLMConfig,
    }

    @field_validator("backend")
    @classmethod
    def validate_backend(cls, backend: str) -> str:
        """验证后端字段。"""
        if backend not in cls.backend_to_class:
            raise ValueError(f"无效的后端类型: {backend}")
        return backend

    @model_validator(mode="after")
    def create_config(self) -> "LLMConfigFactory":
        """
        根据后端类型创建配置实例。
        
        将 config 字典转换为对应的配置类实例。
        """
        config_class = self.backend_to_class[self.backend]
        self.config = config_class(**self.config)
        return self

设计解读

  1. ClassVarbackend_to_class 是类变量,所有实例共享同一个映射表,避免每次实例化时重新创建。

  2. 两阶段验证

    • @field_validator 先验证 backend 字段是否合法
    • @model_validator(mode="after") 在所有字段验证通过后,将 config 字典转换为具体的配置类实例
  3. 使用示例

# 输入数据
data = {
    "backend": "openai",
    "config": {
        "model_name_or_path": "gpt-4",
        "api_key": "sk-xxx",
        "temperature": 0.7
    }
}

# 创建工厂实例
factory = LLMConfigFactory(**data)

# factory.config 现在是 OpenAILLMConfig 实例
print(type(factory.config))  # <class 'OpenAILLMConfig'>
print(factory.config.model_name_or_path)  # "gpt-4"

6.3 Neo4j 多租户隔离配置

class Neo4jGraphDBConfig(BaseGraphDBConfig):
    """
    Neo4j 特定配置类。
    
    此配置支持:
    1) 物理隔离(多数据库模式)— 每个用户获得专用的 Neo4j 数据库
    2) 逻辑隔离(单数据库模式)— 所有用户共享一个或多个数据库,
       但每个节点都用 `user_name` 标记
    """

    db_name: str = Field(..., description="目标 Neo4j 数据库名称")
    auto_create: bool = Field(
        default=False,
        description="如果为 True,在多数据库模式下,当目标 db_name 不存在时自动创建",
    )

    use_multi_db: bool = Field(
        default=True,
        description=(
            "如果为 True: 使用 Neo4j 的多数据库功能进行物理隔离;"
            "每个用户通常获得独立的数据库。 "
            "如果为 False: 使用单个共享数据库,通过 user_name 进行逻辑隔离。"
        ),
    )

    user_name: str | None = Field(
        default=None,
        description=(
            "用于数据隔离的逻辑用户或租户 ID。"
            "如果 use_multi_db 为 False 则必须提供。 "
            "所有节点必须用此标记,所有查询必须按此过滤。"
        ),
    )

    @model_validator(mode="after")
    def validate_config(self):
        """验证逻辑约束以避免配置错误。"""
        if not self.use_multi_db and not self.user_name:
            raise ValueError(
                "在单数据库模式(use_multi_db=False)下,必须提供 `user_name` 进行逻辑隔离。"
            )
        return self

设计解读

  1. 物理隔离 vs 逻辑隔离

    • 物理隔离:每个租户有独立的 Neo4j 数据库,数据完全隔离,安全性高但资源消耗大
    • 逻辑隔离:所有租户共享数据库,通过 user_name 标签区分,资源利用率高但需要严格的查询过滤
  2. 约束验证:当 use_multi_db=False 时,强制要求提供 user_name,防止用户忘记设置租户标识导致数据混乱。

  3. 配置示例

# 物理隔离配置
physical_config = Neo4jGraphDBConfig(
    uri="bolt://localhost:7687",
    user="neo4j",
    password="password",
    db_name="tenant_alice",  # 每个租户一个数据库
    use_multi_db=True,
    user_name=None,  # 不需要逻辑隔离标识
)

# 逻辑隔离配置
logical_config = Neo4jGraphDBConfig(
    uri="bolt://localhost:7687",
    user="neo4j",
    password="password",
    db_name="shared_db",  # 所有租户共享一个数据库
    use_multi_db=False,
    user_name="alice",  # 必须提供租户标识
)

7. 总结

核心价值

  1. 统一的配置管理:为 MemOS 的所有组件提供了一致的配置接口,简化了系统配置的复杂性。

  2. 类型安全:通过 Pydantic 的强类型验证,在配置加载阶段就能发现潜在错误,避免运行时异常。

  3. 可扩展性:工厂模式使得添加新的后端实现非常简单,只需:

    • 创建新的配置类继承相应基类
    • 在工厂的 backend_to_class 映射中添加新条目
  4. 多后端支持:支持丰富的后端选择:

    • LLM:9 种后端(openai, ollama, azure, huggingface, vllm, huggingface_singleton, qwen, deepseek, openai_new)
    • 向量数据库:2 种后端
    • 图数据库:5 种后端
    • 记忆类型:10 种后端

学习要点

  1. Pydantic 进阶用法

    • @field_validator 用于单字段验证
    • @model_validator(mode="after") 用于多字段联合验证
    • ConfigDict 配置类行为
    • ClassVar 类变量的使用
  2. 工厂模式

    • 通过映射表实现配置类的动态创建
    • 两阶段验证确保数据完整性
  3. 配置继承体系

    • 基类定义通用属性和方法
    • 子类添加特定配置参数
    • 工厂类统一创建入口
  4. 多租户设计

    • 物理隔离 vs 逻辑隔离的权衡
    • 通过配置验证强制约束条件
Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐