LLM之RAG实战(十三)| 利用MongoDB矢量搜索实现RAG高级检索

       想象一下,你是一名侦探,身处庞大的信息世界,试图在堆积如山的数据中找到隐藏的一条重要线索,这就是检索增强生成(RAG)发挥作用的地方,它就像你在人工智能和语言模型世界中的可靠助手。但即使是最好的助理也有其局限性,因此,让我们开始探索RAG的高级方法,重点关注大规模文档检索中的精度和上下文。

一、基本RAG

       想象一下,有一本和地平线一样宽百科全书。基本的RAG试图将这些丰富的知识提炼成一个单一的“嵌入”——本质上是一个数字。但是,当你在一个特定的主题上寻求智慧时,比如神秘的百慕大三角,基本的RAG的粗笔画会覆盖更多细节,给你留下一幅不完整的画面。这种限制就像试图用一张只显示大陆的地图来寻找隐藏的宝藏,而不是通往标有“X”的地点的复杂路径。

       另一方面,如果我们只拥有带有嵌入的单个页面,我们可能会找出具体的事实,但当它们交织在一起时,我们就会失去它们所讲述的故事。如果没有叙事,大型语言模型(LLM)很难找到一个能抓住我们探究的真正本质的答案。

       基本RAG,虽然是一个值得称赞的里程碑,但没有做的更好。基本RAG只是一个基础,需要跨越通用知识和精确见解之间的距离,我们需要做更细致的优化工作。

二、路径的细化:父子文档关系

       我们不是对整个百科全书进行单一的总结,而是为每一页(子文档)进行简洁的概述,注意包含的章节(父文档)。该方法在我之前的LLM之RAG实战(五)| 高级RAG 01:使用小块检索,小块所属的大块喂给LLM,可以提高RAG性能博客中有所介绍,这里略过。

2.1 步骤1:父子文档关系

       想象一下,你有一本又大又笨重的书——一本关于所有电器的用户手册。现在,有人问了一个特定的问题:“为什么我的洗衣机显示错误代码2?”,对于基本的RAG,我们要么得到缺乏上下文的小块,要么得到搜索不够准确的大块。然而,高级RAG采用了更聪明的方法。

       首先,手册被分解成大块——这些是我们的“父”文档。每一节都涉及更大的信息。在这些部分中,我们拆分了涵盖特定问题的“子”文档,如洗衣机的错误代码。

       现在,来看看矢量化的魔力。每个子文档都通过嵌入模型进行处理,该模型分析文本并将其转换为向量——一系列表示文本本质的数字。这就像为每一小段信息创建一个DNA图谱。

       每个子文档的文本都被提取到一个向量中,然后将其存储在向量存储中,其父文档也存储在这个向量存储中——这也是一个通用数据库。这使我们不仅可以快速检索最相关的小信息,还可以保留父文档提供的上下文。

2.2 步骤二:问答

       当关于洗衣机的问题出现时,它就变成了一个“嵌入”——把它想象成一个独特的数字签名。然后使用矢量搜索将这些嵌入与类似的子文档进行匹配。如果它与“洗衣机”部分的子文档嵌入紧密对齐,我们就找到了匹配项。

       有了我们的矢量存储和准备,当出现问题时,我们可以迅速找到最相关的子文档。但是,我们没有提供狭义的回应,而是引入了母文档,它提供了更多的背景和上下文。这个准备好的提示富含特定信息和广泛的上下文,然后被输入到大型语言模型(LLM)中,该模型生成精确的上下文感知答案。

       如图所示,这种先进的RAG过程确保LLM具有生成准确响应所需的所有上下文,就像侦探拼凑线索来解开谜团一样。借助MongoDB矢量搜索的强大功能,我们可以以超级计算机的速度和精度浏览这一过程,确保每个问题都得到尽可能好的答案。

三、MongoDB矢量搜索:高级RAG背后的动力

       从父子关系和矢量化的复杂关系中走出来,我们直接进入了MongoDB的矢量搜索领域,该引擎为我们的高级RAG过程提供了动力。让我们深入研究一下MongoDB矢量搜索是如何将筛选堆积如山的数据这一艰巨任务转变为一个精简高效的过程的。

