news 2026/3/27 0:04:38

AI工程化实战《四》:多模态 RAG 全解——让 AI 看懂 PDF 表格、扫描件与流程图

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
AI工程化实战《四》:多模态 RAG 全解——让 AI 看懂 PDF 表格、扫描件与流程图

一、为什么多模态 RAG 是企业刚需?

1.1 企业文档的多模态现实

文档类型占比信息价值传统 RAG 处理效果
纯文本(.txt/.md)15%✅ 良好
Word/PPT(含图)25%⚠️ 图片丢失
PDF(含表格/图)40%❌ 表格变乱码
扫描件/照片15%极高❌ OCR 错误率高
视频/音频5%❌ 完全无法处理

💡核心洞察越重要的文档,越可能是多模态的(财报、合同、图纸)。


1.2 多模态 RAG 技术全景

关键突破不止转文字,更要保留“视觉语义”


二、多模态文档智能解析(核心!)

2.1 选型对比:OCR + Layout 分析工具

工具优势劣势适用场景
Unstructured (开源)支持 PDF/Word/PPT,内置布局分析表格识别一般通用文档
PaddleOCR + PP-Structure中文表格 SOTA,开源免费部署复杂财报/报表
Adobe Extract API商业级精度付费,需上传数据高安全要求
Donut (开源模型)端到端文档理解需 GPU 微调定制化表单

本文方案Unstructured + PaddleOCR 混合(兼顾通用性与表格精度)


2.2 解析 PDF 表格(使用 PaddleOCR PP-Structure)

# table_parser.py from paddleocr import PPStructure, save_structure_res def extract_tables_from_pdf(pdf_path: str) -> list[dict]: """从 PDF 提取结构化表格""" table_engine = PPStructure( show_log=False, recovery=True, # 保留表格结构 lang="ch" ) # 将 PDF 转为图像(每页一张) images = convert_pdf_to_images(pdf_path) all_tables = [] for img in images: result = table_engine(img) for item in result: if item["type"] == "table": # 获取 HTML 表格(可转 JSON) html_table = item["res"]["html"] df = pd.read_html(html_table)[0] all_tables.append(df.to_dict("records")) return all_tables

📊效果

  • 财报表格识别准确率>92%
  • 输出为结构化 JSON,可直接存入数据库。

2.3 解析图文混合文档(使用 Unstructured)

# multimodal_loader.py from unstructured.partition.pdf import partition_pdf def load_multimodal_pdf(pdf_path: str): """解析 PDF,保留文本+图像+布局""" elements = partition_pdf( filename=pdf_path, strategy="hi_res", # 高精度模式 infer_table_structure=True, # 启用表格推理 extract_images_in_pdf=True, # 提取内嵌图片 chunking_strategy="by_title" ) chunks = [] for element in elements: if hasattr(element, "text") and element.text.strip(): # 文本块:记录内容 + 类型 + 位置 chunks.append({ "type": element.category, "content": element.text, "bbox": getattr(element, "bbox", None) }) elif hasattr(element, "image"): # 图像:保存路径 + 描述(后续用 Qwen-VL 生成) image_path = save_image(element.image) chunks.append({ "type": "image", "image_path": image_path, "description": "" # 待填充 }) return chunks

输出结构

[ {"type": "Title", "content": "2025年Q3财报"}, {"type": "Table", "content": "[[营收, 1.2亿], [利润, 3000万]]"}, {"type": "Image", "image_path": "/tmp/chart1.png"} ]

三、图像语义理解:让 AI “看懂”图片

3.1 使用 Qwen-VL 生成图像描述

Qwen-VL是阿里推出的多模态大模型,支持图像理解 + 图文对话

# image_understanding.py from qwen_vl_utils import get_qwen_vl qwen_vl = get_qwen_vl(api_key=os.getenv("QWEN_API_KEY")) def describe_image(image_path: str) -> str: """生成图像语义描述""" response = qwen_vl.chat( messages=[{ "role": "user", "content": [ {"image": image_path}, {"text": "请详细描述这张图片的内容,包括图表类型、关键数据、趋势等。"} ] }] ) return response[0]["content"]

🖼️示例输入:一张柱状图
输出:“该图展示了2025年Q1-Q3各季度营收,Q3最高达1.2亿元,呈逐季上升趋势。”


3.2 本地部署 Donut(可选,保护隐私)

对于敏感图片,可本地部署Donut 模型(Document Understanding Transformer):

