LangChain开发入门
项目名称:“易速鲜花”内部员工知识库问答系统。
项目介绍:“易速鲜花”作为一个大型在线鲜花销售平台,有自己的业务流程和规范,也拥有针对员工的SOP手册。新员工入职培训时,会分享相关的信息。但是,这些信息分散于内部网和HR部门目录各处,有时不便查询;有时因为文档过于冗长,员工无法第一时间找到想要的内容;有时公司政策已更新,但是员工手头的文档还是旧版内容。
基于上述需求,我们将开发一套基于各种内部知识手册的 “Doc-QA” 系统。这个系统将充分利用LangChain框架,处理从员工手册中产生的各种问题。这个问答系统能够理解员工的问题,并基于最新的员工手册,给出精准的答案。
开发框架:整个框架分为这样三个部分。
- 数据源(Data Sources):数据可以有很多种,包括PDF在内的非结构化的数据(Unstructured Data)、SQL在内的结构化的数据(Structured Data),以及Python、Java之类的代码(Code)。在这个示例中,我们聚焦于对非结构化数据的处理。
- 大模型应用(Application,即LLM App):以大模型为逻辑引擎,生成我们所需要的回答。
- 用例(Use-Cases):大模型生成的回答可以构建出QA/聊天机器人等系统。
核心实现机制: 这个项目的核心实现机制是下图所示的数据处理管道(Pipeline)。
在这个管道的每一步中,LangChain都为我们提供了相关工具,让你轻松实现基于文档的问答功能。
具体流程
具体流程分为下面5步。
- Loading:文档加载器把Documents 加载为以LangChain能够读取的形式。
- Splitting:文本分割器把Documents 切分为指定大小的分割,我把它们称为“文档块”或者“文档片”。
- Storage:将上一步中分割好的“文档块”以“嵌入”(Embedding)的形式存储到向量数据库(Vector DB)中,形成一个个的“嵌入片”。
- Retrieval:应用程序从存储中检索分割后的文档(例如通过比较余弦相似度,找到与输入问题类似的嵌入片)。
- Output:把问题和相似的嵌入片传递给语言模型(LLM),使用包含问题和检索到的分割的提示生成答案。
实现流程
加载数据
首先用LangChain中的document_loaders来加载各种格式的文本文件。(这些文件我把它放在OneFlower这个目录中了,如果你创建自己的文件夹,就要调整一下代码中的目录。)
在这一步中,我们从 pdf、word 和 txt 文件中加载文本,然后将这些文本存储在一个列表中。(注意:可能需要安装PyPDF、Docx2txt等库)
文本分割
接下来需要将加载的文本分割成更小的块,以便进行嵌入和向量存储。这个步骤中,我们使用 LangChain中的RecursiveCharacterTextSplitter 来分割文本。
向量数据库存储
紧接着,我们将这些分割后的文本转换成嵌入的形式,并将其存储在一个向量数据库中。在这个例子中,我们使用了 OpenAIEmbeddings 来生成嵌入,然后使用 Qdrant 这个向量数据库来存储嵌入(这里需要pip install qdrant-client)。
信息提取与比较
当内部文档存储到向量数据库之后,我们需要根据问题和任务来提取最相关的信息。此时,信息提取的基本方式就是把问题也转换为向量,然后去和向量数据库中的各个向量进行比较,提取最接近的信息。
向量之间的比较通常基于向量的距离或者相似度。在高维空间中,常用的向量距离或相似度计算方法有欧氏距离和余弦相似度。
- 欧氏距离:这是最直接的距离度量方式,就像在二维平面上测量两点之间的直线距离那样。在高维空间中,两个向量的欧氏距离就是各个对应维度差的平方和的平方根。
- 余弦相似度:在很多情况下,我们更关心向量的方向而不是它的大小。例如在文本处理中,一个词的向量可能会因为文本长度的不同,而在大小上有很大的差距,但方向更能反映其语义。余弦相似度就是度量向量之间方向的相似性,它的值范围在-1到1之间,值越接近1,表示两个向量的方向越相似。
这两种方法都被广泛应用于各种机器学习和人工智能任务中,选择哪一种方法取决于具体的应用场景。
关心数量等大小差异时用欧氏距离,关心文本等语义差异时用余弦相似度。
具体来说,欧氏距离度量的是绝对距离,它能很好地反映出向量的绝对差异。当我们关心数据的绝对大小,例如在物品推荐系统中,用户的购买量可能反映他们的偏好强度,此时可以考虑使用欧氏距离。同样,在数据集中各个向量的大小相似,且数据分布大致均匀时,使用欧氏距离也比较适合。
余弦相似度度量的是方向的相似性,它更关心的是两个向量的角度差异,而不是它们的大小差异。在处理文本数据或者其他高维稀疏数据的时候,余弦相似度特别有用。比如在信息检索和文本分类等任务中,文本数据往往被表示为高维的词向量,词向量的方向更能反映其语义相似性,此时可以使用余弦相似度。
所以我们用余弦相似度
生成回答
这一步是问答系统应用的主要UI交互部分,这里会创建一个 Flask 应用(需要安装Flask包)来接收用户的问题,并生成相应的答案,最后通过 index.html 对答案进行渲染和呈现。
在这个步骤中,我们使用了之前创建的 RetrievalQA 链来获取相关的文档和生成答案。然后,将这些信息返回给用户,显示在网页上。
我们先把本地知识切片后做Embedding,存储到向量数据库中,然后把用户的输入和从向量数据库中检索到的本地知识传递给大模型,最终生成所想要的回答。