☰
生成式召回:突破向量检索天花板,重塑交易搜索
2026/9/28 15:27:16 网站建设 项目流程

搜索这个行当,卷向量检索已经卷了四五年,大家默认“向量召回是标配”。但我在交易搜索项目里越做越清楚一件事:向量召回在标品交易场景有结构性天花板,不解决它,召回率再调也就那样。最近得物交易搜索这边放出的技术复盘,核心观点其实就一句话——别只盯着向量检索,试着用生成式的方式重新定义召回。这个思路我完整跟下来,并且在自己业务里复现了一遍,今天把原理、落地路径和踩过的坑一次讲透。

1. 卷向量检索卷到头了:标品交易搜索的三类典型哑火

先说清楚为什么“向量检索不够用”。不是向量检索本身不好,而是标品交易搜索的查询形态,和通用路的语义检索之间有天然的错位。我总结下来有三类问题,基本覆盖了日常线上 badcase 的大头。

1.1 通用向量模型不认识交易黑话

拿我实际处理过的一条 query 举例:“倒钩灰 AJ1 44码 全新”。懂行的人一看就知道,用户要找的是 Travis Scott 联名的那双低帮 Air Jordan 1,鞋身侧面有个反过来的 Swoosh,圈内叫“倒钩”,2022 年那款的配色叫 Reverse Mocha(反转摩卡),灰色调为主。

但你把这条 query 丢给一个在通用语料上训练出来的 embedding 模型,它算出来的向量离“Travis Scott x Air Jordan 1 Low Reverse Mocha”这个商品标题的向量距离非常远。因为预训练模型没见过“倒钩”这个词和鞋款之间的映射关系。类似的黑话还有“禁穿”(Air Jordan 1 Bred)、“熊猫”(Dunk Low 黑白配色)、“北卡蓝”(北卡罗来纳大学配色)、“富婆快乐鞋”等等。

这种映射断层在通用搜索里可能只是召回排序靠后的问题,但在交易搜索里是致命的:用户搜“倒钩”,如果召回列表前 50 名全是灰色运动鞋而不是那双 AJ1,这一单大概率就流失了。

1.2 款号这类“非自然语言 Token”是向量检索的结构性短板

交易搜索还有一个通用搜索很少遇到的输入形态:货号/款号。用户会直接搜“DD1391-100”“555088-612”这种纯数字字母串,这相当于鞋圈的身份证号。

向量模型处理这种输入非常尴尬。预训练分词器会把“DD1391-100”切成“DD”“1391”“100”这样的碎片,每个碎片映射到向量空间以后,跟完整的款号语义差得很远。更麻烦的是,款号的语义只能靠精确匹配理解,邻近的向量不代表邻近的商品。

也就是说,款号类查询的正确解法是字典精确匹配和结构化检索,向量召回在这种输入上既不快,也不准。你把它硬塞进向量召回体系里,只会白白消耗算力,还把候选集搞乱。

1.3 召回漏斗的尴尬:K 值越开越大,精度越掉越低

向量召回的经典调参手段是把每查询取回的候选数 K 调大。长尾 query 之所以召回不到目标商品,往往不是“向量距离不够近”,而是目标商品在 embedding 空间里压根不在附近。你把 K 从 200 调到 500、再调到 1000,能捞回更多相关商品,但也会带进来大量无关项。

后果是连锁的:向量计算量线性上升,下游粗排、精排的压力也成倍增加。最难受的是,哪怕 K 开到 1000,某些关键属性项(比如某个具体尺码、某个具体的版本年份)仍然是缺失的。这种“候选集大而不全”的问题,靠调 K 解决不了。

我当时的判断是:向量召回做的是“相似物品的近似查找”,而交易搜索要的是“满足用户结构化约束的目标商品”。前者是相似度问题,后者是条件匹配问题。用相似度的思路解条件匹配的问题,方向就不太对。这也是后来我决定认真研究生成式召回的核心原因。

2. 生成式召回到底在做什么:两派技术路线拆解

