• 基于BLIP-2的看图问答原理及实现


    大型语言模型 (LLM) 最近获得了很大的关注,出现了许多流行的模型,如 GPT、OPT、BLOOM 等。 这些模型擅长学习自然语言,非常适合构建聊天机器人、编码助手、决策助手或翻译系统。 然而,他们缺乏其他模式的知识—例如,他们无法处理图像、音频或视频。 这就是 BLIP 的用武之地,通过视觉理解来增强LLM的自然语言能力。

    在这里插入图片描述

    推荐:用 NSDT编辑器 快速搭建可编程3D场景

    本质上,你可以向 BLIP 模型提供图像和文本对来执行各种任务,例如视觉问答 (VQA)、图像字幕或图像文本检索。

    然而,用 BLIP 构建产品可能并不简单:你需要正确的模型服务框架和数据序列化库。 在 Jina AI,我们始终相信多模态 AI,因此我们为此目的优化了 Jina 和 DocArray。 为 BLIP-2 提供服务是这两个项目的典型用例。

    让我们看看它是如何工作的!

    1、BLIP-2

    BLIP-2是论文BLIP-2:Bootstrapping Language-Image Pre-training with Frozen Image Encoders and Large Language Models中提出的视觉语言模型。

    它利用冻结的预训练图像编码器和 LLM,通过在它们之间训练轻量级 12 层 Transformer 编码器,在各种视觉语言任务上实现最先进的性能。
    在这里插入图片描述

    2、Jina 和 DocArray

    在深入研究代码之前,我们先简要介绍一下 Jina 和 DocArray,并解释一下这两个项目最近发生的情况。

    Jina 是一个 MLOps 框架,用于构建和提供多模式 AI 服务,然后在云上扩展和部署它们。 但最近我们一直在重塑 Jina,以更有效地为模型提供服务。 在 3.14 版本中,我们允许用户使用 gRPC 协议将 Executor 作为独立服务提供服务。 在这篇文章中,我们将使用这些新发布的功能来服务于 BLIP-2 模型。

    对于数据表示和序列化,Jina 使用 DocArray,这是一个用于非结构化、多模态数据的库。 它针对传输中的数据进行了优化,因为数据可以以多种格式(包括 protobuf)进行序列化。 换句话说,可以使用 DocArray 格式通过线路接收/发送模型输入和输出。

    我们还重塑了 DocArray,以更好地适应多模式 AI 用例。 事实上,它正在经历大量重构,目标是通过 DocArray v2 提供灵活且强大的数据格式。

    因此,我们将使用当前的 DocArray 和 DocArray v2 的 alpha 版本来表示模型查询和输出(这样做时,你将很快理解我们为什么重构 DocArray!)。

    3、使用 DocArray 和 Jina 为 BLIP-2 提供服务

    由于 BLIP-2 使用 LLM,因此它配备了不同的开源语言模型(即 flan-t5 和 opt)。 在本博客中,我们将使用 flan-t5-xl。 让我们从安装依赖项开始:

    pip install jina torch git+https://github.com/huggingface/transformers pillow
    
    • 1

    然后,我们可以初始化一个加载模型的 Jina Executor:

    from jina import Executor, Deployment, DocumentArray, requests
    from transformers import Blip2Processor, Blip2ForConditionalGeneration
    import torch
    
    class Blip2Executor(Executor):
        def __init__(self, **kwargs):
            super().__init__(**kwargs)
            self.processor = Blip2Processor.from_pretrained("Salesforce/blip2-flan-t5-xl")
            self.model = Blip2ForConditionalGeneration.from_pretrained(
                "Salesforce/blip2-flan-t5-xl", torch_dtype=torch.float16
            )
            self.model.to('cuda')
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    使用 BLIP-2 执行视觉问答任务非常简单:只需将图像和文本问题输入并生成文本输出即可。

    让我们创建一个 Executor Endpoint 方法来启用 VQA 任务:

    @requests
    def vqa(self, docs: DocumentArray, **kwargs):
        for doc in docs:
            doc.load_uri_to_image_tensor()
            inputs = self.processor(images=doc.tensor, text=doc.tags['prompt'], return_tensors="pt").to('cuda', torch.float16)
            generated_ids = self.model.generate(**inputs)
            generated_text = self.processor.batch_decode(generated_ids, skip_special_tokens=True)[0].strip()
            doc.tags['response'] = generated_text
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    DocArray文档可以在张量字段中存储图像,我们可以将提示和文本输出放在标签字段中。

    最后,我们可以使用新发布的 Deployment 类为我们的 Executor 提供服务:

    with Deployment(uses=Blip2Executor, timeout_ready=-1, port=12345) as dep:
        dep.block()`
    
    • 1
    • 2
    Loading checkpoint shards: 100%|██████████████████████████████████| 2/2 [00:05<00:00,  2.92s/it]
    ─────────────────────────────── 🎉 Deployment is ready to serve! ───────────────────────────────
    ╭────────────────────── 🔗 Endpoint ──────────────────────╮
    │  ⛓   Protocol                                     GRPC │
    │  🏠     Local                            0.0.0.0:12345  │
    │  🔒   Private                     192.168.178.31:12345  │
    │  🌍    Public  2003:f1f:4a00:85b7:3950:81fa:952f:12345  │
    ╰─────────────────────────────────────────────────────────╯
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    现在我们的执行者应该准备好服务了。 只需使用 Jina Client 通过 gRPC 向 Executor 发送请求即可:

    在这里插入图片描述

    from jina import Client, Document
    client = Client(port=12345)
    
    docs = client.post(
            on='/', 
            inputs=[Document(
                uri='',
                tags={'prompt': 'Question: How many cats are there? Answer:'}
            )]
    )
    print(docs[0].tags['response'])
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    two
    
    • 1

    正如我们所看到的,BLIP-2 正确地回答了这个问题。 但这个答案的包装有点……笨拙。 虽然 DocArray 提供了标签和块等动态字段的灵活性,但这也带来了一些缺点:没有显式模式、奇怪的语法以及用于输入和输出的相同模式。

    这就是我们在 DocArray v2 中重构内容的原因!

    4、DocArray v2 :更好的语法

    DocArray v2 背后的主要思想是用户可以使用类型提示定义输入和输出模式。 这意味着你在这些模式中定义所需的字段,而不是尝试将数据放入固定模式文档中。

    这是 DocArray v1 表示数据的方式。 表示多模式数据意味着向文档添加更多块(子文档)。
    在这里插入图片描述

    现在,在 DocArray v2 中,模式不再将所有内容都转储到标签和块字段中,而是更加灵活和具有代表性。 你可以根据需要添加任意数量的字段,并确保严格输入数据验证:
    在这里插入图片描述

    这提供了两全其美的优点。 它使用户可以灵活地定义自己的模式,同时提供显式类型以实现更好的数据验证和转换。

    Jina 提供了对 DocArray v2 的早期支持,并允许你在执行器端点中使用模式作为类型注释来定义服务的输入/输出格式。

    让我们看看它是如何工作的。 首先从 v2 开发分支安装 DocArray:

    pip install "git+https://github.com/docarray/docarray@feat-rewrite-v2#egg=docarray[common,torch,image]"
    
    • 1

    然后我们将通过指定输入和输出模式来重写执行器:

    • 输入模式包括图像和文本提示字段。
    • 输出架构仅包含一个文本字段(生成的响应)。
    from jina import Executor, requests
    from transformers import Blip2Processor, Blip2ForConditionalGeneration
    import torch
    
    from docarray import BaseDocument, DocumentArray
    from docarray.typing import ImageUrl
    
    class ImagePrompt(BaseDocument):
        img: ImageUrl
        prompt: str
    
    class Response(BaseDocument):
        answer: str
    
    class Blip2Executor(Executor):
        def __init__(self, **kwargs):
            super().__init__(**kwargs)
            self.processor = Blip2Processor.from_pretrained("Salesforce/blip2-flan-t5-xl")
            self.model = Blip2ForConditionalGeneration.from_pretrained(
                "Salesforce/blip2-flan-t5-xl", torch_dtype=torch.float16
            )
            self.model.to('cuda')
    
        @requests
        def vqa(self, docs: DocumentArray[ImagePrompt], **kwargs) -> DocumentArray[Response]:
            response_docs = DocumentArray[Response]()
            for doc in docs:
                inputs = self.processor(images=doc.img.load(), text=doc.prompt, return_tensors="pt").to('cuda', torch.float16)
                generated_ids = self.model.generate(**inputs)
                generated_text = self.processor.batch_decode(generated_ids, skip_special_tokens=True)[0].strip()
                response_docs.append(Response(answer=generated_text))
            return response_docs
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    现在,让我们为 Executor 提供服务并向其提交请求:

    from jina import Deployment
    
    with Deployment(uses=Blip2Executor) as dep:
        docs = dep.post(on='/bar', inputs=ImagePrompt(
            img='',
            prompt='Question: how many cats are there ? Answer:'
        ), return_type=DocumentArray[Response])
        print(docs[0].answer)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    two
    
    • 1

    5、结束语

    Jina 可让你构建基于 gRPC 的多模式 AI 服务。 它允许你以 Python 方式定义端点和请求/响应模式,从而消除了构建 gRPC 服务的复杂性。

    DocArray 可让你高效地表示和序列化多模式数据。 为此,它提供了预定义的多模式数据类型和内置的 protobuf 序列化。

    因此,Jina 和 DocArray 凭借高效的网络和序列化、Pythonic API 和富有表现力的数据类型等支柱,为构建多模态AI 服务提供了顶级的技术栈。


    原文链接:基于BLIP-2的视觉问答 — BimAnt

  • 相关阅读:
    后端项目-菩提阁
    阿里云中的云服务器的ubuntu中的vim没有显示行号
    【JAVA】07 面向对象(高级)类变量、类方法、代码块、final、抽象类、接口、内部类
    怎么把图片压缩小一点?4个简单的压缩办法
    redis 队列
    比 MyBatis 快了 100 倍
    深度学习 opencv python 公式识别(图像识别 机器视觉) 计算机竞赛
    JavaScript中的模块化编程,包括CommonJS和ES6模块的区别。
    神奇的卡尔曼滤波,行人追踪的福音
    Google开源offload友好协议PSP,目前已正式部署到生产中
  • 原文地址:https://blog.csdn.net/shebao3333/article/details/132872965