• 文档
  • 面向初学者的数据摄取

data-ingestion-beginners-7

使用 LangChain 将 S3 数据发送到 Qdrant 向量存储

时长:30 分钟级别:初学者

将数据摄取到向量存储中对于构建高效的搜索和检索算法至关重要,特别是因为近 80% 的数据是非结构化的,缺乏任何预定义格式。

在本教程中,我们将创建一个简化的数据摄取管道,直接从 AWS S3 中拉取数据并将其馈送到 Qdrant 中。我们将深入探讨向量嵌入,将非结构化数据转换为允许您进行语义搜索的格式。准备好发现新的方法来揭示非结构化数据中隐藏的见解!

摄取工作流程架构

在此工作流程中,我们将使用云存储、自然语言处理 (NLP) 工具和嵌入技术设置强大的文档摄取和分析管道。首先,在 S3 存储桶中处理原始数据,然后使用 LangChain对其进行预处理,应用文本和图像的嵌入 API,并将结果存储在 Qdrant 中——一个针对相似性搜索优化的向量数据库。

图 1:数据摄取工作流程架构 data-ingestion-beginners-2.png

data-ingestion-beginners-5

让我们分解一下此工作流程的每个组件

  • S3 存储桶:这是我们的起点——一个集中式、可扩展的存储解决方案,适用于各种文件类型,如 PDF、图像和文本。
  • LangChain:LangChain 作为管道的协调器,负责提取、预处理和管理数据流以生成嵌入。它简化了 PDF 的处理,因此您无需在此处担心应用 OCR(光学字符识别)。
  • Qdrant:作为您的向量数据库,Qdrant 存储嵌入及其负载 (payloads),从而可以在所有内容类型上实现高效的相似性搜索和检索。

先决条件

data-ingestion-beginners-11

在本节中,您将获得一个从 S3 存储桶中摄取数据的分步指南。但在深入之前,请确保您已设置所有先决条件

示例数据我们将使用一个示例数据集,其中每个文件夹都包含文本格式的产品评论以及相应的图像。
AWS 账户一个活跃的AWS 账户,并有权访问 S3 服务。
Qdrant Cloud一个Qdrant Cloud 账户,并有权访问用于管理集合和运行查询的 WebUI。
LangChain您将使用这个流行的框架将所有内容联系起来。

支持的文档类型

用于摄取的文档可以是各种类型,如 PDF、文本文件或图像。我们将组织一个带有文件夹的结构化 S3 存储桶,其中包含支持的文档类型,用于测试和实验。

Python 环境

确保您有一个安装了以下库的 Python 环境(Python 3.9 或更高版本)

boto3
langchain-community
langchain
python-dotenv
unstructured
unstructured[pdf]
qdrant_client
fastembed

访问密钥:将您的 AWS 访问密钥、S3 密钥和 Qdrant API 密钥存储在 .env 文件中以便于访问。这是一个示例 .env 文件。

ACCESS_KEY = ""
SECRET_ACCESS_KEY = ""
QDRANT_KEY = ""

步骤 1:从 S3 摄取数据

data-ingestion-beginners-9.png

LangChain 框架使得从 AWS S3 等存储服务中摄取数据变得容易,它内置支持加载 PDF、图像和文本文件等格式的文档。

要将 LangChain 与 S3 连接,您将使用 S3DirectoryLoader,它允许您直接从 S3 存储桶将文件加载到 LangChain 的管道中。

示例:配置 LangChain 从 S3 加载文件

以下是如何设置 LangChain 从 S3 存储桶摄取数据

from langchain_community.document_loaders import S3DirectoryLoader

# Initialize the S3 document loader
loader = S3DirectoryLoader(
   "product-dataset",  # S3 bucket name
   "p_1", #S3 Folder name containing the data for the first product
   aws_access_key_id=aws_access_key_id,  # AWS Access Key
   aws_secret_access_key=aws_secret_access_key  # AWS Secret Access Key
)

# Load documents from the specified S3 bucket
docs = loader.load()

步骤 2:将文档转换为嵌入

