Ola-7B是由腾讯、清华大学和南洋理工大学联合开发的多模态语言模型,基于Qwen2.5架构,支持处理图像、视频、音频和文本输入,并输出文本。
下载量 61
发布时间 : 2/20/2025
模型介绍
内容详情
替代品
模型简介
Ola-7B是一种全模态语言模型,能够无缝处理任意空间尺寸和时间长度的视觉输入,支持多种模态数据的联合理解与生成。
模型特点
全模态处理能力
支持图像、视频、音频和文本多种模态数据的联合处理与理解
长上下文支持
32K token的上下文窗口,适合处理长序列输入
高效视觉处理
采用渐进式模态对齐技术,高效处理任意尺寸的视觉输入
模型能力
图像理解
视频理解
音频理解
文本生成
多模态联合推理
使用案例
多媒体内容理解
视频内容分析
分析视频内容并生成描述性文本
图像问答
根据图像内容回答问题
跨模态生成
音频描述生成
根据音频内容生成文字描述
pipeline_tag: 图像文本到文本 license: apache-2.0 base_model:
- Qwen/Qwen2.5-7B-Instruct language:
- 英文
- 中文 datasets:
- HuggingFaceFV/finevideo
Ola-7B
模型概述
Ola-7B模型由腾讯、清华大学和南洋理工大学的研究人员联合开发。基于Qwen2.5语言模型,该模型在文本、图像、视频和音频数据上进行训练,上下文窗口为32K token。它能接收图像/视频、文本和音频作为输入,并输出文本。
Ola提供了一种按需解决方案,能够无缝且高效地处理任意空间尺寸和时间长度的视觉输入。
- 代码仓库: https://github.com/Ola-Omni/Ola
- 支持语言: 英语、中文
- 论文: https://huggingface.co/papers/2502.04328
使用方法
- 从https://huggingface.co/THUdyh/Ola_speech_encoders下载语音编码器
- 将config.json中的路径替换为语音编码器的本地路径
我们提供了一个简单的生成流程来使用我们的模型。更多细节请参考我们的GitHub仓库
import os
os.environ['LOWRES_RESIZE'] = '384x32'
os.environ['HIGHRES_BASE'] = '0x32'
os.environ['VIDEO_RESIZE'] = "0x64"
os.environ['VIDEO_MAXRES'] = "480"
os.environ['VIDEO_MINRES'] = "288"
os.environ['MAXRES'] = '1536'
os.environ['MINRES'] = '0'
os.environ['REGIONAL_POOL'] = '2x'
os.environ['FORCE_NO_DOWNSAMPLE'] = '1'
os.environ['LOAD_VISION_EARLY'] = '1'
os.environ['SKIP_LOAD_VIT'] = '1'
import gradio as gr
import torch
import re
from decord import VideoReader, cpu
from PIL import Image
import numpy as np
import transformers
import moviepy.editor as mp
from typing import Dict, Optional, Sequence, List
import librosa
import whisper
from ola.conversation import conv_templates, SeparatorStyle
from ola.model.builder import load_pretrained_model
from ola.utils import disable_torch_init
from ola.datasets.preprocess import tokenizer_image_token, tokenizer_speech_image_token, tokenizer_speech_question_image_token
from ola.mm_utils import get_model_name_from_path, KeywordsStoppingCriteria, process_anyres_video, process_anyres_highres_image_genli
from ola.constants import IGNORE_INDEX, DEFAULT_IMAGE_TOKEN, IMAGE_TOKEN_INDEX, DEFAULT_SPEECH_TOKEN
model_path = ""
tokenizer, model, image_processor, _ = load_pretrained_model(model_path, None)
model = model.to('cuda').eval()
model = model.bfloat16()
USE_SPEECH=False
cur_dir = os.path.dirname(os.path.abspath(__file__))
def load_audio(audio_file_name):
speech_wav, samplerate = librosa.load(audio_file_name, sr=16000)
if len(speech_wav.shape) > 1:
speech_wav = speech_wav[:, 0]
speech_wav = speech_wav.astype(np.float32)
CHUNK_LIM = 480000
SAMPLE_RATE = 16000
speechs = []
speech_wavs = []
if len(speech_wav) <= CHUNK_LIM:
speech = whisper.pad_or_trim(speech_wav)
speech_wav = whisper.pad_or_trim(speech_wav)
speechs.append(speech)
speech_wavs.append(torch.from_numpy(speech_wav).unsqueeze(0))
else:
for i in range(0, len(speech_wav), CHUNK_LIM):
chunk = speech_wav[i : i + CHUNK_LIM]
if len(chunk) < CHUNK_LIM:
chunk = whisper.pad_or_trim(chunk)
speechs.append(chunk)
speech_wavs.append(torch.from_numpy(chunk).unsqueeze(0))
mels = []
for chunk in speechs:
chunk = whisper.log_mel_spectrogram(chunk, n_mels=128).permute(1, 0).unsqueeze(0)
mels.append(chunk)
mels = torch.cat(mels, dim=0)
speech_wavs = torch.cat(speech_wavs, dim=0)
if mels.shape[0] > 25:
mels = mels[:25]
speech_wavs = speech_wavs[:25]
speech_length = torch.LongTensor([mels.shape[1]] * mels.shape[0])
speech_chunks = torch.LongTensor([mels.shape[0]])
return mels, speech_length, speech_chunks, speech_wavs
def extract_audio(videos_file_path):
my_clip = mp.VideoFileClip(videos_file_path)
return my_clip.audio
def ola_inference(multimodal, audio_path):
visual, text = multimodal["files"][0], multimodal["text"]
if visual.endswith("image2.png"):
modality = "video"
visual = f"{cur_dir}/case/case1.mp4"
if visual.endswith(".mp4"):
modality = "video"
else:
modality = "image"
# 输入音频和视频时,不解析视频中的音频;否则解析视频中的音频
if audio_path:
USE_SPEECH = True
elif modality == "video":
USE_SPEECH = True
else:
USE_SPEECH = False
speechs = []
speech_lengths = []
speech_wavs = []
speech_chunks = []
if modality == "video":
vr = VideoReader(visual, ctx=cpu(0))
total_frame_num = len(vr)
fps = round(vr.get_avg_fps())
uniform_sampled_frames = np.linspace(0, total_frame_num - 1, 64, dtype=int)
frame_idx = uniform_sampled_frames.tolist()
spare_frames = vr.get_batch(frame_idx).asnumpy()
video = [Image.fromarray(frame) for frame in spare_frames]
else:
image = [Image.open(visual)]
image_sizes = [image[0].size]
if USE_SPEECH and audio_path:
audio_path = audio_path
speech, speech_length, speech_chunk, speech_wav = load_audio(audio_path)
speechs.append(speech.bfloat16().to('cuda'))
speech_lengths.append(speech_length.to('cuda'))
speech_chunks.append(speech_chunk.to('cuda'))
speech_wavs.append(speech_wav.to('cuda'))
print('加载音频')
elif USE_SPEECH and not audio_path:
# 解析视频中的音频
audio = extract_audio(visual)
audio.write_audiofile("./video_audio.wav")
video_audio_path = './video_audio.wav'
speech, speech_length, speech_chunk, speech_wav = load_audio(video_audio_path)
speechs.append(speech.bfloat16().to('cuda'))
speech_lengths.append(speech_length.to('cuda'))
speech_chunks.append(speech_chunk.to('cuda'))
speech_wavs.append(speech_wav.to('cuda'))
else:
speechs = [torch.zeros(1, 3000, 128).bfloat16().to('cuda')]
speech_lengths = [torch.LongTensor([3000]).to('cuda')]
speech_wavs = [torch.zeros([1, 480000]).to('cuda')]
speech_chunks = [torch.LongTensor([1]).to('cuda')]
conv_mode = "qwen_1_5"
if text:
qs = text
else:
qs = ''
if USE_SPEECH and audio_path:
qs = DEFAULT_IMAGE_TOKEN + "\n" + "用户语音提问: " + DEFAULT_SPEECH_TOKEN + '\n'
elif USE_SPEECH:
qs = DEFAULT_SPEECH_TOKEN + DEFAULT_IMAGE_TOKEN + "\n" + qs
else:
qs = DEFAULT_IMAGE_TOKEN + "\n" + qs
conv = conv_templates[conv_mode].copy()
conv.append_message(conv.roles[0], qs)
conv.append_message(conv.roles[1], None)
prompt = conv.get_prompt()
if USE_SPEECH and audio_path:
input_ids = tokenizer_speech_question_image_token(prompt, tokenizer, IMAGE_TOKEN_INDEX, return_tensors="pt").unsqueeze(0).to('cuda')
elif USE_SPEECH:
input_ids = tokenizer_speech_image_token(prompt, tokenizer, IMAGE_TOKEN_INDEX, return_tensors="pt").unsqueeze(0).to('cuda')
else:
input_ids = tokenizer_image_token(prompt, tokenizer, IMAGE_TOKEN_INDEX, return_tensors="pt").unsqueeze(0).to('cuda')
if modality == "video":
video_processed = []
for idx, frame in enumerate(video):
image_processor.do_resize = False
image_processor.do_center_crop = False
frame = process_anyres_video(frame, image_processor)
if frame_idx is not None and idx in frame_idx:
video_processed.append(frame.unsqueeze(0))
elif frame_idx is None:
video_processed.append(frame.unsqueeze(0))
if frame_idx is None:
frame_idx = np.arange(0, len(video_processed), dtype=int).tolist()
video_processed = torch.cat(video_processed, dim=0).bfloat16().to("cuda")
video_processed = (video_processed, video_processed)
video_data = (video_processed, (384, 384), "video")
else:
image_processor.do_resize = False
image_processor.do_center_crop = False
image_tensor, image_highres_tensor = [], []
for visual in image:
image_tensor_, image_highres_tensor_ = process_anyres_highres_image_genli(visual, image_processor)
image_tensor.append(image_tensor_)
image_highres_tensor.append(image_highres_tensor_)
if all(x.shape == image_tensor[0].shape for x in image_tensor):
image_tensor = torch.stack(image_tensor, dim=0)
if all(x.shape == image_highres_tensor[0].shape for x in image_highres_tensor):
image_highres_tensor = torch.stack(image_highres_tensor, dim=0)
if type(image_tensor) is list:
image_tensor = [_image.bfloat16().to("cuda") for _image in image_tensor]
else:
image_tensor = image_tensor.bfloat16().to("cuda")
if type(image_highres_tensor) is list:
image_highres_tensor = [_image.bfloat16().to("cuda") for _image in image_highres_tensor]
else:
image_highres_tensor = image_highres_tensor.bfloat16().to("cuda")
pad_token_ids = 151643
attention_masks = input_ids.ne(pad_token_ids).long().to('cuda')
stop_str = conv.sep if conv.sep_style != SeparatorStyle.TWO else conv.sep2
keywords = [stop_str]
stopping_criteria = KeywordsStoppingCriteria(keywords, tokenizer, input_ids)
gen_kwargs = {}
if "max_new_tokens" not in gen_kwargs:
gen_kwargs["max_new_tokens"] = 1024
if "temperature" not in gen_kwargs:
gen_kwargs["temperature"] = 0.2
if "top_p" not in gen_kwargs:
gen_kwargs["top_p"] = None
if "num_beams" not in gen_kwargs:
gen_kwargs["num_beams"] = 1
with torch.inference_mode():
if modality == "video":
output_ids = model.generate(
inputs=input_ids,
images=video_data[0][0],
images_highres=video_data[0][1],
modalities=video_data[2],
speech=speechs,
speech_lengths=speech_lengths,
speech_chunks=speech_chunks,
speech_wav=speech_wavs,
attention_mask=attention_masks,
use_cache=True,
stopping_criteria=[stopping_criteria],
do_sample=True if gen_kwargs["temperature"] > 0 else False,
temperature=gen_kwargs["temperature"],
top_p=gen_kwargs["top_p"],
num_beams=gen_kwargs["num_beams"],
max_new_tokens=gen_kwargs["max_new_tokens"],
)
else:
output_ids = model.generate(
inputs=input_ids,
images=image_tensor,
images_highres=image_highres_tensor,
image_sizes=image_sizes,
modalities=['image'],
speech=speechs,
speech_lengths=speech_lengths,
speech_chunks=speech_chunks,
speech_wav=speech_wavs,
attention_mask=attention_masks,
use_cache=True,
stopping_criteria=[stopping_criteria],
do_sample=True if gen_kwargs["temperature"] > 0 else False,
temperature=gen_kwargs["temperature"],
top_p=gen_kwargs["top_p"],
num_beams=gen_kwargs["num_beams"],
max_new_tokens=gen_kwargs["max_new_tokens"],
)
outputs = tokenizer.batch_decode(output_ids, skip_special_tokens=True)[0]
outputs = outputs.strip()
if outputs.endswith(stop_str):
outputs = outputs[:-len(stop_str)]
outputs = outputs.strip()
return outputs, None
模型架构
-
架构: 预训练的Oryx-ViT + Qwen2.5-7B
-
数据: 混合超过500万张图像/视频/音频数据,分三个阶段训练
-
精度: BFloat16
硬件与软件
-
硬件: 64张NVIDIA Tesla A100
-
编排: HuggingFace Trainer
-
代码: Pytorch
引用
@article{liu2025ola, title={Ola: 通过渐进式模态对齐推动全模态语言模型前沿}, author={刘祖岩 and 董宇豪 and 王家辉 and 刘子威 and 胡文森 and 陆继文 and 饶永明}, journal={arXiv预印本 arXiv:2502.04328}, year={2025} }
Codebert Base
CodeBERT是一个面向编程语言与自然语言的预训练模型,基于RoBERTa架构,支持代码搜索和代码生成文档等功能。
多模态融合
C
microsoft
1.6M
248
Llama 4 Scout 17B 16E Instruct
其他
Llama 4 Scout是Meta开发的多模态AI模型,采用混合专家架构,支持12种语言的文本和图像交互,具有17B激活参数和109B总参数。
多模态融合
Transformers

