前言
上两篇文章分别介绍了LangChain的快速入门和Agent智能体开发。在LLM的实际应用场景中,经常会需要用到特定领域用户的数据,但这些数据不属于模型训练集的一部分,要实现这一需求,最好的方法是通过检索增强生成(RAG)。在用户提问时,先检索特定的外部数据,把检索结果作为上下文传递给LLM,以便大模型返回更精准的结果。今天我们就带大家了解下在LangChain里RAG的使用,结合智谱AI GLM4大模型开发一个基于特定知识库的智能问答应用。
RAG介绍
LangChain中提供了RAG应用程序的所有构建模块。结构图如下:
1、文档加载器
文档加载器用来加载各种不同类型的文档。LangChain提供了100 多种不同的文档加载器,可以加载各种类型文档,包括:CSV、HTML、JSON、Markdown、PDF、DOC、XLS、图片、视频、音频等等。
2、文本分割器
加载文档后,对于长文档,需要分割成更小的块,以适合LLM的上下文窗口。LangChain 有许多内置的文档转换器,可以轻松地拆分、组合、过滤和以其他方式操作文档。 LangChain 提供了多种不同类型的文本分割器。下表列出了所有这些以及一些特征:
- 类型:文本分割器的类型
- 分割依据:此文本拆分器如何拆分文本
- 添加元数据:此文本拆分器是否添加有关每个块来自何处的元数据。
- 描述:分离器的描述,包括有关何时使用它的建议。
3、嵌入模型
嵌入(Embedding)是一种将单词、短语或整个文档转换为密集向量的技术。每个单词或短语被转换成一组数字,这组数字捕捉了该文本的某些语义特征。 嵌入模型通过将文本转换为计算机可以处理的数值形式(即向量),使得计算机能够理解和处理自然语言。通过嵌入捕获文本的语义,可以快速有效地找到文本的其他相似部分。 LangChain提供了超过25种不同嵌入提供商和方法的集成,抱脸上有个中文、英文嵌入模型排行榜,可以作为参考,具体还要选适合自己的,比如开源的,对中文支持比较好的等等:
4、向量数据库
有了嵌入模型对数据的向量化,就需要数据库来支持这些嵌入数据的高效存储和搜索。LangChain提供了50多种不同向量数据库的集成,目前Milvus评分最高。
RAG开发案例 接下来我们实战开发一个基于特定知识库的智能问答应用。还是在Jupyter Notebook环境中执行。
1、创建智谱GLM4大模型对象
首先定义LangChain里智谱大模型的包装类,参考第一篇文章里有,或者从github上下载: 创建大模型对象
# 填写您自己的APIKey
ZHIPUAI_API_KEY = "..."
llm = ChatZhipuAI(
temperature=0.1,
api_key=ZHIPUAI_API_KEY,
model_name="glm-4",
)
加载文档
这里特定领域用户的数据来源于一个示例的ordersample.csv文件,这个文件可以从我的github上获取: 文件具体内容如下: 把orersample.csv下载到jupyter notebook当前ipynb文件目录,使用CSV文档加载器,加载文档内容:
from langchain_community.document_loaders.csv_loader import CSVLoader
loader = CSVLoader(file_path='ordersample.csv')
data = loader.load()
文本分割
通常可以使用递归字符文本分割器对文档对象进行分割,可以设置分割块字符的大小,和重合字符大小。因为我的文档对象比较小,所以每个文档基本上没有达到要切分的大小阈值,可以尝试把文档内容变多,试下效果。
from langchain.text_splitter import RecursiveCharacterTextSplitter
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=1000, chunk_overlap=200, add_start_index=True
)
all_splits = text_splitter.split_documents(data)
向量化存储
接下来我们首先使用嵌入模型对分割后的文档进行向量化,然后存储到向量数据库中。 嵌入模型使用的是bge-large-zh-v1.5,这是BAAI北京智源人工智能研究院开源的,支持中、英文的嵌入模型,在开源嵌入模型中算是效果比较好的一个。 向量数据库使用的是FAISS,是FAIR(Meta人工智能实验室)开源的向量数据库。可以在本地使用,相对轻量些,没有Milvus那么强, 但在本地环境使用也够用了。
from langchain_community.embeddings import HuggingFaceBgeEmbeddings
model_name = "BAAI/bge-large-zh-v1.5"
model_kwargs = {"device": "cpu"}
encode_kwargs = {"normalize_embeddings": True}
bgeEmbeddings = HuggingFaceBgeEmbeddings(
model_name=model_name, model_kwargs=model_kwargs, encode_kwargs=encode_kwargs
)
from langchain_community.vectorstores import FAISS
vector = FAISS.from_documents(all_splits, bgeEmbeddings)
向量库检索
接下来尝试下使用向量库进行检索。
retriever = vector.as_retriever(search_type="similarity", search_kwargs={"k": 3})
retriever.invoke("收货人姓名是张三丰的,有几个订单?金额分别是多少,总共是多少?")
生成问答结果
使用检索链,串联向量库检索和大模型,根据用户的提问,生成问答结果。
from langchain_core.prompts import ChatPromptTemplate
prompt = ChatPromptTemplate.from_template("""仅根据所提供的上下文回答以下问题:
<context>
{context}
</context>
问题: {question}""")
from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables import RunnablePassthrough
retriever_chain = (
{"context": retriever , "question": RunnablePassthrough()}
| prompt
| llm
| StrOutputParser()
)