嵌入 (Embeddings) 是这里的秘密武器——它们是数据的数值表示(如文本、图像或音频),以易于比较的形式捕获“含义”。通过将文本和图像转换为嵌入,您将能够快速高效地执行相似性搜索。将嵌入视为在 Qdrant 中存储和检索数据中有意义见解的桥梁。

我们将用于生成嵌入的模型

为了启动流程,我们将使用两个强大的模型

  1. sentence-transformers/all-MiniLM-L6-v2 嵌入用于转换文本数据。
  2. CLIP(对比语言-图像预训练)用于图像数据。

文档处理函数

data-ingestion-beginners-8.png

接下来,我们将定义两个函数 — process_textprocess_image,以处理文档管道中的不同文件类型。process_text 函数提取并返回基于文本的文档的原始内容,而 process_image 从 S3 源检索图像并将其加载到内存中。

from PIL import Image

def process_text(doc):
    source = doc.metadata['source']  # Extract document source (e.g., S3 URL)

    text = doc.page_content  # Extract the content from the text file
    print(f"Processing text from {source}")
    return source, text

def process_image(doc):
    source = doc.metadata['source']  # Extract document source (e.g., S3 URL)
    print(f"Processing image from {source}")

    bucket_name, object_key = parse_s3_url(source)  # Parse the S3 URL
    response = s3.get_object(Bucket=bucket_name, Key=object_key)  # Fetch image from S3
    img_bytes = response['Body'].read()

    img = Image.open(io.BytesIO(img_bytes))
    return source, img

文档处理的辅助函数

为了从 S3 检索图像,辅助函数 parse_s3_url 将 S3 URL 分解为其存储桶和关键组件。这对于从 S3 存储中获取图像至关重要。

def parse_s3_url(s3_url):
    parts = s3_url.replace("s3://", "").split("/", 1)
    bucket_name = parts[0]
    object_key = parts[1]
    return bucket_name, object_key

步骤 3:将嵌入加载到 Qdrant 中

data-ingestion-beginners-10

现在您的文档已处理并转换为嵌入,下一步是将这些嵌入加载到 Qdrant 中。

在 Qdrant 中创建集合

在 Qdrant 中,数据按集合组织,每个集合代表一组嵌入(或点)及其关联的元数据(负载)。要存储之前生成的嵌入,您首先需要创建一个集合。

以下是如何在 Qdrant 中创建集合来存储文本和图像嵌入

def create_collection(collection_name):
    qdrant_client.create_collection(
        collection_name,
        vectors_config={
            "text_embedding": models.VectorParams(
                size=384,  # Dimension of text embeddings
                distance=models.Distance.COSINE,  # Cosine similarity is used for comparison
            ),
            "image_embedding": models.VectorParams(
                size=512,  # Dimension of image embeddings
                distance=models.Distance.COSINE,  # Cosine similarity is used for comparison
            ),
        },
    )

create_collection("products-data")

此函数创建了一个用于存储文本(384 维)和图像(512 维)嵌入的集合,使用余弦相似度比较集合中的嵌入。

设置好集合后,您可以将嵌入加载到 Qdrant 中。这涉及将嵌入及其关联的元数据(负载)插入(或更新)到指定的集合中。

以下是将嵌入加载到 Qdrant 中的代码

def ingest_data(points):
    operation_info = qdrant_client.upsert(
        collection_name="products-data",  # Collection where data is being inserted
        points=points
    )
    return operation_info

摄取说明

  1. 更新或插入数据点:qdrant_client 上的 upsert 方法将每个 PointStruct 插入到指定的集合中。如果具有相同 ID 的点已存在,它将使用新值进行更新。
  2. 操作信息:该函数返回 operation_info,其中包含有关 upsert 操作的详细信息,例如成功状态或任何潜在错误。

运行摄取代码

以下是如何调用函数并摄取数据

from qdrant_client import models

