使用LangChain强大的大型语言模型查询您的数据框架

使用LangChain查询数据框架

准备好使用Hugging Face的大型语言模型和向量数据库以及LangChain来使用您自己的数据!

Image By Author, generated with Dall-e 2

在之前的文章中,我解释了如何使用类似ChromaDB的向量数据库存储信息,并在创建用于查询Hugging Face的大型语言模型的强力提示时使用它。

在本文中,我们将看到如何使用LangChain完成同样的任务。LangChain将处理搜索我们存储在ChromaDB中的信息的任务,并直接将其传递给正在使用的语言模型。

通过这种方式,我们可以在不需要进行模型微调的情况下使用我们的数据与大型语言模型

由于我们将使用Hugging Face模型,这些模型可以在我们自己的服务器或私有云空间上下载和托管,信息无需通过OpenAI等公司

让我们描述一下本文中我们将遵循的步骤:

  1. 安装必要的库,如ChromaDB或LangChain
  2. 加载数据集并使用LangChain的文档加载器创建文档。
  3. 生成用于存储在数据库中的嵌入。
  4. 创建包含信息的索引。
  5. 设置一个检索器,LangChain将使用它来获取信息。
  6. 加载Hugging Face模型。
  7. 使用语言模型和检索器创建LangChain流水线。
  8. 利用流水线提问。

我们使用了哪些技术?

我们将使用的向量数据库是ChromaDB。它可能是开源向量数据库中最知名的选择之一。

对于模型,我们选择了Hugging Face库中的两个模型。第一个是dolly-v2–3b,另一个是flan-t5-large。值得注意的是,这不仅是两个不同的模型,而且还是为不同功能训练的。

T5是一个文本到文本生成模型系列,旨在根据它们训练的数据集生成文本。它们可以用于文本生成,但它们的响应可能不太有创意。

另一方面,Dolly是纯粹的文本生成系列。这些模型往往会产生更有创造性和广泛的响应。

明星库是LangChain,这是一个开源平台,可以利用大型语言模型的强大功能创建自然语言应用程序。它允许我们在这些模型和其他库或产品(如数据库或各种插件)之间链接输入和输出。

让我们从LangChain开始项目。

代码可在Kaggle的笔记本中找到。本文和笔记本是我在GitHub个人资料上提供的使用大型语言模型创建应用程序课程的一部分。

如果您不想错过任何课程或对现有内容的更新,最好关注该存储库。我将在完成后将新的课程发布在公共存储库中。

使用LangChain、VectorDB和HF查询您的文档

使用Kaggle Notebooks探索和运行机器学习代码 | 使用多个数据源的数据

www.kaggle.com

GitHub – peremartra/Large-Language-Model-Notebooks-Course

通过在GitHub上创建帐户为peremartra/Large-Language-Model-Notebooks-Course做出贡献。

github.com

安装和加载库。

如果您在个人环境中工作并已经测试了这些技术,您可能不需要安装任何东西。然而,如果您使用的是Kaggle或Colab,您将需要安装以下库:

  • langchain:这个革命性的库使得使用大型语言模型创建应用程序成为可能。
  • sentence_transformers:我们将需要生成要存储在向量数据库中的文本的嵌入,因此需要这个库。
  • chromadb:要使用的向量数据库。值得注意的是,ChromaDB以其用户友好的界面而脱颖而出。
!pip install chromadb!pip install langchain!pip install sentence_transformers

除了这些库之外,我们还会导入数据科学中使用最广泛的两个Python库:pandasnumpy

import numpy as np import pandas as pd

加载数据集。

如前所述,此笔记本已经准备好与两个不同的数据集一起使用。这些数据集与之前的RAG(检索增强生成)示例中使用的数据集相同。

RAG意味着使用大型语言模型对数据进行处理,通常被称为“查询您的文档”。

这两个数据集都是表格形式的,并包含与新闻相关的信息:

  1. 主题标记的新闻数据集。
  2. MIT AI新闻发布至2023年。

这两个数据集的内容相似,但列名和存储的信息不同。个人而言,我认为使用多个数据集可以提供很好的价值,可以通过不同的数据源验证和推广结果。

