LangChain入门2 RAG详解

RAG概述

一个典型的RAG应用程序,它有两个主要组件:

  • 索引:从源中获取数据并对其进行索引的管道。这通常在脱机情况下发生。
  • 检索和生成:在运行时接受用户查询,并从索引中检索相关数据,然后将其传递给模型。

从原始数据到答案的完整序列如下所示:

索引

  • 加载:首先我们需要加载我们的数据。我们将为此使用DocumentLoaders。
  • 拆分:文本拆分器将大型文档拆分成更小的块。这对于索引数据和将数据传递给模型都很有用,因为大块更难搜索,也不适合模型的有限上下文窗口。
  • 信息存储:我们需要一个地方来存储和索引我们的拆分,以便以后可以搜索它们。这通常使用VectorStore和Embeddings模型来完成。

检索和生成

  • 检索:给定用户输入,使用Retriever从存储中检索相关拆分。
  • 生成:ChatModel/LLM使用包含问题和检索到的数据的提示生成答案。

代码实例

依赖加载

from langchain_community.llms import Ollama
import bs4
from langchain import hub
from langchain_community.document_loaders import WebBaseLoader
from langchain_chroma import Chroma
from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables import RunnablePassthrough
from langchain_community.embeddings import OllamaEmbeddings
from langchain_text_splitters import RecursiveCharacterTextSplitter
#实例化大模型
llm = Ollama(model="llama2")
#添加向量化
embeddings = OllamaEmbeddings()
# 加载数据
loader = WebBaseLoader(web_paths=("https://lilianweng.github.io/posts/2023-06-23-agent/",),bs_kwargs=dict(parse_only=bs4.SoupStrainer(class_=("post-content", "post-title", "post-header"))),
)
docs = loader.load()
#我们这里查看具体的下载内容
print(docs)

查看具体的下载内容
在这里插入图片描述
加载数据的拆分和灌库

#添加数据的拆分 每1000个为一组并重叠200个字符
text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
#拆分下载的数据
splits = text_splitter.split_documents(docs)
#灌入向量数据库
vectorstore = Chroma.from_documents(documents=splits, embedding=embeddings)

构建检索生成

retriever = vectorstore.as_retriever()
#下载预制的提示词
prompt = hub.pull("rlm/rag-prompt")#调整文本
def format_docs(docs):return "\n\n".join(doc.page_content for doc in docs)

加载数据链

#RunnablePassthrough是Langchain库中的一个类,它允许您传递未更改的输入或带有附加键的输入。
#它可以与RunnableParallel一起使用,将数据传递到映射中的新键。它还可以用于通过assign()方法向链状态添加值
rag_chain = ({"context": retriever | format_docs, "question": RunnablePassthrough()} #检索加强| prompt #提示词| llm #大模型| StrOutputParser() #输出结果样式定义
)
#进行对话
rag_chain.invoke("What is Task Decomposition?")

返回内容
在这里插入图片描述

详细说明

首先加载博客文章的内容。我们可以为此使用DocumentLoaders,它们是从源加载数据并返回文档列表的对象。Document是一个具有一些page_content(str)和元数据(dict)的对象。

在这种情况下,我们将使用WebBaseLoader,它使用urllib从web URL加载HTML,并使用BeautifulSoup将其解析为文本。我们可以通过bs_kwargs将参数传递给BeautifulSoup解析器来自定义HTML->文本解析(请参阅Beautiful Soup文档)。在这种情况下,只有类为“post-content”、“posttitle”或“post-header”的HTML标记是相关的,所以我们将删除所有其他标记。

数据加载

import bs4
from langchain_community.document_loaders import WebBaseLoader# Only keep post title, headers, and content from the full HTML.
bs4_strainer = bs4.SoupStrainer(class_=("post-title", "post-header", "post-content"))
loader = WebBaseLoader(web_paths=("https://lilianweng.github.io/posts/2023-06-23-agent/",),bs_kwargs={"parse_only": bs4_strainer},
)
docs = loader.load()
print(docs)

在这里插入图片描述

