最近在学习一个奇特的技术,叫做生成式检索。
生成式检索是一种利用生成式语言模型来检索的全新信息检索方法。不同于依赖外部索引的传统方法,生成式检索利用单个强大的模型来处理查询和文档语料库。在这个注重推理能力,讲agent的年代,生成式检索却走向了让模型“死记硬背”的另一个极端。
生成式检索用简单的话来说,就是对于输入查询(query),让模型直接生成出语料库里相关文章的id,是的,你没有看错,是直接生成id!当然,这就会涉及到一个很重要的问题——id长啥样?当前的主流做法有几种:
12345这样的数字串,也可能是apdkcr这样的hash串。然后模型在推理阶段是用自己的词表生成出这个id字符串。因为id没有明确含义,这种做法着实是挺难为模型的,相当于问一个人“为人民服务”出现在毛选的第几卷第几本第几页第几行第几个字。从后面的结果表格中可以看出,原子id效果是最好的,这个比较符合预期,但语义id效果最差,感觉这里是还有一些空间的。

说完了id的问题,另一个重要问题是怎么让模型记住这么多id?方法也很土很暴力,就是搞一堆(query, docid) pair 让模型学就完了。如果这种数据不够,那有一些方法合成,比较典型的有:
显然D2Q搞出来的数据更有可能接近使用场景的真实数据,所以效果好很多。D2Q其实不是什么新方法,四五年前就有人在IR任务里拿来增强模型。这两种方法都可以产生大量的训练数据,让模型充分死记硬背。

最后看下这种方法的效果和存在的问题。
根据这篇论文[2]的数据,在语料库不大(100k左右)的情况下这个方法还是表现不错的,可以超过bm25和经典的dual encoder+ann。但不得不说,这个成本可不低,100k文档的训练数据可能是4-5M条,要跑一会。

但当检索范围变大,这种方法的效果下降非常明显。这个结论也不意外,背几首古诗和背新华字典的难度肯定不同。随着语料库变大很快就差于经典的召回方法了。
另一个明显的问题是死记硬背导致的新文档更新问题。当语料库里增加新的文档之后,模型要重新训练,速度慢不说,效果还可能有各种问题。也有不少文章[3]专门研究这个问题。
以上就是对近期学习的一个简单总结。总的来说这个东西学术味道浓了一些,实用价值在现阶段应该还不大。但确实难说后面会不会有跟LLM结合的点。更多相关内容可以看这个Github Repo[4]。
Large Language Models are Built-in Autoregressive Search Engines: http://arxiv.org/abs/2305.09612
[2]How Does Generative Retrieval Scale to Millions of Passages?: http://arxiv.org/abs/2305.11841
[3]DSI++: Updating Transformer Memory with New Documents: http://arxiv.org/abs/2212.09744
[4]awesome-generative-information-retrieval: https://github.com/gabriben/awesome-generative-information-retrieval
code/s?__biz=MzI4MzEyOTIzOA==&mid=2648565034&idx=1&sn=dd217ba1b178dca95fef8269c244626c&chksm=f3a621d3c4d1a8c5aabc2e826a3622807b56b831dee4d45bf43ad6d665318d1fa4eede355009#rd