LLaVA(Large Language and Visual Assistant的缩写)是一种有前景的开源生成式AI模型,它能够复制OpenAI GPT-4在处理图像对话方面的一些能力。用户可以将图片添加到LLaVA聊天会话中,不仅可以讨论这些图片的内容,也可以用它们以可视化的方式描述想法、背景或情况。
LLaVA最吸引人的特点是它在使用更简单的模型架构和数量级更少的训练数据的情况下,能够改进其他开源解决方案。这些特点使得LLaVA不仅训练更快、成本更低,而且更适合在消费级硬件上进行推理。
本文对LLaVA进行了概述,具体来说旨在:
在线使用LLaVA
如果你还没有尝试过,使用LLaVA最简单的方法是访问其作者提供的Web界面。下面的截图展示了该界面的操作方式,用户在给定冰箱内容图片的情况下询问关于吃什么饭的想法。可以使用左侧的小部件加载图片,聊天界面允许以文本形式提问和获取答案。
在这个例子中,LLaVA正确识别了冰箱中的食材,如蓝莓、草莓、胡萝卜、酸奶或牛奶,并提出了相关的想法,如果沙拉、冰沙或蛋糕。
项目网站上给出了与LLaVA对话的其他例子,这些例子表明LLaVA不仅能够描述图像,而且能够根据图像中的元素进行推理和论证(使用图片中的线索识别电影或人,根据图画编码网站,解释幽默情境等)。
在本地运行LLaVA
LLaVA 也可以使用 Ollama 或 Mozilla 的“llamafile”安装在本地机器上。这些工具可以在大多数仅使用 CPU 的消费级机器上运行,因为该模型只需要 8GB 的 RAM 和 4GB 的可用磁盘空间,甚至可以在 Raspberry PI 上成功运行。在围绕 Ollama 项目开发的工具和界面中,一个值得注意的举措是 Ollama-WebUI(如下图所示),它再现了 OpenAI ChatGPT 用户界面的外观和感觉。
Ollama Web 用户界面 — 受 OpenAI ChatGPT 启发
LLaVA主要功能的简要概述
LLaVA由威斯康星大学麦迪逊分校、微软研究院和哥伦比亚大学的研究人员设计,并在最近的NeurIPS 2023上进行了展示。项目的代码和技术规格可以在其Github存储库上访问,该存储库还提供了与助手交互的各种界面。
正如作者在论文摘要中总结的:
“[LLava] 在11个基准测试中达到了最先进的水平。我们最后的13B检查点仅使用120万条公开数据,并在单个8-A100节点上用约一天的时间完成全部训练。我们希望这可以使最先进的LMM研究更容易实现。代码和模型将公开发布。”
该论文中报告的基准结果如下面的雷达图所示,表明了与其他最先进的模型相比的改进。
内部工作原理
LLaVA的数据处理工作流程在概念上很简单。该模型本质上是一个标准的因果语言模型,以语言指令(用户文本提示)作为输入,并返回语言响应。语言模型处理图像的能力是通过一个单独的视觉编码器模型实现的,该模型将图像转换为语言标记,这些标记被悄悄添加到用户文本提示中(充当一种软提示)。LLaVA的过程如下图所示。
LLaVA的语言模型和视觉编码器分别依赖于两个参考模型,称为Vicuna和CLIP。Vicuna是基于LLaMA-2(由Meta设计)的预训练大型语言模型,与中型LLM(HuggingFace上的7B和13B版本)相比具有竞争性。。CLIP是由OpenAI设计的图像编码器,通过对比性语言-图像预训练来预训练图像和文本,使它们在类似的嵌入空间中编码(因此得名“CLIP”)。LLaVA中使用的模型是视觉Transformer变体CLIP-ViT-L/14(在HuggingFace上查看其模型卡片)。
为了使视觉编码器的维度与语言模型的维度相匹配,应用了一个投影模块(上图中的W)。在原始的LLaVA中,它是一个简单的线性投影,在LLaVA 1.5中是一个两层感知器。
训练过程
LLaVA的训练过程包括两个相对简单的阶段。
第一个阶段的唯一目标是调整投影模块W,视觉编码器和LLM的权重保持冻结。训练使用来自CC3M概念性字幕数据集的大约60万个图像/字幕对的子集进行。
在第二阶段,使用158K语言图像指令跟踪数据集,对投影模块权重W和LLM权重进行微调(同时保持视觉编码器权重冻结)。数据是使用GPT4生成的,特征示例包括对话、详细描述和复杂推理。
整个训练使用八个A100 GPU大约需要一天时间。
使用LLaVA进行编程:如何开始
LLaVA模型已集成到Transformers库中,并可以使用标准管道对象加载。7B和13B版本的模型可在LLaVA Hub空间上找到,并且可以以4位和8位加载以节省GPU内存。我们在下面展示了如何在Colab上使用T4 TPU(15GB RAM GPU)执行的代码来加载和运行模型。
下面是一个代码片段,用于加载4位LLaVA 1.5的7B变体:
from transformers import pipeline, BitsAndBytesConfig
import torch
quantization_config = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_compute_dtype=torch.float16
)
model_id = "llava-hf/llava-1.5-7b-hf"
pipe = pipeline("image-to-text", model=model_id, model_kwargs={"quantization_config": quantization_config})
那么,让我们来装载这张图片
我们使用标准的PIL库来加载图片:
import requests
from PIL import Image
image_url = "https://llava-vl.github.io/static/images/titanic.jpg"
image = Image.open(requests.get(image_url, stream=True).raw)
image
最后,我们用图片向LLaVA模型提问,提示要求描述这张图片。
注意:提示的格式如下:
“用户: <image>\n<prompt>\n助手:”
prompt = "USER: <image>\nDescribe this picture\nASSISTANT:"
outputs = pipe(image, prompt=prompt, generate_kwargs={"max_new_tokens": 200})
print(outputs[0]['generated_text'])
将返回以下答案:
“用户:描述这张图片
助手:图片展示了一个大型、空旷的露天剧场,背景是令人惊叹的海洋景色。露天剧场周围是郁郁葱葱的山坡,远处可以看到壮丽的山峰。场景宁静而如画,阳光在景观上方明亮地照耀着。”
LLaVA聊天机器人
最后,我们将创建一个简单的依赖于LLaVA模型的聊天机器人。我们将使用Gradio库,它提供了一种快速简便的方式来创建机器学习网络界面。
界面的核心包括一个图像上传器(一个Gradio Image对象)和一个聊天界面(一个Gradio ChatInterface对象)。
mport gradio as gr
with gr.Blocks() as demo:
with gr.Row():
image = gr.Image(type='pil', interactive=True)
gr.ChatInterface(
update_conversation, additional_inputs=[image]
)
聊天界面连接到一个函数update_conversation,该函数负责保持对话历史,并在用户发送消息时调用LLaVA模型进行响应。
def update_conversation(new_message, history, image):
if image is None:
return "Please upload an image first using the widget on the left"
conversation_starting_from_image = [[user, assistant] for [user, assistant] in history if not assistant.startswith('Please')]
prompt = "USER: <image>\n"
for i in range(len(history)):
prompt+=history[i][0]+'ASSISTANT: '+history[i][1]+"USER: "
prompt = prompt+new_message+'ASSISTANT: '
outputs = pipe(image, prompt=prompt, generate_kwargs={"max_new_tokens": 200, "do_sample" : True, "temperature" : 0.7})[0]['generated_text']
return outputs[len(prompt)-6:]
通过调用launch方法启动界面。
demo.launch(debug=True)
几秒钟后,聊天机器人的网络界面将出现:
恭喜,你的LLaVA聊天机器人现在已经启动并运行了!