Views
No views yet
| Model Name | Base MLLM | Language Part | HF Link |
|---|---|---|---|
| Sa2VA-1B | InternVL2.5-1B | Qwen2.5-0.5B-Instruct | 🤗 link |
| Sa2VA-4B | InternVL2.5-4B | Qwen2.5-3B-Instruct | 🤗 link |
| Sa2VA-8B | InternVL2.5-8B | internlm2_5-7b-chat | 🤗 link |
| Sa2VA-26B | InternVL2.5-26B | internlm2_5-20b-chat | 🤗 link |
| Model Name | MME | MMBench | RefCOCO | RefCOCO+ | RefCOCOg | MeVIS (val_u) | DAVIS |
|---|---|---|---|---|---|---|---|
| Sa2VA-1B | 1504/434 | 71.9 | 79.6 | 73.6 | 77.7 | 53.4 | 69.5 |
| Sa2VA-4B | 1691/610 | 81.8 | 82.4 | 77.6 | 79.7 | 55.9 | 73.7 |
| Sa2VA-8B | 1690/610 | 84.4 | 82.6 | 78.0 | 80.3 | 58.9 | 75.9 |
| Sa2VA-26B | 1698/653 | 85.8 | 82.9 | 79.3 | 81.2 | 61.8 | 78.6 |
Sa2VA using transformers.1import torch
2from transformers import AutoTokenizer, AutoModel
3from PIL import Image
4import numpy as np
5import os
6
7def get_rank_and_world_size():
8 rank = int(os.environ.get('RANK', 0))
9 world_size = int(os.environ.get('WORLD_SIZE', 1))
10 return rank, world_size
11
12def split_model(model_name):
13 import math
14 device_map = {}
15 num_gpus = torch.cuda.device_count()
16 rank, world_size = get_rank_and_world_size()
17 num_gpus = num_gpus // world_size
18
19 num_layers = {'Sa2VA-8B': 32, 'Sa2VA-26B': 48,
20 'Sa2VA-38B': 64, 'Sa2VA-78B': 80}[model_name]
21 # Since the first GPU will be used for ViT, treat it as 0.8 GPU.
22 num_layers_per_gpu = math.ceil(num_layers / (num_gpus - 0.2))
23 num_layers_per_gpu = [num_layers_per_gpu] * num_gpus
24 num_layers_per_gpu[0] = math.ceil(num_layers_per_gpu[0] * 0.8)
25 layer_cnt = 0
26 for i, num_layer in enumerate(num_layers_per_gpu):
27 for j in range(num_layer):
28 device_map[f'language_model.model.layers.{layer_cnt}'] = rank + world_size * i
29 layer_cnt += 1
30 device_map['vision_model'] = rank
31 device_map['mlp1'] = rank
32 device_map['language_model.model.tok_embeddings'] = rank
33 device_map['language_model.model.embed_tokens'] = rank
34 device_map['language_model.output'] = rank
35 device_map['language_model.model.norm'] = rank
36 device_map['language_model.lm_head'] = rank
37 device_map[f'language_model.model.layers.{num_layers - 1}'] = rank
38 device_map['grounding_encoder'] = rank
39 device_map['text_hidden_fcs'] = rank
40 return device_map
41
42# load the model and tokenizer
43path = "ByteDance/Sa2VA-26B"
44device_map = split_model("Sa2VA-26B")
45model = AutoModel.from_pretrained(
46 path,
47 torch_dtype=torch.bfloat16,
48 low_cpu_mem_usage=True,
49 use_flash_attn=True,
50 trust_remote_code=True,
51 device_map=device_map,
52).eval()
53tokenizer = AutoTokenizer.from_pretrained(path, trust_remote_code=True, use_fast=False)
54
55# for image chat
56image_path = "/PATH/TO/IMAGE"
57text_prompts = "<image>Please describe the image."
58image = Image.open(image_path).convert('RGB')
59input_dict = {
60 'image': image,
61 'text': text_prompts,
62 'past_text': '',
63 'mask_prompts': None,
64 'tokenizer': tokenizer,
65 }
66return_dict = model.predict_forward(**input_dict)
67answer = return_dict["prediction"] # the text format answer
68
69# for image chat with segmentation output
70image_path = "/PATH/TO/IMAGE"
71text_prompts = "<image>Could you please give me a brief description of the image? Please respond with interleaved segmentation masks for the corresponding parts of the answer."
72image = Image.open(image_path).convert('RGB')
73input_dict = {
74 'image': image,
75 'text': text_prompts,
76 'past_text': '',
77 'mask_prompts': None,
78 'tokenizer': tokenizer,
79 }
80return_dict = model.predict_forward(**input_dict)
81answer = return_dict["prediction"] # the text format answer
82masks = return_dict['prediction_masks'] # segmentation masks, list(np.array(1, h, w), ...)
83
84# for chat with visual prompt (mask format) input
85mask_prompts = np.load('/PATH/TO/pred_masks.npy') # np.array(n_prompts, h, w)
86image_path = "/PATH/TO/IMAGE"
87text_prompts = "<image>Can you provide me with a detailed description of the region in the picture marked by region1."
88image = Image.open(image_path).convert('RGB')
89input_dict = {
90 'image': image,
91 'text': text_prompts,
92 'past_text': '',
93 'mask_prompts': mask_prompts,
94 'tokenizer': tokenizer,
95 }
96return_dict = model.predict_forward(**input_dict)
97answer = return_dict["prediction"] # the text format answer
98
99# for video chat
100video_folder = "/PATH/TO/VIDEO_FOLDER"
101images_paths = os.listdir(video_folder)
102images_paths = [os.path.join(video_folder, image_path) for image_name in images_paths]
103if len(images_paths) > 5: # uniformly sample 5 frames
104 step = (len(images_paths) - 1) // (5 - 1)
105 images_paths = [images_paths[0]] + images_paths[1:-1][::step][1:] + [images_paths[-1]]
106text_prompts = "<image>Please describe the video."
107input_dict = {
108 'video': images_paths,
109 'text': text_prompts,
110 'past_text': '',
111 'mask_prompts': None,
112 'tokenizer': tokenizer,
113}
114return_dict = model.predict_forward(**input_dict)
115answer = return_dict["prediction"] # the text format answer
116
117
118# for video chat with segmentation mask output
119video_folder = "/PATH/TO/VIDEO_FOLDER"
120images_paths = os.listdir(video_folder)
121images_paths = [os.path.join(video_folder, image_path) for image_name in images_paths]
122text_prompts = "<image>Please segment the person."
123input_dict = {
124 'video': images_paths,
125 'text': text_prompts,
126 'past_text': '',
127 'mask_prompts': None,
128 'tokenizer': tokenizer,
129}
130return_dict = model.predict_forward(**input_dict)
131answer = return_dict["prediction"] # the text format answer
132masks = return_dict['prediction_masks'] # segmentation masks, list(np.array(n_frames, h, w), ...)1@article{sa2va,
2 title={Sa2VA: Marrying SAM2 with LLaVA for Dense Grounded Understanding of Images and Videos},
3 author={Yuan, Haobo and Li, Xiangtai and Zhang, Tao and Huang, Zilong Huang and Xu, Shilin and Ji, Shunping and Tong, Yunhai and Qi, Lu and Feng, Jiashi and Yang, Ming-Hsuan},
4 journal={arXiv preprint},
5 year={2025}
6}