同一个问题,换个上下文就该检索出不同答案——嵌入模型终于学会"看人下菜碟"了

你有没有想过一件挺反直觉的事:现在所有的 embedding 模型,本质上都是"健忘症患者"。

把一段文本丢进去,它吐出一个向量。再丢一段,再吐一个。每段文本都是孤立编码的——它不知道前面发生了什么,也不在乎这段话在整个对话里排第几位。换句话说,它眼里只有这段文字本身,没有上下文,没有时间顺序,没有故事线这回事

平时做语义检索,这没什么问题。但一旦进入长对话、Agent 记忆这种动态场景,麻烦就来了。

举个具体的例子。用户上周说"我喜欢喝美式",这周又说"我最近改喝拿铁了"。现在你问 Agent:"我平时喝什么咖啡?"——一个静态 embedding 模型会怎么做?它会把"美式"和"拿铁"两段都召回,因为这两段在语义上都跟"咖啡偏好"高度相关。它根本分不清哪个是过时信息、哪个是最新状态。

这就是静态嵌入的死穴:同一个查询,永远只能检索出"语义上最像"的东西,而不是"在当前上下文里最该被检索"的东西。

EvoEmbedding 这篇论文想干的事,就是把 embedding 从"静态快照"变成"会进化的表征"。听起来有点玄,但它的设计其实简单得让我有点意外。我们慢慢聊。


核心摘要

EvoEmbedding 提出了一种可进化表征(evolvable representation)的嵌入范式:模型在顺序处理输入时,维护一个持续更新的潜在记忆(latent memory),并把这个记忆和当前文本内容一起编码,生成随上下文演化的 embedding。结果就是——同一个查询,在不同的上下文状态下,能检索出不同的目标,彻底跳出了"静态语义搜索"的框架。

为了让模型学会这个能力,作者构建了 EvoTrain-180K 数据集,用 18 万条合成样本做记忆与检索的联合优化。两个关键工程设计撑起了整个方法:记忆队列(memory queue)防止循环编码导致的表征坍塌,分段批处理(segment-batching)把训练速度拉快 3.8 倍。

效果相当能打:只用了同类模型不到 1% 的数据量、训练上下文长度不到测试场景的 1/10,EvoEmbedding-4B 在 10 个长上下文检索基准上的综合表现超过了 Qwen3-Embedding-8B、KaLM-Embedding-Gemma3-12B 这些更大的专用模型。更有意思的是——一个挂上 EvoEmbedding 的朴素 RAG 流程,居然打过了专门设计的 Agentic Memory 系统(如 Mem0、MemoryOS)。

我的判断:这篇论文最值钱的地方不在于跑分,而在于它换了一个看待 embedding 的视角。它说服了我——长上下文检索的瓶颈,可能从来就不是模型不够大、数据不够多,而是编码方式本身错了


论文信息

  • 标题:EvoEmbedding: Evolvable Representations for Long-Context Retrieval and Agentic Memory
  • 作者:Chang Nie, Chaoyou Fu, Junlan Feng, Caifeng Shan
  • arXiv2606.21649(cs.CL,2026 年 6 月 19 日提交)
  • 项目主页:https://clare-nie.github.io/EvoEmbedding

图1:EvoEmbedding 在长上下文检索与生成任务上的综合表现

图1:EvoEmbedding 家族(0.8B / 2B / 4B)在 10 个基准上的雷达图对比。可以看到,在处理动态上下文的任务(比如长期个性化记忆)上,它明显甩开了传统静态模型和 Agentic 记忆系统。注意那条蓝色的线几乎把所有竞品都包在里面。


问题到底出在哪:静态编码的"时间盲区"

先把痛点说透。

现有 embedding 模型的工作方式是这样的:给你一段文本 \(x\),模型 \(f\) 算出一个固定向量 \(v = f(x)\)。这个 \(v\) 只取决于 \(x\) 本身。无论 \(x\) 出现在对话开头还是结尾,无论它前面铺垫了什么,编码结果都一模一样。

