链载Ai

标题: RAG效果不好怎么办?试试这八大解决方案(含代码) [打印本页]

作者: 链载Ai    时间: 6 小时前
标题: RAG效果不好怎么办?试试这八大解决方案(含代码)
随着自然语言处理(NLP)技术的飞速发展,构建高效的信息检索系统已成为许多企业和开发者的重要需求。LangChain 是一个强大的框架,旨在帮助开发者快速构建和优化基于大型语言模型(LLM)的应用程序。其中检索器是 LangChain 提供的一个核心接口,它可以根据用户的非结构化查询返回相关的文档。每种检索器都有其独特的应用场景和优势,本文将详细介绍 LangChain 中的几种检索器及其应用场景和解决方案,并提供相应的代码示例,帮助开发者将这些技术应用到实际的业务场景中。


一、向量存储检索器

向量检索器是一种基于向量空间模型的检索器,它通过计算查询和文档之间的相似度来实现检索。每个文档和查询都会通过嵌入模型(如 OpenAI Embedding)转换为向量表示,然后通过计算向量之间的相似度(如余弦相似度)来判断文档与查询的相关性。
假设你是一家电商平台的开发者,负责开发一个商品搜索功能,帮助用户快速找到相关商品。你可以使用向量存储检索器来实现这一功能,通过计算商品描述与用户查询之间的相似度,精准返回相关的商品信息。

1.1、解决方案

1.2、工作原理

1.3、处理流程

  1. 文本预处理:对输入的文本进行清洗和标准化处理。

  2. 生成嵌入:使用嵌入模型将文本转换为高维向量。

  3. 存储嵌入:将生成的嵌入存储在向量数据库中,每个嵌入对应一个文档。

  4. 查询处理:用户输入查询文本后,同样使用嵌入模型将其转换为查询向量。

  5. 相似度搜索:在向量数据库中查找与查询向量最相似的嵌入,并返回对应的文档。

1.4、应用场景

1.5、示例代码:

from langchain.vectorstores import FAISSfrom langchain.embeddings import OpenAIEmbeddingsfrom langchain.schema import Document
# 初始化嵌入模型embeddings = OpenAIEmbeddings()
# 创建商品列表(模拟文档)products = [Document(page_content="这款智能手机拥有强大的处理器和高清摄像头。"),Document(page_content="这款笔记本电脑轻薄便携,适合商务旅行。"),Document(page_content="这款智能手表支持健康监测和消息提醒。")]
# 创建向量存储vectorstore = FAISS.from_documents(products, embeddings)
# 查询向量存储query = "最好的智能手机"results = vectorstore.similarity_search(query, k=2)
# 打印结果for doc in results:print(doc.page_content)

二、父文档检索器

父文档检索器是一种基于文档层级关系的检索器,它通过检索“父文档”来帮助获取相关信息。通常,在文档库中存在多个“子文档”(如不同部分或不同章节),而父文档则是它们的整体描述或汇总。父文档检索器的核心思想是通过识别父文档,从而获得与其相关的子文档或详细信息。
假设你是一家律师事务所的开发人员,负责开发一个法律文档检索系统,帮助客户快速找到相关的法律条款和案例。在这种情况下,父文档检索器可以帮助你从大规模的法律文档中提取出完整的案例或条款内容,保证返回的信息不会丢失上下文。

2.1、解决方案

2.2、工作原理

2.3、处理流程

  1. 文档分割:将长文档分割成多个段落,每个段落作为一个独立的文档单元。

  2. 生成嵌入:使用嵌入模型将每个段落转换为嵌入。

  3. 存储嵌入和元数据:将嵌入及其所属的父文档ID存储在向量数据库中。

  4. 查询处理:用户输入查询文本后,使用嵌入模型将其转换为查询向量。

  5. 相似度搜索:在向量数据库中查找与查询向量最相似的嵌入,并返回对应的父文档。

2.4、应用场景

2.5、示例代码

