首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >使用 Unstructured.io 和 Elasticsearch 向量数据库搜索复杂文档

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

原创
作者头像
点火三周
发布于 2024-07-12 14:12:30
发布于 2024-07-12 14:12:30
89002
代码可运行
举报
文章被收录于专栏:Elastic Stack专栏Elastic Stack专栏
运行总次数:2
代码可运行

在构建真实的 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 模型。
代码语言:json
AI代码解释
复制
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 嵌入创建必要的映射。我们还将我们在上一步中创建的管道附加到该索引上。其他所有字段都将动态映射。
代码语言:json
AI代码解释
复制
PUT unstructured-demo
{
  "settings": {
    "default_pipeline": "chunks-to-elser"
  },
  "mappings": {
    "properties": {
      "text_embedding": {
        "type": "sparse_vector"
      },
      "text": {
        "type": "text"
      }
    }
  }
}
  1. 最后一步是使用 Unstructured 的代码示例,利用 Elasticsearch 连接器 来创建分区和分块。请按照 安装依赖项的说明操作。
代码语言:python
代码运行次数:2
运行
AI代码解释
复制
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 服务)。我们设置用户名和密码,并设置要写入的索引:

代码语言:python
代码运行次数:0
运行
AI代码解释
复制
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 的 有效检索增强生成分块论文中了解更多。

代码语言:python
代码运行次数:0
运行
AI代码解释
复制
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 服务可以通过三种不同方式使用:

  • 有限试用的 Unstructured API
  • SaaS Unstructured API
  • AWS/Azure Marketplace Unstructured API

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

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

结论

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

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
【Vue原理】Watch - 源码版
没错,当你调用 Vue 创建实例过程中,会去处理各种选项,其中包括处理 watch
神仙朱
2019/08/02
7880
【Vue原理】Watch - 源码版
手摸手带你理解Vue的Computed原理
computed 在 Vue 中是很常用的属性配置,它能够随着依赖属性的变化而变化,为我们带来很大便利。那么本文就来带大家全面理解 computed 的内部原理以及工作流程。
WahFung
2020/08/24
1.3K0
nextTick的理解和作用
最近使用Vue全家桶做后台系统的时候,遇到了一个很奇葩的问题:有一个输入框只允许输入数字,当输入其它类型的数据时,输入的内容会被重置为null。为了实现这一功能,使用了一个父组件和子组件。为了方便陈述,这里将业务场景简化,具体代码如下:
用户9253515
2021/12/16
8260
Vue响应式依赖收集原理分析-vue高级必备
在 Vue 的初始化阶段,_init 方法执行的时候,会执行 initState(vm) ,它的定义在 src/core/instance/state.js 中。在初始化 data 和 props option 时我们注意 initProps 和 initData 方法中都调用了 observe 方法。通过 observe (value),就可以将数据变成响应式。
yyds2026
2022/10/26
6150
Vue2剥丝抽茧-响应式系统之watch2
Vue2 源码从零详解系列文章, 还没有看过的同学可能需要看一下之前的,vue.windliang.wang/
windliang
2022/08/20
2880
Vue2剥丝抽茧-响应式系统之watch2
手摸手带你理解Vue响应式原理
响应式原理作为 Vue 的核心,使用数据劫持实现数据驱动视图。在面试中是经常考查的知识点,也是面试加分项。
WahFung
2020/08/24
9910
石桥码农:20 vue计算属性和侦听器
在template里的插值表达式,如果太长,会让模板代码变得难于维护;如果有多处用到了同样的插值表达式,也不便于复用和修改。例如,这样的一个插值表达式:
LIYI
2020/02/13
7290
石桥码农:20 vue计算属性和侦听器
Vue.js源码逐行代码注解src下core下observer
达达前端
2023/10/08
4330
vue源码分析-响应式系统工作原理
上一章,我们讲到了Vue初始化做的一些操作,那么我们这一章来讲一个Vue核心概念响应式系统。
yyzzabc123
2022/10/19
5220
vue源码分析-响应式系统工作原理_2023-03-01
上一章,我们讲到了Vue初始化做的一些操作,那么我们这一章来讲一个Vue核心概念响应式系统。
用户10377014
2023/03/01
4890
Vue源码解读之InitState
看上面代码,先声明了一个_watchers的空数组;然后依次判断传递进来的options是否包含系列参数;依次执行initProps、initMethods、initData、initComputed、initWatch。
yyzzabc123
2022/09/28
3340
Vue2剥丝抽茧-响应式系统之watch
Vue2 源码从零详解系列文章, 还没有看过的同学可能需要看一下之前的,vue.windliang.wang/
windliang
2022/08/20
4240
Vue2剥丝抽茧-响应式系统之watch
4. 「vue@2.6.11 源码分析」new Vue() 整体流程和组件渲染之前的准备工作
将组件渲染渲染分为两大步骤:组件信息(事件、方法等等)的初始化,以及组件的渲染。 虽然源码中 $mount方法调用放在了_init方法上,但是感觉拿出来好些,毕竟是两个大的步骤。
tinyant
2023/02/24
7510
4.  「vue@2.6.11 源码分析」new Vue() 整体流程和组件渲染之前的准备工作
请你挑战一下这几道nextTick面试题
Vue大家再熟悉不过了,Vue的this.$nextTick大家也再熟悉不过了,今天我们就来看看自创的nextTick相关的几道面试题,看看你是否真正理解Vue的nextTick。
kai666666
2024/07/11
1570
[咖聊] 您瞅啥?瞅 reactive
props、computed、watch 那些我们放到后面再深究,先从主流程看起。聚焦到 data 部分:
码农小余
2022/06/16
5760
[咖聊]  您瞅啥?瞅 reactive
vue源码分析-响应式系统(二)
在构建简易式响应式系统的时候,我们引出了几个重要的概念,他们都是响应式原理设计的核心,我们先简单回顾一下:
yyzzabc123
2022/10/17
3630
Vue2剥丝抽茧-响应式系统之computed
Vue2 源码从零详解系列文章, 还没有看过的同学可能需要看一下之前的,vue.windliang.wang/
windliang
2022/08/20
4190
Vue2剥丝抽茧-响应式系统之computed
顺藤摸瓜:用单元测试读懂 vue3 watch 函数
在 Vue 3.x 的 Composition API 中,我们可以用近似 React Hooks 的方式组织代码的复用;ref/reactive/computed 等好用的响应式 API 函数可以摆脱组件的绑定,抽离出来被随处使用了。
江米小枣
2020/07/02
2.1K0
Vue——initState【十】
前面我们简单的了解了 vue 初始化时的一些大概的流程,这里我们详细的了解下具体的内容;
思索
2024/08/15
1030
Vue 高频原理面试篇+详细解答
原文首地址 掘金 三连哦 更多好文 github 大家好,我是林一一,这是一篇关于 vue 的原理面试题,如果能够完全弄懂相信对大家很有帮助。 面试题篇 1.老生常谈之, MPA/SPA 的理解,优缺点是什么? MPA 多页面应用。 构成:有多个页面 html 构成, 跳转方式:页面的跳转是从一个页面到另一个页面 刷新的方式:全页面刷新 页面数据跳转:依赖 URL/cookie/localStorage 跳转后的资源 会重新加载 优点:对 SEO 比较友好,开发难度低一点。 SPA单页面应用 页面组成:
前端小tips
2021/12/09
7590
Vue 高频原理面试篇+详细解答
推荐阅读
相关推荐
【Vue原理】Watch - 源码版
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验