RAG 进阶:多模态图片检索技术实践
本文介绍了基于 LangChain 和 LlamaIndex 框架实现多模态 RAG 的技术方案。通过 unstructured 库提取 PDF 中的图片,利用 GPT-4V 生成图片摘要,并结合 MultiVectorRetriever 将原始图片与摘要向量关联。最终实现了对包含图表的金融报告进行图文混合检索,解决了传统文本 RAG 无法理解图像内容的痛点。文章涵盖了环境配置、图片提取、摘要生成、向量存储及查询验证的全过程,并分析了潜在挑战与优化方向。

本文介绍了基于 LangChain 和 LlamaIndex 框架实现多模态 RAG 的技术方案。通过 unstructured 库提取 PDF 中的图片,利用 GPT-4V 生成图片摘要,并结合 MultiVectorRetriever 将原始图片与摘要向量关联。最终实现了对包含图表的金融报告进行图文混合检索,解决了传统文本 RAG 无法理解图像内容的痛点。文章涵盖了环境配置、图片提取、摘要生成、向量存储及查询验证的全过程,并分析了潜在挑战与优化方向。

在 LlamaIndex 和 LangChain 框架的学习过程中,我们通常处理的是纯文本数据。然而,现实世界中的文档往往包含丰富的非结构化信息,如图片、图表、表格等。本文旨在探讨如何将单一文本模态的 RAG(检索增强生成)升级为多模态 RAG,使系统具备读图、搜图的能力。
传统的 RAG 系统主要处理 PDF 中的文本和表格数据。虽然 unstructured 库和 MultiVectorRetriever 已经能很好地处理半结构化数据,但对于图片、声音、视频等非结构化数据的理解能力仍然不足。大模型技术的发展,特别是多模态模型的出现,为这一领域带来了新的解决方案。
多模态模型(Multimodal Model)能够同时处理多种类型的数据输入。例如,GPT-3.5-turbo 仅支持文生文,属于单一模态模型;而 OpenAI 发布的 GPT-4V(Vision)则是一款典型的多模态模型,它不仅能接受文本指令,还能直接解析图像内容并返回文字描述。这种能力的升级,使得 RAG 系统可以直接利用视觉信息进行检索和推理。
为了演示多模态 RAG 的效果,我们选取了一份来自摩根大通(JPMorgan)的每周市场回顾报告作为测试数据。该 PDF 文件包含文本、图表(图片)、表格等多种模态的混合数据,非常适合用于验证系统的图文处理能力。
首先,确保安装了必要的 Python 库。除了常规的 LangChain 和 LlamaIndex 组件外,还需要 unstructured 库来处理文档解析,以及 Pillow 等图像处理库。
pip install langchain langchain-community unstructured[all-docs] openai pillow
下载目标 PDF 文件到本地目录:
import os
os.makedirs("data", exist_ok=True)
!wget -o data/weekly_market_recap.pdf https://am.jpmorgan.com/content/dam/jpm-am-aem/americas/us/en/insights/market-insights/wmr/weekly_market_recap.pdf
使用 GPT-4V 需要有效的 OpenAI API Key,且账号需具备访问 Vision 模型的权限。
import os
os.environ["OPENAI_API_KEY"] = "Your_OpenAI_API_Key"
我们继续使用 unstructured 库提供的 partition_pdf 函数来抽取 PDF 中的不同元素。与处理纯文本不同,多模态场景下必须启用图片提取功能。
from typing import Any
from pydantic import BaseModel
from unstructured.partition.pdf import partition_pdf
# 创建图片输出目录
images_path = "./images"
os.makedirs(images_path, exist_ok=True)
raw_pdf_elements = partition_pdf(
filename="data/weekly_market_recap.pdf",
extract_images_in_pdf=True, # 关键参数:开启图片提取
infer_table_structure=True, # 尝试推断表格结构
chunking_strategy="by_title", # 按标题分块
image_output_dir_path=images_path # 指定图片保存路径
)
将 extract_images_in_pdf 设置为 True 后,unstructured 会自动识别 PDF 中的图像对象并将其保存为独立的图片文件。执行代码后,我们可以观察到 GPU 资源的消耗,这是因为底层可能调用了如 microsoft/table-transformer-struct-recognition 等模型进行辅助分析。
通过命令行查看生成的图片列表:
ls -alt images/
程序会输出类似以下的文件列表,这些即为从 PDF 中抽离出的原始图表和图片:
我们可以使用 IPython 的 Image 类来预览其中一张图片,确认提取是否完整。
为了让向量数据库能够检索图片,我们需要将图片转换为可嵌入的文本表示。由于图片本身无法直接计算向量,我们利用多模态大模型(如 GPT-4V)为每张图片生成一段描述性的摘要(Summary)。这段摘要将作为检索的依据。
我们封装了一个 ImageSummarizer 类,负责读取图片、编码并调用 LLM 生成摘要。
import base64
from langchain.chat_models import ChatOpenAI
from langchain.schema import HumanMessage
class ImageSummarizer:
def __init__(self, image_path: str) -> None:
self.image_path = image_path
# 提示词工程:明确角色和任务,优化摘要以利于检索
self.prompt = """
You are an assistant tasked with summarizing images for retrieval.
These summaries will be embedded and used to retrieve the raw image.
Give a concise summary of the image that is well optimized for retrieval.
Focus on key data points, trends, and labels visible in the chart.
"""
def base64_encode_image(self) -> str:
with open(self.image_path, "rb") as image_file:
return base64.b64encode(image_file.read()).decode("utf-8")
def summarize(self, prompt=None):
if prompt is None:
prompt = self.prompt
base64_image_data = self.base64_encode_image()
chat = ChatOpenAI(model="gpt-4-vision-preview", max_tokens=1000)
response = chat.invoke([
HumanMessage(
content=[
{
"type": "text",
"text": prompt
},
{
: ,
: {: }
}
]
)
])
base64_image_data, response.content
关键点说明:
gpt-4-vision-preview 或后续的稳定版本 gpt-4o 以获得更好的视觉理解能力。遍历所有提取出的图片,生成对应的摘要列表:
import os
image_data_list = []
image_summary_list = []
for img_file in sorted(os.listdir(images_path)):
if img_file.endswith((".jpg", ".png")):
summarizer = ImageSummarizer(os.path.join(images_path, img_file))
data, summary = summarizer.summarize()
image_data_list.append(data)
image_summary_list.append(summary)
print(f"Processed {len(image_summary_list)} images.")
生成的摘要示例如下:
"The image contains three bar charts showing holiday sales growth from 2019 to 2023. The highest peak occurred in 2021."
传统的 RAG 是将文档切片后直接向量化。而在多模态场景中,我们采用'摘要向量 + 原始数据'的双层存储策略。这被称为 MultiVectorRetriever 模式。
Document 的内容,存入向量数据库。这是用户查询时匹配的对象。当用户提问时,系统先在向量库中搜索匹配的摘要,然后根据摘要中的元数据 ID,从 Docstore 中取出原始图片展示给用户或传给 LLM 进行深度分析。
from uuid import uuid4
from langchain.docstore.document import Document
from langchain.vectorstores import FAISS # 或其他向量库
# 假设 retriever 已初始化
id_key = "doc_id"
doc_ids = [str(uuid4()) for _ in image_data_list]
# 创建摘要文档
summary_images = [
Document(page_content=s, metadata={id_key: doc_ids[i]})
for i, s in enumerate(image_summary_list)
]
# 添加摘要到向量库
retriever.vectorstore.add_documents(summary_images)
# 将原始图片数据存入文档存储
retriever.docstore.mset(list(zip(doc_ids, image_data_list)))
这种架构的优势在于:
完成索引构建后,我们可以通过自然语言查询来测试系统的效果。
query = "Which year had the highest holiday sales growth?"
response = chain.invoke(query)
print(response)
系统应能正确识别出图片中的柱状图信息,并指出 2021 年存在最高峰增长。如果配置了正确的工具链,系统不仅会返回文本答案,还能在后台检索到对应的原始图片,供人类验证或进一步展示。
本文详细阐述了如何基于 LangChain 和 LlamaIndex 实现多模态 RAG 系统。核心步骤包括:
unstructured 提取 PDF 中的图片和表格。在实际生产环境中,还需注意以下问题:
未来,随着开源多模态模型(如 LLaVA)的成熟,我们可以考虑本地部署方案,进一步降低对闭源 API 的依赖,提升数据安全性。通过结合文本、图像和表格的多模态检索,RAG 系统将能更全面地理解复杂的企业知识库,为用户提供更精准的决策支持。

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online
生成新的随机RSA私钥和公钥pem证书。 在线工具,RSA密钥对生成器在线工具,online
基于 Mermaid.js 实时预览流程图、时序图等图表,支持源码编辑与即时渲染。 在线工具,Mermaid 预览与可视化编辑在线工具,online
解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online