RAG基建之PDF解析的“无OCR”邪术之旅

打印 上一主题 下一主题

主题 1681|帖子 1681|积分 5043

PDF文件转换成其他格式经常是个浩劫题,大量的信息被锁在PDF里,AI应用无法直接访问。假如能把PDF文件或其对应的图像转换成结构化或半结构化的机器可读格式,那就能大大缓解这个标题,同时也能显著增强人工智能应用的知识库。
  嘿,各位AI探险家们!本日我们将踏上了一段奇妙的PDF解析之旅,探索了那些不用OCR(光学字符识别)也能搞定PDF的神奇小模型。就像哈利·波特不用魔杖也能施法一样,这些小模型用神经网络直接“读懂”PDF,省去了繁琐的OCR步骤,简直是AI界的“无杖邪术”!
RAG(Retrieval-Augmented Generation)基建之PDF解析的“邪术”与“陷阱”

  
概述

之前介绍的基于流水线的PDF解析方法重要使用OCR引擎举行文本识别。然而,这种方法计算本钱高,对语言和文档类型的机动性较差,且OCR错误可能影响后续任务。
因此,应该开辟OCR-Free方法,如图1所示。这些方法不显式使用OCR来识别文本,而是使用神经网络隐式完成任务。本质上,这些方法采用端到端的方式,直接输出PDF解析结果。

OCR-Free vs. 流水线:谁更香?
从结构上看,OCR-Free方法比基于流水线的方法更简单。OCR-Free方法重要需要留意的方面是模型结构的筹划和训练数据的构建。OCR-Free方法固然一步到位,制止了中心步骤的“损耗”,但它的训练和推理速度有点慢,像是一辆豪华跑车,固然性能强大,但油耗高。而基于流水线的方法则像是一辆经济型小车,固然步骤多,但每个模块都很轻量,适合大规模摆设。
接下来,我们将介绍几种具有代表性的OCR-Free小型模型PDF解析框架:


    •    
    • Donut:PDF解析界的“甜甜圈”
      Donut这个小家伙,别看它名字甜,干起活来但是一点都不暗昧。它用Swin Transformer当“眼睛”,BART当“嘴巴”,直接把PDF图像“吃”进去,吐出一串JSON格式的“甜点”。不用OCR,端赖神经网络,简直是PDF解析界的“甜品大师”!  
      
    •    
    • Nougat:PDF解析界的“牛轧糖”
      Nougat,名字听起来就很有嚼劲,它的绝活是把PDF图像变成Markdown。它特别擅长处理复杂的公式和表格,简直是PDF解析界的“糖果工匠”。不过,它的生成速度有点慢,像牛轧糖一样,嚼起来需要点耐烦。  
      
    •    
    • ** Pix2Struct:PDF解析界的“像素邪术师”**
      Pix2Struct是个视觉语言理解的高手,它的任务是从屏蔽的网页截图中预测HTML解析。它不仅能处理PDF,还能搞定网页截图,简直是多才多艺的“像素邪术师”。不过,它的训练数据来自网页,可能会带来一些“有害内容”,使用时得小心点。  

具体介绍

Donut

如图2所示,Donut是一个端到端模型,旨在全面理解文档图像。其架构简单,由基于Transformer的视觉编码器和文本解码器模块组成。

