RAG中的3个高级检索技巧

本文涉及的产品
实时数仓Hologres,5000CU*H 100GB 3个月
实时计算 Flink 版,5000CU*H 3个月
检索分析服务 Elasticsearch 版,2核4GB开发者规格 1个月
简介: RAG系统检索的文档可能并不总是与用户的查询保持一致,这是一个常见的现象。当文档可能缺乏查询的完整答案或者包含冗余信息或包含不相关的细节,或者文档的顺序可能与用户的意图不一致时,就会经常出现这种情况。

本文将探讨三种有效的技术来增强基于rag的应用程序中的文档检索,通过结合这些技术,可以检索与用户查询密切匹配的更相关的文档,从而生成更好的答案。

查询扩展

查询扩展指的是一组重新表述原始查询的技术。

本文将讨论两种易于实现的流行方法。

1、使用生成的答案扩展查询

给定一个输入查询,首先让LLM提供一个假设答案(不管其正确性),然后将查询和生成的答案组合在一个提示中并发送给检索系统。

这种技术效果非常的好。这篇论文有详细的介绍:https://arxiv.org/abs/2212.10496

这个方法的思想是,我们希望检索看起来更像答案的文档,我们感兴趣的是它的结构和表述。所以可以将假设的答案视为帮助识别嵌入空间中相关邻域的模板。

下面是一个示例提示:

 You are a helpful expert financial research assistant.

 Provide an example answer to the given question, that might 
 be found in a document like an annual report.

2、通过包含多个相关问题扩展查询

第二种方法指示LLM生成与原始查询相关的N个问题,然后将它们(+原始查询)全部发送到检索系统。

这样可以从vectorstore中检索更多文档。但是其中一些将是重复的,所以需要执行后处理来删除它们。

这个方法的思想是扩展可能不完整或不明确的初始查询,合并成最终可能相关和互补最终结果。

下面是用来生成相关问题的提示:

 You are a helpful expert financial research assistant. 
 Your users are asking questions about an annual report.
 Suggest up to five additional related questions to help them 
 find the information they need, for the provided question.
 Suggest only short questions without compound sentences. 
 Suggest a variety of questions that cover different aspects of the topic.
 Make sure they are complete questions, and that they are related to 
 the original question.
 Output one question per line. Do not number the questions.

这种方法的缺点是最终会得到更多的文档,而这些文档可能会分散LLM的注意力,使其无法生成有用的答案。

所以就衍生出一个新的方法,重排序

重排序

该方法根据量化其与输入查询的相关性的分数对检索到的文档重新排序。

使用cross-encoder进行重新排序:

交叉编码器cross-encoder是一种深度神经网络,它将两个输入序列作为单个输入处理。允许模型直接比较和对比输入,以更综合和细致的方式理解它们的关系。

给定一个查询,用所有检索到的文档对其进行编码。然后按降序排序。得分高的认为是最相关的文件。

下面有一个简单的示例:

首先安装sentence-transformers

 pip install -U sentence-transformers

使用它加载cross-encoder模型:

 from sentence_transformers import CrossEncoder 
 cross_encoder = CrossEncoder("cross-encoder/ms-marco-MiniLM-L-6-v2")

这里我们选择ms-marco-MiniLM-L-6-v2,对于排序的性能度量可以参考SBERT选择更好的模型。

每对(查询,文档)打分:

 pairs = [[query, doc] for doc in retrieved_documents] 
 scores = cross_encoder.predict(pairs) 

 print("Scores:") for score in scores:     
 print(score)  

 # Scores: 
 # 0.98693466 
 # 2.644579 
 # -0.26802942 
 # -10.73159 
 # -7.7066045 
 # -5.6469955 
 # -4.297035 
 # -10.933233 
 # -7.0384283 
 # -7.3246956

重新整理文件:

 print("New Ordering:") 
 for o in np.argsort(scores)[::-1]:
     print(o+1)

重排序可以与查询扩展一起使用,在生成多个相关问题并检索相应文档(假设最终有M个文档)之后,对它们重新排序并选择最前面的K (K < M)。这样可以选择最重要的部分并且减小上下文的大小。

