Langchain中的表格解析:RAG 和表格的爱恨情仇
实现 RAG(Retrieval-Augmented Generation)是一个挑战,尤其是在有效解析和理解非结构化文档中的表格时。这在处理扫描文档或图像格式的文档时尤为困难。这些挑战至少包括以下三个方面:
-
1.表格的“叛逆期”:不准确的解析可能会破坏表格结构:
表格在文档里就像个叛逆的青少年,结构复杂、格式多变,手写和打印混在一起,还时不时带点非文本元素(比如图片、公式)。想要准确解析它们?难上加难!一不小心,表格结构就被破坏得七零八落,RAG 的结果也跟着遭殃。 -
2.表格标题的“捉迷藏”:如何提取表格标题并有效地将其与相应的表格关联起来。:
表格标题就像个调皮的小精灵,总是藏在表格旁边,但就是不肯乖乖现身。如何找到它并把它和表格“配对”?这可是个技术活儿! -
3.索引结构的“拼图游戏” :如何设计索引结构以有效存储表格的语义信息。:
表格的语义信息怎么存?是存成图像、纯文本、LaTeX,还是只存个摘要?这就像在玩拼图,得找到最合适的拼法,才能让 RAG 系统跑得顺畅。
本文首先介绍了在 RAG 中管理表格的关键技术,然后回顾了一些现有的开源解决方案,最后提出并实现了一个新的解决方案。

工具大比拼
表格解析
该模块的主要功能是从非结构化文档或图像中准确提取表格结构。
附加功能:最好能提取相应的表格标题,并方便开发者将表格标题与表格关联起来。
根据我目前的理解,有几种方法,如图 1 所示:

图 1:表格解析器。
(a). 利用多模态 LLM,如 GPT-4V,来识别表格并从每个 PDF 页面中提取信息。
- 输入:图像格式的 PDF 页面
- 输出:JSON 或其他格式的表格。如果多模态 LLM 无法提取表格数据,它应该对图像进行总结并返回总结。
(b). 利用专业的表格检测模型,如 Table Transformer,来识别表格结构。
- 输入:图像格式的 PDF 页面
- 输出:图像格式的表格
©. 使用开源框架,如 unstructured 等,这些框架也使用对象检测模型(unstructured 的表格检测过程在这篇文章中有详细说明)。这些框架允许对整个文档进行全面的解析,并从解析结果中提取与表格相关的内容。
- 输入:PDF 或图像格式的文档
- 输出:从整个文档的解析结果中获得的纯文本或 HTML 格式的表格
(d). 使用端到端模型,如 Nougat、Donut 等,来解析整个文档并提取与表格相关的内容。这种方法不需要 OCR 模型。
- 输入:PDF 或图像格式的文档
- 输出:从整个文档的解析结果中获得的 LaTeX 或 JSON 格式的表格
值得一提的是,无论使用哪种方法提取表格信息,都应包含表格标题。因为在大多数情况下,表格标题是文档或论文作者对表格的简要描述,可以在很大程度上概括整个表格。
在上述四种方法中,方法 (d) 可以轻松获取表格标题。这对开发者来说非常有利,因为它允许他们将表格标题与表格关联起来。这将在接下来的实验中进行进一步解释。
索引结构
根据索引的结构,解决方案大致可以分为以下几类:
(e). 仅索引图像格式的表格。
(f). 仅索引纯文本或 JSON 格式的表格。
(g). 仅索引 LaTeX 格式的表格。
(h). 仅索引表格的摘要。
(i). 小到大或文档摘要索引结构,如图 2 所示。
- 小块的内容可以是表格每一行的信息或表格的摘要。
- 大块的内容可以是图像格式、纯文本格式或 LaTeX 格式的表格。

图 2:小到大索引结构(上部)和文档摘要索引结构(中部和下部)。作者提供的图片。
如上所述,表格摘要通常使用 LLM 生成:
- 输入:图像格式、文本格式或 LaTeX 格式的表格
- 输出:表格摘要
不需要表格解析、索引或 RAG 的算法
有些算法不需要表格解析。
(j). 将相关图像(PDF 页面)和用户的查询发送到 VQA 模型(如 DAN 等)或多模态 LLM,并返回答案。
- 需要索引的内容:图像格式的文档
- 发送到 VQA 模型或多模态 LLM 的内容:查询 + 对应的页面(图像形式)
(k). 将相关文本格式的 PDF 页面和用户的查询发送到 LLM,然后返回答案。
- 需要索引的内容:文本格式的文档
- 发送到 LLM 的内容:查询 + 对应的页面(文本格式)
(l). 将相关图像(PDF 页面)、文本块和用户的查询发送到多模态 LLM(如 GPT-4V 等),并直接返回答案。
- 需要索引的内容:图像格式的文档和文本格式的文档块
- 发送到多模态 LLM 的内容:查询 + 对应的图像格式文档 + 对应的文本块
此外,以下是一些不需要索引的方法,如图 3 和图 4 所示:

图 3:类别 (m)
(m). 首先,应用类别 (a) 到 (d) 中的一种方法,将文档中的所有表格解析为图像格式。然后直接将所有表格图像和用户的查询发送到多模态 LLM(如 GPT-4V 等),并返回答案。
- 需要索引的内容:无
- 发送到多模态 LLM 的内容:查询 + 所有解析后的表格(图像格式)

图 4:类别 (n)。
(n). 使用 (m) 中提取的图像格式的表格,然后使用 OCR 模型识别表格中的所有文本,然后直接将表格中的所有文本和用户的查询发送到 LLM,并直接返回答案。
- 需要索引的内容:无
- 发送到 LLM 的内容:用户的查询 + 所有表格内容(文本格式)
值得注意的是,有些方法不依赖于 RAG 过程:
- 第一种方法不使用 LLM,而是在特定数据集上进行训练,使模型(如 BERT 类 Transformer)更好地支持表格理解任务,例如 TAPAS。
- 第二种方法使用 LLM,采用预训练、微调方法或提示,使 LLM 能够执行表格理解任务,如 GPT4Table。
现有的开源解决方案
LlamaIndex 提出了四种方法,其中前三种使用多模态模型。
- 检索相关图像(PDF 页面)并将其发送到 GPT-4V 以响应查询。
- 将每个 PDF 页面视为图像,让 GPT-4V 对每个页面进行图像推理。为图像推理构建文本向量存储索引。查询答案时,针对图像推理向量存储进行查询。
- 使用 Table Transformer 从检索到的图像中裁剪表格信息,然后将这些裁剪后的图像发送到 GPT-4V 以响应查询。
- 对裁剪后的表格图像应用 OCR,并将数据发送到 GPT4/ GPT-3.5 以回答查询。
根据本文的分类:
- 第一种方法类似于本文的类别 (j),不需要表格解析。然而,结果显示,即使答案在图像中,也无法生成正确答案。
- 第二种方法涉及表格解析,对应于类别 (a)。索引的内容是表格内容或摘要,基于 GPT-4V 返回的结果,可能对应于类别 (f) 或 (h)。这种方法的缺点是 GPT-4V 从图像中识别表格并提取其内容的能力不稳定,特别是当图像包含表格、文本和其他图像的混合时,这在 PDF 格式中很常见。
- 第三种方法类似于类别 (m),不需要索引。
- 第四种方法类似于类别 (n),也不需要索引。其结果表明,由于无法从图像中提取表格信息,导致生成错误答案。
通过测试,发现第三种方法的整体效果最好。然而,根据我的测试,第三种方法在检测表格方面存在困难,更不用说正确地将表格标题与表格合并了。
Langchain 也提出了一些解决方案,半结构化 RAG 的关键技术包括:
- 表格解析使用 unstructured,属于类别 ©。
- 索引方法是文档摘要索引,属于类别 (i),小块内容:表格摘要,大块内容:原始表格内容(文本格式)。
如图 5 所示:
图 5:Langchain 的半结构化 RAG。来源:半结构化 RAG
半结构化和多模态 RAG 提出了三种解决方案, 架构如图 6 所示。
图 6:Langchain 的半结构化和多模态 RAG。来源:半结构化和多模态 RAG。
选项 1 类似于本文的类别 (l)。它涉及使用多模态嵌入(如 CLIP)来嵌入图像和文本,使用相似性搜索检索两者,并将原始图像和块传递给多模态 LLM 以进行答案合成。
选项 2 利用多模态 LLM,如 GPT-4V、LLaVA、FUYU-8b,从图像生成文本摘要。然后,嵌入并检索文本,并将文本块传递给 LLM 以进行答案合成。
- 表格解析使用 unstructured,属于类别 (d)。
- 索引结构是文档摘要索引(类别 (i)),小块内容:表格摘要,大块内容:文本格式的表格
选项 3 使用多模态 LLM(如 GPT-4V、LLaVA、FUYU-8b)从图像生成文本摘要,然后嵌入并检索图像摘要,并引用原始图像(类别 (i)),然后将原始图像和文本块传递给多模态 LLM 以进行答案合成。
提出的解决方案
本文提出的解决方案:
- 表格解析:使用 Nougat(类别 (d))。根据我的测试,它的表格检测比 unstructured(类别 ©)更有效。此外,Nougat 可以很好地提取表格标题,非常方便与表格关联。
- 文档摘要索引结构(类别 (i)):小块的内容包括表格摘要,大块的内容包括相应的 LaTeX 格式的表格和文本格式的表格标题。我们使用 multi-vector retriever 实现它。
- 表格摘要获取方法:将表格和表格标题发送到 LLM 进行摘要。
这种方法的优点是它高效地解析表格,同时全面考虑了表格摘要与表格之间的关系。它还消除了对多模态 LLM 的需求,从而节省了成本。
Nougat 的原理
Nougat 是基于 Donut 架构开发的。它通过网络隐式识别文本,不需要任何 OCR 相关的输入或模块,如图 8 所示。
图 8:基于 Donut 的端到端架构。Swin Transformer 编码器将文档图像转换为潜在嵌入,随后以自回归方式转换为标记序列。来源:Nougat: Neural Optical Understanding for Academic Documents。
Nougat 解析公式的能力令人印象深刻。它在解析表格方面也表现出色。方便的是,它可以关联表格标题,如图 9 所示:
图 9:运行 Nougat 的结果,结果文件为 Mathpix Markdown 格式(通过 vscode 插件打开),表格为 LaTeX 格式。
我测试发现表格标题总是固定在表格的下一行。这种一致性表明这不是偶然的。 Nougat 是如何实现这种效果的?
鉴于它是一个端到端模型,缺乏中间结果,它很可能严重依赖于其训练数据。
根据格式化训练数据的代码,对于表格,紧跟在 \end{table} 之后的行是 caption_parts,这似乎与提供的训练数据的格式一致:
def format_element(element: Element, keep_refs: bool = False, latex_env: bool = False
) -> List[str]:"""将给定的元素格式化为格式化字符串列表。参数:element (Element): 要格式化的元素。keep_refs (bool, 可选): 是否在格式化中保留引用。默认为 False。latex_env (bool, 可选): 是否使用 LaTeX 环境格式化。默认为 False。返回:List[str]: 表示格式化元素的格式化字符串列表。""".相关文章:
Langchain中的表格解析:RAG 和表格的爱恨情仇
实现 RAG(Retrieval-Augmented Generation)是一个挑战,尤其是在有效解析和理解非结构化文档中的表格时。这在处理扫描文档或图像格式的文档时尤为困难。这些挑战至少包括以下三个方面: 1.表格的“叛逆期”:不准确的解析可能会破坏表格结构: 表格在文档里就像个叛逆的青少…...
神奇的闹钟(算法题)
神奇的闹钟 题目 原题 小蓝发现了一个神奇的闹钟,从纪元时间(19701970 年 11 月 11 日 00:00:0000:00:00)开始,每经过 xx 分钟,这个闹钟便会触发一次闹铃 (纪元时间也会…...
CAT1模块 EC800M HTTP 使用后续记录
记录一下 CAT1 模块EC800 HTTP 使用后续遇到的问题 by 矜辰所致目录 前言一、一些功能的完善1.1 新的交互指令添加1.2 连不上网络处理 二、问题出现三、分析及解决3.1 定位问题3.2 问题分析与解决3.2.1 查看变量在内存中的位置 3.3 数据类型说明3.3.1 常用格式化输出符号…...
Python 标准库与数据结构
Python的标准库提供了丰富的内置数据结构和函数,使用这些工具能为我们提供一套强有力的工具。 需要注意的是,相比C与Java,Python的一些特点: Python不需要显式声明变量类型Python没有模板(Template)的概念,因为Pytho…...
NIO入门
IO和NIO的区别: IO:通过流处理数据,仅支持阻塞IO。 核心组件:InputStream /OutputStream用于字节的读写,Reader / Writer:用于字符流的读写。读取过程中无法被中断,是阻塞式IO。 NIO:通过管道处…...
leetcode 用队列模拟栈
这个其实只需要一个队列就可以的,但是我这里用的是2个队列进行替换, 先转n-1个到空的队列, 然后在此基础上进行队列的互换,把剩下的那一个元素所在的队列进行poleft操作就可以了。 class MyStack:def __init__(self):self.q1_i…...
spring security 使用的过滤器还是拦截器
spring security 使用的过滤器还是拦截器 Spring Security 是一个强大的安全框架,用于保护 Java 应用程序。它主要使用过滤器(Filters)来实现安全功能,而不是拦截器(Interceptors)。不过,它也提…...
大疆上云api介绍
概述 目前对于 DJI 无人机接入第三方云平台,主要是基于 MSDK 开发定制 App,然后自己定义私有上云通信协议连接到云平台中。这样对于核心业务是开发云平台,无人机只是其中一个接入硬件设备的开发者来说,重新基于 MSDK 开发 App 工作量大、成本高,同时还需要花很多精力在无人…...
2025-03-25 Unity 网络基础4——TCP同步通信
文章目录 1 Socket1.1 Socket 类型1.2 构造 Socket1.3 常用属性1.4 常用方法 2 TCP 通信2.1 服务端配置2.2 客户端配置2.3 进行通信2.4 多设备通信 3 区分消息 1 Socket Socket 是 C# 提供的网络通信类(其它语言也有对应的 Socket 类),是…...
C++进阶(一)
个人主页:PingdiGuo_guo 收录专栏:C干货专栏 前言 本篇博客是讲解函数的重载以及引用的知识点的。 文章目录 前言 1.函数重载 1.1何为函数重载 1.2函数重载的作用 1.3函数重载的实现 2.引用 2.1何为引用 2.2定义引用 2.3引用特性 2.4常引用 2…...
深度解读DeepSeek:开源周(Open Source Week)技术解读
深度解读DeepSeek:开源周(Open Source Week)技术解读 深度解读DeepSeek:源码解读 DeepSeek-V3 深度解读DeepSeek:技术原理 深度解读DeepSeek:发展历程 文章目录 一、开源内容概览Day1:FlashMLAD…...
AI Agent开发与应用
AI Agent开发与应用:本地化智能体实践——本地化智能体开发进展与主流框架分析 我要说的都在ppt里面了,相关复现工作请参考ai agent开发实例 OpenManus Dify Owl 第二个版本更新了对话的框架,通过gradio做了一个全新的界面 只测试了阿里云…...
石斛基因组-文献精读122
A chromosome-level Dendrobium moniliforme genome assembly reveals the regulatory mechanisms of flavonoid and carotenoid biosynthesis pathways 《染色体水平的石斛基因组组装揭示了黄酮类和胡萝卜素生物合成途径的调控机制》 摘要 石斛(Dendrobium monil…...
javaSE.多维数组
1 final 引用类型 final int[] arr 继承Object 的引用类型,不能改变引用的对象 存的其实是引用 数组类型数组,其实存的是引用 int [][] arr new int[][] { {1,2,3}, {4,5,6} };int [] a arr[0]; int [] b arr[1];...
Spring IOC容器详解:深入理解控制反转与依赖注入
一、什么是IOC? 在java当中一个类想要使用另一个类的方法,就必须在这个类当中创建这个类的对象,那么可能会出现如下情况, 比如A类当中创建着B对象,B类当中有C对象,C类当中有A对象,这个如果一个类…...
Python条件处理,新手入门到精通
Python条件处理,新手入门到精通 对话实录 **小白**:(崩溃)我写了if x 1:,为什么Python会报错? **专家**:(推眼镜)**是赋值,才是比较**!想判断相…...
JPA实体类注解缺失异常全解:从报错到防御!!!
🚨 JPA实体类注解缺失异常全解:从报错到防御 🛡️ 一、💥 问题现象速览 // 经典报错示例 Caused by: java.lang.IllegalArgumentException: Not a managed type: class com.example.entity.Product典型症状: &…...
Spring 源码硬核解析系列专题(三十二):Spring Cloud LoadBalancer 的负载均衡源码解析
在前几期中,我们从 Spring 核心到 Spring Boot 的多个模块,再到 Spring Cloud Alibaba,逐步揭示了 Spring 生态在微服务领域的广泛应用。Spring Cloud LoadBalancer 是 Spring Cloud 提供的客户端负载均衡组件,替代 Ribbon,支持服务发现和负载均衡策略。本篇将深入 Spring…...
生成式媒介革命已至,搜索如何借力DeepSeek破局?
作为前沿AI技术的代表,DeepSeek不仅突破了传统大模型的算力瓶颈,更以“高性能低成本开源生态”的特性,重塑传播生态。对于搜索行业从业者而言,这场技术变革既是机遇,也是挑战。 DeepSeek的三大“杀手锏”,…...
【Vue3入门1】02- Vue3的基本操作(上)
本文介绍vue3中的一些方法的操作。 目录 1. 绑定事件 v-on 2. 按键修饰符 3. 显示和隐藏 v-show 4. 条件渲染 v-if 5. 条件渲染if-else 1. 绑定事件 v-on 点击事件 v-on:click" 发生事件 " <body><div id"app">{{ msg }} <h2&g…...
【C语言】多进程/多线程
【C语言】多进程/多线程 参考链接多进程/多线程服务器1. 多进程服务器2. 多线程服务器 结语参考链接 参考链接 c 中文网 菜鸟 c 多进程/多线程服务器 多进程和多线程是常用的并发编程技术。它们都允许程序同时执行多个任务,提高了系统的资源利用率和程序的运行效率…...
模糊数学 | 模型 / 集合 / 关系 / 矩阵
注:本文为来自 “模糊数学 | 模型及其应用” 相关文章合辑。 略作重排。 如有内容异常,请看原文。 模糊数学模型:隶属函数、模糊集合的表示方法、模糊关系、模糊矩阵 wamg 潇潇 于 2019-05-06 22:35:21 发布 1.1 模糊数学简介 1965 年&a…...
Browserlist 使用指南:应对浏览器兼容性问题的解决方案
前言 在前端开发中,我们经常需要处理各种不同的浏览器兼容性问题。每个浏览器的版本众多,处理这些问题可能会让人感到头疼。幸运的是,有一个名为 Browserlist 的工具可以大大简化这项工作。本文将介绍 Browserlist 的作用和使用方法…...
QinQ项展 VLAN 空间
随着以太网技术在网络中的大量部署,利用 VLAN 对用户进行隔离和标识受到很大限制。因为 IEEE802.1Q 中定义的 VLAN Tag 域只有 12 个比特,仅能表示 4096 个 VLAN,无法满足城域以太网中标识大量用户的需求,于是 QinQ 技术应运而生。…...
数据结构—树(java实现)
目录 一、树的基本概念1.树的术语2.常见的树结构 二、节点的定义三、有关树结构的操作1.按照数组构造平衡 二叉搜索树2.层序遍历树3.前、中、后序遍历树(1).前序遍历树(2).中序遍历树(3).后序遍历树(4).各种遍历的情况的效果对比 4.元素添加5.元素删除1.删除叶子节点2.删除单一…...
Unity射击游戏手榴弹笔记
数据 在物品系统增加一个新的物品类,手榴弹类,定义手榴弹依附物体的类、配表数据类、背包内物品数据类、新建配表、在背包增加手榴弹数组;手榴弹的预制体需要可拾取的、扔出的;背包界面增加背包内的手榴弹、场景里的手榴弹、别人…...
S32K144外设实验(七):FTM输出多路互补带死区PWM
文章目录 1. 概述1.1 时钟系统1.2 实验目的2. 代码的配置2.1 时钟配置2.2 FTM模块配置2.3 输出引脚配置2.4 API函数调用1. 概述 互补对的PWM输出是很重要的外设功能,尤其应用再无刷电机的控制。 1.1 时钟系统 笔者再墨迹一遍时钟的设置,因为很重要。 FTM的CPU接口时钟为SY…...
SingleMod
SingleMod SingleMod是一种深度学习模型,专为利用纳米孔直接RNA测序(DRS)数据在单RNA分子中精确检测m6A修饰而设计。该模型通过深度多实例回归框架进行训练,能够充分利用广泛的甲基化率标签。SingleMod是一个通用框架,可轻松适配其他核酸修饰的检测模型训练。 注意: Si…...
[网鼎杯 2020 白虎组]PicDown1 [反弹shell] [敏感文件路径] [文件描述符]
常见读取路径 /etc/passwd一些用户和权限还有一些乱七八糟的 /proc/self/cmdline包含用于开始当前进程的命令 /proc/self/cwd/app.py当前工作目录的app.py /proc/self/environ包含了可用进程的环境变量 /proc/pid/exe 包含了正在进程中运行的程序链接; /proc/pid…...
单纯形法之大M法
1. 问题背景与标准化 在求解某些线性规划问题时,往往难以直接找到初始的基本可行解。特别是当约束中存在等式或 “≥” 类型的不等式时,我们需要引入人工变量来构造一个初始可行解。 考虑如下标准形式问题(假设为最大化问题)&am…...