from langchain.vectorstores import FAISSfrom langchain.embeddings import OpenAIEmbeddingsfrom langchain.schema import Documentfrom langchain.retrievers import ParentDocumentRetriever
# 初始化嵌入模型embeddings = OpenAIEmbeddings()
# 创建法律文档列表(模拟文档)legal_documents = [Document(page_content="《公司法》第5条规定了公司设立的条件。", metadata={"parent_doc_id": "doc1"}),Document(page_content="《公司法》第10条规定了公司董事会的职能。", metadata={"parent_doc_id": "doc1"})]
# 创建向量存储vectorstore = FAISS.from_documents(legal_documents, embeddings)
# 创建父文档检索器retriever = ParentDocumentRetriever(vectorstore=vectorstore, docstore=vectorstore.docstore)
# 查询父文档检索器query = "公司法的设立条件"results = retriever.get_relevant_documents(query)
# 打印结果for doc in results:print(doc.page_content)

三、多向量检索器

多向量检索器通过对多个文档的内容进行聚合,从中提取出最具代表性的信息。这种检索器常用于从大量信息中综合和总结出最关键信息。
假设你是金融分析师,正在分析一份公司年度财报。报告中包含了多种类型的信息,如财务数据、公司战略、市场分析等。多向量检索器可以帮助你在检索过程中对不同类型的信息进行分类和加权,从而精准地提取出与你查询最相关的信息。

3.1、解决方案

3.2、工作原理

3.3、处理流程

  1. 多嵌入生成:为每个文档生成多个嵌入,每个嵌入代表文档的一个方面(如摘要、关键词等)。

  2. 存储嵌入和元数据:将生成的嵌入及其对应的文档信息存储在向量数据库中。

  3. 查询处理:用户输入查询文本后,使用嵌入模型将其转换为查询向量。

  4. 相似度搜索:在向量数据库中查找与查询向量最相似的嵌入,并返回对应的文档。

3.4、应用场景

3.5、示例代码

from langchain.vectorstores import FAISSfrom langchain.embeddings import OpenAIEmbeddingsfrom langchain.schema import Documentfrom langchain.retrievers import MultiVectorRetriever
# 初始化嵌入模型embeddings = OpenAIEmbeddings()
# 创建财务报告文档列表(模拟文档)reports = [Document(page_content="公司2022年净收入达到5亿,市场份额稳步增长。", metadata={"category": "financial"}),Document(page_content="2022年公司战略重点是拓展海外市场。", metadata={"category": "strategy"})]
# 创建向量存储vectorstore = FAISS.from_documents(reports, embeddings)
# 创建多向量检索器retriever = MultiVectorRetriever(vectorstore=vectorstore)
# 查询多向量检索器query = "2022年财务报告"results = retriever.get_relevant_documents(query)
# 打印结果for doc in results:print(doc.page_content)

四、自查询检索器

自查询检索器是一种通过自动生成和执行查询来检索相关文档的智能检索器。不同于传统的通过用户输入查询来检索文档的方式,自查询检索器通过预设规则、模型生成或分析文档内容,自动生成一个查询,并通过该查询检索相关文档。这使得检索过程更加自动化和智能化,适用于需要根据文档内容生成查询条件的场景。
假设你正在开发一个社交媒体监控系统,需要根据不同的元数据(如发布日期、作者等)对用户提交的查询进行处理。自查询检索器可以帮助你解析用户的自然语言查询,并根据查询的元数据筛选相关内容。

4.1、解决方案

4.2、工作原理

4.3、处理流程

  1. 查询构造:用户输入自然语言查询,使用语言模型将其转化为具体的检索条件。

  2. 条件生成:生成的检索条件包括要搜索的文本内容和元数据过滤规则。

  3. 存储嵌入和元数据:将文档及其元数据存储在向量数据库中。

  4. 相似度搜索:根据生成的检索条件在向量数据库中查找符合条件的文档。

4.4、应用场景

4.5、示例代码

from langchain.retrievers.self_query import SelfQueryRetrieverfrom langchain.vectorstores import FAISSfrom langchain.embeddings import OpenAIEmbeddingsfrom langchain.chains.query_constructor.base import StructuredQueryOutputParser, get_query_constructor_promptfrom langchain.llms import OpenAI
# 初始化嵌入模型和语言模型embeddings = OpenAIEmbeddings()llm = OpenAI()
# 创建文档列表(模拟文档)documents = [Document(page_content="作者:张三,发布于2022年1月,内容是关于金融的研究。", metadata={"author": "张三", "date": "2022-01-01"}),Document(page_content="作者:李四,发布于2022年3月,内容是关于税务的报告。", metadata={"author": "李四", "date": "2022-03-01"})]
# 创建向量存储vectorstore = FAISS.from_documents(documents, embeddings)
# 创建自查询检索器retriever = SelfQueryRetriever(vectorstore=vectorstore,llm=llm,output_parser=StructuredQueryOutputParser(query_constructor_prompt=get_query_constructor_prompt()))
# 查询自查询检索器query = "关于税务的报告,李四作者"results = retriever.get_relevant_documents(query)
# 打印结果for doc in results:print(doc.page_content)


