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

【Task3】【Datawhale AI夏令营】多模态RAG

科大讯飞AI大赛(多模态RAG方向)

夏令营:让AI读懂财报PDF(多模态RAG)

目前正在尝试在autodl平台上使用4090显卡,将原来baseline使用的fitz改进为MinerU,目前遇到了的错误:

ModuleNotFoundError: No module named ‘image_utils’

缺少image_utils

一开始以为是要安装image_utils包,结果安装后发现仍然缺少调用函数。

卸载image_utils包

从开源仓库下载好正确的image_utils后,目前仍然在继续尝试中。

下面是教程:

copy from 侵删

💡
欢迎回到Datawhale AI夏令营第三期,多模态RAG 方向的学习~

我们将聚焦在「多模态RAG图文问答挑战赛」的赛事项目实践。

作为此次项目实践的最后一个Task,我们将—— 了解更多上分思路!

恭喜你已经完成了Baseline的跑通和赛题理解!这已经超越了80%的参赛者。

在跑通 Baseline 之后,相信我们已经对多模态RAG有了一个基本的认识和实践。

Baseline 方案提供了一个完整的流程,解决了从零到一的问题。接下来,我们要讨论的是如何在这个基础上做得更好。

在这个部分,我们将一起分析 Baseline 的局限性,从几个方面来考虑设计和优化RAG系统,学习三个核心的进阶方向:

使用 MinerU 实现高保真文档解析 :从源头上提升我们知识库的质量。

微调 Embedding 模型 :让我们的检索模块更懂金融领域的专业表达。

微调大语言模型 :训练一个更听话、更专业的问答生成器。

这部分内容会更有挑战性,但掌握了它们,你将能真正深入这个赛题的核心,并具备独立设计和优化高级RAG系统的能力。我们开始吧!

一、我们先回顾一下赛题任务

赛题背景

我们面对的不是干净的纯文本,而是信息量巨大、格式复杂的真实财报PDF。这些文件里文字、图表、表格交织在一起,传统的文本处理技术难以有效利用全部信息,因此需要引入多模态处理能力。

赛题目标

构建一个基于给定PDF知识库的、可溯源的多模态问答系统。简单来说,系统需要“读懂”这些图文混排的PDF,并能准确回答相关问题,同时必须明确指出答案来自哪个文件的哪一页。

评估标准

最终分数由三部分构成,总分为1分。这个评分机制强调了 答案准确性 和 来源可追溯性 并重:

答案内容相似度 (0.5分)

文件名匹配准确率 (0.25分)

页码匹配准确率 (0.25分)

数据集

我们手上有三份材料:

知识库 (财报数据库.zip) : 唯一的、封闭的信息来源,包含多个图文混排的PDF文件。

训练集 (train.json) : 提供“问题-答案-来源”的标注样本,用于系统开发和验证。

测试集 (test.json) : 只包含问题,是我们需要处理并提交结果的目标。

挑战与难点

多模态信息融合 :如何让系统理解文本与图表之间的关联。

检索的信噪比 :如何在海量信息中精准召回最相关的上下文,避免无关信息干扰。

生成的可控性 :如何让大模型忠实于原文作答,并准确溯源,而不是自由发挥。

细粒度信息抽取 :答案可能隐藏在某个表格的单元格或图表的特定部分,对文档解析的精度要求很高。

二、了解一下Baseline方案的优点和不足
在开始之前,确保你的代码内容是最新的,作者更新最快的代码仓库在:https://github.com/li-xiu-qi/spark_multi_rag上

我们先来看看 Baseline 方案。它的好处是逻辑清晰,遵循了“解析-分块-检索-生成”的流程,让我们能快速上手。同时,它的各个部分相对独立,方便我们替换和修改。

优点

逻辑清晰 :整个流程遵循“解析-分块-检索-生成”的经典RAG范式,简单易懂。

端到端完整 :提供了一个可以完整跑通并提交结果的框架,是很好的学习起点。

模块化 :各个组件相对独立,方便我们对其中任一部分进行替换和升级。

不足

文档解析粗糙 :这是最核心的短板。Baseline 使用的 PyMuPDF 只能提取纯文本,完全 丢失了表格、图片 等关键的多模态信息,同时也破坏了原有的版面布局。财报中的大量核心数据都在图表中,这一损失是致命的。

分块策略单一 :按“页”分块过于粗暴。一个完整的表格或逻辑段落可能被硬生生切开,破坏了信息的上下文完整性。

检索精度有限 :仅靠基础的向量相似度检索,对于包含特定术语或需要精确匹配的问题效果不佳,且容易引入噪音。

