当前位置: 首页 > news >正文

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 提出了四种方法,其中前三种使用多模态模型。

  1. 检索相关图像(PDF 页面)并将其发送到 GPT-4V 以响应查询。
  2. 将每个 PDF 页面视为图像,让 GPT-4V 对每个页面进行图像推理。为图像推理构建文本向量存储索引。查询答案时,针对图像推理向量存储进行查询。
  3. 使用 Table Transformer 从检索到的图像中裁剪表格信息,然后将这些裁剪后的图像发送到 GPT-4V 以响应查询。
  4. 对裁剪后的表格图像应用 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.表格的“叛逆期”:不准确的解析可能会破坏表格结构: 表格在文档里就像个叛逆的青少…...

STM32F103_LL库+寄存器学习笔记02 - 开启SysTick(滴答定时器)中断

导言 《STM32F103_LL库寄存器学习笔记01 - 梳理CubeMX生成的LL库最小的裸机系统框架》上一章节对CubeMX生成的最小系统框架进行梳理,在此工程的基础上,梳理SysTick(滴答定时器)中断是怎样开启的?为什么SysTick中断会自…...

AI小白的第七天:必要的数学知识(概率)

概率 Probability 1. 概率的定义 概率是一个介于 0 和 1 之间的数,表示某个事件发生的可能性: 0:事件不可能发生。1:事件必然发生。0 到 1 之间:事件发生的可能性大小。 例如,掷一枚公平的硬币&#xf…...

SVN常用命令

SVN常用命令 基本操作命令 • 检出代码(Checkout):从SVN服务器获取代码到本地。 svn checkout [svn服务器url] [检出本地的path] 示例: svn checkout svn://47.106.183.193/helloworld ./ • 提交代码(Commit&…...

23种设计模式中的策略模式

在策略模式定义了一系列算法或策略,并将每个算法封装在独立的类中,使得它们可以互相替换。通过使用策略模式,可以在运行时根据需要选择不同的算法,而不需要修改客户端代码。 策略模式:Strategy。指的是,定义…...

车载通信方案为何选择CAN/CANFD?

摘要 随着汽车电子技术的飞速发展,车载通信系统在车辆的智能化、网联化进程中扮演着至关重要的角色。控制器局域网络(CAN)及其扩展版本CANFD凭借其卓越的可靠性、高效的数据传输能力和强大的抗干扰特性,成为现代汽车通信架构的核心…...

有价值的面试问题

迅雷一面 都是c和网络问题 了解epoll吗?解释下水平触发和边缘触发,医院的叫号系统应该算哪一种 c类a有成员b,成员b调用了a的函数,但是a不小心把b的成员删除了,会发生什么,怎么解决 c类a有一个static的函数…...

深度学习|表示学习|多头注意力在计算时常见的张量维度变换总结|28

如是我闻: 以下是多头注意力(Multi-Headed Attention)在计算时常见的张量维度变换总结,帮助理解从输入到输出是如何一步步处理的。为了方便,令: B B B 表示 batch size(批量大小) S …...

Mysql内置函数篇

🏝️专栏:Mysql_猫咪-9527的博客-CSDN博客 🌅主页:猫咪-9527-CSDN博客 “欲穷千里目,更上一层楼。会当凌绝顶,一览众山小。” 目录 7.函数 7.1 日期函数 函数总:​编辑 获得当前日期 获得…...

使用事件监听器来处理并发环境中RabbitMQ的同步响应问题

