Serving LLMs on Jetson AGX Thor (Pt. 2): Qwen2-VL & Qwen3-30B with SGLang
This article documents the end-to-end setup of an SGLang inference server on the NVIDIA Jetson AGX Thor (JetPack R38), covering environment installation, dependency compilation, model configuration, server launch, and API testing.
0. What is SGLang?
SGLang is a high-performance inference framework for LLMs and multimodal models, co-developed by Stanford University and collaborators. Its core strengths lie in efficient inference scheduling and structured generation:
| Feature | Description |
|---|---|
| RadixAttention | Prefix-caching attention mechanism that dramatically reduces computation for multi-turn conversations and batched requests with shared prefixes |
| Structured Output | Native support for JSON Schema, regex, and other constrained generation formats — no post-processing required |
| OpenAI-Compatible API | Built-in /v1/chat/completions endpoint, drop-in replacement for the OpenAI ecosystem |
| Continuous Batching | Dynamically inserts new requests to maximize GPU utilization |
| Multimodal Support | Native vision-language model support — a single endpoint for both text-only and vision-language inference |
The typical workflow is: install dependencies → configure the CUDA toolchain → resolve build issues → prepare models → launch the inference server → test and operate. The following sections walk through every step on the Jetson AGX Thor.
1. Prerequisites
Supported Environment
| Item | Value |
|---|---|
| Device | NVIDIA Jetson AGX Thor |
| OS | Ubuntu (JetPack R38, REVISION 4.0) |
| GPU | NVIDIA AGX Thor, 126 GB VRAM |
| CUDA | 13.0 |
| Python | 3.13 (Conda env sglang) |
| Storage | NVMe SSD 937 GB |
Directory Conventions
Use /workspace as the base path for all models and artifacts:
| Type | Path |
|---|---|
| HuggingFace model | /workspace/models/Qwen2-VL-7B-Instruct/ |
| HuggingFace model | /workspace/models/Qwen3-30B-A3B-Instruct-2507/ |
2. Environment Setup
2.1 Create a Conda Environment
conda create -n sglang python=3.13 -y
conda activate sglang2.2 Install SGLang
pip install sglang3. Configuring the CUDA Toolchain
Jetson AGX Thor ships only with CUDA runtime libraries — the development toolkit (headers and nvcc) is not included by default.
3.1 Installation
sudo apt update
sudo apt install cuda-toolkit3.2 Locating Header Files
After installation, find the CUDA header locations:
find /usr -name "cuda_runtime_api.h" 2>/dev/nullOn Jetson AGX Thor, the path is:
/usr/local/cuda-13.0/targets/sbsa-linux/include/cuda_runtime_api.hNote: Jetson uses
sbsa-linux, not the traditional desktopaarch64-linux.
3.3 Configuring Environment Variables
export CUDA_HOME=/usr/local/cuda-13.0
export C_INCLUDE_PATH=$CUDA_HOME/targets/sbsa-linux/include:$C_INCLUDE_PATH
export CPLUS_INCLUDE_PATH=$CUDA_HOME/targets/sbsa-linux/include:$CPLUS_INCLUDE_PATH
export PATH=$CUDA_HOME/bin:$PATHTo make these permanent, append to ~/.bashrc:
echo 'export CUDA_HOME=/usr/local/cuda-13.0' >> ~/.bashrc
echo 'export PATH=$CUDA_HOME/bin:$PATH' >> ~/.bashrc
echo 'export C_INCLUDE_PATH=$CUDA_HOME/targets/sbsa-linux/include:$C_INCLUDE_PATH' >> ~/.bashrc
echo 'export CPLUS_INCLUDE_PATH=$CUDA_HOME/targets/sbsa-linux/include:$CPLUS_INCLUDE_PATH' >> ~/.bashrc
source ~/.bashrc4. Dependency Compilation
outlines_core is a Rust-based package that requires the following dependencies for source builds:
4.1 Install Rust
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
# Choose the default installation (option 1)
source $HOME/.cargo/env
rustc --version4.2 Install OpenSSL Development Libraries
sudo apt install libssl-dev pkg-config4.3 Python 3.14 Compatibility
When using Python 3.14, PyO3 (v0.22.6) is not supported. Set the compatibility flag:
export PYO3_USE_ABI3_FORWARD_COMPATIBILITY=1
pip install outlines_core5. Model Preparation
5.1 Available Models
ls /workspace/models/Qwen2-VL-7B-Instruct
Qwen3-30B-A3B-Instruct-25075.2 Model Format Overview
| Path | Format | Compatible Frameworks |
|---|---|---|
| /workspace/models/Qwen2-VL-7B-Instruct | Hugging Face | SGLang, vLLM |
| /workspace/models/Qwen3-30B-A3B-Instruct-2507 | Hugging Face | SGLang, vLLM |
6. Starting the Inference Server
6.1 Small Model Validation (Qwen2-VL-7B)
python3 -m sglang.launch_server \
--model-path /workspace/models/Qwen2-VL-7B-Instruct \
--host 0.0.0.0 \
--log-level infoSuccess indicators:
[INFO] Uvicorn running on http://0.0.0.0:30000 (Press CTRL+C to quit)
[INFO] The server is fired up and ready to roll!6.2 Large Model Launch (Qwen3-30B)
Due to CUDA Graph compatibility issues on the NVIDIA Jetson AGX Thor platform, CUDA Graph must be disabled:
python3 -m sglang.launch_server \
--model-path /workspace/models/Qwen3-30B-A3B-Instruct-2507 \
--host 0.0.0.0 \
--log-level info \
--cuda-graph-backend-decode disabled \
--cuda-graph-backend-prefill disabled \
--mem-fraction-static 0.806.3 Key Parameters
| Parameter | Purpose | Rationale |
|---|---|---|
--model-path | Path to the HuggingFace model | Supports both local paths and HuggingFace Hub IDs |
--host 0.0.0.0 | Listen on all network interfaces | Allows access from other devices on the LAN |
--log-level info | Log verbosity | debug / info / warning; use debug when troubleshooting |
--cuda-graph-backend-decode disabled | Disable CUDA Graph for decode phase | CUDA Graph deadlocks on AGX Thor — must be disabled |
--cuda-graph-backend-prefill disabled | Disable CUDA Graph for prefill phase | Same as above |
--mem-fraction-static 0.80 | Allocate 80% VRAM for KV Cache | Can be raised for longer contexts in low-concurrency edge scenarios |
7. API Testing
7.1 Plain Text Request
curl http://localhost:30000/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "Qwen2-VL-7B-Instruct",
"messages": [{"role": "user", "content": "Hello, introduce yourself."}],
"max_tokens": 100
}'7.2 Multimodal Image Request (Qwen2-VL)
Since base64-encoded images can exceed the command-line argument length limit, send the request via file:
# Encode image to base64 and construct the request JSON
IMG_BASE64=$(base64 -w 0 /path/to/your/image.png)
cat > /tmp/vl_request.json << ENDJSON
{
"model": "Qwen2-VL-7B-Instruct",
"messages": [{
"role": "user",
"content": [
{"type": "image_url", "image_url": {"url": "data:image/png;base64,${IMG_BASE64}"}},
{"type": "text", "text": "Describe this image."}
]
}],
"max_tokens": 200
}
ENDJSON
# Send the request
curl http://localhost:30000/v1/chat/completions \
-H "Content-Type: application/json" \
-d @/tmp/vl_request.json8. Server Management
8.1 Stopping the Server
# Option 1: Press Ctrl+C in the launch terminal
# Option 2: Force-kill the process
pkill -f sglang
# Verify cleanup
ps aux | grep sglang8.2 Running in the Background
nohup python3 -m sglang.launch_server \
--model-path /workspace/models/Qwen3-30B-A3B-Instruct-2507 \
--host 0.0.0.0 \
--log-level info \
--cuda-graph-backend-decode disabled \
--cuda-graph-backend-prefill disabled \
> /tmp/sglang.log 2>&1 &
# Tail the logs
tail -f /tmp/sglang.log8.3 Checking Server Status
# Check port binding
ss -tlnp | grep 30000
# GPU memory usage
nvidia-smi
# Process status
ps aux | grep sglangFinal Thoughts
After walking through the entire SGLang deployment pipeline, a few reflections to share:
SGLang’s onboarding experience is remarkably smooth. A single
pip install, a one-liner Python module launch, and an OpenAI-compatible API out of the box.The main Jetson AGX Thor compatibility pain point is CUDA Graph. CUDA Graph, which is enabled by default on desktop GPUs, causes deadlocks on AGX Thor. Disabling it restores normal functionality, but at some performance cost. This is the single most important caveat for edge-platform deployments and deserves official attention in future releases.
The outlines_core Rust build chain is a hidden cost. On ARM platforms like Jetson, precompiled wheels for many Python packages are unavailable, forcing source builds — which means Rust, OpenSSL, and other extra dependencies must be prepared ahead of time. For developers less familiar with system administration, this can be the first real hurdle.
SGLang differentiates at the scheduling layer, not the operator layer. The model weights stay frozen — all optimization happens at the runtime scheduling level. RadixAttention reuses KV caches across requests with shared prefixes. Continuous batching dynamically inserts new requests to keep the GPU saturated. Prefill-Decode disaggregation lets compute-heavy and memory-bound phases scale independently. The core question SGLang asks is: “When 1,000 requests arrive at once, how do you schedule them for maximum efficiency?” SGLang doesn’t do compile-level hardware optimization itself — it stands on low-level operator libraries like FlashInfer and FlashAttention. Its moat is not how extreme its kernels are, but how intelligent its scheduling strategy is. This also explains why SGLang shines in high-concurrency, multi-tenant online serving — the fiercer the contention, the more its scheduling edge matters.
On the AGX Thor, SGLang wasn’t built for this hardware — but the fact that it runs at all is telling. As a single-user edge device, Thor’s typical workload is low-latency single-request inference for embodied intelligence and robotic control — not hundreds or thousands of concurrent requests. That’s exactly the scenario where SGLang’s scheduling capabilities are least needed. But flip the lens: being able to run a datacenter-grade inference framework end-to-end on an edge card is itself a testament to the Jetson platform’s capability. If future edge deployments evolve toward multi-model, multi-request concurrency — say, a single robot simultaneously running navigation, manipulation, and dialogue models — SGLang’s scheduling advantage would naturally surface.
I hope this guide helps you. May your Jetson run inference smoothly, may every curl return the answer you’re looking for. Happy deploying.