if __name__ == "__main__":
    collection_name = "products-data"
    create_collection(collection_name)
    for i in range(1,6): # Five documents
        folder = f"p_{i}"
        loader = S3DirectoryLoader(
            "product-dataset",
            folder,
            aws_access_key_id=aws_access_key_id,
            aws_secret_access_key=aws_secret_access_key
        )
        docs = loader.load()
        points, text_review, product_image = [], "", ""
        for idx, doc in enumerate(docs):
            source = doc.metadata['source']
            if source.endswith(".txt") or source.endswith(".pdf"):
                _text_review_source, text_review = process_text(doc)
            elif source.endswith(".png"):
                product_image_source, product_image = process_image(doc)
        if text_review:
            point = models.PointStruct(
                id=idx,  # Unique identifier for each point
                vector={
                    "text_embedding": models.Document(
                        text=text_review, model="sentence-transformers/all-MiniLM-L6-v2"
                    ),
                    "image_embedding": models.Image(
                        image=product_image, model="Qdrant/clip-ViT-B-32-vision"
                    ),
                },
                payload={"review": text_review, "product_image": product_image_source},
            )
            points.append(point)
    operation_info = ingest_data(points)
    print(operation_info)

PointStruct 通过以下关键参数实例化

  • id:每个嵌入的唯一标识符,通常是一个增量索引。

  • vector:一个字典,包含用于嵌入的文本和图像输入。qdrant-client 在底层使用 FastEmbed 来自动在本地从这些输入生成向量表示。

  • payload:一个字典,存储附加元数据,如产品评论和图像引用,这对于搜索期间的检索和上下文非常宝贵。

该代码动态加载 S3 存储桶中的文件夹,分别处理文本和图像文件,并将其嵌入及关联数据存储在专门的列表中。然后为每个数据条目创建一个 PointStruct,并调用摄取函数将其加载到 Qdrant 中。

探索 Qdrant WebUI 控制面板

将嵌入加载到 Qdrant 后,您可以使用 WebUI 控制面板可视化和管理您的集合。该控制面板提供了一个清晰、结构化的界面,用于查看集合及其数据。让我们在下一节中仔细看看。

步骤 4:在 Qdrant WebUI 中可视化数据

要开始在 Qdrant WebUI 中可视化数据,请前往概览部分,然后选择访问数据库

图 2:从 Qdrant UI 访问数据库 data-ingestion-beginners-2.png

出现提示时,输入您的 API 密钥。进入后,您将能够查看您的集合和相应的数据点。您应该会看到您的集合显示如下

图 3:Qdrant 中的 product-data 集合 data-ingestion-beginners-4.png

以下是摄入到 Qdrant 中的最新点

图 4:添加到 product-data 集合的最新点 data-ingestion-beginners-6.png

Qdrant WebUI 的搜索功能允许您在您的集合中执行向量搜索。通过应用过滤器和参数的选项,检索相关嵌入和探索数据中的关系变得容易。要开始,请转到左侧面板中的控制台,您可以在其中创建查询

图 5:Qdrant 控制台概览 data-ingestion-beginners-1.png

第一个查询检索所有集合,第二个从 product-data 集合中获取点,第三个执行一个示例查询。这展示了在 Qdrant UI 中与数据交互是多么直接。

现在,让我们使用一个查询从数据库中检索一些文档!

图 6:查询 Qdrant 客户端以检索相关文档 data-ingestion-beginners-3.png

在这个示例中,我们查询了设计得到改进的手机。然后,我们使用 OpenAI 将文本转换为向量,并检索到了一条相关的手机评论,其中强调了设计改进。

结论

在本指南中,我们设置了一个 S3 存储桶,摄取了各种数据类型,并将嵌入存储在 Qdrant 中。使用 LangChain,我们动态处理了文本和图像文件,使得处理每种文件类型变得容易。

现在轮到您了。尝试使用不同的数据类型(例如视频)进行实验,并探索 Qdrant 的高级功能以增强您的应用程序。要开始,请立即注册 Qdrant。

data-ingestion-beginners-12

此页面有帮助吗?

感谢您的反馈!🙏

很抱歉听到此消息。😔 您可以在 GitHub 上编辑此页面,或创建一个 GitHub 问题。