多模态 RAG
许多文档包含多种内容类型,包括文本和图像。
然而,大多数 RAG 应用中,图像中捕获的信息往往被忽略。
随着多模态 LLM 的出现,如 GPT-4V,值得考虑如何在 RAG 中利用图像:
选项 1:
- 使用多模态嵌入(例如 CLIP)来嵌入图像和文本
- 使用相似性搜索检索图像和文本
- 将原始图像和文本片段传递给多模态 LLM 进行答案合成
选项 2:
选项 3:
本文重点介绍选项3 。
- 我们将使用非结构化来解析文档 (PDF) 中的图像、文本和表格。
- 我们将使用带有 Chroma 的多向量检索器来存储原始文本和图像以及它们的摘要以供检索。
- 我们将使用 GPT-4V 进行图像摘要(用于检索)以及通过图像和文本(或表格)的联合审查进行最终答案合成。
该选项 Option 2 适用于LLM无法使用多模态进行答案综合的情况(例如,成本等)。
Packages 包
除了以下pip包外,您还需要系统中的 poppler (安装说明)和 tesseract (安装说明)。
! pip install -U langchain openai chromadb langchain-experimental # (newest versions required for multi-modal)
! pip install "unstructured[all-docs]" pillow pydantic lxml pillow matplotlib chromadb tiktoken
Data Loading 数据加载
对 PDF 表格、文本和图像进行分区
让我们看看 Jamin Ball 的一个受欢迎的博客。
这是一个很好的用例,因为大部分信息都是在图像(表格或图表)中捕获的。
我们用它来 Unstructured 对它进行分区。
要跳过 Unstructured 提取:
这是一个 zip 文件,其中包含提取的图像和 pdf 的子集。
如果您想使用提供的文件夹,那么只需为文档选择 pdf 加载器:
from langchain_community.document_loaders import PyPDFLoader
loader = PyPDFLoader(path + fname)
docs = loader.load()
tables = [] # Ignore w/ basic pdf loader
texts = [d.page_content for d in docs]
from langchain_text_splitters import CharacterTextSplitter
from unstructured.partition.pdf import partition_pdf
# Extract elements from PDF
def extract_pdf_elements(path, fname):
"""
Extract images, tables, and chunk text from a PDF file.
path: File path, which is used to dump images (.jpg)
fname: File name
"""
return partition_pdf(
filename=path + fname,
extract_images_in_pdf=False,
infer_table_structure=True,
chunking_strategy="by_title",
max_characters=4000,
new_after_n_chars=3800,
combine_text_under_n_chars=2000,
image_output_dir_path=path,
)
# Categorize elements by type
def categorize_elements(raw_pdf_elements):
"""
Categorize extracted elements from a PDF into tables and texts.
raw_pdf_elements: List of unstructured.documents.elements
"""
tables = []
texts = []
for element in raw_pdf_elements:
if "unstructured.documents.elements.Table" in str(type(element)):
tables.append(str(element))
elif "unstructured.documents.elements.CompositeElement" in str(type(element)):
texts.append(str(element))
return texts, tables
# File path
fpath = "/Users/rlm/Desktop/cj/"
fname = "cj.pdf"
# Get elements
raw_pdf_elements = extract_pdf_elements(fpath, fname)
# Get text, tables
texts, tables = categorize_elements(raw_pdf_elements)
# Optional: Enforce a specific token size for texts
text_splitter = CharacterTextSplitter.from_tiktoken_encoder(
chunk_size=4000, chunk_overlap=0
)
joined_texts = " ".join(texts)
texts_4k_token = text_splitter.split_text(joined_texts)
Multi-vector retriever 多向量检索器
使用多向量检索器对图像(和/或文本、表格)摘要进行索引,但检索原始图像(以及原始文本或表格)。
Text and Table summaries 文本和表格摘要
我们将使用 GPT-4 来生成表格和可选的文本摘要。
如果使用较大的块大小(例如,如上所述,我们使用 4k 令牌块),则建议使用文本摘要。
摘要用于检索原始表和/或原始文本块。
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI
# Generate summaries of text elements
def generate_text_summaries(texts