构建LangChain应用程序的示例代码:53、利用多模态大型语言模型在RAG应用中处理混合文档的示例

news2024/7/7 19:31:26

许多文档包含多种内容类型,包括文本和图像。

然而,在大多数 RAG 应用中,图像中捕获的信息都会丢失。

随着多模态LLMs的出现,比如GPT-4V,如何在RAG中利用图像是值得考虑的。

本篇指南的亮点是:

  • 使用非结构化来解析文档 (PDF) 中的图像、文本和表格。
  • 使用多模态嵌入(例如 CLIP)来嵌入图像和文本
  • 使用 VDMS 作为支持多模式的矢量存储
  • 使用相似性搜索检索图像和文本
  • 将原始图像和文本块传递到多模式 LLM 以进行答案合成

Packages

对于 unstructured ,您的系统中还需要 poppler (安装说明)和 tesseract (安装说明)。

# (newest versions required for multi-modal)
! pip install --quiet -U vdms langchain-experimental

# lock to 0.10.19 due to a persistent bug in more recent versions
! pip install --quiet pdf2image "unstructured[all-docs]==0.10.19" pillow pydantic lxml open_clip_torch

启动VDMS服务器

让我们使用端口 55559 而不是默认的 55555 启动 VDMS docker。记下端口和主机名,因为矢量存储需要这些端口和主机名,因为它使用 VDMS Python 客户端连接到服务器。

! docker run --rm -d -p 55559:55555 --name vdms_rag_nb intellabs/vdms:latest

# Connect to VDMS Vector Store
from langchain_community.vectorstores.vdms import VDMS_Client

vdms_client = VDMS_Client(port=55559)

docker: Error response from daemon: Conflict. The container name
“/vdms_rag_nb” is already in use by container
“0c19ed281463ac10d7efe07eb815643e3e534ddf24844357039453ad2b0c27e8”.
You have to remove (or rename) that container to be able to reuse that
name. See ‘docker run --help’.

# from dotenv import load_dotenv, find_dotenv
# load_dotenv(find_dotenv(), override=True);

数据加载

分割 PDF 文本和图像

让我们看一个包含有趣图像的 pdf 示例。

国会图书馆的著名照片:

  • https://www.loc.gov/lcm/pdf/LCM_2020_1112.pdf
  • 我们将在下面使用它作为示例

我们可以使用下面的 Unstructed 中的 partition_pdf 来提取文本和图像。

from pathlib import Path

import requests

# Folder with pdf and extracted images
datapath = Path("./multimodal_files").resolve()
datapath.mkdir(parents=True, exist_ok=True)

pdf_url = "https://www.loc.gov/lcm/pdf/LCM_2020_1112.pdf"
pdf_path = str(datapath / pdf_url.split("/")[-1])
with open(pdf_path, "wb") as f:
    f.write(requests.get(pdf_url).content)
# Extract images, tables, and chunk text
from unstructured.partition.pdf import partition_pdf

raw_pdf_elements = partition_pdf(
    filename=pdf_path,
    extract_images_in_pdf=True,
    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=datapath,
)

datapath = str(datapath)
# Categorize text elements by type
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))

我们的文档的多模态嵌入

我们将使用 OpenClip 多模态嵌入。

我们使用更大的模型以获得更好的性能(在 langchain_experimental.open_clip.py 中设置)。

model_name = "ViT-g-14"
checkpoint = "laion2b_s34b_b88k"
import os

from langchain_community.vectorstores import VDMS
from langchain_experimental.open_clip import OpenCLIPEmbeddings

# Create VDMS
vectorstore = VDMS(
    client=vdms_client,
    collection_name="mm_rag_clip_photos",
    embedding_function=OpenCLIPEmbeddings(
        model_name="ViT-g-14", checkpoint="laion2b_s34b_b88k"
    ),
)

# Get image URIs with .jpg extension only
image_uris = sorted(
    [
        os.path.join(datapath, image_name)
        for image_name in os.listdir(datapath)
        if image_name.endswith(".jpg")
    ]
)