在完成笔记本后,探索第三个不同的数据集并复制其功能将会很有益。

由于我们在Kaggle上使用的资源有限,所以必须注意内存限制。因此,为了避免超过Kaggle的内存限制(如果您不使用GPU,则为30 GB),我们不会使用整个数据集。

使用数据集的一个较小的子集仍然可以让我们有效地探索和演示LangChain的功能,同时保持在资源限制范围内。

让我们来看一下topic-labeled-news-dataset的前两条记录。

在第一个数据集中,我们将使用title列作为我们的文档。虽然文本可能不是很长,但它是一个完美的例子。我们可以使用它来搜索文章数据库,并找到那些讨论特定主题的文章。

news = pd.read_csv('/kaggle/input/topic-labeled-news-dataset/labelled_newscatcher_dataset.csv', sep=';')MAX_NEWS = 1000DOCUMENT="title"TOPIC="topic"#news = pd.read_csv('/kaggle/input/bbc-news/bbc_news.csv')#MAX_NEWS = 500#DOCUMENT="description"#TOPIC="title"#因为它只是一个课程,我们选择News的一小部分。subset_news = news.head(MAX_NEWS)

我们创建了包含数据集中一部分新闻的DataFrame subset_news

要使用其中一个数据集,只需取消注释对应数据集的行。在每种情况下,我们调整要用作数据的列的名称和子集将包含的记录数。这种方法可以让我们轻松地在不同数据集之间进行切换。

从DataFrame生成文档。

为了创建文档,我们将使用LangChain中的一个加载器。在我们的示例中,我们将使用DataFrameLoader,但还有各种加载器可用于各种来源,如CSV、文本文件、HTML、JSON、PDF,甚至用于产品(如Confluence)的加载器。

from langchain.document_loaders import DataFrameLoaderfrom langchain.vectorstores import Chroma

一旦我们加载了库,我们需要创建加载器。为此,我们指定DataFrame和我们想要用作文档内容的列的名称。这些信息将传递给向量数据库ChromaDB,存储并在语言模型生成响应时使用。

df_loader = DataFrameLoader(subset_news, page_content_column=DOCUMENT)

要创建文档,我们只需调用加载器的load函数。

df_document = df_loader.load()
display(df_document)

让我们来看一下文档的内容:

[Document(page_content="A closer look at water-splitting's solar fuel potential", metadata={'topic': 'SCIENCE', 'link': 'https://www.eurekalert.org/pub_releases/2020-08/dbnl-acl080620.php', 'domain': 'eurekalert.org', 'published_date': '2020-08-06 13:59:45', 'lang': 'en'}), Document(page_content='An irresistible scent makes locusts swarm, study finds', metadata={'topic': 'SCIENCE', 'link': 'https://www.pulse.ng/news/world/an-irresistible-scent-makes-locusts-swarm-study-finds/jy784jw', 'domain': 'pulse.ng', 'published_date': '2020-08-12 15:14:19', 'lang': 'en'}),

正如我们所看到的,它创建了一个文档,其中每个页面对应于指定列的记录内容。此外,我们在“metadata”字段中找到其他数据,使用列名进行标记。

我鼓励您尝试使用其他数据集,并查看数据的外观。

创建嵌入。

首先,如果有必要,让我们了解一下嵌入是什么。它只是任何数据的数值表示。在我们的特定情况下,它将是要存储的文本的数值表示。

这种数值表示采用向量的形式。向量只是多维空间中一个点的表示。换句话说,我们不必在二维或三维平面上可视化点,因为我们习惯了。向量可以表示任意维数的点。

对我们来说,这可能看起来很复杂或难以想象,但从数学上讲,计算两个点之间的距离无论它们是在二维、三维还是任意维度中并没有太大区别。

这些向量使我们能够计算它们之间的差异或相似性,从而能够非常高效地搜索相似信息。

关键在于确定我们为每个单词分配哪些向量,因为我们希望具有相似含义的单词在距离上更接近于具有更不同含义的单词。Hugging Face库负责处理这个方面,所以我们不必太担心。我们只需要确保所有要存储的数据和要执行的查询的一致转换。

让我们导入一些库:

  1. CharacterTextSplitter:我们将使用这个库将信息分组成块。
  2. HuggingFaceEmbeddingsSentenceTransformerEmbedding:在笔记本中,我两者都使用过,并且没有发现它们之间有任何区别。这些库负责检索将执行数据嵌入的模型。
from langchain.text_splitter import <a></a><a>CharacterTextSplitter#from langchain.embeddings import HuggingFaceEmbeddings

没有一种百分之百正确的方式将文档分成块。关键考虑因素是较大的块将为模型提供更多上下文。然而,使用较大的块也会增加我们的向量存储的大小,这可能会占用较多的内存。

找到上下文大小和内存使用之间的平衡是优化应用程序性能的关键。

我决定使用块大小为250个字符,重叠为10个字符。这意味着一个块的最后10个字符将是下一个块的前10个字符。这是一个相对较小的块大小,但对于我们正在处理的信息类型来说绰绰有余。

text_splitter = CharacterTextSplitter(chunk_size=250, chunk_overlap=10)
texts = text_splitter.split_documents(df_document)

现在,我们可以使用文本创建嵌入。

from langchain.embeddings.sentence_transformer import SentenceTransformerEmbeddingsembedding_function = SentenceTransformerEmbeddings(model_name="all-MiniLM-L6-v2")#embedding_function = HuggingFaceEmbeddings(#    model_name="sentence-transformers/all-MiniLM-L6-v2"#)  

如您所见,我使用了SentenceTransformerEmbeddings而不是HuggingFaceEmbeddings。您可以通过修改注释的行轻松更改它。

使用这两个库,您可以调用相同的预训练模型来生成嵌入。我在两者中都使用了all-MiniLM-L6-v2。因此,虽然每个库生成的嵌入之间可能会有轻微差异,但它们将是微小的,并且不会对性能产生显著影响。

最初,SentenceTransformerEmbeddings专门用于转换句子,而HuggingFaceEmbeddings更通用,可以为段落或整个文档生成嵌入。

实际上,鉴于我们文档的性质,使用任一库时预计不会有任何差异。

有了生成的嵌入,我们可以创建索引

chromadb_index = Chroma.from_documents(    texts, embedding_function, persist_directory='./input')

这个索引是我们将用来提问的,并且被特别设计为高效!毕竟经过了这么多努力,我们最不希望的就是它变得缓慢和不精确 :-)。

让我们开始使用LangChain吧!

现在是有趣的部分:使用LangChain链接操作以创建我们使用大型语言模型的第一个小应用程序!

该应用程序非常简单,只包括两个步骤和两个组件。第一步将涉及一个检索器。该组件用于从我们存储在ChromaDB中的文档或提供的文本中检索信息。在我们的情况下,它将使用嵌入执行基于相似性的搜索以检索与用户查询相关的信息

第二个也是最后一个步骤将涉及我们的语言模型,它将接收检索器返回的信息。

因此,我们需要导入库来创建检索器和流水线。

from langchain.chains import RetrievalQAfrom langchain.llms import HuggingFacePipeline

现在,我们可以使用之前创建的嵌入索引来创建检索器。

retriever = chromadb_index.as_retriever()

我们已经完成了链或流水线的第一步。现在,让我们继续进行第二步:语言模型。

在笔记本中,我使用了Hugging Face提供的两个不同模型。

第一个模型是dolly-v2–3b,是Dolly系列中最小的模型。我个人非常喜欢这个模型。虽然它可能不像其他一些模型那样受欢迎,但它生成的回答要比GPT-2好得多,达到了与OpenAI的GPT-3.5相似的水平。该模型具有30亿个参数,接近我们可以在Kaggle上加载的内存限制。该模型经过了文本生成的训练,生成了精心制作的回答。

第二个模型来自T5系列。请注意,此模型特别设计用于文本到文本的生成,从而生成更简洁和简短的回答。

一定要至少尝试使用这两个模型,看看它们的表现如何。

model_id = "databricks/dolly-v2-3b" #我个人最喜欢的文本生成模型,用于测试task="text-generation"#model_id = "google/flan-t5-large" #不错的文本到文本生成模型#task="text2text-generation"