3.1 矢量搜索:快速寻找答案

       MongoDB中的矢量搜索就像在浩瀚的数据海洋中拥有一盏高功率探照灯。当我们的洗衣机爱好者询问那个令人讨厌的错误代码时,矢量搜索不仅仅是梳理数据,它还可以精确定位信息的确切位置,这要归功于我们早些时候创建的独特的“数字签名”。最棒的部分?它以惊人的速度做到了这一点,使得搜索答案的速度就像翻阅一个组织良好的文件柜一样快。

3.2 结构与速度想结合

       MongoDB的矢量搜索将结构和速度和谐地结合在一起。父文档和子文档的存储,以及它们的矢量化本质,使MongoDB能够快速识别最相关的数据片段,而不会被不太相关的信息所困扰。这是一位一丝不苟的图书管理员和一位侦探大师的完美结合,确保了没有遗漏任何线索,每个答案都切中要害。

3.3 语境丰富性:增加的层次

       在这里,事情变得更加有趣。一旦矢量搜索精确定位了相关的子文档,它就不会止步于此。通过检索父文档,它确保了上下文的丰富性不会丢失。这意味着我们的LLM不仅了解“什么”,还了解“为什么”和“如何”,提供了超出表面水平的答案。

3.4 MongoDB:不仅仅是一个数据库

       MongoDB不仅仅是一个存储数据的地方;这是一个动态的生态系统,支持先进的RAG过程的每一步。它可以轻松管理复杂的父文档和子文档网络,并促进快速矢量搜索,使高级RAG功能强大。使用MongoDB,我们不仅仅是在寻找答案;我们正在制定既能提供信息又能与上下文相关的回应。

3.5 结果:知情、准确的回答

       由于高级RAG和MongoDB矢量搜索之间的强大协作,生成的响应不仅准确,而且信息丰富。当我们的用户询问洗衣机上的错误代码时,他们会收到一个既准确又充满有用上下文的回复,类似于为他们量身定制的全面指南。

       MongoDB矢量搜索是这一高级RAG过程的支柱,提供了在复杂的数据检索环境中导航所需的速度和精度。在下一节中,我们将探索这一过程的实际实施,展示如何将先进的RAG系统应用到生活中,为用户提供人工智能所能提供的最佳答案。请继续关注我们将理论转化为实践,并充分发挥先进RAG的潜力。

四、用MongoDB矢量搜索实现高级RAG

      将Advanced RAG与MongoDB Vector Search集成到我们的系统中,首先是几个技术组件的和数据处理流程。下面看一下具体步骤:

4.1 步骤1:设置和初始化

       我们通过设置环境和建立必要的联系来启动工作,这包括加载环境变量,初始化OpenAI和MongoDB客户端,以及定义我们的数据库和集合名称。

import osfrom dotenv import load_dotenvfrom pymongo import MongoClientfrom langchain.embeddings import OpenAIEmbeddings# Load environment variables from .env fileload_dotenv(override=True)# Set up MongoDB connection detailsOPENAI_API_KEY = os.environ["OPENAI_API_KEY"]MONGO_URI = os.environ["MONGO_URI"]DB_NAME = "pdfchatbot"COLLECTION_NAME = "advancedRAGParentChild"# Initialize OpenAIEmbeddings with the API keyembeddings = OpenAIEmbeddings(openai_api_key=OPENAI_API_KEY)# Connect to MongoDBclient = MongoClient(MONGO_URI)db = client[DB_NAME]collection = db[COLLECTION_NAME]

4.2 步骤2:数据加载和分块

       接下来,我们将重点处理作为数据源的PDF文档。文档被加载并拆分为“父”和“子”块,以准备嵌入和向量化。

