使用 Unstructured.io 和 Elasticsearch 向量数据库搜索复杂文档

了解如何使用 Unstructured.io 和 Elasticsearch 摄取和搜索复杂的专有文档,以用于 RAG 应用程序。

在构建真实的 RAG 应用程序中,解析文档以使其信息可搜索是一个重要的步骤。Unstructured.io 和 Elasticsearch 在这种情况下有效地协同工作,为开发人员提供了互补的工具来构建 RAG 应用程序。

Unstructured.io 提供了一套工具,用于提取、清理和转换不同格式和不同内容源的文档。将文档添加到 Elasticsearch 索引后,开发人员可以选择许多 Elastic 功能,包括聚合、过滤器、RBAC 工具以及 BM25 或向量搜索功能,以将复杂的业务逻辑实现到 RAG 应用程序中。

在本博文中,我们将研究一个相当常见的用例,即 解析和摄取包含文本、表格和图像的 PDF 文档。我们将使用 Elastic 的 ELSER 模型创建稀疏向量嵌入,然后使用 Elasticsearch 作为向量数据库来存储和搜索嵌入。

Unstructured 的强大功能在于可以识别文档的唯一组件并将其提取到“文档元素”中的模型。Unstructured 还能够使用不同的策略而不是仅按字符数量来对分区进行分块。这些“智能分区和分块”策略可以提高搜索相关性并减少 RAG 应用程序中的幻觉。

解析数据后,我们将其作为向量嵌入存储在 Elasticsearch 向量数据库中并运行搜索操作。我们使用 Elasticsearch 向量数据库连接器将此数据发送到 Elastic。我们还在流程中附加了一个管道,以便在摄取时创建 ELSER(用于语义搜索的开箱即用的稀疏编码器模型)嵌入。

如何解析和搜索非结构化文档

  1. 在 Elastic 平台中部署 ELSER 模型,
  2. 创建一个 摄取管道,它将为摄取的分块创建嵌入。字段 text 将存储分块的文本,text_embeddings 将存储嵌入。我们将使用 ELSER v2 模型。
PUT _ingest/pipeline/chunks-to-elser
{
  "processors": [
    {
      "inference": {
        "model_id": ".elser_model_2_linux-x86_64",
        "input_output": [
          {
            "input_field": "text",
            "output_field": "text_embedding"
          }
        ]
      }
    }
  ]
}
  1. 下一步是创建一个索引 unstructured-demo,其中包含 ELSER 嵌入所需的映射。我们还将把我们在上一步中创建的管道附加到此索引。我们将允许所有其他字段进行动态映射。
PUT unstructured-demo
{
  "settings": {
    "default_pipeline": "chunks-to-elser"
  },
  "mappings": {
    "properties": {
      "text_embedding": {
        "type": "sparse_vector"
      },
      "text": {
        "type": "text"
      }
    }
  }
}
  1. 最后一步是运行 Unstructured 的代码示例,使用 Elasticsearch 连接器 来创建分区和分块。按照 安装依赖项的说明 进行操作。
import os

from unstructured.ingest.connector.elasticsearch import (
    ElasticsearchAccessConfig,
    ElasticsearchWriteConfig,
    SimpleElasticsearchConfig,
)
from unstructured.ingest.connector.local import SimpleLocalConfig
from unstructured.ingest.interfaces import (
    ChunkingConfig,
    PartitionConfig,
    ProcessorConfig,
    ReadConfig,
)
from unstructured.ingest.runner import LocalRunner
from unstructured.ingest.runner.writers.base_writer import Writer
from unstructured.ingest.runner.writers.elasticsearch import (
    ElasticsearchWriter,
)

我们将主机设置为 Elastic Cloud(Elasticsearch 服务)。我们设置用户名和密码,并设置我们要写入的索引

def get_writer() -> Writer:
    return ElasticsearchWriter(
        connector_config=SimpleElasticsearchConfig(
            access_config=ElasticsearchAccessConfig(
                hosts="https://unstructured-demo.es.us-central1.gcp.cloud.es.io",
                username="elastic",
                password=<insert password>
            ),
            index_name="unstructured-demo",
        ),
        write_config=ElasticsearchWriteConfig(
            batch_size_bytes=15_000_000,
            num_processes=2,
        ),
    )