这套范式在传统 IR(信息检索)里没毛病——你检索一篇文档,文档就是文档,跟它在哪个语料库里、排第几无关。但长上下文场景完全是另一回事。

我自己之前在做长对话记忆的时候碰到过一模一样的坑。用户的状态是会变的:今天的偏好可能推翻昨天的,一个事实可能被后续的对话更新。静态 embedding 把每一句话都当成独立的、永恒不变的事实来编码,结果检索的时候,新旧信息混在一起全召回,下游的生成模型被一堆自相矛盾的"历史"绕晕。

论文里有张图把这个对比讲得特别清楚。

图2:可进化表征 vs 静态检索,以及在 LongMemEval 上的 SOTA 表现

图2:(左)同一个查询在不同上下文下,EvoEmbedding 生成的是会演化的表征,能避开静态方法那种"召回过时信息"的毛病。(右)在 LongMemEval 上,挂了 EvoEmbedding-4B 的标准 RAG 超过了现有的记忆基线,而且 token 开销几乎为零。

那有人会说,长上下文的问题不是已经有一堆方案了吗?比如各种 latent memory 的工作,像 M+、LatentRAG 这些,都在用潜在表征来压缩历史。

对,但论文点出了这些方法的一个共同软肋:它们的记忆机制和 LLM 的自回归生成过程深度耦合。说人话就是,它们需要白盒访问模型内部的 hidden states 才能工作。这意味着什么?意味着你没法把它们用在 GPT-4o 这种只给你 API 的闭源商业模型上。而且,让同一个模型既管记忆又管生成、还不做显式隔离,很容易整出幻觉这种不可预测的行为。

EvoEmbedding 的切入点就在这——把"记忆"这件事从生成里剥离出来,专门做成一个检索表征模块。这个解耦,是它后面所有设计的起点。


方法核心:让记忆"流动"起来

EvoEmbedding 的整体思路,一句话概括:模型一边顺序读输入,一边维护一个不断更新的潜在记忆;编码每段文本时,把这个记忆和文本内容揉在一起,生成会随上下文进化的 embedding。

来看架构图。

图3:EvoEmbedding 整体架构

图3:在第 t 步处理输入分段时,模型并行做两件事。(左)记忆进化:LLM 把当前分段和前一步的记忆压缩进可学习的 token,投影后更新一个 FIFO 潜在记忆队列。(右)表征生成:把历史潜在记忆和当前分段结合,生成一个可进化的检索 embedding。

两条并行的任务流

模型在每个时间步 \(t\) 做两件事,可以用两个公式概括:

\[\mathbf{\tilde{M}_t} = \pi_{\theta_m}(x_t, \mathbf{M_{t-1}})\]
\[\mathbf{v_t} = \pi_{\theta_r}(x_t, \mathbf{M_{t-1}})\]

第一条是记忆进化:拿当前分段 \(x_t\) 和上一步的记忆 \(\mathbf{M_{t-1}}\),生成 \(K\) 个新的潜在 token \(\mathbf{\tilde{M}_t}\)

第二条是表征生成:同样拿 \(x_t\)\(\mathbf{M_{t-1}}\),但这次输出的是一个用于检索的向量 \(\mathbf{v_t}\)

注意这里的精巧之处——查询阶段只跑第二条任务流。也就是说,你拿一个 query 进来,它会用当前积累的记忆状态 \(\mathbf{M_T}\) 去编码,所以同一个 query 在不同记忆状态下,编出来的向量就是不一样的。这就是"可进化"的本质。

\(\theta_m\)\(\theta_r\) 是模型里负责这两个任务的不同参数——作者用了 multi-LoRA 设计,把记忆进化和表征生成两个能力解耦开,推理时可以灵活切换。

记忆队列:防坍塌的关键

这部分我觉得是整篇论文最有工程智慧的地方。

如果你让一个模型反复地、循环地编码自己生成的记忆,会发生什么?表征坍塌(representation collapse)。这是 RNN 时代就有的老问题——信息在循环里反复传递,最后所有的表征都糊成一团,区分度全没了。

