Skip to content

Commit 5d2304d

Browse files
maryamtahhanclaude
andcommitted
Add vLLM Offline Backend for batch processing
Implements standalone offline backend using vLLM's LLM class for micro-batching. Adapted to main's architecture without VLLMBackendBase, using main's import patterns (lazy loading via guidellm.extras, utils.audio/vision). Features: - Batch processing with configurable batch_size (default: 32) - Chat template support (plain, default-template, custom Jinja2) - Multimodal data handling (image/audio) - Single-process execution for batch coordination - Compatible with vLLM 0.21.0+ Co-Authored-By: Claude Sonnet 4.5 <[email protected]> Signed-off-by: Maryam Tahhan <[email protected]>
1 parent 009a331 commit 5d2304d

6 files changed

Lines changed: 1032 additions & 4 deletions

File tree

docs/guides/backends.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,12 @@ GuideLLM is designed to work with OpenAI-compatible HTTP servers, enabling seaml
88

99
GuideLLM supports OpenAI-compatible HTTP servers, which provide a standardized API for interacting with LLMs. This includes popular implementations such as [vLLM](https://github.com/vllm-project/vllm) and [Text Generation Inference (TGI)](https://github.com/huggingface/text-generation-inference). These servers allow GuideLLM to perform evaluations, benchmarks, and optimizations with minimal setup.
1010

11-
### vLLM Python backend
11+
### vLLM Python Backends
1212

13-
GuideLLM supports running inference in the same process using the **vLLM Python backend** (`vllm_python`). This backend runs inference in the same process as GuideLLM's using vLLM's python API (AsyncLLMEngine), without an HTTP server. For setup, installation options (container, existing vLLM, pip), and examples, see [vLLM Python backend](vllm-python-backend.md).
13+
GuideLLM supports running inference in the same process using vLLM's Python API, without an HTTP server:
14+
15+
- **vLLM Python backend** (`vllm_python`): Uses vLLM's AsyncLLMEngine for async streaming inference. For setup and examples, see [vLLM Python backend](vllm-python-backend.md).
16+
- **vLLM Offline backend** (`vllm_offline`): Uses vLLM's LLM class for batch processing with micro-batching. Designed for offline benchmarking where batch efficiency is prioritized over streaming latency. For setup and examples, see [vLLM Offline backend](vllm-offline-backend.md).
1417

1518
## Examples for Spinning Up Compatible Servers
1619

Lines changed: 235 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,235 @@
1+
# vLLM Offline Backend
2+
3+
The **vLLM Offline backend** (`vllm_offline`) provides synchronous batch processing using vLLM's `LLM` class. It collects requests into micro-batches and processes them together for maximum throughput, making it ideal for offline benchmarking scenarios where batching efficiency is prioritized over per-request latency.
4+
5+
## When to Use the Offline Backend
6+
7+
**Use `vllm_offline` when:**
8+
9+
- Running offline batch inference on large datasets
10+
- Maximizing throughput is more important than individual request latency
11+
- You have a known dataset size and want optimal batch processing
12+
- Benchmarking pure model throughput without HTTP overhead
13+
- Processing datasets for evaluation or ETL pipelines
14+
15+
**Use `vllm_python` (AsyncLLMEngine) when:**
16+
17+
- You need streaming token-by-token responses
18+
- Simulating production-like continuous request arrival
19+
- Measuring realistic latency characteristics
20+
- Need async request handling
21+
22+
**Use OpenAI HTTP backend when:**
23+
24+
- Testing against a production vLLM server
25+
- Measuring end-to-end latency including network overhead
26+
- Benchmarking a deployed service
27+
28+
## Installation
29+
30+
The offline backend requires vLLM to be installed. See the [vLLM Python Backend installation guide](vllm-python-backend.md#installation) for recommended installation methods.
31+
32+
## Basic Usage
33+
34+
```bash
35+
guidellm benchmark run \
36+
--backend vllm_offline \
37+
--model "Qwen/Qwen3-0.6B" \
38+
--backend-kwargs '{"batch_size": 64}' \
39+
--data "prompt_tokens=256,output_tokens=128" \
40+
--max-requests 1000
41+
```
42+
43+
## Backend Options
44+
45+
Configure the offline backend via `--backend-kwargs` with JSON:
46+
47+
```bash
48+
--backend-kwargs '{
49+
"model": "meta-llama/Llama-2-7b-hf",
50+
"batch_size": 64,
51+
"vllm_config": {
52+
"tensor_parallel_size": 2,
53+
"gpu_memory_utilization": 0.9
54+
}
55+
}'
56+
```
57+
58+
### Key Parameters
59+
60+
- **`model`** (required): Model identifier or path
61+
- **`batch_size`**: Number of requests to collect before processing (default: 32)
62+
- Larger batches = higher throughput but more latency
63+
- Smaller batches = lower latency but less throughput
64+
- Recommended: 32-128 for most use cases
65+
- **`vllm_config`**: Dictionary of vLLM EngineArgs parameters
66+
- `tensor_parallel_size`: Number of GPUs for tensor parallelism
67+
- `gpu_memory_utilization`: Fraction of GPU memory to use (0.0-1.0)
68+
- `max_model_len`: Maximum sequence length
69+
- See [vLLM Engine Arguments](https://docs.vllm.ai/en/stable/configuration/engine_args/) for all options (use Python parameter names)
70+
- **`request_format`**: How to format prompts
71+
- `"default-template"` (default): Use tokenizer's chat template
72+
- `"plain"`: No chat template, plain text concatenation
73+
- Path or string: Custom Jinja2 chat template
74+
- **`image_placeholder`**: Placeholder for images (default: `"<image>"`)
75+
- **`audio_placeholder`**: Placeholder for audio (default: `"<|audio|>"`)
76+
77+
## How Micro-Batching Works
78+
79+
The offline backend uses a **micro-batching** approach:
80+
81+
1. **Buffering**: As requests arrive via `resolve()`, they're added to a buffer
82+
2. **Batch Detection**: When buffer reaches `batch_size`, trigger processing
83+
3. **Batch Processing**: Process entire batch with one `LLM.generate()` call
84+
4. **Result Distribution**: Return cached results to waiting requests
85+
5. **Flush on Shutdown**: Remaining requests processed when backend shuts down
86+
87+
This gives you 10-100x fewer model forward passes compared to per-request processing while working within GuideLLM's scheduler architecture.
88+
89+
## Examples
90+
91+
### Basic Throughput Benchmark
92+
93+
```bash
94+
guidellm benchmark run \
95+
--backend vllm_offline \
96+
--model "Qwen/Qwen3-0.6B" \
97+
--data "prompt_tokens=512,output_tokens=256" \
98+
--profile throughput \
99+
--max-seconds 60
100+
```
101+
102+
### Large Batch Processing
103+
104+
```bash
105+
guidellm benchmark run \
106+
--backend vllm_offline \
107+
--backend-kwargs '{"batch_size": 128}' \
108+
--model "meta-llama/Llama-2-7b-hf" \
109+
--data path/to/dataset.csv \
110+
--max-requests -1 # Process entire dataset
111+
```
112+
113+
### Multi-GPU Configuration
114+
115+
```bash
116+
guidellm benchmark run \
117+
--backend vllm_offline \
118+
--backend-kwargs '{
119+
"model": "meta-llama/Llama-2-70b-hf",
120+
"batch_size": 64,
121+
"vllm_config": {
122+
"tensor_parallel_size": 4,
123+
"gpu_memory_utilization": 0.95
124+
}
125+
}' \
126+
--data "prompt_tokens=1024,output_tokens=512"
127+
```
128+
129+
### HuggingFace Dataset
130+
131+
```bash
132+
guidellm benchmark run \
133+
--backend vllm_offline \
134+
--model "meta-llama/Llama-2-7b-hf" \
135+
--backend-kwargs '{"batch_size": 32}' \
136+
--data "hf:cnn_dailymail" \
137+
--data-args '{"name": "3.0.0"}' \
138+
--data-column-mapper '{"column_mappings": {"text_column": "article"}}'
139+
```
140+
141+
## Performance Tuning
142+
143+
### Choosing Batch Size
144+
145+
| Batch Size | Throughput | Latency | Memory | When to Use |
146+
| ---------- | ---------- | ------- | ------ | ---------------------------- |
147+
| 8-16 | Low | Low | Low | Small models, limited memory |
148+
| 32-64 | Good | Medium | Medium | General use, balanced |
149+
| 128-256 | High | High | High | Large GPUs, max throughput |
150+
151+
**Rule of thumb**: Start with 32, increase until GPU utilization >90% or OOM.
152+
153+
### Memory Optimization
154+
155+
```bash
156+
# Reduce memory usage
157+
--backend-kwargs '{
158+
"batch_size": 16,
159+
"vllm_config": {
160+
"gpu_memory_utilization": 0.8,
161+
"max_model_len": 2048
162+
}
163+
}'
164+
```
165+
166+
### Maximizing Throughput
167+
168+
```bash
169+
# Maximize throughput
170+
--backend-kwargs '{
171+
"batch_size": 128,
172+
"vllm_config": {
173+
"gpu_memory_utilization": 0.95,
174+
"enable_prefix_caching": true
175+
}
176+
}'
177+
```
178+
179+
## Comparison: Offline vs Python vs HTTP
180+
181+
| Feature | `vllm_offline` | `vllm_python` | OpenAI HTTP |
182+
| -------------- | ---------------- | ------------- | ------------ |
183+
| **Batching** | Micro-batching | Continuous | Continuous |
184+
| **Throughput** | Highest | High | Good |
185+
| **Latency** | Higher (batched) | Lower | Lowest† |
186+
| **Streaming** | No | Yes | Yes |
187+
| **Overhead** | None | None | HTTP/network |
188+
| **Processes** | 1 | 1 | Multiple |
189+
| **Use Case** | Offline eval | Research | Production |
190+
191+
*† Subject to network conditions*
192+
193+
## Troubleshooting
194+
195+
### "Backend not started up for process"
196+
197+
The backend wasn't initialized. Ensure your benchmark calls the backend lifecycle correctly (this should happen automatically).
198+
199+
### Out of Memory (OOM)
200+
201+
Reduce `batch_size` or `gpu_memory_utilization`:
202+
203+
```bash
204+
--backend-kwargs '{"batch_size": 16, "vllm_config": {"gpu_memory_utilization": 0.7}}'
205+
```
206+
207+
### Batch Processing Too Slow
208+
209+
Increase `batch_size` for better GPU utilization:
210+
211+
```bash
212+
--backend-kwargs '{"batch_size": 64}'
213+
```
214+
215+
### Wrong Prompt Format
216+
217+
Specify `request_format` explicitly:
218+
219+
```bash
220+
--backend-kwargs '{"request_format": "plain"}'
221+
```
222+
223+
## Limitations
224+
225+
1. **No Streaming**: Results returned after entire batch completes
226+
2. **Single Process**: Limited to 1 worker process for batch coordination
227+
3. **Fixed Batch Window**: Batches based on count, not time
228+
4. **Multi-turn Not Supported**: Conversation history not yet implemented
229+
230+
## See Also
231+
232+
- [vLLM Python Backend](vllm-python-backend.md) - AsyncLLMEngine-based backend
233+
- [Backends Guide](backends.md) - Overview of all backends
234+
- [vLLM Engine Arguments](https://docs.vllm.ai/en/stable/configuration/engine_args/) - Full configuration options
235+
- [vLLM LLM Class](https://docs.vllm.ai/en/stable/offline_inference/llm.html) - Underlying API documentation

src/guidellm/backends/openai/http.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ class OpenAIHTTPBackendArgs(BackendArgs):
8686
api_key: SecretStr | None = Field(
8787
default=None,
8888
description="HTTP Bearer token API key for authentication to server",
89-
examples=["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"],
89+
examples=["sk-your-api-key-here"],
9090
)
9191
api_routes: dict[str, str] = Field(
9292
default_factory=dict,

src/guidellm/backends/vllm_python/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@
55
GenerationResponse from vLLM output.
66
"""
77

8+
from .offline import VLLMOfflineBackend
89
from .vllm import VLLMPythonBackend
910
from .vllm_response import VLLMResponseHandler
1011

11-
__all__ = ["VLLMPythonBackend", "VLLMResponseHandler"]
12+
__all__ = ["VLLMPythonBackend", "VLLMOfflineBackend", "VLLMResponseHandler"]

0 commit comments

Comments
 (0)