尧图精选

生成式召回:电商搜索从向量匹配到意图生成的新范式

🕒 发布时间:2026/10/1 4:45:17 📁 来源:尧图网络
先给大家看一条真实到不能再真实的搜索日志用户在得物App里输入“女朋友说想要那种很软很舒服的拖鞋”然后退出重进又搜了一次“可爱毛绒棉拖鞋”。如果你只做向量检索第一条query基本就是废的——它太口语、太冗长、太像聊天了。但用户确实有明确购买意图只是表达方式和商品标题隔着十万八千里。这其实就是我最近一直在琢磨的问题当向量检索的天花板就顶在那儿的时候交易搜索的召回还能怎么突破得物交易搜索团队给出的答案是不只在原来“查候选集”的框框里继续卷而是直接用生成式模型把“候选”本身给造出来。这篇文章我就把这次从“向量召回”到“生成式召回”的范式转换过程、关键设计、以及我们踩过的那些坑完整地拆开聊一聊。1. 向量检索卷到边际收益为负问题到底出在哪先说一个可能有点反常识的结论目前在电商搜索里向量召回早就不是那个“上了就能涨几个点”的万能药了。相反在最成熟的类目上它已经进入了一个边际收益递减甚至为负的阶段。1.1 用户query远比我们想象的更“长”和“模糊”传统向量检索的流程大家都很熟query侧编码器把输入query编码成一个向量商品侧编码器把商品标题、属性、标签编码成一个向量然后做ANN近邻检索。这套框架最舒服的区间是处理“词面匹配不上但语义接近”的场景比如用户搜“老爹鞋”商品标题里写的是“复古运动鞋”。但用户一旦说出“给男朋友买的打篮球穿的鞋不要太贵但要有牌面”整个框架就开始难受了。这种query有三个特点让双塔难以下咽长度失衡训练时我们几乎看不到那么长的query线上来了一个17个词的句子embedding早就被压扁变形了。意图复合这句话里有“买给男友”、“打篮球”、“价格敏感”、“品牌调性”四个子意图。向量只能把它压成一个点信息全挤在一起哪个意图都表达不充分。口语实体对不齐商品侧是规范化的“篮球鞋 实战 耐磨 中帮”query侧是“打篮球穿的鞋”。字面完全对不上向量要硬学这种映射样本永远不够。用我自己的话说就是向量检索擅长的是“模糊匹配”而交易搜索里越来越值钱的是“意图理解”——这两者之间有本质差异。1.2 双塔ANN的固有断层你的召回上限被embedding质量焊死了长期以来我们都把优化焦点放在“如何训练更好的embedding”。今天加一个难负样本明天换一个更强的底座模型后天把frozen tower换成端到端联合训练。这确实有效但大家心里都清楚一件事召回结果的天花板由embedding空间的表达能力决定。这个天花板有多硬我举个具体的例子。某个头部品牌做了一款“联名限定球鞋”标题是“XX品牌 x 潮玩IP 联名限量款 高帮板鞋”。它上线第一周搜索侧曝光几乎为零。因为在embedding空间里query“限量联名鞋”和这双鞋的向量距离并没有显著近于其他普通板鞋。向量模型学到的是“板鞋”这个相对泛化的语义至于“联名”、“限定”、“潮玩IP”这些强交易属性的词在预训练和微调数据里都太稀疏了根本不足以把它和其他板鞋拉开距离。这就导致一个尴尬的局面你花大力气把embedding训练得越来越好结果只是把同一批候选的排序做得更精细而候选本身从一开始就没变过。召回的上限是“候选生成机制”决定的不是embedding决定的。想清楚这一点你会发现继续卷向量检索的性价比远没有想象中那么高。1.3 向量召回的“语义”是近义不是“意图推演”我再补一刀。很多人把向量召回叫“语义召回”这其实是个不小的误会。向量模型做的是“表征相似度”它能把“跑鞋”“跑步鞋”拉得很近但它不会推理。什么叫推理用户搜“晴天穿的鞋”和“雨天穿的鞋”向量模型大概率认为这俩很相似——因为字面里都有“穿的鞋”。但真实世界的商品逻辑是晴天对应板鞋、帆布鞋雨天对应防滑短靴、雨鞋。向量模型不知道这些。它只知道字符和词频层面的共现规律而交易搜索里真正有价值的是常识与商品知识的组合推理。这也是我们决定尝试生成式召回的起点与其继续在“表征空间”里打转不如让模型直接“想”出符合用户意图的商品描述然后再用这套描述去检索商品库。这就是范式的跃迁——从“查候选”到“造候选”。2. 生成式召回不是在“多路召回”里再加一路很多团队一听“生成式召回”就认为哦就是用大模型改写一下query或者扩写几个同义词然后丢给ES和向量检索去查。这确实是生成式与大模型最常见的结合点但得物做这件事的姿势不太一样。2.1 从“查候选”到“造候选”召回逻辑的倒转传统召回不管多少路本质都是“给定query去索引里查一个候选集合”。生成式召回的思路刚好倒过来给定query先用模型生成若干个“理想的商品侧描述”再用这些描述作为检索条件去找真实商品。举个例子。用户搜“见导师穿的正式一点的衣服”。传统向量召回拿到这个query直接编码去找距离近的商品效果可以想见。生成式召回这一步会先让模型输出中间产物比如商务衬衫 长袖 免烫 纯色正装西裤 男士 修身 垂感商务休闲皮鞋 黑色 真皮 软底你发现问题没有我们根本没有在“相似性”层面做努力而是先把抽象的query翻译成了具体的“商品语言”。这些生成出来的描述随便哪一条拿去和商品库做匹配都比原始query好使得多。这等于把老路子里的“编码-比对”问题变成了一个“文本生成-精确匹配”问题。2.2 得物场景的生成目标设计不能光“像人话”要“像商品标题”既然要“造候选”那到底造什么形态的中间产物这个设计决策直接决定了项目的走向。我们对比过三条路线路线生成产物示例优点缺点Query改写“见导师的正式着装”理解成本低仍然偏泛和商品侧语言有gap商品描述扩写“正式商务风格男士衬衫”贴近商品侧表达容易丢失多意图覆盖面窄多意图拆分属性补全多个候选描述每个带具体属性词信息密度高召回精准可并行对生成模型要求最高需要强约束我们最终选了第三条路。原因很简单query里往往藏着不止一个需求而一个向量只能表达一个点。我上面那个“见导师”的例子模型只要能识别出“上装、下装、鞋履”这三个方向然后每个方向生成1-2个商品侧描述整个候选集的结构就和以前完全不同了。在实操层面我们让生成模型输出的不是一段自然语言而是一组“商品画像元组”[类目词, 属性词集合, 风格词, 性别/人群词]。这样做有两个直接好处一是后接检索模块时解析成本极低不需要再对自由文本做切词和NER二是约束了模型的输出空间幻觉率明显下降。生成的“画风”是否像商品标题直接决定了后面能否召回好东西——这个细节我觉得是全文最值得强调的设计之一。2.3 生成式与向量检索是互补关系不是替代关系这里必须澄清一个误区生成式召回不是要把向量检索干掉而是把向量检索从“独挑大梁”的位置上解放出来。我们在实践中形成的分工是这样的对于“字面上就能匹配”或者“embedding空间里表达得很清晰”的query向量检索又快又准没必要换成生成式。对于“多意图、口语化、知识依赖型”的长尾query生成式召回能构造出一个向量检索永远给不出的候选集合。所以最终线上架构是先轻量分类把query分为“简单意图”和“复杂意图”两路。简单意图走传统多路召回复杂意图走生成式召回两路结果在粗排阶段合并由排序模型统一打分。从工程上看这不是“取代”而是“补位”。但恰好是这种补位把整个系统的召回边界往外推了一大截。3. 交易搜索落地生成式召回的工程链路与关键拆解概念讲明白了下面全是硬核的工程细节。这一章我按落地的时间顺序来讲从整体链路到每一环怎么做、为什么这么做。3.1 整体链路改写-生成-校验-合并一步都不能省先看完整的数据流这是我们在线上稳定运行的单次召回全链路用户query → 意图识别与路由轻量模型30ms内完成 → 生成式召回服务大模型生成商品画像2-3个候选 → 结构化校验类目映射、属性归一、非法词过滤 → 多检索器执行ES短语匹配 向量召回 类目数据库直查 → 候选合并与去重 → 粗排/精排你注意我没有把“生成”这一步做完就送进粗排中间强行加了一个结构化校验层。这一层在demo阶段大家都觉得是多余开销但真实跑起来之后你会发现它是保命的一层。校验层主要干三件事类目映射模型输出的是自由文本类目名比如“鞋靴”但库里真实类目是“运动鞋-篮球鞋-高帮”需要一套映射关系把它归一到真实叶子类目。属性白名单过滤我们给生成模型一份“可被检索的属性词表”比如颜色、材质、款式、功能。模型输出的词如果不在白名单里直接丢弃。宁可少召回一点也不能让模型自创一个库里根本不存在的属性。非法词过滤品牌词、敏感词、竞品词都要在这里控一遍。说句实话这层校验我们一开始就没打算省因为大模型生成的“自由度”在检索场景里就是一把双刃剑。3.2 生成模型选型与线上延迟时延的账要一笔一笔算生成式召回上线前团队内部争论最激烈的不是效果而是延迟。交易搜索的端到端延迟预算一般是在200ms左右召回到排序通常只能分到50-80ms。你让一个大模型在线实时生成怎么算都超预算。我们的解法是分了两步走。第一步离线全量生成缓存。对于高频query我们离线跑一遍生成任务把所有生成结果落地到缓存表。线上直接查缓存命中率能做到70%以上耗时趋近于0。这一步把延迟问题解决了一大半。第二步在线轻量生成兜底。长尾query没有缓存必须要实时生成。我们在这里没有用动辄几十B的大模型而是部署了一个精简的生成模型参数量控制在几B以内单次生成控制在150ms以内。为了压这个时延我们把解码长度限制在64个token以内、batch设置为1、并开了推理加速服务。实测下来全链路p99延迟只增加了18ms。你看看这个数字再想想生成式召回带来的召回增量这笔账其实相当划算。我们在评审时反复跟老板讲了同一个观点延迟增量本质上是一次性的但召回边界扩展带来的收益是持续性的。3.3 商品侧的知识注入让模型知道“库存里到底有什么”一开始我们跑出来的生成结果有一个共性问题模型生成的东西很美但库里没有。比如用户搜“复古跑鞋”模型生成“复古网面跑步鞋 元年配色 透气”但库里根本没这批货等于白生成。后来我们想明白了生成模型不能只在“query到商品语言”这个方向上训练还得把商品库的分布知识灌进去。具体做法是在训练阶段做了一步“库存感知约束”把高频商品类目、常见属性组合作为额外的结构化Prompt输入在解码阶段通过约束解码constrained decoding把输出限制为数据库中真实出现过的类目词和属性词组合训练数据里刻意加入“负例商品侧描述”——这些描述语法正确、语义合理但库里确实不存在——让模型学会避坑。这步做完之后生成结果的“可检索率”即生成结果能在库中命中商品的比率从57%直接拉升到83%。我印象特别深刻的是之前模型特别爱生成“鸳鸯配色”这种词库里其实只有零星几双。自从注入了库存感知约束这类“好看但没货”的生成明显变少了。4. 效果验证与踩坑实录哪些涨了、哪些白干、哪些翻车讲完架构和设计来聊点真实的。这部分我希望给同行们省下一些试错成本无论你是做搜索还是做推荐里面有几条经验是通用的。4.1 离线评测召回率只涨了3.4%但别急着下结论项目进入评测阶段第一版离线指标出来的时候团队内部反应其实是分裂的。生成式召回叠加线上整体召回率涨了3.4个百分点。有同学觉得“就这”但负责搜索和商品的同学都很兴奋。原因在于这3.4%的构成很不均匀。我们把召回增益按query类型拆开看Query类型占比召回增益转化增益品牌词/型号词42%0.3%0.1%品类词31%2.1%1.4%长尾口语/多意图词27%9.6%6.2%看出来没有增量几乎全部来自长尾口语和多意图query。这正好印证了我们的判断在简单query上继续做向量检索的精细优化收益已经很低了。而在复杂query上生成式召回几乎是“凭空变出一个新候选集”。所以这里我建议所有准备做类似项目的团队不要只看大盘召回率一定要按query难度分层去看。大盘不涨不代表方法无效很可能是你的基线在简单query上太强了增量被稀释了。4.2 线上A/B测试转化率提升的来源根本不是你想的那个线上实验我们跑了三周实验组和对照组整体转化率差值是4.7%。这个数字放到交易搜索场景里算是很可观的。但让我最意外的不是这个数字本身而是我们后来在分析时发现转化率提升的最大来源不是新增成交而是无效曝光减少。什么意思生成式召回补进来的候选因为更贴合用户意图所以粗排之后真正能进入用户视野的商品和用户原本想要的越来越一致。用户看到的商品越来越“对味”点进去发现不是想要的、然后跳出的情况大幅减少平台的搜索满意度指标随之上涨。这么说吧那一批“搜见导师装”被生成式召回精准补上商务衬衫的用户他们点进去之后大概率会下单或者至少会深度浏览。而在老系统里他们可能翻了三页都没找到合意的东西然后带着负反馈离开。好的召回不只是带来成交还能减少用户反复寻找的挫败感。4.3 踩坑记录三个翻车现场和最终解法任何项目都不可能一帆风顺这里分享三个我们真实踩过、且花了不小代价才填平的坑。坑一多意图拆分的“泛化灾难”。第一版生成模型上线后我们发现它对“泛意图”query的处理有问题。比如用户搜“礼物”模型一口气生成了“口红礼盒”“球鞋”“蓝牙音箱”“键盘”十几个方向的商品画像。这看起来“很聪明”但实际检索出来的商品五花八门排序模型根本不知道该给谁高分。后来我们在意图拆分层加了一个频次约束只有用户query明确包含“送/给/买给”这类对象指示词时才允许多意图拆分否则默认走单意图主路径。坑二生成内容的“自嗨”倾向。生成模型特别喜欢输出“高颜值”“小众设计”“炸街”这类在社区内容里常见、但在商品检索里毫无用处的形容词。这些词在商品库的标题和属性里基本不出现。所以无论模型怎么生成检索器都匹配不到。后面我们做了两件事一是把生成模型的训练数据从“社区文案”替换为“商品/搜索共现语料”二是在解码端直接把这些低信息词加入“禁止输出清单”。效果立竿见影无效生成率从41%降到了12%。坑三时延基尼系数拉满——缓存命中率在高峰期骤降。因为高频query离线缓存做得好我们把在线生成能力砍得很“薄”。结果一到晚上潮玩新品首发这类热点时段大量全新query涌入缓存命中率直接往下掉在线生成服务被瞬间打到限流。这个问题本质上不是模型问题是流量预估问题。解决方案分两步短期先给在线生成服务扩容并加了热点Query的提前预生成长期则是把生成服务做成“按需弹性扩缩容”和运营侧的营销日历联动。5. 生成式召回对搜索系统设计思路的改变值得被记住的三条经验项目上线并稳定运行之后我自己的认知也发生了一些变化。这些变化不是那种“项目复盘PPT里的总结”而是真真切切影响了我后续做系统设计时的判断方式。5.1 兜底的不是模型是“约束和控制”做生成式召回项目之前我的第一反应是“模型越强越好”。但经历过上面那些坑之后我现在的看法是在召回这个环节模型的“想象力”必须被刻意压制。召回侧的核心诉求不是“生成一个漂亮的句子”而是“生成一个能精准命中库内商品的检索条件”。你的约束条件建得越扎实你的召回结果就越稳定。所以如果让我给同行一个建议我会说在动手调模型之前先去把商品库的Schema、类目树、属性词典彻底吃透。好模型的贡献可能占30%剩下的70%全在“约束设计”和“资源组织方式”上。5.2 召回问题本质上是“候选生成机制”的问题以前讨论召回优化大家最常问的是“你的阈值调到了多少”“难负样本怎么挖的”“embedding维度换多大”。生成式召回上线之后我越来越觉得这些问题的层次都太低了。真正值得问的问题是你的系统为这个query准备了哪些候选这些候选是从哪来的如果换一种候选生成机制结果会有什么不同向量检索的贡献在于“高效地从一个大池子里捞东西”它的瓶颈在于“只能捞池子里的”。而生成式召回提供的是一个完全不同的视野先理解用户打算买什么再倒推出什么商品能满足它最后才回库里去捞。这两个视角放在一起同类问题瞬间打开。5.3 别把“范式跃迁”想得太玄它就是一次很朴实的重新分工“范式跃迁”这个词最近被用得有点烂大街好像不换一套模型架构就不配叫跃迁。但就我们在得物交易搜索的实践来看真正的跃迁反而是很朴实的你知道原来那套东西的边界在哪了你也看到了一条绕开这个边界的路你愿意投入资源把它走通。没有什么一蹴而就的魔法模型有的只是几十个版本的结构化约束、数以万计的badcase分析、和一次次延迟优化。技术在往前走但真正有价值的不是名词本身而是那些在约束条件下做出的真金白银的取舍。生成式召回的下一步我们还在探索多模态方向的扩展以及如何让生成结果与排序模型更深度地联动。这些如果后面有新的进展和踩坑我会再出来同步。
上一篇/下一篇内容由系统自动关联 返回资讯列表 →