EvoEmbedding 用一个 FIFO(先进先出)队列来管理记忆:

\[\mathbf{M_t} = \text{Queue}(\mathbf{M_{t-1}}, f_m(\mathbf{\tilde{M}_t}))\]

队列容量 \(C = L \times K\),存的是最近 \(L\) 步生成的潜在表征。\(f_m(\cdot)\) 是个投影器,把新生成的 token 映射到共享记忆空间。

这个队列设计的妙处在于两点:

第一,有界循环。 任何一个历史记忆,最多被循环编码 \(L\) 次就会被挤出队列。这直接掐断了无限循环导致的坍塌——所以 EvoEmbedding 能直接在长上下文上训练,不需要那种从短到长的课程学习(curriculum learning)。这点后面消融实验会证明它有多关键。

第二,有界容量。 严格限制记忆大小,既把计算复杂度框住了,又逼着模型学会在每一步把新知识和历史状态融合——因为它没法把所有东西都记下来,必须做取舍。

论文给了个很形象的数字:相比 M+ 那种缓存逐层特征的做法,EvoEmbedding 只存 \(C = 512\) 个潜在 token,内存占用大概也就相当于编码一张图片。

分段批处理:3.8 倍加速从哪来

顺序处理分段有个天然的效率问题——你得一段一段地前向传播,GPU 利用率低得可怜。

作者的解法叫动态分段批处理(Dynamic Segment-Batching):不再一段一段跑,而是把 \(k\) 个连续分段拼在一起并行处理。\(k\) 是动态决定的,保证拼接后的总长度不超过某个阈值(比如 2048 token)。

记忆进化的公式就变成了批处理形式:\(\mathbf{\tilde{M}_{t:t+k}} = \pi_{\theta_m}(x_{t:t+k}, \mathbf{M_{t-1}})\)

这一招把训练速度拉快了 3.8 倍,而且——这点让我有点意外——性能不降反升。后面消融实验会看到具体数字。

训练目标:一个被冻住的 backbone

训练用的是两个损失的组合:

\[\mathcal{L} = \mathcal{L}_{mem} + \mathcal{L}_{con}\]

\(\mathcal{L}_{mem}\) 是记忆生成损失,用标准交叉熵。这里有个设计我得专门拎出来说——预测答案时,作者把 backbone LLM 的参数冻住,并且关掉所有 LoRA adapter

\[\mathcal{L}_{mem} = -\sum_{j=1}^{|y|} \log P(y_j \mid y_{<j}, q, \mathbf{M}_t)\]

为什么要这么做?因为这样一来,loss 的梯度会穿过冻住的 backbone,直接反传到记忆 \(\mathbf{M}_t\) 上。这就隐式地强迫记忆模块生成出"backbone 原生语义空间能听懂"的潜在状态。这个设计挺聪明的——它保证了记忆不是自说自话,而是和基座模型的理解能力对齐的。

\(\mathcal{L}_{con}\) 是对比损失,用来把 query 表征和相关上下文对齐。作者还加了个长度加权因子 \(\log(N+1)\),因为负样本数量 \(N\) 会随输入长度剧烈变化,这个因子能自适应地校准 loss 尺度,让不同长度的序列都能稳定优化。


数据:EvoTrain-180K 怎么造出来的

模型再巧,没有合适的数据也学不会"看上下文检索"这个能力。标准的检索数据集都是孤立的 query-document 对,根本不包含动态上下文。所以作者自己造了一个。

图4:EvoTrain-180K 数据构建流程

图4:三阶段的自动化数据合成流程——(1)跨领域、跨格式、跨长度的原始上下文构建;(2)用 LLM 和 40 多种模板生成语义型和推理型查询;(3)做正负样本标注和噪声过滤。

三个阶段拆开看:

Stage 1:原始上下文构建。 造了三类上下文——从 FineWeb 采样的多样化网页文本(用滑动窗口切成顺序分段)、LLM 合成的多轮人格驱动对话、以及从文本/对话里抽取的各类记忆。