from langchain.document_loaders import PyPDFLoaderfrom langchain.text_splitter import RecursiveCharacterTextSplitter# Initialize the text splitters for parent and child documentsparent_splitter = RecursiveCharacterTextSplitter(chunk_size=2000)child_splitter = RecursiveCharacterTextSplitter(chunk_size=200)# Function to process PDF document and split it into chunksdef process_pdf(file):    loader = PyPDFLoader(file.name)    docs = loader.load()    parent_docs = parent_splitter.split_documents(docs)        # Process parent documents    for parent_doc in parent_docs:        parent_doc_content = parent_doc.page_content.replace('\n', ' ')        parent_id = collection.insert_one({            'document_type': 'parent',            'content': parent_doc_content        }).inserted_id                # Process child documents        child_docs = child_splitter.split_documents([parent_doc])        for child_doc in child_docs:            child_doc_content = child_doc.page_content.replace('\n', ' ')            child_embedding = embeddings.embed_documents([child_doc_content])[0]            collection.insert_one({                'document_type': 'child',                'content': child_doc_content,                'embedding': child_embedding,                'parent_ref': parent_id            })    return "PDF processing complete"

4.3 步骤3:查询嵌入和矢量搜索

       当提交查询时,我们将其转换为嵌入,并执行向量搜索以找到最相关的子文档,链接回它们的父文档以获取上下文。

# Function to embed a query and perform a vector searchdef query_and_display(query):    query_embedding = embeddings.embed_documents([query])[0]        # Retrieve relevant child documents based on query    child_docs = collection.aggregate([{        "$vectorSearch": {            "index": "vector_index",            "path": "embedding",            "queryVector": query_embedding,            "numCandidates": 10        }    }])        # Fetch corresponding parent documents for additional context    parent_docs = [collection.find_one({"_id": doc['parent_ref']}) for doc in child_docs]    return parent_docs, child_docs

4.4 步骤4:通过上下文感知生成响应

       在识别出相关文档后,我们为LLM创建一个提示,其中包括用户的查询和匹配文档中的内容。这确保了响应具有信息性和上下文相关性。

from langchain.llms import OpenAI# Initialize the OpenAI clientopenai_client = OpenAI(api_key=OPENAI_API_KEY)# Function to generate a response from the LLMdef generate_response(query, parent_docs, child_docs):    response_content = " ".join([doc['content'] for doc in parent_docs if doc])    chat_completion = openai_client.chat.completions.create(        messages=[{"role": "user", "content": query}],        model="gpt-3.5-turbo"    )    return chat_completion.choices[0].message.content

4.5 第五步:串联所有组件

       最后,我们将这些元素组合成一个连贯的界面,用户可以在其中上传文档并提出问题。这是使用Gradio实现的,它提供了一种用户友好的方式来与我们先进的RAG系统交互。

with gr.Blocks(css=".gradio-container {background-color: AliceBlue}") as demo:    gr.Markdown("Generative AI Chatbot - Upload your file and Ask questions")    with gr.Tab("Upload PDF"):        with gr.Row():            pdf_input = gr.File()            pdf_output = gr.Textbox()        pdf_button = gr.Button("Upload PDF")    with gr.Tab("Ask question"):        question_input = gr.Textbox(label="Your Question")        answer_output = gr.Textbox(label="LLM Response and Retrieved Documents", interactive=False)        question_button = gr.Button("Ask")    question_button.click(query_and_display, inputs=[question_input], outputs=answer_output)    pdf_button.click(process_pdf, inputs=pdf_input, outputs=pdf_output)demo.launch()

4.6 步骤6:在MongoDB Atlas上创建索引

{  "fields": [    {      "numDimensions": 1536,      "path": "embedding",      "similarity": "cosine",      "type": "vector"    },    {      "path": "document_type",      "type": "filter"    }  ]}

参考文献:

[1] https://ai.gopubby.com/byebye-basic-rag-embracing-advanced-retrieval-with-mongodb-vector-search-47b550be2c59

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

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

相关文章

小心JDK20 ZipOutputStream