支持多种语言
L
meta-llama
817.62k
844
Unixcoder Base
Apache-2.0
UniXcoder是一个统一的多模态预训练模型,利用代码注释和抽象语法树等多模态数据预训练代码表示。
多模态融合
Transformers

英语
U
microsoft
347.45k
51
TITAN
TITAN是一个多模态全切片基础模型,通过视觉自监督学习和视觉-语言对齐进行预训练,用于病理学图像分析。
多模态融合
Safetensors
英语
T
MahmoodLab
213.39k
37
Qwen2.5 Omni 7B
其他
Qwen2.5-Omni 是一个端到端的多模态模型,能够感知文本、图像、音频和视频等多种模态,并以流式方式生成文本和自然语音响应。
多模态融合
Transformers

英语
Q
Qwen
206.20k
1,522
Minicpm O 2 6
MiniCPM-o 2.6是一款手机端运行的GPT-4o级多模态大模型,支持视觉、语音与直播流处理
多模态融合
Transformers

其他
M
openbmb
178.38k
1,117
Llama 4 Scout 17B 16E Instruct
其他
Llama 4 Scout是Meta推出的17B参数/16专家混合的多模态AI模型,支持12种语言和图像理解,具有行业领先性能。
多模态融合
Transformers

支持多种语言
L
chutesai
173.52k
2
Qwen2.5 Omni 3B
其他
Qwen2.5-Omni是一款端到端多模态模型,能够感知文本、图像、音频和视频等多种模态信息,并以流式方式同步生成文本和自然语音响应。
多模态融合
Transformers

