我在LlamaIndex和LangChain框架学习中,都有玩过RAG。最近准备开个RAG进阶系统,一同学习AI, 一同生长。欢迎点赞,留言交流。
前沿
上篇咱们打理了pdf格式文件中非结构化的文本和结构化的table 混合的半结构化数据,学习了unstructured、MultiVectorRetriever等Advanced RAG的用法,但却没有去处理图片、声音、视频等非结构化数据。本文咱们从大模型的视点,将单一文本模态,升级为多模态RAG。咱们在这里主要处理下图片,让RAG有读图、搜图的能力。
多模态模型 Multi modal model
它能够处理多种模态的数据。比方文字、表格、图片都是不同的模态。根据这些内容,多模态模型能够更加完整和精确的对数据的了解。gpt-3.5-turbo 只能文生文,是单一模态的。OpenAI 近期发布的GPT4V便是一款多模态模型。除了文字,GPT4V还能够接受图片,并回来文字。下图便是GPT4V图像识别的demo。
PDF数据
咱们运用到的pdf 文件是一份来自JP Morgan的每周商场回顾。
上图包含了文本、图表(图片)、表格等多模态、半结构数据。PDF就两页,方便咱们剖析RAG的功用和效果。
装置依靠, 下载PDF
这个和上个项目相同,咱们只需换下PDF地址就好了,代码不贴了,咱们去上篇文章找。
... 依靠装置和上篇相同
!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
import os
os.environ["OPENAI_API_KEY"]="Your OpenAI API Key with access to GPT-4 version"
不同类型element
咱们依然运用的是partition_pdf函数,由unstructured库供给,抽取不同类型的内容elements。
# 创建了图片目录
!mkdir images
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帮咱们抽离的图片。
# 显示图片 pdf 里一切的图标都在这一张图片里
from IPython.display import Image
Image("images/figure-1-1.jpg")
图片摘要
上篇文章咱们做了文本、表格摘要,现在来做图片摘要,咱们写了一个类。
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的关联。
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 将原始数据和摘要数据关联
... 文字、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)))
发问
query = "Which year had the highest holiday sales growth?"
chain.invoke(query)
咱们能够看到图片中的第一个柱状图21年有个最高峰增长。RAG的答复也是正确的,咱们今天的任务也达到了。
总结
- unstructured 图片抽离
- 图片摘要过程