模型泛用性 :无论是 Embedding 模型还是 LLM,我们用的都是通用预训练模型,它们并没有针对“金融财报”这个垂直领域进行优化,理解上会存在偏差。

针对以上不足,我们可以规划出一条清晰的优化路径,对baseline方案进行修改,这也是我们进阶教程的核心脉络:

升级数据解析核心 :放弃 PyMuPDF, 切换到 MinerU 。利用 MinerU 强大的版面分析能力,提取出包含表格(转为Markdown)、图片、以及带有层级结构(标题、段落)的文本内容。这是提升分数上限关键的一步。

优化分块与索引策略 :有了 MinerU 精细化的解析结果,我们可以进行对 图片进行进一步的内容解释,添加图片的描述信息。

引入重排(Re-ranking) :在检索(Retrieve)环节后增加一个 重排步骤,选出最相关的几个结果,提高给到大语言模型的上下文质量。

先用向量检索召回一个较粗泛的候选集(如Top 20),

再用一个更精准的重排模型对这20个候选项进行打分排序,

选取真正的Top K(如Top 3-5)喂给LLM,大幅提升信噪比。

实施模型微调 :让模型更适应财报问答的场景。

微调Embedding模型 :利用 train.json 中的问答对构造训练数据,让模型学习财报领域的语义关系,提升检索召回的准确率。

微调LLM :利用 train.json 构造“指令-上下文-回答”格式的数据,对LLM进行指令微调。主要目的是让LLM更“听话”,能更忠实地根据我们提供的上下文作答,并严格按照要求的格式输出答案和来源。

运行全量测试数据:

💡
baseline里面的代码默认只运行了10条测试数据,只需要修改一个变量就能在baseline的基础上得到较大的分数提升

修改rag_from_page_chunks.py文件里面的变量TEST_SAMPLE_NUM,将原来的10改成None,运行全量的测试数据会消耗比较久的时间,大概会消耗20分钟左右。

图片

三、一起分析赛题的进阶要点

这个赛题的核心,是考察构建一个信息完整、结果精确的RAG系统的能力。系统的表现好坏,取决于知识库的构建、检索的准确性和生成的可控性这几个环节。

进阶要点1:提取文档的多模态内容
一个重要的部分是文档解析和多模态内容的理解。

RAG的效果很大程度上依赖于知识库的质量。如果源头就是有信息损失的,后续再怎么处理效果也有限。

像 MinerU 这样的工具能帮助我们进行版面分析,区分出标题、段落、表格和图片,并且能把表格转换成 Markdown 这种结构化格式。

这样处理后,知识库的内容就比纯文本丰富多了。

对于解析出来的图片,我们可以用多模态大模型,比如 Qwen-VL,来生成文字描述,把图片信息也文本化,方便后续的检索。

相关的资料可以查看 MinerU 和 Qwen-VL 在 GitHub 上的项目仓库。

加入mineru进行解析,我们的项目流程图就会变成这样:

图片

其中使用mineru进行解析内容的版本在我们的github仓库内是有提供的,文件名字叫做mineru_pipeline_all.py,

感兴趣的同学可以直接使用他进行生成all_pdf_page_chunks.json提供给后续的知识库构建使用。

图片
具体的参考代码如下:

💡
(点击右侧◀展开查看 mineru_pipeline_all.py 参考代码)

这段代码的核心目标是搭建一个自动化的数据预处理流水线。

它的作用是接收原始的 PDF 文件,然后通过一系列步骤,最终生成一个结构化的 JSON 文件( all_pdf_page_chunks.json )。

这个 JSON 文件就是我们构建 RAG 知识库所需要的最终材料,里面的每一项都是一个知识块,可以直接用于后续的向量化和索引。

我们可以把整个过程理解成一个三步走的流水线。

💡
第一步:用 MinerU 解析 PDF ( parse_all_pdfs 函数)

💡
第二步:将解析结果整理成 Markdown 格式 ( process_all_pdfs_to_page_json 函数)

💡
第三步:汇总所有内容,生成最终的知识库文件 ( process_page_content_to_chunks 函数)

进阶要点2:“粗召回”与“精召回”的检索策略
另一个要点是检索策略。

当知识库内容更丰富后,如何精确查找就变得更重要。

我们可以采用一个两步走的检索策略,也就是先“召回”再“重排”。

第一步“召回”,用向量检索或者关键词检索(比如BM25算法),快速地找到一个比较大的候选范围,目的是把相关的都找出来。

第二步“重排”,用一个更精准的重排模型,比如 FlagEmbedding 仓库里的 BGE-ReRanker 模型,来给这些候选项和问题的相关性打分,然后选出分数最高的几个。

