1、 什么RAG?
RAG(Retrieval Augmented Generation, 检索增强生成),即 LLM 在回答问题或生成文本时,先会从大量文档中检索出相关的信息,然后基于这些信息生成回答或文本,从而提高预测质量。
RAG 方法使得我们不必为每一个特定的任务重新训练整个大模型,只需要外挂上知识库,即可为模型提供额外的信息输入,提高其回答的准确性。
AG模型尤其适合知识密集型的任务。
2、LLM已经很强了,为什么仍需要RAG?
- 幻觉问题:LLM 文本生成的底层原理是基于概率的 token by token 的形式,因此会不可避免地产生“一本正经的胡说八道”的情况。
- 时效性问题:LLM 的规模越大,大模型训练的成本越高,周期也就越长。那么具有时效性的数据也就无法参与训练,所以也就无法直接回答时效性相关的问题,例如“帮我推荐几部热映的电影?”。
- 数据安全问题:通用的 LLM 没有企业内部数据和用户数据,那么企业想要在保证安全的前提下使用 LLM,最好的方式就是把数据全部放在本地,企业数据的业务计算全部在本地完成。而在线的大模型仅仅完成一个归纳的功能。
3、对比SFT,RAG有什么优点?
- 可扩展性 (Scalability):减少模型大小和训练成本,并允许轻松扩展知识
- 准确性 (Accuracy):模型基于事实并减少幻觉
- 可控性 (Controllability):允许更新或定制知识
- 可解释性 (Interpretability):检索到的项目作为模型预测中来源的参考
- 多功能性 (Versatility):RAG 可以针对多种任务进行微调和定制,包括QA、文本摘要、对话系统等。
4、如何实现RAG?
概括来说,RAG 的实现主要包括三个主要步骤:数据索引、检索和生成。
1. 数据索引的构建
该部分主要功能是将原始数据处理成为便于检索的格式(通常为embedding),该过程又可以进一步分为:
Step1: 数据提取
即从原始数据到便于处理的格式化数据的过程,具体工程包括:
- 数据获取:获得作为知识库的多种格式的数据,包括PDF、word、markdown以及数据库和API等;
- 数据清洗:对源数据进行去重、过滤、压缩和格式化等处理;
- 信息提取:提取重要信息,包括文件名、时间、章节title、图片等信息。
Step 2: 分块(Chunking)
由于文本可能较长,或者仅有部分内容相关的情况下,需要对文本进行分块切分,分块的方式有:
- 固定大小的分块方式:一般是256/512个tokens,取决于embedding模型的情况,弊端是会损失很多语义。
- 基于意图的分块方式:
- 句分割:最简单的是通过句号和换行来做切分,常用的意图包有基于NLP的NLTK和spaCy;
- 递归分割:通过分而治之的思想,用递归切分到最小单元的一种方式;
- 特殊分割:用于特殊场景。
常用的工具如 langchain.text_splitter 库中的类CharacterTextSplitter,可以指定分隔符、块大小、重叠和长度函数来拆分文本。
Step 3: 向量化(embedding)及创建索引
即将文本、图像、音频和视频等转化为向量矩阵的过程,也就是变成计算机可以理解的格式。常用的工具
如 langchain.embeddings.openai.OpenAIEmbeddings
和 langchain.embeddings.huggingface.HuggingFaceEmbeddings
等。
生成 embedding 之后就是创建索引。最常见的即使用 FAISS 库创建向量搜索索引。使用langchain.vectorstores
库中的 FAISS 类的from_texts
方法,使用文本块和生成的嵌入来构建搜索索引。
2.检索(Retrieval)
检索环节是获取有效信息的关键环节。检索优化一般分为下面五部分工作:
- 元数据过滤:当我们把索引分成许多chunks的时候,检索效率会成为问题。这时候,如果可以通过元数据先进行过滤,就会大大提升效率和相关度。
- 图关系检索:即引入知识图谱,将实体变成node,把它们之间的关系变成relation,就可以利用知识之间的关系做更准确的回答。特别是针对一些多跳问题,利用图数据索引会让检索的相关度变得更高;
- 检索技术:检索的主要方式还是这几种:
- 相似度检索:包括欧氏距离、曼哈顿距离、余弦等;
- 关键词检索:这是很传统的检索方式,元数据过滤也是一种,还有一种就是先把chunk做摘要,再通过关键词检索找到可能相关的chunk,增加检索效率。
- SQL检索:更加传统的检索算法。
- 重排序(Rerank):相关度、匹配度等因素做一些重新调整,得到更符合业务场景的排序。
- 查询轮换:这是查询检索的一种方式,一般会有几种方式:
- 子查询:可以在不同的场景中使用各种查询策略,比如可以使用LlamaIndex等框架提供的查询器,采用树查询(从叶子结点,一步步查询,合并),采用向量查询,或者最原始的顺序查询chunks等;
- HyDE:这是一种抄作业的方式,生成相似的或者更标准的 prompt 模板。
3. 文本生成
文本生成就是将原始 query 和检索得到的文本组合起来输入模型得到结果的过程,本质上就是个提示词工程。
此外还有全流程的框架,如 Langchain 和 LlamaIndex 。
5、RAG有哪些不足?
- 检索效果依赖 embedding 和检索算法,可能检索到无关信息,反而对输出有负面影响;
- 大模型如何利用检索到的信息仍是黑盒的,可能仍存在不准确(甚至生成的文本与检索信息相冲突);
- 对所有任务都无差别检索 k 个文本片段,效率不高,同时会大大增加模型输入的长度;
- 无法引用来源,也因此无法精准地查证事实,检索的真实性取决于数据源及检索算法。
6、什么是self-RAG?
RAG 方法都遵循着共同的范式,即: query+contert→LLM ,其中 query 表示用户的输入,context 表示检索获得的补充信息,然后共同输入到 LLM 中,可以认为这是一种检索前置的被动的增强方式。
相比而言,Self-RAG 则是更加主动和智能的实现方式,主要步骤概括如下:
- 判断是否需要额外检索事实性信息(retrieve on demand),仅当有需要时才召回
- 平行处理每个片段:生产prompt+一个片段的生成结果
- 使用反思字段,检查输出是否相关,选择最符合需要的片段;
- 再重复检索
- 生成结果会引用相关片段,以及输出结果是否符合该片段,便于查证事实。
Self-RAG 的一个重要创新是 Reflection tokens (反思字符):通过生成反思字符这一特殊标记来检查输出。这些字符会分为 Retrieve 和 Critique 两种类型,会标示:检查是否有检索的必要,完成检索后检查输出的相关性、完整性、检索片段是否支持输出的观点。模型会基于原有词库和反思字段来生成下一个 token。
7、self-RAG的过程是怎样的
Self-RAG 使用反思字符来自我评估输出,使其在推理过程中具有适应性。
根据任务的不同,可以定制模型,通过检索更多段落来优先考虑事实准确性,或强调开放式任务的创造力。
该模型可以决定何时检索段落或使用设定的阈值来触发检索。
当需要检索时,生成器同时处理多个段落,产生不同的候选。 进行片段级 beam search 以获得最佳序列。 每个细分的分数使用 Critic 分数进行更新,该分数是每个批评标记类型的归一化概率的加权和。
可以在推理过程中调整这些权重以定制模型的行为。 与其他需要额外训练才能改变行为的方法不同,Self-RAG 无需额外训练即可适应。