五、关键词匹配检索器(上下文压缩)

基于上下文的检索器在检索过程中,考虑到查询和文档的上下文关系,不仅仅依据关键词或向量相似度。它通过捕捉上下文信息来提高检索的准确性和相关性。
假设你是一个内容网站的开发者,需要为用户提供一个快速的新闻检索功能。用户可以通过输入一个关键词,快速找到与该关键词相关的新闻文章。关键词匹配检索器可以高效地根据查询词找到相关的内容,而不需要复杂的模型推理。

5.1、解决方案

5.2、工作原理

5.3、处理流程

  1. 初步检索:使用常规的向量存储检索器获取初步的检索结果。

  2. 文档压缩:在初步检索结果中进一步筛选,确保只保留最相关的部分。

  3. 相似度计算:使用嵌入模型计算文档片段的相似度,去除无关信息。

  4. 最终结果:返回经过压缩后的最相关文档片段。

5.4、应用场景

5.5、示例代码:

from langchain.vectorstores import FAISSfrom langchain.embeddings import OpenAIEmbeddingsfrom langchain.schema import Documentfrom langchain.retrievers import KeywordMatcherRetriever
# 初始化嵌入模型embeddings = OpenAIEmbeddings()
# 创建新闻文档列表(模拟文档)news_articles = [Document(page_content="近日,全球股市下跌,原因是各国经济放缓。", metadata={"category": "finance"}),Document(page_content="科技行业迎来突破性发展,人工智能成为焦点。", metadata={"category": "technology"})]
# 创建向量存储vectorstore = FAISS.from_documents(news_articles, embeddings)
# 创建关键词匹配检索器retriever = KeywordMatcherRetriever(vectorstore=vectorstore)
# 查询关键词匹配检索器query = "股市"results = retriever.get_relevant_documents(query)
# 打印结果for doc in results:print(doc.page_content)


六、基于规则的检索器(例如时间加权)

基于规则的检索器通过用户定义的规则对文档进行筛选。规则可以基于文档的元数据或内容特征,如特定的字段值或内容匹配条件。适用于业务逻辑较为简单、规则明确的检索场景。
假设你是一个法务团队的开发者,正在开发一个合同审查系统。这个系统需要通过设定规则(如合同金额、签约方等),快速筛选出符合要求的合同条款。基于规则的检索器可以帮助你在大量合同中筛选出符合特定规则的文档,并进行自动化审查。

6.1、解决方案

6.2、工作原理

6.3、处理流程

  1. 时间权重:为每个文档分配一个时间戳,并根据时间戳计算权重。

  2. 生成嵌入:使用嵌入模型将文档转换为嵌入。

  3. 存储嵌入和时间戳:将生成的嵌入及其时间戳存储在向量数据库中。

  4. 查询处理:用户输入查询文本后,使用嵌入模型将其转换为查询向量。

  5. 相似度搜索:在加权的向量数据库中查找与查询向量最相似的嵌入,并返回对应的文档。

6.4、应用场景

6.5、示例代码

from langchain.vectorstores import FAISSfrom langchain.embeddings import OpenAIEmbeddingsfrom langchain.schema import Documentfrom langchain.retrievers import RuleBasedRetriever
# 初始化嵌入模型embeddings = OpenAIEmbeddings()
# 创建合同文档列表(模拟文档)contracts = [Document(page_content="合同1:金额100万,签约方甲方是公司A。", metadata={"contract_value": "100万", "party": "公司A"}),Document(page_content="合同2:金额50万,签约方甲方是公司B。", metadata={"contract_value": "50万", "party": "公司B"})]
# 创建向量存储vectorstore = FAISS.from_documents(contracts, embeddings)
# 定义筛选规则:金额大于等于100万,甲方是公司Adef filter_rule(doc):return doc.metadata['contract_value'] == "100万" and doc.metadata['party'] == "公司A"
# 创建基于规则的检索器retriever = RuleBasedRetriever(vectorstore=vectorstore, filter_func=filter_rule)
# 查询基于规则的检索器query = "金额100万,甲方公司A"results = retriever.get_relevant_documents(query)
# 打印结果for doc in results:print(doc.page_content)