“生成式召回”这个名字容易让人误会,以为就是把大模型直接拿来跑线上检索。实际上它指的是:把“召回”这个检索问题,重构成一个“条件生成”问题。具体有两条路线,我分开讲。

2.1 路线 A:生成式查询扩展(Generative Query Expansion)

这条路线不改变现有的索引结构,而是用生成模型把用户的自然语言 query 转写成多条结构化的、可执行的子查询,再去走原有的倒排索引或向量索引。

比如用户输入“倒钩灰 AJ1 44码”,生成模型输出这样的结构化意图:

{ "brand": "Air Jordan", "series": "Travis Scott 联名", "model": "AJ1 Low", "colorway": "Reverse Mocha", "size": 44 }

拿到这组结构化字段以后,系统可以组合出多个子查询:“Travis Scott + AJ1 Low + 灰色”“Air Jordan + 倒钩 + 44”等,并行去检索。本质上是把用户模糊的口语表达,先展开成机器能执行的多条精确表达,再把结果融合。

这条路线的优点是工程改动小,原有的倒排索引、向量索引都能复用。缺点是生成质量决定上限——如果意图解析错了,后续全错。

2.2 路线 B:可微检索索引(DSI 风格)

另一条更激进的路,参考的是学术界的 DSI(Differentiable Search Index,可微检索索引)思路:把商品库本身编码进生成模型的参数里,召回时直接让模型生成商品 ID,而不是先检索再排序。

训练阶段,给每个商品分配一个唯一的数字 ID 或结构化编码;推理阶段,给定 query,模型直接输出最匹配的商品 ID 序列。整个检索过程没有倒排表,没有向量近邻搜索,就是一个 encoder-decoder 的条件生成过程。

这个思路对“封闭集合”特别有效。什么叫封闭集合?就是候选商品数量有限且相对稳定的集合。交易搜索恰好符合:平台上的 SKU 数量级通常在百万到千万之间,商品有明确的属性结构(品牌、系列、货号、配色、尺码),完全可以编码成结构化 ID。

我个人的观点是:得物这类交易搜索实际上是 DSI 路线最合适的落地场景,比通用网页搜索合适得多。因为通用搜索的网页集合无边无际且文档结构松散,而交易搜索的候选集是有限的、结构高度规整的。

2.3 为什么交易搜索是生成式召回的最佳试验田

总结下来,适合生成式召回的场景需要三个条件:候选空间有限、物品描述高度结构化、用户意图可以用属性组合表达。交易搜索三个条件全占。

零售商品的标题“品牌+系列+货号+配色”本身就是一套天然的结构化描述,用户查询“某某联名、什么配色、多大码”,本质上就是在描述一组属性约束。生成模型非常擅长从自然语言里提取结构化约束,这是它的舒适区。

而且交易搜索的 query 总量相对可控,用户反复搜的就那些热门商品和款式,生成式召回可以被缓存、被蒸馏、被持续优化。不像开放域的网页搜索,query 分布无限长尾。

3. 得物的三重压力:黑话、款号与热点时效

聊完通用原理,得说说得物这种平台的特殊性。得物交易搜索的压力不止来自黑话,还有标品主数据、热点时效和交易意图的三重叠加。

3.1 标品主数据:一个被严重低估的结构化知识库

很多人聊搜索只盯着模型和索引,忽略了一个事实:得物上的商品天然就有一份高质量的标品主数据。每一款球鞋都有品牌、系列、货号、官方配色名、发售年份、版本说明。这些数据组合起来,就是一个极其干净的商品知识库。

生成式召回能不能落地,前提就是有没有这样一个知识库。模型生成的任何内容,都必须能在知识库里找到对应实体,否则就是幻觉。我后来把整个商品知识库的实体表(品牌别名表、系列别名表、配色别名表、货号表)全部抽出来,喂给生成模型做 constrained generation,这比让模型自由发挥靠谱一个数量级。

换个角度说,这也是“知识库 + 向量库”这对组合在交易搜索里的正确打开方式:向量库负责存储和近似检索商品向量,知识库负责提供生成阶段的词汇约束和实体校验。两者各司其职,混在一起用必出问题。