太棒了!我们已经有了创建流水线所需的一切!现在让我们来做吧!

hf_llm = HuggingFacePipeline.from_model_id(    model_id=model_id,    task=task,    model_kwargs={        "temperature": 0,        "max_length": 256    },)

让我们看看每个参数的含义:

  1. model_id:Hugging Face中模型的标识符。您可以从Hugging Face获取它,通常由模型名称后跟版本号组成。
  2. task:在这里,我们指定要使用模型的任务。某些模型被训练用于多个任务。您可以在模型的Hugging Face文档中找到特定模型支持的任务。
  3. model_kwargs:此参数允许我们指定特定于模型的其他参数。在这种情况下,我提供了温度(我们希望模型有多具有创造力)和响应的最大长度。

现在,我们需要使用模型和检索器来配置流水线。

document_qa = RetrievalQA.from_chain_type(    llm=hf_llm, chain_type="stuff", retriever=retriever)

在变量chain_type中,我们指定链条的功能,有四个选项:

  1. stuff:最简单的选项,它只是选择它认为合适的文档,并将它们用于传递给模型的提示。
  2. refine:它使用不同的文档对模型进行多次调用,尝试每次获得更精细的响应。它可能对模型进行大量调用,因此应谨慎使用。
  3. map reduce:它试图将所有文档压缩为一个文档,可能通过多次迭代实现。它可以压缩和合并文档,以适应发送给模型的提示。
  4. map re-rank:它为每个文档调用模型并对它们进行排序,最后返回最佳文档。与`refine`类似,根据预期的调用次数,它可能存在风险。

现在我们可以使用新创建的链条来提问问题,它们将考虑来自DataFrame的数据,这些数据现在是Vector数据库的一部分。

#新闻采集数据集的示例问题。response = document_qa.run("我可以买一台东芝笔记本电脑吗?")#BBC数据集的示例问题。#response = document_qa.run("谁将会见鲍里斯·约翰逊?")display(response)

所以,显而易见,所得到的答案将取决于所使用的数据集和模型。对于是否可以购买东芝笔记本电脑的问题,根据模型的不同,我们会得到两个非常不同的回答:

Dolly: “不,东芝将于2023年正式停止生产他们的笔记本电脑。传奇的东芝正式停止制造笔记本电脑。东芝在35年后正式关闭他们的笔记本电脑。东芝于2023年正式停止生产他们的笔记本电脑。”

T5: “不。”

正如您所看到的,每个模型都为响应添加了自己的个性!

结论 持续学习!

实际上,这比人们想象的要简单得多。现在比以前更容易,因为大语言模型的爆发以及像LangChain这样的工具的出现。

我们使用了一个向量数据库来存储之前加载到DataFrame中的数据。虽然我们也可以使用任何其他数据源。

我们将它们作为Hugging Face中可用的几个语言模型的输入,并观察到模型根据DataFrame中的信息提供了响应。

但不要止步于此,对笔记本进行自己的修改并解决可能出现的任何问题。一些想法包括:

  • 同时使用两个数据集,并最好搜索第三个数据集。更好的是,您是否认为可以将其调整为阅读您的简历?我相信只需进行一些微小的调整即可实现。
  • 尝试使用第三个Hugging Face模型。
  • 更改数据源。它可以是文本文件、Excel文件,甚至可以是像Confluence这样的文档工具。

有关大型语言模型的完整课程可在Github上找到。要获取有关新文章的更新,请考虑关注该存储库或给它点赞。 这样,您将在添加新内容时收到通知。

GitHub – peremartra/Large-Language-Model-Notebooks-Course

通过在GitHub上创建一个帐户来为peremartra/Large-Language-Model-Notebooks-Course做出贡献。

github.com

本文是我们探索大型语言模型的实际应用的系列文章之一。您可以在以下列表中找到其他文章:

Pere Martra

大型语言模型实践课程

查看列表3个故事

我经常写关于深度学习和机器学习的文章。 考虑 关注我在VoAGI上 以获取有关新文章的更新。 当然,欢迎您与我在LinkedIn上联系。