Donut不依赖任何与OCR相关的模块,而是使用视觉编码器从文档图像中提取特征,并直接使用文本解码器生成token序列。输出序列可以转换为JSON等结构化格式。
代码如下:
  1. class DonutModel(PreTrainedModel):
  2.     r"""
  3.     Donut: 一个端到端的OCR-Free文档理解Transformer。
  4.     编码器将输入的文档图像映射为一组嵌入,
  5.     解码器预测所需的token序列,可以将其转换为结构化格式,
  6.     给定提示和编码器输出的嵌入
  7.     """
  8.     config_class = DonutConfig
  9.     base_model_prefix = "donut"
  10.     def __init__(self, config: DonutConfig):
  11.         super().__init__(config)
  12.         self.config = config
  13.         self.encoder = SwinEncoder(
  14.             input_size=self.config.input_size,
  15.             align_long_axis=self.config.align_long_axis,
  16.             window_size=self.config.window_size,
  17.             encoder_layer=self.config.encoder_layer,
  18.             name_or_path=self.config.name_or_path,
  19.         )
  20.         self.decoder = BARTDecoder(
  21.             max_position_embeddings=self.config.max_position_embeddings,
  22.             decoder_layer=self.config.decoder_layer,
  23.             name_or_path=self.config.name_or_path,
  24.         )
  25.     def forward(self, image_tensors: torch.Tensor, decoder_input_ids: torch.Tensor, decoder_labels: torch.Tensor):
  26.         """
  27.         给定输入图像和所需的token序列计算损失,
  28.         模型将以教师强制的方式进行训练
  29.         参数:
  30.             image_tensors: (batch_size, num_channels, height, width)
  31.             decoder_input_ids: (batch_size, sequence_length, embedding_dim)
  32.             decode_labels: (batch_size, sequence_length)
  33.         """
  34.         encoder_outputs = self.encoder(image_tensors)
  35.         decoder_outputs = self.decoder(
  36.             input_ids=decoder_input_ids,
  37.             encoder_hidden_states=encoder_outputs,
  38.             labels=decoder_labels,
  39.         )
  40.         return decoder_outputs
  41.     ...
  42.     ...
复制代码
编码器

Donut使用Swin-Transformer作为图像编码器,因为它在初步的文档解析研究中表现精彩。该图像编码器将输入的文档图像转换为一组高维嵌入。这些嵌入将作为文本解码器的输入。
对应代码如下:
  1. class SwinEncoder(nn.Module):
  2.     r"""
  3.     基于SwinTransformer的Donut编码器
  4.     使用预训练的SwinTransformer设置初始权重和配置,
  5.     然后修改详细配置作为Donut编码器
  6.     参数:
  7.         input_size: 输入图像大小(宽度,高度)
  8.         align_long_axis: 如果高度大于宽度,是否旋转图像
  9.         window_size: SwinTransformer的窗口大小(=patch大小)
  10.         encoder_layer: SwinTransformer编码器的层数
  11.         name_or_path: 预训练模型名称,要么在huggingface.co.注册,要么保存在本地。
  12.                       否则,将设置为`swin_base_patch4_window12_384`(使用`timm`)。
  13.     """
  14.     def __init__(
  15.         self,
  16.         input_size: List[int],
  17.         align_long_axis: bool,
  18.         window_size: int,
  19.         encoder_layer: List[int],
  20.         name_or_path: Union[str, bytes, os.PathLike] = None,
  21.     ):
  22.         super().__init__()
  23.         self.input_size = input_size
  24.         self.align_long_axis = align_long_axis
  25.         self.window_size = window_size
  26.         self.encoder_layer = encoder_layer
  27.         self.to_tensor = transforms.Compose(
  28.             [
  29.                 transforms.ToTensor(),
  30.                 transforms.Normalize(IMAGENET_DEFAULT_MEAN, IMAGENET_DEFAULT_STD),
  31.             ]
  32.         )
  33.         self.model = SwinTransformer(
  34.             img_size=self.input_size,
  35.             depths=self.encoder_layer,
  36.             window_size=self.window_size,
  37.             patch_size=4,
  38.             embed_dim=128,
  39.             num_heads=[4, 8, 16, 32],
  40.             num_classes=0,
  41.         )
  42.         self.model.norm = None
  43.         # 使用swin初始化权重
  44.         if not name_or_path:
  45.             swin_state_dict = timm.create_model("swin_base_patch4_window12_384", pretrained=True).state_dict()
  46.             new_swin_state_dict = self.model.state_dict()
  47.             for x in new_swin_state_dict:
  48.                 if x.endswith("relative_position_index") or x.endswith
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

万万哇

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表