3.2 向量库选型:别把存储引擎和知识体系混为一谈

这里顺便回答一个高频问题:向量库检索到底需要什么数据库?我做过的对比测试结论如下:

方案适用数据量优点缺点
ES (dense_vector + kNN)千万级以下与倒排索引统一管理,少一套组件大规模向量下性能一般
Milvus亿级支持标量过滤与向量混合查询,扩展性好需要单独部署运维
Faiss离线批量简单高效,适合全量重建不支持动态实时更新
PGVector百万级沿用 PG 生态,接入简单量级上来以后性能掉得快

我的实际体感是:交易搜索如果数据量在千万级以内,直接用 ES 的 kNN 就够了,省得维护两套系统。量再往上走、或需要复杂属性过滤后再算相似度时,再上 Milvus。但核心提醒一句:向量库只是存储和近似检索引擎,召回质量的大头在模型和策略上。你换一个更快的向量库,解决不了“倒钩映射不到 Travis Scott”这种语义问题。

3.3 交易意图不只是“像”,还要“能买”

通用搜索要的是“相关”,交易搜索要的是“可成交”。用户搜“AJ1 芝加哥 40码”,他不仅要看到 AJ1 芝加哥这款鞋,还要看到 40 这个尺码有货、是全新还是二手、价格在什么区间。

向量检索本身只建模了文本相似度,这些交易约束它一概不知道。生成式召回的好处在于,它可以在生成阶段就把这些约束纳入输出结构:品牌、系列、配色、尺码、成色、价格带。生成模型输出的不是“一个相似的文本”,而是一组“可执行的结构化交易条件”。

这个差异在线上表现非常直观:向量召回给的是“看起来像的”,生成式召回给的是“用户真能下单的”。交易平台要的是后者。

还有一类特殊压力是热点时效。某明星上脚某款鞋之后,三小时内查询量能翻几十倍,而且用户用的词往往是最新的网络叫法。向量模型是冻结的,新词映射靠重新训练,周期赶不上热点;生成模型可以通过 few-shot 或在线改写快速把新叫法映射到既有商品属性上,响应速度完全不在一个量级。

4. 可落地的两段式方案:从离线扩写到在线约束生成

讲完原理,说落地。我的经验是不要一上来就全量上在线生成式召回,风险太大。稳妥的做法是分两段走:先做离线索引侧重构,再做在线约束生成。

4.1 先做索引侧重构:让商品也会“说话”

第一段是在商品端下功夫。给每个 SKU 建一套“语言指纹”,集合所有可能的叫法。具体步骤:

  1. 用 LLM 对每个 SKU 生成搜索别名,prompt 大概长这样:
你是潮流商品搜索专家。给定商品的基础信息,列出用户在购买时会使用的所有搜索叫法: 包括官方名称、泛称、配色别称、圈内黑话、网络流行叫法。 商品信息:Air Jordan 1 Low Travis Scott Reverse Mocha 货号 DM0856-100
  1. 让大模型生成一批别名,比如“倒钩灰”“反转摩卡”“TS AJ1 低帮灰”“倒钩 AJ1 低帮 44”等。

  2. 关键一步:生成的别名必须过白名单校验。每个别名都要能映射回商品知识库里的合法属性,映射不上的直接丢弃。

  3. 把这些别名回灌进倒排索引和向量索引,让商品在检索阶段“更容易被各种说法命中”。

这一步的收益是立竿见影的。因为索引侧扩容不改变线上链路,没有延迟风险,出了问题随时可以回滚。我建议任何一个团队想搞生成式召回,都先从这个动作开始。

4.2 在线生成式召回模块拆分

