← Open Source
PKU-YuanGroup

Chat-UniVi

[CVPR 2024 Highlight🔥] Chat-UniVi: Unified Visual Representation Empowers Large Language Models with Image and Video Understanding.

ModelsVision modelsPython
Open on GitHub
Momentum
+0stars in 24 hours0.0%
943
Stars
48
Forks
+0
This week
2
Contributors
Created 2023-11-13 · Updated 2026-10-04 · #12483 today
Top developers

PKU-YuanGroup/Chat-UniVi is ranked 12,483 with 943 stars.

Same-category comparison

PKU-YuanGroup/Chat-UniVi is ranked 12,483 among these 8 peers; fuxiao0719/GeoWizard is ranked 12,486.

Same-category comparison
NameRankMetrics
VAST-AI-Research/MIDI-3D12,416
Language:
Python
Stars:
953
Forks:
75
Description:
[CVPR 2025] MIDI: Multi-Instance Diffusion for Single Image to 3D Scene Generation.
zai-org/CogView212,426
Language:
Python
Stars:
952
Forks:
85
Description:
official code repo for paper "CogView2: Faster and Better Text-to-Image Generation via Hierarchical Transformers".
Vchitect/LaVie12,436
Language:
Python
Stars:
950
Forks:
64
Description:
[IJCV 2024] LaVie: High-Quality Video Generation with Cascaded Latent Diffusion Models.
NVlabs/ODISE12,477
Language:
Python
Stars:
944
Forks:
60
Description:
Official PyTorch implementation of ODISE: Open-Vocabulary Panoptic Segmentation with Text-to-Image Diffusion Models [CVPR 2023 Highlight].
fuxiao0719/GeoWizard12,486
Language:
Python
Stars:
943
Forks:
42
Description:
[ECCV'24] GeoWizard: Unleashing the Diffusion Priors for 3D Geometry Estimation from a Single Image.
vivo-ai-lab/BlueLM12,490
Language:
Python
Stars:
943
Forks:
72
allenai/molmo12,507
Language:
Python
Stars:
939
Forks:
97
Description:
Code for the Molmo Vision-Language Model.
nghuyong/ERNIE-Pytorch12,563
Language:
Python
Stars:
931
Forks:
122
Description:
ERNIE Pytorch Version.
Key parameters and specifications
Key parameters and specifications
ParameterValue
LanguagePython
CategoryModels
SubcategoryVision models
Stars943
Forks48
Contributors2
Created date2023-11-13
Updated date2026-10-04
Stars in 1 day0
Stars in 7 days0
Rank12,483
Previous rank12,408
Rank change-75
7-day stars rank13,447
Previous 7-day stars rank13,458
7-day stars rank change11
Total stars rank11,664
Previous total stars rank11,646
Total stars rank change-18
CountryChina
README summary

Chat-UniVi: Unified Visual Representation Empowers Large Language Models with Image and Video Understanding If you like our project, please give us a star ⭐ on GitHub for the latest update. 💡 I also have other LLM projects that may interest you ✨. We sincerely apologize for any inconvenience our oversight may have caused you. **[2024/04/05]** **Chat-UniVi** has been selected as a **Highlight** paper at CVPR 2024! **[2024/02/27]** Our **Chat-UniVi** has been accepted by CVPR 2024! **[2024

/01/05]** We enhance the video loading code by introducing support for variable-length videos. This improvement involves eliminating the previous zero-filling operation on the video. We find that this updated video loading method significantly boosts performance (Results). **[2023/12/05]** The visualization script is available at VISUALIZATION. **[2023/11/22]** ⚡ The **online demo** is available at Hugging Face Demo. **[2023/11/22]** The processed data is available at DATA. **[2023/11/21]** 💡 We release Chat-UniVi-13B. Our

proposed unified visual representation framework greatly reduces the number of visual tokens, so you can train **13B unified image and video understanding models** in full parameters directly on **8 A100 GPUs** within **3 days**. Chat-UniVi-13B has better performance (Results). The training code for Chat-UniVi-13B has been updated (TRAIN_AND_VALIDATE. **[2023/11/21]** We provide inference code for video understanding and image understanding. **[2023/11/21]** We enhance the video loading code by introducing support for

variable-length videos. This improvement involves eliminating the previous zero-filling operation on the video. We find that this updated video loading method significantly boosts performance. **[2023/11/15]** Code are available now! Welcome to **watch** 👀 this repository for the latest updates. 😮 Highlights 💡 Unified visual representation for image and video We employ **a set of dynamic visual tokens** to uniformly represent images and videos. This representation framework empowers the model to efficiently utilize **a limited number of visual tokens** to

simultaneously capture **the spatial details necessary for images** and **the comprehensive temporal relationship required for videos**. 🔥 Joint training strategy, making LLMs understand both image and video Chat-UniVi is trained on a mixed dataset containing both images and videos, allowing direct application to tasks involving both mediums without requiring any modifications. 🤗 High performance, complementary learning with image and video Extensive experimental results demonstrate that Chat-UniVi, as a unified model, consistently outperforms even existing methods exclusively designed for either images

or videos. ⚡ Demo Please change the model path on line 15 of the main_demo. Then run the demo: A conversation with both image and video A conversation includes multiple videos A conversation includes multiple images A conversation includes the video A conversation in Chinese With translation API, our model can also support Chinese conversations. We will add code to support Chinese conversations in future updates. 🚀 Main Results Image understanding Following LLaVA, we report the relative scores to GPT-4

for instruction-following questions. Video understanding Following Video-ChatGPT, we report the relative scores between the output of the model

Frequently asked questions

How many stars and forks are recorded?

PKU-YuanGroup/Chat-UniVi has 943 stars and 48 forks.

What is the repository rank?

PKU-YuanGroup/Chat-UniVi is ranked 12,483.

What language and category are recorded?

PKU-YuanGroup/Chat-UniVi has 943 stars, uses Python and belongs to Models.

Which repository is closest in rank?

PKU-YuanGroup/Chat-UniVi is compared with fuxiao0719/GeoWizard, ranked 12,486 with 943 stars.

README

Chat-UniVi: Unified Visual Representation Empowers Large Language Models with Image and Video Understanding

If you like our project, please give us a star ⭐ on GitHub for the latest update.

💡 I also have other LLM projects that may interest you ✨.

MoH: Multi-Head Attention as Mixture-of-Head Attention

Peng Jin, Bo Zhu, Li Yuan, Shuicheng Yan

MoE++: Accelerating Mixture-of-Experts Methods with Zero-Computation Experts

Peng Jin, Bo Zhu, Li Yuan, Shuicheng Yan

-->

📣 News

  • [2024/04/05] We've revised the temporal evaluation performance of video understanding, resulting in an actual model performance of 47.9 instead of the previously stated 57.8. We sincerely apologize for any inconvenience our oversight may have caused you.
  • [2024/04/05] Chat-UniVi has been selected as a Highlight paper at CVPR 2024! (Top 3% of 11532 submissions).
  • [2024/02/27] Our Chat-UniVi has been accepted by CVPR 2024!
  • [2024/01/05] We enhance the video loading code by introducing support for variable-length videos. This improvement involves eliminating the previous zero-filling operation on the video. We find that this updated video loading method significantly boosts performance (Results).
  • [2023/12/05] The visualization script is available at VISUALIZATION.md.
  • [2023/11/22] ⚡ The online demo is available at Hugging Face Demo. Welcome to try!
  • [2023/11/22] The processed data is available at DATA.md.
  • [2023/11/21] 💡 We release Chat-UniVi-13B. Our proposed unified visual representation framework greatly reduces the number of visual tokens, so you can train 13B unified image and video understanding models in full parameters directly on 8 A100 GPUs within 3 days. Chat-UniVi-13B has better performance (Results). The training code for Chat-UniVi-13B has been updated (TRAIN_AND_VALIDATE.md).
  • [2023/11/21] We provide inference code for video understanding and image understanding.
  • [2023/11/21] We enhance the video loading code by introducing support for variable-length videos. This improvement involves eliminating the previous zero-filling operation on the video. We find that this updated video loading method significantly boosts performance.
  • [2023/11/15] Code are available now! Welcome to watch 👀 this repository for the latest updates.

😮 Highlights

💡 Unified visual representation for image and video

We employ a set of dynamic visual tokens to uniformly represent images and videos. This representation framework empowers the model to efficiently utilize a limited number of visual tokens to simultaneously capture the spatial details necessary for images and the comprehensive temporal relationship required for videos.

🔥 Joint training strategy, making LLMs understand both image and video

Chat-UniVi is trained on a mixed dataset containing both images and videos, allowing direct application to tasks involving both mediums without requiring any modifications.

🤗 High performance, complementary learning with image and video

Extensive experimental results demonstrate that Chat-UniVi, as a unified model, consistently outperforms even existing methods exclusively designed for either images or videos.

⚡ Demo

Please change the model path on line 15 of the main_demo.py first. Then run the demo:

# For Chat-UniVi-7B
CUDA_VISIBLE_DEVICES=0 uvicorn main_demo_7B:app --host 0.0.0.0 --port 8888

# For Chat-UniVi-13B
CUDA_VISIBLE_DEVICES=0 uvicorn main_demo_13B:app --host 0.0.0.0 --port 8888

A conversation with both image and video

A conversation includes multiple videos

A conversation includes multiple images

A conversation includes the video

A conversation in Chinese

With translation API, our model can also support Chinese conversations. We will add code to support Chinese conversations in future updates.

🚀 Main Results

Image understanding

Following LLaVA, we report the relative scores to GPT-4 for instruction-following questions.

Methods

LLM

Conversation

Detail Description

Complex Reasoning

All

Chat-UniVi-7B

Vicuna-7B

84.1

74.2

93.7

84.2

Chat-UniVi-13B

Vicuna-13B

84.1

79.4

94.7

86.1

Video understanding

Following Video-ChatGPT, we report the relative scores between the output of the model and the ground truth, with the assistance of GPT. It is worth noting that the results reported in Video-ChatGPT span a range from 0 to 5. To standardize the metrics, we normalize all scores to a scale of 0 to 100.

Methods

LLM

Correct

Detail

Context

Temporal

Consistency

Chat-UniVi-7B

Vicuna-7B

57.8

58.2

69.2

47.9

56.2

Chat-UniVi-13B

Vicuna-13B

59.4

59.8

70.5

60.6

ScienceQA

We report both zero-shot and fine-tuning results on the ScienceQA test set.

Methods

LLM

Average

Subject

Context Modality

Grade

NAT

SOC

LAN

TXT

IMG

NO

G1-6

G7-12

Chat-UniVi-7B

Vicuna-7B

88.78

88.50

93.03

85.91

88.51

85.97

88.15

88.88

88.60

Chat-UniVi-13B

Vicuna-13B

90.99

90.41

95.05

88.91

89.64

88.05

90.94

91.19

90.64

VideoQA

We follow the evaluation protocol in Video-ChatGPT, i.e., employing GPT-assisted evaluation to assess the capabilities of models.

Methods

LLM Size

MSRVTT-QA

MSVD-QA

TGIF-QA

ActivityNet-QA

Accuracy

Score

Accuracy

Score

Accuracy

Score

Accuracy

Score

Video-LLaMA

7B

29.6

1.8

51.6

2.5

12.4

1.1

LLaMA-Adapter

7B

43.8

2.7

54.9

3.1

34.2

2.7

VideoChat

7B

45.0

2.5

56.3

2.8

34.4

2.3

26.5

2.2

Video-ChatGPT

7B

49.3

2.8

64.9

3.3

51.4

3.0

35.2

2.7

Video-LLaVA

7B

59.2

3.5

70.7

3.9

70.0

4.0

45.3

3.3

Chat-UniVi-7B

7B

54.6

3.1

65.0

3.6

60.3

3.4

45.8

3.2

Chat-UniVi-7B with new video loading code

7B

55.0

3.1

69.3

3.7

69.0

3.8

46.1

3.3

Chat-UniVi-7B v1.5

7B

57.5

3.2

68.8

3.7

70.0

3.8

47.2

3.3

Hallucination Evaluation (POPE)

Our model also achieves impressive results in the object hallucination benchmark.

Methods

LLM Size

Random

Popular

Adversarial

Accuracy

F1-Score

Yes

Accuracy

F1-Score

Yes

Accuracy

F1-Score

Yes

LLaVA

7B

72.16

78.22

76.29

61.37

71.52

85.63

58.67

70.12

88.33

Video-LLaVA

7B

86.2

85.2

42.0

85.3

84.0

42.1

81.6

80.8

45.8

Chat-UniVi-7B

7B

85.19

86.05

54.67

69.50

74.39

69.10

64.97

71.54

73.10

Chat-UniVi-7B v1.5

7B

87.01

86.09

41.86

85.87

84.76

42.73

83.23

82.31

44.77

😍 Visualization

Visualization for the image inputs

Visualization for the video inputs

🛠️ Requirements and Installation

Attention! If you are using a Windows system, please make sure to comment out deepspeed in pyproject.toml (#Line 20), as installing deepspeed may result in errors on Windows (see Link). Keep in mind that deepspeed is intended for training models only. If you are solely engaged in inference and not training models, it is recommended to comment it out.

  • Python >= 3.10
  • Install required packages:
git clone https://github.com/PKU-YuanGroup/Chat-UniVi
cd Chat-UniVi
conda create -n chatunivi python=3.10 -y
conda activate chatunivi
pip install --upgrade pip
pip install -e .
# pip install ninja  # If you only intend to perform inference, there's no need to install ```ninja```.
# pip install flash-attn --no-build-isolation  # If you only intend to perform inference, there's no need to install ```flash-attn```.

🤖 API

We open source all modalities preprocessing code. If you want to load the model from the model hub on Hugging Face or on local, you can use the following code snippets.

Inference for Video Understanding

import torch
import os
from ChatUniVi.constants import *
from ChatUniVi.conversation import conv_templates, SeparatorStyle
from ChatUniVi.model.builder import load_pretrained_model
from ChatUniVi.utils import disable_torch_init
from ChatUniVi.mm_utils import tokenizer_image_token, get_model_name_from_path, KeywordsStoppingCriteria
from PIL import Image
from decord import VideoReader, cpu
import numpy as np


def _get_rawvideo_dec(video_path, image_processor, max_frames=MAX_IMAGE_LENGTH, image_resolution=224, video_framerate=1, s=None, e=None):
    # speed up video decode via decord.

    if s is None:
        start_time, end_time = None, None
    else:
        start_time = int(s)
        end_time = int(e)
        start_time = start_time if start_time >= 0. else 0.
        end_time = end_time if end_time >= 0. else 0.
        if start_time > end_time:
            start_time, end_time = end_time, start_time
        elif start_time == end_time:
            end_time = start_time + 1

    if os.path.exists(video_path):
        vreader = VideoReader(video_path, ctx=cpu(0))
    else:
        print(video_path)
        raise FileNotFoundError

    fps = vreader.get_avg_fps()
    f_start = 0 if start_time is None else int(start_time * fps)
    f_end = int(min(1000000000 if end_time is None else end_time * fps, len(vreader) - 1))
    num_frames = f_end - f_start + 1
    if num_frames > 0:
        # T x 3 x H x W
        sample_fps = int(video_framerate)
        t_stride = int(round(float(fps) / sample_fps))

        all_pos = list(range(f_start, f_end + 1, t_stride))
        if len(all_pos) > max_frames:
            sample_pos = [all_pos[_] for _ in np.linspace(0, len(all_pos) - 1, num=max_frames, dtype=int)]
        else:
            sample_pos = all_pos

        patch_images = [Image.fromarray(f) for f in vreader.get_batch(sample_pos).asnumpy()]

        patch_images = torch.stack([image_processor.preprocess(img, return_tensors='pt')['pixel_values'][0] for img in patch_images])
        slice_len = patch_images.shape[0]

        return patch_images, slice_len
    else:
        print("video path: {} error.".format(video_path))


if __name__ == '__main__':
    # Model Parameter
    model_path = "Chat-UniVi/Chat-UniVi"  # or "Chat-UniVi/Chat-UniVi-13B"、"Chat-UniVi/Chat-UniVi-v1.5"
    video_path = ${video_path}

    # The number of visual tokens varies with the length of the video. "max_frames" is the maximum number of frames.
    # When the video is long, we will uniformly downsample the video to meet the frames when equal to the "max_frames".
    max_frames = 100

    # The number of frames retained per second in the video.
    video_framerate = 1

    # Input Text
    qs = "Describe the video."

    # Sampling Parameter
    conv_mode = "simple"
    temperature = 0.2
    top_p = None
    num_beams = 1

    disable_torch_init()
    model_path = os.path.expanduser(model_path)
    model_name = "ChatUniVi"
    tokenizer, model, image_processor, context_len = load_pretrained_model(model_path, None, model_name)

    mm_use_im_start_end = getattr(model.config, "mm_use_im_start_end", False)
    mm_use_im_patch_token = getattr(model.config, "mm_use_im_patch_token", True)
    if mm_use_im_patch_token:
        tokenizer.add_tokens([DEFAULT_IMAGE_PATCH_TOKEN], special_tokens=True)
    if mm_use_im_start_end:
        tokenizer.add_tokens([DEFAULT_IM_START_TOKEN, DEFAULT_IM_END_TOKEN], special_tokens=True)
    model.resize_token_embeddings(len(tokenizer))

    vision_tower = model.get_vision_tower()
    if not vision_tower.is_loaded:
        vision_tower.load_model()
    image_processor = vision_tower.image_processor

    if model.config.config["use_cluster"]:
        for n, m in model.named_modules():
            m = m.to(dtype=torch.bfloat16)

    # Check if the video exists
    if video_path is not None:
        video_frames, slice_len = _get_rawvideo_dec(video_path, image_processor, max_frames=max_frames, video_framerate=video_framerate)

        cur_prompt = qs
        if model.config.mm_use_im_start_end:
            qs = DEFAULT_IM_START_TOKEN + DEFAULT_IMAGE_TOKEN * slice_len + DEFAULT_IM_END_TOKEN + '\n' + qs
        else:
            qs = DEFAULT_IMAGE_TOKEN * slice_len + '\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()

        input_ids = tokenizer_image_token(prompt, tokenizer, IMAGE_TOKEN_INDEX, return_tensors='pt').unsqueeze(
            0).cuda()

        stop_str = conv.sep if conv.sep_style != SeparatorStyle.TWO else conv.sep2
        keywords = [stop_str]
        stopping_criteria = KeywordsStoppingCriteria(keywords, tokenizer, input_ids)

        with torch.inference_mode():
            output_ids = model.generate(
                input_ids,
                images=video_frames.half().cuda(),
                do_sample=True,
                temperature=temperature,
                top_p=top_p,
                num_beams=num_beams,
                output_scores=True,
                return_dict_in_generate=True,
                max_new_tokens=1024,
                use_cache=True,
                stopping_criteria=[stopping_criteria])

        output_ids = output_ids.sequences
        input_token_len = input_ids.shape[1]
        n_diff_input_output = (input_ids != output_ids[:, :input_token_len]).sum().item()
        if n_diff_input_output > 0:
            print(f'[Warning] {n_diff_input_output} output_ids are not the same as the input_ids')
        outputs = tokenizer.batch_decode(output_ids[:, input_token_len:], skip_special_tokens=True)[0]
        outputs = outputs.strip()
        if outputs.endswith(stop_str):
            outputs = outputs[:-len(stop_str)]
        outputs = outputs.strip()
        print(outputs)

Inference for Image Understanding

import torch
import os
from ChatUniVi.constants import *
from ChatUniVi.conversation import conv_templates, SeparatorStyle
from ChatUniVi.model.builder import load_pretrained_model
from ChatUniVi.utils import disable_torch_init
from ChatUniVi.mm_utils import tokenizer_image_token, get_model_name_from_path, KeywordsStoppingCriteria
from PIL import Image


if __name__ == '__main__':
    # Model Parameter
    model_path = "Chat-UniVi/Chat-UniVi"  # or "Chat-UniVi/Chat-UniVi-13B"、"Chat-UniVi/Chat-UniVi-v1.5"
    image_path = ${image_path}

    # Input Text
    qs = "Describe the image."

    # Sampling Parameter
    conv_mode = "simple"
    temperature = 0.2
    top_p = None
    num_beams = 1

    disable_torch_init()
    model_path = os.path.expanduser(model_path)
    model_name = "ChatUniVi"
    tokenizer, model, image_processor, context_len = load_pretrained_model(model_path, None, model_name)

    mm_use_im_start_end = getattr(model.config, "mm_use_im_start_end", False)
    mm_use_im_patch_token = getattr(model.config, "mm_use_im_patch_token", True)
    if mm_use_im_patch_token:
        tokenizer.add_tokens([DEFAULT_IMAGE_PATCH_TOKEN], special_tokens=True)
    if mm_use_im_start_end:
        tokenizer.add_tokens([DEFAULT_IM_START_TOKEN, DEFAULT_IM_END_TOKEN], special_tokens=True)
    model.resize_token_embeddings(len(tokenizer))

    vision_tower = model.get_vision_tower()
    if not vision_tower.is_loaded:
        vision_tower.load_model()
    image_processor = vision_tower.image_processor

    # Check if the video exists
    if image_path is not None:
        cur_prompt = qs
        if model.config.mm_use_im_start_end:
            qs = DEFAULT_IM_START_TOKEN + DEFAULT_IMAGE_TOKEN + DEFAULT_IM_END_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()

        input_ids = tokenizer_image_token(prompt, tokenizer, IMAGE_TOKEN_INDEX, return_tensors='pt').unsqueeze(0).cuda()

        image = Image.open(image_path)
        image_tensor = image_processor.preprocess(image, return_tensors='pt')['pixel_values'][0]

        stop_str = conv.sep if conv.sep_style != SeparatorStyle.TWO else conv.sep2
        keywords = [stop_str]
        stopping_criteria = KeywordsStoppingCriteria(keywords, tokenizer, input_ids)

        with torch.inference_mode():
            output_ids = model.generate(
                input_ids,
                images=image_tensor.unsqueeze(0).half().cuda(),
                do_sample=True,
                temperature=temperature,
                top_p=top_p,
                num_beams=num_beams,
                max_new_tokens=1024,
                use_cache=True,
                stopping_criteria=[stopping_criteria])

        input_token_len = input_ids.shape[1]
        n_diff_input_output = (input_ids != output_ids[:, :input_token_len]).sum().item()
        if n_diff_input_output > 0:
            print(f'[Warning] {n_diff_input_output} output_ids are not the same as the input_ids')
        outputs = tokenizer.batch_decode(output_ids[:, input_token_len:], skip_special_tokens=True)[0]
        outputs = outputs.strip()
        if outputs.endswith(stop_str):
            outputs = outputs[:-len(stop_str)]
        outputs = outputs.strip()
        print(outputs)

🗝️ Training & Validating

👍 Acknowledgement

  • LLaVA The codebase we built upon and it is an efficient large language and vision assistant.
  • Video-ChatGPT Great job contributing the evaluation code and dataset.

🤝 Related Projects

  • Video-LLaVA This framework exhibits remarkable interactive capabilities between images and videos.

🔒 License

  • The majority of this project is released under the Apache 2.0 license as found in the LICENSE file.
  • The service is a research preview intended for non-commercial use only, subject to the model License of LLaMA, Terms of Use of the data generated by OpenAI, and Privacy Practices of ShareGPT. Please contact us if you find any potential violations.

✏️ Citation

If you find this paper useful, please consider staring 🌟 this repo and citing 📑 our paper:

@article{jin2023chatunivi,
  title={Chat-UniVi: Unified Visual Representation Empowers Large Language Models with Image and Video Understanding}, 
  author={Peng Jin and Ryuichi Takanobu and Caiwan Zhang and Xiaochun Cao and Li Yuan},
  journal={arXiv preprint arXiv:2311.08046},
  year={2023}
}

✨ Contributors

Nearby in the ranking
Similar items