I2I recall

plus2047 于 2022-10-01 发布

Swing 一文着重介绍了算法本身的细节,本文介绍 Q2I2I 召回的在搜索业务中的一些经验。阅读本文之前请先阅读 Swing for Search(Swing 算法在搜索召回中的应用)

Trigger 选取

我们在上文中介绍过,Q2I2I 的 trigger 也可以在 pre-rank 之后选取 top item. 但这种方法主要问题是一般由于延时、计算量限制,这样召回的物品可能没有办法再走一遍 pre-rank 流程了。这种方法比较适用于常常出现召回数量不足的系统。当 pre-rank 之后发现召回数量不足时,可以使用这种方法召回一些 item 作为补充。

而更合理的做法是在召回阶段设法选取一些 item 作为 trigger. 保留几十个较为合适,可用的方案包括,

I2I 工程实现方式

给定 Trigger 之后,如何实现 I2I 召回就容易多了。但还是可以有两种方式:最直观的一种方法是把 I2I 列表写进 Redis Cache, 直接读 Cache. 这种方法简单而且可控性好,可以很方便的调整每个 Trigger 的召回数量。

还有一种不那么直观的方法,搜索系统中常常使用 ElasticSearch 或者类似的倒排系统,于是可以把 I2I 表作为 tag 写进文档倒排表中。I2I 表格原则上是对称的,对倒排索引不需要特殊处理。这种方法的好处是可以与文本方法结合,比如要求 item 满足一定的文本匹配条件。

这种方法多了一层抽象,而且由于是倒排表,不容易直接控制每个 Trigger 的召回数量,反而是可以控制倒排索引的 I2I list 长度,间接控制召回数量。ElasticSearch 在召回时需要给出一个排序公式,如果 I2I tag 命中 文档数量过多,同时 ElasticSearch 召回数量有限,那么,最后主要起作用的其实是这个排序公式。于是,这种方法会有 trigger 数量,倒排索引 I2I tag 数量,ElasticSearch 召回数量,排序公式等众多需要小心决策的参数,而且这些参数对 I2I 实际命中数量的控制都是间接的。

收益讨论

Q2I2I 召回在搜索场景中效果意外的很不错。笔者曾经认为,这种召回方式因为是「两跳」的,效果可能不会很好。既然有方法实现 Q2I 第一跳,为什么还要额外的第二跳呢?但实际经验表明,这种方法即使在 text match, vector recall 等方法之后上线,也能有一定的收益。如果较早上线,甚至能够占据相当大的流量,成为主力召回方法。对此,笔者认为原因可能包括,