RAG检索中使用一个 长上下文重排序器(Long Context Reorder) 对检索到的文档进行进一步的处理和排序,优化输出顺序

news/2025/2/23 5:24:40

使用一个长上下文重排序器对检索到的文档进行进一步的处理和排序,优化输出顺序。
优化前的检索内容,顺序混乱:
在这里插入图片描述

优化后的检索内容,按顺序排列:
在这里插入图片描述
使用 LongContextReorder 对检索得到的文档进行重新排序。这一步的目的是在有较长上下文时,优化文档的顺序,使得后续生成回答或处理时能更好地利用整体信息,而不是单纯按照检索的相关性顺序。

示例代码如下:

python">from langchain_community.vectorstores import Chroma
from langchain_community.document_transformers import (
    LongContextReorder,
)
from langchain_community.embeddings import HuggingFaceEmbeddings

# Load blog
import bs4
from langchain_community.document_loaders import WebBaseLoader

# 设置一个常见的浏览器 User-Agent 字符串
os.environ["USER_AGENT"] = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36"

loader = WebBaseLoader(
    web_paths=("https://www.yixue.com/%E6%80%8E%E6%A0%B7%E7%9C%8B%E8%A1%80%E5%B8%B8%E8%A7%84%E5%8C%96%E9%AA%8C%E5%8D%95",),
    bs_kwargs=dict(
        parse_only=bs4.SoupStrainer(
            class_=("mw-body-content")
        )
    ),
)

blog_docs = loader.load()

# Split
from langchain.text_splitter import RecursiveCharacterTextSplitter
text_splitter = RecursiveCharacterTextSplitter.from_tiktoken_encoder(
    chunk_size=300, 
    chunk_overlap=50)

# Make splits
splits = text_splitter.split_documents(blog_docs)

# Get embeddings.
embeddings = HuggingFaceEmbeddings(model_name="all-MiniLM-L6-v2")

# Create a retriever
retriever = Chroma.from_documents(splits, embedding=embeddings).as_retriever(
    search_kwargs={"k": 10}
)
question = "血红蛋白(Hb)测定人体正常范围是多少?"

# Get relevant documents ordered by relevance score
docs = retriever.invoke(query)


reordering = LongContextReorder()
reordered_docs = reordering.transform_documents(docs)

下面我来详细解释这段代码的作用和每个部分的含义,并用通俗的语言和例子说明。


1. 背景和总体思路

整体流程包括:

  • 加载网页内容:从指定的 URL 下载博客页面。
  • 文本拆分:将加载的长文档拆分成更小的片段,便于后续处理。
  • 生成嵌入向量:利用预训练的语言模型将每个文本片段转换为数值向量,表示其语义信息。
  • 构建向量数据库:把所有文本片段的嵌入向量存储在向量数据库(这里使用 Chroma)中,以便快速检索。
  • 检索相关文档:根据用户的查询(例如“什么是任务分解”)从向量数据库中找出最相关的文本片段。
  • 文档重排序:使用一个长上下文重排序器对检索到的文档进行进一步的处理和排序,优化输出顺序。

2. 代码详细解释

a. 导入所需的模块
python">from langchain_community.vectorstores import Chroma
from langchain_community.document_transformers import LongContextReorder
from langchain_community.embeddings import HuggingFaceEmbeddings

这些导入模块提供了:

  • Chroma:一个向量数据库,用于存储和检索文本嵌入。
  • LongContextReorder:用于重新排序文档,使得在长文本处理时能够更好地利用上下文。
  • HuggingFaceEmbeddings:利用 HuggingFace 提供的预训练模型生成文本的嵌入向量。
b. 加载网页内容
python">import bs4
from langchain_community.document_loaders import WebBaseLoader

# 设置 User-Agent,模拟常见浏览器
os.environ["USER_AGENT"] = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36"

loader = WebBaseLoader(
    web_paths=("https://www.yixue.com/%E6%80%8E%E6%A0%B7%E7%9C%8B%E8%A1%80%E5%B8%B8%E8%A7%84%E5%8C%96%E9%AA%8C%E5%8D%95",),
    bs_kwargs=dict(
        parse_only=bs4.SoupStrainer(
            class_=("mw-body-content")
        )
    ),
)
blog_docs = loader.load()

这里使用 WebBaseLoader 来加载一个博客页面,传入了目标 URL。使用 BeautifulSoup 的 SoupStrainer 只解析页面中类名为 "mw-body-content" 的部分(这样可以过滤掉无关内容,只保留主要文章内容)。设置 User-Agent 主要是为了让网站认为这是来自真实浏览器的请求,防止被屏蔽。

举例说明:假设你要加载一篇博客文章,但网页中有大量广告、侧边栏等噪音信息。利用 SoupStrainer 只选取文章主要内容,能保证后续处理的文本质量更高。

c. 文本拆分
python">from langchain.text_splitter import RecursiveCharacterTextSplitter
text_splitter = RecursiveCharacterTextSplitter.from_tiktoken_encoder(
    chunk_size=300, 
    chunk_overlap=50)
splits = text_splitter.split_documents(blog_docs)

这里的作用是将加载到的长文档拆分成多个较小的文本块:

  • chunk_size=300:每个块大约300个字符(或token)。
  • chunk_overlap=50:相邻文本块之间有50个字符的重叠,确保上下文连贯,不会因为拆分而丢失关键信息。

举例说明:如果一篇文章有3000个字符,拆分后可能生成大约10个文本块,每个块之间有一部分内容重复,这样在检索时就能更好地捕捉到上下文信息。

d. 生成文本嵌入
python">embeddings = HuggingFaceEmbeddings(model_name="all-MiniLM-L6-v2")

