快手用生成式重做了搜索,都藏在这两篇论文里

夕小瑶科技说

上周一个在快手做搜索的前同事发消息给我,说他们前段时间搞了一个收益非常大的上线,发了两篇论文,能不能帮忙宣传一下。


这个朋友去年还跟我吐槽,感觉自己马上要失业了,做搜索已经不知道该优化啥了。


ChatGPT要替代搜索引擎,这个论调炒了两年,作为一个做了五年搜索算法的老兵,过去两年我一直在思考一个问题:搜索系统还能做点什么。


BERT双塔、向量检索、多路召回、精排蒸馏...该加的路都加了,该卷的点都卷完了。行业共识是搜索已经是一个成熟技术,增量优化空间越来越小。


我问他改进有多大?他说这套系统已经在快手搜索全量上线,创造了近两年最大的单次实验收益。


“你们咋做的?”他就把论文发过来了。


Rethinking倒排索引、Rethinking搜索架构。


倒排索引是搜索系统的基石,从1998年到现在27年了,全世界搞搜索的都在这个框架里优化。


这两个Rethinking让我有点警惕,抱着怀疑的心态去看了下这两篇论文。


读完后的整体感受是:


快手这两篇论文(UniDex和UniSearch)在当下生成式大模型热度这么高的时候,这种工业级系统改进的工作,真的非常稀缺,有种返璞归真的感觉。


很多人以为生成式搜索就是Perplexity那种AI问答,其实快手做的是完全不同的另一件事。


Perplexity是改变了你「怎么看结果」,从10条蓝链接变成AI生成的答案;快手的内容还是快手里真实的短视频、直播间,改变的是系统「怎么找到结果」 后者是技术创新。具体来说:


  • UniDex把倒排索引从「词」换成了「语义ID」;

  • UniSearch把召回-粗排-精排三段式换成了端到端生成。


今天这篇文章,我会带入到之前做搜索算法的角色,讲一下面对数百亿视频资源、数十万并发直播间、每天数亿次搜索请求的业务场景里,他们在技术上怎么做到的。


UniDex重构倒排索引


先来聊聊UniDex。


倒排索引(Inverted Index)是所有搜索引擎的基石技术,基于词匹配(Term-based)进行检索。


词→包含该词的文档列表
"红烧肉"→[Doc1,Doc5,Doc29,...]
"教程"→[Doc1,Doc8,Doc15,...]


比如用户搜"红烧肉教程",系统找到“红烧肉”、“教程”两个索引的交集,然后用BM25打分。从1998年Google诞生到现在,这个范式一直在用。


但它有个致命问题:只能匹配"字词",无法理解"语义"。比如query用"教程",视频用"指南"、"tutorial"就没办法召回。


这就是 词汇鸿沟 (Vocabulary Mismatch)。为了缓解这个问题,工程师们发明了无数补丁:同义词词典、停用词处理、query改写、多路召回...系统也逐渐复杂,每次改动都要祈祷别把其他地方搞挂。


快手技术团队在这篇论文里给出了一种节省资源、搜索体验更好的解决方案—— UniDex。


从基于词项(Term-based)转向基于模型的语义(Model-based)索引。不用词,改用模型学出来的语义ID(Semantic IDs)。


UniDex主要包含两个核心模块:


  1. UniTouch(触达模块):将query和doc映射为离散的语义ID。

  2. UniRank(排序模块):通过语义匹配对检索结果进行精细排序。

UniTouch负责将视频和query映射为 语义ID序列


视频→Doc Encoder→语义嵌入→FSQ量化→8个语义ID序列,例如:


猫咪→[S1:57099,S2:315147,S3:315371,...]
狗狗→[S1:57099,S2:218453,S3:425681,...]


查询时也生成语义ID。


Query "可爱的猫"→Query Encoder→语义嵌入→FSQ量化→3个语义ID[S1:57099,S2:315147,S3:315371]。


为什么query用3个ID,document用8个?


