跳到主内容
精选88MarkTechPost(RSS)技巧与观点

使用 deepDoctection 构建端到端文档智能处理流水线教程

Building an End-to-End Document Intelligence Pipeline with deepDoctection

原文
推荐理由

这是一篇极具实操价值的工程指南,完整覆盖了从环境配置、模型选型到自定义组件开发及下游 RAG 对接的全流程,参数与代码均可直接复用,适合需要落地文档解析的工程人员收藏实践。

In this tutorial, we implement a document intelligence pipeline with deepDoctection 1.2.x that combines layout detection, table structure recognition, OCR, reading-order reconstruction, annotation linking, and structured export in a single workflow. We configure the analyzer explicitly with DocLayNet-based layout detection, Table Transformer structure recognition, and DocTR OCR, then inspect the resulting Page objects to understand how deepDoctection represents text, figures, tables, relationships, provenance, and reading order. We also extend the framework by registering custom object types and implementing our own PipelineComponent for extracting monetary and date entities while classifying documents by their tabular characteristics. Finally, we assemble a custom pipeline manually with ServiceFactory, explore filtering and service rollback, serialize processed pages, and transform document annotations into ordered JSONL chunks suitable for downstream RAG and retrieval systems.

在本教程中,我们使用 deepDoctection 1.2.x 实现了一个文档智能流水线,该流水线将布局检测、表格结构识别、OCR、阅读顺序重建、注释链接和结构化导出整合到单一工作流中。我们通过基于 DocLayNet 的布局检测、Table Transformer 结构识别以及 DocTR OCR 显式配置分析器,然后检查生成的 Page 对象,以了解 deepDoctection 如何表示文本、图表、表格、关系、来源和阅读顺序。我们还通过注册自定义对象类型并实现用于提取货币和日期实体并按表格特征对文档进行分类的自定义 PipelineComponent 来扩展框架。最后,我们使用 ServiceFactory 手动组装自定义流水线,探索过滤和服务回滚机制,序列化处理后的页面,并将文档注释转换为适合下游 RAG 和检索系统的有序 JSONL 块。

代码 · 47
!pip install -q "deepdoctection" "transformers>=5.2.0" "timm" "python-doctr" "pdfplumber" "networkx" "lxml"
import os
os.environ["DD_USE_TORCH"]  = "True"
os.environ["DPI"]           = "200"
os.environ["LOG_LEVEL"]     = "INFO"
os.environ["ENABLE_DYNAMIC_OBJECT_TYPES"] = "False"
import json, re, textwrap
from pathlib import Path
from collections import Counter
import numpy as np
import matplotlib.pyplot as plt
from IPython.display import HTML, display
import deepdoctection as dd
print("deepdoctection:", dd.__version__)
import transformers.integrations.peft as _hf_peft
if _hf_peft.is_peft_available():
   _hf_peft.is_peft_available = lambda: False
   print("patched: PEFT adapter lookup disabled for from_pretrained")
!mkdir -p /content/docs /content/imgs
!wget -q -O /content/docs/paper.pdf \
 Click to access 2312.13560.pdf
!wget -q -O /content/imgs/finance.png \
 https://raw.githubusercontent.com/deepdoctection/notebooks/main/sample/finance/1bcac3899c9cb1c0b0f650b1431d3d52_7.png
PDF = Path("/content/docs/paper.pdf")
PNG = Path("/content/imgs/finance.png")
OUT = Path("/content/out"); OUT.mkdir(exist_ok=True)
def show(img, w=16):
   if img is None: return
   plt.figure(figsize=(w, w * 1.3)); plt.axis("off"); plt.imshow(img); plt.show()
def analyze_any(pipe, path, **kw):
   """
   Dispatch correctly for a directory, a PDF, or a single image file.
   DoctectionPipe can stream a directory or a PDF from disk, but a *single*
   image has no reader — path= only supplies the file name / provenance, and
   the pixels must be handed in via bytes=. Without this you get:
     ValueError: When passing a path to a single image, bytes of the image
                 must be passed
   """
   path = Path(path)
   if path.is_dir():
       kw.setdefault("file_type", [".jpg", ".png", ".jpeg", ".tif"])
       return pipe.analyze(path=path, **kw)
   if path.suffix.lower() == ".pdf":
       return pipe.analyze(path=path, **kw)
   if path.suffix.lower() in (".png", ".jpg", ".jpeg", ".tif"):
       return pipe.analyze(path=path, bytes=path.read_bytes(), **kw)
   raise ValueError(f"unsupported input: {path}")