Stage 2:动态 QA 生成。 这步有两个关键设计:预定义了 40 多种模板类型(比如指代消解、时序理解),用不同类型和规模的 LLM 生成问题,既保证有简单的语义匹配题,也有需要深度理解上下文的复杂题。

Stage 3:检索标注与验证。 用 Gemini-3.1-Pro-Preview 做检索标注和样本验证,识别出 query 相关分段作为正样本,同时排除幻觉、剔除那些靠通用知识就能答、不依赖给定历史的问题。

最后产出 184,137 条高质量样本。每条样本严格控制在 12K token、256 个分段以内。

这里有个数字值得停一下:EvoEmbedding 用的训练数据量不到同类 embedding 模型的 1%,训练上下文长度不到测试场景的 1/10。 用这么点数据撬动 SOTA,本身就说明问题不在数据量,而在范式。


实验:朴素 RAG 打过专用记忆系统?

主结果:小模型吊打大模型

先看检索任务的主表。

模型 Size Dim ESG LoCoMo LongMemEval REALTALK QASPER PeerQA CovidQA MLDR Overall
Multilingual-e5-large 0.6B 1024 51.4 65.6 80.5 54.5 72.6 40.6 89.5 97.0 69.0
KaLM-Embedding-Gemma3 12B 3840 63.6 58.4 93.0 54.9 73.8 44.7 93.0 100.0 72.7
Qwen3-Embedding-8B 8B 4096 63.6 49.6 87.9 50.4 70.5 41.2 93.9 95.0 69.0
EvoEmbedding-0.8B 0.8B 1024 85.7 63.0 83.0 58.0 83.1 48.1 94.4 98.0 76.7
EvoEmbedding-2B 2B 1024 86.7 74.1 90.6 60.7 87.0 51.8 95.0 98.0 80.5
EvoEmbedding-4B 4B 1024 84.0 76.3 91.7 62.6 85.1 51.7 94.9 98.0 80.5

(Recall@10,节选关键行)

把这张表看明白,有几个点很扎眼:

EvoEmbedding-4B 的 Overall Recall@10 做到 80.5,比第二名 KaLM-Embedding-Gemma3-12B(72.7)高了 7.8 个点。NDCG@10 那栏也是同样的故事,65.2 vs 57.1,高 8.1 个点。

但真正让我注意的是那个 0.8B 的小不点——它只有 0.8B 参数、1024 维向量,综合分却到了 76.7,把 8B、12B 的大块头全压在身下。你想想看,参数差了一个数量级,embedding 维度也只有人家的 1/4 到 1/3,结果反而赢了。这不是参数堆出来的胜利,是范式的胜利。

再看生成任务。

图5:朴素 RAG 用不同检索方法的生成精度对比

图5:在不同检索规模(Top-k)下,挂 EvoEmbedding-4B 的朴素 RAG 流程综合表现最好。注意 LoCoMo 上的精度一直涨到 k=32 都没饱和,而其他数据集大多在 k=8 或 k=16 见顶后略降——这是因为太大的上下文窗口会引入干扰噪声。

朴素 RAG vs Agentic Memory:这个对比有点狠

这是论文最有冲击力的部分。来看 LongMemEval 的细分表。

方法 Temp Multi Knowledge User Assistant Preference Overall
Full Context 33.1 35.6 76.9 82.9 87.5 50.0 54.8
Mem0 41.9 28.1 28.6 55.3 26.1 81.8 39.5
MemoryOS 28.6 36.8 61.5 72.9 92.9 33.3 49.6
A-MEM 51.9 51.1 76.9 90.0 96.4 40.0 65.2
LightMem 54.2 51.9 66.7 80.0 31.3 80.0 70.2
Qwen3-Embedding-8B (RAG) 57.9 62.4 76.9 90.0 98.2 63.3 71.4
EvoEmbedding-4B(RAG) 63.2 71.4 84.6 98.6 100.0 60.0 77.6