这种方式能有效地提升检索结果的信噪比。

其中rerank的模型可以使用FlagEmbedding进行推理:

from FlagEmbedding import FlagReranker

model = FlagReranker(
‘BAAI/bge-reranker-large’,
use_fp16=True,
devices=[“cuda:0”], # 如果没有 GPU,可以使用 “cpu”
)

pairs = [
[“法国的首都是什么?”, “巴黎是法国的首都。”],
[“法国的首都是什么?”, “中国的人口超过14亿人。”],
[“中国的人口是多少?”, “巴黎是法国的首都。”],
[“中国的人口是多少?”, “中国的人口超过14亿人。”]
]

scores = model.compute_score(pairs)
scores

运行上面的代码后会输出:

[7.42578125, -9.2421875, -9.484375, 5.51953125]

四、还可以尝试尝试这些进阶方法和思路
还有哪些创新性的 方案和方向 可以去思考?

如何想出、实现更多创新、多元的方案?

进阶思路1:多路召回与融合
除了上面提到的优化点,我们还可以看看其他一些方案。

我们还可以尝试多路召回与融合的思路。这个方法的核心是同时使用多种不同的检索方式,从不同角度去寻找相关的知识块,然后再把找到的结果合并起来。

比如,我们可以并行运行两种检索:一种是基于关键词的检索,像 BM25 算法,它擅长匹配问题中出现的具体词语;另一种是基于向量的语义检索,使用 embedding 模型来查找意思相近但用词可能不同的内容。这样,两条通路可以形成优势互补。

图片
在从不同通路拿到各自的召回结果列表后,接下来的问题就是如何把它们融合成一个更高质量的排序。

这里通常有两种处理思路:

第一种是使用重排模型(Re-ranker)。

我们可以把所有通路召回的结果汇总到一起,然后用一个重排模型,比如基于 FlagEmbedding 的模型,来对这个大集合进行统一的、更精细的相关性打分,最后选出分数最高的几个结果。

第二种是使用无需训练模型的融合算法,

一个常见的例子是倒数排名融合(Reciprocal Rank Fusion, RRF)。

这种方法会根据每个文档在不同召回列表中的排名位置,来计算出一个综合分数,然后根据这个综合分数生成一个新的排序。

无论采用哪种融合方式,最终的目标都是得到一个排序更优的上下文列表,再将这个列表交给大语言模型去生成答案。

进阶思路2:构建知识图谱
还有一个方向是构建知识图谱。现在我们的知识库里的知识块是相互独立的,但原文中它们是有结构联系的。

我们可以把一份文档表示成一个知识图谱,里面的节点可以是段落、表格、图表、公司名等实体,边则表示它们之间的关系,比如“位于”、“描述”或者“属于”。

这样,在回答一些需要多步推理的问题时,就可以通过图谱的查询来找到答案。

图片

进阶思路3:让RAG系统拥有自我修正的能力
我们甚至可以考虑让RAG系统拥有自我修正的能力。

具体来说,就是让系统在检索一次之后,能自己判断一下找到的上下文够不够回答问题。

如果不够,它可以自己生成一个新的、更具体的查询语句,再次进行检索,把两次的结果合在一起再生成答案。

这会让整个问答过程更动态一些。

图片

进阶思路4:模型微调
整个微调流程可以分为两大步: 数据准备 和 模型训练 。主要涉及到 spark_data_process.ipynb 和 spark_model_finetune.ipynb 两个文件。

4.1 数据准备 (spark_data_process.ipynb)

模型微调的第一步,也是最关键的一步,是准备高质量的训练数据。

我们的目标是利用官方提供的 train.json ,将其转换为模型能够理解的“指令-输入-输出”格式。

这一过程在 spark_data_process.ipynb 中完成。

核心目标 :将原始的问答数据,转换为符合Alpaca指令格式的 qa_train.json 文件。

💡
点击右侧◀展开 spark_data_process.ipynb参考代码

spark_data_process.ipynb 的核心逻辑是将每个问答对(Q&A pair)包装成一个结构化的字典。

输入与输出 : input 字段对应原始问题,output 字段对应标准答案。模型在训练时会学习到,在收到这样的 instruction 和 input 后,应该生成类似 output 的回答。

最终产物 :执行该脚本后,我们会得到 qa_train.json 文件,这是下一步模型训练的直接输入。

我们通过提供一个固定的 instruction (指令),作为学习材料,通过微调教会模型在我们这个财报任务下的“角色”和“任务”。

这使得模型在面对新的问题时,能更好地按照我们期望的身份和方式来回答。

4.2 模型训练 (spark_model_finetune.ipynb)
有了标准格式的训练数据,我们就可以开始进行模型的有监督微调(Supervised Fine-Tuning, SFT)。

