构建多模态RAG系统:使用多模态嵌入和LLM增强检索

社区文章 发布于2025年5月1日

更多详情:https://www.youtube.com/watch?v=BI2ROqd38t4

总结:

本项目讨论了开发一个多模态检索增强生成系统,该系统能够处理图像、文本和表格,超越了传统的基于文本的系统。它强调了将图像转换为文本描述的局限性,并介绍了一种使用(Cohere的Embed V4模型)[https://cohere.com/blog/embed-4]的新方法,该模型生成固定大小的多模态嵌入,以实现高效检索。工作流程包括为文档图像创建嵌入、将其存储在向量存储中,以及使用Gemini等多模态LLM根据用户查询生成答案。

--

引言

目前大多数检索增强生成(RAG)系统都仅限于文本,但现实世界的文档包含图像、表格和图表等丰富多样的内容类型。处理非文本内容的传统方法涉及生成视觉元素的文本描述(字幕),然后嵌入这些字幕——本质上是将所有内容都转换为文本。然而,这种方法会丢失大量的上下文信息,并且严重依赖于提示的质量。

本文探讨了如何构建一个真正的多模态RAG系统,该系统能够直接处理图像和文本,从而从包含视觉元素的文档中实现更准确、更全面的信息检索。

仅限文本的RAG在视觉内容方面的问题

处理包含图像、表格和信息图表的文档时,传统的基于文本的RAG系统面临以下几个局限性:

  1. 信息丢失 - 将丰富的视觉数据转换为文本描述会丢失上下文信息
  2. 字幕质量依赖性 - 结果严重依赖于AI生成字幕的质量
  3. 提示工程负担 - 需要为视觉到文本的转换精心设计提示
  4. 无法进行视觉推理 - 文本描述难以捕捉空间关系和视觉模式

考虑包含复杂图表的财务报告、带有诊断图像的医疗文档或带有图表的技术文档——文本描述根本无法捕捉所有相关细节。

两种视觉增强RAG方法

我们将探索使用Cohere的Embed v4 + Gemini的基于API的解决方案

让我们深入了解实施细节!

Cohere Embed v4 + Gemini

Cohere的Embed v4模型提供先进的多模态嵌入,可以直接编码图像进行检索。与一些创建多级嵌入(需要高内存)的方法不同,Embed v4生成与标准向量存储兼容的固定大小嵌入。

实施步骤

  1. 设置和认证
import cohere
cohere_api_key = "" # Replace with your Cohere API key
co = cohere.ClientV2(api_key=cohere_api_key)

from google import genai
gemini_api_key = "" # Replace with your Gemini API key
client = genai.Client(api_key=gemini_api_key)
  1. 图像处理函数
import PIL
import io
import base64

max_pixels = 1568*1568  # Max resolution for images

# Resize too large images
def resize_image(pil_image):
    org_width, org_height = pil_image.size
    if org_width * org_height > max_pixels:
        scale_factor = (max_pixels / (org_width * org_height)) ** 0.5
        new_width = int(org_width * scale_factor)
        new_height = int(org_height * scale_factor)
        pil_image.thumbnail((new_width, new_height))

# Convert images to a base64 string
def base64_from_image(img_path):
    pil_image = PIL.Image.open(img_path)
    img_format = pil_image.format if pil_image.format else "PNG"
    
    resize_image(pil_image)
    
    with io.BytesIO() as img_buffer:
        pil_image.save(img_buffer, format=img_format)
        img_buffer.seek(0)
        img_data = f"data:image/{img_format.lower()};base64,"+base64.b64encode(img_buffer.read()).decode("utf-8")
    
    return img_data
  1. 为图像创建嵌入
import numpy as np
import os
import requests
import tqdm

img_paths = []
doc_embeddings = []

for name, url in tqdm.tqdm(images.items()):
    img_path = os.path.join(img_folder, name)
    img_paths.append(img_path)
    
    # Download the image if needed
    if not os.path.exists(img_path):
        response = requests.get(url)
        response.raise_for_status()
        
        with open(img_path, "wb") as fOut:
            fOut.write(response.content)
    
    # Get the base64 representation of the image
    api_input_document = {
        "content": [
            {"type": "image", "image": base64_from_image(img_path)},
        ]
    }
    
    # Call the Embed v4.0 model
    api_response = co.embed(
        model="embed-v4.0",
        input_type="search_document",
        embedding_types=["float"],
        inputs=[api_input_document],
    )
    
    # Store embedding
    emb = np.asarray(api_response.embeddings.float[0])
    doc_embeddings.append(emb)

doc_embeddings = np.vstack(doc_embeddings)
  1. 实现搜索功能
def search(question, max_img_size=800):
    # Compute the embedding for the query
    api_response = co.embed(
        model="embed-v4.0",
        input_type="search_query",
        embedding_types=["float"],
        texts=[question],
    )
    
    query_emb = np.asarray(api_response.embeddings.float[0])
    
    # Compute cosine similarities
    cos_sim_scores = np.dot(query_emb, doc_embeddings.T)
    
    # Get the most relevant image
    top_idx = np.argmax(cos_sim_scores)
    hit_img_path = img_paths[top_idx]
    
    return hit_img_path
  1. 使用Gemini生成答案
def answer(question, img_path):
    prompt = [f"""Answer the question based solely on the information from the image.
               Question: {question}""", PIL.Image.open(img_path)]
    
    response = client.models.generate_content(
        model="gemini-2.5-flash-preview-04-17",
        contents=prompt
    )
    
    return response.text
  1. 整合所有功能
question = "What is the net profit for Nike?"
top_image_path = search(question)
answer_text = answer(question, top_image_path)

阿拉伯语词典导航和定义检索用例:

我实施了这个VisionRAG系统,并用阿拉伯语词典页面进行了广泛测试,在各种查询中取得了令人印象深刻的结果。

image/png

我创建了一个阿拉伯语词典页面图像数据库,并使用阿拉伯语和英语的自然语言查询测试了该系统。

  1. 基本定义查询
    • 查询:“ما معنى البروز؟”(“brose”是什么意思?)
    • 过程:系统搜索了词典页面并检索到包含该定义的精确页面
    • 结果:系统成功返回了图像中术语表下“brose”一词的定义,解释它指一种由燕麦片制成的食物。

高级考虑事项

用于提高效率的矢量量化

嵌入向量可以进行量化(从32位精度降低到4位或8位精度),以显著减少存储需求,同时保持大部分检索性能。这使得多模态RAG系统在大规模部署中更具实用性。

image/png

混合方法

为了获得最佳性能,请考虑:

  • 同时嵌入图像和相关文本
  • 创建重排序器设置以提高检索质量
  • 对隐私敏感型应用使用本地模型
  • 在同一系统中结合多种模态(文本、图像、表格)

结论

多模态RAG代表了信息检索系统的下一个演进,能够实现更强大的文档理解和查询回答能力。通过直接处理视觉元素而不是将所有内容转换为文本,这些系统可以:

  1. 保留视觉数据中的上下文信息
  2. 回答需要视觉推理的复杂问题
  3. 像人类一样更自然地处理文档
  4. 处理图表和表格等信息密集型可视化内容

无论您选择基于云API的方法还是完全本地化的实现,多模态RAG都为金融、医疗保健、技术文档、教育等领域的应用开辟了新的可能性。


本文是根据对多模态RAG系统的研究和各种来源的实施细节编写的。代码示例仅用于教育目的,可能需要为生产使用进行调整。如需更多信息,请查看:https://www.youtube.com/watch?v=V1VOdoEFaDw

社区

注册登录评论