基于LangChain 实现 Advanced RAG-后检索优化(下)-上下文压缩与过滤

摘要

        Advanced RAG 的后检索优化,是指在检索环节完成后、最终响应生成前,通过一系列策略与技术对检索结果进行深度处理,旨在显著提升生成内容的相关性与质量。在这些优化手段中,上文压缩与过滤技术是提升检索结果质量的重要手段。它能巧妙筛除冗余、无关信息,萃取关键内容,为后续处理奠定优质基础。本文将聚焦上文压缩与过滤技术展开深入探究,并依托功能强大的 LangChain 框架,具体阐释相关策略的实现路径,助力深入理解与应用这一关键技术。

上下文压缩原理说明

  • 多元检索:利用各类基础检索器,如基于关键词匹配的传统检索器、向量检索器等。这些检索器从不同数据源(如文档库、知识库等)获取与问题相关的信息。比如在一个企业知识问答场景中,向量检索器可从企业内部文档向量数据库中找出语义相关的文档片段,关键词检索器则可定位包含特定业务术语的资料。

  • 信息汇聚:将从不同检索器获取到的信息整合到文档压缩器中。此时,收集到的信息可能包含大量冗余、不相关或重复的内容。例如,多个检索器可能返回关于同一主题但表述略有差异的段落。

  • 精准过滤提取:文档压缩器运用多种技术对输入信息进行处理。一方面,通过文本分类、关键词提取等方法判断信息与问题的相关性,剔除明显无关的内容;另一方面,利用摘要算法,如抽取式摘要或生成式摘要技术,提炼出关键信息。比如对于一个关于 “如何优化电商网站用户体验” 的问题,压缩器会过滤掉电商运营中物流配送等无关信息,提取页面布局优化、交互设计等相关内容。

        通过这一系列步骤,RAG 系统能够为后续的生成模型提供精炼、有效的上下文信息,助力生成更准确、有用的回答。

LLMChainExtractor 文档压缩

        LLMChainExtractor 借助大语言模型(LLM)的理解和生成能力,对检索到的文本进行分析。它能识别文本中的关键信息片段,依据语言逻辑和语义关联,将重要内容提取出来。它能深入理解文本语义,提取出具有较高价值的信息,适用于各种复杂文本结构的处理。

代码示例

from langchain.document_loaders import TextLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.embeddings import HuggingFaceEmbeddings
from langchain.vectorstores import Chroma
from langchain.chat_models import ChatOpenAI
from langchain.prompts import PromptTemplate
from langchain.chains.llm import LLMChain
from langchain.retrievers.document_compressors import LLMChainExtractor
from langchain.retrievers import ContextualCompressionRetriever# 加载文档
loader = TextLoader('example.txt', encoding='utf-8')
docs = loader.load()# 分割文档
text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=100)
chunks = text_splitter.split_documents(docs)# 创建向量存储
embeddings = HuggingFaceEmbeddings()
vectorstore = Chroma.from_documents(documents=chunks, embedding=embeddings)# 初始化 LLM
llm = ChatOpenAI(temperature=0)# 创建 LLMChain
llm_chain = LLMChain(llm=llm)# 创建 LLMChainExtractor
compressor = LLMChainExtractor(llm_chain=llm_chain)# 创建基础检索器
base_retriever = vectorstore.as_retriever()# 创建 ContextualCompressionRetriever
compression_retriever = ContextualCompressionRetriever(base_compressor=compressor,base_retriever=base_retriever
)# 定义查询
query = "文档中提到的关键要点有哪些?"# 执行检索
results = compression_retriever.get_relevant_documents(query)# 打印结果
for doc in results:print(doc.page_content)
  • LLMChainExtractor:使用 LLMChainExtractor 作为文档压缩器,它将使用 LLMChain 从检索到的文档中提取相关信息。我们的代码中并未定义prompt,所以LLMChainExtractor 将使用默认的prompt 结构,在langchain.retrievers.document_compressors.chain_extract_prompt中定义。我们也可将默认提示词作为参考,自定义文本压缩提示词,默认prompt 如下所示:

# flake8: noqa
prompt_template = """Given the following question and context, extract any part of the context *AS IS* that is relevant to answer the question. If none of the context is relevant return {no_output_str}. Remember, *DO NOT* edit the extracted parts of the context.> Question: {{question}}
> Context:
>>>
{{context}}
>>>
Extracted relevant parts:"""
  • ContextualCompressionRetriever:是 LangChain 框架中用于文档检索的工具,主要功能是在检索文档时对结果进行上下文相关的压缩,以提高检索效率和质量。通过ContextualCompressionRetriever我们可以配置不同的检索器与压缩器,最终在检索时实现文档压缩提取的效果。

LLMChainFilter 文档过滤

   LLMChainFilter是 LangChain 中用于过滤文档的工具,它基于 LLMChain 的结果对文档进行筛选,只有符合特定条件的文档才会被保留。

  • LLMChainFilter利用LLMChain来处理文档。LLMChain由一个语言模型(LLM)和一个提示模板(PromptTemplate)组成。用户提供一个提示模板,其中包含文档内容和一些特定的问题或条件。LLMChain将文档内容填充到提示模板中,并调用语言模型生成回答。

  • 生成的回答会被用于判断文档是否通过过滤。可以根据回答的内容、结构或其他特征来定义过滤条件。例如,可以设置条件为当语言模型生成的回答中包含特定关键词时,文档通过过滤;或者当回答满足某种语义理解,如对某个问题的回答为肯定时,文档通过过滤。

代码示例

from langchain.document_loaders import TextLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.embeddings import HuggingFaceEmbeddings
from langchain.vectorstores import Chroma
from langchain.chat_models import ChatOpenAI
from langchain.prompts import PromptTemplate
from langchain.chains.llm import LLMChain
from langchain.retrievers.document_compressors import LLMChainExtractor
from langchain.retrievers import ContextualCompressionRetriever
from langchain.retrievers.document_compressors import LLMChainFilter# 加载文档
loader = TextLoader('example.txt', encoding='utf-8')
docs = loader.load()# 分割文档
text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=100)
chunks = text_splitter.split_documents(docs)# 创建向量存储
embeddings = HuggingFaceEmbeddings()
vectorstore = Chroma.from_documents(documents=chunks, embedding=embeddings)# 初始化 LLM
llm = ChatOpenAI(temperature=0)# 创建用于过滤的 LLMChain
filter_llm_chain = LLMChain(llm=llm)# 创建 LLMChainFilter
filter = LLMChainFilter(llm_chain=filter_llm_chain)# 定义查询
query = "文档中提到的关键技术有哪些?"# 执行检索
docs = retriever.get_relevant_documents(query)# 执行过滤
filtered_docs = filter.compress_documents(docs, query=query)# 打印结果
for doc in filtered_docs:print(doc.page_content)
  • LLMChainFilter:我们使用LLMChainFilter 结合LLM进行文本过滤,用户可以自定义过滤提示词,也可使用LangChain 框架在langchain.retrievers.document_compressors.chain_filter_prompt 中提供的默认提示词,或作为参考:

# flake8: noqa
prompt_template = """Given the following question and context, return YES if the context is relevant to the question and NO if it isn't.> Question: {question}
> Context:
>>>
{context}
>>>
> Relevant (YES / NO):"""

EmbeddingsFilter 向量相似度过滤

   EmbeddingsFilter使用预训练的词嵌入模型或句子嵌入模型,将文本转换为低维向量空间中的向量表示。通过计算这些向量之间的相似度,来判断文本之间的相关性或相似性,进而根据设定的阈值对文本进行过滤。

  • 优势

    • 高效性:基于向量空间的计算,能够快速计算文本之间的相似度,相比基于文本内容的直接比较,大大提高了过滤的效率,尤其适用于处理大规模文本数据。

    • 语义理解能力:预训练的嵌入模型能够捕捉文本的语义信息,因此EmbeddingsFilter可以从语义层面判断文本的相关性,而不仅仅是基于表面的词汇匹配,从而提高过滤的准确性。

  • 局限

    • 依赖预训练模型:其性能高度依赖于所使用的预训练嵌入模型的质量和适用性。如果模型不能很好地捕捉文本的语义和句法信息,或者与具体应用场景不匹配,可能会导致过滤效果不佳。

    • 缺乏领域适应性:对于一些特定领域的文本,可能需要针对该领域进行专门的模型训练或调整,否则可能无法准确理解领域特定的术语和概念,影响过滤的准确性。

    • 难以处理复杂语义关系:虽然能够捕捉一定的语义信息,但对于一些复杂的语义关系和上下文依赖的文本理解,可能存在局限性,无法像人类一样全面、准确地理解文本的含义。

