原文: 前沿重器[38] | 微软新文query2doc:用大模型做query检索拓展
比较主流的检索方案:
- 字面检索(sparse,稀疏)
- 向量检索(dense,稠密)
query对文档文段的召回,一直是存在困难的,因为两者无论是信息还是语义,其实都有很大的鸿沟。一般地,大家常用的方式有诸如“将qa匹配转化为qq匹配”、query改写、同义词、通过用户反馈构造匹配模型等手段。
论文:Query2doc: Query Expansion with Large Language Models 通过大模型的手段来进行改写。
1,拓展方法
文章思想:
- 在开始检索之前,先用query让模型生成一次答案,然后把query和答案合并送给模型。
举个例子,例如用户输入的是“儿童防沉迷”,原来是直接把“儿童防沉迷”直接用于检索,输入检索库中进行召回,然而现在,我们会结合prompt,先输入给大模型,并得到大模型的结果:
输入:
什么是儿童防沉迷。
要求,用大约100字回复。
------------------
输出:(结果来自chatglm2-int8)
儿童防沉迷是指避免儿童沉迷于网络、游戏、电子书等电子娱乐活动,保护儿童身心健康和防止未成年人受到网络游戏沉迷、网络信息诈骗等问题的影响。为了实现这一目标,家长和社会应该共同努力,对儿童进行网络安全教育,限制儿童使用电子产品的时间和内容,并营造良好的家庭氛围,鼓励儿童积极参与有益身心的活动,如运动、阅读、艺术等。
可以看到,相比原始query儿童防沉迷,还拓展了大量的相关信息,例如游戏、网络、未成年人等,这些词汇很直观地,能扩展更多概念解释,对提升召回肯定是有好处的。
改写是改写玩了,但是要放进去检索,更好地进行召回,还是有些技巧的,按照论文,对字面检索和向量检索,都有一些特定的设计。
1.1 字面检索
因为模型的生成多半会很长,所以在相似度计算的过程中,会稀释,所以在拼接过程中,需要对原始query复制几份再来拼接,用公式来描述,就是这样,其中d‘是大模型生成的内容,n是复制的次数:
1.2 向量检索
因为向量召回的泛化能力是比较强的,因此不需要复制,直接拼接起来就好了:
然而相比字面检索,最大的困难并不在拼接,而在于训练,因为输入和文档仍旧不是一个分布(两者语义并不相同甚至完全不相同,只是匹配),所以仍旧离不开训练,不过为了体现拓展的部分的效果,此处还是使用比较朴素的训练方案,即根据用户点击之类的行为构造数据集,并使用BM25等的方式获得难负例。
2、实验结果和分析
从实验结果看,收益无疑是巨大的,作者的分析其实更加有收获:
- 模型大小的提升对最终的召回效果是有收益的,随着模型变大,生成的文本对预测效果有提升。
- 该方案本身对向量表征模型(embedding)的训练,也是有明显收益的。
- 对字面检索而言,原始query和大模型生成的回复之间,是互补关系,两者组合才能真正达到提升。
然后是作者用两个案例做了分析,来探索本方案生效的机理和可能的缺陷。
- 首先,大模型直接生成一个答案,很大程度拉近了检索词和文档之间在语义空间上的相似,因为本质上两者都是回复问题。
- 其次,大模型的生成可能并不正确(幻觉问题),尤其是关键部位(例如时间、关键名词之类的),这个关键部位的错误可能会导致最终的检索错误。
3、在现实中,仍旧有很多细节问题还需要进一步考虑(可以作为优化点)
- 现实场景下的召回相似度应该如何计算,尤其是向量相似度,这里需要很多的数据支撑。
- 召回后的下一步,仍旧依赖相对完善的精排模块,也需要考虑类似的匹配机制,否则即使召回层有了召回,排序层面也会被排到后面去。
- 大模型本身的幻觉问题,会对召回带来很大的影响,该问题对召回还是有影响的,需要考虑如何尽可能剔除或者缓解。
- 性能问题,依赖大模型是能够有所提升,但是多一次的大模型的请求,无疑让整体耗时有了很大的影响。(这点在论文中也有提及)
补充
1,检索–>reranker 后任然有个别合适的 ’块‘ 排在最后面位置?
这个时候就可以分析bad case 。继续优化重拍模块了,看看是什么原因被排到了最后,一般:
- 找回链路不信任
- 关键链路漏召回
- 相似度计算
- 有问题的规则
都有可能出现问题,base case 分析推荐:
心法利器[37] | bad case治疗术:认知篇
心法利器[38] | bad case治疗术:现状篇
心法利器[39] | bad case治疗术:分析篇
心法利器[40] | bad case治疗术:解决篇
心法利器[32] | 一些印象深刻的bad case
ML&DEV[13] | bad case分析
NLP.TM[22] | 如何修正NLP问题的bad case
心法利器[103] | 大模型bad case修复方案思考