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 分钟前
Loop Engineering —— 循环的设计与自主执行
人工智能·agent
米小虾14 分钟前
Harness Engineering —— 系统的安全护栏
人工智能·agent
火山引擎开发者社区29 分钟前
积分当钱花,火山引擎开发者激励计划首月消费双倍回馈
人工智能
aqi001 小时前
15天学会AI应用开发(十)把文本嵌入模型换成国产模型
人工智能·python·ai编程
MobotStone1 小时前
为什么在AI时代,“好奇心”成了最值钱的能力?
人工智能
武子康2 小时前
调查研究-200 llama.cpp b9754:一次很小但很关键的 Agent 工具调用修复
人工智能·agent·llama
Ralph_Salar3 小时前
从0到1搭建AI智能支付风控助手Stage1-RAG知识库升级 — 元数据让检索更精准
人工智能
武子康3 小时前
调查研究-199 MCP Zero-Touch OAuth:为什么它是 MCP 进入企业生产的关键门槛?
人工智能·agent·mcp