从零开始学 LangChain(3) | 豆包MarsCode AI刷题

255 阅读6分钟

LangChain+LLM的配置就是使原本复杂的东西变得特别简单,特别易于操作。

把本地知识切片后做Embedding,存储到向量数据库中,然后把用户的输入和从向量数据库中检索到的本地知识传递给大模型,最终生成所想要的回答。

1.LangChain框架

整个框架分为这样三个部分。

  • 数据源(Data Sources):数据可以有很多种,包括PDF在内的非结构化的数据(Unstructured Data)、SQL在内的结构化的数据(Structured Data),以及Python、Java之类的代码(Code)。在这个示例中,我们聚焦于对非结构化数据的处理。

  • 大模型应用(Application,即LLM App):以大模型为逻辑引擎,生成我们所需要的回答。

  • 用例(Use-Cases):大模型生成的回答可以构建出QA/聊天机器人等系统。

2.核心实现机制

这个项目的核心实现机制是下图所示的数据处理管道(Pipeline)。 image.png 在这个管道的每一步中,LangChain都为我们提供了相关工具,让你轻松实现基于文档的问答功能。

具体流程分为下面5步。

  • (1)Loading(数据的准备和载入)

    文档加载器把Documents 加载为以LangChain能够读取的形式。

    需要利用Open AI的两种不同模型做以下两件事:

    • 用OpenAI的Embedding模型为文档做嵌入。
    • 调用OpenAI的GPT模型来生成问答系统中的回答。
  • (2)Splitting(文本的分割)

    文本分割器把Documents 切分为指定大小的分割,我把它们称为“文档块”或者“文档片”。

    使用 LangChain中的RecursiveCharacterTextSplitter 来分割文本。

  • (3)Storage(向量数据库存储)

    将上一步中分割好的“文档块”以“嵌入”(Embedding)的形式存储到向量数据库(Vector DB)中,形成一个个的“嵌入片”。

    使用OpenAIEmbeddings 来生成嵌入,然后使用 Qdrant 这个向量数据库来存储嵌入

    • 文本嵌入

      词嵌入(Word Embedding)是自然语言处理和机器学习中的一个概念,它将文字或词语转换为一系列数字,通常是一个向量。简单地说,词嵌入就是一个为每个词分配的数字列表。这些数字不是随机的,而是捕获了这个词的含义和它在文本中的上下文。因此,语义上相似或相关的词在这个数字空间中会比较接近。

      举个例子,通过某种词嵌入技术,我们可能会得到: "国王" -> [1.2, 0.5, 3.1, …] "皇帝" -> [1.3, 0.6, 2.9, …] "苹果" -> [0.9, -1.2, 0.3, …]

      从这些向量中,我们可以看到“国王”和“皇帝”这两个词的向量在某种程度上是相似的,而与“苹果”这个词相比,它们的向量则相差很大,因为这两个概念在语义上是不同的。

      词嵌入的优点是,它提供了一种将文本数据转化为计算机可以理解和处理的形式,同时保留了词语之间的语义关系。这在许多自然语言处理任务中都是非常有用的,比如文本分类、机器翻译和情感分析等。

    • 向量数据库

      向量数据库,也称为矢量数据库或者向量搜索引擎,是一种专门用于存储和搜索向量形式的数据的数据库。在众多的机器学习和人工智能应用中,尤其是自然语言处理和图像识别这类涉及大量非结构化数据的领域,将数据转化为高维度的向量是常见的处理方式。这些向量可能拥有数百甚至数千个维度,是对复杂的非结构化数据如文本、图像的一种数学表述,从而使这些数据能被机器理解和处理。然而,传统的关系型数据库在存储和查询如此高维度和复杂性的向量数据时,往往面临着效率和性能的问题。因此,向量数据库被设计出来以解决这一问题,它具备高效存储和处理高维向量数据的能力,从而更好地支持涉及非结构化数据处理的人工智能应用。

      向量数据库有很多种,比如Pinecone、Chroma和Qdran

  • (4)Retrieval(相关知识的获取)

    应用程序从存储中检索分割后的文档(例如通过比较余弦相似度,找到与输入问题类似的嵌入片)。

    信息提取的基本方式就是把问题也转换为向量,然后去和向量数据库中的各个向量进行比较,提取最接近的信息。

    在RetrievalQA 链中有下面两大重要组成部分。

    • LLM是大模型,负责回答问题。
    • retriever(vectorstore.as_retriever())负责根据问题检索相关的文档,找到具体的“嵌入片”。这些“嵌入片”对应的“文档块”就会作为知识信息,和问题一起传递进入大模型。本地文档中检索而得的知识很重要,因为从互联网信息中训练而来的大模型不可能拥有“易速鲜花”作为一个私营企业的内部知识

    向量之间的比较通常基于向量的距离或者相似度。在高维空间中,常用的向量距离或相似度计算方法有欧氏距离和余弦相似度。

    • 欧氏距离:这是最直接的距离度量方式,就像在二维平面上测量两点之间的直线距离那样。在高维空间中,两个向量的欧氏距离就是各个对应维度差的平方和的平方根。

    • 余弦相似度:在很多情况下,我们更关心向量的方向而不是它的大小。例如在文本处理中,一个词的向量可能会因为文本长度的不同,而在大小上有很大的差距,但方向更能反映其语义。余弦相似度就是度量向量之间方向的相似性,它的值范围在-1到1之间,值越接近1,表示两个向量的方向越相似。

      关心数量等大小差异时用欧氏距离,关心文本等语义差异时用余弦相似度。

  • (5)Output(生成回答并展示)

    把问题和相似的嵌入片传递给语言模型(LLM),使用包含问题和检索到的分割的提示生成答案

    这里会创建一个 Flask 应用(需要安装Flask包)来接收用户的问题,并生成相应的答案,最后通过 index.html 对答案进行渲染和呈现。