Image-Text-to-Text
Transformers
Safetensors
mage_vl
multimodal
vision-language-model
mage-vl
video-understanding
streaming
conversational
custom_code
Instructions to use microsoft/Mage-VL with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use microsoft/Mage-VL with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("image-text-to-text", model="microsoft/Mage-VL", trust_remote_code=True) messages = [ { "role": "user", "content": [ {"type": "image", "url": "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/p-blog/candy.JPG"}, {"type": "text", "text": "What animal is on the candy?"} ] }, ] pipe(text=messages)# Load model directly from transformers import AutoModelForImageTextToText model = AutoModelForImageTextToText.from_pretrained("microsoft/Mage-VL", trust_remote_code=True, device_map="auto") - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- vLLM
How to use microsoft/Mage-VL with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "microsoft/Mage-VL" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "microsoft/Mage-VL", "messages": [ { "role": "user", "content": [ { "type": "text", "text": "Describe this image in one sentence." }, { "type": "image_url", "image_url": { "url": "https://cdn.britannica.com/61/93061-050-99147DCE/Statue-of-Liberty-Island-New-York-Bay.jpg" } } ] } ] }'Use Docker
docker model run hf.co/microsoft/Mage-VL
- SGLang
How to use microsoft/Mage-VL with SGLang:
Install from pip and serve model
# Install SGLang from pip: pip install sglang # Start the SGLang server: python3 -m sglang.launch_server \ --model-path "microsoft/Mage-VL" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "microsoft/Mage-VL", "messages": [ { "role": "user", "content": [ { "type": "text", "text": "Describe this image in one sentence." }, { "type": "image_url", "image_url": { "url": "https://cdn.britannica.com/61/93061-050-99147DCE/Statue-of-Liberty-Island-New-York-Bay.jpg" } } ] } ] }'Use Docker images
docker run --gpus all \ --shm-size 32g \ -p 30000:30000 \ -v ~/.cache/huggingface:/root/.cache/huggingface \ --env "HF_TOKEN=<secret>" \ --ipc=host \ lmsysorg/sglang:latest \ python3 -m sglang.launch_server \ --model-path "microsoft/Mage-VL" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "microsoft/Mage-VL", "messages": [ { "role": "user", "content": [ { "type": "text", "text": "Describe this image in one sentence." }, { "type": "image_url", "image_url": { "url": "https://cdn.britannica.com/61/93061-050-99147DCE/Statue-of-Liberty-Island-New-York-Bay.jpg" } } ] } ] }' - Docker Model Runner
How to use microsoft/Mage-VL with Docker Model Runner:
docker model run hf.co/microsoft/Mage-VL
| # Copyright (c) Microsoft Corporation. | |
| # Licensed under the MIT License. | |
| import torch | |
| import torch.nn.functional as F | |
| from torch import nn | |
| from .common_model import CompressionModel | |
| from ..layers.layers import SubpelConv2x, DepthConvBlock, \ | |
| ResidualBlockUpsample, ResidualBlockWithStride2 | |
| from ..layers.cuda_inference import CUSTOMIZED_CUDA_INFERENCE, round_and_to_int8, \ | |
| bias_pixel_shuffle_8, bias_quant | |
| qp_shift = [0, 8, 4] | |
| extra_qp = max(qp_shift) | |
| g_ch_src_d = 3 * 8 * 8 | |
| g_ch_recon = 320 | |
| g_ch_y = 128 | |
| g_ch_z = 128 | |
| g_ch_d = 256 | |
| class FeatureExtractor(nn.Module): | |
| def __init__(self): | |
| super().__init__() | |
| self.conv1 = nn.Sequential( | |
| DepthConvBlock(g_ch_d, g_ch_d), | |
| DepthConvBlock(g_ch_d, g_ch_d), | |
| ) | |
| self.conv2 = nn.Sequential( | |
| DepthConvBlock(g_ch_d, g_ch_d), | |
| DepthConvBlock(g_ch_d, g_ch_d), | |
| DepthConvBlock(g_ch_d, g_ch_d), | |
| DepthConvBlock(g_ch_d, g_ch_d), | |
| ) | |
| def forward(self, x, quant): | |
| x1, ctx_t = self.forward_part1(x, quant) | |
| ctx = self.forward_part2(x1) | |
| return ctx, ctx_t | |
| def forward_part1(self, x, quant): | |
| x1 = self.conv1(x) | |
| ctx_t = x1 * quant | |
| return x1, ctx_t | |
| def forward_part2(self, x1): | |
| ctx = self.conv2(x1) | |
| return ctx | |
| class Encoder(nn.Module): | |
| def __init__(self): | |
| super().__init__() | |
| self.conv1 = nn.Conv2d(g_ch_src_d, g_ch_d, 1) | |
| self.conv2 = nn.Sequential( | |
| DepthConvBlock(g_ch_d * 2, g_ch_d), | |
| DepthConvBlock(g_ch_d, g_ch_d), | |
| ) | |
| self.conv3 = DepthConvBlock(g_ch_d, g_ch_d) | |
| self.down = nn.Conv2d(g_ch_d, g_ch_y, 3, stride=2, padding=1) | |
| self.fuse_conv1_flag = False | |
| def forward(self, x, ctx, quant_step): | |
| feature = F.pixel_unshuffle(x, 8) | |
| if not CUSTOMIZED_CUDA_INFERENCE or not x.is_cuda: | |
| return self.forward_torch(feature, ctx, quant_step) | |
| return self.forward_cuda(feature, ctx, quant_step) | |
| def forward_torch(self, feature, ctx, quant_step): | |
| feature = self.conv1(feature) | |
| feature = self.conv2(torch.cat((feature, ctx), dim=1)) | |
| feature = self.conv3(feature) | |
| feature = feature * quant_step | |
| feature = self.down(feature) | |
| return feature | |
| def forward_cuda(self, feature, ctx, quant_step): | |
| if not self.fuse_conv1_flag: | |
| fuse_weight1 = torch.matmul( | |
| self.conv2[0].adaptor.weight[:, :g_ch_d, 0, 0], | |
| self.conv1.weight[:, :, 0, 0] | |
| )[:, :, None, None] | |
| fuse_weight2 = self.conv2[0].adaptor.weight[:, g_ch_d:] | |
| self.conv2[0].adaptor.bias.data = self.conv2[0].adaptor.bias + \ | |
| torch.matmul(self.conv2[0].adaptor.weight[:, :g_ch_d, 0, 0], | |
| self.conv1.bias[:, None])[:, 0] | |
| self.conv2[0].adaptor.weight.data = torch.cat([fuse_weight1, fuse_weight2], dim=1) | |
| self.fuse_conv1_flag = True | |
| feature = self.conv2(torch.cat((feature, ctx), dim=1)) | |
| feature = self.conv3(feature, quant_step=quant_step) | |
| feature = self.down(feature) | |
| return feature | |
| class Decoder(nn.Module): | |
| def __init__(self): | |
| super().__init__() | |
| self.up = SubpelConv2x(g_ch_y, g_ch_d, 3, padding=1) | |
| self.conv1 = nn.Sequential( | |
| DepthConvBlock(g_ch_d * 2, g_ch_d), | |
| DepthConvBlock(g_ch_d, g_ch_d), | |
| DepthConvBlock(g_ch_d, g_ch_d), | |
| ) | |
| self.conv2 = nn.Conv2d(g_ch_d, g_ch_d, 1) | |
| def forward(self, x, ctx, quant_step,): | |
| if not CUSTOMIZED_CUDA_INFERENCE or not x.is_cuda: | |
| return self.forward_torch(x, ctx, quant_step) | |
| return self.forward_cuda(x, ctx, quant_step) | |
| def forward_torch(self, x, ctx, quant_step): | |
| feature = self.up(x) | |
| feature = self.conv1(torch.cat((feature, ctx), dim=1)) | |
| feature = self.conv2(feature) | |
| feature = feature * quant_step | |
| return feature | |
| def forward_cuda(self, x, ctx, quant_step): | |
| feature = self.up(x, to_cat=ctx, cat_at_front=False) | |
| feature = self.conv1(feature) | |
| feature = F.conv2d(feature, self.conv2.weight) | |
| feature = bias_quant(feature, self.conv2.bias, quant_step) | |
| return feature | |
| class ReconGeneration(nn.Module): | |
| def __init__(self): | |
| super().__init__() | |
| self.conv = nn.Sequential( | |
| DepthConvBlock(g_ch_d, g_ch_recon), | |
| DepthConvBlock(g_ch_recon, g_ch_recon), | |
| DepthConvBlock(g_ch_recon, g_ch_recon), | |
| DepthConvBlock(g_ch_recon, g_ch_recon), | |
| ) | |
| self.head = nn.Conv2d(g_ch_recon, g_ch_src_d, 1) | |
| def forward(self, x, quant_step): | |
| if not CUSTOMIZED_CUDA_INFERENCE or not x.is_cuda: | |
| return self.forward_torch(x, quant_step) | |
| return self.forward_cuda(x, quant_step) | |
| def forward_torch(self, x, quant_step): | |
| out = self.conv(x) | |
| out = out * quant_step | |
| out = self.head(out) | |
| out = F.pixel_shuffle(out, 8) | |
| out = torch.clamp(out, 0., 1.) | |
| return out | |
| def forward_cuda(self, x, quant_step): | |
| out = self.conv[0](x) | |
| out = self.conv[1](out) | |
| out = self.conv[2](out) | |
| out = self.conv[3](out, quant_step=quant_step) | |
| out = F.conv2d(out, self.head.weight) | |
| return bias_pixel_shuffle_8(out, self.head.bias) | |
| class HyperEncoder(nn.Module): | |
| def __init__(self): | |
| super().__init__() | |
| self.conv = nn.Sequential( | |
| DepthConvBlock(g_ch_y, g_ch_z), | |
| ResidualBlockWithStride2(g_ch_z, g_ch_z), | |
| ResidualBlockWithStride2(g_ch_z, g_ch_z), | |
| ) | |
| def forward(self, x): | |
| return self.conv(x) | |
| class HyperDecoder(nn.Module): | |
| def __init__(self): | |
| super().__init__() | |
| self.conv = nn.Sequential( | |
| ResidualBlockUpsample(g_ch_z, g_ch_z), | |
| ResidualBlockUpsample(g_ch_z, g_ch_z), | |
| DepthConvBlock(g_ch_z, g_ch_y), | |
| ) | |
| def forward(self, x): | |
| return self.conv(x) | |
| class PriorFusion(nn.Module): | |
| def __init__(self): | |
| super().__init__() | |
| self.conv = nn.Sequential( | |
| DepthConvBlock(g_ch_y * 3, g_ch_y * 3), | |
| DepthConvBlock(g_ch_y * 3, g_ch_y * 3), | |
| DepthConvBlock(g_ch_y * 3, g_ch_y * 3), | |
| nn.Conv2d(g_ch_y * 3, g_ch_y * 3, 1), | |
| ) | |
| def forward(self, x): | |
| return self.conv(x) | |
| class SpatialPrior(nn.Module): | |
| def __init__(self): | |
| super().__init__() | |
| self.conv = nn.Sequential( | |
| DepthConvBlock(g_ch_y * 4, g_ch_y * 3), | |
| DepthConvBlock(g_ch_y * 3, g_ch_y * 3), | |
| nn.Conv2d(g_ch_y * 3, g_ch_y * 2, 1), | |
| ) | |
| def forward(self, x): | |
| return self.conv(x) | |
| class RefFrame(): | |
| def __init__(self): | |
| self.frame = None | |
| self.feature = None | |
| self.poc = None | |
| class DMC(CompressionModel): | |
| def __init__(self): | |
| super().__init__(z_channel=g_ch_z, extra_qp=extra_qp) | |
| self.qp_shift = qp_shift | |
| self.feature_adaptor_i = DepthConvBlock(g_ch_src_d, g_ch_d) | |
| self.feature_adaptor_p = nn.Conv2d(g_ch_d, g_ch_d, 1) | |
| self.feature_extractor = FeatureExtractor() | |
| self.encoder = Encoder() | |
| self.hyper_encoder = HyperEncoder() | |
| self.hyper_decoder = HyperDecoder() | |
| self.temporal_prior_encoder = ResidualBlockWithStride2(g_ch_d, g_ch_y * 2) | |
| self.y_prior_fusion = PriorFusion() | |
| self.y_spatial_prior = SpatialPrior() | |
| self.decoder = Decoder() | |
| self.recon_generation_net = ReconGeneration() | |
| self.q_encoder = nn.Parameter(torch.ones((self.get_qp_num() + extra_qp, g_ch_d, 1, 1))) | |
| self.q_decoder = nn.Parameter(torch.ones((self.get_qp_num() + extra_qp, g_ch_d, 1, 1))) | |
| self.q_feature = nn.Parameter(torch.ones((self.get_qp_num() + extra_qp, g_ch_d, 1, 1))) | |
| self.q_recon = nn.Parameter(torch.ones((self.get_qp_num() + extra_qp, g_ch_recon, 1, 1))) | |
| self.dpb = [] | |
| self.max_dpb_size = 1 | |
| self.curr_poc = 0 | |
| def reset_ref_feature(self): | |
| if len(self.dpb) > 0: | |
| self.dpb[0].feature = None | |
| def add_ref_frame(self, feature=None, frame=None, increase_poc=True): | |
| ref_frame = RefFrame() | |
| ref_frame.poc = self.curr_poc | |
| ref_frame.frame = frame | |
| ref_frame.feature = feature | |
| if len(self.dpb) >= self.max_dpb_size: | |
| self.dpb.pop(-1) | |
| self.dpb.insert(0, ref_frame) | |
| if increase_poc: | |
| self.curr_poc += 1 | |
| def clear_dpb(self): | |
| self.dpb.clear() | |
| def set_curr_poc(self, poc): | |
| self.curr_poc = poc | |
| def apply_feature_adaptor(self): | |
| if self.dpb[0].feature is None: | |
| return self.feature_adaptor_i(F.pixel_unshuffle(self.dpb[0].frame, 8)) | |
| return self.feature_adaptor_p(self.dpb[0].feature) | |
| def res_prior_param_decoder(self, z_hat, ctx_t): | |
| hierarchical_params = self.hyper_decoder(z_hat) | |
| temporal_params = self.temporal_prior_encoder(ctx_t) | |
| _, _, H, W = temporal_params.shape | |
| hierarchical_params = hierarchical_params[:, :, :H, :W].contiguous() | |
| params = self.y_prior_fusion( | |
| torch.cat((hierarchical_params, temporal_params), dim=1)) | |
| return params | |
| def get_recon_and_feature(self, y_hat, ctx, q_decoder, q_recon): | |
| feature = self.decoder(y_hat, ctx, q_decoder) | |
| x_hat = self.recon_generation_net(feature, q_recon) | |
| return x_hat, feature | |
| def prepare_feature_adaptor_i(self, last_qp): | |
| if self.dpb[0].frame is None: | |
| q_recon = self.q_recon[last_qp:last_qp+1, :, :, :] | |
| self.dpb[0].frame = self.recon_generation_net(self.dpb[0].feature, q_recon).clamp_(0, 1) | |
| self.reset_ref_feature() | |
| def compress(self, x, qp): | |
| # pic_width and pic_height may be different from x's size. x here is after padding | |
| # x_hat has the same size with x | |
| device = x.device | |
| q_encoder = self.q_encoder[qp:qp+1, :, :, :] | |
| q_decoder = self.q_decoder[qp:qp+1, :, :, :] | |
| q_feature = self.q_feature[qp:qp+1, :, :, :] | |
| feature = self.apply_feature_adaptor() | |
| ctx, ctx_t = self.feature_extractor(feature, q_feature) | |
| y = self.encoder(x, ctx, q_encoder) | |
| hyper_inp = self.pad_for_y(y) | |
| z = self.hyper_encoder(hyper_inp) | |
| z_hat, z_hat_write = round_and_to_int8(z) | |
| cuda_event_z_ready = torch.cuda.Event() | |
| cuda_event_z_ready.record() | |
| params = self.res_prior_param_decoder(z_hat, ctx_t) | |
| y_q_w_0, y_q_w_1, s_w_0, s_w_1, y_hat = \ | |
| self.compress_prior_2x(y, params, self.y_spatial_prior) | |
| cuda_event_y_ready = torch.cuda.Event() | |
| cuda_event_y_ready.record() | |
| feature = self.decoder(y_hat, ctx, q_decoder) | |
| cuda_stream = self.get_cuda_stream(device=device, priority=-1) | |
| with torch.cuda.stream(cuda_stream): | |
| self.entropy_coder.reset() | |
| cuda_event_z_ready.wait() | |
| self.bit_estimator_z.encode_z(z_hat_write, qp) | |
| cuda_event_y_ready.wait() | |
| self.gaussian_encoder.encode_y(y_q_w_0, s_w_0) | |
| self.gaussian_encoder.encode_y(y_q_w_1, s_w_1) | |
| self.entropy_coder.flush() | |
| bit_stream = self.entropy_coder.get_encoded_stream() | |
| torch.cuda.synchronize(device=device) | |
| self.add_ref_frame(feature, None) | |
| return { | |
| 'bit_stream': bit_stream, | |
| } | |
| def decompress(self, bit_stream, sps, qp): | |
| dtype = next(self.parameters()).dtype | |
| device = next(self.parameters()).device | |
| q_decoder = self.q_decoder[qp:qp+1, :, :, :] | |
| q_feature = self.q_feature[qp:qp+1, :, :, :] | |
| q_recon = self.q_recon[qp:qp+1, :, :, :] | |
| self.entropy_coder.set_use_two_entropy_coders(sps['ec_part'] == 1) | |
| self.entropy_coder.set_stream(bit_stream) | |
| z_size = self.get_downsampled_shape(sps['height'], sps['width'], 64) | |
| self.bit_estimator_z.decode_z(z_size, qp) | |
| feature = self.apply_feature_adaptor() | |
| c1, ctx_t = self.feature_extractor.forward_part1(feature, q_feature) | |
| z_hat = self.bit_estimator_z.get_z(z_size, device, dtype) | |
| params = self.res_prior_param_decoder(z_hat, ctx_t) | |
| infos = self.decompress_prior_2x_part1(params) | |
| ctx = self.feature_extractor.forward_part2(c1) | |
| cuda_stream = self.get_cuda_stream(device=device, priority=-1) | |
| with torch.cuda.stream(cuda_stream): | |
| y_hat = self.decompress_prior_2x_part2(params, self.y_spatial_prior, infos) | |
| cuda_event = torch.cuda.Event() | |
| cuda_event.record() | |
| cuda_event.wait() | |
| x_hat, feature = self.get_recon_and_feature(y_hat, ctx, q_decoder, q_recon) | |
| self.add_ref_frame(feature, x_hat) | |
| return { | |
| 'x_hat': x_hat, | |
| } | |
| def shift_qp(self, qp, fa_idx): | |
| return qp + self.qp_shift[fa_idx] | |