使用 Unstructured.io 与 Elasticsearch 向量数据库:高效搜索复杂文档的新方案

适合从事智能文档分析、法律科技、金融报告处理、企业知识搜索等行业开发者,构建能处理 PDF、Word、HTML、邮件等复杂文档的新一代搜索系统。

目录

  1. 为什么需要处理复杂文档?
  2. Unstructured.io 简介与优势
  3. Elasticsearch 向量数据库简介
  4. 整体架构图解:复杂文档 → 搜索引擎
  5. 文档处理流程与向量生成
  6. Elasticsearch 向量索引配置与搜索
  7. 完整实战代码示例:从文档到搜索结果
  8. 常见问题与性能优化
  9. 总结与推荐实践

一、为什么需要处理复杂文档?

企业中存在大量结构不清晰、跨格式的文档,如:

  • 合同(PDF、DOCX)
  • 技术手册(HTML、PPT)
  • 邮件(.eml)
  • 扫描件(OCR图像)

传统全文检索系统的难点:

  • 格式繁多,解析复杂
  • 内容结构嵌套,无法按段搜索
  • 用户问题常以自然语言提出,需要语义匹配

因此,需要:

  • 统一抽取内容
  • 按段生成向量
  • 在向量数据库中进行语义检索

二、Unstructured.io 简介与优势

Unstructured.io 是一个文档结构化开源工具,支持多种格式统一提取。

支持格式

类型示例
文档PDF, DOCX, PPTX
网页HTML
邮件.eml, .msg
图像PNG, JPG(带OCR)

输出格式

每段内容被提取为 JSON 对象,附带元信息(位置、页码、类型等):

{
  "type": "NarrativeText",
  "text": "本合同适用于...",
  "metadata": {
    "page_number": 3,
    "element_id": "uuid-1234"
  }
}

特点

  • 基于分段(chunk)思想提取内容
  • 自动识别结构:标题、表格、图像、正文等
  • 可用于向量搜索预处理

三、Elasticsearch 向量数据库简介

Elasticsearch 自 8.x 起原生支持向量字段,支持:

  • 精确 kNN 与近似 kNN(HNSW)
  • 向量维度最大 2048
  • dense_vector 字段 + knn 查询

常配合 Embedding 模型实现语义搜索:

  • 文本 → 向量(通过模型)
  • 向量 → Elasticsearch 检索

四、整体架构图解(文字描述)

       +------------------+
       |  PDF/DOCX 文件等  |
       +--------+---------+
                ↓
       +------------------+
       |  Unstructured.io  |  ← 文档结构提取 & 分段
       +--------+---------+
                ↓
       +------------------+
       |   Embedding 模型  |  ← 将段落转为向量(如 BGE/MPNet)
       +--------+---------+
                ↓
       +------------------+
       | Elasticsearch 向量索引 |
       +------------------+
                ↓
       +------------------+
       | 自然语言查询 → 搜索 |
       +------------------+

五、文档处理流程与向量生成

5.1 使用 unstructured 提取文档结构

安装:

pip install unstructured

解析 PDF 示例:

from unstructured.partition.pdf import partition_pdf

elements = partition_pdf("contract.pdf")
for el in elements:
    print(el.text, el.metadata.page_number)

5.2 使用嵌入模型转向量

安装 HuggingFace 模型:

pip install sentence-transformers

示例:

from sentence_transformers import SentenceTransformer

model = SentenceTransformer("BAAI/bge-base-zh")
vectors = [model.encode(el.text) for el in elements if el.text.strip()]

六、Elasticsearch 向量索引配置与搜索

6.1 映射配置

PUT /document_index
{
  "mappings": {
    "properties": {
      "text": { "type": "text" },
      "embedding": {
        "type": "dense_vector",
        "dims": 768,
        "index": true,
        "similarity": "cosine",
        "index_options": {
          "type": "hnsw",
          "m": 16,
          "ef_construction": 128
        }
      },
      "page": { "type": "integer" },
      "file_id": { "type": "keyword" }
    }
  }
}

