【MemOS源码解读系列】(一)配置管理层
记忆系统是AI Agent的核心组件之一,其设计质量直接决定了Agent在复杂任务中的表现。从今天起,我们将围绕国产中间件MemOS(版本:2.0.9)展开源码级解读,帮助大家深入理解一个生产级 Agent 记忆系统的设计与实现。
1. 整体概述
项目定位
src/memos/configs 是 MemOS 项目的配置管理层,负责定义和管理整个记忆操作系统中所有组件的配置参数。该模块采用 Pydantic 数据模型 进行强类型验证,并提供统一的配置加载、保存和序列化机制。
主要职责
- 配置抽象:为 LLM、嵌入器、向量数据库、图数据库、记忆类型等组件提供统一的配置接口
- 类型安全:使用 Pydantic 进行严格的类型验证,防止配置错误
- 多后端支持:通过工厂模式支持多种后端实现(如 OpenAI、Ollama、Azure 等 LLM 后端)
- 序列化支持:支持 JSON/YAML 格式的配置文件读写
- 配置复用:通过继承机制实现配置参数的复用和扩展
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 文件加载配置的完整流程:
4.2 多后端配置创建流程
以 LLM 配置为例,展示工厂模式的工作流程:
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.*- 使用LLMConfigFactorymemos.embedders.*- 使用EmbedderConfigFactorymemos.vec_dbs.*- 使用VectorDBConfigFactorymemos.graph_dbs.*- 使用GraphDBConfigFactorymemos.memories.*- 使用MemoryConfigFactorymemos.mem_os.*- 使用MOSConfigmemos.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
设计解读:
-
exclude=True:model_schema字段在序列化(如保存到 JSON/YAML)时会被排除,因为它仅用于运行时类型识别,不需要持久化。 -
extra="forbid":严格禁止未定义的字段,防止用户输入拼写错误的配置项。例如,如果用户写了"model_nmae"而非"model_name",Pydantic 会抛出验证错误,而非静默忽略。 -
strict=True:启用严格模式,要求类型完全匹配。例如,字符串"123"不会自动转换为整数123。 -
@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
设计解读:
-
ClassVar:backend_to_class是类变量,所有实例共享同一个映射表,避免每次实例化时重新创建。 -
两阶段验证:
@field_validator先验证backend字段是否合法@model_validator(mode="after")在所有字段验证通过后,将config字典转换为具体的配置类实例
-
使用示例:
# 输入数据
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
设计解读:
-
物理隔离 vs 逻辑隔离:
- 物理隔离:每个租户有独立的 Neo4j 数据库,数据完全隔离,安全性高但资源消耗大
- 逻辑隔离:所有租户共享数据库,通过
user_name标签区分,资源利用率高但需要严格的查询过滤
-
约束验证:当
use_multi_db=False时,强制要求提供user_name,防止用户忘记设置租户标识导致数据混乱。 -
配置示例:
# 物理隔离配置
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. 总结
核心价值
-
统一的配置管理:为 MemOS 的所有组件提供了一致的配置接口,简化了系统配置的复杂性。
-
类型安全:通过 Pydantic 的强类型验证,在配置加载阶段就能发现潜在错误,避免运行时异常。
-
可扩展性:工厂模式使得添加新的后端实现非常简单,只需:
- 创建新的配置类继承相应基类
- 在工厂的
backend_to_class映射中添加新条目
-
多后端支持:支持丰富的后端选择:
- LLM:9 种后端(openai, ollama, azure, huggingface, vllm, huggingface_singleton, qwen, deepseek, openai_new)
- 向量数据库:2 种后端
- 图数据库:5 种后端
- 记忆类型:10 种后端
学习要点
-
Pydantic 进阶用法:
@field_validator用于单字段验证@model_validator(mode="after")用于多字段联合验证ConfigDict配置类行为ClassVar类变量的使用
-
工厂模式:
- 通过映射表实现配置类的动态创建
- 两阶段验证确保数据完整性
-
配置继承体系:
- 基类定义通用属性和方法
- 子类添加特定配置参数
- 工厂类统一创建入口
-
多租户设计:
- 物理隔离 vs 逻辑隔离的权衡
- 通过配置验证强制约束条件
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐
所有评论(0)