嵌入的适配器

这个方法利用用户检索文档相关性的反馈来训练一个新的适配器。

适配器是完全微调预训练模型的轻量级替代方案。一盘情况下适配器会插入到预训练模型层之间的小型前馈神经网络中,所以训练适配器的目标是更改嵌入查询,以便为特定任务生成更好的检索结果。

嵌入适配器是一个可以在嵌入阶段之后和检索之前插入的阶段。把它想象成一个对原始嵌入进行缩放的矩阵。

要训练适配器,需要执行以下步骤。

1、准备数据

这些数据可以手工标记或由LLM生成。数据必须包括元组(query, document)及其相应的标签(如果文档与查询相关,则为1,否则为-1)。

为了演示,我们将创建一个合成数据集,首先生成金融分析师在分析财务报告时可能会问的示例问题。

让我们使用LLM直接生成:

 import os
 import openai
 from openai import OpenAI

 from dotenv import load_dotenv, find_dotenv
 _ = load_dotenv(find_dotenv())
 openai.api_key = os.environ['OPENAI_API_KEY']

 PROMPT_DATASET = """
 You are a helpful expert financial research assistant. 
 You help users analyze financial statements to better understand companies.
 Suggest 10 to 15 short questions that are important to ask when analyzing 
 an annual report.
 Do not output any compound questions (questions with multiple sentences 
 or conjunctions).
 Output each question on a separate line divided by a newline.
 """

 def generate_queries(model="gpt-3.5-turbo"):
     messages = [
         {
             "role": "system",
             "content": PROMPT_DATASET,
         },
     ]

     response = openai_client.chat.completions.create(
         model=model,
         messages=messages,
     )
     content = response.choices[0].message.content
     content = content.split("\n")
     return content


 generated_queries = generate_queries()
 for query in generated_queries:
     print(query)

 # 1. What is the company's revenue growth rate over the past three years?
 # 2. What are the company's total assets and total liabilities?
 # 3. How much debt does the company have? Is it increasing or decreasing?
 # 4. What is the company's profit margin? Is it improving or declining?
 # 5. What are the company's cash flow from operations, investing, and financing activities?
 # 6. What are the company's major sources of revenue?
 # 7. Does the company have any pending litigation or legal issues?
 # 8. What is the company's market share compared to its competitors?
 # 9. How much cash does the company have on hand?
 # 10. Are there any major changes in the company's executive team or board of directors?
 # 11. What is the company's dividend history and policy?
 # 12. Are there any related party transactions?
 # 13. What are the company's major risks and uncertainties?
 # 14. What is the company's current ratio and quick ratio?
 # 15. How has the company's stock price performed over the past year?

然后,我们对每个生成的问题进行文档检索,得到了一个结果的合集

 results = chroma_collection.query(query_texts=generated_queries, n_results=10, include=['documents', 'embeddings'])
 retrieved_documents = results['documents']

然后需要评估每个问题与其相应文件的相关性。这里也使用LLM来完成这项任务:

 PROMPT_EVALUATION = """
 You are a helpful expert financial research assistant. 
 You help users analyze financial statements to better understand companies.
 For the given query, evaluate whether the following satement is relevant.
 Output only 'yes' or 'no'.
 """

 def evaluate_results(query, statement, model="gpt-3.5-turbo"):
     messages = [
     {
         "role": "system",
         "content": PROMPT_EVALUATION,
     },
     {
         "role": "user",
         "content": f"Query: {query}, Statement: {statement}"
     }
     ]

     response = openai_client.chat.completions.create(
         model=model,
         messages=messages,
         max_tokens=1
     )
     content = response.choices[0].message.content
     if content == "yes":
         return 1
     return -1

现在就得到了我们的训练数据:每个元组将包含查询的嵌入、文档的嵌入和标签(1,-1)。

 retrieved_embeddings = results['embeddings']
 query_embeddings = embedding_function(generated_queries)

 adapter_query_embeddings = []
 adapter_doc_embeddings = []
 adapter_labels = []

 for q, query in enumerate(tqdm(generated_queries)):
     for d, document in enumerate(retrieved_documents[q]):
         adapter_query_embeddings.append(query_embeddings[q])
         adapter_doc_embeddings.append(retrieved_embeddings[q][d])
         adapter_labels.append(evaluate_results(query, document))