RabbitListener 是 Spring AMQP 提供的核心注解,用于简化 RabbitMQ 消息监听器的创建。以下是对 RabbitListener(queues "balloonWords.queue") 的详细解析: 一、基础功能 队列监听 通过 queues 属性指定监听的队列名称(如 "…...

基于Java的班级事务管理系统(源码+lw+部署文档+讲解),源码可白嫖!

摘要 随着世界经济信息化、全球化的到来和电子商务的飞速发展,推动了很多行业的改革。若想达到安全,快捷的目的,就需要拥有信息化的组织和管理模式,建立一套合理、畅通、高效的线上管理系统。当前的班级事务管理存在管理效率低下…...

Rviz 同时显示多个独立 URDF!解决双机械臂+底盘等场景(球体+方块实例演示)

视频讲解: Rviz 同时显示多个独立 URDF!解决双机械臂底盘等场景(球体方块实例演示) 仓库地址:GitHub - LitchiCheng/ros2_package 有小伙伴留言说想看下同时使用多个独立的urdf如何配置,实际上这个场景是很…...

【C++】--- 类和对象(中)之日期类的实现

日期类的实现 1. 应该实现哪些默认成员函数 构造函数是需要自己来实现的,因为日期类的成员变量都是内置类型,是否初始化取决于编译器,这里可以给出一个带参全缺省的构造函数,由于日期类不需要申请资源,所有不用显式的实现析构函…...

kafka基础

一:消息队列(message queue [MQ]): 1.1消息队列解释:用来存储消息的队列 简单理解就是将需要的数据传输到队列里,队列可存可取,like 一个管道,但是与hdfs不同的是kafka作为临时存储 1.2消息队列中间件 消息队列中间件其实就是一个组件,简单例子就是用户对于服务器产…...

蓝桥杯第十届 特别的数

题目描述 小明对数位中含有 2、0、1、9 的数字很感兴趣(不包括前导 0),在 1 到 40 中这样的数包括 1、2、9、10 至 32、39 和 40,共 28 个,他们的和是 574。 请问,在 1 到 n 中,所有这样的数的…...

fpga pcie

pcie reg 介绍 debug pcie issue using lspci & setpci 介绍了lspci & setpci用法, 以及fpga pcie调试过程中重点关注的reg Lspci -tv Sudo lspci -vvv -s 18:00.0 Sudo lspci -nvmms 18:00.0 setpci --dumpregs setpci -s 18:00.0 COMMAND #&#x…...

模数转换电路(A/D转换器)

A/D转换,是将输入的模拟电压量转换成相应的数字量。 A/D转换器的类型很多,按工作原理可分为直接转换型和间接转换型两大类。前者直接将模拟电压量转换成数字量,后者是先将模拟电压量转换成一个中间量,再将中间量转换成数字量。 …...

PAT乙级1007

常规解法 #include <iostream> using namespace std;// 判断一个数是否为素数的函数 bool isprime(int a) {// 遍历 2 到 sqrt(a) 之间的数&#xff0c;判断 a 是否能被它们整除for (int i 2; i * i < a; i) {if (a % i 0) // 如果能整除&#xff0c;说明 a 不是素…...

代码随想录刷题day52|(二叉树篇)106.从中序与后序遍历序列构造二叉树

目录 一、二叉树理论知识 二、构造二叉树思路 2.1 构造二叉树流程&#xff08;给定中序后序 2.2 整体步骤 2.3 递归思路 2.4 给定前序和后序 三、相关算法题目 四、易错点 一、二叉树理论知识 详见&#xff1a;代码随想录刷题day34|&#xff08;二叉树篇&#xff09;二…...

MTK平台 Android12-Android13 默认搜狗输入法

系统默认搜狗输入法功能实现 文章目录 需求&#xff1a;场景 参考资料需求实现内置搜狗输入法配置第三方apk .mk 和 搜狗安装包&#xff0c;不可卸载方式搜狗输入法module 配置到系统device.mk 中去 设置搜狗输入法为默认输入法给输入法授权&#xff0c;默认所有权限 总结思考 …...

vue3实现动态路由

文章目录 一、基础信息1.路由构成2.菜单配置表3.vue-router4方法 二、实现思路1.登录获取菜单配置表2.导航守卫3.添加动态路由4.渲染菜单5.退出登录删除动态路由 三、实现代码1.路由守卫2.基础路由文件3.添加动态路由逻辑4.待特殊处理路由配置表5.404类路由6.删除动态路由 场景…...

行为型设计模式

深入理解行为型设计模式&#xff1a;模板方法、观察者、责任链 设计模式是软件开发中解决常见问题的经典方案&#xff0c;而行为型设计模式尤其关注对象之间的职责分配与通信方式。本文将详细讲解模板方法模式、观察者模式和责任链模式。 一、模板方法模式&#xff08;Templat…...

【服务器环境安装指南-指定 cuda 版本】在 Ubuntu 22.04 上完成 cuda-toolkit 12.0 和 cudnn 12.x 的安装教程

0.引言 在深度学习和高性能计算领域&#xff0c;CUDA 和 cuDNN 是不可或缺的工具。为充分发挥硬件性能&#xff0c;我们需要在服务器环境中正确配置这些工具。然而&#xff0c;安装过程中可能会遇到诸多挑战&#xff0c;例如版本兼容性和环境变量设置等问题。本篇文章将以 Ubu…...

蓝桥杯第十届 数的分解

题目描述 本题为填空题&#xff0c;只需要算出结果后&#xff0c;在代码中使用输出语句将所填结果输出即可。 把 2019 分解成 3 个各不相同的正整数之和&#xff0c;并且要求每个正整数都不包含数字 2 和 4&#xff0c;一共有多少种不同的分解方法&#xff1f; 注意交换 3 个…...

二叉搜索树

目录 概念 代码实现 成员 基本结构 查找 插入 删除 中序遍历 拷贝构造 赋值运算符重载 析构函数 递归实现 递归实现查找 递归实现插入 递归实现删除 概念 关于二叉树的基本结构已经进行过详细剖析&#xff0c;本篇博客将对一种特殊的二叉树进行分析。 二叉树&…...

Linux多线程详解

Linux多线程详解 一、Linux多线程概念1.1 什么是线程1.2 进程和线程1.3 进程的多个线程共享1.4 进程和线程的关系 二、Linux线程控制2.1 POSIX线程库2.2 线程创建2.3 获取线程ID pthread_self2.4 线程等待pthread_join2.5 线程终止2.6 线程栈 && pthread_t2.7 线程的局…...

攻防世界-web-1

Training-WWW-Robots 在URL后面加上/robots.txt 直接在URL后面添加/fl0g.php PHP2 他问我能不能登录这个网站&#xff0c;又因为考察php内容&#xff0c;在URL后面添加/index.php&#xff0c;无任何回显 试试/index.phps 分析一下代码&#xff0c;发现要用get方式上传idadmin,…...

笔记本+移动端维修全套教程

今天分享的是笔记本移动端维修全套教程&#xff08;免费视频资料大全&#xff09; 当自己手机或者电脑坏了&#xff0c;很多人都会想着去维修店铺修&#xff0c;但价格不透明&#xff0c;容易被坑&#xff0c;当自己了解一些之后&#xff0c;即使不会修&#xff0c;也可以对手…...

【STM32】知识点介绍二:GPIO引脚介绍

文章目录 一、概述二、GPIO的工作模式三、寄存器编程 一、概述 GPIO&#xff08;英语&#xff1a;General-purpose input/output&#xff09;,即通用I/O(输入/输出)端口&#xff0c;是STM32可控制的引脚。STM32芯片的GPIO引脚与外部设备连接起来&#xff0c;可实现与外部通讯、…...

【STM32】GPIO

目录 1、什么是GPIO2、什么是GPIO组3、GPIO的基本结构4、GPIO位结构5、GPIO八种工作模式6、GPIO相关寄存器1. 端口配置低寄存器GPIO[x]_CRL和端口配置高寄存器GPIO[x]_CRH, Config Register High和Config Register Low)2. 端口输入数据寄存器(GPIO[x]_IDR)3. 端口输出数据寄存器…...

