本文对文本RAG涉及到的主要12种关键“超参数”进行简单总结,主要包括摄取阶段(数据清洗、数据分块、embedding模型选择、元数据过滤、多重索引和索引算法)和推理阶段【检索和生成】(查询转换、检索参数、高级检索策略、重排序、大模型和Prompt工程)。下面将分别进行介绍:
一、摄取阶段
摄取阶段是构建RAG管道的准备步骤,类似于ML管道中的数据清理和预处理步骤。通常,摄入阶段包括以下步骤:
-
收集数据
-
对数据进行分块
-
对分块后的数据进行embedding
-
将分块数据embedding和块存储在矢量数据库中
1.1 数据清理
与任何数据科学管道一样,数据的质量严重影响RAG管道的结果。在继续执行以下任何步骤之前,请确保您的数据符合以下标准:
1)数据干净:可以应用一些自然语言处理中常用的基本数据清理技术,例如确保所有特殊字符都正确编码;
2)数据准确:确保信息一致且事实准确,以避免信息冲突误导LLM
1.2 分块
对文档进行分块是RAG管道中引入外部知识源的一个重要准备步骤,通常是将长文档分解成更小的部分(但它也可以将较小的片段组合成连贯的段落)。
在LangChain中,支持不同的text splitters[1],比如字符、令牌等。这取决于您拥有的数据类型,例如,如果您的输入数据是代码,而不是Markdown文件,则需要使用不同的分块技术。
块的理想长度(chunk_size)取决于具体用例:如果你的用例是问答,你可能需要更短的块;但如果你的案例是摘要,你可能会需要更长的块。此外,如果一个区块太短,它可能没有包含足够的上下文。另一方面,如果一个块太长,它可能包含太多不相关的信息。
此外,还需要考虑块(重叠)之间的“滚动窗口”,这样可以保证块之间的语义连贯性。
1.3 嵌入模型
嵌入模型是检索的核心,嵌入的质量严重影响检索结果。通常,生成嵌入的维度越高,嵌入的精度就越高。
可以在 Massive Text Embedding Benchmark (MTEB)排行榜[2]查看可用的文本嵌入模型,该排行榜涵盖164个文本嵌入模型(在撰写本文时)。
虽然可以开箱即用地使用通用嵌入模型,但在某些情况下,可以根据用户的特定用例微调嵌入模型,这样可以避免领域外问题。根据LlamaIndex进行的实验,微调嵌入模型可以使检索评估指标的性能提高5%-10%。
请注意,无法对所有嵌入模型进行微调(例如,OpenAI的text-ebmedding-ada-002目前无法进行微调)。
1.4 元数据
将矢量嵌入存储在矢量数据库中时,某些矢量数据库允许将它们与元数据(或未矢量化的数据)一起存储。用元数据注释矢量嵌入有助于对搜索结果进行额外的后处理,如元数据过滤(添加元数据,如日期、章节或分章引用)。
1.5 多重索引
如果元数据不足以提供额外的信息来从逻辑上分离不同类型的上下文,可能需要尝试使用多个索引,例如,可以对不同类型的文档使用不同的索引。
1.6 索引算法
为了实现大规模相似性搜索,矢量数据库和矢量索引库使用近似最近邻(ANN)搜索,而不是k最近邻(kNN)搜索。顾名思义,ANN算法近似于最近的邻居,因此可能不如kNN算法精确。
这里有不同的ANN算法可以参考,如Facebook Faiss[3](聚类)、Spotify Annoy[4](树)、Google ScaNN[5](矢量压缩)和HNSWLIB[6](接近图)。此外,这些ANN算法中的许多都有一些参数可以调整,例如HNSW[1]的ef、efConstruction和maxConnections。
此外,还可以为这些索引算法启用矢量压缩。与人工神经网络算法类似,矢量压缩会损失一些精度。然而,根据矢量压缩算法的选择及其调整,也可以对此进行优化。
然而,这些参数已经由向量数据库和向量索引库的研究团队在基准测试实验期间进行了调整,而不是由RAG系统的开发人员进行调整。然而,如果想自己尝试使用这些参数来压榨一点性能,建议可以参考这篇文章[7]。
二、推理阶段(检索和生成)
RAG管道的主要组成部分是检索和生成组成部分。本节主要讨论改进检索的策略(查询转换、检索参数、高级检索策略和重新排序模型),因为这是两者中更具影响力的组成部分。也会谈到了一些改进生成的策略(LLM和Prompt工程)。
2.1 查询转换
由于在RAG管道中检索附加上下文的搜索查询也会嵌入到向量空间中,因此其措辞也会影响搜索结果。因此,如果您的搜索查询没有得到令人满意的搜索结果,您可以尝试各种查询转换技术[8],例如:
- 重新表述:使用LLM重新表述查询,然后重试;
- 假设文档嵌入(HyDE):使用LLM生成对搜索查询的假设响应,并将两者用于检索;
- 子查询:将较长的查询分解为多个较短的查询。
2.2 检索参数
检索是RAG管道的重要组成部分。首先要考虑的是语义搜索是否足以满足您的用例,或者您是否想尝试混合搜索[9]。
在后一种情况下,需要在混合搜索中对稀疏和密集检索方法的聚合进行加权实验。因此,有必要调整参数alpha,该参数控制语义(alpha=1)和基于关键字的搜索(alpha=0)之间的权重。
此外,要检索的搜索结果的数量也将发挥重要作用。检索到的上下文的数量将影响所用上下文窗口的长度。此外,如果您使用的是重新排序模型,则需要考虑向该模型输入多少上下文。
请注意,虽然用于语义搜索的所用相似性度量是一个可以更改的参数,不需要进行实验,而应该根据所使用的嵌入模型进行设置(例如,text-embedding-ada-002支持余弦相似性或multi-qa-MiniLM-l6-cos-v1支持余弦相似、点积和欧几里得距离)。
2.3 高级检索策略
本节的基本思想是,用于检索的块不一定与用于生成的块相同。理想情况下,应该嵌入较小的块便于检索,而应该检索较大的上下文。
- 句子窗口检索:不要只检索相关的句子,而是检索检索到的句子前后适当句子的窗口;
- 自动合并检索:文档以树状结构组织。在查询时,可以将单独但相关的较小块合并到较大的上下文中。
2.4 重新排序模型
虽然语义搜索根据上下文与搜索查询的语义相似性来检索上下文,但“最相似”并不一定意味着“最相关”。重新排序模型,如Cohere[10]的重新排序模型可以通过计算每个检索到的上下文的查询相关性得分来帮助消除不相关的搜索结果。
|“most similar” doesn’t necessarily mean “most relevant”
如果使用的是重新排序器模型,则可能需要重新调整重新排序器输入的搜索结果数量,以及希望将多少重新排序的结果输入LLM。
与嵌入模型一样,同样可以对重新排序器进行微调。
2.5 LLM
LLM是生成响应的核心组件,根据用户的需求,可以有多种LLM可供选择,可以考虑例如开源模型或专有模型、推理成本、上下文长度等因素来选择大模型。
2.6 Prompt工程
如何表达或设计你的提示将对LLM的完成产生重大影响。此外,在提示中使用一些few-shot示例可以提高生成的质量。
如Retrieval parameters中所述,输入到提示中的上下文数量是一个超参数。虽然RAG管道的性能可以随着相关上下文的增加而提高,但如果相关上下文位于许多上下文的中间,则LLM也不会识别相关上下文,因此也可能会遇到“中间丢失”效应。
参考文献:
[1] https://python.langchain.com/docs/modules/data_connection/document_transformers/
[2] https://huggingface.co/spaces/mteb/leaderboard
[3] https://github.com/facebookresearch/faiss
[4] https://github.com/spotify/annoy
[5] https://github.com/google-research/google-research/tree/master/scann
[6] https://github.com/nmslib/hnswlib
[7] https://weaviate.io/blog/rag-evaluation?source=post_page-----7ca646833439--------------------------------#indexing-knobs
[8] https://gpt-index.readthedocs.io/en/v0.6.9/how_to/query/query_transformations.html
[9] https://towardsdatascience.com/improving-retrieval-performance-in-rag-pipelines-with-hybrid-search-c75203c2f2f5?source=post_page-----7ca646833439--------------------------------
[10] https://cohere.com/rerank?ref=txt.cohere.com&__hstc=14363112.8fc20f6b1a1ad8c0f80dcfed3741d271.1697800567394.1701091033915.1701173515537.7&__hssc=14363112.1.1701173515537&__hsfp=3638092843