代码 · 47
!pip install -q "deepdoctection" "transformers>=5.2.0" "timm" "python-doctr" "pdfplumber" "networkx" "lxml"
import os
os.environ["DD_USE_TORCH"]  = "True"
os.environ["DPI"]           = "200"
os.environ["LOG_LEVEL"]     = "INFO"
os.environ["ENABLE_DYNAMIC_OBJECT_TYPES"] = "False"
import json, re, textwrap
from pathlib import Path
from collections import Counter
import numpy as np
import matplotlib.pyplot as plt
from IPython.display import HTML, display
import deepdoctection as dd
print("deepdoctection:", dd.__version__)
import transformers.integrations.peft as _hf_peft
if _hf_peft.is_peft_available():
   _hf_peft.is_peft_available = lambda: False
   print("patched: PEFT adapter lookup disabled for from_pretrained")
!mkdir -p /content/docs /content/imgs
!wget -q -O /content/docs/paper.pdf \
 Click to access 2312.13560.pdf
!wget -q -O /content/imgs/finance.png \
 https://raw.githubusercontent.com/deepdoctection/notebooks/main/sample/finance/1bcac3899c9cb1c0b0f650b1431d3d52_7.png
PDF = Path("/content/docs/paper.pdf")
PNG = Path("/content/imgs/finance.png")
OUT = Path("/content/out"); OUT.mkdir(exist_ok=True)
def show(img, w=16):
   if img is None: return
   plt.figure(figsize=(w, w * 1.3)); plt.axis("off"); plt.imshow(img); plt.show()
def analyze_any(pipe, path, **kw):
   """
   Dispatch correctly for a directory, a PDF, or a single image file.
   DoctectionPipe can stream a directory or a PDF from disk, but a *single*
   image has no reader — path= only supplies the file name / provenance, and
   the pixels must be handed in via bytes=. Without this you get:
     ValueError: When passing a path to a single image, bytes of the image
                 must be passed
   """
   path = Path(path)
   if path.is_dir():
       kw.setdefault("file_type", [".jpg", ".png", ".jpeg", ".tif"])
       return pipe.analyze(path=path, **kw)
   if path.suffix.lower() == ".pdf":
       return pipe.analyze(path=path, **kw)
   if path.suffix.lower() in (".png", ".jpg", ".jpeg", ".tif"):
       return pipe.analyze(path=path, bytes=path.read_bytes(), **kw)
   raise ValueError(f"unsupported input: {path}")

We install the required deepDoctection dependencies, configure its runtime environment, and apply a compatibility patch for Transformers and PEFT. We download the sample PDF and image files that we use throughout the tutorial and prepare our output directory. We also define helper functions to visualize images and consistently analyze directories, PDFs, and individual image files.

我们安装所需的 deepDoctection 依赖项,配置其运行时环境,并应用针对 Transformers 和 PEFT 的兼容性补丁。我们下载本教程中使用的示例 PDF 和图像文件,并准备输出目录。我们还定义了辅助函数,用于可视化图像并一致地分析目录、PDF 和单个图像文件。