print(len(docs[0].page_content))
#43131
print(docs[0].page_content[:500])
"""LLM Powered Autonomous AgentsDate: June 23, 2023  |  Estimated Reading Time: 31 min  |  Author: Lilian WengBuilding agents with LLM (large language model) as its core controller is a cool concept. Several proof-of-concepts demos, such as AutoGPT, GPT-Engineer and BabyAGI, serve as inspiring examples. The potentiality of LLM extends beyond generating well-written copies, stories, essays and programs; it can be framed as a powerful general problem solver.
Agent System Overview#
In
"""

文本拆分

from langchain_text_splitters import RecursiveCharacterTextSplittertext_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200, add_start_index=True
)
all_splits = text_splitter.split_documents(docs)

RecursiveCharacterTextSplitter 通过递归地查看字符来拆分文本。 递归地尝试按不同的字符进行拆分,以找到一个有效的字符。 创建一个新的TextSplitter。

print(len(all_splits))
#66
print(len(all_splits[0].page_content))
#969
print(all_splits[10].metadata)
#{'source': 'https://lilianweng.github.io/posts/2023-06-23-agent/',
#'start_index': 7056}

索引:存储

现在我们需要对66个文本块进行索引,以便在运行时对它们进行搜索。最常见的方法是嵌入每个文档分割的内容,并将这些嵌入插入到矢量数据库(或矢量存储)中。当我们想搜索分割时,我们采用文本搜索查询,嵌入它,并执行某种“相似性”搜索,以识别嵌入与查询嵌入最相似的存储分割。最简单的相似性度量是余弦相似性——我们测量每对嵌入(它们是高维向量)之间的角度的余弦。
我们可以使用Chroma矢量存储和OpenAIEmbeddings模型将所有文档分割嵌入并存储在一个命令中。

from langchain_chroma import Chroma
from langchain_community.embeddings import OllamaEmbeddings
#添加向量化
embeddings = OllamaEmbeddings()
#灌库
vectorstore = Chroma.from_documents(documents=all_splits, embedding=embeddings)

检索与生成:检索

现在让我们来编写实际的应用程序逻辑。我们想要创建一个简单的应用程序,该应用程序接受用户问题,搜索与该问题相关的文档,将检索到的文档和初始问题传递给模型,并返回答案。

首先,我们需要定义搜索文档的逻辑。LangChain定义了一个Retriever接口,该接口封装了一个索引,该索引可以在给定字符串查询的情况下返回相关文档。

最常见的Retriever类型是VectorStoreRetriever,它使用向量存储的相似性搜索功能来促进检索。使用VectorStore.as_Retriever(),任何VectorStore都可以很容易地转换为Retriever:

"""
矢量存储是用于有效存储和查询矢量嵌入的数据结构,矢量嵌入是数据点的高维数值表示。向量存储通常用于机器学习应用程序中的任务,如相似性搜索、异常检测和聚类。
在Langchain的上下文中,VectorStore类是用于处理向量存储的接口。它提供了添加和查询矢量的方法,以及执行各种操作的方法,例如计算矢量之间的距离和根据某些标准过滤矢量。
"""
retriever = vectorstore.as_retriever(search_type="similarity", search_kwargs={"k": 6})
retrieved_docs = retriever.invoke("What are the approaches to Task Decomposition?")
print(len(retrieved_docs))
#6
print(retrieved_docs[0].page_content)

在这里插入图片描述

检索与生成

from langchain import hub
#加载的提示词
prompt = hub.pull("rlm/rag-prompt")example_messages = prompt.invoke({"context": "filler context", "question": "filler question"}
).to_messages()
print(example_messages)

返回

[HumanMessage(content=“You are an assistant for question-answering tasks. Use the following pieces of retrieved context to answer the question. If you don’t know the answer, just say that you don’t know. Use three sentences maximum and keep the answer concise.\nQuestion: filler question \nContext: filler context \nAnswer:”)]

print(example_messages[0].content)

You are an assistant for question-answering tasks. Use the following pieces of retrieved context to answer the question. If you don’t know the answer, just say that you don’t know. Use three sentences maximum and keep the answer concise.
Question: filler question
Context: filler context

LCEL

我们将使用LCEL Runnable协议来定义链,使我们能够以透明的方式将组件和函数管道连接在一起,在LangSmith中自动跟踪我们的链,从而获得流式、异步和批量调用

