MemOS 模型后端配置指南:LLM 与 Embedder 工厂的架构、参数与实战
MemOS 模型后端配置指南:LLM 与 Embedder 工厂的架构、参数与实战
导读
本文基于 MemOS 官方模块文档 model_backend.md 展开,系统讲解 MemOS 如何通过 LLMFactory 与 EmbedderFactory 两个 Pydantic 工厂类,将模型逻辑与运行时配置彻底解耦:只需一次 backend= 切换,即可在同一套 API 下接入 Ollama、OpenAI、Azure、Qwen、DeepSeek、HuggingFace、vLLM 等对话模型,以及 Ollama、sentence-transformers、火山引擎 Ark、通用 OpenAI 兼容接口等嵌入模型。读完本文,你将掌握两种工厂的完整配置模式、全部后端参数与默认值、流式输出与思维链(CoT)处理,并能直接复用仓库中开箱即用的 8 个 LLM 场景与 5 个嵌入器场景示例。
概述:双工厂架构如何解耦模型与配置
MemOS 将模型逻辑与运行时配置分离为两个正交维度,由两个 Pydantic 工厂统一管理:
| 工厂类 | 产出 | 典型后端 |
|---|---|---|
LLMFactory |
对话模型 | ollama, openai, azure, qwen, deepseek, huggingface, huggingface_singleton, vllm, openai_new |
EmbedderFactory |
文本嵌入器 | ollama, sentence_transformer, ark, universal_api |
两个工厂均接受 *_ConfigFactory.model_validate(...) 生成的配置对象,因此切换服务提供商只需修改 backend= 一个字段。从源码结构看,这一设计的核心是双层映射:
- 配置层:
LLMConfigFactory.backend_to_class将后端名映射到具体 Pydantic 配置类(见 src/memos/configs/llm.py),并在model_validator阶段把传入的config字典实例化为对应配置对象; - 实现层:
LLMFactory.backend_to_class将同一后端名映射到具体的模型实现类(见 src/memos/llms/factory.py)。
这意味着"换后端"只是换两个映射表里的键,上层调用方永远面对统一的 generate / generate_stream / embed 接口,这一模式与 MemOS 中 Chunker、VecDB 等模块的工厂设计保持一致。
LLM 模块
支持的 LLM 后端
| Backend | 说明 | 示例 model_name_or_path |
|---|---|---|
ollama |
本地 Ollama 服务器 | qwen3:0.6b |
openai |
兼容 OpenAI 的 Chat Completions 接口 | gpt-4.1-nano |
azure |
Azure OpenAI Chat Completions | <your-deployment-name> |
qwen |
DashScope 兼容 OpenAI 的 API | qwen-plus |
deepseek |
DeepSeek 兼容 OpenAI 的 API | deepseek-chat / deepseek-reasoner |
huggingface |
本地 transformers pipeline | Qwen/Qwen3-1.7B |
huggingface_singleton |
与 huggingface 相同,但启用单例复用 |
Qwen/Qwen3-1.7B |
vllm |
兼容 OpenAI 的 vLLM 服务器 | Qwen/Qwen2.5-7B-Instruct |
openai_new |
OpenAI Responses API 封装 | gpt-4.1 |
需要补充的是,从 src/memos/llms/factory.py 与 src/memos/configs/llm.py 的源码映射可以看出,当前仓库实际还内置了第 10 个后端 minimax(对应 MinimaxLLMConfig / MinimaxLLM,官方示例中可用模型包括 MiniMax-M2.7 等),原文档表格未列出,但同样可以通过 backend="minimax" 直接启用。
LLM 配置模式
所有 LLM 后端共享 BaseLLMConfig 中的通用字段(定义见 src/memos/configs/llm.py):
| 字段 | 类型 | 默认值 | 描述 |
|---|---|---|---|
model_name_or_path |
str | –(必填) | 模型 ID 或本地标签 |
temperature |
float | 0.7 | 采样温度 |
max_tokens |
int | 8192 | 最大生成 token 数 |
top_p / top_k |
float / int | 0.95 / 50 | 采样裁剪参数 |
| API 专用字段 | 如 api_key、api_base |
– | OpenAI 兼容的认证信息 |
remove_think_prefix |
bool | False | 从生成文本中移除思考标签(<think>...</think>)内的内容 |
default_headers |
dict | None | None | 请求默认 HTTP 头(源码级补充字段) |
各后端的 API 专用字段 差异集中在 api_base / api_key 的默认值与认证方式上,以下是源码中确认的默认端点(src/memos/configs/llm.py):
openai:api_base默认https://api.openai.com/v1,需要api_key;支持enable_thinking(默认 None,即保留提供商默认行为)、extra_body,还支持backup_client一键开启主备双通道容灾(backup_api_key、backup_api_base、backup_model_name_or_path、backup_headers);azure:字段名为base_url(默认https://api.openai.azure.com/)+api_version(默认2024-03-01-preview)+api_key,模型名对应 Azure 上的部署名;qwen:继承 OpenAI 配置,api_base默认https://dashscope-intl.aliyuncs.com/compatible-mode/v1;deepseek:继承 OpenAI 配置,api_base默认https://api.deepseek.com;ollama:api_base默认http://localhost:11434,enable_thinking默认 False;vllm:api_key默认为空串(本地服务可省略),api_base默认http://localhost:8088/v1,enable_thinking默认 False;huggingface/huggingface_singleton:额外提供do_sample(默认 False,即贪心解码)与add_generation_prompt(默认 True,自动套用对话生成模板);openai_new:封装 OpenAI Responses API,enable_thinking默认 False。
工厂用法
from memos.configs.llm import LLMConfigFactory
from memos.llms.factory import LLMFactory
cfg = LLMConfigFactory.model_validate({
"backend": "ollama",
"config": {"model_name_or_path": "qwen3:0.6b"}
})
llm = LLMFactory.from_config(cfg)
这里的 LLMConfigFactory.model_validate 会先校验 backend 合法性(不在映射表中的后端名直接抛 ValueError: Invalid backend),随后通过 model_validator(mode="after") 把 config 字典自动实例化为对应后端配置类(见 src/memos/configs/llm.py),因此工厂拿到的始终是类型完备的强类型配置,而不是裸字典。
LLM 核心 API
所有后端实现均继承自抽象基类 BaseLLM(见 src/memos/llms/base.py),对外只暴露两个核心方法:
| 方法 | 用途 |
|---|---|
generate(messages: list) |
返回完整的字符串响应 |
generate_stream(messages) |
以流式方式逐块生成内容 |
值得注意的是,LLMFactory.from_config 被 @singleton_factory() 装饰(见 src/memos/llms/factory.py),即同一配置下创建的 LLM 实例会被单例化复用,避免重复初始化客户端连接——这也是 huggingface_singleton 后端在加载本地大模型场景下的关键价值。
流式输出与思维链(CoT)
messages = [{"role": "user", "content": "Let's think step by step: …"}]
for chunk in llm.generate_stream(messages):
print(chunk, end="")
对于 Qwen、DeepSeek 这类会返回 reasoning_content(推理内容)的模型,OpenAILLM 与 AzureLLM 的流式实现会自动把推理过程包装成 <think>...</think> 块再按序输出(见 src/memos/llms/openai.py):推理内容先于正文输出,并保证 </think> 正确闭合。Ollama 后端同样支持 thinking 字段的流式透传(见 src/memos/llms/ollama.py)。如果希望最终结果不含思考过程,只需设置 remove_think_prefix: true,工厂内部会调用 remove_thinking_tags 剥离思考标签内容。
完整代码 全部 8 个场景示例请参见 examples/basic_modules/llm.py,覆盖:Ollama 工厂用法、Pydantic 直接实例化、OpenAI(含流式)、HuggingFace 本地模型、Qwen(DashScope)、DeepSeek-chat、MiniMax、DeepSeek-reasoner 推理 + CoT 流式。
性能建议
- 在本地原型开发时,使用
qwen3:0.6b可将内存占用控制在 2 GB 以内,配合 Ollama 本地服务即可完成全流程验证; - 结合 KV Cache(详见 KVCacheMemory 文档)可降低首个 token 的生成延迟(TTFT):MemOS 的
MemScheduler会把语义稳定、高频复用的背景知识预计算为KVCacheItem(Key/Value 张量),推理时直接注入注意力缓存,避免对未变化的记忆内容重复编码,从而显著压缩 prefill 阶段开销。
嵌入模块
支持的嵌入器后端
| Backend | 说明 | 示例 model_name_or_path |
|---|---|---|
ollama |
本地 Ollama 服务器 | nomic-embed-text:latest |
sentence_transformer |
本地 sentence-transformers | nomic-ai/nomic-embed-text-v1.5 |
ark |
火山引擎 Ark 嵌入服务 | <ark-model-id> |
universal_api |
通用服务提供商封装(如 OpenAI、Azure) | text-embedding-3-large |
嵌入器配置模式
所有嵌入器共享 BaseEmbedderConfig(见 src/memos/configs/embedder.py)中的公共字段:
| 字段 | 类型 | 默认值 | 描述 |
|---|---|---|---|
model_name_or_path |
str | –(必填) | 模型 ID 或本地标签 |
embedding_dims |
int | None | None | 嵌入向量维度 |
max_tokens |
int | None | 8192 | 单条文本最大 token 数,超限自动截断;设为 None 可关闭截断 |
headers_extra |
dict | None | None | 额外请求头,仅 universal_api 后端使用 |
后端专属字段:
ollama:api_base默认http://localhost:11434;ark:必填api_key,api_base默认https://ark.cn-beijing.volces.com/api/v3/,另有chunk_size(默认 1)与multi_modal(默认 False,是否启用文本 + 图像多模态嵌入);sentence_transformer:trust_remote_code默认 True,允许加载依赖远程代码的 HF 模型;universal_api:必填provider(如openai)与api_key,可选base_url指向自定义或代理端点;同样支持backup_client及配套的backup_base_url、backup_api_key、backup_model_name_or_path、backup_headers_extra主备容灾配置。
工厂用法
from memos.configs.embedder import EmbedderConfigFactory
from memos.embedders.factory import EmbedderFactory
cfg = EmbedderConfigFactory.model_validate({
"backend": "ollama",
"config": {"model_name_or_path": "nomic-embed-text:latest"}
})
embedder = EmbedderFactory.from_config(cfg)
从 src/memos/embedders/factory.py 可以看到两个额外的实现细节:
- 与 LLM 工厂一样,
from_config也被@singleton_factory()装饰,同一配置的嵌入器实例全局复用; EmbedderFactory.cacheable_backends = {"ollama", "ark", "universal_api"}——当嵌入优化开关embedding_optimization_enabled()打开时,这三个后端的实例会被自动包装为CachingEmbedder,对相同文本命中向量缓存,避免重复调用昂贵的嵌入 API(sentence_transformer是本地模型,不在缓存列表中)。
嵌入调用与文本截断
所有嵌入器实现 embed(texts: list<a href="https://link.gitcode.com/i/132392556ba5132622fea03781518eab" target="_blank">str]) -> list[list[float]] 接口。BaseEmbedder 内置了 token 级截断保护(见 [src/memos/embedders/base.py):优先使用 tiktoken(gpt-4o-mini 编码,失败回退 cl100k_base)统计 token 数,超过 max_tokens 的文本通过二分搜索定位最优截断点;未安装 tiktoken 时退化为启发式估算(中文字符约 1 token/字,其余字符约 4 字符/token)。此外每次嵌入调用都会由 log_embedding_call 装饰器记录模型、批次大小、字符数、耗时与状态等观测指标,便于排查嵌入链路性能问题。
实战:从示例到真实配置
LLM 全场景速查
仓库 examples/basic_modules/llm.py 提供了可直接运行的 8 个场景,以下是两个最具代表性的完整配置:
本地 Ollama(推荐原型方案)
config = LLMConfigFactory.model_validate({
"backend": "ollama",
"config": {
"model_name_or_path": "qwen3:0.6b",
"temperature": 0.8,
"max_tokens": 1024,
"top_p": 0.9,
"top_k": 50,
},
})
llm = LLMFactory.from_config(config)
response = llm.generate([{"role": "user", "content": "How are you? /no_think"}])
需要注意 Ollama 后端在初始化时会自动检查本地模型是否存在,缺失则调用 client.pull(...) 拉取(见 src/memos/llms/ollama.py);若未指定模型名,默认回退到 llama3.1:latest。
DeepSeek 推理 + 思维链流式
cfg2 = LLMConfigFactory.model_validate({
"backend": "deepseek",
"config": {
"model_name_or_path": "deepseek-reasoner",
"api_key": "sk-xxx",
"api_base": "https://api.deepseek.com",
"temperature": 0.2,
"max_tokens": 1024,
"remove_think_prefix": False,
},
})
llm = LLMFactory.from_config(cfg2)
for chunk in llm.generate_stream([
{"role": "user", "content": "Explain step-by-step. "
"If a train travels A→B at 60 mph and returns at 40 mph, "
"what is the average speed? Let's think step by step."}
]):
print(chunk, end="")
其余场景(OpenAI、HuggingFace、Qwen、MiniMax 等)的完整代码同样在该文件中,api_key 一律建议通过环境变量注入,切勿硬编码提交到版本库。
嵌入器全场景速查
仓库 examples/basic_modules/embedder.py 提供 5 个场景,核心用法如下:
# Ollama 本地嵌入(需先 ollama pull nomic-embed-text)
config = EmbedderConfigFactory.model_validate({
"backend": "ollama",
"config": {"model_name_or_path": "nomic-embed-text:latest"},
})
embedder = EmbedderFactory.from_config(config)
embedding = embedder.embed(["This is a sample text for embedding generation."])
print("embedding shape:", len(embedding[0]))
# Universal API 包装 OpenAI(可换成任意兼容端点)
config_api = EmbedderConfigFactory.model_validate({
"backend": "universal_api",
"config": {
"provider": "openai",
"api_key": "<YOUR_KEY>",
"model_name_or_path": "text-embedding-3-large",
"base_url": "https://api.myproxy.com/v1",
},
})
embedder_api = EmbedderFactory.from_config(config_api)
该文件还演示了批量嵌入(一次传入多段文本)、sentence_transformer 本地模型(首次运行会自动从 HuggingFace 下载)以及 universal_api 对接 Azure 的写法。使用 sentence_transformer 时需确保安装 einops(部分 HF 模型如 nomic-bert 依赖它)。
在 MemOS 配置文件中落地
模型后端不仅可以在 Python 代码中以工厂方式使用,也是 MemOS 顶层配置的组成部分。参考调度器配置示例 memos_config_w_scheduler.yaml,chat_model 与 mem_reader 内的 llm / embedder 均使用相同的 backend + config 双层结构:
user_id: "root"
chat_model:
backend: "huggingface_singleton"
config:
model_name_or_path: "Qwen/Qwen3-1.7B"
temperature: 0.1
remove_think_prefix: true
max_tokens: 4096
mem_reader:
backend: "simple_struct"
config:
llm:
backend: "huggingface_singleton"
config:
model_name_or_path: "Qwen/Qwen3-1.7B"
temperature: 0.1
remove_think_prefix: true
max_tokens: 4096
embedder:
backend: "ollama"
config:
model_name_or_path: "nomic-embed-text:latest"
chunker:
backend: "sentence"
config:
tokenizer_or_token_counter: "gpt2"
chunk_size: 512
chunk_overlap: 128
这种"一次定义、全链路复用"的配置方式,正是双工厂解耦设计在生产部署中的直接体现:chat_model 决定对话生成所用的 LLM,mem_reader.llm 决定文档结构化抽取所用的 LLM,mem_reader.embedder 决定向量化所用的嵌入器,三者可各自独立切换后端而互不影响。
源码级验证与测试
- 后端映射的强约束:
LLMConfigFactory.validate_backend与EmbedderConfigFactory的field_validator都会在配置解析阶段拦截非法后端名(src/memos/configs/llm.py、src/memos/configs/embedder.py),错误配置在"进入工厂之前"即被拒绝,而非在运行时炸出晦涩的调用栈; - 统一抽象接口:
BaseLLM(src/memos/llms/base.py)与BaseEmbedder(src/memos/embedders/base.py)是全部后端的共同契约,业务代码只需面向抽象编程; - 单元测试覆盖:仓库通过 tests/llms/test_factory.py 与 tests/embedders/test_factory.py 验证两个工厂的类结构与映射完整性,LLM 后端行为另有 tests/llms/test_openai.py、tests/llms/test_ollama.py、tests/llms/test_hf.py 等专项测试兜底。
总结
MemOS 的模型后端体系用一个统一的双工厂模式,把"选择模型提供商"从业务代码中彻底剥离:backend 字段是唯一需要修改的开关,其余全部由 Pydantic 配置类完成强类型校验与默认值管理。无论是本地 2 GB 以内的 Ollama 快速原型(qwen3:0.6b + nomic-embed-text)、需要可控推理的 DeepSeek 思维链场景,还是面向生产的主备容灾(backup_client)与嵌入向量缓存(CachingEmbedder),都可以在本文所述配置模式内直接落地。建议进一步阅读 KVCacheMemory 文档 了解 TTFT 优化,并结合 examples/basic_modules/llm.py 与 examples/basic_modules/embedder.py 实际运行验证。