# Add images
if image_uris:
    vectorstore.add_images(uris=image_uris)

# Add documents
if texts:
    vectorstore.add_texts(texts=texts)

# Make retriever
retriever = vectorstore.as_retriever()

RAG

vectorstore.add_images 将存储/检索图像作为 base64 编码字符串。

import base64
from io import BytesIO

from PIL import Image


def resize_base64_image(base64_string, size=(128, 128)):
    """
    Resize an image encoded as a Base64 string.

    Args:
    base64_string (str): Base64 string of the original image.
    size (tuple): Desired size of the image as (width, height).

    Returns:
    str: Base64 string of the resized image.
    """
    # Decode the Base64 string
    img_data = base64.b64decode(base64_string)
    img = Image.open(BytesIO(img_data))

    # Resize the image
    resized_img = img.resize(size, Image.LANCZOS)

    # Save the resized image to a bytes buffer
    buffered = BytesIO()
    resized_img.save(buffered, format=img.format)

    # Encode the resized image to Base64
    return base64.b64encode(buffered.getvalue()).decode("utf-8")


def is_base64(s):
    """Check if a string is Base64 encoded"""
    try:
        return base64.b64encode(base64.b64decode(s)) == s.encode()
    except Exception:
        return False


def split_image_text_types(docs):
    """Split numpy array images and texts"""
    images = []
    text = []
    for doc in docs:
        doc = doc.page_content  # Extract Document contents
        if is_base64(doc):
            # Resize image to avoid OAI server error
            images.append(
                resize_base64_image(doc, size=(250, 250))
            )  # base64 encoded str
        else:
            text.append(doc)
    return {"images": images, "texts": text}

目前,我们使用 RunnableLambda 格式化输入,同时向 ChatPromptTemplates 添加图像支持。

我们的可运行程序遵循经典的 RAG 流程 -

  • 我们首先计算上下文(在本例中是“文本”和“图像”)和问题(这里只是一个 RunnablePassthrough)

  • 然后我们将其传递到提示模板中,这是一个自定义函数,用于格式化 llava 模型的消息。

  • 最后我们将输出解析为字符串。

在这里,我们使用 Ollama 来服务 Llava 模型。请参阅 Ollama 了解设置说明。

from langchain_community.llms.ollama import Ollama
from langchain_core.messages import HumanMessage
from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables import RunnableLambda, RunnablePassthrough


def prompt_func(data_dict):
    # Joining the context texts into a single string
    formatted_texts = "\n".join(data_dict["context"]["texts"])
    messages = []

    # Adding image(s) to the messages if present
    if data_dict["context"]["images"]:
        image_message = {
            "type": "image_url",
            "image_url": {
                "url": f"data:image/jpeg;base64,{data_dict['context']['images'][0]}"
            },
        }
        messages.append(image_message)

    # Adding the text message for analysis
    text_message = {
        "type": "text",
        "text": (
            "As an expert art critic and historian, your task is to analyze and interpret images, "
            "considering their historical and cultural significance. Alongside the images, you will be "
            "provided with related text to offer context. Both will be retrieved from a vectorstore based "
            "on user-input keywords. Please convert answers to english and use your extensive knowledge "
            "and analytical skills to provide a comprehensive summary that includes:\n"
            "- A detailed description of the visual elements in the image.\n"
            "- The historical and cultural context of the image.\n"
            "- An interpretation of the image's symbolism and meaning.\n"
            "- Connections between the image and the related text.\n\n"
            f"User-provided keywords: {data_dict['question']}\n\n"
            "Text and / or tables:\n"
            f"{formatted_texts}"
        ),
    }
    messages.append(text_message)
    return [HumanMessage(content=messages)]


def multi_modal_rag_chain(retriever):
    """Multi-modal RAG chain"""

    # Multi-modal LLM
    llm_model = Ollama(
        verbose=True, temperature=0.5, model="llava", base_url="http://localhost:11434"
    )

    # RAG pipeline
    chain = (
        {
            "context": retriever | RunnableLambda(split_image_text_types),
            "question": RunnablePassthrough(),
        }
        | RunnableLambda(prompt_func)
        | llm_model
        | StrOutputParser()
    )

    return chain

