ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

生成式召回:交易搜索从“匹配”到“生成”的范式跃迁

生成式召回:交易搜索从“匹配”到“生成”的范式跃迁 搜索圈这两年有个现象一提召回优化所有人第一反应就是上向量检索。双塔、多向量、图索引、ANN团队之间比的就是谁Recall50更高好像不把Embedding做到极致就不配叫搜索。我在交易搜索这块摸爬滚打久了越来越觉得这阵风有点跑偏——不是向量检索不好而是很多团队把“召回洼地”误判成了“向量洼地”。尤其像得物交易搜索这种场景用户不是来查资料的而是来“买东西”的。“我要买一双适合秋冬穿的复古篮球鞋预算五百以内”这句话背后的真实需求分词、向量化、ANN排序根本没接住。后来我把实践重心从“把向量召回调得更准”切换到“用生成式方法重构召回链路”效果反而比继续压向量指标明显。这篇文章就聊聊我看到的“召回范式跃迁”从单一query走进倒排和向量索引变成先生成一组“query约束”组合再并行召回。看完你至少能理解三件事交易搜索里向量检索的天花板在哪生成式召回到底是把什么“生成”了出来以及这套东西落地时真正烧钱、踩坑的地方在哪。1. 交易搜索的召回为什么卷向量检索不是终点1.1 交易搜索的query和文本搜索根本不是一回事通用文本搜索里用户输入通常是完整的一句话或几个关键词系统要解决的核心问题是“语义相关性”。但交易搜索的用户表达完全是另一套逻辑query普遍很短口语化严重“aj 42码 500”“通勤鞋 黑色”“有没有适合打球的鞋”信息密度极高一句话里同时塞了类目、人群、价格、尺码、颜色、场景等多个约束购买意图有明显层级不是“相关就行”而是“这东西是不是用户真的想买、能买、适合买”。传统倒排索引对“aj 42码 500”这种表达几乎是束手无策的分词后不是缺字就是错位。向量检索确实解决了“球鞋”和“篮球鞋”这种语义鸿沟问题但价格、尺码这些约束在向量空间里很难表达。哪怕你让模型学得再好“500以内”和“500以上”在Embedding空间的距离也远小于“男鞋”和“女鞋”的语义距离——用户要的是过滤模型却只能做相似。一句话总结向量检索解决的是“语义相似”交易搜索的难点却有一大半在“意图拆解和约束满足”上。1.2 向量检索解决了什么又留下了什么我在内部复盘时习惯把召回能力拆成五个维度来对比可以看得更清楚能力维度传统倒排向量检索生成式召回字面匹配强弱中通过改写间接增强语义扩展弱强强结构化约束价格/尺码/人群中弱强多意图拆分人工规则弱强可解释性高低中这么一对比就明白了向量检索主要补强了第二行“语义扩展”但对交易搜索最要命的“结构化约束”和“多意图拆分”不但没帮上忙有时候还把情况搞得更糟——因为模型把约束当成普通词学进了向量里召回时它不会做过滤只会做相似匹配。1.3 先判断“洼地”在哪再决定要不要换范式很多团队一上来就卷向量其实没搞清楚自己的召回瓶颈是什么。我建议先做一轮无结果率和bad case归因分析方法很简单按周抽样无结果的query人工标注失败原因分成三类语义不理解query里的词和商品标题词面完全不同传统倒排召不回约束没卡住词面都命中了但价格、尺码、品牌等硬约束导致过滤后为空意图没拆开用户一句话里有多个可能意图系统只按单一query去召回漏了另一条路。我在类似平台上做过统计交易搜索里第二类和第三类占比往往超过一半。如果你们平台的bad case也以这两类为主那向量检索基本已经卷到头了——继续加大模型、换索引、调参都只是在“语义相似”这条路上做边际优化真正能让召回产生质变的是把召回入口从“匹配”改成“生成”。2. 问答式搜索体验背后的“查询改写引擎”2.1 查询改写不是新概念但生成式把它做“活”了传统查询改写大家都不陌生同义词表、近义扩展、纠错、归一化本质是“一条query进来规则映射成另一条query”。生成式查询改写完全不同它输入原始query和上下文输出多个候选query每个候选对应一种可能的购买意图还可以直接附带结构化约束。举个例子用户输入“想买双运动鞋主要跑步穿不要太贵”生成式改写可能会给出这样一组结果跑步鞋运动鞋 跑步跑步鞋 平价query“跑步鞋”约束price300这不是简单的同义替换而是把用户原话里的“意图子集”逐个显式化。为什么要显式化因为召回阶段无论走倒排还是向量系统都只能拿一条query去检索。一条query只能覆盖一种意图和一个语义侧面生成多条候选后才能把用户没说全的需求捞全。我在这块踩过的第一个坑是直接把生成结果并成一条超长query丢给检索。结果分词后一堆词互相干扰召回反而变差。正确做法是每组“query约束”独立召回最后再融合。2.2 多轮对话和碎片化表达是生成式改写最能打的地方移动端搜索越来越像“助手”。用户可能先问“有没有适合通勤的鞋”紧接着补一句“黑色最好”甚至语音输入还会漏字、乱序。这种多轮碎片化表达对传统term weighting是降维打击——你很难用词频权重判断“黑色”应该叠加到上一轮而不是独立成一条新query。生成式改写引擎可以维护一个简单的对话状态当前query、历史轮次实体、用户画像。把“黑色”并入上一轮的“通勤鞋”生成“通勤鞋 黑色”候选如果用户发的是“不要浅色”还要识别出这是“排除约束”生成检索计划时得带上负面过滤条件。我实现的流程大致是这样输入: 当前query, 多轮上下文, 用户画像 1. 意图识别判断是首轮搜索还是补充轮 2. 约束抽取提取 颜色:黑 场景:通勤 等槽位 3. 候选生成LLM生成N个query变体 结构化约束 4. 校验过滤约束保留校验 相似度去重 5. 输出: 检索计划列表 [{query, constraints}]第4步很多人会忽略但它特别关键。LLM生成的候选可能重复也可能把约束搞丢不校验就直接拿去召回轻则浪费算力重则召回结果完全跑偏。2.3 改写前先抽约束别让“五百以内”变成向量距离的一部分生成式改写最大的风险是把硬约束当成普通词处理。用户说“五百以内”模型把它写进query变成“五百以内跑步鞋”倒排和向量都把“五百以内”当关键词去匹配结果召回来的全是标题里写了“五百以内”的商品用户真正想要的“500元以下的跑步鞋”反而被淹没了。我的经验是生成之前先做一轮约束抽取把价格、折扣、尺码、品牌、人群、新旧状态单独抽成槽位query里只留下检索语义部分。召回时这两条路并行语义query走倒排和向量召回结构化约束走属性过滤或正排过滤。至于约束是严格过滤还是宽松加权要看业务容忍度。价格通常严格过滤品牌和人群可以做成“先召回后加权”。比如用户说“女生篮球鞋”如果平台女生篮球鞋供给极少严格过滤可能直接无结果宽松一点先把“篮球鞋”召回来后面排序再综合判断反而对业务更友好。3. 从“给你一个query”到“给你一组query条件”候选生成与约束抽取3.1 一次搜索多路召回生成多组“query约束”并行交易搜索的召回范式变化我用最简单的方式概括旧范式用户query - 分词 - 倒排/向量召回一个集合新范式用户query - 生成模型 - 多组检索计划 - 并行召回 - 融合排序。检索计划长什么样我习惯用JSON结构化表示[ { query: 复古篮球鞋, constraints: {gender: 男, season: 秋冬, price_max: 500} }, { query: 篮球鞋 秋冬, constraints: {style: 复古} }, { query: 休闲运动鞋, constraints: {gender: 男, price_max: 500} } ]每一组里的query负责语义召回constraints负责结构化过滤。三组结果并行召回后做融合最终交给排序层。这就是标题里“生成式”的准确含义——它不是直接生成商品而是生成检索计划和查询条件。这种设计和传统“多路召回”的区别在于传统多路的每一路是人工配置好的固定规则比如“类目召回路”“品牌召回路”“新品召回路”覆盖面靠堆规则生成式多路是模型根据当前query现场生成长尾意图不用人肉枚举覆盖范围随模型的泛化能力走。3.2 结构化约束与非结构化语义的融合顺序比算法更重要多路召回之后融合策略我踩过很多坑最后沉淀下来一个原则硬约束前置过滤软约束后置加权。具体操作是生成结果里的价格、库存、发货地这些硬约束在进入向量检索或者倒排检索之前就先过滤掉避免无效计算。品牌、风格、人群这类软约束召回阶段不做硬过滤而是在融合阶段给命中约束的doc加权重。比如用户生成的三条检索计划都含“秋冬”某件商品如果同时命中了“秋冬”标签融合分数自然应该更高。融合排序我建议不要一上来就上复杂的Learning to Rank先用RRFReciprocal Rank Fusion或者简单的线性加权把链路跑通后面有数据了再迭代成可学习的融合模型。上来就搞复杂模型结果就是出了问题你根本分不清是生成式改写的问题还是融合模型的问题。3.3 多样性控制采样温度、top_k和去重LLM生成多个候选query时有个通病自嗨式重复。temperature设太低三条候选几乎一样设太高候选天马行空召回一堆不相关商品。我的实操配置temperature在0.7到0.9之间top_k取50左右生成后做两轮去重。第一轮用编辑距离去重第二轮用query的Embedding相似度去重相似度阈值0.85以上就只保留一条。另外还要加一个多样性约束每条检索计划尽量覆盖不同的约束子集或不同类目避免三条计划都是“篮球鞋”的不同说法。多样性也需要指标来衡量。我在离线阶段会统计单条query生成的N条检索计划之间类目覆盖率和约束覆盖率。如果生成的5条计划全是同一个类目说明模型偷懒了需要调节多样性的采样参数。3.4 为什么把它称为“召回范式跃迁”因为召回系统里模型扮演的角色变了。过去的召回模型是“匹配器”给定一条query去商品库里找最相似的doc角色是判官。而生成式召回里的模型是“生成器匹配器”它先基于用户表达生成多条可能的检索路线匹配器只是执行层角色是军师加执行者。这种改变带来的直接好处是召回入口的宽度。以前系统只有一条路走窄了就是漏召回现在系统先自己开出几条路每一条都可能捞回不同的商品子集最后融合在一起。用户表达得越模糊、越长、越口语化这个范式收益越大——因为模糊表达对应的潜在意图多生成多条路正好接住这种多峰分布。4. 生成式召回的排序与训练跨塔架构、损失函数、蒸馏4.1 改写模型的训练数据根本没有现成的标注集生成式召回落地时最大的拦路虎是数据。你不可能找人把几百万条query的“检索计划”都标出来我的做法是从搜索日志里挖正样本同一session里用户query与点击/成交商品标题的配对相似query同一商品被不同query点击共现触发query改写学习增强样本用离线LLM把原始query生成多种表达再用规则或小模型过滤保留与原始query语义一致的候选。一个特别容易踩的坑用商品标题原文做监督信号。电商标题全是营销文案“复古做旧篮球鞋男秋冬加绒保暖实战球鞋学生平价”这种直接拿来训练模型会学着输出一堆营销词。正确做法是先做商品结构化解析用类目、品牌、风格、人群、适用场景这些属性标签当监督信号让模型学的是“检索友好的表达”而不是“标题复读机”。4.2 召回双塔的Anchor从“原始query”变成“生成后的表达”生成式改造后召回模型不一定非要换成生成式架构双塔仍然是最高效的线上检索结构。但query塔的输入要变不再只吃原始query而是吃原始query和生成后的候选query的融合表示。我用的一个简化方案是把生成的多条候选query分别过query塔得到多个向量再和原始query向量做加权融合或attention融合然后和doc塔算相似度。训练时正样本是“生成query与点击商品”的配对负样本用batch内负采样加全局困难负样本。损失函数用InfoNCE或者带margin的hinge loss都可以。关键点在于query塔和doc塔的连接锚点变了。以前锚定的是“用户实际输入的词”现在锚定的是“用户真实意图的多种显式表达”。这样一来即使改写的query和原始query字面差距很远只要它更贴近用户真实意图的表达召回模型也能学会给它更高的分。4.3 蒸馏让召回塔“偷师”精排和生成模型想让召回结果在业务指标上变好不能只靠召回模型自己学还要把精排模型的知识蒸馏到召回塔里。精排模型见过大量特征对商品与query的匹配判断更准但它太重不可能在召回阶段对所有商品打分。蒸馏的目标函数我用的是KL散度让召回塔的打分分布尽量接近精排模型在同一个商品候选集合上的分布。这么做之后离线RecallK可能不升反降但线上成交转化往往变好——因为召回结果里与用户意图高度相关的商品比例提高了排序压力变小了。蒸馏温度要控制好。温度过高召回会向头部热门商品坍缩长尾商品和新鲜商品曝光明显减少温度过低蒸馏又学不到精排的排序知识。我一般从1.0开始调观察长尾品类曝光占比这个护栏指标跌太多就降温。4.4 在线服务链路改写的延迟预算怎么卡生成式召回最让工程头疼的就是延迟和稳定性。我的链路设计和预算是这样意图识别和约束抽取轻量模型20到50毫秒LLM改写小模型或带缓存100到300毫秒多路召回并行每一路50到150毫秒融合和排序50毫秒。整体预算压在300到500毫秒以内超过就做降级。降级策略分两层第一层改写结果超时直接回退到原始query召回保证用户体验不会从“能搜”变成“不能搜”第二层生成式链路的LLM网关必须做熔断任何一个环节失败都不能影响主链路。缓存策略也要设计好。热门query的改写结果按天级缓存每天凌晨全量刷新长尾query实时生成。我见过有人把所有query都丢给LLM实时生成结果网关被打爆线上故障一串串。记住热门query的生成性价比很低因为基线已经很强真正需要动态生成的是长尾口语化query。5. 同构离线评估与在线效果离线指标、回归测试、A/B实验框架5.1 离线评测别只盯着RecallK约束保留率才是命门生成式召回链路比传统召回多了一个“生成质量”变量所以离线评估也要分成两层。第一层评估生成结果本身。评测集要覆盖四类query热门query、长尾口语化query、多轮对话query、带复杂约束的query。指标除了文本生成常用的BLEU和编辑距离之外我最重视的是“约束保留率”——统计生成结果是否把用户原query里的价格、尺码、人群、品牌等约束完整保留下来。约束保留率不过90%线上无结果率一定会涨。第二层评估召回效果。在这个评测集上计算RecallK、MRR、NDCG但不要只看平均值要分层看热门query的提升、长尾query的提升、约束类query的提升。很多团队只汇报整体Recall涨了多少结果一看全是热门query在拉平均数长尾query其实变差了这就是典型的“伪提升”。5.2 离线涨点不等于线上增长交易搜索的北极星是成交我见过太多团队卡在这一步离线Recall涨了5个点高高兴兴上A/B线上GMV纹丝不动甚至下跌。原因不复杂——交易搜索的北极星是成交不是相关性。相关更好的排序不等于更高转化因为转化还受价格、库存、供给丰富度、用户购买意愿等多重因素影响。所以A/B实验的指标体系必须这样搭指标类型具体指标作用主指标GMV、支付转化率、搜索无结果率判断业务是否变好辅助指标点击率、人均浏览商品数、搜索到成交时长判断用户行为路径变化护栏指标客单价波动、类目偏移、新品曝光占比防止召回改偏实验时长建议至少跑7到14天因为生成式链路对长尾query的改善需要时间积累跑太短会被“新奇效应”误导。分桶策略上我建议按“用户query”双重分桶。只按用户分桶长尾query样本太少实验跑不出显著性只按query分桶用户维度又会被污染。双重分桶虽然复杂但数据质量高很多。5.3 回归测试和bad case管理改召回最怕“局部变差”召回范式改造最大的风险不是整体不涨而是某个细分场景变差却没被发现。比如生成式改写把“二手球鞋”改成“球鞋”因为生成词表里根本没有“二手”这个概念结果二手供给全部消失了。我的做法是开发一个新旧召回TopN商品集合的diff工具每天自动对比新增了哪些商品、消失了哪些商品、哪些类目占比发生变化。diff结果出来后组织bad case评审分类打标召回不相关、约束丢失、改写错误、意图偏差。积累两周后这些bad case会变成很有价值的few-shot样例——把它们塞回生成模型的prompt里很多问题会以意想不到的速度消失。有一点特别提醒case评审不能用“数量”作为唯一标准。一个明确购买意图的query出现bad case损失可能比一百个低意向query的bad case还大。我给每个case按“购买意图强度”加权排序先处理权重高的。6. 交易搜索场景落地中的几个“坑”从冷启动到可解释性6.1 热门query的“伪提升”和长尾query的“假死”这个坑我前面提了一嘴但值得单独展开。热门query的基线已经很高生成式无论怎么写提升空间都很有限还容易把流量引向错误方向。真正受益的是长尾、口语化、多轮query但这些query样本少模型往往学不好。冷启动阶段不要一上来就全量开放。我的节奏是先用规则加热门词表兜底一批确定性的改写结果对低置信度长尾query走灰度放量流量从1%慢慢涨建立自动反馈闭环生成式改写的召回结果如果连续N天没有点击或成交自动降级回退到原始query召回。“假死”问题也出在长尾query上。生成模型把用户query改写得过于“通顺”把口语化的关键信息改丢了导致检索出来的商品看着相关实际完全不是用户要的东西。这种问题离线很难发现因为从文本看改写是通顺的只能靠线上无点击率和无结果率来兜底。6.2 可解释性与“幻觉约束”生成模型比你想的更会胡说LLM在生成检索计划时会出现“幻觉约束”。用户说“女生篮球鞋”它生成“男生篮球鞋”用户说“预算500以内”它生成结果里价格约束丢了用户说“二手闲置”它理解成“全新”。这些问题的共性在于模型在用概率补全它以为合理的约束而不是忠实还原用户表达。应对手段我总结成三条生成结果必须过一道约束保留校验用规则或者小NER模型检查约束槽位是否完整校验不过就重新生成或直接回退原始query每个上线结果保留“检索计划快照”包括原始query、生成query、约束槽位、召回来源用户投诉或bad case评审时能一键溯源对高价值query支持人工修正修正结果进入缓存和样本库反哺后续训练。约束校验的检查项可以做成这样一张表约束类型用户表达示例校验方式价格“500以内”“预算三百”数值范围抽取检查生成结果是否保留性别/人群“女生”“男款”实体抽取检查是否被改写商品状态“二手”“全新”枚举词表检查尺码“42码”数值单位检查6.3 时延、成本与商品理解生成式不是万能药生成式召回的成本大头不在训练在线上推理。我曾经算过一笔账全量query实时走LLM生成光是GPU成本就比整个召回集群还贵延迟还经常打满预算。控制成本的方法只有那几个热门query缓存、低峰期离线批量生成、用开源小模型做线上主链路、把LLM API降级成离线增强工具。但比成本更隐蔽的问题是商品理解。生成式改写能产出“秋冬复古篮球鞋男”这种检索计划但如果商品侧没有“季节秋冬”“风格复古”这些结构化标签约束条件根本落不到索引上生成得再好也白搭。所以我强烈建议做生成式召回的同时一定要同步把商品结构化补齐。类目、品牌、价格、风格、人群、适用场景、季节这些属性先解析干净。有条件的话用“营销标题结构化标签用户常搜词”拼成一段检索友好描述再灌进向量库和倒排索引。没有这层地基生成式召回就是空中楼阁。6.4 把生成式当成“策略调度器”而不是“商品生成器”最后说一个我最有体会的经验。一开始我也踩过“让模型直接生成商品列表”的坑——既然生成式这么能写干脆让LLM直接吐商品结果结果上线之后bad case满天飞幻觉商品、过时商品、价格不真实的商品全都出来了。因为LLM的知识停留在训练阶段它并不知道你平台此刻的实时库存和价格。后来我把思路换成“策略调度器”生成模型不直接生成商品而是生成检索计划比如“query约束召回通道组合”商品检索和排序仍然交给确定性系统。这样等于把生成模型的泛化能力和现有系统的精准可控结合在了一起——生成负责开脑洞执行负责守底线。整个链路稳定之后我才开始逐步放开长尾query的实时生成比例业务指标也在这时候才开始稳定向上走。如果你也在交易搜索里纠结要不要上生成式召回我建议不要一开始就想着替换向量检索先补查询改写和约束抽取这两块跑通评估体系后再慢慢扩展。这条路线慢一点但每一步都踩得实。
返回列表