构建一个检索增强生成(RAG)应用程序

news2024/11/15 21:43:39

:::tips
此文档是LangChain官方教程的实践总结:
https://python.langchain.com/v0.2/docs/tutorials/rag/
实践前你需要准备:
OPENAI_API_KEY Generator:根据检索到的信息和用户的查询生成自然语言的回答。
LANGCHAIN_API_KEY 密切监控和评估您的应用程序,以便您可以快速、自信地开发。
py 环境准备(conda)。
:::

简介

我们将在网站上构建一个 QA 应用程序。我们将使用的具体网站是 Lilian Weng 的 LLM Powered Autonomous Agents 博客文章,该网站允许我们提出有关帖子内容的问题。

一步一步成功

数据收集

我们需要首先加载博客文章内容。为此,我们可以使用 DocumentLoaders,它们是从源加载数据并返回文档列表的对象。 Document 是一个带有一些 page_content (str) 和 metadata (dict) 的对象。
在本例中,我们将使用 WebBaseLoader,它使用 urllib 从 Web URL 加载 HTML,并使用 BeautifulSoup 将其解析为文本。我们可以通过 bs_kwargs 将参数传递给 BeautifulSoup 解析器来自定义 HTML -> 文本解析(请参阅 BeautifulSoup 文档)。在这种情况下,只有类为“post-content”、“post-title”或“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()

len(docs[0].page_content)
43131
print(docs[0].page_content[:500])
######

      LLM Powered Autonomous Agents
    
Date: June 23, 2023  |  Estimated Reading Time: 31 min  |  Author: Lilian Weng


Building 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

数据分块

我们加载的文档长度超过 42k 个字符。这太长了,无法适应许多模型的上下文窗口。即使对于那些可以在其上下文窗口中容纳完整帖子的模型,模型也可能很难在很长的输入中找到信息。
为了解决这个问题,我们将把 Document 分割成块以进行嵌入和向量存储。这应该可以帮助我们在运行时仅检索博客文章中最相关的部分。
在本例中,我们将把文档分成 1000 个字符的块,块之间有 200 个字符的重叠。重叠有助于降低将语句与与其相关的重要上下文分开的可能性。我们使用 RecursiveCharacterTextSplitter,它将使用常见的分隔符(如换行符)递归地分割文档,直到每个块的大小合适。这是针对一般文本用例推荐的文本分割器。
我们设置 add_start_index=True ,以便将初始文档中每个分割文档开始的字符索引保留为元数据属性“start_index”。

from langchain_text_splitters import RecursiveCharacterTextSplitter

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

len(all_splits)
66
len(all_splits[0].page_content)
969
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_openai import OpenAIEmbeddings

vectorstore = Chroma.from_documents(documents=all_splits, embedding=OpenAIEmbeddings())

检索

现在让我们编写实际的应用逻辑。我们想要创建一个简单的应用程序,它接受用户问题,搜索与该问题相关的文档,将检索到的文档和初始问题传递给模型,然后返回答案。
首先,我们需要定义搜索文档的逻辑。 LangChain 定义了一个 Retriever 接口,它包装了一个索引,该索引可以在给定字符串查询的情况下返回相关的 Documents 。
最常见的 Retriever 类型是 VectorStoreRetriever,它使用向量存储的相似性搜索功能来促进检索。任何 VectorStore 都可以通过 VectorStore.as_retriever() 轻松转换为 Retriever :

retriever = vectorstore.as_retriever(search_type="similarity", search_kwargs={"k": 6})

retrieved_docs = retriever.invoke("What are the approaches to Task Decomposition?")

len(retrieved_docs)
6
print(retrieved_docs[0].page_content)
Tree of Thoughts (Yao et al. 2023) extends CoT by exploring multiple reasoning possibilities at each step. It first decomposes the problem into multiple thought steps and generates multiple thoughts per step, creating a tree structure. The search process can be BFS (breadth-first search) or DFS (depth-first search) with each state evaluated by a classifier (via a prompt) or majority vote.
Task decomposition can be done (1) by LLM with simple prompting like "Steps for XYZ.\n1.", "What are the subgoals for achieving XYZ?", (2) by using task-specific instructions; e.g. "Write a story outline." for writing a novel, or (3) with human inputs.

生成

我们使用 gpt-3.5-turbo OpenAI 聊天模型,但任何 LangChain LLM 或 ChatModel 都可以替换。

import os

os.environ["OPENAI_API_KEY"] = "your openai api key"

from langchain_openai import ChatOpenAI

llm = ChatOpenAI(model="gpt-3.5-turbo-0125")

我们使用已签入 LangChain 提示中心的 RAG 提示。rlm/rag-prompt

from langchain import hub

prompt = hub.pull("rlm/rag-prompt")

截屏2024-06-21 下午5.43.23.png

组装链

我们将使用 LCEL Runnable 协议来定义链,使我们能够

  • 以透明的方式将组件和功能连接在一起
  • 在 LangSmith 中自动追踪我们的链条
  • 开箱即用地进行流式、异步和批量呼叫。
