Image-Text-to-Text
Transformers
Safetensors
mage_vl
multimodal
vision-language-model
mage-vl
video-understanding
streaming
conversational
custom_code
Instructions to use Mage-Fans/Mage-VL with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use Mage-Fans/Mage-VL with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("image-text-to-text", model="Mage-Fans/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("Mage-Fans/Mage-VL", trust_remote_code=True, device_map="auto") - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- vLLM
How to use Mage-Fans/Mage-VL with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "Mage-Fans/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": "Mage-Fans/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/Mage-Fans/Mage-VL
- SGLang
How to use Mage-Fans/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 "Mage-Fans/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": "Mage-Fans/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 "Mage-Fans/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": "Mage-Fans/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 Mage-Fans/Mage-VL with Docker Model Runner:
docker model run hf.co/Mage-Fans/Mage-VL
| import math | |
| import torch | |
| import numpy as np | |
| from torch import nn | |
| import torch.nn.functional as F | |
| from ..layers.cuda_inference import build_index_dec, build_index_enc, process_with_mask | |
| class EntropyCoder(): | |
| def __init__(self): | |
| super().__init__() | |
| from MLCodec_extensions_cpp import RansEncoder, RansDecoder | |
| self.encoder = RansEncoder() | |
| self.decoder = RansDecoder() | |
| def pmf_to_quantized_cdf(pmf, precision=16): | |
| from MLCodec_extensions_cpp import pmf_to_quantized_cdf as _pmf_to_cdf | |
| cdf = _pmf_to_cdf(pmf.tolist(), precision) | |
| cdf = torch.IntTensor(cdf) | |
| return cdf | |
| def pmf_to_cdf(pmf, tail_mass, pmf_length, max_length): | |
| entropy_coder_precision = 16 | |
| cdf = torch.zeros((len(pmf_length), max_length + 2), dtype=torch.int32) | |
| for i, p in enumerate(pmf): | |
| prob = torch.cat((p[: pmf_length[i]], tail_mass[i]), dim=0) | |
| _cdf = EntropyCoder.pmf_to_quantized_cdf(prob, entropy_coder_precision) | |
| cdf[i, : _cdf.size(0)] = _cdf | |
| return cdf | |
| def reset(self): | |
| self.encoder.reset() | |
| def add_cdf(self, cdf, cdf_length, offset): | |
| enc_cdf_idx = self.encoder.add_cdf(cdf, cdf_length, offset) | |
| dec_cdf_idx = self.decoder.add_cdf(cdf, cdf_length, offset) | |
| assert enc_cdf_idx == dec_cdf_idx | |
| return enc_cdf_idx | |
| def encode_y(self, symbols, cdf_group_index): | |
| # symbols: int16, high 8 bits: int8 symbol to be encoded; low 8 bits: uint8 index to use | |
| assert symbols.dtype == torch.int16 | |
| self.encoder.encode_y(symbols.cpu().numpy(), cdf_group_index) | |
| def encode_z(self, symbols, cdf_group_index, start_offset, per_channel_size): | |
| self.encoder.encode_z(symbols.to(torch.int8).cpu().numpy(), | |
| cdf_group_index, start_offset, per_channel_size) | |
| def flush(self): | |
| self.encoder.flush() | |
| def get_encoded_stream(self): | |
| return self.encoder.get_encoded_stream().tobytes() | |
| def set_stream(self, stream): | |
| self.decoder.set_stream((np.frombuffer(stream, dtype=np.uint8))) | |
| def decode_y(self, indexes, cdf_group_index): | |
| self.decoder.decode_y(indexes.to(torch.uint8).cpu().numpy(), cdf_group_index) | |
| def decode_and_get_y(self, indexes, cdf_group_index, device, dtype): | |
| rv = self.decoder.decode_and_get_y(indexes.to(torch.uint8).cpu().numpy(), cdf_group_index) | |
| rv = torch.as_tensor(rv) | |
| return rv.to(device).to(dtype) | |
| def decode_z(self, total_size, cdf_group_index, start_offset, per_channel_size): | |
| self.decoder.decode_z(total_size, cdf_group_index, start_offset, per_channel_size) | |
| def get_decoded_tensor(self, device, dtype, non_blocking=False): | |
| rv = self.decoder.get_decoded_tensor() | |
| rv = torch.as_tensor(rv) | |
| return rv.to(device, non_blocking=non_blocking).to(dtype) | |
| def set_use_two_entropy_coders(self, use_two_entropy_coders): | |
| self.encoder.set_use_two_encoders(use_two_entropy_coders) | |
| self.decoder.set_use_two_decoders(use_two_entropy_coders) | |
| class Bitparm(nn.Module): | |
| def __init__(self, qp_num, channel, final=False): | |
| super().__init__() | |
| self.final = final | |
| self.h = nn.Parameter(torch.nn.init.normal_( | |
| torch.empty([qp_num, channel, 1, 1]), 0, 0.01)) | |
| self.b = nn.Parameter(torch.nn.init.normal_( | |
| torch.empty([qp_num, channel, 1, 1]), 0, 0.01)) | |
| if not final: | |
| self.a = nn.Parameter(torch.nn.init.normal_( | |
| torch.empty([qp_num, channel, 1, 1]), 0, 0.01)) | |
| else: | |
| self.a = None | |
| def forward(self, x, index): | |
| h = torch.index_select(self.h, 0, index) | |
| b = torch.index_select(self.b, 0, index) | |
| x = x * F.softplus(h) + b | |
| if self.final: | |
| return x | |
| a = torch.index_select(self.a, 0, index) | |
| return x + torch.tanh(x) * torch.tanh(a) | |
| class AEHelper(): | |
| def __init__(self): | |
| super().__init__() | |
| self.entropy_coder = None | |
| self.cdf_group_index = None | |
| self._offset = None | |
| self._quantized_cdf = None | |
| self._cdf_length = None | |
| def set_cdf_info(self, quantized_cdf, cdf_length, offset): | |
| self._quantized_cdf = quantized_cdf.cpu().numpy() | |
| self._cdf_length = cdf_length.reshape(-1).int().cpu().numpy() | |
| self._offset = offset.reshape(-1).int().cpu().numpy() | |
| def get_cdf_info(self): | |
| return self._quantized_cdf, \ | |
| self._cdf_length, \ | |
| self._offset | |
| class BitEstimator(AEHelper, nn.Module): | |
| def __init__(self, qp_num, channel): | |
| super().__init__() | |
| self.f1 = Bitparm(qp_num, channel) | |
| self.f2 = Bitparm(qp_num, channel) | |
| self.f3 = Bitparm(qp_num, channel) | |
| self.f4 = Bitparm(qp_num, channel, True) | |
| self.qp_num = qp_num | |
| self.channel = channel | |
| def forward(self, x, index): | |
| return self.get_cdf(x, index) | |
| def get_logits_cdf(self, x, index): | |
| x = self.f1(x, index) | |
| x = self.f2(x, index) | |
| x = self.f3(x, index) | |
| x = self.f4(x, index) | |
| return x | |
| def get_cdf(self, x, index): | |
| return torch.sigmoid(self.get_logits_cdf(x, index)) | |
| def update(self, entropy_coder): | |
| self.entropy_coder = entropy_coder | |
| with torch.no_grad(): | |
| device = next(self.parameters()).device | |
| medians = torch.zeros((self.qp_num, self.channel, 1, 1), device=device) | |
| index = torch.arange(self.qp_num, device=device, dtype=torch.int32) | |
| minima = medians + 8 | |
| for i in range(8, 1, -1): | |
| samples = torch.zeros_like(medians) - i | |
| probs = self.forward(samples, index) | |
| minima = torch.where(probs < torch.zeros_like(medians) + 0.0001, | |
| torch.zeros_like(medians) + i, minima) | |
| maxima = medians + 8 | |
| for i in range(8, 1, -1): | |
| samples = torch.zeros_like(medians) + i | |
| probs = self.forward(samples, index) | |
| maxima = torch.where(probs > torch.zeros_like(medians) + 0.9999, | |
| torch.zeros_like(medians) + i, maxima) | |
| minima = minima.int() | |
| maxima = maxima.int() | |
| offset = -minima | |
| pmf_start = medians - minima | |
| pmf_length = maxima + minima + 1 | |
| max_length = pmf_length.max() | |
| device = pmf_start.device | |
| samples = torch.arange(max_length, device=device) | |
| samples = samples[None, None, None, :] + pmf_start | |
| half = float(0.5) | |
| lower = self.forward(samples - half, index) | |
| upper = self.forward(samples + half, index) | |
| pmf = upper - lower | |
| pmf = pmf[:, :, 0, :] | |
| upper = self.forward(maxima.to(torch.float32), index) | |
| tail_mass = lower[:, :, 0, :1] + (1.0 - upper[:, :, 0, -1:]) | |
| pmf = pmf.reshape([-1, max_length]) | |
| tail_mass = tail_mass.reshape([-1, 1]) | |
| pmf_length = pmf_length.reshape([-1]) | |
| offset = offset.reshape([-1]) | |
| quantized_cdf = EntropyCoder.pmf_to_cdf(pmf, tail_mass, pmf_length, max_length) | |
| cdf_length = pmf_length + 2 | |
| self.set_cdf_info(quantized_cdf, cdf_length, offset) | |
| self.cdf_group_index = self.entropy_coder.add_cdf(*self.get_cdf_info()) | |
| def build_indexes(self, size, qp): | |
| B, C, H, W = size | |
| indexes = torch.arange(C, dtype=torch.int).view(1, -1, 1, 1) + qp * self.channel | |
| return indexes.repeat(B, 1, H, W) | |
| def encode_z(self, x, qp): | |
| _, _, H, W = x.size() | |
| return self.entropy_coder.encode_z(x.reshape(-1), self.cdf_group_index, qp * self.channel, | |
| H * W) | |
| def decode_z(self, size, qp): | |
| self.entropy_coder.decode_z(self.channel * size[0] * size[1], self.cdf_group_index, | |
| qp * self.channel, size[0] * size[1]) | |
| def get_z(self, size, device, dtype): | |
| output_size = (1, self.channel, size[0], size[1]) | |
| val = self.entropy_coder.get_decoded_tensor(device, dtype, non_blocking=True) | |
| return val.reshape(output_size) | |
| class GaussianEncoder(AEHelper): | |
| def __init__(self): | |
| super().__init__() | |
| self.scale_min = 0.11 | |
| self.scale_max = 16.0 | |
| self.scale_level = 128 # <= 256 | |
| self.scale_table = self.get_scale_table(self.scale_min, self.scale_max, self.scale_level) | |
| self.log_scale_min = math.log(self.scale_min) | |
| self.log_scale_max = math.log(self.scale_max) | |
| self.log_scale_step = (self.log_scale_max - self.log_scale_min) / (self.scale_level - 1) | |
| self.log_step_recip = 1. / self.log_scale_step | |
| self.force_zero_thres = None | |
| self.decode_index_cache = {} | |
| self.decode_zeros_cache = {} | |
| def get_scale_table(min_val, max_val, levels): | |
| return torch.exp(torch.linspace(math.log(min_val), math.log(max_val), levels)) | |
| def update(self, entropy_coder, force_zero_thres=None): | |
| self.entropy_coder = entropy_coder | |
| self.force_zero_thres = force_zero_thres | |
| pmf_center = torch.zeros_like(self.scale_table) + 8 | |
| scales = torch.zeros_like(pmf_center) + self.scale_table | |
| cdf_distribution = torch.distributions.normal.Normal(0., scales) | |
| for i in range(8, 1, -1): | |
| samples = torch.zeros_like(pmf_center) + i | |
| probs = cdf_distribution.cdf(samples) | |
| probs = torch.squeeze(probs) | |
| pmf_center = torch.where(probs > torch.zeros_like(pmf_center) + 0.9999, | |
| torch.zeros_like(pmf_center) + i, pmf_center) | |
| pmf_center = pmf_center.int() | |
| pmf_length = 2 * pmf_center + 1 | |
| max_length = torch.max(pmf_length).item() | |
| device = pmf_center.device | |
| samples = torch.arange(max_length, device=device) - pmf_center[:, None] | |
| samples = samples.float() | |
| scales = torch.zeros_like(samples) + self.scale_table[:, None] | |
| cdf_distribution = torch.distributions.normal.Normal(0., scales) | |
| upper = cdf_distribution.cdf(samples + 0.5) | |
| lower = cdf_distribution.cdf(samples - 0.5) | |
| pmf = upper - lower | |
| tail_mass = 2 * lower[:, :1] | |
| quantized_cdf = torch.Tensor(len(pmf_length), max_length + 2) | |
| quantized_cdf = EntropyCoder.pmf_to_cdf(pmf, tail_mass, pmf_length, max_length) | |
| self.set_cdf_info(quantized_cdf, pmf_length+2, -pmf_center) | |
| self.cdf_group_index = self.entropy_coder.add_cdf(*self.get_cdf_info()) | |
| def process_with_mask(self, y, scales, means, mask): | |
| return process_with_mask(y, scales, means, mask, self.force_zero_thres) | |
| def build_indexes_decoder(self, scales): | |
| scales = scales.reshape(-1) | |
| indexes, skip_cond = build_index_dec(scales, self.scale_min, self.scale_max, | |
| self.log_scale_min, self.log_step_recip, | |
| self.force_zero_thres) | |
| if self.force_zero_thres is not None: | |
| indexes = indexes[skip_cond] | |
| return indexes, skip_cond | |
| def build_indexes_encoder(self, symbols, scales): | |
| symbols = symbols.reshape(-1) | |
| scales = scales.reshape(-1) | |
| symbols = build_index_enc(symbols, scales, self.scale_min, self.scale_max, | |
| self.log_scale_min, self.log_step_recip, self.force_zero_thres) | |
| return symbols | |
| def encode_y(self, x, scales): | |
| symbols = self.build_indexes_encoder(x, scales) | |
| return self.entropy_coder.encode_y(symbols, self.cdf_group_index) | |
| def get_decode_index_cache(self, num, device): | |
| if num not in self.decode_index_cache: | |
| c = torch.arange(0, num, dtype=torch.int32, device=device) | |
| self.decode_index_cache[num] = c | |
| return self.decode_index_cache[num] | |
| def get_decode_zeros_cache(self, num, device): | |
| if num not in self.decode_zeros_cache: | |
| c = torch.zeros(num, dtype=torch.int32, device=device) | |
| self.decode_zeros_cache[num] = c | |
| return self.decode_zeros_cache[num].clone() | |
| def decode_and_get_y(self, scales, dtype, device): | |
| indexes, skip_cond = self.build_indexes_decoder(scales) | |
| self.decode_y(indexes) | |
| return self.get_y(scales.shape, scales.numel(), dtype, device, skip_cond, indexes) | |
| def decode_y(self, indexes): | |
| self.entropy_coder.decode_y(indexes, self.cdf_group_index) | |
| def get_y(self, shape, numel, dtype, device, skip_cond, indexes): | |
| if len(indexes) == 0: | |
| return torch.zeros(shape, dtype=dtype, device=device) | |
| if skip_cond is not None: | |
| curr_index = self.get_decode_index_cache(numel, device) | |
| back_index = self.get_decode_zeros_cache(numel, device) | |
| back_index.masked_scatter_(skip_cond, curr_index) | |
| val = self.entropy_coder.get_decoded_tensor(device, dtype, non_blocking=True) | |
| if skip_cond is not None: | |
| y = torch.index_select(val, 0, back_index) * skip_cond | |
| return y.reshape(shape) | |
| return val.reshape(shape) | |