多模态 RAG 实战:结合视觉大模型的文档智能问答
·
多模态 RAG 实战:结合视觉大模型的文档智能问答
1. 引言
传统 RAG(Retrieval-Augmented Generation)只能处理文本,但现实中的文档充满了图表、表格和示意图。本文将构建一个多模态 RAG 系统,能够同时理解文档中的文字和图像,实现真正的文档智能问答。
技术栈:
- 文档解析:PyMuPDF + Unstructured
- 图像理解:GPT-4o / LLaVA
- 向量数据库:ChromaDB
- 文本嵌入:OpenAI text-embedding-3-small
- 编排框架:LangChain
2. 系统架构
文档输入 → 解析(文本+图像) → 多模态嵌入 → 向量存储
↓
用户提问 → 检索(文本+图像) → 多模态LLM生成 → 回答
3. 文档解析:提取文本与图像
import fitz # PyMuPDF
import os
from pathlib import Path
def extract_content(pdf_path: str, output_dir: str = "extracted"):
"""从 PDF 中提取文本块和图像"""
os.makedirs(output_dir, exist_ok=True)
doc = fitz.open(pdf_path)
contents = []
for page_idx, page in enumerate(doc):
# 提取文本
text_blocks = page.get_text("blocks")
for block in text_blocks:
if block[6] == 0: # 文本块
contents.append({
"type": "text",
"content": block[4].strip(),
"page": page_idx,
"bbox": block[:4],
})
# 提取图像
image_list = page.get_images(full=True)
for img_idx, img in enumerate(image_list):
xref = img[0]
base_image = doc.extract_image(xref)
img_path = f"{output_dir}/page{page_idx}_img{img_idx}.png"
with open(img_path, "wb") as f:
f.write(base_image["image"])
contents.append({
"type": "image",
"content": img_path,
"page": page_idx,
"bbox": None,
})
doc.close()
return contents
4. 多模态描述生成
使用视觉大模型为图像生成文本描述:
import base64
from openai import OpenAI
client = OpenAI()
def describe_image(image_path: str) -> str:
"""用 GPT-4o 为图像生成描述"""
with open(image_path, "rb") as f:
img_base64 = base64.b64encode(f.read()).decode()
response = client.chat.completions.create(
model="gpt-4o",
messages=[{
"role": "user",
"content": [
{"type": "text", "text":
"请详细描述这张图片的内容,包括所有可见的文字、"
"数据、图表类型、关键趋势和结论。"
"如果是表格,提取所有行列数据。"},
{"type": "image_url", "image_url": {
"url": f"data:image/png;base64,{img_base64}"
}},
],
}],
max_tokens=1000,
)
return response.choices[0].message.content
5. 向量化与存储
from langchain_community.vectorstores import Chroma
from langchain_openai import OpenAIEmbeddings
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.schema import Document
def build_vectorstore(contents: list, persist_dir: str = "chroma_db"):
"""构建多模态向量数据库"""
embeddings = OpenAIEmbeddings(model="text-embedding-3-small")
splitter = RecursiveCharacterTextSplitter(
chunk_size=500, chunk_overlap=50
)
documents = []
for item in contents:
if item["type"] == "text":
chunks = splitter.split_text(item["content"])
for chunk in chunks:
documents.append(Document(
page_content=chunk,
metadata={"page": item["page"], "source": "text"}
))
elif item["type"] == "image":
description = describe_image(item["content"])
documents.append(Document(
page_content=description,
metadata={
"page": item["page"],
"source": "image",
"image_path": item["content"],
}
))
vectorstore = Chroma.from_documents(
documents, embeddings, persist_directory=persist_dir
)
return vectorstore
6. 多模态 RAG 查询链
from langchain.chains import RetrievalQA
from langchain_openai import ChatOpenAI
def multimodal_query(vectorstore, question: str) -> str:
"""多模态 RAG 查询"""
retriever = vectorstore.as_retriever(
search_type="mmr", # 最大边际相关性
search_kwargs={"k": 5}
)
# 检索相关文档
docs = retriever.invoke(question)
# 分离文本和图像上下文
text_context = []
image_descriptions = []
for doc in docs:
if doc.metadata["source"] == "image":
image_descriptions.append(
f"[图片描述 - 第{doc.metadata['page']}页]: "
f"{doc.page_content}"
)
else:
text_context.append(doc.page_content)
# 构造多模态 prompt
context = "\n\n".join(text_context + image_descriptions)
llm = ChatOpenAI(model="gpt-4o", temperature=0)
response = llm.invoke(
f"基于以下上下文回答问题。如果涉及图表数据,请引用具体数值。\n\n"
f"上下文:\n{context}\n\n"
f"问题:{question}"
)
return response.content
7. 完整使用示例
# 1. 解析文档
contents = extract_content("annual_report.pdf")
print(f"提取了 {len(contents)} 个内容块")
# 2. 构建向量库
vectorstore = build_vectorstore(contents)
# 3. 查询
answer = multimodal_query(
vectorstore,
"2024年Q3的营收增长率是多少?与Q2相比趋势如何?"
)
print(answer)
输出示例:
根据文档中的财务图表,2024年Q3营收为3.2亿元,同比增长28.5%。
Q2营收为2.8亿元,同比增长22.1%。Q3较Q2增长了14.3%,
整体呈加速增长趋势。
8. 性能优化
| 优化方向 | 方法 | 效果 |
|---|---|---|
| 图像去重 | pHash 感知哈希去重 | 减少 30% 冗余图像 |
| 嵌入缓存 | SQLite 缓存已嵌入文本 | 避免重复 API 调用 |
| 分块策略 | 按语义分块而非固定长度 | 提升检索精度 |
| 重排序 | Cohere Reranker | mAP@5 提升 15% |
9. 总结
多模态 RAG 的核心在于:
- 解析层:PDF → 文本 + 图像的完整提取
- 理解层:视觉大模型将图像转化为可检索的文本描述
- 检索层:统一的向量空间,同时检索文本和图像内容
- 生成层:大模型综合文本与图像信息生成准确回答
生产环境中建议增加查询改写(Query Rewriting)和答案校验(Groundedness Check)环节。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐
所有评论(0)