把一个文档压成一个向量,曾是 RAG 的常识,现在被它自己拆了回去
故事是这样的
前两天刷 Hugging Face 的博客,看到 Sentence Transformers 发了 6.0。我第一反应是,这不就是那个做句向量、做 RAG 检索最常被拿来开箱即用的库吗,它又能折腾出什么花
结果看到一条,给我整不会了。它在 6.0 里加了第四种模型类型,叫 MultiVectorEncoder,专门干 ColBERT 那种迟交互检索的活

图:Hugging Face 官方博客宣布 Sentence Transformers 6.0 与 MultiVectorEncoder
啥意思呢。我给你说个最直观的对比
以前我们做语义检索,一个文档不管多长,最后都压成一个向量,经典维度 384 或者 768,一个 9 个 token 的短句,变成 1×384 这么一根。Sentence Transformers 这次反过来,它不给整段文本生成单向量了,它给每个 token 都留一个向量,维度压到 128。同一个 9 token 文档,从前是 1×384,现在是 9×128 的一个矩阵
你如果做过 RAG 肯定心里咯噔一下。我们过去几年默认的那套常识,把一个文档压成一个向量,省空间、好比对、能塞进任何向量数据库,突然就被这个库自己拆台了
我当时就愣住了
这不是新概念啊。ColBERT 这个迟交互的思路,2020 年就有人提了。它的核心就一个公式,MaxSim,拿 query 里每个 token 的向量,去和文档里每个 token 的向量做点积,取最大值再求和。坦率的讲,就是不在编码阶段把文档压扁,而是把粒度留到比对的那一刻才做决定。哪个 query token 和哪个 document token 最像,现场算
这玩意妙在哪。单向量检索,文档里有个关键词埋在第三段,它跟其他八段一平均,那个信号就稀释了。迟交互不平均,token 对 token 地比对,那个关键词的痕迹一直留着
Sentence Transformers 自己跑的 NanoBEIR 基准也印证了这点。同样的 backbone、同样的参数量,多向量的 LateOn 均值 0.6868,密集的 DenseOn 是 0.6764,13 个数据集里赢了 9 个。长文档检索更夸张,mLateOn 77.92 对 mDenseOn 51.59,差了二十多分
你敢信???一个 2020 年的老想法,塞进今天最流行的嵌入库,还把当年最劝退的那件事顺手解决了
当年 ColBERT 为啥没火遍天下。就一个字,贵。每个 token 都存一个向量,索引直接爆炸。同样的 Natural Questions 语料,LateOn 的索引是 608414 个向量,float32 下 311.5 MB,而 all-MiniLM-L6-v2 这种密集向量才 7.5 MB。差了 42 倍
你要是做个小 demo 无所谓,真往生产里放,一个索引胀到几十倍,谁都怕
Sentence Transformers 6.0 给的解法叫 Token Pooling。把相邻的 token 向量按 pool_factor 合并,factor 取 2,索引从 608414 砍到 305438,大小 156.4 MB,检索性能几乎没掉,平均还能保住未池化时的 100.6%。factor 取 3,104.7 MB,性能 99.0%
这就很骚了。42 倍的膨胀,砍到 2 倍,精度几乎原地不动
说到这你可能会问,那它具体怎么用,跟以前一样简单吗
代码几乎没变。from sentence_transformers import MultiVectorEncoder,然后 model.encode_query 和 model.encode_document 分开调,注意这俩必须分开,query 和 document 用的是不同的编码方式,混了就不对。返回的也不是一个整齐的矩阵,而是一堆长度不一的二维张量,因为一个文档本来 token 数就不一样
它还能直接读 ColBERT 的老模型。Stanford-NLP 的 colbertv2.0、answerai 的 colbert-small,甚至 LiquidAI 的 LFM2.5-ColBERT,都能一行 MultiVectorEncoder("模型名") 加载。ColPali 那套视觉文档检索、音频、视频也都能吃,model.modalities 一看就知道它支持什么模态
我有时候觉得,这件事比它表面看着要重
我们做工程选技术,常常是被「默认」绑架的。RAG 默认单向量,不是因为它最好,是因为它最早成熟、最省事、生态最全。一个库把另一种范式做成了开箱即用的一等公民,等于把选择的权利还给你。你以前不是不想用迟交互,是你不想为它重写一整套索引和比对逻辑。现在这层壳被揭掉了
话说回来,我也得讲句公道话。多向量不是银弹。索引再怎么压,它还是要比单向量大几倍,长文档、超大规模语料下,存储和比对成本你得自己掂量。而且文档长度截断也是个问题,LateOn 默认 document_length 300,超了就丢。这些都不是换个库就能消失的现实
我一直觉得,技术选型最怕的是「只有一条路」。Sentence Transformers 把 ColBERT 收编进来,不意味着单向量就死了,它只是让你多了一个旋钮。文档短、追求极致召回、预算够,你上多向量。文档长、规模大、要极致便宜,你留单向量。同一个库,两种范式,你自己拧
想想这几年 AI 基础设施的节奏,这种「把学术圈的好东西,做进工业级默认」的事越来越多了。Flash Attention 当年也是论文里的东西,现在成了训练标配。RAG 这套迟交互,拖了六年才进主流嵌入库,慢是慢了点,但它终于来了
话说回来,工具永远在变,变的是你能不能看清它背后那层取舍
一个 9 token 的文档,从前是一根向量,现在是一把向量。看起来是维度的小事,背后是「什么时候该把信息压扁、什么时候该留住」这个老问题的又一次回答
大时代啊,朋友们
夜雨聆风