代码 · 39
dd.print_model_infos(add_description=False, add_config=False, add_categories=False)
profile = dd.ModelCatalog.get_profile("Aryn/deformable-detr-DocLayNet/model.safetensors")
print("\nlayout model categories:", profile.categories)
print("is registered:", dd.ModelCatalog.is_registered("Aryn/deformable-detr-DocLayNet/model.safetensors"))
config_overwrite = [
   "USE_ROTATOR=False",
   "USE_LAYOUT=True",
   "USE_LAYOUT_NMS=True",
   "USE_TABLE_SEGMENTATION=True",
   "USE_TABLE_REFINEMENT=False",
   "USE_PDF_MINER=False",
   "USE_OCR=True",
   "USE_LAYOUT_LINK=True",
   "LAYOUT.WEIGHTS=Aryn/deformable-detr-DocLayNet/model.safetensors",
   "ITEM.WEIGHTS=deepdoctection/tatr_tab_struct_v2/model.safetensors",
   "ITEM.FILTER=['table']",
   "OCR.USE_DOCTR=True",
   "OCR.USE_TESSERACT=False",
   "OCR.USE_TEXTRACT=False",
   "OCR.WEIGHTS.DOCTR_WORD=doctr/db_resnet50/db_resnet50-ac60cadc.pt",
   "OCR.WEIGHTS.DOCTR_RECOGNITION=doctr/crnn_vgg16_bn/crnn_vgg16_bn-0417f351.pt",
   "SEGMENTATION.THRESHOLD_ROWS=0.4",
   "SEGMENTATION.THRESHOLD_COLS=0.4",
   "SEGMENTATION.FULL_TABLE_TILING=True",
   "WORD_MATCHING.RULE=ioa",
   "WORD_MATCHING.THRESHOLD=0.3",
   "WORD_MATCHING.MAX_PARENT_ONLY=True",
   "TEXT_ORDERING.INCLUDE_RESIDUAL_TEXT_CONTAINER=True",
   "TEXT_ORDERING.PARAGRAPH_BREAK=0.035",
   "TEXT_ORDERING.BROKEN_LINE_TOLERANCE=0.003",
   "LAYOUT_LINK.PARENTAL_CATEGORIES=['figure','table']",
   "LAYOUT_LINK.CHILD_CATEGORIES=['caption']",
]
analyzer = dd.get_dd_analyzer(config_overwrite=config_overwrite)
print("\n--- pipeline ---")
for sid, name in analyzer.get_pipeline_info().items():
   print(f"{sid}  {name}")
print("\n--- what this pipeline produces ---")
print(analyzer.get_meta_annotation())
代码 · 39
dd.print_model_infos(add_description=False, add_config=False, add_categories=False)
profile = dd.ModelCatalog.get_profile("Aryn/deformable-detr-DocLayNet/model.safetensors")
print("\nlayout model categories:", profile.categories)
print("is registered:", dd.ModelCatalog.is_registered("Aryn/deformable-detr-DocLayNet/model.safetensors"))
config_overwrite = [
   "USE_ROTATOR=False",
   "USE_LAYOUT=True",
   "USE_LAYOUT_NMS=True",
   "USE_TABLE_SEGMENTATION=True",
   "USE_TABLE_REFINEMENT=False",
   "USE_PDF_MINER=False",
   "USE_OCR=True",
   "USE_LAYOUT_LINK=True",
   "LAYOUT.WEIGHTS=Aryn/deformable-detr-DocLayNet/model.safetensors",
   "ITEM.WEIGHTS=deepdoctection/tatr_tab_struct_v2/model.safetensors",
   "ITEM.FILTER=['table']",
   "OCR.USE_DOCTR=True",
   "OCR.USE_TESSERACT=False",
   "OCR.USE_TEXTRACT=False",
   "OCR.WEIGHTS.DOCTR_WORD=doctr/db_resnet50/db_resnet50-ac60cadc.pt",
   "OCR.WEIGHTS.DOCTR_RECOGNITION=doctr/crnn_vgg16_bn/crnn_vgg16_bn-0417f351.pt",
   "SEGMENTATION.THRESHOLD_ROWS=0.4",
   "SEGMENTATION.THRESHOLD_COLS=0.4",
   "SEGMENTATION.FULL_TABLE_TILING=True",
   "WORD_MATCHING.RULE=ioa",
   "WORD_MATCHING.THRESHOLD=0.3",
   "WORD_MATCHING.MAX_PARENT_ONLY=True",
   "TEXT_ORDERING.INCLUDE_RESIDUAL_TEXT_CONTAINER=True",
   "TEXT_ORDERING.PARAGRAPH_BREAK=0.035",
   "TEXT_ORDERING.BROKEN_LINE_TOLERANCE=0.003",
   "LAYOUT_LINK.PARENTAL_CATEGORIES=['figure','table']",
   "LAYOUT_LINK.CHILD_CATEGORIES=['caption']",
]
analyzer = dd.get_dd_analyzer(config_overwrite=config_overwrite)
print("\n--- pipeline ---")
for sid, name in analyzer.get_pipeline_info().items():
   print(f"{sid}  {name}")
print("\n--- what this pipeline produces ---")
print(analyzer.get_meta_annotation())

We inspect deepDoctection’s model registry to verify the layout model and its supported document categories. We explicitly configure the analyzer to combine layout detection, table segmentation, DocTR OCR, word matching, reading-order reconstruction, and layout linking. We then initialize the analyzer and inspect its pipeline components and the annotation types that it produces.