一个只用了 Top-8 检索分段的标准朴素 RAG,挂上 EvoEmbedding-4B,综合精度 77.6%,把 LightMem(70.2%)这种专门设计的 Agentic Memory 系统甩开了 7 个多点。Single-User 子任务 98.6%、Single-Assistant 直接 100.0%。

而且——它还超过了 Full Context 基线(54.8%)整整 22.8 个点。这说明 EvoEmbedding 不只是"找得准",它还能主动过滤掉那些会干扰生成模型的过时、噪声历史

更关键的一笔:图2 右边那个对比里提到,EvoEmbedding 的 token 开销几乎为零,因为它不需要像 Agentic 系统那样单独跑一个记忆构建阶段——它的潜在记忆是在编码阶段顺手建好的,测试时根本不依赖生成模型。

当然,论文也老实承认了短板:在 LoCoMo 的 Temporal 和 Open-domain 子任务上,EvoEmbedding 还是稍逊于高度专门化的 LightMem。这点我挺欣赏,没有把所有指标都吹成第一。

即插即用:给现有记忆系统做增强

EvoEmbedding 还能当成一个 plug-and-play 模块,去升级现有的记忆管线。作者在 LoCoMo 上重做了 A-MEM、LightMem、MemoryOS,用它做重排器。

结果是:给 A-MEM 带来 +19.2%、给 MemoryOS 带来 +20.5% 的绝对提升,而且在三个框架上都稳定超过了"推理策略"和 Qwen3-Reranker-4B 的重排策略。因为它只维护固定大小的潜在记忆、避开了二次复杂度,GPU 开销跟 Qwen3-Reranker-4B 相当。

时序敏感性:可视化看"进化"是真的

光说"可进化"还不够,得证明模型真的捕捉到了时间顺序。这是我觉得最漂亮的一个分析实验。

图6:长上下文检索中的时序查询敏感性分析

图6:用"firstly""lastly""in the middle"三种时间关键词去查询 256 个分段。(上排)相似度曲线——EvoEmbedding 在 "lastly" 时相似度随时间递增、在 "firstly" 时在开头分段急剧峰值;而静态模型的曲线全都纠缠重叠在一起。(下排)t-SNE 可视化——基线模型的表征完全混在一起,EvoEmbedding 的潜在空间则按时间位置干净地分成了不同簇。

这张图把"静态 vs 进化"的差别讲得淋漓尽致。Qwen3-Embedding-8B、KaLM 这些静态模型,面对"firstly"和"lastly"两个截然相反的时序意图,相似度曲线几乎重合——它们压根分不清。EvoEmbedding 则能精准解耦:问"最先"就在开头峰值,问"最后"就随时间递增爬到末尾。

下排的 t-SNE 更直接——基线的表征糊成一团,EvoEmbedding 按时间位置分成了清晰的、不重叠的簇。这就是"持续更新的潜在记忆"把时序信息编进表征的视觉证据。


消融:哪些设计是命根子

消融表把每个组件的贡献量化得很清楚。

策略 训练时间(h) LoCoMo LongMemEval PersonaMem-32K PersonaMME-32K PersonaMME-128K Overall
EvoEmbedding-4B 26.6 69.9 76.6 56.2 72.0 72.8 69.5
w/o Memory Queue 91.3 17.0 10.0 46.9 64.3 64.3 40.6(降 28.9)
w/o Memory Loss 27.7 15.2 11.4 48.9 65.5 64.3 41.1(降 28.4)
w/o Length-Weighting 26.5 68.4 73.8 54.5 71.6 73.2 68.3(降 1.2)
w/o Segment-Batching 101.4 66.0 75.0 54.3 71.2 71.6 67.6(降 1.9)

这张表的信息量很大:

记忆队列和记忆损失是绝对的命根子。 去掉任意一个,LoCoMo 和 LongMemEval 上直接崩盘——掉了超过 50%(LoCoMo 从 69.9 跌到 17.0)。这就是表征坍塌的真实代价。另外三个数据集掉得轻一些(约 8%),是因为它们是选择题形式。