代码示例

from langchain.retrievers.document_compressors import EmbeddingsFilter'''对检索到的文档块与查询进行相似度计算,如果相似度大于0.66,则保留该文档块,否则过滤掉'''
embeddings_filter = EmbeddingsFilter(embeddings=embeddings_model, similarity_threshold=0.66)compression_retriever = ContextualCompressionRetriever(base_compressor=embeddings_filter, base_retriever=retriever
)compressed_docs = compression_retriever.invoke("deepseek的发展历程"
)
print("-------------------EmbeddingsFilter压缩后--------------------------")
pretty_print_docs(compressed_docs)

EmbeddingsRedundantFilter 冗余文档过滤

  EmbeddingsRedundantFilter是一种基于嵌入向量的过滤器,用于识别和过滤文本数据中的冗余信息。EmbeddingsRedundantFilter通过计算文本向量之间的相似度来判断文本是否冗余。常用的相似度计算方法包括余弦相似度、欧式距离等。如果两个文本的向量相似度超过了设定的阈值,就认为它们是冗余的,其中一个文本可能会被过滤掉。

  • 优势

    • 语义层面的过滤:与基于简单字符串匹配或词频统计的过滤方法不同,EmbeddingsRedundantFilter基于文本的嵌入向量进行计算,能够从语义层面理解文本的相似性,更准确地识别真正的冗余信息,即使文本的表述方式有所不同。

    • 高效性:借助现代的向量计算库和优化算法,计算文本向量相似度的过程可以高效地进行,能够处理大规模的文本数据,满足实时性要求较高的应用场景。

  • 局限

    • 阈值设定的主观性:确定文本是否冗余的相似度阈值通常需要人工设定,这在一定程度上具有主观性。不同的应用场景和数据特点可能需要不同的阈值,不合适的阈值可能导致过滤效果不佳,要么过滤掉过多有用信息,要么保留了过多冗余信息。

    • 对嵌入模型的依赖:其性能高度依赖于所使用的嵌入模型的质量和适用性。如果嵌入模型不能很好地捕捉文本的语义和句法信息,或者与具体应用领域的文本特点不匹配,可能会导致对文本相似性的判断不准确,进而影响冗余过滤的效果。

    • 无法处理复杂语义关系:尽管嵌入模型能够捕捉一定的语义信息,但对于一些复杂的语义关系和上下文依赖的文本理解,仍然存在局限性。例如,对于具有隐喻、反讽等修辞手法的文本,或者在特定领域中具有特殊含义的术语,可能无法准确判断其与其他文本的冗余关系。

代码示例

from langchain.retrievers.document_compressors import DocumentCompressorPipeline
from langchain_community.document_transformers import EmbeddingsRedundantFilter# 默认文档间相似度超过0.95则为冗余文档
redundant_filter = EmbeddingsRedundantFilter(embeddings=embeddings_model, similarity_threshold=0.95)# 根据问题与文档的相似度过滤
relevant_filter = EmbeddingsFilter(embeddings=embeddings_model, similarity_threshold=0.66)# Transformers转换器 与 compressor压缩器结合
'''
1、通过EmbeddingsRedundantFilter过滤冗余文档
2、通过EmbeddingsFilter过滤与问题相似度低于0.66的文档
'''
pipeline_compressor = DocumentCompressorPipeline(transformers=[redundant_filter, relevant_filter]
)compression_retriever = ContextualCompressionRetriever(base_compressor=pipeline_compressor, base_retriever=retriever
)compressed_docs = compression_retriever.invoke("deepseek的发展历程"
)print("-------------------DocumentCompressorPipeline压缩后--------------------------")
pretty_print_docs(compressed_docs)
  • EmbeddingsRedundantFilter:创建冗余文档过滤器。它使用 embeddings_model 将文档转换为向量表示,并通过计算向量间的相似度来判断文档是否冗余。similarity_threshold=0.95 表示当两个文档向量的相似度超过 0.95 时,就认为这两个文档是冗余的,其中一个文档会被过滤掉。

  • EmbeddingsFilter:向量过滤器。同样使用 embeddings_model 将文档和查询问题转换为向量表示。similarity_threshold=0.66 表示只有当文档向量与查询问题向量的相似度超过 0.66 时,该文档才会被保留,否则会被过滤掉。

  • DocumentCompressorPipeline :文档压缩管道。将 redundant_filter 和 relevant_filter 组合成一个处理管道。在处理文档时,会先使用 redundant_filter 过滤掉冗余文档,再使用 relevant_filter 过滤掉与查询问题相似度低于 0.66 的文档。