6.2 向量写入示例

from elasticsearch import Elasticsearch

es = Elasticsearch()

for i, el in enumerate(elements):
    if el.text.strip():
        doc = {
            "text": el.text,
            "embedding": vectors[i],
            "page": el.metadata.page_number,
            "file_id": "contract_2025"
        }
        es.index(index="document_index", document=doc)

七、完整实战代码流程(简化版)

from unstructured.partition.pdf import partition_pdf
from sentence_transformers import SentenceTransformer
from elasticsearch import Elasticsearch

# 文档提取
elements = partition_pdf("contract.pdf")

# 文本向量化
model = SentenceTransformer("BAAI/bge-base-zh")
texts = [el.text for el in elements if el.text.strip()]
vectors = model.encode(texts)

# 写入 Elasticsearch
es = Elasticsearch()

for i, el in enumerate(elements):
    if el.text.strip():
        es.index(index="document_index", document={
            "text": el.text,
            "embedding": vectors[i],
            "page": el.metadata.page_number,
            "file_id": "contract_2025"
        })

八、自然语言搜索示例

用户输入:“合同中关于违约责任的条款是什么?”

搜索代码

query = "违约责任条款"
query_vector = model.encode(query)

resp = es.search(index="document_index", knn={
    "field": "embedding",
    "query_vector": query_vector.tolist(),
    "k": 5,
    "num_candidates": 100
})

for hit in resp["hits"]["hits"]:
    print(hit["_score"], hit["_source"]["text"])

九、常见问题与优化建议

问题原因解决方式
查询不准向量召回数过低调大 num_candidates
PDF 无法读取结构PDF 不规范使用 pdfplumber 替代解析
写入慢向量维度大 + 网络延迟批量 bulk 写入
查询慢dense_vector 无索引设置 index: true 并使用 HNSW

十、总结与推荐实践

模块推荐工具/配置
文档解析unstructured
文本嵌入BAAI/bge-base-zh, sentence-transformers
向量搜索Elasticsearch 8.x + HNSW
查询接口REST API / LangChain 接入
扩展能力可集成 OCR、表格结构提取等模块

评论已关闭

推荐阅读

AIGC实战——Transformer模型
2024年12月01日
Socket TCP 和 UDP 编程基础(Python)
2024年11月30日
python , tcp , udp
如何使用 ChatGPT 进行学术润色?你需要这些指令
2024年12月01日
AI
最新 Python 调用 OpenAi 详细教程实现问答、图像合成、图像理解、语音合成、语音识别(详细教程)
2024年11月24日
ChatGPT 和 DALL·E 2 配合生成故事绘本
2024年12月01日
omegaconf,一个超强的 Python 库!
2024年11月24日
【视觉AIGC识别】误差特征、人脸伪造检测、其他类型假图检测
2024年12月01日
[超级详细]如何在深度学习训练模型过程中使用 GPU 加速
2024年11月29日
Python 物理引擎pymunk最完整教程
2024年11月27日
MediaPipe 人体姿态与手指关键点检测教程
2024年11月27日
深入了解 Taipy:Python 打造 Web 应用的全面教程
2024年11月26日
基于Transformer的时间序列预测模型
2024年11月25日
Python在金融大数据分析中的AI应用(股价分析、量化交易)实战
2024年11月25日
AIGC Gradio系列学习教程之Components
2024年12月01日
Python3 `asyncio` — 异步 I/O,事件循环和并发工具
2024年11月30日
llama-factory SFT系列教程:大模型在自定义数据集 LoRA 训练与部署
2024年12月01日
Python 多线程和多进程用法
2024年11月24日
Python socket详解,全网最全教程
2024年11月27日
python之plot()和subplot()画图
2024年11月26日
理解 DALL·E 2、Stable Diffusion 和 Midjourney 工作原理
2024年12月01日