import os

os.environ["LANGCHAIN_TRACING_V2"] = "true"
os.environ["LANGCHAIN_API_KEY"] = "your langchain api key"
os.environ["OPENAI_API_KEY"] = "your openai api key"

from langchain_openai import ChatOpenAI

llm = ChatOpenAI(model="gpt-3.5-turbo-0125")
import bs4
from langchain import hub
from langchain_chroma import Chroma
from langchain_community.document_loaders import WebBaseLoader
from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables import RunnablePassthrough
from langchain_openai import OpenAIEmbeddings
from langchain_text_splitters import RecursiveCharacterTextSplitter

# Load, chunk and index the contents of the blog.
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()

text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
splits = text_splitter.split_documents(docs)
vectorstore = Chroma.from_documents(documents=splits, embedding=OpenAIEmbeddings())

# Retrieve and generate using the relevant snippets of the blog.
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)


rag_chain = (
    {"context": retriever | format_docs, "question": RunnablePassthrough()}
    | prompt
    | llm
    | StrOutputParser()
)

response = rag_chain.invoke("What is Agent System Overview?")

print(response)

调用

我询问了两个问题

  • What is Task Decomposition?

截屏2024-06-21 下午5.51.09.png

  • What is Agent System Overview?

截屏2024-06-21 下午5.51.30.png

剖析 LCEL(链) 以了解发生了什么

首先:这些组件中的每一个( retriever 、 prompt 、 llm 等)都是 Runnable 的实例。这意味着它们实现相同的方法 - 例如同步和异步 .invoke 、 .stream 或 .batch - 这使它们更容易连接在一起。它们可以通过 | 运算符连接到 RunnableSequence(另一个 Runnable)。
当遇到 | 运算符时,LangChain 会自动将某些对象转换为可运行对象。此处, format_docs 被转换为 RunnableLambda,带有 “context” 和 “question” 的字典被转换为 RunnableParallel。细节并不重要,重要的是每个对象都是一个 Runnable。
让我们跟踪输入问题如何流经上述可运行对象:
正如我们在上面看到的, prompt 的输入预计是一个带有键 “context” 和 “question” 的字典。因此,该链的第一个元素构建了可运行对象,它将根据输入问题计算这两个值:

  • retriever | format_docs 将问题传递给检索器,生成Document对象,然后传递给 format_docs 生成字符串;
  • RunnablePassthrough() 不变地传递输入问题。

然后 chain.invoke(question) 将构建一个格式化的提示,准备进行推理。
最后一步是 llm ,它运行推理,以及 StrOutputParser() ,它只是从 LLM 的输出消息中提取字符串内容。

遇到的问题

USER_AGENT

截屏2024-06-21 下午6.02.39.png
不阻塞运行,解决方案:
添加下面代码

user_agent = "MyPythonApp/1.0 (Language=Python/3.9; Platform=Linux/Ubuntu20.04)"
os.environ["USER_AGENT"] = user_agent

SSLError

截屏2024-06-21 下午6.04.49.png
阻塞运行,解决方案:
换个代理。

LangSmith展示

截屏2024-06-21 下午6.09.02.png
截屏2024-06-21 下午6.09.29.png
截屏2024-06-21 下午6.09.52.png

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

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

相关文章

加速度传感器采集时无效数据的产生及消除

1.现象 这是振动传感器的原始采样信号,它有一个明显的上升沿,这个上升沿,看时间轴标尺,大概持续了至少50ms,它是从哪里来的呢? 加速度传感器一般是由恒流源驱动的。而恒流源的原始电源输入是个经由电源模…

3dmax最小细分,最大细分,全局细分倍增怎么设置才合理

在3ds Max中进行高质量渲染时,细分(Subdivision)是一个至关重要的参数。细分的设置直接影响到渲染结果的细节程度和渲染时间。以下内容详细解释最小细分、最大细分和全局细分倍增的含义及作用,并解释在渲染设置时,怎样…

Llama3应用与RAG的实现

源码见文末 实现效果 1.Llama3安装 官网:https://ollama.com/download/linuxhttps://ollama.com/download/linux 首先,安装ollama, 安装后能够很好下载其模型

如何只用 ClickHouse SQL 实现 K-Means 聚类

本文字数:15474;估计阅读时间:39 分钟 审校:庄晓东(魏庄) 本文在公众号【ClickHouseInc】首发 Meetup活动 ClickHouse 上海首届 Meetup 讲师招募中,欢迎讲师在文末扫码报名! 介绍 最…

扫地机器人无故中止问题的TRIZ解决方案

在我们享受智能家居带来的便捷时,扫地机器人无疑是家中不可或缺的“小帮手”。然而,当这个小家伙突然“罢工”,不再听从我们的指令,甚至无故中止工作时,你是否也感到头疼不已?今天,深圳天行健企…

关于ip地址的网页无法访问navigator的gpu、媒体、蓝牙等设备的解决方法