英语
Q
Qwen
48.07k
219
One Align
MIT
Q-Align是一个多任务视觉评估模型,专注于图像质量评估(IQA)、美学评估(IAA)和视频质量评估(VQA),在ICML2024上发表。
多模态融合
Transformers

O
q-future
39.48k
25
Biomedvlp BioViL T
MIT
BioViL-T是一个专注于分析胸部X光片和放射学报告的视觉语言模型,通过时序多模态预训练提升性能。
多模态融合
Transformers

英语
B
microsoft
26.39k
35
精选推荐AI模型
Llama 3 Typhoon V1.5x 8b Instruct
专为泰语设计的80亿参数指令模型,性能媲美GPT-3.5-turbo,优化了应用场景、检索增强生成、受限生成和推理任务
大型语言模型
Transformers

支持多种语言
L
scb10x
3,269
16
Cadet Tiny
Openrail
Cadet-Tiny是一个基于SODA数据集训练的超小型对话模型,专为边缘设备推理设计,体积仅为Cosmo-3B模型的2%左右。
对话系统
Transformers

英语
C
ToddGoldfarb
2,691
6
Roberta Base Chinese Extractive Qa
基于RoBERTa架构的中文抽取式问答模型,适用于从给定文本中提取答案的任务。
问答系统
中文
R
uer
2,694
98
AIbase是一个专注于MCP服务的平台,为AI开发者提供高质量的模型上下文协议服务,助力AI应用开发。
简体中文