HyDE
HyDE(Hypothetical Document Embeddings)出自2022年12月的论文《Precise Zero-Shot Dense Retrieval without Relevance Labels》,是谈到RAG优化时经常被提起的一个方法。其思路很简单,对于query先让LLM生成一个假设可回答query对应的passage,将生成的passage向量编码之后去检索与其最相似的文档。即相比于直接将query向量编码之后检索相似文档,HyDE多了LLM生成假设文档这一步。
HyDE论文中示意的流程图如上图,主要分为两步:
- 第一步让LLM针对query生成多个假设文档。
- 第二步对生成的多个假设文档进行向量编码之后,用它们的平均向量去检索最相似的文档。在计算平均向量时,也可以考虑将原始query的向量作为其输入向量的一部分。
LlamaIndex中定义了HyDEQueryTransform实现了HyDE,这个类包含一个字段include_original
标识是否包括原始query,默认为True。 LLM生成假设文档的prompt模板如下:
HYDE_TMPL = (
"Please write a passage to answer the question\n"
"Try to include as many key details as possible.\n"
"\n"
"\n"
"{context_str}\n"
"\n"
"\n"
'Passage:"""\n'
)
HyDE论文中提出的主要使用场景是zero-shot稠密检索系统,作者认为它可以作为搜索系统初期没有相关日志训练有监督稠密检索器时的替代方案。在RAG场景下,如果LLM生成的假设文档与应用场景契合就可以提升效果,不然就会造成一些错误回答,LlamaIndex的文档中提到了两个失败案例,如果不使用HyDE得到的结果才是合理的:1.没有上下文时LLM生成的内容会错误解释query造成检索结果不匹配生成错误回答;2.对于开放式问题会造成偏见。
LLM4CS
LLM4CS出自2023年3月的《Large Language Models Know Your Contextual Search Intent: A Prompting Framework for Conversational Search》( github ),主要针对多轮对话中用户意图的理解。
LLM4CS的整体流程如上图所示,目的是将用户的会话查询转换为可以用于检索的搜索意图向量,然后使用这个向量去检索相关文档,包括如下三步:
1)改写:让LLM根据上下文对当前问题进行改写。
2)回复生成:让LLM成一个假设回复。
3)聚合:对改写的emb和回复的emb进行融合,生成最终的搜索意图查询向量。
Query2doc
Query2doc出自2023年3月的论文《Query2doc: Query Expansion with Large Language Models》,与HyDE有点类似,都利用LLM来生成伪文档,只是利用伪文档的方式有些许差异。
Query2doc如上图所示首先用few-shot prompt让LLM生成一个伪文档,接下来将原始query与伪文档拼接起来作为新的query。在稀疏检索和稠密检索上拼接的策略有所不同:
- 稀疏检索:因为query一般会比伪文档短很多,所以会将原始query复制n份(论文中n=5)后和伪文档 q ′ q^{'} q′拼接起来。即 q + = c o n c a t ( { q } × n , q ′ ) q^+=concat(\{q\}\times n, q^{'}) q+=concat({q}×n,q′)。
- 稠密检索:将原始query和伪文档
q
′
q^{'}
q′用
[SEP]
符号拼接起来: q + = c o n c a t ( q , [ S E P ] , d ′ ) q^+=concat(q, [SEP], d^{'}) q+=concat(q,[SEP],d′)。
rewrite-retrieve-read
rewrite-retrieve-read出自2023年5月的论文《Query Rewriting for Retrieval-Augmented Large Language Models》(github)。
论文将常规的先检索相关文档作为上下文让LLM回答问题的流程称之为retrieve-then-read(下图(a)),而在检索之前先用LLM将query进行改写的方式称为rewrite-retrieve-read(下图(b))。
论文让LLM改写query的prompt如下(因为论文中是使用搜索引擎作为检索器,所以在prompt中写的是针对搜索引擎来提供新的query):
## 对Open-domain QA
'''Think step by step to answer this question, and provide search engine queries for knowledge that you need. Split the queries with ';' and end the queries with '**'. {demonstration} Question: {x} Answer:
'''
### Multiple choice QA:
'''Provide a better search query for web search engine to answer the given question, end the queries with '**'. {demonstration} Question: {x} Answer:
'''
除了直接让LLM改写query之外,论文还提出如上图©所示的微调一个预训练模型T5的思路,分为两步训练:在第一步中先让LLM针对原始query x生成改写query x ~ \tilde{x} x~,并将LLM基于改写query检索文档作为上下文能够正确回答的 ( x , x ~ ) (x, \tilde{x}) (x,x~)作为warm-up训练集来微调T5。在第二步中使用PPO来继续微调模型。
Iter-RetGen
Iter-RetGen出自2023年5月的论文《Enhancing Retrieval-Augmented Large Language Models with Iterative Retrieval-Generation Synergy》,这篇论文严格来说是查询扩展。
Iter-RetGen将检索-生成的过程迭代T次,在第t次迭代时:1. 将前一次迭代的生成 y t − 1 y_{t-1} yt−1与query q连接用来检索top-k个文档片段;2. 让LLM根据检索的文档片段和q一起生成 y t y_t yt。
STEP-BACK Prompting
STEP-BACK Prompting出自2023年10月的论文《Take a Step Back: Evoking Reasoning via Abstraction in Large Language Models》。
STEP-BACK Prompting作者基于很多任务中包含了太多的细节难以让LLM检索相关事实来回答问题,比如上面图片中的两个例子。在这两个例子中如果问一个更抽象的问题(step-back question)更有利于模型去回答问题。所以STEP-BACK Prompting分为两步:
- 抽象Abstraction:让LLM基于原问题问关于问题的更抽象的概念或原则的通用step-back question,然后基于step-back question检索相关的事实。
- Reasoning:基于前一步检索的事实,LLM就能推理出回答原始问题的答案了。
论文中在Knowledge QA数据集上试验时的prompt如下: