微信扫码
添加专属顾问
导言
RAG是使用大模型,同时避免大模型幻觉, 且解决垂直业务领域的高效方式,而多模态的RAG构建又是融合多种数据, 包括音频,视频,文档的信息和知识构建RAG的有效手段,本文介绍了视觉文档多模态RAG系统的构建方式, 并附上完整代码。
通过阅读本文,你能够了解:
如何构建增加视觉文档的多模态RAG
获取完整代码
关注公众号,复制"视觉多模态RAG源码下载"并后台发送,获取 完整代码
概述
在本文中,我将指导使用OpenAI的GPT-4o模型构建一个多模式RAG聊天应用程序。以下是你将学到的内容:
多模式RAG聊天应用程序:创建一个应用程序,通过从PDF文档中检索信息来实现视觉问题回答。
无缝解析:使用Unstructured库无缝解析文本、表格和图像。
性能评估:使用DeepEval库提供的各种指标评估聊天机器人的性能。
Streamlit用户界面:通过Streamlit应用程序演示该应用程序。
为什么要阅读本文?
你是否对利用像GPT-4o这样的先进基础模型的多模态能力来构建自己的AI应用程序感兴趣?那么你需要阅读该文章。
无论您是一名市场营销专业人士,寻求从市场研究报告中获取见解,还是一名医疗从业者分析多模态医疗文件,或者一名法律专业人士处理复杂的法律文件,本文都为提供了宝贵的见解。
我将对每个概念进行彻底解释,并提供所有代码的详细解释。
多模态 RAG 的崛起
从基于文本的 RAG 模型向多模态 RAG 系统的转变代表了人工智能能力的重大飞跃。以下是一个快速概述:
起源:RAG 这个术语是在 2021 年 4 月创造的,通过基于文本的知识增强语言输出。
进展:随着像 GPT-4o 这样的模型在 2024 年 5 月发布,我们现在可以整合视觉信息,实现图像、表格和文本的同时处理。
新可能性:这种演变使得更全面和具有上下文丰富的人工智能应用成为可能。
在本文中,我将展示一个案例研究,使用多模态 RAG 框架对我在 Neurocomputing 上的一篇研究文章进行问答。该文章包括文本、表格和图表,我们将探讨 GPT-4o 的视觉能力如何回答复杂问题。
目录
设置虚拟环境并安装Python库
预处理非结构化数据
文本、表格和图像摘要
多模态检索器
多模态RAG链
LLM评估
使用Streamlit的用户界面
设置虚拟环境并安装Python库
首先,让我们使用以下命令设置虚拟环境:
python3.10 -m venv venv
现在,让我们安装必要的包。您可以在GitHub存储库的主目录中的'requirements.txt'中找到它们。
pip install -r requirements.txt
现在,打开一个jupyter笔记本,比如说"your-project.ipynb"来开始编写您的代码。就是这样!我们现在已经准备好进入主要细节了。
这是多模式RAG项目的GitHub存储库:
GitHub - bhargobdeka/advanced-RAG-app: This repository will consist of advanced RAG applications.
预处理非结构化数据
构建 RAG 应用程序的第一步是将上下文加载到数据库中,在这种情况下是使用 PDF 文档。
由于大型语言模型(LLM)的上下文窗口限制,我们无法直接将整个文档存储并传递到提示符中。这样做很可能会导致错误,因为它超过了最大token数。
为了克服这个问题,我们将从文档中提取不同的元素 - 图像、文本和表格。对于这个任务,我们将使用 Unstructured 库。
安装
首先,让我们安装该软件包(如果尚未通过pip安装)
#%brew install tesseract poppler%pip install -q "unstructured[all-docs]"
请注意,系统中还需要 'tesseract' 和 'poppler' 库,以便无结构库能够处理文本提取以及从图像中提取文本。您可以使用 homebrew 安装这两个软件包(参见注释行)。
分区和分块
from unstructured.partition.pdf import partition_pdfelements = partition_pdf(filename="TAGIV.pdf", # mandatorystrategy="hi_res", # mandatory to use ``hi_res`` strategyextract_images_in_pdf=True,# mandatory to set as ``True``extract_image_block_types=["Image", "Table"],# optionalextract_image_block_to_payload=False,# optionalextract_image_block_output_dir="saved_images",# optional - only works when ``extract_image_block_to_payload=False``)
我们将使用 partition_pdf 模块来对文档进行分区,并从我们的文件 'TAGIV.pdf' 中提取不同的元素。我们将设置一个 hi_res 策略来提取高质量的图像和表格。可选参数 extract_image_block_types 和 extract_image_block_output_dir 指定只提取并保存图像和表格到名为 "saved_images" 的目录中。
现在,我们将使用 chunk_by_title 方法来对元素进行分块,该方法用于根据 '标题或标题' 将提取的元素分成块。这适用于研究文章,通常包括独立部分和子部分的内容,如介绍、方法、结果等。
from unstructured.chunking.title import chunk_by_title # might be better for an articlefrom typing import Anychunks = chunk_by_title(elements)Output:# 文档中的不同类别category_counts = {}for element in chunks:category = str(type(element))if category in category_counts:category_counts[category] += 1else:category_counts[category] = 1{"": 200,"": 3,"": 2}
分块显示有三个唯一的类别:
•CompositeElements
•Table
•TableChunk
'CompositeElements' 是不同文本的集合,可能是段落、章节、页脚、公式等。还有三个 'Table' 结构以及两个 'TableChunk',通常表示表格的一部分或片段。因此,可能表格跨页,只有一部分被分块。
文档中有四个表,只有三个被完全解析。?
过滤
接下来,我们将简化文档元素,以便将文本和表格数据分开处理。为此,我们将定义一个 Pydantic 模型来标准化文档元素,并根据它们的类型将它们分类为“文本”或“表格”。
from pydantic import BaseModelclass Element(BaseModel):type: strtext: Any
按类型分类
categorized_elements = []for element in chunks:if "unstructured.documents.elements.CompositeElement" in str(type(element)):categorized_elements.append(Element(type="text", text=str(element)))elif "unstructured.documents.elements.Table" in str(type(element)):categorized_elements.append(Element(type="table", text=str(element)))
文本
text_elements = [e for e in categorized_elements if e.type == "text"]
表格
table_elements = [e for e in categorized_elements if e.type == "table"]
我们将遍历文档元素的块,识别每个元素的类型,并将其附加到一个分类列表中。最后,我们将这个列表过滤成分别用于文本和表格元素的两个列表。有了这个,预处理步骤现在已经结束。
文本、表格和图片摘要
为了在本文后面使用多向量检索器,我们需要为文本、表格和图片元素创建摘要。这些摘要将存储在向量存储器中,当我们将输入查询传递到提示时,将实现语义搜索。
文本和表格摘要
让我们从文本和表格摘要开始。首先,我们将设置一个提示模板,指示AI充当专家研究助理,负责总结表格和文本。接下来,我们将创建一个链,通过这个提示和GPT-4o模型处理每个文本和表格元素,生成简洁的摘要。
为了提高效率,我们将使用`max_concurrency`参数同时批处理五个文本或表格元素。
%pip install -q langchain langchain-chroma unstructured[all-docs] pydantic lxml langchainhub langchain-openaifrom langchain_core.output_parsers import StrOutputParserfrom langchain_core.prompts import ChatPromptTemplatefrom langchain_openai import ChatOpenAI
检索器
提示
prompt_text = """您是一名专家研究助理,负责总结研究文章中的表格和文本。给出文本的简洁总结。文本块:{element}"""
prompt = ChatPromptTemplate.from_template(prompt_text)
摘要链
model = ChatOpenAI(temperature=0, model="gpt-4o")summarize_chain = {"element": lambda x: x} | prompt | model | StrOutputParser()应用到文本
texts = [i.text for i in text_elements]text_summaries = summarize_chain.batch(texts, {"max_concurrency": 5})Apply to tablestables = [i.text for i in table_elements]table_summaries = summarize_chain.batch(tables, {"max_concurrency": 5})
图像摘要
接下来,我们将设置函数来帮助我们总结我们的图像。我们将定义三个关键函数:`encode_image`,`image_summarize` 和 `generate_img_summaries`。
1. encode_image:此函数以二进制读取模式('rb')打开图像文件,并返回其 base64 编码的字符串表示。
2. image_summarize:此函数使用包含指示模型如何总结图像的提示的 HumanMessage 对象。它还包括 base64 编码的图像数据,格式化为数据 URL 以直接嵌入内容中的图像。
3. generate_img_summaries:此函数处理给定目录中的所有 JPG 图像,为每个图像生成摘要并返回 base64 编码的图像。
这些函数将使我们能够高效地总结和处理图像,并将它们无缝集成到我们的多模态 RAG 应用程序中。
以下是完整的代码:
## 获取图像摘要import base64import osfrom langchain_core.messages import HumanMessagedef encode_image(image_path):"""获取base64字符串"""with open(image_path, "rb") as image_file:return base64.b64encode(image_file.read()).decode("utf-8")def image_summarize(img_base64, prompt):"""生成图像摘要"""chat = ChatOpenAI(model="gpt-4o", max_tokens=1024)msg = chat.invoke([HumanMessage(content=[{"type": "text", "text": prompt},{"type": "image_url","image_url": {"url": f"data:image/jpg;base64,{img_base64}"},},])])return msg.contentdef generate_img_summaries(path):"""生成图像摘要和base64编码字符串path: 通过Unstructured提取的.jpg文件列表的路径"""# 存储base64编码的图像img_base64_list = []# 存储图像摘要image_summaries = []# 提示prompt = """您是一名助手,负责为检索摘要图像。\这些摘要将被嵌入并用于检索原始图像。\给出一份简洁的图像摘要,以便更好地进行检索。"""# 应用于图像for img_file in sorted(os.listdir(path)):if img_file.endswith(".jpg"):img_path = os.path.join(path, img_file)base64_image = encode_image(img_path)img_base64_list.append(base64_image)image_summaries.append(image_summarize(base64_image, prompt))return img_base64_list, image_summariesfpath = "saved_images"图像摘要img_base64_list, image_summaries = generate_img_summaries(fpath)
多模态检索器
有了我们的摘要准备好了,我们可以创建我们的多模态检索器。
多向量检索器
我们将建立一个多向量检索器,它接受向量存储、文档存储、id_key 和 search_kwargs 作为输入。这种方法允许我们单独索引内容摘要,同时存储原始内容,从而实现高效的检索。请注意,这只是执行多模态 RAG 的一种方式;另一种方法可能涉及使用多模态嵌入来使用CLIP嵌入文本和图像,然后将原始图像和文本块传递给多模态 LLM。我可能会在未来的博客文章中探索这一点。?
我们的检索器利用 Chroma 向量存储来存储内容摘要的嵌入,并使用 InMemoryStore 来存储完整内容。这种设置使得通过摘要进行语义搜索,同时在需要时检索相应的完整内容成为可能。每个文档都使用 UUID 分配一个唯一标识符,这是检索器所必需的。
为了简化向向量存储添加摘要和向文档存储添加原始内容的过程,我们将添加一个名为 add_documents 的辅助函数。该函数确保只添加可用的摘要。
import uuidfrom langchain.retrievers.multi_vector import MultiVectorRetriever from langchain.storage import InMemoryStorefrom langchain_chroma import Chromafrom langchain_core.documents import Documentfrom langchain_openai import OpenAIEmbeddingsdef create_multi_vector_retriever(vectorstore, text_summaries, texts, table_summaries, tables, image_summaries, images):"""创建检索器,索引摘要,但返回原始图像、表格或文本"""# 初始化存储层store = InMemoryStore()id_key = "doc_id"# 创建多向量检索器retriever = MultiVectorRetriever(vectorstore=vectorstore,docstore=store,id_key=id_key,search_kwargs={"k": 2}# 限制为前 2 个结果)# 添加文档到向量存储和文档存储的辅助函数def add_documents(retriever, doc_summaries, doc_contents):doc_ids = [str(uuid.uuid4()) for _ in doc_contents]summary_docs = [Document(page_content=s, metadata={id_key: doc_ids[i]})for i, s inenumerate(doc_summaries)]retriever.vectorstore.add_documents(summary_docs)retriever.docstore.mset(list(zip(doc_ids, doc_contents)))# 添加文本、表格和图像# 在添加之前检查 text_summaries 不为空if text_summaries:add_documents(retriever, text_summaries, texts)# 在添加之前检查 table_summaries 不为空if table_summaries:add_documents(retriever, table_summaries, tables)# 在添加之前检查 image_summaries 不为空if image_summaries:add_documents(retriever, image_summaries, images)return retriever
创建检索器
# 用于索引摘要的向量存储vectorstore = Chroma(collection_name="mm_tagiv_paper", embedding_function=OpenAIEmbeddings())# 创建检索器retriever_multi_vector_img = create_multi_vector_retriever(vectorstore,text_summaries,texts,table_summaries,tables,image_summaries,img_base64_list,)
测试以及完整代码
代码组织结构如下:
advanced-RAG-app/
│
├── utils/
│ ├── __init__.py
│ ├── image_processing.py
│ ├── rag_chain.py
│ ├── rag_evaluation.py
│ └── retriever.py
│
└── main.py
└── requirements.txt
关注公众号,复制"视觉多模态RAG源码下载"并后台发送,获取 完整代码
53AI,企业落地大模型首选服务商
产品:场景落地咨询+大模型应用平台+行业解决方案
承诺:免费POC验证,效果达标后再合作。零风险落地应用大模型,已交付160+中大型企业
2026-07-01
提升 RAG 准确率全攻略 让你的 AI 知识库 真正靠谱起来!
2026-06-30
教程:如何用AutoRAG + Milvus避免RAG 与Agent 中出现串租问题
2026-06-30
知识库不是文件堆——我把RAG准确率从60%调到了92%
2026-06-30
本体论语义建设新思路,另类RAG来解决检索问题
2026-06-30
别把RAG当架构:Ontology(本体)才是Agent的业务世界
2026-06-29
PixelRAG:伯克利团队颠覆传统 RAG,用截图代替文本检索! 28 天狂揽 3000+ Star!
2026-06-29
腾讯WeKnora开源详解(三):检索引擎与生态集成
2026-06-29
腾讯开源WeKnora详解(二):知识库与对话核心能力
2026-04-06
2026-04-27
2026-04-23
2026-04-20
2026-04-09
2026-04-12
2026-04-22
2026-04-10
2026-05-14
2026-04-30
2026-06-23
2026-06-23
2026-06-15
2026-06-10
2026-06-10
2026-05-20
2026-05-18
2026-05-11
欢迎您使用【53AI 官方网站】(以下简称“本网站”或“我们”)。本《会员服务协议》(以下简称“本协议”)是您(以下简称“会员”或“用户”)与【深圳市博思协创网络科技有限公司】之间关于注册、登录及使用本网站会员服务所订立的法律协议。
在您注册或登录前,请务必审慎阅读、充分理解各条款内容,特别是免除或限制责任的条款、知识产权条款、争议解决条款等。此类条款将以加粗形式提示您注意。 当您通过微信公众号授权、手机验证码验证或其他方式成功登录本网站时,即视为您已完全理解并同意接受本协议的全部内容。
一、 定义
本网站:指由【深圳市博思协创网络科技有限公司】运营的,域名为【53ai.com】的网站及相关移动端页面。
会员服务:指本网站向注册会员提供的知识库文章查阅、内容检索及其他相关增值服务。
知识库内容:指本网站发布的包括但不限于文字、图表、数据、研究报告、行业分析等数字化内容资源。
二、 账号注册与登录
登录方式:本网站支持以下登录方式,您可根据实际情况选择:
微信公众号授权登录:您同意将您的微信OpenID信息授权给本网站,用于创建或关联会员账号。
手机验证码登录:您需提供真实有效的手机号码,并通过短信验证码完成身份验证与登录/注册。
账号安全:您的账号仅限您本人使用,禁止赠与、借用、租用、转让或售卖。因您保管不善导致的账号被盗、密码泄露等损失,由您自行承担。
实名认证:根据相关法律法规要求,我们可能要求您在特定功能下完成实名认证。如您拒绝提供,可能无法使用部分或全部服务。
未成年人保护:若您未满18周岁,请在法定监护人的陪同下阅读本协议,并在征得监护人同意后使用本服务。
三、 服务内容与规范
知识库查阅权限:会员登录后,有权按照其会员等级对应的权限范围,在线浏览、检索本网站知识库中的相关文章及内容。
服务变更:我们有权根据业务发展需要,调整、变更或终止部分服务内容,并将以网站公告、公众号消息等方式提前通知。
禁止行为:您在使用服务时不得实施以下行为:
利用技术手段批量爬取、下载、转存知识库内容;
将知识库内容用于商业目的或未经授权地向第三方传播;
干扰本网站正常运行或侵犯其他用户合法权益;
发布违法违规信息或从事违反公序良俗的活动。
四、 知识产权声明
权利归属:本网站知识库中的排版设计、软件代码等内容的知识产权均归【公司全称】或原权利人所有,受《中华人民共和国著作权法》等法律保护。
有限许可:本网站授予会员一项非独占、不可转让、不可转授权的普通许可,仅限于个人学习、研究之目的在线查阅知识库内容。
侵权追责:未经书面许可,任何单位或个人不得以任何形式复制、转载、摘编、镜像、汇编或以其他方式使用上述内容。一经发现,我们保留追究其法律责任的权利。
五、 个人信息保护
我们重视对您个人信息的保护。关于我们如何收集、使用、存储和保护您的个人信息,请单独阅读 《隐私政策》。
您通过微信公众号授权或手机号验证所提供的信息,我们将严格按照《个人信息保护法》的规定处理,仅用于身份识别、服务提供及安全验证等必要用途。
您可以随时通过网站设置或联系客服行使查阅、更正、删除个人信息及撤回授权同意的权利。
六、 免责声明
内容准确性:知识库内容仅供参考,不构成专业建议。我们不对其完整性、准确性、时效性作任何明示或暗示的保证,您应自行判断并承担使用风险。
不可抗力:因自然灾害、政策法规变化、网络故障、第三方平台接口异常(如微信接口维护、运营商短信通道故障)等不可抗力导致的服务中断或延迟,我们不承担违约责任。
第三方链接:本网站可能包含指向第三方网站的链接,该等网站的内容和服务不受我们控制,请您自行甄别风险。
七、 违约责任
如您违反本协议约定,我们有权视情节采取警告、限制功能、暂停服务、注销账号等措施,并保留要求赔偿损失的权利。
如因您的违约行为导致我们遭受行政处罚、第三方索赔或商誉损失,您应承担全部赔偿责任(包括但不限于罚款、赔偿金、律师费、公证费等)。
八、 法律适用与争议解决
本协议的订立、执行和解释均适用中华人民共和国大陆地区法律。
因本协议产生的或与本协议有关的任何争议,双方应友好协商解决;协商不成的,任何一方均可向【公司所在地】有管辖权的人民法院提起诉讼。
九、 其他
本协议构成双方就本服务达成的完整协议,取代此前任何口头或书面约定。
本协议任一条款被认定为无效或不可执行的,不影响其他条款的效力。
我们对本协议享有最终解释权,并在法律允许的范围内保留随时修改的权利。修改后的协议一经公布即生效,继续使用服务即视为同意修订内容。