如果一个 AI 助手真的长期陪你工作,它很快会遇到一个朴素但棘手的问题:过去聊过的东西越来越多,它到底该翻哪一段记忆?
最直觉的做法是把历史对话都存起来,等用户发问时用 embedding 找相似片段,再塞给大模型。但长期记忆不是普通文档检索。很多关键记忆并不一定和当前问题字面相似,它们可能是某次偏好、某个工具调用结果、某条隐藏约束,甚至是一段多轮任务中间产物。
MemSifter 的切入点很清楚:不要让主力大模型一边翻完整历史、一边完成当前任务;也不要在写入阶段做过重的图谱、摘要或层级索引。让一个更小的代理模型专门负责翻记忆,先想清楚当前任务需要什么,再把最有用的历史会话挑出来。
作用原理
MemSifter 的推理链路可以拆成三步。
1. Session Embedding
用 bge-m3 对历史 session 做粗筛,去掉明显无关的内容。
2. Session Ranking
MemSifter-4B-Thinking 进行 Think-and-Rank,输出最相关 session ID。
3. Chat LLM
任意 OpenAI 兼容对话模型读取精选记忆并生成最终回答。
三个关键设计
原始记忆按 session 存储
论文没有要求把记忆提前压缩成图谱或摘要,而是保留原始交互历史。系统会把历史按主题连续性切成一个个 session,每个 session 有自己的 ID。MemSifter 学的不是"把事实压进参数",而是"如何从外部原始记忆里找证据"。
embedding 只做粗筛
如果历史记忆太长,超过代理模型可处理的上下文窗口,系统先用轻量 embedding 模型做一次粗粒度筛选。这一步的职责很克制:减少长度和噪声,但不摘要候选 session,尽量保留原文细节。
MemSifter 做 Think-and-Rank
核心发生在这里。MemSifter 是一个 4B 级别的生成式 session ranker,基于 Qwen3-4B-Thinking 训练。它拿到当前问题和候选历史 session 后,会先分析当前任务需要哪些历史信息,再输出最相关 session 的 ID 排名。之后,主力 Chat LLM 只接收排名靠前的 session。
关键创新:用最终结果训练检索器
很多检索器优化的是 Recall、Precision、NDCG 这类检索指标。但在 LLM 记忆场景里,真正的问题是:这段记忆有没有让最终答案变好?
MemSifter 的训练目标因此不是"像不像人工标注的相关文档",而是"选出来的记忆是否提升了工作大模型的任务表现"。论文称之为 task-outcome-oriented reward,也就是面向任务结果的奖励。
Marginal Utility Reward
系统会比较两种情况:大模型不看记忆时表现如何;大模型看了 MemSifter 选出的 top-k 记忆后表现如何。两者的差值,就是这些记忆真正带来的增益。这样可以避免把"模型本来就会答对"的题错误归功给检索器。
Rank-Sensitive Reward
找到正确记忆还不够,还要把最关键的记忆排在最前面。MemSifter 借鉴 DCG 的递减权重思想,让靠前位置的有效增益获得更高奖励。论文还使用 Fibonacci 式 progressive cutoff,减少训练时反复调用工作大模型的成本。
实验读数
论文在八类长期记忆与深度研究任务上评估,包括 LoCoMo、LongMemEval、PersonaMem、PerM-V2、ZH4O、HotpotQA、WebWalker、WebDancer。
41.79 F1
LoCoMo 32K 设置:DeepSeek-V3.2-Exp 作为工作大模型时,MemSifter 的 F1 分数。
70.00 NDCG@1
检索质量:LoCoMo 32K 下显著高于 BGE-M3 与 ReasonRank 等基线。
3.98s
延迟:WebDancer 128K 上 MemSifter 4B 的单 H20 推理延迟。
49.87s
对比:同一条件下 DeepSeek-V3.2-Exp 直接读取 128K 历史的延迟。
这组结果的含义不是"以后不需要长上下文模型",而是:对于长期记忆系统,把全部历史都扔给大模型并不总是最优解。一个专门训练过的小模型,可能更适合做上下文入口处的筛选器。
如何使用
官方仓库给了三种层次:单样本快速推理、批量复现实验、训练自己的 ranker。第一次建议先跑通单样本链路。
安装与准备
git clone https://github.com/plageon/MemSifter.git
cd MemSifter
pip install torch sentence-transformers vllm openai pyyaml loguru numpy pandas
下载模型:
huggingface-cli download BAAI/bge-m3 --local-dir models/bge-m3
huggingface-cli download zstanjj/MemSifter-4B-Thinking \
--local-dir models/zstanjj/MemSifter-4B-Thinking
三阶段调用
import json
from memsifter.toolkit import SessionEmbedder, SessionRanker, LLMChat
with open("data/test_memory.json") as f:
entry = json.load(f)[0]
embedder = SessionEmbedder(model_path="models/bge-m3", device="cuda:0")
ranker = SessionRanker(
model_path="models/zstanjj/MemSifter-4B-Thinking",
device="cuda:1",
)
chat = LLMChat(
api_key="YOUR_KEY",
base_url="YOUR_BASE_URL",
model_name="YOUR_MODEL",
)
top_sessions = embedder.get_top_sessions(
question=entry["question"],
sessions=entry["haystack_sessions"],
dates=entry["haystack_dates"],
top_k=20,
)
ranked_sessions = ranker.rerank(
question=entry["question"],
pre_ranked_sessions=top_sessions,
top_k=5,
)
predicted_answer = chat.answer(
question=entry["question"],
ranked_sessions=ranked_sessions,
)
print(predicted_answer)
我的建议是:第一次不要急着训练。先把自己的历史交互整理成 session 格式,用官方 release 的 MemSifter-4B-Thinking 跑通"粗筛 → 重排 → 回答"链路。等确认它确实能在你的任务中提升答案质量,再考虑用自己的数据做 task reward 训练。
一句话总结
MemSifter 给 LLM 记忆系统提供了一个很实用的工程哲学:记忆不只是存储问题,更是"在当前任务中,什么历史最有用"的决策问题。