测试检索并运行 RAG

from IPython.display import HTML, display


def plt_img_base64(img_base64):
    # Create an HTML img tag with the base64 string as the source
    image_html = f'<img src="data:image/jpeg;base64,{img_base64}" />'

    # Display the image by rendering the HTML
    display(HTML(image_html))


query = "Woman with children"
docs = retriever.invoke(query, k=10)

for doc in docs:
    if is_base64(doc.page_content):
        plt_img_base64(doc.page_content)
    else:
        print(doc.page_content)

GREAT PHOTOGRAPHS
The subject of the photo, Florence Owens Thompson, a Cherokee from Oklahoma, initially regretted that Lange ever made this photograph. “She was a very strong woman. She was a leader,” her daughter Katherine later said. “I think that’s one of the reasons she resented the photo — because it didn’t show her in that light.”

DOROTHEA LANGE. “DESTITUTE PEA PICKERS IN CALIFORNIA. MOTHER OF SEVEN
CHILDREN. AGE THIRTY-TWO. NIPOMO, CALIFORNIA.” MARCH 1936. NITRATE
NEGATIVE. FARM SECURITY ADMINISTRATION-OFFICE OF WAR INFORMATION
COLLECTION. PRINTS AND PHOTOGRAPHS DIVISION.

—Helena Zinkham

—Helena Zinkham

NOVEMBER/DECEMBER 2020 LOC.GOV/LCM
在这里插入图片描述

chain = multi_modal_rag_chain(retriever)
response = chain.invoke(query)
print(response)
1. Detailed description of the visual elements in the image: The image features a woman with children, likely a mother and her family, standing together outside. They appear to be poor or struggling financially, as indicated by their attire and surroundings.
2. Historical and cultural context of the image: The photo was taken in 1936 during the Great Depression, when many families struggled to make ends meet. Dorothea Lange, a renowned American photographer, took this iconic photograph that became an emblem of poverty and hardship experienced by many Americans at that time.
3. Interpretation of the image's symbolism and meaning: The image conveys a sense of unity and resilience despite adversity. The woman and her children are standing together, displaying their strength as a family unit in the face of economic challenges. The photograph also serves as a reminder of the importance of empathy and support for those who are struggling.
4. Connections between the image and the related text: The text provided offers additional context about the woman in the photo, her background, and her feelings towards the photograph. It highlights the historical backdrop of the Great Depression and emphasizes the significance of this particular image as a representation of that time period.
! docker kill vdms_rag_nb
vdms_rag_nb

总结

本文介绍了如何在检索-生成(RAG)应用中结合使用多模态大型语言模型(LLMs),如GPT-4V,来处理包含文本和图像的混合文档。文章首先强调了在RAG中整合图像信息的重要性,并提出了使用非结构化工具来解析PDF中的图像、文本和表格的方法。接着,介绍了如何利用多模态嵌入(例如CLIP)和VDMS作为矢量存储来嵌入和检索图像和文本。文章还提供了详细的代码示例,包括如何启动VDMS服务器、加载数据、创建多模态嵌入、构建RAG链,以及如何测试检索和RAG链的运行。最后,文章通过一个具体的例子演示了如何使用RAG链来分析和解释图像,并提供了对图像的详细描述、历史和文化背景、象征意义的解释,以及图像与相关文本之间的联系。

扩展知识:

多模态LLMs:能够同时处理和生成图像和文本,适用于需要理解多种数据类型的应用场景。
RAG模型:结合了检索系统和生成模型,能够从大量文档中检索相关信息并生成答案。
VDMS:一种矢量数据库管理系统,支持多模态数据的存储和检索。
CLIP模型:由OpenAI开发,能够将图像和文本映射到共同的嵌入空间,用于图像和文本的联合检索。
非结构化数据处理:指对PDF等文档进行解析,提取其中的文本、图像和表格等信息,为后续处理提供结构化数据。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1894600.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Airflow: 大数据调度工具详解

欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;欢迎订阅相关专栏&#xff1a; 欢迎关注微信公众号&#xff1a;野老杂谈 ⭐️ 全网最全IT互联网公司面试宝典&#xff1a;收集整理全网各大IT互联网公司技术、项目、HR面试真题. ⭐️ AIGC时代的创新与未来&a…

国产芯片方案/蓝牙咖啡电子秤方案研发

咖啡电子秤芯片方案精确值可做到分度值0.1g的精准称重,并带有过载提示、自动归零、去皮称重、压低报警等功能&#xff0c;工作电压在2.4V~3.6V之间&#xff0c;满足于咖啡电子秤的电压使用。同时咖啡电子秤PCBA设计可支持四个单位显示&#xff0c;分别为&#xff1a;g、lb、oz、…

stm32——定时器级联

在STM32当中扩展定时范围&#xff1a;单个定时器的定时长度可能无法满足某些应用的需求。通过级联&#xff0c;可以实现更长时间的定时&#xff1b;提高定时精度&#xff1a;能够在长定时的基础上&#xff0c;通过合理配置&#xff0c;实现更精细的定时控制&#xff1b;处理复杂…

Git安装以及环境配置(详细)

一、Git下载 1.官网&#xff08;但是很慢&#xff09; https://git-scm.com/ 2.镜像版&#xff08;比较推荐&#xff09; CNPM Binaries Mirror 里边多个选择合适的进行下载&#xff08;不要选带有rc0,rc1的&#xff0c;都是预发布版本&#xff09; 进入后如下&#xff0c…

【LeetCode】十一、滑动窗口:长度最小的子数组 + 定长子串的元音最大数目

文章目录 1、滑动窗口2、leetcode209&#xff1a;长度最小的子数组3、leetcode1456&#xff1a;定长子串中元音的最大数目 1、滑动窗口 如下&#xff0c;有一个数组&#xff0c;现三个元素为一组&#xff0c;求最大的和&#xff0c;自然可以while循环实现&#xff1a;i 、i1、…

无线领夹麦克风哪个品牌好,推荐口碑最好的麦克风品牌

在5G网络普及的浪潮下&#xff0c;短视频平台的兴起带动了一股全民创作的热潮。无论是城市街头还是乡间小径&#xff0c;人们纷纷拿起手机&#xff0c;记录生活中的点点滴滴。领夹式麦克风凭借其精准的拾音特性和稳定的信号传输&#xff0c;无论是在静止状态还是在移动过程中&a…

【MindSpore学习打卡】应用实践-计算机视觉-SSD目标检测:从理论到实现

在计算机视觉领域&#xff0c;目标检测是一个至关重要的任务。它不仅要求识别图像中的目标物体&#xff0c;还需要精确定位这些物体的位置。近年来&#xff0c;随着深度学习技术的飞速发展&#xff0c;各种高效的目标检测算法层出不穷。SSD&#xff08;Single Shot MultiBox De…

Elasticsearch 使用误区之二——频繁更新文档

在使用 Elasticsearch 时&#xff0c;频繁更新文档是一种常见误区。这不仅影响性能&#xff0c;还可能导致系统资源的浪费。 理解 Elasticsearch 的文档更新机制对于优化性能至关重要。 关于 Elasticsearch 更新操作&#xff0c;常见问题如下&#xff1a; ——https://t.zsxq.c…

2024年显著性检测部分论文及代码汇总(3)

ICML Size-invariance Matters: Rethinking Metrics and Losses for Imbalanced Multi-object Salient Object Detection code Abstacrt&#xff1a;本文探讨了显著性检测中评价指标的尺寸不变性&#xff0c;尤其是当图像中存在多个大小不同的目标时。作者观察到&#xff0c;…

Elasticsearch集群部署(上)

