Model reference · open weights

LLaVA-OneVision-2

LLMs lmms-lab-encoder Vision + text 1 build Open weights 11k dl/mo

LLaVA-OneVision-2 is an open-weight language model from lmms-lab-encoder. LLaVA-OneVision-2-8B-Instruct (BF16) weighs 17.1 GB; the smallest configuration that runs it is 2× RTX 3060 12 GB.

For self-hosting, compare this build's requirements below with the GPU you plan to rent.

  • LLaVA-OneVision-2 is an 8.5B parameter multimodal vision-language model developed by lmms-lab-encoder that processes single images, multi-image inputs, and video.
  • It is built on a Qwen3-8B language backbone with a OneVision-style vision encoder and supports a context length of 262144 tokens.
  • The model operates in English and Chinese and is distributed under the Apache-2.0 license.

Summary of the lmms-lab-encoder/LLaVA-OneVision-2-8B-Instruct model card, 2026-10-01

What it is

Released bylmms-lab-encoder
Released2026-05-11
Parameters8.5B
VRAM17.1 GB for the weights

What it runs on

Memory and cards for LLaVA-OneVision-2-8B-Instruct (BF16)

17.1 GBweights, file size
147 MBcache per 1K tokens
2.0 GBruntime overhead, at least
262,144 tokenscontext max
CardRequests at onceContext maxMemory
8K each32K each
RTX 3060 12 GB … RTX 4060 Ti 16 GB
2 smaller cards
RTX 3090 24 GB328K23.4 GB
RTX 4090 24 GB328K23.4 GB
RTX 5090 32 GB9278K31.0 GB
L40S 48 GB205164K44.0 GB
A100 80 GB4812all 256K78.2 GB
H100 80 GB4511all 256K78.1 GB
RTX PRO 6000 Blackwell 96 GB5814all 256K93.8 GB
DGX Spark (GB10) 128 GB unified6917all 256K107 GB
H200 141 GB9423all 256K138 GB
B200 180 GB12531all 256K176 GB
2× RTX 3060 12 GB
tensor parallel
113K11.6 GB a card
2× RTX 4060 Ti 16 GB
tensor parallel
8264K15.4 GB a card
2× RTX 4090 24 GB
tensor parallel
215169K23.4 GB a card
2× RTX 3090 24 GB
tensor parallel
215169K23.4 GB a card
Memory needed at each load
Requests at once8K tokens each32K tokens each
120.3 GB23.9 GB
525.1 GB43.3 GB
828.8 GB57.8 GB
1638.4 GB96.4 GB
3257.8 GB174 GB
6496.4 GB328 GB

One card, with vLLM's small-card settings.

From the model card

What lmms-lab-encoder says about LLaVA-OneVision-2

Read the model card

[!IMPORTANT] 🌟 The core work on this project is led by Glint Lab. For an interactive online experience, visit ve2s.ai.

A multimodal vision-language model that handles single images, multi-image, and video inputs, built on a Qwen3-8B language backbone with a OneVision-style vision encoder.

The model is distributed as a HuggingFace transformers checkpoint with custom code (trust_remote_code=True).

Requirements

Base (image + frame-sampling video)

pip install "transformers>=5.7.0" "torch>=2.4" pillow requests decord

Optional: codec video backend

The model ships a second video backend (video_backend="codec") that replaces uniform frame sampling with codec-aware canvas packing driven by motion vectors and bit-cost — typically yielding stronger long-video accuracy at the same token budget. To enable it you need two extra pieces:

# 1. The cv-preinfer CLI (PyPI: codec-video-prep) drives canvas extraction.
pip install codec-video-prep opencv-python

# 2. A working `ffmpeg` binary must be on PATH.
#    Verify with: ffmpeg -version

ffmpeg version: ffmpeg 4.4.x – 7.x is recommended.

The codec backend additionally needs POSIX flock (already present on Linux/macOS) for the on-disk result cache, and roughly 2 GB free disk under $ONLINE_CODEC_CACHE_DIR (defaults to $HF_HOME/online_codec) per processed video.

Quick start

The repository ships a ready-to-run demo_inference.py that covers both image and video paths.

# Image (default sample image; no auth required)
python demo_inference.py

# Image, custom file + prompt
python demo_inference.py --mode image --media /path/to/cat.jpg \
    --prompt "What is the cat doing?"