鸿蒙移动应用开发--UI组件布局

实验要求&#xff1a; 制作一个B站视频卡片界面&#xff0c;大致如下图所示&#xff0c;要求应用到线性布局、层叠布局等相关课堂知识。背景图、logo及文本内容不限。 实验环境 &#xff1a;DevEco Studio 实验过程&#xff1a; 步骤1&#xff1a;创建项目 1. 在您的开发环境…...

[MySQL]MySQL数据库基础知识与操作

MySQL基础知识 为什么要有数据库&#xff1f; 文件存储的缺点 1.没有以某种特定的数据格式存储数据&#xff0c;查找不方便&#xff0c;只能遍历2.安全性&#xff1a;数据误操作后不能回滚3.每次操作数据都要用户自己操作4.数据量大的时候&#xff0c;操作的成本很高 创建一…...

卡诺图化简法的原理

引子 若两个最小项只有一个因子不同&#xff0c;则称这两个最小项具有相邻性。 例如&#xff0c; A ′ B C ′ ABC A′BC′和 A B C ABC ABC两个最小项仅第一个因子不同&#xff0c;所以它们具有相邻性。这两个最小项相加时定能合并成一项并将一对不同的因子消去 A ′ B C ′…...

从零开始:使用Luatools工具高效烧录Air780EPM核心板项目的完整指南

