uncloseai.
How We Run Inference
How we run inference
This section is optional. This is only if you wanted to try to contribute idle GPU time to the project or if you wanted to reproduce everything in your own cluster.
vLLM Setup — Hermes (3090)
We use vLLM to run models, generally with full f16 safetensors. We make sure to use a virtualenv to hold the dependencies.
Note: For Hermes, we use an FP8 quant by adamo1139 (adamo1139/Hermes-3-Llama-3.1-8B-FP8-Dynamic), which is optimized for 4090 and 3090 GPUs.
Tool Calling: The --enable-auto-tool-choice and --tool-call-parser hermes flags are required for Hermes 3 to support function calling via the OpenAI-compatible API. Without these flags, tool calling requests will fail.
GPU Memory: The --max-num-seqs 32 and --gpu-memory-utilization 0.85 flags cap concurrent sequences and leave VRAM headroom. Without these, vLLM defaults to 256 concurrent sequences, which OOMs during sampler warmup on a 24 GiB card at 82k context (error: torch.OutOfMemoryError: CUDA out of memory ... when warming up sampler with 256 dummy requests). 32 is a sensible concurrency for an 8B model on a single 3090.
Stand up a replica cluster on a new domain.
sudo apt-get install gcc python3.12-dev python3.12-venv
cd ~
python3 -m venv env
source env/bin/activate
pip install vllm
python -m vllm.entrypoints.openai.api_server \
--model adamo1139/Hermes-3-Llama-3.1-8B-FP8-Dynamic \
--host 0.0.0.0 --port 18888 \
--max-model-len 82000 \
--max-num-seqs 32 \
--gpu-memory-utilization 0.85 \
--enable-auto-tool-choice \
--tool-call-parser hermes
vLLM Setup — Qwen (4090)
TL;DR: On a single RTX 3090 or 4090 (24 GiB VRAM), you can run the INT4 quant of Qwen3.6-27B with fp8 KV cache to fit a 64k token context window.
Qwen3.6-27B is the multimodal flagship from the Qwen team — vision + text in a single model (capable of OCR, document parsing, screenshot reading, charts). We run it on a single RTX 4090 (24 GiB VRAM) via vLLM.
Model choice: We serve Lorbus/Qwen3.6-27B-int4-AutoRound — 17.45 GiB weights including the MTP draft layer and vision encoder. The AWQ alternative (cyankiwi/Qwen3.6-27B-AWQ-INT4) is heavier at 19.04 GiB on disk; AutoRound is the lighter pick for a 24 GiB card.
fp8 KV cache: --kv-cache-dtype fp8 halves KV memory on Ada Lovelace (sm_89, RTX 4090). Critical for fitting 64k context with a 27B model on a 24 GiB card. Quality cost is near zero for chat — KV in fp8 alongside already-INT4 weights stays far below the quant noise floor.
GPU memory budget: --gpu-memory-utilization 0.95 leaves just enough KV pool (~2.3 GiB) for one active 64k sequence. 0.92 reports only 1.62 GiB pool because vit (vision transformer) warmup eats more activation memory than expected. 0.95 works because vLLM accounts for actual peak measured during warmup.
Tool calling: Lorbus's chat template emits the qwen3_coder tool format (<tool_call><function=...><parameter=...>). Use --tool-call-parser qwen3_coder so vLLM parses these into proper OpenAI tool_calls JSON. Without it, agent frameworks like hermes-agent and goose can't drive tool use against the endpoint.
Context window: --max-model-len 65536 matches the 64k minimum that hermes-agent and similar frameworks require. vLLM mixes prompt lengths in continuous batching — short chat requests (8k each, ~0.29 GiB KV with fp8) still squeeze alongside one long 64k sequence (2.3 GiB).
Salt state + pillar (foxhop-states, foxhop-pillar) drive the deployment; the systemd unit below is the rendered ExecStart.
sudo apt-get install gcc python3.12-dev python3.12-venv ninja-build
cd ~
python3 -m venv env
source env/bin/activate
pip install vllm
vllm serve Lorbus/Qwen3.6-27B-int4-AutoRound \
--host 0.0.0.0 --port 18888 \
--max-model-len 65536 \
--max-num-seqs 16 \
--gpu-memory-utilization 0.95 \
--kv-cache-dtype fp8 \
--dtype auto \
--quantization auto_round \
--enable-prefix-caching \
--enable-auto-tool-choice \
--tool-call-parser qwen3_coder
Why ninja-build: FlashInfer (vLLM's CUDA sampling backend) JIT-compiles its top-k/top-p kernels on first request and shells out to ninja. The pip wheel doesn't bundle the binary, so without ninja-build installed the engine crashes at startup with FileNotFoundError: 'ninja'.
Proxy Setup
If you want to see how we setup the proxy, check out /etc/caddy/Caddyfile
hermes.ai.unturf.com {
reverse_proxy <removed>:18888
log {
output file /var/log/caddy/hermes.ai.unturf.com.log {
roll_size 50mb
roll_keep 5
}
}
tls {
on_demand
}
}
qwen.ai.unturf.com {
reverse_proxy <removed>:18889
log {
output file /var/log/caddy/qwen.ai.unturf.com.log {
roll_size 50mb
roll_keep 5
}
}
tls {
on_demand
}
}
speech.ai.unturf.com {
reverse_proxy <removed>:8000
log {
output file /var/log/caddy/speech.ai.unturf.com.log {
roll_size 50mb
roll_keep 5
}
}
tls {
on_demand
}
}
Model Discovery
vLLM provides an OpenAI-compatible API with built-in documentation. You can discover available models and explore the full API using these endpoints:
Swagger Documentation
Access the interactive API docs at the /docs endpoint:
hermes.ai.unturf.com/docs - Hermes endpoint Swagger docs
qwen.ai.unturf.com/docs - Qwen endpoint Swagger docs
The Swagger UI lets you explore all available endpoints, see request/response schemas, and test API calls directly in your browser.
Model Discovery
To get the current model ID being hosted, query the /v1/models endpoint:
- hermes.ai.unturf.com/v1/models - Hermes models
- qwen.ai.unturf.com/v1/models - Qwen models (vision + text)
Or via curl:
curl https://hermes.ai.unturf.com/v1/models
curl https://qwen.ai.unturf.com/v1/models
Example response:
{
"object": "list",
"data": [
{
"id": "adamo1139/Hermes-3-Llama-3.1-8B-FP8-Dynamic",
"object": "model",
"created": 1735689600,
"owned_by": "vllm",
"root": "adamo1139/Hermes-3-Llama-3.1-8B-FP8-Dynamic",
"max_model_len": 82000
}
]
}
The id field contains the model name you should use in your API calls. The max_model_len field tells you the maximum context length supported.
Tip: Always query /v1/models programmatically rather than hardcoding model names. This ensures your code works even when models are updated or swapped.
Rate Limiting
Rate limiting is configured based on client IP address: 3 requests per second per IP per endpoint.
Next Steps
Ready to add text-to-speech to your application?