使用 HuggingFace 提供的预训练模型 “all-MiniLM-L6-v2” 将每个文本块转换为一个高维向量,这个向量代表了文本的语义信息,便于后续比较文本之间的相似度。

举例说明:假设有两个文本块分别描述“如何进行任务分解”和“任务分解的步骤”,经过嵌入后,这两个文本的向量在空间中距离较近,因为它们主题相似。

e. 构建向量数据库和检索器
python">retriever = Chroma.from_documents(splits, embedding=embeddings).as_retriever(
    search_kwargs={"k": 10}
)
question = "血红蛋白(Hb)测定人体正常范围是多少?"
docs = retriever.invoke(query)
  • Chroma.from_documents:将之前拆分的文本块和生成的嵌入存储到一个 Chroma 向量数据库中。
  • as_retriever(search_kwargs={“k”: 10}):构造一个检索器,设置查询时返回最相关的10个文本块。
  • retriever.invoke(query):根据输入的查询“什么是任务分解”检索出相关的文本块。

举例说明:当用户查询“血红蛋白(Hb)测定人体正常范围是多少”时,系统会自动搜索数据库中与该查询最匹配的文本块,并返回这10个最相关的内容。这样用户能快速得到与问题高度相关的答案片段。

f. 文档重排序
python">reordering = LongContextReorder()
reordered_docs = reordering.transform_documents(docs)

最后使用 LongContextReorder 对检索得到的文档进行重新排序。这一步的目的是在有较长上下文时,优化文档的顺序,使得后续生成回答或处理时能更好地利用整体信息,而不是单纯按照检索的相关性顺序。

举例说明:假如检索出来的10个文本块中有些虽然相关但顺序零散(可看前面给的输出效果对比图),通过重排序可以把那些逻辑连续、信息衔接紧密的片段放在一起,形成更连贯的答案。


总结

整段代码展示了如何从一个网页中加载内容,经过文本拆分、生成嵌入向量,再通过向量数据库进行语义检索,最后对检索结果进行重排序,最终实现一个高效的文档问答系统。

  • 加载网页:提取文章核心内容。
  • 拆分文本:避免单一长文本处理困难,保证上下文完整。
  • 生成嵌入:将文本转换为能量化语义的向量。
  • 向量检索:根据查询找出最相关的文本片段。
  • 重排序:优化片段顺序,形成连贯的回答。

这种方法在知识问答、搜索引擎、文档摘要等应用场景中非常实用。通过将长文档拆分和向量化,可以快速准确地找到用户所需的信息。


http://www.niftyadmin.cn/n/5862982.html

相关文章

ThinkORM模型静态方法create好像对MongoDB不支持

软件版本 think-orm&#xff1a;3.0PHP&#xff1a;8.4.1MongoDB&#xff1a;8.0.4 &#xff08;本地单数据 非集群&#xff09;注&#xff1a;我是在 webman 框架下使用think-orm&#xff0c;并非在 thinkphp框架下使用 使用场景 定义的模型如下&#xff1a; <?php na…

嵌入式硬件篇---数字电子技术中的时序逻辑

文章目录 前言简介1. 关键延迟时间的定义与作用(1) 传输延迟&#xff08;Propagation Delay&#xff09;定义作用示例 (2) 时钟到输出延迟&#xff08;Clock-to-Q Delay, Tcq&#xff09;定义作用示例 (3) 建立时间&#xff08;Setup Time, Tsetup&#xff09;定义作用示例 (4)…

k8s集群内的pod连接集群外部的mysql, k8s集群内部服务如何连接集群外部mysql? 一文搞明白

一、为什么不将mysql服务部署到k8s集群中使用呢&#xff1f; 1.有状态服务在K8s中的管理比较复杂&#xff0c;特别是持久化存储的问题。虽然K8s有StatefulSet和PV/PVC&#xff0c;但配置和维护起来需要更多工作,同时以下问题仍需解决&#xff1a;-存储可靠性&#xff1a;如果使…

Docker国内镜像源部署deepseek

‌部署deepseek时Docker拉取国内镜像失败可能是由于国内网络环境复杂或镜像源配置不正确导致的‌。 具体原因可能包括&#xff1a; ‌网络问题‌&#xff1a;国内网络环境复杂&#xff0c;可能导致访问国内镜像仓库的速度较慢或无法访问&#xff0c;进而影响Docker镜像的拉取…

RTSP场景下的RTP与RTCP

一、RTP 数据包格式&#xff08;RFC 3550 Section 5.1&#xff09; 1. RTP 头部结构 0 1 2 30 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 -------------------------------- |V2|P|X| CC |M|…

微信小程序数据绑定与事件处理:打造动态交互体验

在上一篇中&#xff0c;我们学习了如何搭建微信小程序的开发环境并创建了一个简单的“Hello World”页面。然而&#xff0c;一个真正的小程序不仅仅是静态内容的展示&#xff0c;它需要与用户进行动态交互。本文将深入探讨微信小程序中的数据绑定和事件处理机制&#xff0c;通过…

为Eclipse IDE安装插件IBM编程助手watsonx Code Assistant

从Eclipse IDE 安装 从Eclipse IDE 安装插件&#xff1a; _1、在Eclipse IDE 中&#xff0c;单击帮助菜单&#xff0c;然后选择EclipseMarketplace。 _2、根据您计划进行的工作类型选择安装方式&#xff1a; 有关代码建议、代码解释、代码文档和单元测试的集成生成式人工智能&a…

金融学-金融机构

前言 金融机构在金融体系运行体系运营中起着不可获缺的关键作用.如规则的制定与监管-中央银行,体系的运营证券公司,体系的供贷的参与者金融中介.本章将用一种说明我们的金融体系是怎样改进经济效率的经济分析,来讲述相关金融机构 金融结构的经济学分析 世界各国的金融体系在…