总结

压缩器说明
LLMChainExtractor通过 LLM 根据用户查询提取检索的文档内容。
LLMChainFilter通过 LLM 根据用户查询过滤检索的文档
EmbeddingsFilter通过向量模型根据用户查询计算文档与问题相似度,过滤低于指定阈值的文档
EmbeddingsRedundantFilter通过向量模型根据用户查询计算检索文档之间的相似度,过滤高于阈值的文档

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/79281.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

为什么 Vite 速度比 Webpack 快?

一、webpack会先进行编译,再运行,vite会直接启动,再按需编译文件。 首先看两张图,可以清晰的看到,上面的图是webpack编译过的,而下面的图是vite直接使用工程内文件。 二、区别于Webpack先打包的方式&am…

C# 操作符

C# 操作符 一、操作符概览二、优先级与运算顺序三、各类操作符的实例 一、操作符概览 操作符(运算符)的本质是函数的简记法 操作符不能脱离与它关联的数据类型 int x 5; int y 4; int z x / y; Console.WriteLine(z);//输出1double a 5.0; double b…

C++设计模式:面向对象的八大设计原则之四

里氏替换原则(Liskov Substitution Principle,LSP)是面向对象设计中的一个重要原则,它指出子类必须能够替换它的基类,并且程序的行为不会发生改变。也就是说,在任何使用基类对象的地方,都可以透…

网络通信领域的基础或流行协议

一、TCP(传输控制协议) 1. 宏观介绍 TCP:全称“Transmission Control Protocol”——传输控制协议,是互联网最基础的传输协议之一。传输层协议,提供面向连接、可靠的字节流传输服务。它通过三次握手建立连接、四次挥手断开连接,确保数据有序、完整地传输作用:让两个设备…

【教学类-34-10】20250503(通义万相)4*3蝴蝶拼图(圆形、三角、正方、半圆的凹凸小块+参考图灰色)

背景需求 2023年从网站上搜索拼图代码,陆续改良了圆形、三角形、菱形凹凸) 【教学类-34-05】20230425拼图(“圆角”凹凸拼图)3*4格子(中班主题《个别化拼图》偏美术)_拼图的槽叫什么形状-CSDN博客文章浏览阅读1.1k次。【教学类-34-05】20230425拼图(“圆角”凹凸拼图)…

bellard.org‌ : QuickJS 如何使用 qjs 执行 js 脚本

参阅上一篇:Fabrice Bellard(个人网站:‌bellard.org‌)介绍 Fabrice Bellard(个人网站:‌bellard.org‌)是计算机领域最具影响力的程序员之一,其贡献跨越多个技术领域并持续推动开…

数据结构---

案例一 1.随机生成n个工人工时,100以内,工号分别为2021101到2021100n 2.以工时数为关键字分别使用选择排序、冒泡排序、插入排序进行升序排序。 3.把排序后的结果输出,包括工号工时数 4.比较三种算法对相同的n值数组排序所花的时间 代码如下&…

Python硬核革命:从微控制器到FPGA的深度开发指南

1. 重新定义硬件开发:Python的颠覆性突破 传统硬件开发长期被C/C++和Verilog/VHDL统治,但Python正通过两条路径改变这一格局: 1.1 微控制器领域的MicroPython革命 完整Python 3.4语法支持,运行在资源受限的MCU上(最低要求:64KB ROM,16KB RAM) 直接内存访问能力,突破…

基于springboot+vue的宠物共享平台

