LangChain + Streamlit + Llama:将对话式AI引入本地机器
在过去的几个月里,大型语言模型(LLM)获得了极大的关注,引起了全球开发人员的兴趣。这些模型创造了令人兴奋的前景,特别是对于从事聊天机器人、个人助理和内容创作的开发人员而言。LLM带来的可能性引发了开发人员的热情 |人工智能 |NLP社区。
在线工具推荐:3D数字孪生场景编辑器 - GLTF/GLB材质纹理编辑器 - 3D模型在线转换 - Three.js AI自动纹理开发包 - YOLO 虚幻合成数据生成器 - 三维模型预览图生成器
什么是LLMS?
大型语言模型 (LLM) 是指能够生成与人类语言非常相似的文本并以自然方式理解提示的机器学习模型。这些模型使用包括书籍、文章、网站和其他来源在内的广泛数据集进行训练。通过分析数据中的统计模式,LLM可以预测应遵循给定输入的最可能的单词或短语。
通过利用大型语言模型(LLM),我们可以整合特定领域的数据来有效地解决查询。当处理模型在初始训练期间无法访问的信息(例如公司的内部文档或知识库)时,这变得特别有利。
用于此目的的体系结构称为检索增强生成,或者不太常见的生成问答。
什么是语言链
LangChain 是一个令人印象深刻且免费提供的框架,经过精心设计,使开发人员能够创建由语言模型(尤其是大型语言模型 (LLM))推动的应用程序。
LangChain彻底改变了各种应用程序的开发过程,包括聊天机器人,生成式问答(GQA)和总结。通过将来自多个模块的组件无缝链接在一起,LangChain 能够创建围绕 LLM 的强大功能量身定制的卓越应用程序。
赋予动机?
在本文中,我将演示从头开始创建自己的文档助手的过程,利用LLaMA 7b和Langchain,一个专门为与LLM无缝集成而开发的开源库。
以下是博客结构的概述,概述了将提供该过程详细细分的特定部分:
Setting up the virtual environment and creating file structure
Getting LLM on your local machine
Integrating LLM with LangChain and customizing PromptTemplate
Document Retrieval and Answer Generation
Building application using Streamlit
第 1 部分:设置虚拟环境和创建文件结构
设置虚拟环境为运行应用程序提供了一个受控和隔离的环境,确保其依赖项与其他系统范围的包分开。此方法简化了依赖项的管理,并有助于在不同环境之间保持一致性。
为了设置此应用程序的虚拟环境,我将在我的 GitHub 存储库中提供 pip 文件。首先,让我们创建必要的文件结构,如图所示。或者,您可以简单地克隆存储库以获取所需的文件。
在模型的文件夹中,我们将存储我们将下载的LLM,而pip文件将位于根目录中。
要创建虚拟环境并安装其中的所有依赖项,我们可以使用同一目录中的命令或简单地运行批处理文件,它将从.这将确保所有必要的包和库都安装在虚拟环境中。成功安装依赖项后,我们可以继续下一步,其中包括下载所需的模型。这是存储库。pipenv installsetup_env.batpipfile
第 2 部分:在本地计算机上获取 LLaMA
什么是LLaMA?
LLaMA是由Facebook的母公司Meta AI设计的一种新的大型语言模型。LLaMA 拥有从 7 亿到 65 亿个参数的各种模型集合,是可用的最全面的语言模型之一。24 年 2023 月 <> 日,Meta 向公众发布了 LLaMA 模型,展示了他们对开放科学的奉献精神。
考虑到LLaMA的卓越功能,我们选择利用这种强大的语言模型来实现我们的目的。具体来说,我们将采用最小版本的LLaMA,称为LLaMA 7B。即使在这种缩小的尺寸下,LLaMA 7B也提供了重要的语言处理能力,使我们能够高效地实现预期的结果。
官方研究论文:LLaMA: Open and Efficient Foundation Language Models
要在本地CPU上执行LLM,我们需要一个GGML格式的本地模型。有几种方法可以实现这一点,但最简单的方法是直接从Hugging Face模型存储库下载 bin 文件。在我们的例子中,我们将下载 美洲驼7B 模型。这些模型是开源的,可免费下载。
如果您想节省时间和精力,请不要担心 - 我已经为您提供了保障。这是您下载模型的直接链接?只需下载它的任何版本,然后将文件移动到我们根目录中的 models 目录中。这样,您就可以方便地访问模型以供您使用。
什么是 GGML?为什么选择GGML?如何GGML?拉马大学 CPP
GGML 是一个用于机器学习的张量库,它只是一个C++库,允许您仅在 CPU 或 CPU + GPU 上运行 LLM。它定义了用于分发大型语言模型 (LLM) 的二进制格式。GGML利用了一种称为量化的技术,该技术允许大型语言模型在消费者硬件上运行。
现在什么是量化?
LLM 权重是浮点(十进制)数字。就像与小整数(例如 1000)相比,它需要更多的空间来表示大整数(例如 1)一样,与低精度浮点数(例如 0.0001)相比,它需要更多的空间来表示高精度浮点数(例如 0.1)。量化大型语言模型的过程涉及降低表示权重的精度,以减少使用该模型所需的资源。GGML支持许多不同的量化策略(例如4位,5位和8位量化),每种策略在效率和性能之间提供了不同的权衡。
为了有效地使用这些模型,必须考虑内存和磁盘要求。由于模型当前已完全加载到内存中,因此您需要足够的磁盘空间来存储它们,并需要足够的 RAM 在执行期间加载它们。对于 65B 型号,即使在量化之后,也建议至少有 40 GB 的可用 RAM。值得注意的是,内存和磁盘要求目前是等效的。
量化在管理这些资源需求方面起着至关重要的作用。除非您可以访问特殊的计算资源
通过降低模型参数的精度并优化内存使用,量化使模型能够在更适度的硬件配置上使用。这可确保在更广泛的设置下运行模型仍然可行且高效。
如果它是一个C++库,我们如何在 Python 中使用它?
这就是Python绑定发挥作用的地方。绑定是指为我们python和C++在两种语言之间创建桥梁或接口的过程。我们将使用 哪个 Python 绑定,它充当纯 C/C++ 中 LLaMA 模型的推理。的主要目标是使用 4 位整数量化运行 LLaMA 模型。这种集成使我们能够有效地利用LLaMA模型,利用C / C++实现的优势和4位整数量化的优势llama-cpp-pythonllama.cppllama.cpp
准备好 GGML 模型并准备好我们所有的依赖项(感谢 pipfile),是时候开始我们的 LangChain 之旅了。但在进入令人兴奋的 LangChain 世界之前,让我们先从习惯的“Hello World”仪式开始——这是我们在探索新语言或框架时遵循的传统,毕竟,LLM 也是一种语言模型。
瞧!! 我们已经成功地在CPU上执行了我们的第一个LLM,完全离线,完全随机(你可以使用超参数温度)。
随着这一激动人心的里程碑的完成,我们现在准备开始我们的主要目标:使用 LangChain 框架对自定义文本进行问答。
第 3 部分:LLM 入门 — 语言链集成
在上一节中,我们使用美洲驼cpp 初始化了LLM。现在,让我们利用LangChain框架来开发使用LLM的应用程序。您可以通过文本与它们进行交互的主要界面。为了简化,很多模型都是文本输入,文本输出。因此,LangChain 中的许多接口都以文本为中心。
快速工程的兴起
在不断发展的编程领域,出现了一个引人入胜的范式:提示。提示涉及向语言模型提供特定输入以引发所需的响应。这种创新的方法使我们能够根据我们提供的输入来塑造模型的输出。
值得注意的是,我们表达提示的方式中的细微差别会显着影响模型响应的性质和实质。结果可能因措辞而异,这突出了在制定提示时仔细考虑的重要性。
为了提供与LLM的无缝交互,LangChain提供了几个类和函数,使使用提示模板可以轻松构造和处理提示。这是生成提示的可重现方法。它包含一个文本字符串模板,可以从最终用户那里获取一组参数并生成提示。让我们举几个例子。
我希望前面的解释对提示的概念有了更清晰的把握。现在,让我们继续提示LLM。
这工作得很好,但这不是LangChain的最佳利用。到目前为止,我们已经使用了单个组件。我们采用格式化的提示模板,然后采用 llm,然后将这些参数传递到 llm 中以生成答案。对于简单的应用程序,单独使用 LLM 是可以的,但更复杂的应用程序需要将 LLM 相互链接或与其他组件链接。
LangChain为此类链式应用程序提供了链接口。我们非常笼统地将链定义为对组件的一系列调用,其中可以包括其他链。链允许我们将多个组件组合在一起,以创建一个单一的、连贯的应用程序。例如,我们可以创建一个链,该链接受用户输入,使用提示模板对其进行格式化,然后将格式化的响应传递给LLM。我们可以通过将多个链组合在一起,或者通过将链与其他组件组合在一起来构建更复杂的链。
为了理解这一点,让我们创建一个非常简单的链,该链将接受用户输入,使用它格式化提示,然后使用我们已经创建的上述各个组件将其发送到LLM。
处理多个变量时,您可以选择使用字典共同输入它们。本节到此结束。现在,让我们深入了解主要部分,我们将外部文本合并为检索器以进行问答。
第 4 部分:生成用于问答的嵌入和向量存储
在许多LLM应用程序中,需要模型训练集中未包含的用户特定数据。LangChain 为您提供加载、转换、存储和查询数据的基本组件。
这五个阶段是:
- 文档加载器:它用于将数据加载为文档。
- 文档转换器:它将文档拆分为较小的块。
- 嵌入:它将块转换为矢量表示,即嵌入。
- 矢量存储:它用于将上述块向量存储在向量数据库中。
- 猎犬:它用于检索一组向量,这些向量与嵌入在同一潜在空间中的向量形式的查询最相似。
现在,我们将演练五个步骤中的每一个步骤,以检索与查询最相似的文档块。之后,我们可以根据检索到的向量块生成答案,如提供的图像所示。
但是,在继续之前,我们需要准备执行上述任务的文本。出于这个虚构测试的目的,我从维基百科上复制了一篇关于一些流行的 DC 超级英雄的文本。以下是文字:
加载和转换文档
首先,让我们创建一个文档对象。在此示例中,我们将使用文本加载器。但是,Lang 链提供对多个文档的支持,因此根据您的特定文档,您可以使用不同的加载器。接下来,我们将使用该方法检索数据并将其作为文档从预配置的源加载。load
加载文档后,我们可以通过将文档分解为较小的块来继续转换过程。为了实现这一点,我们将使用文本分配器。默认情况下,拆分器在“\n\n”分隔符处分隔文档。但是,如果将分隔符设置为 null 并定义特定的区块大小,则每个区块将具有指定的长度。因此,生成的列表长度将等于文档长度除以区块大小。总之,它将类似于这样的东西:。让我们说到做到。list length = length of doc / chunk size
旅程的一部分是嵌入!!
这是最重要的一步。嵌入生成文本内容的矢量化描绘。这具有实际意义,因为它允许我们在向量空间内概念化文本。
词嵌入只是单词的向量表示,向量包含实数。由于语言通常包含至少数万个单词,因此由于维度数量众多,简单的二进制词向量可能变得不切实际。词嵌入通过在低维向量空间中提供单词的密集表示来解决此问题。
当我们谈论检索时,我们指的是检索一组与嵌入在同一潜在空间中的向量形式的查询最相似的向量。
LangChain 中的基本嵌入类公开了两种方法:一种用于嵌入文档,另一种用于嵌入查询。前者将多个文本作为输入,而后者则采用单个文本。
为了全面了解嵌入,我强烈建议深入研究基础知识,因为它们构成了神经网络如何处理文本数据的核心。我已经在我的一个博客中使用TensorFlow广泛地讨论了这个主题。这是链接。
词嵌入 — 神经网络的文本表示
创建矢量存储和检索文档
矢量存储可有效管理嵌入式数据的存储,并代表您促进矢量搜索操作。嵌入和存储生成的嵌入向量是存储和搜索非结构化数据的常用方法。在查询期间,还会嵌入非结构化查询,并检索与嵌入查询相似度最高的嵌入向量。这种方法能够有效地从载体存储中检索相关信息。
在这里,我们将利用Chroma,这是一个嵌入数据库和矢量存储,专门用于简化包含嵌入的AI应用程序的开发。它提供了一套全面的内置工具和功能,以方便您的初始设置,所有这些都可以通过执行简单的命令方便地安装到您的本地计算机上。pip install chromadb
到目前为止,我们已经见证了嵌入和向量存储从大量文档集合中检索相关块的非凡能力。现在,是时候将这个检索到的块作为上下文与我们的查询一起呈现给LLM。挥动其神奇的魔杖,我们将恳求LLM根据我们提供给它的信息生成答案。重要的部分是提示结构。
但是,强调结构良好的提示的重要性至关重要。通过制定精心设计的提示,我们可以减轻LLM产生幻觉的可能性 - 在面对不确定性时可能会发明事实。
在不延长等待的情况下,让我们现在进入最后阶段,看看我们的LLM是否能够产生令人信服的答案。现在是见证我们努力达到顶峰并揭晓结果的时候了。我们在这里咕噜咕噜?
这是我们一直在等待的时刻!我们已经做到了!我们刚刚利用本地运行的LLM构建了自己的问答机器人。
第 5 部分:使用流光链接所有内容
本节完全是可选的,因为它不能作为 Streamlit 的综合指南。我不会深入研究这部分;相反,我将介绍一个允许用户上传任何文本文档的基本应用程序。然后,他们将可以选择通过文本输入提问。在后台,该功能将与我们在上一节中介绍的功能保持一致。
但是,在Streamlit中上传文件时有一个警告。为了防止潜在的内存不足错误,特别是考虑到LLM的内存密集型性质,我将简单地读取文档并将其写入文件结构中的临时文件夹,并将其命名为这样,无论文档的原始名称如何,Textloader都将在将来无缝处理它。raw.txt.
目前,该应用程序专为文本文件而设计,但您可以将其改编为 PDF、CSV 或其他格式。基本概念保持不变,因为LLM主要用于文本输入和输出。此外,您可以尝试使用由 Llama C++ 绑定支持的不同 LLM。
在不进一步深入研究复杂细节的情况下,我展示了该应用程序的代码。随意自定义它以适合您的特定用例。
以下是流光应用程序的外观。
这次我喂了从维基复制的《黑暗骑士》的剧情,只是问谁的脸被严重烧伤了? LLM回答说——哈维·登特。
由3D建模学习工作室 整理翻译,转载请注明出处!