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

作者:来自 Elastic Amy Ghate, Rishikesh Radhakrishnan, Hemant Malik

使用非结构化和 Elasticsearch 向量数据库为 RAG 应用程序提取和搜索复杂的专有文档

在使信息可搜索之前解析文档是构建实际 RAG 应用程序的重要步骤。Unstructured.io 和 Elasticsearch 在此场景中有效地协同工作,为开发人员提供构建 RAG 应用程序的互补工具。

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

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

Unstructured 的强大之处在于模型可以识别文档的独特组件并将其提取到 “document elements - 文档元素” 中。非结构化数据还可以使用不同的策略(而不仅仅是字符数)对分区进行分块。这些 “智能分区和分块” 策略可以提高搜索相关性并减少 RAG 应用程序中的幻觉。

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

总体流程

1)在 Elastic 平台中部署 ELSER 模型,
3)创建一个摄取管道,该管道将为摄取的块创建嵌入。字段文本将存储分块文本,而 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"
          }
        ]
      }
    }
  ]
}

3)下一步是创建一个索引 unstructured-demo,其中包含 ELSER 嵌入的必要映射。我们还将把上一步中创建的管道附加到此索引。我们将允许所有其他字段进行动态映射。

PUT unstructured-demo
{
  "settings": {
    "default_pipeline": "chunks-to-elser"
  },
  "mappings": {
    "properties": {
      "text_embedding": {
        "type": "sparse_vector"
      },
      "text": {
        "type": "text"
      }
    }
  }
}

4)最后一步是使用 Elasticsearch 连接器运行 Unstructured 的代码示例来创建分区和块。按照说明安装依赖项。

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 中的分区函数(partitioning functions)从非结构化文档中提取结构化内容。partition 函数检测文档类型并自动确定适当的 partition 函数。如果用户知道他们的文件类型,他们也可以指定特定的分区函数。在分区步骤中,我们指示 Unstructured 通过传入 pdf_infer_table_structure=True 并将分区策略(partition strategy)设置为 hi_res 来推断表结构,从而自动识别文档的布局。你可以在此处了解各种非结构化分区策略。我们将 chunking strategy 设置为 by_title,它 “preserves section and page boundaries - 保留了章节和页面边界”。分块策略对 RAG 应用程序的性能和质量有重大影响。你可以在他们的论文《Chunking for Effective Retrieval Augmented Generation》中了解有关 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,这在 RAG 场景中很有用,因为你想要将段落的整个上下文传递给 LLM。如果你想知道哪些单个分区组成了一个块,你可以在 base-64 编码的 orig_elements 字段中找到它。在上面的示例中,我们使用了 Unstructured 的 API 服务。这些 API 服务可以以三种不同的方式使用:

  • Limited trial Unstructured API
  • SaaS Unstructured API
  • AWS/Azure Marketplace Unstructured API

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

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

结论

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

准备好自己尝试一下了吗?开始免费试用。
希望将 RAG 构建到你的应用程序中?想要尝试使用向量数据库的不同 LLMs?
在 Github 上查看我们针对 LangChain、Cohere 等的示例笔记本,并立即加入 Elasticsearch Relevance Engine 培训。

原文:Search complex documents using Unstructured.io and Elasticsearch vector database — Elastic Search Labs

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/798221.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Admin.NET源码学习(2:安装并运行前端)

根据Admin.NET的GitHub主页介绍&#xff0c;前端运行步骤需要运行pnpm命令。百度pnpm的话&#xff0c;需要支持npm相关的命令支持。   根据参考文献4&#xff0c;安装Node.js后会提供npm命令支持&#xff08;npm是Node.js的软件包管理器&#xff0c;用于安装、发布和共享Jav…

FreeRTOS 入门 知识

什么是FreeRTOS FreeRTOS 是一个轻量级的实时操作系统&#xff08;RTOS&#xff09;&#xff0c;由 Richard Barry 在 2003 年开发&#xff0c;并且由亚马逊的 FreeRTOS 项目&#xff08;一个由 Amazon Web Services (AWS) 支持的开源项目&#xff09;进一步推动和发展。FreeR…

顺序表算法 - 合并两个有序数组

88. 合并两个有序数组 - 力扣&#xff08;LeetCode&#xff09;https://leetcode.cn/problems/merge-sorted-array/description/思路: void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n) {int l1,l2,l3;l1 m-1;l2 n-1;l3 mn-1;//l1和l2大于…

DispatcherServlet懒加载带来的问题和思考

问题 DispatcherServlet的懒加载会导致在用户在进行第一次请求的时候会比正常慢很多&#xff0c;如果这个时候大量请求同时过来&#xff0c;那么阻塞和cpu的暴增就会显而易见。 背景 在回顾SpringMvc对servlet的增强的过程中&#xff0c;突然发现DispatcherServlet是懒加载的…

7.2 AQS原理

AQS 原理 概述 全称是 AbstractQueuedSynchronizer&#xff0c;是阻塞式锁和相关的同步器工具的框架。 特点&#xff1a; 用 state 属性来表示资源的状态&#xff08;分独占模式和共享模式&#xff09;&#xff0c;子类需要定义如何维护这个状态&#xff0c;控制如何获取锁和…

JAVA自定义注释