开发语言:Java框架:springbootJDK版本:JDK1.8服务器:tomcat7数据库:mysql 5.7数据库工具:Navicat12开发软件:eclipse/myeclipse/ideaMaven包:Maven3.3.9 系统展示 宠物寄养管理 宠…

day 11 超参数调整

一、内参与外参(超参数) 内参是模型为了适应训练数据而自动调整的,是模型内部与训练数据紧密相关的因素,不同的训练数据会导致模型学习到不同的参数值,这些参数在模型训练完成后就固定下来。 超参数是在模型训练前需…

快速搭建对象存储服务 - Minio,并解决临时地址暴露ip、短链接请求改变浏览器地址等问题

其他文章 服务容错治理框架resilience4j&sentinel基础应用---微服务的限流/熔断/降级解决方案-CSDN博客 conda管理python环境-CSDN博客 快速搭建对象存储服务 - Minio,并解决临时地址暴露ip、短链接请求改变浏览器地址等问题-CSDN博客 大模型LLMs的MCP入门-…

朴素贝叶斯分类器

朴素贝叶斯分类器 朴素贝叶斯是一种基于密度估计的分类算法,它利用贝叶斯定理进行预测。该算法的核心假设是在给定类别的情况下,各个特征之间是条件独立的,尽管这一假设在现实中通常不成立,但朴素贝叶斯分类器依然能够生成对有偏…

在 Trae CN IDE 中配置 Python 3.11的指南

在 Trae CN IDE 中配置 Python 3.11的指南 下载 python 3.11 安装 Python 3.11 首先,我们需要确保安装了 Python 3.11。可以从Python 官方网站下载适合你操作系统的版本。 链接 如果你已经安装了 Python 3.11,可以通过以下命令确认: 文…

MQTT 协议与 HTTP 协议的区别

在现代的网络通信中,MQTT 协议和 HTTP 协议都扮演着重要的角色,但它们有着不同的特点和适用场景。下面我们就从多个方面来详细探讨它们之间的区别。 一.协议设计理念 1. MQTT 协议 MQTT(Message Queuing Telemetry Transport)即…

Postgresql源码(145)优化器nestloop参数化路径评估不准问题分析

相关 《Postgresql源码(133)优化器动态规划生成连接路径的实例分析》 1 问题 最近遇到一个问题,评估行数和真实行数存在较大差距,导致计划不准的问题。 nestloop内表评估是根据外表的参数来的。因为外表驱动表每取一条&#xff…

HTML与CSS实现风车旋转图形的代码技术详解

在前端开发中,HTML和CSS是构建网页的基础技术。通过巧妙运用HTML的结构搭建和CSS的样式控制,我们能够实现各种精美的视觉效果。本文将对一段实现旋转图形效果的HTML和CSS代码进行详细解读,剖析其中的技术要点。 一、运行效果 HTML与CSS实现风…

linux下,ollama会把模型文件保存在哪里?

文章目录 运行ollama,有两种形式,估计得分开讨论首先是使用自动启动的ollama:先跑个“小一点的大模型”但是现在模型文件存在哪儿呢?运行ollama,有两种形式,估计得分开讨论 我们用两种方式,来运行ollama。 首先是使用自动启动的ollama: ps -aux | grep ollama系统自…

鼎讯信通 智能通信干扰设备:多频段多模态信号压制解决方案

在万物互联时代,通信安全已成为现代社会的核心基础设施防护重点。面对日益复杂的电磁环境挑战,新一代智能通信干扰设备通过技术创新实现了信号压制能力的革命性突破。本文将深入解析该设备的八大核心功能与技术特性,展现其在商业通信保障、工…

【2025软考高级架构师】——案例分析总结(13)

摘要 本文对2025年软考高级架构师的考纲及案例分析进行了总结。内容涵盖系统规划、架构设计、系统建模、安全架构、可靠性分析、大数据架构等多方面知识点,还涉及软件质量特性、系统流程图与数据流图、嵌入式系统架构、分布式系统设计等考查内容,详细列…

js单调栈解题模板

模板 function solve(arr) {const stack [];const result new Array(arr.length).fill(默认值);for (let i 0; i < arr.length; i) {while (stack.length && 比较条件(arr[i], arr[栈顶])) {const top stack.pop();result[top] 计算结果(i, top); }stack.push…