因为query通常短且语义聚焦,3个ID足够;而document内容丰富,可能包含多个语义侧面,需要更多ID来表达。


这样即使query和视频元数据没有字面重合,只要语义相近就能检索到。


为什么要量化成离散ID?


因为连续的embedding无法直接建倒排索引。必须把连续空间离散化,才能像传统Term一样查表。


如何判断query和document是否相关?


传统BM25看有多少词重叠,UniDex的方法是看有多少语义ID重叠。


并且使用了"Max-Max"匹配策略,只要query的3个ID和doc的8个ID有1个匹配就召回,因为用户query可能有多重意图,匹配一个就该返回。


UniRank是精排模块,采用类似ColBERT的token级交互,但更轻量,因为query和doc只使用少量token,大大提升语义匹配精度。


UniRank与UniTouch用的是同一套语义编码框架,这样的好处是召回和排序两个阶段共用统一的语义表征方式,避免表征差异导致的匹配偏差。



所以它是用了一个统一的语义建模框架,这就是论文标题为什么叫"Unified Semantic Modeling"的原因。


UniDex的实际效果


看Table 1,这个对比很说明问题。


传统BM25的Recall@300是49.56%,SPLADE这种神经稀疏检索做到56.56%,快手自己的baseline是55.33%, UniDex直接干到70.74%,逼近了Dense Retrieval的效果上限。



再看Table 5的线上数据,在快手短视频搜索里(10亿视频库),CTR、VPD、LPC这些用户满意度指标全涨了。



更关键的是资源消耗:CPU核数-20550(节省了2万多核),内存节省37TB,响应延迟降低25%。


为什么能省资源? 传统的同义词扩展、query改写、多路召回、复杂term匹配规则...都省了,UniDex只需要一次模型推理,得到query语义ID,查UniDex的语义倒排索引就可以,简洁高效。


UniSearch:统一搜索三段式


再来聊一下UniSearch。


UniDex是重构了搜索的"索引层",那么UniSearch则是动了搜索的架构。


传统搜索(包括用了UniDex的系统)本质还是检索范式,召回-粗排-精排,UniSearch是生成范式,Query直接生成Top-K结果的语义ID序列,统一了三段式。


“统一”的三层含义


看到一个模型替代三段式,很多人觉得就是把召回、粗排、精排三个模型合并成一个大模型。


太浅了。


传统级联架构的问题不是"模型太多",而是召回、粗排、精排的优化目标都不一致。


而且号称"生成式推荐"的相关模型们,也没有逃出这个陷阱,也是两阶段,先训练Video Encoder,再训Generator。


UniSearch是一个“真端到端”的训练架构。


把Search Generator和Video Encoder放到一个训练框架里,联合优化。


看架构图。Search Generator负责理解query、生成语义ID序列;Video Encoder负责把视频编码成embedding、通过VQ-VAE量化成语义ID。


两个模型虽然独立,但关键在于它们通过统一的损失函数绑在一起。论文里的联合损失函数写得很清楚:


L=λ1·L_contrast+λ2·L_codebook+λ3·L_NTP


  • L_contrast:query和video的语义对齐。

  • L_codebook:VQ-VAE的codebook质量。关键是这个codebook是可学习的。

  • L_NTP:Generator的生成准确性。


从语义对齐、离散化质量、生成准确性,全程一个目标函数联合优化。


论文里还有个很巧妙的设计。


每个视频用k个语义ID表示,但这k个ID不是独立学的,而是用 残差对比学习 (Residual Contrastive Learning)逐步递进:


  • 第1步生成:ID_1(粗粒度语义:动画类)

  • 第2步生成:ID_2(细粒度语义:儿童向)

  • 第3步生成:ID_3(最细粒度:熊出没IP)


分别对应召回的粗粒度、粗排的中粒度、精排的细粒度,自然形成了从粗到细的层次结构,模拟了传统三阶段的能力递进。


UniSearch要在直播搜索全量上线,面临的第一个问题就是: 直播内容的极端动态性。