interface 声明 package test; public interface InProgress { } InProgress public void calculateInterest(float amount, float rate) { } 带成员 public interface TODO {String value(); } InProgress //只有成员变量名有value时&#xff0c;值有给value赋值时可以这…

redis源码分析之底层数据结构(一)-动态字符串sds

1.绪论 我们知道redis是由c语言实现的&#xff0c;c语言中是自带字符串的&#xff0c;但是为什么redis还要再实现自己的动态字符串呢&#xff0c;这种动态字符串的底层数据结构是怎样的呢?接下来我们带着这些问题来看一看redis中的动态字符串sds。 2.sds的组成 struct __at…

MySQL覆盖索引和索引跳跃扫描

最近在深入学习MySQL&#xff0c;在学习最左匹配原则的时候&#xff0c;遇到了一个有意思的事情。请听我细细道来。 我的MySQL版本为8.0.32 可以通过 show variables like version; 查看使用的版本。 准备工作&#xff1a; 先建表&#xff0c;SQL语句如下&#xff1a; c…

ARM学习(29)NXP 双coreMCU IMX1160学习----NorFlash 启动引脚选择

ARM学习&#xff08;28&#xff09;NXP 双coreMCU IMX1160学习----NorFlash 启动引脚选择 1、多种启动方式介绍 IMX1166 支持多组flexSPI 引脚启动&#xff0c;FlexSPI1以及FlexSPI2&#xff0c;通过boot cfg可以切换FlexSPI得实例。 每个实例又支持多组引脚&#xff0c;总共…

Linux系统的用户组管理和权限以及创建用户

1.Linux是多用户的操作系统&#xff0c;正如在Windows系统中可以进行用户账号的切换&#xff0c;Linux同样允许多用户操作。在Linux服务器环境中&#xff0c;通常由多名运维人员共同管理&#xff0c;而这些运维人员各自拥有不同的权限和级别。因此&#xff0c;我们可以根据每个…

LeetCode 3011.判断一个数组是否可以变为有序

注&#xff1a;这个题目有序的意思是“升序” 解法一&#xff1a;bubblesort O(nlogn) 核心思想&#xff1a;冒泡每次会将一个数归位到最后的位置上&#xff0c;所以我们如果碰到无法向右交换的数字&#xff0c;即可return false class Solution { public:// 返回一个十进制…

《昇思25天学习打卡营第2天|02快速入门》

课程目标 这节课准备再学习下训练模型的基本流程&#xff0c;因此还是选择快速入门课程。 整体流程 整体介绍下流程&#xff1a; 数据处理构建网络模型训练模型保存模型加载模型 思路是比较清晰的&#xff0c;看来文档写的是比较连贯合理的。 数据处理 看数据也是手写体数…

提高项目透明度:有效的跟踪软件

国内外主流的10款项目进度跟踪软件对比&#xff1a;PingCode、Worktile、Teambition、Tower、Asana、Trello、Jira、ClickUp、Notion、Liquid Planner。 在项目管理中&#xff0c;确保进度跟踪的准确性与效率是每位项目经理面临的主要挑战之一。选用合适的项目进度跟踪软件不仅…

800 元打造家庭版 SOC 安全运营中心

今天,我们开始一系列新的文章,将从独特而全面的角度探索网络安全世界,结合安全双方:红队和蓝队。 这种方法通常称为“紫队”,集成了进攻和防御技术,以提供对威胁和安全解决方案的全面了解。 在本系列的第一篇文章中,我们将指导您完成以 100 欧元约800元左右的预算创建…

Sentinel-1 Level 1数据处理的详细算法定义(三)

《Sentinel-1 Level 1数据处理的详细算法定义》文档定义和描述了Sentinel-1实现的Level 1处理算法和方程,以便生成Level 1产品。这些算法适用于Sentinel-1的Stripmap、Interferometric Wide-swath (IW)、Extra-wide-swath (EW)和Wave模式。 今天介绍的内容如下: Sentinel-1 L…

zookeeper的shell操作

一&#xff1a;启动拽库的shell命令行 zkCli.sh -server localhost:2181 退出&#xff1a;quit 二&#xff1a;查询所有的命令 help 三&#xff1a;查询对应的节点 --查询zk上的根节点 ls / ls /zookeeper 四&#xff1a;查询对应节点的节点信息&#xff08;节点的元数据&a…

idea启动ssm项目详细教程

前言 今天碰到一个ssm的上古项目&#xff0c;项目没有使用内置的tomcat作为服务器容器&#xff0c;这个时候就需要自己单独设置tomcat容器。这让我想起了我刚入行时被外置tomcat配置支配的恐惧。现在我打算记录一下配置的过程&#xff0c;希望对后面的小伙伴有所帮助吧。 要求…

React学习笔记02-----

一、React简介 想实现页面的局部刷新&#xff0c;而不是整个网页的刷新。AJAXDOM可以实现局部刷新 1.特点 &#xff08;1&#xff09;虚拟DOM 开发者通过React来操作原生DOM&#xff0c;从而构建页面。 React通过虚拟DOM来实现&#xff0c;可以解决DOM的兼容性问题&#x…

UNIAPP_ReferenceError: TextEncoder is not defined 解决

错误信息 1、安装text-decoding npm install text-decoding2、main.js import { TextEncoder, TextDecoder } from text-decoding global.TextEncoder TextEncoder global.TextDecoder TextDecoder