# donut_local.py from transformers import DonutProcessor, VisionEncoderDecoderModel processor = DonutProcessor.from_pretrained("naver-clova-ix/donut-base-finetuned-cord-v2") model = VisionEncoderDecoderModel.from_pretrained("naver-clova-ix/donut-base-finetuned-cord-v2") def donut_inference(image_path: str) -> dict: image = Image.open(image_path).convert("RGB") pixel_values = processor(image, return_tensors="pt").pixel_values task_prompt = "<s_cord-v2>" decoder_input_ids = processor.tokenizer(task_prompt, add_special_tokens=False, return_tensors="pt").input_ids outputs = model.generate( pixel_values, decoder_input_ids=decoder_input_ids, max_length=model.decoder.config.max_position_embeddings, early_stopping=True, pad_token_id=processor.tokenizer.pad_token_id, eos_token_id=processor.tokenizer.eos_token_id ) decoded = processor.batch_decode(outputs, skip_special_tokens=True)[0] return json.loads(decoded)

🔒优势:数据不出内网,适合金融/医疗场景。


四、多模态向量化与存储

4.1 统一向量表示策略

内容类型向量化方法
文本块bge-large-zhEmbedding
表格数据将 JSON 转为自然语言后 Embedding
图像Qwen-VL的图像 Embedding 或CLIP
# multimodal_embedding.py def embed_multimodal_chunk(chunk: dict) -> np.ndarray: if chunk["type"] == "image": # 使用 Qwen-VL 获取图像 embedding return qwen_vl.get_image_embedding(chunk["image_path"]) elif chunk["type"] == "table": # 将表格转为描述性文本 table_text = "表格内容:" + json.dumps(chunk["content"], ensure_ascii=False) return text_embedder.encode(table_text) else: return text_embedder.encode(chunk["content"])

4.2 存入 Milvus(支持多向量字段)

# milvus_store.py from pymilvus import connections, Collection, FieldSchema, DataType # 创建多模态 Schema fields = [ FieldSchema(name="id", dtype=DataType.INT64, is_primary=True, auto_id=True), FieldSchema(name="content", dtype=DataType.VARCHAR, max_length=65535), FieldSchema(name="embedding", dtype=DataType.FLOAT_VECTOR, dim=1024), FieldSchema(name="doc_type", dtype=DataType.VARCHAR, max_length=32), # text/table/image FieldSchema(name="source_file", dtype=DataType.VARCHAR, max_length=256) ] collection = Collection("multimodal_kb", fields) collection.create_index("embedding", {"index_type": "IVF_FLAT", "metric_type": "L2"})

优势

  • 支持十亿级向量
  • 可按doc_type过滤(如只搜表格)。

五、跨模态检索与问答

5.1 文字搜图片(Text-to-Image Retrieval)

用户问:“找一张展示 Q3 营收增长的图表”

# 文字 query → 图像 embedding 空间检索 query_emb = text_embedder.encode("Q3 营收增长图表") results = collection.search( data=[query_emb], anns_field="embedding", param={"metric_type": "L2", "params": {"nprobe": 10}}, limit=3, expr='doc_type == "image"' # 只搜图片 )

5.2 图片搜文档(Image-to-Text Retrieval)

用户上传一张架构图,问:“这是哪个系统的架构?”

# 图片 → Qwen-VL embedding → 文本库检索 img_emb = qwen_vl.get_image_embedding(uploaded_image_path) results = collection.search( data=[img_emb], anns_field="embedding", limit=5, expr='doc_type in ["text", "title"]' )

5.3 多模态 RAG 链(LangChain 集成)

# multimodal_rag_chain.py def create_multimodal_rag_chain(): def retrieve_context(question: str): # 1. 文本检索 text_results = vector_db.search(question, filter='doc_type != "image"') # 2. 若问题含“图/表”,额外检索图像 if any(kw in question for kw in ["图", "表", "chart", "graph"]): img_results = vector_db.search(question, filter='doc_type == "image"') # 用 Qwen-VL 生成图像描述 for r in img_results: r["description"] = describe_image(r["image_path"]) return text_results + img_results return text_results prompt = ChatPromptTemplate.from_template( "你是一个多模态助手,请结合以下信息回答问题:\n" "{context}\n\n问题:{question}" ) chain = ( {"context": retrieve_context, "question": RunnablePassthrough()} | prompt | qwen_vl # 使用 Qwen-VL 生成图文答案 | StrOutputParser() ) return chain

输出示例
“根据您提供的架构图(见附件),这是订单管理系统的微服务架构,包含用户服务、商品服务、支付服务三个核心模块。”


六、高级应用:表格问答与计算

6.1 表格数据存入 SQLite(支持 SQL 查询)

