适合从事智能文档分析、法律科技、金融报告处理、企业知识搜索等行业开发者,构建能处理 PDF、Word、HTML、邮件等复杂文档的新一代搜索系统。
目录
- 为什么需要处理复杂文档?
- Unstructured.io 简介与优势
- Elasticsearch 向量数据库简介
- 整体架构图解:复杂文档 → 搜索引擎
- 文档处理流程与向量生成
- Elasticsearch 向量索引配置与搜索
- 完整实战代码示例:从文档到搜索结果
- 常见问题与性能优化
- 总结与推荐实践
一、为什么需要处理复杂文档?
企业中存在大量结构不清晰、跨格式的文档,如:
- 合同(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、表格结构提取等模块 |