MemOS PreferenceTextMemory 深度指南构建基于用户偏好的明文记忆系统【免费下载链接】MemOSSelf-evolving memory OS for LLM AI Agents: ultra-persistent memory, hybrid-retrieval, and cross-task skill reuse, with 35.24% token savings and DeepSeek Harness support.项目地址: https://gitcode.com/gh_mirrors/memos/MemOS导读PreferenceTextMemory是 MemOS 中专门用于存储和管理用户偏好的明文textual记忆模块它通过 LLM 自动从对话中抽取显式与隐式偏好借助向量嵌入实现语义检索并将偏好持久化到向量数据库Milvus / Qdrant中。本文以官方文档为主体骨架结合 源码实现 与 示例配置 进行纵深解析读完你将掌握PreferenceTextMemory的完整 API、配置方法、底层抽取/去重/检索原理以及一套可直接复制运行的端到端示例。为什么需要偏好记忆大模型本身不具备长期记忆能力对话一结束用户偏好也随之丢失。PreferenceTextMemory解决的核心问题是让系统记住用户喜欢什么、不喜欢什么并在后续交互中基于这些偏好提供个性化服务。优势特性从 官方文档 与源码实现来看该模块具备以下能力双重偏好提取自动识别显式偏好与隐式偏好二者使用独立的 LLM 提示词模板分别抽取见 extractor.py 中extract_explicit_preference与extract_implicit_preference语义理解使用向量嵌入Embedding理解偏好的深层含义而非简单关键词匹配智能去重NaiveAdder通过 LLM 判断新偏好与已存偏好是否重复/冲突自动决定新增、更新还是跳过见 adder.py精准检索基于向量相似度的语义搜索检索时并行查询显式/隐式两个集合并支持可选的重排序Reranker与阈值过滤持久化存储支持向量数据库Milvus / Qdrant同时支持将全部偏好序列化到本地 JSON 文件实现备份与恢复可扩展性Extractor、Adder、Retriever 均采用工厂模式可替换后端实现支持大规模偏好数据管理个性化增强通过user_id、session_id等元数据为每个用户维护独立的偏好档案。应用场景个性化对话代理记住用户喜好让回答更贴合个人口味智能推荐系统基于偏好向量检索做个性化推荐客户服务系统为 VIP 用户提供定制化服务如偏好简短回答则自动压缩回复内容过滤系统根据偏好筛选内容例如过滤用户明确表示不感兴趣的话题学习辅助系统识别用户学习风格如喜欢代码示例需要详细解释自适应调整教学方式。简单来说凡是需要构建记住用户喜好并据此提供个性化服务的系统PreferenceTextMemory都是合适的落点。核心概念与工作流程记忆结构在 MemOS 中偏好记忆以PreferenceTextMemory表示每条记忆都是一个TextualMemoryItem存放于向量数据库示例配置使用 Milvus。TextualMemoryItem的结构定义见 item.pyid唯一记忆 ID类型为 UUID 字符串省略时自动生成memory主要文本即偏好记忆的核心内容对应抽取结果中的context_summarymetadata偏好元数据包括层次结构信息、嵌入向量、标签、实体、来源和状态等具体类型为PreferenceTextualMemoryMetadata。偏好记忆按来源分为两类在存储时分别落入不同的集合collection显式偏好记忆explicit_preference用户明确表达的喜好或厌恶。示例我喜欢深色模式我不吃辣请用简短的回答我更喜欢技术文档而不是视频教程隐式偏好记忆implicit_preference从用户行为和对话模式中推断出的偏好。示例用户总是询问代码示例 → 偏好实践导向的学习用户经常要求详细解释 → 偏好深入理解用户多次提到环保话题 → 关注可持续发展智能提取PreferenceTextMemory使用 LLM 自动从对话中同时提取显式和隐式偏好无需手动标注。从源码看NaiveExtractor.extract会对每个文本块并行提交显式与隐式抽取任务extractor.py并在抽取前调用detect_lang自动选择中/英文提示词模板。元数据字段PreferenceTextualMemoryMetadataPreferenceTextualMemoryMetadata继承自TextualMemoryMetadata含user_id、session_id、status、tags、source、updated_at等通用字段并新增以下偏好专属字段定义见 item.py字段类型描述preference_typeexplicit_preference/implicit_preference偏好记忆类型决定写入哪个集合dialog_idstr对话 ID用于关联偏好记忆与特定对话original_textstr原始文本包含用户偏好信息的对话原文embeddinglist[float]嵌入向量用于语义搜索和检索preferencestr用户偏好信息LLM 抽取出的偏好描述created_atstr创建时间戳ISO 8601mem_cube_idstr记忆立方 ID用于关联偏好记忆与特定记忆立方scorefloat检索结果中偏好记忆与 query 的相似度评分核心工作流当运行偏好记忆示例时数据流依次经历四个阶段抽取Extract使用 LLM 从原始对话文本中提取结构化偏好记忆显式 隐式嵌入Embed为抽取出的偏好内容context_summary生成向量嵌入供相似性搜索使用存储Store将偏好记忆按preference_type分别写入 Milvus 的explicit_preference/implicit_preference集合同时更新各元数据字段搜索Search通过向量相似度查询并行检索两个集合并融合返回最相关的偏好记忆。API 参考初始化PreferenceTextMemory(config: PreferenceTextMemoryConfig)构造时传入一个PreferenceTextMemoryConfig配置对象。从 preference.py 源码可见初始化过程中会通过各工厂自动装配全套子组件LLMFactory.from_config(config.extractor_llm)→ 抽取/去重用的 LLMVecDBFactory.from_config(config.vector_db)→ 向量数据库Milvus / QdrantEmbedderFactory.from_config(config.embedder)→ 嵌入模型RerankerFactory.from_config(config.reranker)→ 可选重排序器ExtractorFactory/AdderFactory/RetrieverFactory→ 抽取器、写入器、检索器默认 backend 均为naive。核心方法以下方法与 官方文档 保持一致并可在 preference.py 中找到对应实现方法描述源码要点get_memory(messages, type, info, **kwargs)从原始对话中抽取偏好记忆委托Extractor.extract支持并发抽取search(query, top_k, ...)使用向量相似度检索 top-k 偏好记忆强制附加{status: activated}过滤条件load(dir)从存储的 JSON 文件中加载偏好记忆读取dir/memory_filename并按集合写入向量库dump(dir)将所有偏好记忆序列化到目录中的 JSON 文件遍历vector_db.config.collection_name逐个集合导出add(memories)批量添加偏好记忆到向量数据库委托Adder.add内部做重复/冲突判定get_with_collection_name(collection_name, memory_id)通过集合名称和记忆 ID 获取特定偏好记忆单条精确查询异常统一转为ValueErrorget_by_ids_with_collection_name(collection_name, memory_ids)通过集合名称和记忆 IDs批量获取偏好记忆批量查询并构造TextualMemoryItem列表get_all()获取所有偏好记忆返回{explicit_preference: [...], implicit_preference: [...]}字典get_memory_by_filter(filter, page, page_size)根据过滤条件获取偏好记忆跨集合过滤按created_at倒序支持分页delete(memory_ids)删除指定 ID 的偏好记忆在所有集合上执行删除delete_by_filter(filter)根据过滤条件删除偏好记忆在所有集合上执行条件删除delete_with_collection_name(collection_name, memory_ids)删除指定集合中指定 IDs 的偏好记忆仅作用于单个集合delete_all()删除所有偏好记忆先删除集合再重建delete_collectioncreate_collection文件存储当调用dump(dir)时MemOS 将所有偏好记忆序列化到目录中的 JSON 文件中dir/config.memory_filename默认文件名为textual_memory.json定义于 memory.py 的BaseTextMemoryConfig.memory_filename而 示例配置 中显式设置为preference_textual_memories.json。load(dir)会按同一文件名回读逐集合调用vector_db.add恢复到向量库中——因此备份与恢复是一对对称操作建议始终使用相同目录与配置。配置深度解析读懂 preference_config.json示例配置 完整定义了一个可运行的PreferenceTextMemory实例Ollama LLM Milvus Ollama Embedder{ extractor_llm: { backend: ollama, config: { model_name_or_path: qwen3:0.6b, temperature: 0.0, remove_think_prefix: true, max_tokens: 8192 } }, vector_db: { backend: milvus, config: { collection_name: [explicit_preference, implicit_preference], vector_dimension: 768, distance_metric: cosine, uri: ./milvus_demo.db } }, embedder: { backend: ollama, config: { model_name_or_path: nomic-embed-text:latest } }, reranker: { backend: cosine_local, config: { level_weights: { topic: 1.0, concept: 1.0, fact: 1.0 }, level_field: background } }, extractor: { backend: naive, config: {} }, adder: { backend: naive, config: {} }, retriever: { backend: naive, config: {} }, memory_filename: preference_textual_memories.json }各配置项的作用对应 memory.py 中PreferenceTextMemoryConfig的字段定义extractor_llm记忆抽取与去重判定所用的 LLM。推荐temperature: 0.0因为抽取与判定任务需要稳定、确定性的输出remove_think_prefix: true用于剥离模型思考前缀保证返回的 JSON 可被json.loads正确解析。vector_db偏好记忆的存储后端。关键点有两个collection_name必须是[explicit_preference, implicit_preference]——源码中get_all直接硬编码这两个集合名Adder也依据preference_type映射到这两个集合见 adder.pyvector_dimension示例 768必须与 Embedder 输出维度一致例如nomic-embed-text输出 768 维向量distance_metric使用cosine余弦相似度。embedder向量嵌入模型负责把偏好文本转成向量示例为 Ollama 的nomic-embed-text:latest。reranker可选检索后的重排序器。示例使用cosine_local在检索阶段对召回结果按相似度重新打分排序见 retrievers.py。extractor/adder/retriever三个子流程的后端选择示例均使用naive当前AdderConfigFactory的backend_to_class仅注册了naive见 config.py。memory_filenamedump/load使用的备份文件名可自定义以区分不同类型的记忆。除配置项外还有两个影响运行时行为的环境变量值得注意PREFERENCE_ADDER_MODE写入去重模式fast默认基于单条召回 快速 LLM 判定或fine精细判定支持多候选合并见 adder.pyPREFERENCE_SEARCH_THRESHOLD检索结果相似度阈值默认0.0低于该分数的偏好会被过滤掉见 retrievers.pyDEDUP_PREF_EXP_BY_TEXTUAL置为true时开启显式偏好与文本记忆库的跨库去重见 adder.py。动手实践从 0 到 1创建 PreferenceTextMemory 配置配置需要定义三部分embedding 模型如nomic-embed-text:latest、向量数据库后端如 Milvus、以及可选的 LLM 记忆抽取器。可以直接复用仓库提供的 示例配置from memos.configs.memory import PreferenceTextMemoryConfig config PreferenceTextMemoryConfig.from_json_file(examples/data/config/preference_config.json)运行前请确保Ollama 已拉取qwen3:0.6b与nomic-embed-text:latest模型且 Milvus 使用本地文件模式uri: ./milvus_demo.db即可零依赖运行。初始化 PreferenceTextMemoryfrom memos.memories.textual.preference import PreferenceTextMemory preference_memory PreferenceTextMemory(config)构造函数会按上文所述自动装配 LLM、向量库、Embedder、Reranker 以及抽取/写入/检索三大组件。抽取结构化记忆使用记忆抽取器将对话解析为多个TextualMemoryItem。注意输入格式是list[MessageList]即多轮对话的列表scene_data [[ {role: user, content: Tell me about your childhood.}, {role: assistant, content: I loved playing in the garden with my dog.} ]] memories preference_memory.get_memory(scene_data, typechat, info{user_id: 1234}) preference_memory.add(memories)typechat会写入元数据的type字段标识来源类型info{user_id: 1234}用于为记忆打上用户维度标识实现每用户独立偏好档案info中不属于记忆元数据字段的键值会被折叠到metadata.info中见 extractor.py抽取器内部会先将长对话切块Splitter.split_chunks(..., split_typeoverlap)再并发执行显式/隐式偏好抽取。搜索记忆results preference_memory.search(Tell me more about the user, top_k2)search返回list[TextualMemoryItem]其底层执行过程见 preference.py 与 retrievers.py自动附加{status: activated}过滤只检索有效记忆将 query 通过 Embedder 转为向量并行对explicit_preference与implicit_preference两个集合各召回top_k * 2条候选分别按相似度排序经 Reranker 重排、阈值过滤后合并返回。备份与恢复支持偏好记忆的持久化存储与随时重载preference_memory.dump(tmp/pref_memories) preference_memory.load(tmp/pref_memories)dump(tmp/pref_memories)会在该目录下生成preference_textual_memories.json文件名取自配置JSON 以集合名分组组织所有记忆load(tmp/pref_memories)读回该文件逐集合写入向量库若文件不存在会记录 warning 而非抛错具备一定的容错性。完整代码示例以下示例整合了上述所有步骤提供一个端到端的完整流程以 Milvus 为例——复制即可运行from memos.configs.memory import PreferenceTextMemoryConfig from memos.memories.textual.preference import PreferenceTextMemory # 创建 PreferenceTextMemory config PreferenceTextMemoryConfig.from_json_file(examples/data/config/preference_config.json) preference_memory PreferenceTextMemory(config) preference_memory.delete_all() # 清理历史数据保持环境干净 scene_data [[ {role: user, content: Tell me about your childhood.}, {role: assistant, content: I loved playing in the garden with my dog.} ]] # 从原始对话中抽取偏好记忆并添加到 Milvus 数据库中 memories preference_memory.get_memory(scene_data, typechat, info{user_id: 1234}) preference_memory.add(memories) # 搜索记忆 results preference_memory.search(Tell me more about the user, top_k2) for item in results: print(item.id, item.memory, item.metadata.preference_type, item.metadata.score) # 持久化存储偏好记忆 preference_memory.dump(tmp/pref_memories)源码级原理补充抽取器显式与隐式偏好如何被同时发现NaiveExtractorextractor.py对每个切块执行两条并行流水线显式偏好使用NAIVE_EXPLICIT_PREFERENCE_EXTRACT_PROMPT中英文各一套模板存放于 templates让 LLM 输出 JSON 数组再将explicit_preference字段改名为preference写入元数据隐式偏好使用NAIVE_IMPLICIT_PREFERENCE_EXTRACT_PROMPT从多轮对话模式中推断偏好同样产出结构化 JSON。两者的记忆正文均取 LLM 返回的context_summary并用embedder.embed([context_summary])[0]生成向量dialog_id使用uuid4()生成created_at取当前 ISO 时间。若 LLM 返回内容无法解析为 JSON抽取器会记录日志并返回None保证单条失败不影响整体流程。写入器智能去重与冲突合并NaiveAdder.addadder.py对每条新记忆先在对应集合中按user_id过滤检索 top-5 候选再调用 LLM 判定fast 模式若召回分数低于 0.5 直接新增否则用NAIVE_JUDGE_UPDATE_OR_ADD_PROMPT判断新旧内容是否表达同一偏好——相同则更新旧记录不同则新增fine 模式用NAIVE_JUDGE_UPDATE_OR_ADD_PROMPT_FINE做更精细的多候选判定支持合并多条相关偏好跨库去重当DEDUP_PREF_EXP_BY_TEXTUALtrue且存在text_mem时还会把显式偏好与普通文本记忆库比对防止偏好与事实记忆重复。这就是官方文档中自动检测和合并重复或冲突的偏好的底层实现。检索器双集合并行召回NaiveRetriever.retrieveretrievers.py使用线程池同时检索显式与隐式偏好集合各自召回top_k * 2后通过 Rerankernaive或original_text模式重排再按PREFERENCE_SEARCH_THRESHOLD过滤最终将两组结果拼接返回。这种先扩召回、再精排、后过滤的流水线在保证语义覆盖的同时提升了检索精度。小结PreferenceTextMemory是 MemOS 中实现用户画像能力的关键模块LLM 负责从对话中自动挖掘显式与隐式偏好向量库负责存储与语义检索写入器负责去重与冲突合并而dump/load则让偏好数据可以随时备份与恢复。开发者只需一份 配置文件 加几行调用代码即可为对话代理、推荐系统、客服系统等场景注入持久的个性化记忆能力。相关完整实现可继续阅读 preference.py、item.py 以及 配置定义。【免费下载链接】MemOSSelf-evolving memory OS for LLM AI Agents: ultra-persistent memory, hybrid-retrieval, and cross-task skill reuse, with 35.24% token savings and DeepSeek Harness support.项目地址: https://gitcode.com/gh_mirrors/memos/MemOS创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