目录 前言 一. 环境准备 二. 实施部署 三. 安装配置head监控插件 &#xff08;只在第一台es部署&#xff09; 四. Kibana部署&#xff08;当前还是在第一台es部署&#xff09; 五. 安装配置Nginx反向代理 六. Logstash部署与测试 下篇&#xff1a;Elasticsearch集群部…

汽配企业MES管理系统的四大应用场景

在当今快速迭代的汽车工业领域&#xff0c;一家位于繁华工业园区的中型汽配制造企业正经历着前所未有的变革。该企业&#xff0c;作为汽车发动机零部件的重要供应商&#xff0c;其客户网络遍布国内外&#xff0c;与多家知名汽车制造商保持着紧密的合作关系。然而&#xff0c;随…

WordPress主题大前端DUX v8.7源码下载

全新&#xff1a;用户注册流程&#xff0c;验证邮箱&#xff0c;设置密码 新增&#xff1a;列表显示小视频和横幅视频 新增&#xff1a;文章内容中的外链全部增加 nofollow 新增&#xff1a;客服功能中的链接添加 nofollow 优化&#xff1a;产品分类的价格显示

JavaScript中的this指向

1. 全局环境下的this 在全局环境中&#xff08;在浏览器中是window对象&#xff0c;在Node.js中是global对象&#xff09;&#xff0c;this指向全局对象。 console.log(this window); // 在浏览器中为true console.log(this.document ! undefined); // true&#xff0c;因为…

测试引擎模拟接口实战

在上一章的内容中&#xff0c;我简单介绍了整个微服务的各个子模块&#xff0c;还封装了一些工具类。 当然&#xff0c;若还没完成上次内容的也可以点击右侧的传送门------传送门 EngineApplication 在开发测试引擎模拟接口之前&#xff0c;还需要给xxx-engine创建一个Sprin…

盛元广通打造智慧校园实验室安全管理系统

盛元广通智慧校园实验室安全管理系统以安全为重点&#xff0c;构建由学校、二级单位、实验室组成的三级联动的实验室安全多级管理体系、多类用户角色&#xff0c;内置教育部标准检查表&#xff0c;支撑实验室相关业务过程的智慧管理。实现通过PC端/手机移动端开展检查工作、手机…

上位机图像处理和嵌入式模块部署(mcu项目1:实现协议)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 这种mcu的嵌入式模块理论上都是私有协议&#xff0c;因为上位机和下位机都是自己开发的&#xff0c;所以只需要自己保证上、下位机可以通讯上&…

【SQL】⼀棵 B+树能存储多少条数据

B树的存储容量取决于多个因素&#xff0c;包括树的阶&#xff08;即每个节点的最大子节点数&#xff09;、键的大小和每个节点的容量。计算一棵B树能存储多少条数据&#xff0c;通常需要了解以下参数&#xff1a; 节点大小&#xff1a;一般情况下&#xff0c;节点大小等于数据…

2024Datawhale-AI夏令营——机器学习挑战赛——学习笔记

#ai夏令营#datawhale#夏令营 Day1:入门级demo运行 这个其实比较简单&#xff0c;按照操作来做就行了&#xff0c;特征工程和调参暂时都没有做&#xff0c;后续的才是重头戏。 Day2:正式比赛开始 赛题&#xff1a;数据挖掘赛道——利用机器学习方法根据给定的特征判断PROTACs…

选微调、RAG还是微调+RAG?

RAG技术是一种结合了检索与生成的方法。它通常依赖于两个核心组件&#xff1a;一个大型语言模型&#xff08;如GPT-3&#xff09;和一个检索系统&#xff08;如向量数据库&#xff09;。RAG先使用检索系统从大量数据中检索出相关信息&#xff0c;然后将这些信息提供给语言模型&…

python自动化内存管理

引用 在编程中&#xff0c;引用是指用来标识、访问或操作某个对象的值的标识符或变量。我们可以将引用看作是对象的别名&#xff0c;通过引用可以操作对象&#xff0c;包括读取、修改和传递对象的值。 举例来说&#xff0c;假设我们有一个字符串对象name&#xff0c;我们可以创…