本文将深入讲解如何使用Luatools工具烧录一个具体的项目到Air780EPM开发板中。如何使用官方推荐的Luatools工具&#xff08;一款跨平台、命令行驱动的烧录利器&#xff09;&#xff0c;通过“环境配置→硬件连接→参数设置→一键烧录”四大步骤&#xff0c;帮助用户实现Air780E…...

探秘Transformer系列之(18)--- FlashAttention

探秘Transformer系列之&#xff08;18&#xff09;— FlashAttention 文章目录 0x00 概述0.1 问题0.2 其它解决方案0.3 Flash Attention 0x01 背景知识1.1 GPU相关概念硬件概念运行单元内存 软件概念运行模式线程模型Grid & DeviceBlock & SMThread & SPThread &am…...

VUE2导出el-table数据为excel并且按字段分多个sheet

首先在根目录下建一个文件夹export用来存储export.js import * as XLSX from xlsxfunction autoWidthFunc(ws, data) {// 设置每列的最大宽度const colWidth data.map(row > row.map(val > {var reg new RegExp([\\u4E00-\\u9FFF], g) // 检测字符串是否包含汉字if (v…...

Android面试总结之Android RecyclerView:从基础机制到缓存优化

引言 在 Android 开发中&#xff0c;RecyclerView是高效展示列表数据的核心组件。其强大的性能源于独特的视图复用机制和四级缓存体系。本文将结合源码与示例&#xff0c;带你深入理解RecyclerView的工作原理与优化策略。 核心组件 RecyclerView&#xff1a;作为容器视图&am…...

【C#语言】C#文件操作实战:动态路径处理与安全写入

文章目录 ⭐前言⭐一、场景痛点⭐二、完整实现代码⭐三、关键技术解析&#x1f31f;1、动态路径处理&#x1f31f;2、智能目录创建&#x1f31f;3、安全的文件写入 ⭐四、进阶扩展方案&#x1f31f;1、用户自定义路径选择&#x1f31f;2、异常处理增强&#x1f31f;3、异步写入…...

react中 useEffect和useLayoutEffect的区别

useEffect 和 useLayoutEffect 都是 React 中用于处理副作用的 Hook&#xff0c;但它们在执行时机和用途上有一些关键区别。理解这些区别可以帮助你更好地选择适合的 Hook 来实现特定的功能。 1. 执行时机 useEffect&#xff1a; 异步执行&#xff1a;useEffect 是在组件渲染完…...

TDengine 中的系统信息统计

简介 TDengine 3.0 版本开始提供一个内置数据库 performance_schema&#xff0c;Performance_Schema 数据库中存储了系统中的各种统计信息&#xff0c;包括存储及性能有关统计数据。本节详细介绍其中的表和表结构。 PERF_APP 提供接入集群的应用&#xff08;客户端&#xff…...

C++可变参数

可变参数C风格的可变参数C风格可变参数的使用 C11可变参数模板递归展开参数包参数列表展开折叠表达式 STL中的emplace插入接口 可变参数 C风格的可变参数 可变参数是一种语言特性&#xff0c;可以在函数声明中使用省略号...来表示函数接受可变数量的参数。 例如典型的printf…...

建造者模式 (Builder Pattern)

建造者模式 (Builder Pattern) 是一种创建型设计模式,它将一个复杂对象的构建与其表示分离,使得同样的构建过程可以创建不同的表示。 一、基础 1.1 意图 将一个复杂对象的构建与其表示分离,使得同样的构建过程可以创建不同的表示。 1.2 适用场景 当创建复杂对象的算法应该…...

Thales靶机攻略

1.下载导入VBox&#xff0c;并启动靶机 靶机地址&#xff1a;https://download.vulnhub.com/thales/Thales.zip 解压后&#xff0c;在VBox中导入虚拟电脑。包含所有网卡的MAC地址。 导入完成&#xff0c;设置网卡模式为仅主机网络。开启靶机。 kali网卡更改为桥接模式。点击工…...

【redis】哨兵:搭建主从/哨兵节点详解和细节

文章目录 编排步骤搭建主从节点创建容器启动容器 搭建哨兵节点创建容器哨兵节点配置文件配置节点启动容器 主从/哨兵节点连入同一个局域网 编排步骤 分为两组 yml&#xff0c;先后启动 我们其实也可以用于一个 yml 文件&#xff0c;直接启动 6 个容器&#xff0c;但是&#x…...

零基础上手Python数据分析 (9):DataFrame 数据读取与写入 - 让数据自由穿梭

回顾一下,上篇博客我们学习了 Pandas 的核心数据结构 Series 和 DataFrame。 DataFrame 作为 Pandas 的 “王牌” 数据结构,是进行数据分析的基石。 但 DataFrame 的强大功能,还需要建立在 数据输入 (Input) 和 数据输出 (Output) 的基础上。 数据从哪里来? 分析结果又如何…...

Emacs 折腾日记(十九)——配置输入法和vim操作方式

上一篇文章中&#xff0c;我们将Emacs变得稍微好看了点。换成了自己喜欢的主题和颜色&#xff0c;这样每天用起来也比较养眼&#xff0c;不会特别排斥。本篇文章的主要任务就是配置输入法方便输入中文以及将vim的操作模式搬到Emacs中。进一步提到Emacs的可用性 配置中文输入法…...

Docker 镜像构建与优化

一、Dockerfile 构建镜像 1.1.拉取所需镜像 首先 docker pull 拉取一个 centos7 的镜像。 docker pull centos:7 下载 nginx 源码包。 官网&#xff1a;nginx: download wget https://nginx.org/download/nginx-1.26.3.tar.gz 1.2.解决 CentOS 7 安装源问题 因为原本的 …...

Mininet--moduledeps.py源码解析

整体构架概述 1. What is it moduledeps.py是Mininet网络模拟框架的模块依赖管理工具&#xff0c;用于动态管理Linux内核模块&#xff08;如Open vSwitch、TUN/TAP&#xff09;和验证系统环境。其核心目的是确保Mininet运行所需的底层模块和可执行文件已正确加载或存在&#…...

JAVA EE_多线程-初阶(一)

1.认识线程 1.1概念 1&#xff09;线程是什么 线程是在进程内部中进行运行的&#xff0c;可以把它想成一个“执行流“&#xff0c;每个线程负责执行线程内的部分代码&#xff0c;多个线程之间可以”同时“执行多个代码。 “同时”&#xff1a;指并行&#xff0c;采用分时复用…...

批量优化与压缩 PPT,减少 PPT 文件的大小

我们经常能够看到有些 PPT 文档明明没有多少内容&#xff0c;但是却占用了很大的空间&#xff0c;存储和传输非常的不方便&#xff0c;这时候通常是因为我们插入了一些图片/字体等资源文件&#xff0c;这些都可能会导致我们的 PPT 文档变得非常的庞大&#xff0c;今天就给大家介…...