我们在参考代码中使用了 unsloth 框架高效微调 Qwen2.5-7B 。

💡

  1. 环境配置与模型加载

💡
2. 添加LoRA适配器

💡
3. 加载并格式化数据

💡
4. 配置并启动训练

💡
5. 推理验证与模型保存

通过以上步骤,我们就完成了一次完整的模型微调。得到的 lora_model 文件夹包含了微调后的模型权重,可以在RAG的生成环节加载它。

通过系统的模型微调,我们可以显著提升RAG系统在财报问答任务上的表现。

微调后的模型不仅能更准确地理解财报术语,还能更好地遵循输出格式要求,为最终的评分提升打下坚实的基础。

不过数据量可能需要进一步的扩展,因为训练集可能还是属于比较少的,如果需要真正能提高在排行榜上的分数,还是建议去做一些数据工程。

附录:补充知识点概述
Re-ranking ,中文叫重排。它是在RAG检索流程中,初步召回一批候选内容后,用一个更精准的模型对这些内容与问题的相关性重新排序的步骤。

Hybrid Search ,混合检索。它通常指结合了关键词检索(如BM25)和向量检索两种方式的检索策略,能同时利用两种方法的优点。

Vision-Language Model (VLM) ,视觉语言模型,也就是我们说的多模态大模型。它能同时处理图像和文本信息。

Knowledge Graph ,知识图谱。它是一种用图的结构来表示知识和实体间关系的方法。

更多参考资料推荐
为什么你的RAG效果总差一点?从RankNet到Qwen,一文读懂Rerank模型的演进:

https://mp.weixin.qq.com/s/10Tx71A8SMj4ja_wVoYeTg

RAG系统召回率低? BGE-M3 多语言多功能重塑文本检索:

https://mp.weixin.qq.com/s/1PURiKFP1WBx6VnScszm3A

多模态RAG的三类图文问答实现方式,你知道多少种?:

https://mp.weixin.qq.com/s/FXyjbalyDB21RFOVW1O_RA

搭建RAG系统时,可能会遇到的7个具体问题:

https://arxiv.org/html/2401.05856v1

一种带有“自我修正”能力的RAG方法:

https://arxiv.org/abs/2401.15884

LlamaIndex 是一个专门用来构建RAG应用的框架:

https://docs.llamaindex.ai/en/stable/

Hugging Face 官方提供的模型训练指南:

https://huggingface.co/docs/transformers/training

Unsloth 是一个高效训练模型的框架:

https://docs.unsloth.ai/

LangGraph是用来构建有状态、多步骤应用的程序库:

https://github.com/langchain-ai/langgraph

MinerU是功能强大的文档解析工具,能将PDF精准地转换为结构化的Markdown或JSON:

https://mineru.net/

https://github.com/opendatalab/MinerU

http://www.dtcms.com/a/324836.html

相关文章:

  • 3.4路由守卫
  • Words or Vision Do Vision-Language Models Have Blind Faith in Text
  • Java中new的相关知识
  • nginx-主配置文件
  • Redis的批处理优化
  • 【高等数学】第八章 向量代数与空间解析几何——第六节 空间曲线及其方程
  • ECP HRFORM 提示ADS服务异常
  • 【嵌入式电机控制#补充3】SDK电机控制台的功能
  • C9800在NAT设备之后怎么办?
  • [创业之路-541]:经营分析会 - 企业的经营分析会,研发负责人负责提供哪些信息?
  • Linux810 shell 条件判断 文件工具 ifelse
  • 【牛客刷题】小红的项链(字节跳动面试题)
  • Linux操作系统从入门到实战(十七)进程与进程基本概念
  • doubletrouble靶机攻略
  • Docker 数据卷的核心原理与管理逻辑
  • 【数据结构与算法-Day 14】先进先出的公平:深入解析队列(Queue)的核心原理与数组实现
  • 端口扫描器用户使用手册 (EXE版)
  • JavaScript 变量:数据存储的核心机制
  • C++ 黑马 内存分配模型
  • 详解Windows(十六)——计划任务
  • Linux安装Jenkins-2.432,jdk17
  • Day11 原理篇
  • 华为防火墙配置指南【附实战案例】
  • python urllib模块怎么使用
  • 【软件测试】概念篇 — 详解
  • 广东省省考备考(第七十二天8.10)——言语理解与表达、判断推理(强化训练)
  • APISIX 路由优先级
  • SupChains团队:化学品制造商 ChampionX 供应链需求预测案例分享(十七)
  • 托福阅读记录
  • TypeScript 中的as const是什么?