文章目录

好奇这张图片是在哪里拍的?问问LLaVA吧!
LLaVA(大型语言和视觉助手的缩写)是一个有前途的开源生成AI模型,可以复制OpenAI GPT-4的一些能力,与图像进行对话。用户可以将图像添加到LLaVA聊天对话中,讨论这些图像的内容,还可以将它们用作以视觉方式描述想法、背景或情境的方式。
LLaVA最引人注目的特点是它能够在使用更简单的模型架构和数量级更少的训练数据的情况下改进其他开源解决方案。这些特点使LLaVA不仅更快、更便宜地进行训练,而且更适合在消费者硬件上进行推理。
本文概述了LLaVA,更具体地旨在:
-
展示如何从Web界面进行实验,以及如何在计算机或笔记本电脑上安装它
-
解释其主要技术特点
-
说明如何使用它进行编程,使用HuggingFace库(Transformers和Gradio)在Google Colab上构建一个简单的聊天机器人应用程序作为示例。
在线使用LLaVA
如果您还没有尝试过,使用LLaVA的最简单方法是访问其作者提供的Web界面。下面的截图说明了界面的操作方式,其中用户询问如何根据冰箱内容的图片获得做饭的想法。可以使用左侧的小部件加载图像,聊天界面允许以文本形式提问并获得答案。
在线LLaVA界面
在这个例子中,LLaVA正确地识别了冰箱里的食材,比如蓝莓、草莓、胡萝卜、酸奶或牛奶,并提出了相关的想法,比如水果沙拉、冰沙或蛋糕。
LLaVA的其他对话示例可以在项目网站上找到,这些示例说明LLaVA不仅可以描述图像,还可以根据图像中的元素进行推理和推断(使用图片中的线索识别电影或人物,根据绘画编写网站,解释幽默情境等)。
在本地运行LLaVA
LLaVA也可以使用Ollama或Mozilla的’llamafile’在本地机器上安装。这些工具可以在大多数仅支持CPU的消费级机器上运行,因为该模型只需要8GB的RAM和4GB的可用磁盘空间,甚至已经成功地在树莓派上运行过。在Ollama项目周围开发的工具和界面中,一个值得注意的举措是Ollama-WebUI(如下图所示),它复制了OpenAI ChatGPT用户界面的外观和感觉。
LLaVA的主要特点简要概述
LLaVA是由威斯康星大学麦迪逊分校、微软研究院和哥伦比亚大学的研究人员设计的,并最近在NeurIPS 2023上展示。该项目的代码和技术规范可以在其Github存储库上访问,该存储库还提供了与助手交互的各种接口。
正如作者在他们论文的摘要中总结的那样:
[LLava]在11个基准测试中取得了最先进的成果。我们的最终13B检查点仅使用了120万个公开可用的数据,并在单个8-A100节点上的约1天内完成了完整的训练。我们希望这可以使最先进的LMM研究更加易于访问。代码和模型将公开可用。
下面的雷达图显示了与其他最先进模型相比的改进的基准结果,这些结果在论文中报告。
内部工作原理
LLaVA的数据处理工作流程在概念上非常简单。该模型基本上作为标准因果语言模型运作,将语言指令(用户文本提示)作为输入,并返回语言响应。语言模型处理图像的能力是由一个单独的视觉编码器模型实现的,该模型将图像转换为语言标记,这些标记被静默地添加到用户文本提示中(作为一种软提示)。LLaVA的过程如下图所示。
LLaVA网络架构(图片来自paper)
LLaVA的语言模型和视觉编码器依赖于两个称为Vicuna和CLIP的参考模型。Vicuna是一个基于LLaMA-2(由Meta设计)的预训练大型语言模型,具有与中型LLM相媲美的性能(请参阅HuggingFace上的7B和13B版本的模型卡片)。CLIP是由OpenAI设计的图像编码器,经过预训练以在相似的嵌入空间中编码图像和文本(因此称为“CLIP”)。LLaVA中使用的模型是视觉变换器变体CLIP-ViT-L/14(请参阅HuggingFace上的模型卡片)。
为了使视觉编码器的维度与语言模型的维度匹配,应用了一个投影模块(上图中的W)。在原始的LLaVA中,它是一个简单的线性投影,而在LLaVA 1.5中是一个两层感知器。
训练过程
LLaVA的训练过程包括两个相对简单的阶段。
第一阶段仅旨在调整投影模块W,并保持视觉编码器和LLM的权重冻结。训练使用来自CC3M概念字幕数据集约600k个图像/字幕对的子集进行,可在HuggingFace的此存储库中获得。
在第二阶段,使用包含158K个语言-图像指令跟随数据的数据集,同时微调投影模块权重W和LLM权重(同时保持视觉编码器的权重冻结)。这些数据是使用GPT4生成的,并包含对话、详细描述和复杂推理的特征示例,可在HuggingFace的此存储库中获得。
整个训练过程使用八个A100 GPU大约需要一天的时间。
使用LLaVA进行编程:如何入门
代码可在 Colab相关笔记本* 上获得。
LLaVA模型已集成到Transformers库中,可以使用标准的pipeline对象加载。模型的7B和13B变体可在LLaVA 😊 Hub空间上获得,并且可以以4位和8位加载以节省GPU内存。下面我们将演示如何加载和运行模型的代码,该代码可以在Colab上使用T4 TPU(15GB RAM GPU)执行。
以下是加载LLaVA 1.5的7B变体的代码片段(以4位加载):
from transformers import pipeline, BitsAndBytesConfig # 导入所需的库
import torch # 导入torch库
quantization_config = BitsAndBytesConfig( # 创建一个BitsAndBytesConfig对象,用于配置量化参数
load_in_4bit=True, # 设置加载模型时使用4位量化
bnb_4bit_compute_dtype=torch.float16 # 设置计算时使用16位浮点数
)
model_id = "llava-hf/llava-1.5-7b-hf" # 设置模型的ID
pipe = pipeline("image-to-text", model=model_id, model_kwargs={"quantization_config": quantization_config}) # 创建一个图像到文本的pipeline对象,使用指定的模型和量化配置
让我们加载这张图片。
我们使用标准的PIL库来加载图片:
# 导入requests模块和PIL库
import requests
from PIL import Image
# 定义图片链接
image_url = "https://cdn.pixabay.com/photo/2018/01/29/14/13/italy-3116211_960_720.jpg"
# 通过requests模块获取图片流,并使用PIL库打开图片
image = Image.open(requests.get(image_url, stream=True).raw)
# 显示图片
image
让我们最终使用图片查询LLaVA模型,并提示描述图片。
注意:提示的格式如下所示:
“USER: \n\nASSISTANT:”
# 定义一个字符串变量prompt,用于存储对话的起始部分
prompt = "USER: <image>\nDescribe this picture\nASSISTANT:"
# 调用pipe方法,传入图片和对话起始部分作为参数,同时设置生成文本的最大长度为200个token
outputs = pipe(image, prompt=prompt, generate_kwargs={"max_new_tokens": 200})
# 打印生成的文本结果
print(outputs[0]['generated_text'])
LLaVA聊天机器人
让我们最终创建一个简单的聊天机器人,它依赖于LLaVA模型。我们将使用Gradio库,它提供了一种快速简便的方式来创建机器学习的Web界面。
界面的核心包括一个图像上传器(一个Gradio Image对象)和一个聊天界面(一个Gradio ChatInterface对象)。
import gradio as gr
# 创建一个Gradio应用程序
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"
# 从历史记录中找到不以“Please”开头的对话,作为新的对话起点
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文件,并开启调试模式
demo.launch(debug=True)
几秒钟后,聊天机器人的Web界面将出现:
恭喜,您的LLaVA聊天机器人现在已经启动!
有用的链接
-
使用AutoPrecessor和LLaVAForConditionalGeneration加载和运行LLaVA:Colab笔记本