然后将它们放在Torch Dataset中作为训练集

 adapter_query_embeddings = torch.Tensor(np.array(adapter_query_embeddings))
 adapter_doc_embeddings = torch.Tensor(np.array(adapter_doc_embeddings))
 adapter_labels = torch.Tensor(np.expand_dims(np.array(adapter_labels),1))
 dataset = torch.utils.data.TensorDataset(adapter_query_embeddings, adapter_doc_embeddings, adapter_labels)

2、定义模型

我们定义了一个函数,它将查询嵌入、文档嵌入和适配器矩阵作为输入。该函数首先将查询嵌入与适配器矩阵相乘,并计算该结果与文档嵌入之间的余弦相似度。

 def model(query_embedding, document_embedding, adaptor_matrix):
     updated_query_embedding = torch.matmul(adaptor_matrix, query_embedding)
     return torch.cosine_similarity(updated_query_embedding, document_embedding, dim=0)

3、损失

我们的目标是最小化由前一个函数计算的余弦相似度。所以可以直接使用均方误差(MSE)

 def mse_loss(query_embedding, document_embedding, adaptor_matrix, label):
     return torch.nn.MSELoss()(model(query_embedding, document_embedding, adaptor_matrix), label)

4、训练过程

初始化适配器矩阵并训练它超过100次。

 # Initialize the adaptor matrix
 mat_size = len(adapter_query_embeddings[0])
 adapter_matrix = torch.randn(mat_size, mat_size, requires_grad=True)

 min_loss = float('inf')
 best_matrix = None
 for epoch in tqdm(range(100)):
     for query_embedding, document_embedding, label in dataset:
         loss = mse_loss(query_embedding, document_embedding, adapter_matrix, label)
         if loss < min_loss:
             min_loss = loss
             best_matrix = adapter_matrix.clone().detach().numpy()
         loss.backward()
         with torch.no_grad():
             adapter_matrix -= 0.01 * adapter_matrix.grad
             adapter_matrix.grad.zero_()

训练完成后,适配器可用于扩展原始嵌入并适应用户任务。

我们需要做的就是将原始的嵌入输出与适配器矩阵相乘,然后再将其输入到检索系统。

 test_vector = torch.ones((mat_size,1))
 scaled_vector = np.matmul(best_matrix, test_vector).numpy()

 test_vector.shape
 # torch.Size([384, 1])

 scaled_vector.shape
 # (384, 1)

 best_matrix.shape
 # (384, 384)

这样,我们检索系统后续使用的嵌入向量就是经过我们微调后的向量了,这相当于针对特定的任务进行优化

总结

我们介绍的这些检索技术有助于提高文档的相关性。但是这方面的研究还正在进行,还有很多其他方法例如,

利用真实反馈数据对嵌入模型进行微调;直接微调LLM以使其检索能力最大化(RA-DIT);探索更复杂的嵌入适配器使用深度神经网络而不是矩阵;深度和智能分块技术

这些技术我们也会在后面进行整理和介绍,感谢阅读。

https://avoid.overfit.cn/post/2f2d747462c44425be906b7c5611fe37

作者:Ahmed Besbes