第二段才是真正的在线生成式召回。我把整个模块拆成四块:

  • 意图解析器:轻量级的 seq2seq 模型,或者一个蒸馏过的小参数 LLM,负责把用户 query 转成结构化检索条件。
  • 约束解码器:生成时把每一步的输出 token 限制在商品知识库的词汇表内。这一步必须有,否则模型会输出一堆不存在的品牌和配色。
  • 多查询执行器:根据结构化条件组合出多条子查询,并行走精确匹配、倒排检索和向量检索。
  • 兜底策略:如果生成结果为空、或校验不通过,直接回退到原来的向量召回链路,不让用户看到空结果。

在线生成阶段我不会让模型直接输出商品 ID,而是只让它输出结构化属性。原因有两层:一是商品 ID 的分布太稀疏,生成难度大、幻觉率高;二是属性层生成即使略有不准确,后续还能通过多查询组合来弥补。用一个更小的模型、更低的延迟,达到足够好的效果,这才是工程正道。

4.3 多通道融合:如何让新旧召回协同

新增一条召回通道以后,最关键的问题是融合。我的建议是用 RRF(Reciprocal Rank Fusion)起步:

RRF得分 = Σ 1 / (k + rank_i)

对每个候选商品,把它在每一条召回通道里的排名换算成分数加总,k 通常取 60。RRF 的好处是它不依赖各通道的分数分布——向量通道的 cosine 分数和精确匹配通道的分数量纲完全不一样,直接加权没法比,但排名是可以比的。

融合后的候选集统一交给粗排和精排。这里有个我踩过的坑:不要让生成式通道的结果直接进入顶部位置。生成式召回的价值是“提供之前召回不到的正确候选”,而不是“替排序层做决定”。它召回回来的商品到底排第几,应该由精排模型根据用户行为和商品特征去判断,否则很容易出现生成模型一错、整页结果跟着错的情况。

5. 线上治理的硬仗:延迟、幻觉、失效与灰度

生成式召回的难点从来不在“跑通 demo”,而在“稳定上线并且不影响大盘”。这里面有四场硬仗,我挨个说。

5.1 延迟预算:生成不能拖垮主链路

搜索引擎的延迟预算非常严格。我们内部要求 p99 控制在 200 毫秒以内,而一个生成模型单次 decode 就可能吃掉 30 到 50 毫秒,这还没算意图解析和多查询执行的开销。

我采用的组合拳是:

优化手段典型收益主要风险
触发条件过滤只有复杂 query 才走生成链路,覆盖约 30% 流量简单 query 享受不到新增召回增益
并行调用意图解析和多通道检索并行执行,不串行累加需要治理线程池和超时
结果缓存热点 query 二次命中时延迟趋近 0需要处理缓存新鲜度
小模型蒸馏decode 耗时从 40ms 压到 8ms 左右意图理解能力有折扣,需反复评测

实际跑下来,触发条件过滤是最划算的一笔投资。什么样的 query 需要生成式召回?核心判断标准是:向量召回命中的商品转化率显著低于均值、或者用户 query 里含有知识库别名表中的黑话词。这两类 query 触发生成链路,其余直接走老链路。这样既控制了平均延迟,又把资源花在了最需要的地方。

5.2 幻觉治理:三层护栏缺一不可

无限制、无审核的生成式 AI 在交易搜索这种严肃场景里绝对不可用。模型一定会输出知识库里不存在的品牌、自创配色、错误货号。我上了三道护栏,缺一不可:

第一层是词汇表约束。生成阶段就把候选词限制在品牌表、系列表、配色表、货号表里,从源头压缩幻觉空间。

第二层是规则校验。生成结果必须能通过货号正则校验、并且能在商品知识库里查到对应实体。查不到的,整条结果直接作废。

第三层是聚合校验。生成出的结构化条件去检索以后,至少得返回一个商品,否则判定本次生成为“无效召回”,走兜底链路。

这套护栏跑下来,生成链路的无效率能压到 5% 以下。没有护栏之前,这个数字大概在 20% 以上——也就是说每五次就有一次生成结果是没法用的。这还是在已经做了词典约束的前提下,可见校验环节有多重要。

5.3 灰度与效果评估:业务指标说了算

召回层的改动对线上影响是间接的,直接看业务指标往往看不出波动。我的做法是建一套独立的评估矩阵:

离线阶段看四个指标:整体召回率(recall@100)、新增召回率(生成式通道单独带来的、其他通道没有召回到的候选比例)、精确率、候选多样性。其中“新增召回率”是最关键的——如果生成式通道召回来的东西其他通道本来就能召回,那这层就是白做的。

在线灰度阶段,我按照 1% 到 5% 到 20% 到 50% 的节奏逐步放量,每一步盯四类业务指标:无结果率(NBR)、搜索点击率、搜索到下单的转化率(CVR)、每搜索 GMV。无结果率下降是生成式召回最能直接贡献的指标,因为很多长尾黑话词在原来的链路下可能直接搜不到。

一个特别提醒:召回层改动以后,排序层的分布会被打乱。原来排在前面的商品可能被新召回的商品挤下去。所以灰度期间一定要盯排序层的指标变化,必要时把新通道召回的结果先做降权,等排序模型逐步适应之后再放开。

6. 复盘与建议:哪些套路可复用,哪些坑必须绕开

最后做个复盘。这套方案在交易搜索场景跑了大半年,有成功的经验,也有花了不少学费换来的教训,我挑最有价值的几点分享。

6.1 我认为最值得复用的三个经验

第一,先做离线端物品扩写,再做在线生成式召回。这两件事的收益比大概是 1 比 3 的投入产出关系。离线扩写几乎没有风险,先把它吃透,你会在标注数据、词表建设、模型评测上积累一大笔经验,这些正好是在线生成式召回的前置条件。

第二,约束解码和存在性校验必须从一开始就做,不要等到幻觉炸了再补。补护栏比建护栏贵得多,因为早期你的评测数据和线上日志都是脏的,debug 起来极痛苦。

第三,融合用 RRF 起步,排序权完全交给下游精排。这个选择让我少踩了好几个坑。任何自定义的加权公式在初期都会引入玄学调参,而 RRF 简单、稳定、可解释,等跑出置信度再换更复杂的融合策略不迟。

6.2 给同类交易平台的落地路线图

如果你所在的平台也在做类似的搜索召回升级,我建议的行动顺序是这样的:

  1. 梳理商品主数据,建立品牌、系列、配色、货号、别名的结构化知识库。
  2. 选好向量存储引擎(多数场景 ES 够用),把商品向量索引和离线别名扩写的流程跑通。
  3. 用搜索日志里“query-商品点击对”构建训练数据,蒸馏一版轻量意图解析模型。
  4. 上线在线生成式召回通道,先并行观测、不直接融合,确认新增召回质量达标。
  5. 逐步打开融合开关,先小流量再大流量,全程盯无结果率和转化率。
  6. 用线上数据回流,定期刷新别名表和意图模型,形成数据飞轮。

这套路线里的每一步都有清晰的上线时间和退出条件,不会出现“推倒重来”的尴尬。

6.3 一些观察与后续想法

我最初对生成式召回的预期并不高,总觉得是学术概念在工程上的硬着陆。实际跑完以后,我的判断改变了:在标品交易搜索这个场景里,生成式召回不是替代向量检索,而是补上了向量检索在“结构化意图匹配”上那块缺失的拼图。尤其当商品知识库足够干净、query 形态足够口语化的时候,它的增益比其他任何召回改造都明显。

后面我还在琢磨两个方向:一是把生成式召回和用户实时行为特征结合,让生成条件带上个性化偏好;二是探索直接在生成阶段输出商品 ID 的完整 DSI 方案。前者离上线近,后者风险高但想象空间大。如果有同行也在探索这两条路,欢迎一起聊聊。

最后分享一个小技巧:给生成式召回做评测时,不要只看合成测试集,一定要从线上日志里切一段真实的、未经过人工筛选的长尾 query 做盲测。那些看起来“很蠢”的搜索词,往往才是生成式召回真正的用武之地。我见过太多项目,在精心构造的评测集上指标漂亮,一上真实流量就现原形。真话难听,但这就是搜索这个行当的日常。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询