94057c3d3e
PR Test (NPU) / check-changes (push) Has been cancelled
PR Test (NPU) / pr-gate (push) Has been cancelled
PR Test (NPU) / set-image-config (push) Has been cancelled
PR Test (NPU) / stage-b-test-1-npu-a2 (0) (push) Has been cancelled
PR Test (NPU) / stage-b-test-1-npu-a2 (1) (push) Has been cancelled
PR Test (NPU) / stage-b-test-2-npu-a2 (0) (push) Has been cancelled
PR Test (NPU) / stage-b-test-2-npu-a2 (1) (push) Has been cancelled
PR Test (NPU) / stage-b-test-4-npu-a3 (push) Has been cancelled
PR Test (NPU) / stage-b-test-16-npu-a3 (push) Has been cancelled
PR Test (NPU) / multimodal-gen-test-1-npu-a3 (push) Has been cancelled
PR Test (NPU) / multimodal-gen-test-2-npu-a3 (push) Has been cancelled
PR Test (Arm64) / pr-gate (push) Has been cancelled
PR Test (Arm64) / check-changes (push) Has been cancelled
PR Test (Arm64) / build-test (push) Has been cancelled
PR Test (sgl-router) / gate (push) Has been cancelled
PR Test (sgl-router) / tier-1 — lint (push) Has been cancelled
PR Test (sgl-router) / tier-2 — build + test (push) Has been cancelled
PR Test (sgl-router) / tier-3 — docker (placeholder) (push) Has been cancelled
PR Test (sgl-router) / tier-3 — k8s integration (push) Has been cancelled
PR Test (sgl-router) / tier-3 — e2e (push) Has been cancelled
PR Test (sgl-router) / finish (push) Has been cancelled
PR Test (NPU) / single-node-poc (map[name:qwen3_6_27b_w8a8_1p_in64k_out1k_50ms runner:linux-aarch64-a3-2 test_case:test/registered/ascend/performance/qwen3_6_27b/test_npu_qwen3_6_27b_w8a8_1p_in64k_out1k_50ms.py test_type:perf]) (push) Has been cancelled
PR Test (NPU) / pr-test-npu-finish (push) Has been cancelled
PR Test (Xeon) / pr-gate (push) Has been cancelled
PR Test (Xeon) / check-changes (push) Has been cancelled
PR Test (Xeon) / build-test (, xeon-gnr, base-b-test-cpu) (push) Has been cancelled
PR Test (XPU) / check-changes (push) Has been cancelled
PR Test (XPU) / pr-gate (push) Has been cancelled
PR Test (XPU) / stage-a-test-1-gpu-xpu (push) Has been cancelled
PR Test (XPU) / wait-for-stage-a (push) Has been cancelled
PR Test (XPU) / stage-b-test-1-gpu-xpu (push) Has been cancelled
PR Test (XPU) / finish (push) Has been cancelled
CI Model Inventory / build-inventory (push) Has been cancelled
Lint / lint (push) Has been cancelled
PR Benchmark (SMG Components) / Benchmark Compilation Check (push) Has been cancelled
PR Benchmark (SMG Components) / Benchmark - Manual Policy (push) Has been cancelled
PR Benchmark (SMG Components) / Benchmark - Request Processing (push) Has been cancelled
PR Benchmark (SMG Components) / Benchmark Summary (push) Has been cancelled
PR Test (SMG) / build-wheel (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on windows (x86_64 - auto) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on macos (x86_64 - auto) (push) Has been cancelled
PR Test (SMG) / python-unit-tests (push) Has been cancelled
PR Test (SMG) / unit-tests (push) Has been cancelled
PR Test (SMG) / benchmarks (push) Has been cancelled
PR Test (SMG) / chat-completions (push) Has been cancelled
PR Test (SMG) / chat-completions-4gpu (push) Has been cancelled
PR Test (SMG) / e2e (push) Has been cancelled
PR Test (SMG) / docker-build-test (push) Has been cancelled
PR Test (SMG) / k8s-integration (push) Has been cancelled
PR Test (SMG) / finish (push) Has been cancelled
PR Test (SMG) / summarize-benchmarks (push) Has been cancelled
Release SGLang Model Gateway Docker Image / publish (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on macos (aarch64 - auto) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on linux (aarch64 - auto) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on linux (x86_64 - auto) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on linux (aarch64 - musllinux_1_1) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on linux (x86_64 - musllinux_1_1) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / Build SDist (push) Has been cancelled
Release SGLang Model Gateway to PyPI / Upload to PyPI (push) Has been cancelled
Release SGLang Kernels / build-cu129-matrix (aarch64, 12.9, 3.10, arm-kernel-build-node) (push) Has been cancelled
Release SGLang Kernels / build-cu129-matrix (x86_64, 12.9, 3.10, x64-kernel-build-node) (push) Has been cancelled
Release SGLang Kernels / release-cu129 (push) Has been cancelled
Release SGLang Kernels / build-cu130-matrix (aarch64, 13.0, 3.10, arm-kernel-build-node) (push) Has been cancelled
Release SGLang Kernels / build-cu130-matrix (x86_64, 13.0, 3.10, x64-kernel-build-node) (push) Has been cancelled
Release SGLang Kernels / release-cu130 (push) Has been cancelled
Release SGLang Kernels / build-rocm-matrix (3.10, 700) (push) Has been cancelled
Release SGLang Kernels / build-rocm-matrix (3.10, 720) (push) Has been cancelled
Release SGLang Kernels / release-rocm700 (push) Has been cancelled
Release SGLang Kernels / release-rocm720 (push) Has been cancelled
Release SGLang Kernels / build-musa43 (43, 3.10) (push) Has been cancelled
Release SGLang Kernels / release-musa43 (push) Has been cancelled
250 lines
7.5 KiB
Plaintext
250 lines
7.5 KiB
Plaintext
---
|
|
title: "Query VLM with Offline Engine"
|
|
metatags:
|
|
description: "SGLang VLM offline engine: raw images, processor output, precomputed embeddings. Qwen2.5-VL and Llama 4 examples."
|
|
---
|
|
This tutorial demonstrates how to use SGLang's **offline Engine API** to query VLMs. We will demonstrate usage with Qwen2.5-VL and Llama 4. This section demonstrates three different calling approaches:
|
|
|
|
1. **Basic Call**: Directly pass images and text.
|
|
2. **Processor Output**: Use HuggingFace processor for data preprocessing.
|
|
3. **Precomputed Embeddings**: Pre-calculate image features to improve inference efficiency.
|
|
|
|
## Understanding the Three Input Formats
|
|
|
|
SGLang supports three ways to pass visual data, each optimized for different scenarios:
|
|
|
|
### 1. **Raw Images** - Simplest approach
|
|
- Pass PIL Images, file paths, URLs, or base64 strings directly
|
|
- SGLang handles all preprocessing automatically
|
|
- Best for: Quick prototyping, simple applications
|
|
|
|
### 2. **Processor Output** - For custom preprocessing
|
|
- Pre-process images with HuggingFace processor
|
|
- Pass the complete processor output dict with `format: "processor_output"`
|
|
- Best for: Custom image transformations, integration with existing pipelines
|
|
- Requirement: Must use `input_ids` instead of text prompt
|
|
|
|
### 3. **Precomputed Embeddings** - For maximum performance
|
|
- Pre-calculate visual embeddings using the vision encoder
|
|
- Pass embeddings with `format: "precomputed_embedding"`
|
|
- Best for: Repeated queries on same images, caching, high-throughput serving
|
|
- Performance gain: Avoids redundant vision encoder computation (30-50% speedup)
|
|
|
|
**Key Rule**: Within a single request, use only one format for all images. Don't mix formats.
|
|
|
|
The examples below demonstrate all three approaches with both Qwen2.5-VL and Llama 4 models.
|
|
|
|
## Querying Qwen2.5-VL Model
|
|
|
|
```python Example
|
|
import nest_asyncio
|
|
|
|
nest_asyncio.apply()
|
|
|
|
import sglang.test.doc_patch # noqa: F401
|
|
|
|
model_path = "Qwen/Qwen2.5-VL-3B-Instruct"
|
|
chat_template = "qwen2-vl"
|
|
example_image_url = "https://raw.githubusercontent.com/sgl-project/sglang/main/examples/assets/example_image.png"
|
|
```
|
|
|
|
```python Example
|
|
from io import BytesIO
|
|
import requests
|
|
from PIL import Image
|
|
|
|
from sglang.srt.parser.conversation import chat_templates
|
|
|
|
image = Image.open(BytesIO(requests.get(example_image_url).content))
|
|
|
|
conv = chat_templates[chat_template].copy()
|
|
conv.append_message(conv.roles[0], f"What's shown here: {conv.image_token}?")
|
|
conv.append_message(conv.roles[1], "")
|
|
conv.image_data = [image]
|
|
|
|
print("Generated prompt text:")
|
|
print(conv.get_prompt())
|
|
print(f"\nImage size: {image.size}")
|
|
image
|
|
```
|
|
|
|
### Basic Offline Engine API Call
|
|
|
|
```python Example
|
|
from sglang import Engine
|
|
|
|
llm = Engine(model_path=model_path, chat_template=chat_template, log_level="warning")
|
|
```
|
|
|
|
```python Example
|
|
out = llm.generate(prompt=conv.get_prompt(), image_data=[image])
|
|
print("Model response:")
|
|
print(out["text"])
|
|
```
|
|
|
|
### Call with Processor Output
|
|
|
|
Using a HuggingFace processor to preprocess text and images, and passing the `processor_output` directly into `Engine.generate`.
|
|
|
|
```python Example
|
|
from transformers import AutoProcessor
|
|
|
|
processor = AutoProcessor.from_pretrained(model_path, use_fast=True)
|
|
processor_output = processor(
|
|
images=[image], text=conv.get_prompt(), return_tensors="pt"
|
|
)
|
|
|
|
out = llm.generate(
|
|
input_ids=processor_output["input_ids"][0].detach().cpu().tolist(),
|
|
image_data=[dict(processor_output, format="processor_output")],
|
|
)
|
|
print("Response using processor output:")
|
|
print(out["text"])
|
|
```
|
|
|
|
### Call with Precomputed Embeddings
|
|
|
|
You can pre-calculate image features to avoid repeated visual encoding processes.
|
|
|
|
```python Example
|
|
from transformers import AutoProcessor
|
|
from transformers import Qwen2_5_VLForConditionalGeneration
|
|
|
|
processor = AutoProcessor.from_pretrained(model_path, use_fast=True)
|
|
model = Qwen2_5_VLForConditionalGeneration.from_pretrained(model_path).eval()
|
|
vision = model.model.visual.cuda()
|
|
```
|
|
|
|
```python Example
|
|
processor_output = processor(
|
|
images=[image], text=conv.get_prompt(), return_tensors="pt"
|
|
)
|
|
|
|
input_ids = processor_output["input_ids"][0].detach().cpu().tolist()
|
|
|
|
precomputed_embeddings = vision(
|
|
processor_output["pixel_values"].cuda(), processor_output["image_grid_thw"].cuda()
|
|
)
|
|
precomputed_embeddings = precomputed_embeddings.pooler_output
|
|
|
|
multi_modal_item = dict(
|
|
processor_output,
|
|
format="precomputed_embedding",
|
|
feature=precomputed_embeddings,
|
|
)
|
|
|
|
out = llm.generate(input_ids=input_ids, image_data=[multi_modal_item])
|
|
print("Response using precomputed embeddings:")
|
|
print(out["text"])
|
|
|
|
llm.shutdown()
|
|
```
|
|
|
|
## Querying Llama 4 Vision Model
|
|
|
|
```python Example
|
|
model_path = "meta-llama/Llama-4-Scout-17B-16E-Instruct"
|
|
chat_template = "llama-4"
|
|
|
|
from io import BytesIO
|
|
import requests
|
|
from PIL import Image
|
|
|
|
from sglang.srt.parser.conversation import chat_templates
|
|
|
|
# Download the same example image
|
|
image = Image.open(BytesIO(requests.get(example_image_url).content))
|
|
|
|
conv = chat_templates[chat_template].copy()
|
|
conv.append_message(conv.roles[0], f"What's shown here: {conv.image_token}?")
|
|
conv.append_message(conv.roles[1], "")
|
|
conv.image_data = [image]
|
|
|
|
print("Llama 4 generated prompt text:")
|
|
print(conv.get_prompt())
|
|
print(f"Image size: {image.size}")
|
|
|
|
image
|
|
```
|
|
|
|
### Llama 4 Basic Call
|
|
|
|
Llama 4 requires more computational resources, so it's configured with multi-GPU parallelism (tp_size=4) and larger context length.
|
|
|
|
```python Example
|
|
llm = Engine(
|
|
model_path=model_path,
|
|
enable_multimodal=True,
|
|
attention_backend="fa3",
|
|
tp_size=4,
|
|
context_length=65536,
|
|
)
|
|
|
|
out = llm.generate(prompt=conv.get_prompt(), image_data=[image])
|
|
print("Llama 4 response:")
|
|
print(out["text"])
|
|
```
|
|
|
|
### Call with Processor Output
|
|
|
|
Using HuggingFace processor to preprocess data can reduce computational overhead during inference.
|
|
|
|
```python Example
|
|
from transformers import AutoProcessor
|
|
|
|
processor = AutoProcessor.from_pretrained(model_path, use_fast=True)
|
|
processor_output = processor(
|
|
images=[image], text=conv.get_prompt(), return_tensors="pt"
|
|
)
|
|
|
|
out = llm.generate(
|
|
input_ids=processor_output["input_ids"][0].detach().cpu().tolist(),
|
|
image_data=[dict(processor_output, format="processor_output")],
|
|
)
|
|
print("Response using processor output:")
|
|
print(out)
|
|
```
|
|
|
|
### Call with Precomputed Embeddings
|
|
|
|
```python Example
|
|
from transformers import AutoProcessor
|
|
from transformers import Llama4ForConditionalGeneration
|
|
|
|
processor = AutoProcessor.from_pretrained(model_path, use_fast=True)
|
|
model = Llama4ForConditionalGeneration.from_pretrained(
|
|
model_path, torch_dtype="auto"
|
|
).eval()
|
|
|
|
vision = model.vision_model.cuda()
|
|
multi_modal_projector = model.multi_modal_projector.cuda()
|
|
|
|
print(f'Image pixel values shape: {processor_output["pixel_values"].shape}')
|
|
input_ids = processor_output["input_ids"][0].detach().cpu().tolist()
|
|
|
|
# Process image through vision encoder
|
|
image_outputs = vision(
|
|
processor_output["pixel_values"].to("cuda"),
|
|
aspect_ratio_ids=processor_output["aspect_ratio_ids"].to("cuda"),
|
|
aspect_ratio_mask=processor_output["aspect_ratio_mask"].to("cuda"),
|
|
output_hidden_states=False
|
|
)
|
|
image_features = image_outputs.last_hidden_state
|
|
|
|
# Flatten image features and pass through multimodal projector
|
|
vision_flat = image_features.view(-1, image_features.size(-1))
|
|
precomputed_embeddings = multi_modal_projector(vision_flat)
|
|
|
|
# Build precomputed embedding data item
|
|
mm_item = dict(
|
|
processor_output,
|
|
format="precomputed_embedding",
|
|
feature=precomputed_embeddings
|
|
)
|
|
|
|
# Use precomputed embeddings for efficient inference
|
|
out = llm.generate(input_ids=input_ids, image_data=[mm_item])
|
|
print("Llama 4 precomputed embedding response:")
|
|
print(out["text"])
|
|
```
|