在使用threejs的WebGPURenderer渲染器时,发现localhost以及127.0.0.1才能访问到navigator.gpu,直接使用ip会变成undefined,原因是为了用户的隐私安全,只能在安全的上下文中使用,非安全的上下文就会是undefined,安全上下…

SHAP中使用shap.summary_plot对多分类任务模型中特征重要性绘图

在文心一言中输入: 使用shap.summary_plot展示各个特征对模型输出类别的重要性 其输出的代码为(不正确): from sklearn import datasets from sklearn.model_selection import train_test_split from sklearn import svm import …

git clone中的报错问题解决:git@github.com: Permission denied (publickey)

报错: Submodule path ‘kernels/3rdparty/llm-awq’: checked out ‘19a5a2c9db47f69a2851c83fea90f81ed49269ab’ Submodule path ‘kernels/3rdparty/nvbench’: checked out ‘75212298727e8f6e1df9215f2fcb47c8c721ffc9’ Submodule path ‘kernels/3rdparty/t…

为什么 Swift 没有原生的 subArray 方法?

为什么 Swift 没有原生的 subArray 方法? Swift 是一门设计精良的编程语言,以其灵活性和高性能著称。在 Swift 中截取数组的子数组是一个常见的操作,但你可能会发现 Swift 标准库中并没有直接提供一个 subArray 方法。这是为什么呢&#xff…

软考中级软件设计师查成绩:终于合格了。

软考中级软件设计师终于合格了。 考试时间是8:30-12:30,我下午一点多要赶火车。考试的地方很偏僻,离火车站30多里地。所以,我必须提前交卷。客观题有大概10道题都是蒙的C。应用题中的算法考的是哈夫曼算法&#xff0…

【python】PyQt5各个控件语法解析,QObject父子对象的操作

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,…

Python文本挖掘数据分析——竞争分析(1)

文章目录 前言项目背景与目标品类分布分析数据准备与处理查看数据类目作图查看占比的不同 适用对象作图查看适用对象占比 产品结构分析对商品分类汇总定义作图函数拜耳安速科凌虫控 前言 数据说明: 项目背景与目标 该项目旨在分析三个品牌(拜耳、安速、科凌虫控&…

从删库到还原

欢迎来到我的博客,代码的世界里,每一行都是一个故事 🎏:你只管努力,剩下的交给时间 🏠 :小破站 从删库到还原 魔法一魔法二魔法三魔法四查看是否开启binlog,且format为row执行以下命…

常微分方程算法之编程示例四(龙格-库塔法)

目录 一、算例一 1.1 研究问题 1.2 C代码 1.3 计算结果 二、算例二 2.1 研究问题 2.2 C代码 2.3 计算结果 一、算例一 本节我们采用龙格-库塔法(Runge-Kutta法)求解算例。 龙格-库塔法的原理及推导请参考: 常微分方程算法之龙…

钡铼BL101网关6串口Modbus转MQTT优化智慧园区设备互联

BL101网关:优化智慧园区设备互联的关键利器 在当今快速发展的智能化时代,智慧园区管理对于设备之间的高效互联至关重要。钡铼(BL101)网关作为一款功能强大的Modbus转MQTT设备,不仅支持多种通信协议和硬件接口&#xf…

安帝康生物完成超2亿元A轮融资,持续深耕呼吸感染和疼痛领域创新药研发

日前,嘉兴安帝康生物科技有限公司(下称“安帝康生物”)正式宣布完成超2亿元A轮融资,由先声药业(02096.HK)、华金投资与华金大道联合领投,老股东同创伟业、嘉兴新创创投持续加投,嘉睿…

【CVPR2024】Bootstrapping Autonomous Radars with Self-Supervised Learning

原文链接:https://arxiv.org/abs/2312.04519 简介:自动驾驶中的雷达可以在极端天气下进行感知,但相关模型的训练受到标注困难的阻碍。本文提出自监督框架,利用大量无标注雷达数据预训练雷达表达。方法包括雷达到雷达的、以及雷达到…

适用于不同场合的高频俄语祝福语,柯桥零基础俄语培训

Приятного аппетита. Кушайте на здоровье. (говорят те, кто подает еду на стол, обычно это хозяйка дома, квартиры, или официант в кафе, ресторане…

论文辅导 | 基于贝叶斯优化LSTM的锂电池健康状态评估方法

辅导文章 模型描述 在传统的 LSTM 神经网络中,超参数的取值对模型性能有很大影响,但人工调参很难得到最优解。 因此,本文加入了 BO 来迭代出最优超参数。 在利用LSTM 神经网络评估锂电池 SoH 的基础上,通过 BO来提高评估的精确度。 预测效果

`THREE.PointsMaterial` 是 Three.js 中用于创建粒子系统材质的类。它允许你设置粒子系统的外观属性,比如颜色、大小和透明度。

demo案例 THREE.PointsMaterial 是 Three.js 中用于创建粒子系统材质的类。它允许你设置粒子系统的外观属性,比如颜色、大小和透明度。下面是对其构造函数的参数、属性和方法的详细讲解。 构造函数 const material new THREE.PointsMaterial(parameters);参数&am…