from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables import RunnablePassthroughdef format_docs(docs):return "\n\n".join(doc.page_content for doc in docs)rag_chain = ({"context": retriever | format_docs, "question": RunnablePassthrough()}| prompt| llm| StrOutputParser()
)
for chunk in rag_chain.stream("What is Task Decomposition?"):print(chunk, end="", flush=True)

在这里插入图片描述

模型选择

#构建提示词模版
from langchain_core.prompts import PromptTemplate
#提示词
template = """Use the following pieces of context to answer the question at the end.
If you don't know the answer, just say that you don't know, don't try to make up an answer.
Use three sentences maximum and keep the answer as concise as possible.
Always say "thanks for asking!" at the end of the answer.{context}Question: {question}Helpful Answer:"""
#模版加载
custom_rag_prompt = PromptTemplate.from_template(template)rag_chain = ({"context": retriever | format_docs, "question": RunnablePassthrough()}| custom_rag_prompt| llm| StrOutputParser()
)
#结果输出
rag_chain.invoke("What is Task Decomposition?")

在这里插入图片描述
以上是整体使用LangChain 构建RAG 的总体流程。
感谢阅读。

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

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

相关文章

机器学习:深入解析SVM的核心概念【一、间隔与支持向量】

直接阅读原始论文可能有点难和复杂,所以导师直接推荐我阅读周志华的《西瓜书》!!然后仔细阅读其中的第六章:支持向量机 间隔与支持向量 **问题一:什么叫法向量?为什么是叫法向量**什么是法向量?…

ChatGPT向付费用户推“记忆”功能,可记住用户喜好 | 最新快讯

4月30日消息,人工智能巨头OpenAI宣布,其开发的聊天机器人ChatGPT将在除欧洲和韩国以外的市场全面上线“记忆”功能。这使得聊天机器人能够“记住”ChatGPT Plus付费订阅用户的详细信息,从而提供更个性化的服务。 OpenAI早在今年2月就已经宣布…

AJAX家政系统 自营+多商家(高级授权)+独立端口 -源码下载

应用介绍 后台:https://service.hnajax.com/hxeJVakAdf.php/index/login AJAX家政系统 自营多商家(高级授权)独立端口 基于FastAdmin和原生微信小程序开发的一款同城预约、上门服务、到店核销家政系统,用户端、服务端(高级授权)、门店端(高级授权)各端…

HTML:认识HTML及基本语法

目录 1. HTML介绍 2. 关于软件选择和安装 3. HTML的基本语法 1. HTML介绍 HyperText Markup Language 简称HTML,意为:超文本标记语言 超文本:是指页面内可以包含的图片,链接,声音,视频等内容 标记&am…

76、堆-数据流的中位数

思路: 这个问题是动态数据流中位数查找问题。在数据流中,数据是逐个到来的,而我们需要在任何时候快速返回已有数据的中位数。中位数是将数据集分成两个等长的子集,一个包含所有较小的元素而另一个包含所有较大的元素。 为了高效解…

升级 Vite 5 出现警告 The CJS build of Vite‘s Node API is deprecated

错误描述 vue3-element-admin 项目将Vite4 升级至 Vite5 后,项目运行出现如下警告: The CJS build of Vites Node API is deprecated. See https://vitejs.dev/guide/troubleshooting.html#vite-cjs-node-api-deprecated for more details.图片 问题原因 Vite 官方弃用 C…

WIN10 anaconda 安装 CondaError: Run ‘conda init‘ before ‘conda activate‘

1 下载 https://www.anaconda.com/download/success 2 安装 3 修改环境变量 安装后修改环境变量 4 winrun 进入命令窗口 输入cmd 输入 conda info 5 创建 虚拟环境 conda create -n yolov8 python3.8 -y 6 CondaError: Run ‘conda init’ before ‘conda activate’ c…

在Primavera P6 中维护自定义活动栏

前言 自从 Henry Gantt 在 1910 年左右提出这个想法以来,以图形方式显示项目进度表并沿时间刻度显示条形图一直延续到当今最复杂和流行的项目进度系统中。在本文中,我们将仔细研究 Primavera P6 Professional 中的甘特图,并探索一些自定义其…

【新知实验室 - TRTC 实践】音视频互动 Demo、即时通信 IM 服务搭建