为什么去掉队列训练时间还暴涨到 91.3 小时?因为没了队列的有界机制,每步要更新整个 512 容量的记忆,而不是只生成 16 个 token。队列把生成开销限制在每步 \(K=16\) token,顺手把训练效率提了 3.4 倍。

分段批处理是效率的命根子。 训练时间从 101.4 小时压到 26.6 小时,3.8 倍加速实锤。而且综合性能还涨了 1.9 个点——这个"既快又好"的结果,我一开始是有点怀疑的,但消融数据摆在这。

长度加权贡献相对小(1.2 个点),但它解决的是"模型偏向短序列"这个隐蔽问题,算是锦上添花。

再补一个效率对比表,这里有个需要客观看待的 trade-off:

模型 Size 编码时间(s) 峰值显存(GB) 最佳 Top-k 精度(%)
Qwen3-Embedding-8B 8B 5.52 43.1 k=16 73.2
KaLM-Embedding-Gemma3 12B 9.89 69.3 k=4 72.8
EvoEmbedding 4B 22.08 20.9 k=8 77.6

EvoEmbedding 显存占用最低(20.9GB,因为只维护固定大小的潜在记忆),精度最高。但代价是编码时间显著更长(22.08s vs 5.52s)——因为它要顺序处理、连续构建记忆,没法像静态模型那样并行编码所有分段。这是它范式上的固有代价,论文也没藏着掖着。


我的判断:范式比跑分更值钱

聊完了,说说我的真实看法。

先说亮点。这篇论文最打动我的,不是那些超过 8B、12B 模型的跑分数字,而是它重新定义了 embedding 该是什么。静态编码这个范式我们用了太久,久到几乎没人去质疑"为什么一段文本的向量必须是固定的"。EvoEmbedding 给了一个反例——当上下文是动态的、有时序的、需要持续追踪状态的,embedding 就该跟着进化。这个 insight 本身就很有价值。

它的工程设计也确实扎实。记忆队列防坍塌、分段批处理提速、冻结 backbone 对齐语义空间——每一个都不是花架子,消融实验把它们的贡献量化得明明白白。尤其是"朴素 RAG 打过专用 Agentic Memory 系统"这个结果,对整个 Agent 记忆领域是有冲击力的:它在暗示,与其在外部搭一套复杂的记忆管线,不如把时序和上下文感知直接编进表征里。这个方向如果成立,能省掉很多工程复杂度。

但我也有几个保留意见。

第一,编码延迟是个真问题。22 秒 vs 5 秒的差距,在很多实时检索场景下是致命的。论文把它归为"范式固有代价",但这意味着 EvoEmbedding 更适合离线建库、对延迟不敏感的场景,在线实时检索可能水土不服。

第二,数据全是合成的。EvoTrain-180K 的上下文、QA、标注几乎全靠 LLM 生成(Gemini、各种 LLM)。合成数据的质量天花板和分布偏差,是个绕不开的隐患。论文说做了幻觉过滤,但合成数据里那种微妙的"模型味"会不会让模型学到某种捷径,这点我不太确定,得看后续更多 out-of-domain 的验证。

第三,LoCoMo 的 Temporal 子任务还是输给了 LightMem。一个号称"时序感知"的模型,在最考验时序的子任务上没拿第一,这说明它的时序能力还有上限,离"完全解决"还有距离。

总的来说,这是一篇我会推荐细读的论文。它的价值不在于刷了多少榜,而在于它提供了一个值得长期下注的方向——可进化表征。如果你在做长上下文检索、对话记忆、或者 Agent 的长期记忆系统,这个思路真的值得试试。哪怕只是把"embedding 必须静态"这个隐含假设拿出来重新审视一遍,都已经够本了。

至于它会不会成为未来长上下文检索的标配——我觉得方向是对的,但那个编码延迟问题不解决,大规模落地还得再等等。


觉得有启发的话,欢迎点赞、在看、转发。跟进最新AI前沿,关注我