Oracle 團隊竟然這麽粗心,編譯JDK 20 時ZipOutputStream沒有編譯成功就發佈了。 所以這個20版本不可以使用ZipOutputStream。 GZIPInputStream 只能做最後的壓縮,不能添加多個附件ZipEntry。 下一個版本21不存在這個問題。 try(var zipOut new ZipOu…

数据分析——火车信息

任务目标 任务 1、整理火车发车信息数据,结果的表格形式为: 2、并输出最终的发车信息表 难点 1、多文件 一个文件夹,多个月的发车信息,一个excel,放一天的发车情况 2、数据表的格式特殊 如何分析表是一个难点 数…

案例102:基于微信小程序的旅游社交管理系统设计与实现

文末获取源码 开发语言:Java 框架:SSM JDK版本:JDK1.8 数据库:mysql 5.7 开发软件:eclipse/myeclipse/idea Maven包:Maven3.5.4 小程序框架:uniapp 小程序开发软件:HBuilder X 小程序…

解决VMware 虚拟机 ubuntu 20.04 异常关闭导致虚拟网卡 ens33 无法工作问题

问题描述 由于经常使用 SSH 远程链接 VMware 中的虚拟机 ubuntu,每次关闭都是挂起,时间久了,虚拟机运行有些卡顿了,此时可以通过 Linux 命令重启或者关闭 ubuntu,也可以之间使用 VMWare 中的【虚拟机】-- 【电源】-&g…

SiC电机控制器(逆变器)发展概况及技术方向

SiC电机控制器(逆变器)发展概况及技术方向 1.概述2.电动汽车动力系统设计趋势3.栅极驱动器和驱动电源配置4.结论 tips:资料来自网上搜集,仅供学习使用。 1.概述 2022年到2023年,第三代半导体碳化硅被推上了新的热潮。…

前端uniapp的tab选项卡for循环切换、开通VIP实战案例【带源码/最新】

目录 效果图图1图2 源码最后 这个案例是uniapp&#xff0c;同样也适用Vue项目&#xff0c;语法一样for循环&#xff0c;点击切换 效果图 图1 图2 源码 直接代码复制查看效果 <template><view class"my-helper-service-pass"><view class"tab…

第14课 利用openCV快速数豆豆

除了检测运动&#xff0c;openCV还能做许多有趣且实用的事情。其实openCV和FFmpeg一样都是宝藏开源项目&#xff0c;貌似简单的几行代码功能实现背后其实是复杂的算法在支撑。有志于深入学习的同学可以在入门后进一步研究算法的实现&#xff0c;一定会受益匪浅。 这节课&#…

(Python + Selenium4)Web自动化测试自学Day1

目录 文章声明⭐⭐⭐让我们开始今天的学习吧&#xff01;自动打开Chrome浏览器实现自动搜索元素定位常用的元素定位方式By.IDBy.CLASS_NAMEBy.TAG_NAMEBy.NAMEBy.LINK_TEXTBy.PARTIAL_LINK_TEXTBy.CSS_SELECTOR根据id定位根据class定位根据属性定位组合定位 By.XPATH 文章声明⭐…

#error 在C语言中的作用

1、#error命令是C/C语言的预处理命令之一 #error 是C语言中的预处理指令之一&#xff0c;用于在编译时生成一个错误消息。当编译器遇到 #error 指令时&#xff0c;会立即停止编译&#xff0c;并将指定的错误消息输出到编译器的错误信息中。 在给定的代码中&#xff0c;#error…

玩转Mysql 二(MySQL的目录结构与表结构)

一路走来,所有遇到的人,帮助过我的、伤害过我的都是朋友,没有一个是敌人。 一、MYSQL目录结构及命令存放路径 1、查看MYSQL数据文件存放路径 mysql> show variables like datadir; 注意:生成环境要提前规划好数据存放目录,存储一般以T为单位闪盘。 2、MYSQL命令存放…

Note: A Woman Doctor Lina

A woman doctor Lina 女医生丽娜 Born in a pigs’ nest, Lina led a poor life in her childhood. 出生在猪圈里&#xff0c;丽娜过着贫穷的童年生活。 led nest She was looked down upon by the children of her generation. 她被她同时代的孩子瞧不起。 generation look…

私有云平台搭建openstack和ceph结合搭建手册

OpenStack与云计算 什么是云&#xff1f; 如何正确理解云&#xff0c;可以从以下几个方面。 云的构成。 用户&#xff1a;对用户而言是透明无感知的&#xff0c;不用关心底层构成&#xff0c;只需要知道利用云完成自己任务即可。 云提供商&#xff1a;对云资产管理和运维。 云…

CentOS安装JDK

目录 一、文件准备 1、目录创建 2、导入jdk压缩文件 3、解压压缩包 二、配置 1.配置环境变量 2.使用source命令生效环境变量 3、测试 总结 一、文件准备 1、目录创建 在/usr/local下创建java 目录 2、导入jdk压缩文件 3、解压压缩包 tar -zxf jdk-8u201-linux-x64.t…

[C#]使用onnxruntime部署yolov8-onnx印章检测

【官方框架地址】 https://github.com/ultralytics/ultralytics.git 【算法介绍】 YOLOv8是目标检测领域中的一种先进算法&#xff0c;它是YOLO&#xff08;You Only Look Once&#xff09;系列算法的最新发展。YOLO算法以其高效和实时的性能而著名&#xff0c;而YOLOv8则进一…

计算机毕业设计----ssm大学生兼职论坛

项目介绍 该项目是一个大学生校园兼职平台&#xff0c;分为前台和后台功能&#xff0c;主要用户有三种角色&#xff1a;分别是商家、学生、管理员。商家可以发布兼职信息&#xff0c;发布后&#xff0c;管理员进入后台确认信息是否有效&#xff0c;并且审核该兼职信息。学生登…

gRPC - gRPC 整合 SpringBoot(全代码 + 避坑!)

目录 一、gRPC 整合 SpringBoot 1.1、创建项目 1.2、天坑&#xff08;看前须知&#xff09;&#xff01; 1.2.1、天坑背景 1.2.2、解决天坑 1.3、api 开发 1.4、server 开发 1.5、client 开发 1.6、演示效果 一、gRPC 整合 SpringBoot 1.1、创建项目 api&#xff1a;编…

关于图像分类任务中划分数据集,并且生成分类类别的josn字典文件

1. 前言 在做图像分类任务的时候&#xff0c;数据格式是文件夹格式&#xff0c;相同文件夹下存放同一类型的类别 不少网上的数据&#xff0c;没有划分数据集&#xff0c;虽然代码简单&#xff0c;每次重新编写还是颇为麻烦&#xff0c;这里记录一下 如下&#xff0c;有的数据…

大语言模型的幻觉:解析、成因及解决方法

目录 前言1 大语言模型的幻觉现象解析1.1 输入冲突幻觉&#xff08;Input-conflicting&#xff09;1.2 上下文冲突幻觉&#xff08;Context-conflicting&#xff09;1.3 事实冲突幻觉&#xff08;Fact-conflicting&#xff09; 2 幻觉产生的原因2.1 数据偏差和模型缺陷2.2 知识…

如何发布自己的golang库

如何发布自己的golang库 1、在 github/gitee 上创建一个 public 仓库&#xff0c;仓库名与 go 库名一致&#xff0c;然后将该仓库 clone 到本地。 本文这里使用 gitee。 $ git clone https://gitee.com/zsx242030/goutil.git2、进入项目文件夹&#xff0c;进行初始化。 $ go…

uniapp微信小程序投票系统实战 (SpringBoot2+vue3.2+element plus ) -后端鉴权拦截器实现

锋哥原创的uniapp微信小程序投票系统实战&#xff1a; uniapp微信小程序投票系统实战课程 (SpringBoot2vue3.2element plus ) ( 火爆连载更新中... )_哔哩哔哩_bilibiliuniapp微信小程序投票系统实战课程 (SpringBoot2vue3.2element plus ) ( 火爆连载更新中... )共计21条视频…