用Langchain搭建RAG(一)

263 阅读3分钟

写在前面

上回提到,在Langchain中,RAG(Retriever Augumented Generation)可以简单写成下述形式:
RAG=Retriever+Prompt+LLMRAG = Retriever + Prompt+ LLM
这篇笔记记录搭建一个RAG System Demo的过程,并对Langchain框架的运行进行初步的探索。

搭建流程

导入包

from langchain_community.document_loaders import WebBaseLoader
from langchain_core.output_parsers import StrOutputParser
from langchain_openai import OpenAIEmbeddings,ChatOpenAI
from langchain_text_splitters import RecursiveCharacterTextSplitter
import os

LLM

配置大语言模型(这里使用豆包,使用方法见首页右上角文档。)

llm = ChatOpenAI(
    base_url = os.environ.get("DOUBAO_ENDPOINT"),
    api_key = os.environ.get("DOUBAO_API_KEY"),
    model = os.environ.get("DOUBAO_CHAT_MODEL")
)

相较于openai client,简单理解为将client中的参数与chat completion函数中的参数封装到了一起。
跳转到ChatOpenAI类定义,在注释中有一些比较有意思的示例参考:
流式传输&异步调用: image.png 工具调用: image.png 异步请求可参考这篇文章:
unite.ai/zh-CN/Pytho…
这可以让你在等待远程服务器对你的请求作出响应时,去干一些其他的事情,或者同时给远程服务器发多个请求,而不是傻等着服务器返回响应。
下面是构建 VectorBase(Retriever)的部分。

Retriever

DocumentLoader

在许多示例中,Document Loader一般对PDF或Word/txt进行操作,Langchain官网中使用WebBaseLoader,对网页信息进行载入。

WebLoader

对于给定的网页,Langchain中的WebLoader使用beautiful soup 4 进行网页内容信息(html)的提取;提供两个接口,一个是lazy_load串行提取,一个是aload异步提取,区别在于,lazyload可以指定提取特定标签内容中的信息,而aload不能。
返回的文档包括截取的内容与元数据(地址和html标题)
运行程序

loader = WebBaseLoader(
    web_path="https://aws.amazon.com/cn/what-is/retrieval-augmented-generation/",
# bs_kwargs=
)
result = loader.lazy_load()
print(list(result))

因为LazyLoad返回的是一个生成器,Load是将lazyload的输出转成了list,所以程序中作出上述处理。
返回如下图所示:

image.png 可以看到爬下来的网页还是有很多并不需要的内容。可通过写bs_kwargs来过滤无效内容:

loader = WebBaseLoader(
    web_path="https://aws.amazon.com/cn/what-is/retrieval-augmented-generation/",
    bs_kwargs=dict(
        parse_only=bs4.SoupStrainer(
            class_=("eb-faq-content")
        )
    )
)
result = loader.lazy_load()
result = list(result)
print(result)

在网页中想要的内容与HTML对应的部分,可通过框选--》右键--》检查(inspect)来获取

TextSplitter

RecursiveCharacterTextSplitter

递归字符文本分割,通过预先定义分割符号,在尽量满足chunk size的前提下尽可能保留完整原文本中的语义信息。 通过split documents函数,分割得到一系列Documents.

写在后面

这一把简单过了一下LLM,Document Loader 和 text splitter. 针对调用LLM,简单过了一下流式调用和异步调用,异步调用是在构建llm应用中非常重要的一个部分(串行请求太慢,同时,并行请求过快可能会被服务端制裁)
Document Loader和Text Splitter同样是构建RAG系统中,简单却重要的部分。RAG回答准确的核心是从文本中召回真正有用的部分,高质量的数据和语义完备的分块是召回高质量提示词的前提。
下一篇,变得更强。