我们检查 deepDoctection 的模型注册表,以验证布局模型及其支持的文档类别。我们显式配置分析器,以结合布局检测、表格分割、DocTR OCR、词匹配、阅读顺序重建和布局链接。然后我们初始化分析器,并检查其流水线组件及其产生的注释类型。

代码 · 33
df = analyze_any(analyzer, PDF, session_id="tutorial01", max_datapoints=3)
df.reset_state()
pages = list(df)
print(f"\nparsed {len(pages)} pages")
page = pages[0]
show(page.viz(show_figures=True, show_residual_layouts=True, show_table_structure=True))
print("== narrative text ==")
print(textwrap.fill(page.text[:900], 110))
print("\n== layout blocks in reading order ==")
for doc_id, img_id, pno, ann_id, order, cat, txt in page.chunks[:12]:
   print(f"[{order:>3}] {str(cat):<15} {txt[:70]!r}")
print("\n== category histogram ==")
print(Counter(a.category_name for a in page.get_annotation()))
for fig in page.figures:
   linked = fig.get_relationship("layout_link")
   print("figure", fig.annotation_id[:8], "-> caption ids:", [i[:8] for i in linked])
if page.words:
   w = page.words[0]
   print("\nword:", w.characters, "| service:", w.service_id,
         "| model:", w.model_id, "| bbox:", [round(x) for x in w.bbox])
tbl_pages = [p for p in pages if p.tables]
if tbl_pages:
   t = tbl_pages[0].tables[0]
   print(f"table {t.number_of_rows}x{t.number_of_columns}, "
         f"max_row_span={t.max_row_span}, max_col_span={t.max_col_span}")
   display(HTML(t.html))
   for row in t.csv[:5]:
       print([c[:22] for c in row])
   for c in t.cells[:5]:
       print(f"  r{c.row_number} c{c.column_number} "
             f"(span {c.row_span}x{c.column_span}) {c.text[:40]!r}")
else:
   print("no table on these pages — the finance.png sample below has one")
代码 · 33
df = analyze_any(analyzer, PDF, session_id="tutorial01", max_datapoints=3)
df.reset_state()
pages = list(df)
print(f"\nparsed {len(pages)} pages")
page = pages[0]
show(page.viz(show_figures=True, show_residual_layouts=True, show_table_structure=True))
print("== narrative text ==")
print(textwrap.fill(page.text[:900], 110))
print("\n== layout blocks in reading order ==")
for doc_id, img_id, pno, ann_id, order, cat, txt in page.chunks[:12]:
   print(f"[{order:>3}] {str(cat):<15} {txt[:70]!r}")
print("\n== category histogram ==")
print(Counter(a.category_name for a in page.get_annotation()))
for fig in page.figures:
   linked = fig.get_relationship("layout_link")
   print("figure", fig.annotation_id[:8], "-> caption ids:", [i[:8] for i in linked])
if page.words:
   w = page.words[0]
   print("\nword:", w.characters, "| service:", w.service_id,
         "| model:", w.model_id, "| bbox:", [round(x) for x in w.bbox])
tbl_pages = [p for p in pages if p.tables]
if tbl_pages:
   t = tbl_pages[0].tables[0]
   print(f"table {t.number_of_rows}x{t.number_of_columns}, "
         f"max_row_span={t.max_row_span}, max_col_span={t.max_col_span}")
   display(HTML(t.html))
   for row in t.csv[:5]:
       print([c[:22] for c in row])
   for c in t.cells[:5]:
       print(f"  r{c.row_number} c{c.column_number} "
             f"(span {c.row_span}x{c.column_span}) {c.text[:40]!r}")
else:
   print("no table on these pages — the finance.png sample below has one")

We run the configured analyzer on the sample PDF and materialize the resulting pages from the lazy data flow. We inspect narrative text, reading-order chunks, annotation categories, figure-caption relationships, word provenance, and bounding boxes. We also access detected tables through HTML, CSV, and individual cell representations to examine their structured output.

我们在示例 PDF 上运行配置好的分析器,并从惰性数据流中实例化生成的页面。我们检查叙述性文本、阅读顺序块、注释类别、图-注关系、词的来源以及边界框。我们还通过 HTML、CSV 和单个单元格表示访问检测到的表格,以检查其结构化输出。

更进一步:量化金融体系

看懂新闻只是起点——沿量化金融路径,把它变成能交付的工程能力

进入量化体系 →

相似阅读

另一事件,读法相近