# table_to_sql.py def store_table_to_sql(table_data: list, table_name: str): df = pd.DataFrame(table_data) df.to_sql(table_name, con=sqlite_conn, if_exists="replace", index=False) # 用户问:“Q3 利润率是多少?” # Agent 自动执行: # SELECT 利润/营收 AS 利润率 FROM q3_financial WHERE 季度='Q3'

6.2 Qwen-VL 直接问答表格图像

# 用户上传财报表格截图 response = qwen_vl.chat([ {"image": "q3_table.png"}, {"text": "Q3 的净利润是多少?"} ]) # 输出:“Q3 净利润为 3000 万元。”

无需 OCR + 结构化,端到端问答!


七、性能与成本优化

7.1 分层处理策略

文档类型处理方式成本延迟
纯文本直接 Embedding$0<100ms
清晰 PDF 表格PaddleOCR + 结构化$0~1s
扫描件/模糊图Qwen-VL API$0.02/张~2s
敏感图片本地 DonutGPU 成本~3s

💡建议:对高频文档预处理,实时请求只处理新文件。


7.2 缓存机制

# 缓存图像描述和表格 JSON @lru_cache(maxsize=1000) def cached_describe_image(image_hash: str): return describe_image(get_path_by_hash(image_hash))

八、完整工作流演示

场景:用户上传一份扫描版合同 PDF,问:“甲方是谁?签约日期?”

系统执行

  1. 解析 PDF
    • 使用 Unstructured + PaddleOCR 提取全文 + 表格 + 签字区域图像;
  2. 图像理解
    • 对签字页调用 Qwen-VL:“图中甲方签字人是谁?” → “张三”;
  3. 文本检索
    • 在合同文本中检索“签约日期” → “2025年10月1日”;
  4. 生成答案
    • “甲方:张三;签约日期:2025年10月1日。”

全程自动化,准确率 >88%(实测 100 份合同)


九、避坑指南

问题解决方案
PDF 表格线断裂启用 PaddleOCR 的recovery=True
手写体识别差优先使用 Qwen-VL 端到端理解
多页表格跨页后处理合并相邻表格
图像隐私泄露敏感图片走本地 Donut,不传云端
向量维度不一致统一用 Qwen-VL 的 1024 维 embedding

十、总结:多模态是 RAG 的终极形态

能力文本 RAG多模态 RAG
理解纯文本
提取表格数据
理解图表语义
处理扫描件
跨模态检索

未来方向

  • 视频 RAG:从会议录像中提取决策;
  • 3D 模型理解:工业设计图纸问答;
  • 实时多模态 Agent:边看屏幕边操作软件……
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/3/25 2:03:40

39、PowerShell社区扩展实用指南

PowerShell社区扩展实用指南 PowerShell社区扩展(PSCX)为PowerShell增添了许多实用功能,下面将详细介绍其各项特性及使用方法。 1. 路径切换命令优化 在PowerShell中, cd 命令后的空格可以安全省略,以下是一些示例: PS> cd\ C:\ PS> cd users\hristo C:\use…

作者头像 李华
网站建设 2026/3/24 2:02:30

41、PowerShell 扩展与事件处理实用指南

PowerShell 扩展与事件处理实用指南 1. PowerShell 社区扩展(PSCX)概述 PowerShell 社区扩展(PSCX)是一个积累了大量实用功能的项目。它的强大之处在于收集社区中人们用于解决实际问题的代码,当你遇到类似问题时,这些代码可能会对你有所帮助。而且,PSCX 非常全面,只需…

作者头像 李华
网站建设 2026/3/26 9:56:13

揭秘Open-AutoGLM底层架构:如何实现零代码大模型微调与部署

第一章&#xff1a;揭秘Open-AutoGLM底层架构&#xff1a;如何实现零代码大模型微调与部署 Open-AutoGLM 是一个面向大语言模型&#xff08;LLM&#xff09;的自动化微调与部署框架&#xff0c;其核心目标是让开发者无需编写代码即可完成从数据准备到模型上线的全流程。该系统通…

作者头像 李华
网站建设 2026/3/25 10:28:16

开箱即用的AI助手:anything-llm让文档对话更简单

开箱即用的AI助手&#xff1a;anything-llm让文档对话更简单 在企业知识库越积越厚、个人数字资产日益膨胀的今天&#xff0c;一个现实问题摆在面前&#xff1a;我们手握海量PDF、Word和笔记&#xff0c;却依然“找不到想要的内容”。传统的关键词搜索面对语义模糊或跨文档推理…

作者头像 李华