Skip to main content
Vision-language models in Loops train on examples that pair images with text. The trainer turns each image into visual tokens, places them before the text tokens, and computes loss over the combined sequence in the same forward_backward() and optim_step() round trip as text-only training. Checkpoints, sampling, and deployment work the same way; only the input construction changes. For a complete run that fine-tunes on geometry diagrams, deploys the checkpoint, and sends an image prompt, see Fine-tune a vision model with the Loops SDK.

Supported models

The Vision column of the model catalog marks the models that accept image inputs.

Build an image input

Each training example becomes a Datum:
  • model_input contains one ImageChunk with the image bytes and one text chunk with the problem and answer tokens.
  • loss_fn_inputs supplies the loss targets through a TensorData named target_tokens, with one target token per input position.
ImageChunk takes the image bytes inline, as JPEG or PNG. One chunk holds one image; add more chunks for more images. Pass the image already resized: the trainer doesn’t resize images and rejects a decoded image larger than 18 MB or 50 megapixels.
Loops doesn’t fetch external image URLs. Pass the bytes inline in ImageChunk. The ImageAssetPointerChunk type exists for Tinker compatibility, but its constructor raises ValueError.
ImageChunk.expected_tokens tells the trainer how many input tokens the image becomes. The model replaces the image with exactly that many image tokens, so the number must match what the model actually produces. For Qwen VL and Muse Spark models, compute it from the image processor as prod(image_grid_thw) // merge_size**2. The following functions build a Datum from an image, a prompt, and an answer. image_processor is the model’s Hugging Face image processor, loaded with AutoImageProcessor.from_pretrained(base_model, trust_remote_code=True), and tokenizer comes from training_client.get_tokenizer():
The trainer expands each ImageChunk into expected_tokens copies of the model’s image-placeholder token ID and appends the text chunk. Because to_datum omits the final answer token from the input, the input sequence is [image: expected_tokens] [prompt: len(p)] [answer: len(a) - 1].

Set the loss targets

The input and target_tokens have the same length, expected_tokens + len(p) + len(a) - 1. Mask the image and prompt positions with -100, which cross-entropy ignores, except for the last prompt position. That position targets the first answer token. The remaining positions target the subsequent answer tokens, including the final answer token.

Send images to a deployed checkpoint

Deploy a checkpoint from a vision run like any other. The deployment serves an OpenAI-compatible /v1/chat/completions endpoint that accepts images as base64-encoded data in the image_url format:
Text-only prompts work on the same deployment.

Next steps