RAG 进阶 多模态图片检索

我在LlamaIndex和LangChain框架学习中,都有玩过RAG。最近准备开个RAG进阶系统,一起学习AI, 一起成长。欢迎点赞,留言交流。

前沿

  上篇我们打理了pdf格式文件中非结构化的文本和结构化的table 混合的半结构化数据,学习了unstructured、MultiVectorRetriever等Advanced RAG的用法,但却没有去处理图片、声音、视频等非结构化数据。本文我们从大模型的角度,将单一文本模态,升级为多模态RAG。我们在这里主要处理下图片,让RAG有读图、搜图的能力。

  它可以处理多种模态的数据。比如文字、表格、图片都是不同的模态。根据这些内容,多模态模型能够更加完整和精确的对数据的理解。gpt-3.5-turbo 只能文生文,是单一模态的。OpenAI 近期发布的GPT4V就是一款多模态模型。除了文字,GPT4V还可以接受图片,并返回文字。下图就是GPT4V图像识别的demo。

PDF数据

  我们使用到的pdf 文件是一份来自JP Morgan的每周市场回顾。

  上图包含了文本、图表(图片)、表格等多模态、半结构数据。PDF就两页,方便我们分析RAG的功能和效果。

安装依赖, 下载PDF

  这个和上个项目一样,我们只要换下PDF地址就好了,代码不贴了,大家去上篇文章找。

ruby 复制代码
... 依赖安装和上篇一样
!wget -o weekly_market_recap.pdf https://am.jpmorgan.com/content/dam/jpm-am-aem/americas/us/en/insights/market-insights/wmr/weekly_market_recap.pdf

OPENAI api_key

lua 复制代码
import os
os.environ["OPENAI_API_KEY"]="Your OpenAI API Key with access to GPT-4 version"

不同类型element

  我们仍然使用的是partition_pdf函数,由unstructured库提供,抽取不同类型的内容elements。

bash 复制代码
# 创建了图片目录
!mkdir images
ini 复制代码
from typing import Any
from pydantic import BaseModel
from unstructured.partition.pdf import partition_pdf

images_path = "./images"
raw_pdf_elements = partition_pdf(
    filename="weekly_market_recap.pdf",
    extract_images_in_pdf=True, # 上篇为false, 现在GPT4了,鸟枪换炮
    infer_table_structure=True, # table 结构化数据
    chunking_strategy="by_title"
    ... # 一样的省略
    image_output_dir_path=images_path
)

   我们将extract_images_in_pdf设置为True,并配置了image_output_dir_path。执行代码,一会儿,执行完成。下图展示了GPU消耗,这是因为用到了microsoft/table-transformer-struct-recognition模型。

  我们执行!ls -alt images/ 代码看到了unstructured帮我们抽离的图片。

python 复制代码
# 显示图片 pdf 里所有的图标都在这一张图片里
from IPython.display import Image
Image("images/figure-1-1.jpg")

图片摘要

  上篇文章我们做了文本、表格摘要,现在来做图片摘要,我们写了一个类。

python 复制代码
class ImageSummarizer:
    def __init__(self, image_path) -> None:
        self.image_path=image_path
        # 提示词希望LLM担任助理的角色,帮助给图片做摘要。摘要是基于图片的分析来做的,拿到摘要后可以用来做retrieval 也就是检索。
        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.
        """
        
        def base64_encode_image(self):
            with open(self.image_path, "rb") as image_file:
                return base64.b64encode(image_file.read()).decode("utf-8")
        
        def summarize(self, prompt=Npne):
            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 if prompt else self.prompt
                        },
                        # 使用的是base64编码的图片
                        {
                            type: "image_url",
                            image_url:{"url":f"data:image/jpeg:base64,{base64_image_data}"}
                        }
                    ]
                )
            ])
            # 返回的就图片数据和LLM返回
            return base64_image_data, response.content

图片摘要处理

  当我们有了ImageSummarizer类,就可以和上篇文章一样做原图片和summarize的关联。

scss 复制代码
image_data_list = []
image_summary_list = []

for img_file in sorted(os.listdir(images_path)):
    if img_file.endswith(".jpg"):
        summarizer = ImageSummarizer(os.path.join(images_path, img_file))
        data, summary = summarizer.summarize()
        image.data_list.append(data)
        imag_summary_list.append(summary)
image_summary_list

  摘要中,介绍了图片中包含了三个独立的图表,包含了不同的经济和市场数据。分别介绍了三个图标包含的数据信息。

  文本数据和table数据和上篇一样,此处略过。

MultiVectorRetriever 将原始数据和摘要数据关联

less 复制代码
... 文字、ta b le省略
doc_ids = (str(uuid.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_document(summary_images)
retriever.docstore.mset(list(zip(doc_ids, image_data_list)))

提问

ini 复制代码
query = "Which year had the highest holiday sales growth?"
chain.invoke(query)

  我们可以看到图片中的第一个柱状图21年有个最高峰增长。RAG的回答也是正确的,我们今天的任务也达到了。

总结

  • unstructured 图片抽离
  • 图片摘要过程

参考资料

相关推荐
夕阳_醉了1 分钟前
让 AI 回答“打字般”浮现:用 Vue 3 + DeepSeek 实现流式聊天
前端·vue.js·人工智能
xiaoyunxuexibiji3 分钟前
供应商绩效评价体系如何建立?从评价指标到自动化考核
运维·人工智能·自动化
lucas_AI4 分钟前
一次 92 分一次 8 分,都是同一个系统:EVICALC 用 1730 道题教你做人
llm
lucas_AI5 分钟前
488 GiB 变 3.81 GiB:腾讯把视觉文档检索的索引砍掉 128 倍,精度只让了 7 分
人工智能
星川皆无恙6 分钟前
基于知识图谱的百科问答系统:Django + Neo4j 与实现
人工智能·python·机器学习·自然语言处理·django·知识图谱·neo4j
Raas1007 分钟前
MemT-1.0 接入设计指南:硬件核算、三方案选型与写入触发点
大数据·网络·人工智能·机器学习·数据挖掘·ai agent
金仓社区的KK7 分钟前
Agent Skill 没按预期执行?用请求、调用记录和产物排查
人工智能·软件构建·ai-native
java1234_小锋9 分钟前
MySQL 宣布正式拥抱 AI
数据库·人工智能·mysql
打工仔折腾 AI11 分钟前
介入式脑机接口的跨尺度解码与闭环调控:从算法落地到后端工程实践
人工智能·后端·python·深度学习·算法·ai agent 实战
Aloudata12 分钟前
Data Agent vs AI Native BI:企业数据分析的下一代入口到底是什么?
大数据·人工智能·数据分析·data·语义层