七、层级检索器

层级检索器是对文档的内容进行分层结构化管理的检索器。它通过对文档进行分类和组织,能够根据不同层级进行检索。例如,可以按项目阶段、文档类型等不同维度进行检索。
假设你是一家建筑公司的项目经理,负责一个大型工程项目的管理。你需要检索项目的不同阶段文档(如设计阶段、施工阶段等)。层级检索器可以帮助你通过设置层级关系,将项目分为不同的阶段,并根据阶段进行精准的文档检索。

7.1、解决方案

7.2、工作原理

7.3、处理流程

  1. 子查询生成:从用户的初始查询出发,使用语言模型生成多个相关的子查询。

  2. 多检索:分别使用每个子查询在向量存储中进行检索。

  3. 结果综合:综合所有子查询的结果,根据相似度评分返回最相关的文档。

7.4、应用场景

7.5、示例代码

from langchain.vectorstores import FAISSfrom langchain.embeddings import OpenAIEmbeddingsfrom langchain.schema import Documentfrom langchain.retrievers import HierarchicalRetriever
# 初始化嵌入模型embeddings = OpenAIEmbeddings()
# 创建项目阶段文档列表(模拟文档)project_documents = [Document(page_content="设计阶段文档:项目规划和设计图纸。", metadata={"phase": "设计"}),Document(page_content="施工阶段文档:施工进度报告。", metadata={"phase": "施工"})]
# 创建向量存储vectorstore = FAISS.from_documents(project_documents, embeddings)
# 创建层级检索器retriever = HierarchicalRetriever(vectorstore=vectorstore, hierarchy_field="phase")
# 查询层级检索器query = "设计阶段文档"results = retriever.get_relevant_documents(query)
# 打印结果for doc in results:print(doc.page_content)

八、基于图谱的检索器(集成检索器)

图谱检索器使用图谱数据结构来进行信息检索。文档与文档之间、文档与查询之间的关系通过图的结构来表示。通过图的连接,检索器可以高效地发现和利用文档之间的相关性。

假设你在开发一个医学信息检索系统,用户可以根据症状或疾病查询相关的药物和治疗方法。通过构建一个包含疾病、症状和药物之间关系的图谱,你可以使用图谱检索器来快速定位相关的医学信息,并给出精确的查询结果。

8.1、解决方案

8.2、工作原理

8.3、处理流程

  1. 多检索器组合:结合多个检索器的优点,如向量存储检索器、父文档检索器等。

  2. 多策略检索:可以同时使用关键词匹配和语义相似度等多种策略。

  3. 结果综合:根据查询文本,从多个检索器中获取结果,并综合所有结果,返回最相关的文档。

8.4、应用场景

8.5、示例代码

from langchain.vectorstores import FAISSfrom langchain.embeddings import OpenAIEmbeddingsfrom langchain.schema import Documentfrom langchain.retrievers import GraphRetriever
# 初始化嵌入模型embeddings = OpenAIEmbeddings()
# 创建医学知识文档列表(模拟文档)medical_knowledge = [Document(page_content="心脏病的常见症状包括胸痛、呼吸急促。", metadata={"disease": "心脏病", "symptoms": "胸痛, 呼吸急促"}),Document(page_content="高血压的治疗方法包括改变饮食和药物治疗。", metadata={"disease": "高血压", "treatment": "饮食调整, 药物治疗"})]
# 创建向量存储vectorstore = FAISS.from_documents(medical_knowledge, embeddings)
# 创建图谱检索器retriever = GraphRetriever(vectorstore=vectorstore, graph_structure={"disease": "treatment"})
# 查询图谱检索器query = "高血压的治疗方法"results = retriever.get_relevant_documents(query)
# 打印结果for doc in results:print(doc.page_content)

九、总结

通过本文介绍的八种 LangChain 检索器,您可以根据具体的业务需求和场景,选择最合适的检索方式来构建高效的信息检索系统。无论是简单的关键词匹配,还是复杂的图谱关系检索,LangChain 都提供了强大而灵活的工具,帮助开发者更好地解决业务中常见的信息检索问题。希望通过这些实例和代码,您能够更好地理解并应用这些检索器,在实际项目中提高工作效率并优化业务流程。






欢迎光临 链载Ai (https://www.lianzai.com/) Powered by Discuz! X3.5