电商搜索,商品相对稳定,小时级更新就够了。短视频搜索,内容缓慢增长,分钟级更新也能接受。


但直播不一样。


11:00:00,某主播开播"熊出没玩具开箱";11:30:00,转播"王者荣耀";12:00:00,下播。内容每分钟都在变,直播间每秒都在开播/下播。快手有 数十万并发直播间 ,每秒数千次状态变化,所以UniSearch的实时链路必须做到秒级响应。


所以线上实时链路里是怎么跑的呢?


看架构图,整个链路分三块:以用户输入Query "熊出没"为例进行说明:


实时生产模块


这是保证内容时效性的关键。


Embedding生产 :直播间一开播,Video Encoder立刻提取标题、封面、主播信息等特征,编码成语义向量。


码本生产 :语义向量通过VQ-VAE量化成离散的语义ID。论文设计是k=3层ID,每层512个codebook,总共512³≈1.3亿种组合。


实时消费:新增/更新/逐出。


  • 新增:直播间开播,生成语义ID,写入Trie树。

  • 更新:主播改变内容(从聊天变打游戏),1分钟内embedding刷新,ID重新映射。

  • 逐出:直播间下播,从Trie树删除对应路径。


论文说的是"1分钟时间窗口"——直播间的表征每分钟更新一次,保证内容和ID的一致性。


动态Trie树


这是整个实时链路的核心创新。


传统生成式模型的致命问题:可能生成不存在的ID组合。Trie树能实时监听"码本生产"的数据流,维护所有在线直播间的有效路径。


图上画的很清楚,t-1时刻的Trie和t时刻的Trie,结构在动态变化——有新节点加入,有旧节点移除。


UniSearch输出的不是直接的ID序列,而是码本概率分布。然后在Trie树上做beam search。


第1步生成:ID=57099(动画类)
问Trie:"接下来能选哪些?"Trie返回:[315147,315148,315149](当前在线的有效子节点)


第2步生成:从[315147,315148,315149]里选,假设选了315147(儿童向)再问Trie:"接下来能选哪些?"Trie返回:[315371,315372,...]


第3步生成:选315371(熊出没IP)


每一步生成时,Trie只允许选择"有效路径",保证生成的路径一定指向真实的直播间。


论文数据:有效生成率从51.3%提升到99.8%。


Reward System+Online Training


右侧的Reward System收集两种信号:


  • R_system:精排模型的系统评分(相关性、质量)

  • R_interaction:用户真实行为(点击、观看、关注)


合成最终奖励:R=γ1×R_system+γ2×R_interaction


每天晚上,左侧的Online Training用 SPO算法 (Search Preference Optimization)更新模型。


比如发现用户更喜欢"玩具开箱"类直播?→增加相关ID的生成概率。第二天早上新参数同步到线上,系统在持续进化。


这就是工业级生成式搜索的完整闭环。


UniSearch在快手直播搜索全量上线后,TPC+3.31%是快手直播搜索近两年单次实验的最大收益。



更有意思的是深入分析: 65%的增长来自长尾query ,因为UniSearch本质是语义理解提升了。



还有,58%的增长来自新用户。


新用户没有历史行为,传统推荐很难个性化。UniSearch靠语义理解能给出更准确的搜索结果。


最后


当所有人都在讨论"大模型能做什么"的时候,大部分答案都指向:生成文本、写代码、做助手。仿佛生成式AI的全部价值就是"替代人类生产内容"。


但快手这个案例让我看到了完全不同的可能性:


生成式AI不一定要生成内容,它可以用来重构系统架构。


UniDex和UniSearch的核心都是“统一”——统一的语义空间、统一的优化目标、统一的训练框架。


端到端优化,消除系统内耗,这应该是工业级系统的护城河。

本内容来源于网络 原文链接,观点仅代表作者本人,不代表虎嗅立场。如涉及版权问题请联系 hezuo@huxiu.com,我们将及时核实并处理。