一、TRTC 初识 TRTC 是什么 TRTC(Tencent RTC)腾讯实时音视频,源自于 QQ 音视频团队,是基于 QQ 音视频多年来的音视频技术积累,位于腾讯云的 RTC 云服务。TRTC 支持腾讯会议、企业微信直播、微信视频号、腾讯云课堂、…

一个类实现Mybatis的SQL热更新

引言 平时用SpringBootMybatis开发项目,如果项目比较大启动时间很长的话,每次修改Mybatis在Xml中的SQL就需要重启一次。假设项目重启一次需要5分钟,那修改10次SQL就过去了一个小时,成本有点太高了。关键是每次修改完代码之后再重…

FineBI学习:K线图

效果图 底表结构:日期、股票代码、股票名称、开盘价、收盘价、最高价、最低价 步骤: 横轴:日期 纵轴:开盘价、最低价 选择【自定义图表】,或【瀑布图】 新建字段:价差(收盘-开盘&#xf…

POETIZE个人博客系统源码 | 最美博客

源码介绍 POETIZE个人博客系统源码 | 最美博客 这是一个 SpringBoot Vue2 Vue3 的产物,支持移动端自适应,配有完备的前台和后台管理功能。 网站分两个模块: 博客系统:具有文章,表白墙,图片墙&#xf…

CSS 伪类、伪元素的应用实例:电池充电、高能进度条

一、目的 本文通过 CSS 伪类、伪元素,结合动画 animation 和 Vue 动态样式属性(通过 CSS 变量)的写法,来实现电池充电、高能进度条的效果,如下图所示。 二、基础知识 1、CSS 伪类、伪元素 简单概括成以下 4 点&#x…

谷粒商城实战(020 RabbitMQ-消息确认)

Java项目《谷粒商城》架构师级Java项目实战,对标阿里P6-P7,全网最强 总时长 104:45:00 共408P 此文章包含第258p-第p261的内容 消息确认 生产者 publishers 消费者 consumers 设置配置类 调用api 控制台 抵达brocker 代理 新版本ReturnCallbac…

DevEco Studio mac版启动不了【鸿蒙开发Bug已解决】

文章目录 项目场景:问题描述原因分析:解决方案:此Bug解决方案总结Bug解决方案寄语项目场景: 最近也是遇到了这个问题,看到网上也有人在询问这个问题,本文总结了自己和其他人的解决经验,解决了【DevEco Studio mac版启动不了】的问题。 问题描述 报错如下。 -------…

如何判断第三方软件测试公司是否具有资质

在软件开发的过程中,软件测试是确保软件质量、稳定性和用户体验的关键环节。许多企业选择将软件测试工作交给专业的第三方软件测试公司来完成,以确保测试的准确性和公正性。但是,如何判断一个第三方软件测试公司是否具有资质呢?以…

Python urllib 爬虫入门(2)

本文为Python urllib类库爬虫更入门的一些操作和爬虫实例及源码。 目录 模拟浏览器请求 简单模拟 设置随机user-agent 请求超时 HTTP请求类型 Get请求 Post请求 抓取网页动态请求 封装ajax请求 调用 循环调用 抓取小说 封装请求函数 把html写入本地分析 调用 正…

2024年Docker常用操作快速查询手册

目录 一、Linux系统上 Docker安装流程(以ubuntu为例) 一、卸载所有冲突的软件包 二、设置Docker的apt存储库(这里使用的是阿里云软件源) 三、直接安装最新版本的Docker 三、安装指定版本的Docker 四、验证Docker是否安装成功…

Linux 手动部署JDK21 环境

1、下载包(我下载的是tar) https://www.oracle.com/cn/java/technologies/downloads/#java21 完成后进行上传 2、检查已有JDK,并删除(我原有是jdk8) rpm -qa | grep -i java | xargs -n1 rpm -e --nodeps3、清理掉 profile中的j…

Mybatis-Plus扩展接口InnerInterceptor

InnerInterceptor 接口就是 MyBatis-Plus 提供的一个拦截器接口,用于实现一些常用的 SQL 处理逻辑,处理 MyBatis-Plus 的特定功能,例如PaginationInnerInterceptor、OptimisticLockerInnerInterceptor 等,都实现了 InnerInterceptor 接口,并添…