目录
相关文章
|
SQL 人工智能 分布式计算
基于阿里云PAI平台搭建知识库检索增强的大模型对话系统
基于原始的阿里云计算平台产技文档,搭建一套基于大模型检索增强答疑机器人。本方案已在阿里云线上多个场景落地,将覆盖阿里云官方答疑群聊、研发答疑机器人、钉钉技术服务助手等。线上工单拦截率提升10+%,答疑采纳率70+%,显著提升答疑效率。
|
7天前
|
人工智能 自然语言处理 安全
通过阿里云Milvus与PAI搭建高效的检索增强对话系统
阿里云向量检索Milvus版是一款全托管的云服务,兼容开源Milvus并支持无缝迁移。它提供大规模AI向量数据的相似性检索服务,具备易用性、可用性、安全性和低成本等优势,适用于多模态搜索、检索增强生成(RAG)、搜索推荐、内容风险识别等场景。用户可通过PAI平台部署RAG系统,创建和配置Milvus实例,并利用Attu工具进行可视化操作,快速开发和部署应用。使用前需确保Milvus实例和PAI在相同地域,并完成相关配置与开通服务。
|
2月前
|
存储 边缘计算 自然语言处理
25 个值得关注的检索增强生成 (RAG) 模型和框架
大型语言模型(LLM)如GPT-4在自然语言处理(NLP)领域展现了卓越能力,但也存在知识截止、静态知识库和内存限制等局限。检索增强生成(RAG)通过集成检索机制,允许LLM动态访问和整合外部数据源,提高了生成响应的准确性、相关性和时效性。本文深入探讨了25种先进的RAG变体,每种变体都旨在优化检索和生成过程的特定方面,涵盖成本限制、实时交互和多模态数据集成等问题,展示了RAG在提升NLP能力方面的多功能性和潜力。
91 4
25 个值得关注的检索增强生成 (RAG) 模型和框架
|
2月前
|
机器学习/深度学习 存储 自然语言处理
方案测评|巧用文档智能和RAG构建大语言模型知识库
本文介绍了一款基于文档智能和大语言模型(LLM)的文档解析及问答应用,旨在提升企业文档管理和信息检索效率。系统通过文档解析、知识库构建和问答服务三大模块,实现了从文档上传到智能问答的全流程自动化。
|
2月前
|
数据采集 人工智能 自然语言处理
文档智能与检索增强生成结合的LLM知识库方案测评:优势与改进空间
《文档智能 & RAG让AI大模型更懂业务》解决方案通过结合文档智能和检索增强生成(RAG)技术,构建企业级文档知识库。方案详细介绍了文档清洗、向量化、问答召回等步骤,但在向量化算法选择、多模态支持和用户界面上有待改进。部署过程中遇到一些技术问题,建议优化性能和增加实时处理能力。总体而言,方案在金融、法律、医疗等领域具有广泛应用前景。
76 11
|
8月前
|
自然语言处理 物联网 API
检索增强生成(RAG)实践:基于LlamaIndex和Qwen1.5搭建智能问答系统
检索增强生成(RAG)实践:基于LlamaIndex和Qwen1.5搭建智能问答系统
检索增强生成(RAG)实践:基于LlamaIndex和Qwen1.5搭建智能问答系统
|
3月前
|
数据采集 自然语言处理 算法
实战RAG:构建基于检索增强的问答系统
【10月更文挑战第21天】在当今大数据时代,如何高效地从海量信息中获取所需知识,成为一个亟待解决的问题。检索增强的生成模型(Retrieval-Augmented Generation, RAG)应运而生,它结合了检索技术和生成模型的优点,旨在提高生成模型的回答质量和准确性。作为一名热衷于自然语言处理(NLP)领域的开发者,我有幸在多个项目中应用了RAG技术,并取得了不错的成效。本文将从我个人的实际经验出发,详细介绍如何使用RAG技术来构建一个问答系统,希望能够帮助那些已经对RAG有一定了解并希望将其应用于实际项目中的开发者们。
288 1
|
3月前
|
数据采集 自然语言处理 UED
文档智能和检索增强生成(RAG)技术
文档智能和检索增强生成(RAG)技术
Nyx
|
3月前
|
算法
文档智能和检索增强生成构建知识库
本文介绍了文档智能(Document Mind)与检索增强生成(RAG)结合使用的原理及其优势。文档智能负责解析和结构化文档内容,RAG则利用这些数据提供准确的问答服务。部署过程中,清晰的步骤指导和详细的文档帮助快速解决问题。方案适用于企业知识库、客户支持系统等场景,但在处理大文档和复杂格式时需进一步优化。
Nyx
64 0
|
3月前
LangChain-05 RAG Conversational 增强检索会话
LangChain-05 RAG Conversational 增强检索会话
39 2