换 embedding 模型或调维度,向来是 RAG 工程里动静最大的动作之一:维度定 768 还是 1024,意味着向量库的 schema、内存预算、索引参数全套重来(《增量更新与模型迁移》一篇讲过迁移的代价)。有没有办法让一个向量「按需伸缩」——预算宽裕时用全量维度,预算紧张时砍一半照样能用?嵌套表示学习(Matryoshka Representation Learning,MRL)给出的答案是肯定的,而且它已经悄悄成为主流嵌入服务的默认能力。这篇讲清它的原理边界和两种实用玩法。
名字的由来:俄罗斯套娃
MRL(Kusupati 等人,2022)的名字来自俄罗斯套娃:大娃娃里套着小娃娃,每个都能独立成件。MRL 训练出的嵌入向量也是这个结构——向量的前 k 维本身就是一个可用的 k 维嵌入。比如一个 1536 维的向量,取前 512 维、前 256 维、前 64 维,每一截都是一个「自成一体」的低维嵌入,都能拿去做相似度检索,只是粒度和精度不同。
直觉上可以这样理解:训练时不只要求「全量向量的相似度排序正确」,还同时要求每一个前缀截断的排序也正确。这个约束逼着模型把信息按重要性排布——最关键的语义信号挤在最前面的维度里,越往后越是精细化修正。结果就是前 64 维承载了大部分「粗语义」,后面的一千多维提供的是越来越细的分辨力。
工程上实现这个性质,训练侧的改动出奇地小:对若干个截断点(比如 64/128/256/512)各接一个损失函数,一起优化。这也是为什么 MRL 能迅速被主流模型吸收——它不是架构革命,是训练目标的一次扩展。
用法一:直接截断,降维省内存
最直接的用法是把截断当成降维手段。OpenAI 的 text-embedding-3 系列(2024 年初发布)是第一个把 MRL 暴露成 API 参数的主流服务:调用时传 dimensions,服务端直接返回截断后的向量,官方文档明确说明性能损失远小于同维度的传统模型——因为这是「原生支持降维」,而不是事后 PCA。本地开源阵营里,多个主流嵌入模型家族也已采用 MRL 训练。
算一笔账感受收益:1536 维 float32 是 6KB/条,截到 256 维是 1KB/条,内存与索引成本直接砍六分之,HNSW 的图也更好建、查询更快。注意两个纪律:其一,截断必须在入库与查询两侧同步做,一侧 1536 一侧 256,相似度没有意义;其二,截断点是模型训练时就定好的那些(64/128/256…),截在任意位置不一定有保障。
另一个边界要划清:MRL 的「可截」是训练出来的性质,不是所有向量都享有。拿一个普通训练的嵌入模型,把 768 维向量砍成 384 维——信息损失没有规律、语义排布没有按重要性重排,召回率往往崩得毫无悬念。「embedding 向量截断降维」这个网上流传的技巧,只对 MRL 模型成立。
用法二:级联检索,速度与精度兼得
MRL 更进阶的用法是级联(cascade)检索:用短前缀做粗筛、全量向量做精排。流程是——查询向量先截前 64/128 维,与库内同样截断的向量算距离,海选出 top 1000 的候选池(短向量点积的计算量和内存带宽都小数倍,这一步快很多);再用全量向量只对这一千条候选重打分,选出最终 top 10。
flowchart LR
Q["查询向量 1536 维"] --> T1["截前 128 维"]
T1 --> S1["粗筛:全库扫短向量"]
S1 --> C["候选池 top 1000"]
Q --> T2["保留全量 1536 维"]
C --> S2["精排:只对候选用全向量重打分"]
T2 --> S2
S2 --> R["最终 top 10"]
这和上一篇《向量压缩》讲的「粗排压缩 + 精排原始」是同一个范式,只是压缩手段从量化/PQ 换成了前缀截断。MRL 版本有个独特的优势:截断向量与全量向量来自同一次嵌入计算——粗筛和精排可以用同一份 embedding 缓存,不像 PQ 那样要维护码本,也不像量化那样有额外的编解码开销。对延迟敏感、吞吐巨大的检索首跳(比如日志检索、推荐候选),级联截断是内存和 CPU 双省的方案。
截断与压缩的叠加:两条路不冲突
MRL 截断与上一篇《向量压缩》的量化不是二选一,可以叠加:截断降维度(1536→256 维),量化降每维比特(float32→int8),两者相乘的压缩率相当可观——256 维 int8 相对 1536 维 float32 是 24 倍。叠加的顺序固定为「先截断后量化」:截断在嵌入服务的输出端完成(dimensions 参数),量化在入库管道里做,互不干扰。叠加时有一个验证纪律要追加:压缩组合的召回曲线必须整体重测——截断的损失和量化的损失不是简单相加,两者叠加后的分布可能有额外的交互劣化,实测说话。与 PQ 的叠加同理可行(对截断后的向量再做 OPQ-PQ),但注意截断后维度低、PQ 段数要相应减少(每段维度 6~16 的算术仍然适用)。
级联之外:截断做「查询预算分级」
MRL 还有一个较少被提及的用法:按查询的置信度动态选粒度。首跳用极短前缀(64~128 维)全库粗筛,如果粗筛结果的分数分布「头部陡峭」(第一名遥遥领先、断崖式下跌),说明匹配明确,直接精排前几名收工;如果分数分布「平坦」(前十名分数黏在一起),说明语义空间里这个查询有很多似是而非的候选,需要用全量向量精排更大的候选池。这是把「计算预算花给疑难查询」的自适应思路——《查询路由》的路由思想在维度维度的延伸,实现上只多一个「分布平坦度」的判断,对延迟敏感、成本敏感的超大库检索是个值得一试的杠杆。
生态现状与迁移提醒
模型侧的支持现状(截至 2026-11):商业 API 阵营里 OpenAI 的 text-embedding-3 系列原生暴露 dimensions 参数;开源阵营的多个主流嵌入模型家族已采用 MRL 训练,模型卡上通常标注「MRL / Matryoshka 支持」与推荐截断点。使用前核对两件事:模型卡是否明确支持、推荐的截断点列表(任意位置截断不保证效果,落在训练时的截断点上才有保障)。迁移提醒接上《增量更新与模型迁移》的纪律:从非 MRL 模型迁到 MRL 模型,仍是全量重建 + 双索引灰度的标准流程,MRL 只影响「迁移完成后的灵活性」,不改变「新旧向量不可混库」的铁律——别因为「都是 1536 维」就心存侥幸,维度相同不代表空间相同。
选型与验证建议
给三步可操作的判断。第一步,确认模型是否真 MRL:看模型卡或 API 文档有没有明确的截断支持(dimensions 参数、MRL 字样),没有就当普通模型用,别截。第二步,实测截断曲线:用真实查询集分别测 25%/50%/100% 维度下的 recall@k,损失曲线每个人的语料都不同——经验上截到一半召回损失常在极小范围,但「你的数据你自己量」。第三步,决定用法:单级截断适合纯降本,级联适合既降本又保召回的低延迟场景。
还有一点值得提醒:截断与重排序是互补而非竞争——短向量粗筛 + 原生 reranker 精排的组合(《一篇读懂 Reranker》)在召回和延迟上往往又优于纯向量级联,代价是多一跳模型推理。预算的分配顺序通常是:先白拿 MRL 的截断收益,再考虑要不要上 reranker。
级联的失效排查
级联检索上线后有自己的故障模式,三个高频症状与排查方向。症状一:粗筛丢真命中(精排结果明显不如全量暴力扫描)——粗筛前缀太短或候选池过小,把真答案挡在了精排门外;处置是加大粗筛召回量(前缀 128→256 或候选池 1000→3000),用评测集的召回对比定位丢失发生在哪一级。症状二:级联不提速(延迟与单级全量差不多)——常见原因是候选池精排走了逐条请求而非批量矩阵乘,精排层的批量化是第一排查点;另一可能是粗筛候选池过大(过采样倍数失控),画「池大小-延迟」曲线找拐点。症状三:截断后分数不可比(业务侧拿截断向量的分数做逻辑判断出现错乱)——截断向量的分数分布与全量不同,业务阈值要重新标定,分数只在同一粒度内可比这条纪律要写进接口文档。三个症状的排查都绕不开同一件工具:评测集——先有一把尺子,级联的每一级才有对错可言。
截断点的选择策略
截断粒度不是单选题,可以按用途分层配置:首跳用短前缀(128~256 维做第一跳检索,省内存省延迟),精排与存储用全量(rerank 或重打分环节拿全向量保证区分度),两套粒度并存于同一系统——这就是「多粒度索引」的朴素形态,MRL 让它无需两次嵌入计算(同一次推理截两次即可)。粒度选择的验证方法:把「用途 × 粒度」列成矩阵,逐一在评测集上量召回——首跳粒度的底线是「粗筛不丢」,精排粒度的底线是「排序正确」,两条底线各自达标即可,不必追求全粒度一致。另外提醒一个运维细节:多粒度并存时,库内同一 chunk 会存多份不同长度的向量,schema 里要标明粒度版本,避免增量更新时只刷了一份(《增量更新与模型迁移》的版本戳纪律在这里加倍重要)。
小结
嵌套向量的价值一句话:把「维度」从一次性的架构决策,变成了运行时可调的旋钮。训练时多挂几个前缀损失,换来推理后任意截断可用——API 一行参数降维省钱,级联检索兼顾速度与精度。而它的边界同样要刻在脑子里:可截是训练出来的特权,普通模型的向量随手一截就是灾难;截断必须两侧同步、实测曲线后再定粒度。
参考资料
- Kusupati et al., Matryoshka Representation Learning (arXiv:2205.13147) —— 前缀可用的训练方法与实验
- OpenAI: Embeddings API 与 dimensions 参数 —— text-embedding-3 系列的降维用法与官方说明
- 本系列前篇:《向量压缩:PQ、量化与二值嵌入》《一篇读懂 Embedding》《增量更新与模型迁移》
读者留言
COMMENTS 暂无还没有留言,来说第一句?