对于下一步,注册 获取 Unstructured API 端点和密钥。Unstructured 中的分区函数从非结构化文档中提取结构化内容。partition 函数检测文档类型并自动确定适当的分区函数。如果用户知道其文件类型,他们还可以指定特定的分区函数。在分区步骤中,我们指示 Unstructured 通过传入 pdf_infer_table_structure=True 并将分区策略设置为 hi_res 来推断表结构,从而自动识别文档的布局。您可以在此处了解各种 Unstructured 分区策略。我们将 分块策略 设置为 by_title,它“保留节和页面边界”。分块策略对 RAG 应用程序的性能和质量有重大影响。您可以在其 用于有效检索增强生成的分块论文 中了解更多关于 Unstructured 在这方面的工作。

writer = get_writer()
runner = LocalRunner(
        processor_config=ProcessorConfig(
            verbose=True,
            output_dir="local-output-to-elasticsearch",
            num_processes=2,
        ),
        connector_config=SimpleLocalConfig(
            input_path=<path to PDF>,
        ),
        read_config=ReadConfig(),
        partition_config=PartitionConfig(pdf_infer_table_structure=True,strategy='hi_res',partition_by_api=True, partition_endpoint=<your partition endpoint>', api_key=<your api key>),
        chunking_config=ChunkingConfig(chunk_elements=True, max_characters=500, chunking_strategy="by_title"),
        writer=writer,
        writer_kwargs={},
    )
runner.run()

在 Elasticsearch 向量数据库中的结果文档中,您将看到由 Unstructured API 生成的某些有趣的元数据。如果元素是表格,您将看到表格的 HTML 结构以及有关其外观的信息。如果是文本块并且是先前块的延续,您将看到 is_continuation,这在您希望将段落的整个上下文传递给 LLM 的 RAG 场景中很有价值。如果您想知道哪些单独的分区构成一个块,您可以在 base-64 编码的 orig_elements 字段中找到它。在上面的示例中,我们使用了 Unstructured 的 API 服务。这些 API 服务可以通过三种不同的方式使用

  • Unstructured API 的有限试用版
  • Unstructured API 的 SaaS 版本
  • AWS/Azure 市场上的 Unstructured API

试用版提供的处理能力上限为 1000 页,您的文档可用于专有模式的训练和评估目的。对于快速原型设计,您还可以查看 Unstructured 的开源 版本。非结构化库为您提供了使用其 Python 安装程序运行的选项。如果您想避免处理多个依赖项,您可以使用捆绑了所有必需库的 Docker 容器。Unstructured API 与开源版本相比,提供了以下其他功能

  • 显着提高了文档和表格提取的性能,并具有高级分块和改进的转换管道
  • 访问最新的视觉转换器模型和企业级功能,例如安全性、SOC2 合规性、IAM(身份验证和身份管理)

结论

有效的文档解析是构建有效的 RAG 解决方案的重要步骤。Unstructured 将原始文档转换为 LLM 可以理解的数据的方法,加上 Elastic 作为向量数据库和搜索平台的优势,将加速您构建 AI 的旅程。搜索愉快!

Elasticsearch 与行业领先的 Gen AI 工具和提供商具有原生集成。查看我们关于超越 RAG 基础知识的网络研讨会 Beyond RAG Basics,或构建生产就绪型应用程序 Elastic 向量数据库

要为您的用例构建最佳搜索解决方案,请开始 免费云试用 或立即在您的 本地机器 上试用 Elastic。

准备好构建最先进的搜索体验了吗?

足够先进的搜索并非一人之力所能完成。Elasticsearch 由数据科学家、ML Ops 工程师、软件工程师等等众多同样热爱搜索的人员提供支持,他们与您一样对搜索充满热情。让我们携手合作,构建能够为您提供所需结果的梦幻搜索体验。

亲自试一试