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
| #!/usr/bin/env python | |
| """Run Mage-VL-Base image or video inference offline or through SGLang.""" | |
| import argparse | |
| import base64 | |
| import mimetypes | |
| from pathlib import Path | |
| def image_url(image: str) -> str: | |
| if image.startswith(("http://", "https://", "data:")): | |
| return image | |
| path = Path(image) | |
| mime = mimetypes.guess_type(path.name)[0] or "image/jpeg" | |
| encoded = base64.b64encode(path.read_bytes()).decode("ascii") | |
| return f"data:{mime};base64,{encoded}" | |
| def sample_video(video: str, num_frames: int): | |
| import cv2 | |
| import numpy as np | |
| from PIL import Image | |
| capture = cv2.VideoCapture(video) | |
| frame_count = int(capture.get(cv2.CAP_PROP_FRAME_COUNT)) | |
| if frame_count <= 0: | |
| capture.release() | |
| raise ValueError(f"Could not read video: {video}") | |
| indices = np.linspace(0, frame_count - 1, min(num_frames, frame_count), dtype=int) | |
| frames = [] | |
| for index in indices: | |
| capture.set(cv2.CAP_PROP_POS_FRAMES, int(index)) | |
| ok, frame = capture.read() | |
| if not ok: | |
| capture.release() | |
| raise ValueError(f"Could not decode frame {index} from: {video}") | |
| frames.append(Image.fromarray(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))) | |
| capture.release() | |
| return frames | |
| def run_offline(args): | |
| import os | |
| import torch | |
| from PIL import Image | |
| from transformers import AutoModelForCausalLM, AutoProcessor | |
| model_path = args.model | |
| if args.video and args.video_backend == "codec" and args.codec_engine == "neural": | |
| if not os.path.isdir(model_path): | |
| from huggingface_hub import snapshot_download | |
| model_path = snapshot_download(args.model) | |
| processor = AutoProcessor.from_pretrained(model_path, trust_remote_code=True) | |
| model = AutoModelForCausalLM.from_pretrained( | |
| model_path, trust_remote_code=True, torch_dtype="auto", device_map="auto" | |
| ).eval() | |
| media_type = "image" if args.image else "video" | |
| messages = [{"role": "user", "content": [ | |
| {"type": media_type}, {"type": "text", "text": args.question}, | |
| ]}] | |
| text = processor.apply_chat_template(messages, tokenize=False, add_generation_prompt=True) | |
| if args.image: | |
| inputs = processor( | |
| text=[text], images=[Image.open(args.image).convert("RGB")], return_tensors="pt" | |
| ) | |
| elif args.video_backend == "codec": | |
| codec_config = { | |
| "engine": "hevc" if args.codec_engine == "traditional" else "dcvc-rt", | |
| "target_canvas": args.num_frames, | |
| "patch": 16, | |
| } | |
| if args.codec_engine == "neural": | |
| codec_config["dcvc"] = { | |
| "pkg_dir": os.path.join(model_path, "neural_codec"), | |
| "device": str(model.device), | |
| } | |
| inputs = processor( | |
| text=[text], | |
| videos=[args.video], | |
| video_backend="codec", | |
| max_pixels=args.max_pixels, | |
| codec_config=codec_config, | |
| return_tensors="pt", | |
| padding=True, | |
| ) | |
| else: | |
| inputs = processor( | |
| text=[text], | |
| videos=[sample_video(args.video, args.num_frames)], | |
| return_tensors="pt", | |
| padding=True, | |
| ) | |
| inputs = {k: (v.to(model.device) if hasattr(v, "to") else v) for k, v in inputs.items()} | |
| if "pixel_values" in inputs: | |
| inputs["pixel_values"] = inputs["pixel_values"].to(model.dtype) | |
| with torch.inference_mode(): | |
| output = model.generate(**inputs, max_new_tokens=args.max_new_tokens, do_sample=False) | |
| answer = processor.tokenizer.decode( | |
| output[0, inputs["input_ids"].shape[1]:], skip_special_tokens=True | |
| ) | |
| print(answer.strip()) | |
| def run_online(args): | |
| from openai import OpenAI | |
| if args.image: | |
| content = [{"type": "image_url", "image_url": {"url": image_url(args.image)}}] | |
| else: | |
| content = [ | |
| {"type": "image_url", "image_url": {"url": frame_url(frame)}} | |
| for frame in sample_video(args.video, args.num_frames) | |
| ] | |
| content.append({"type": "text", "text": args.question}) | |
| client = OpenAI(base_url=args.base_url, api_key=args.api_key) | |
| response = client.chat.completions.create( | |
| model=args.model, | |
| messages=[{"role": "user", "content": content}], | |
| max_tokens=args.max_new_tokens, | |
| ) | |
| print(response.choices[0].message.content) | |
| def frame_url(frame) -> str: | |
| import io | |
| buffer = io.BytesIO() | |
| frame.save(buffer, format="JPEG") | |
| encoded = base64.b64encode(buffer.getvalue()).decode("ascii") | |
| return f"data:image/jpeg;base64,{encoded}" | |
| def main(): | |
| parser = argparse.ArgumentParser(description=__doc__) | |
| parser.add_argument("--mode", choices=("offline", "online"), required=True) | |
| media = parser.add_mutually_exclusive_group(required=True) | |
| media.add_argument("--image", help="Local image path") | |
| media.add_argument("--video", help="Local video path") | |
| parser.add_argument("--video-backend", choices=("frames", "codec"), default="frames") | |
| parser.add_argument( | |
| "--codec-engine", choices=("traditional", "neural"), default="traditional" | |
| ) | |
| parser.add_argument("--num-frames", type=int, default=32) | |
| parser.add_argument("--max-pixels", type=int, default=150000) | |
| parser.add_argument("--question", default="Describe this media.") | |
| parser.add_argument("--model", default="microsoft/Mage-VL") | |
| parser.add_argument("--max-new-tokens", type=int, default=256) | |
| parser.add_argument("--base-url", default="http://localhost:30000/v1") | |
| parser.add_argument("--api-key", default="EMPTY") | |
| args = parser.parse_args() | |
| if args.mode == "online" and args.video_backend == "codec": | |
| parser.error("online video inference supports only --video-backend frames") | |
| if args.num_frames <= 0: | |
| parser.error("--num-frames must be positive") | |
| (run_offline if args.mode == "offline" else run_online)(args) | |
| if __name__ == "__main__": | |
| main() | |