# Video (16 uniformly-sampled frames; max-pixels caps per-frame resolution for memory)
python demo_inference.py --mode video --media /path/to/clip.mp4 \
    --num-frames 16 --max-pixels 200704 \
    --prompt "Describe what happens in this video."

Programmatic use

import torch
from transformers import AutoProcessor, AutoModelForImageTextToText
from PIL import Image

MODEL_ID = "lmms-lab-encoder/LLaVA-OneVision-2-8B-Instruct"

processor = AutoProcessor.from_pretrained(MODEL_ID, trust_remote_code=True)
model = AutoModelForImageTextToText.from_pretrained(
    MODEL_ID, trust_remote_code=True, dtype=torch.bfloat16, device_map="cuda",
).eval()

# ----- Image -----
image = Image.open("cat.jpg").convert("RGB")
messages = [{"role": "user", "content": [
    {"type": "image"},
    {"type": "text", "text": "Describe this image in detail."},
]}]
text = processor.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
inputs = processor(text=[text], images=[image], return_tensors="pt", padding=True)
inputs = {k: v.to("cuda") if hasattr(v, "to") else v for k, v in inputs.items()}

out = model.generate(**inputs, max_new_tokens=256, do_sample=False)
print(processor.tokenizer.decode(out[0, inputs["input_ids"].shape[-1]:], skip_special_tokens=True))

# ----- Video -----
# Lower max_pixels if you hit OOM on long videos.
processor.video_processor.max_pixels = 200704

messages = [{"role": "user", "content": [
    {"type": "video"},
    {"type": "text", "text": "Describe what happens in this video."},
]}]
text = processor.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
inputs = processor(
    text=[text], videos=["clip.mp4"], return_tensors="pt", padding=True,
    num_frames=16,  # exact frame count; or use target_fps / max_frames
)
inputs = {k: v.to("cuda") if hasattr(v, "to") else v for k, v in inputs.items()}
out = model.generate(**inputs, max_new_tokens=256, do_sample=False)
print(processor.tokenizer.decode(out[0, inputs["input_ids"].shape[-1]:], skip_special_tokens=True))

Video — codec backend (recommended for long videos)

The codec backend is exposed as a single processor kwarg (video_backend="codec"). Everything else — canvas extraction via cv-preinfer, on-disk caching, patch-position bookkeeping, chat-template rewriting — happens inside processor(...):

# Make sure: `pip install codec-video-prep opencv-python` and ffmpeg on PATH.
messages = [{"role": "user", "content": [
    {"type": "video"},
    {"type": "text", "text": "Describe what happens in this long video."},
]}]
text = processor.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)

inputs = processor(
    text=[text],
    videos=["long_clip.mp4"],
    video_backend="codec",
    max_pixels=150000,          # per-canvas pixel budget; lower if OOM
    return_tensors="pt",
    padding=True,
    # Optional: override codec defaults from preprocessor_config.json
    # codec_config={"target_canvas": 32, "group_size": 32, "images_per_group": 4},
)
inputs = {k: v.to("cuda") if hasattr(v, "to") else v for k, v in inputs.items()}

out = model.generate(**inputs, max_new_tokens=256, do_sample=False)
print(processor.tokenizer.decode(out[0, inputs["input_ids"].shape[-1]:], skip_special_tokens=True))

Defaults for the codec pipeline live in preprocessor_config.json under the "codec" key (target_canvas=32, group_size=32, images_per_group=4, patch=14, min_group_frames=8, max_group_frames=64); they can be overridden per call via codec_config={...}.

Short-video behaviour: if the input video has fewer frames than target_canvas requires (or fewer than min_group_frames), a UserWarning is emitted and inference proceeds with however many canvases cv-preinfer can actually form. For very short clips, falling back to the frame-sampling backend is usually a better choice.

Notes

  • The vision tower is a OneVision-style encoder; the language backbone is Qwen3-8B.
  • chat_template.jinja follows the Qwen3 chat format and emits ... placeholders; the processor expands them per-frame (frames backend) or per-canvas-patch-run (codec backend).
  • Two video backends are availabl

Quoted from the model card on Hugging Face. The full card is behind the Hugging Face link above.

© 2026 AxForge · EU-hosted AI infrastructure Pricing Docs Trust Privacy Terms