Deploying an LLM with Triton and TRT-LLM#
This guide walks through serving a Hugging Face LLM with Triton Inference Server using the TensorRT-LLM PyTorch backend (LLM API). The PyTorch backend serves supported Hugging Face models directly — no TensorRT engine compilation required.
[!NOTE] The legacy TensorRT engine-build workflow (
convert_checkpoint.py+trtllm-buildand theinflight_batcher_llmensemble model layout) is deprecated and is being removed from TensorRT-LLM. This guide uses the modern LLM API / PyTorch backend instead. See the TensorRT-LLM Backend README for the full set of configuration and deployment options.
This guide uses
nvidia/DeepSeek-R1-0528-FP4-V2
as the example model.
Serve the model with Triton#
1. Launch the container#
export RELEASE=26.09
docker run --rm -it --net host --shm-size=2g --ulimit memlock=-1 --gpus all \
-v ~/.cache/huggingface:/root/.cache/huggingface \
nvcr.io/nvidia/tritonserver:${RELEASE}-trtllm-python-py3 bash
Check NGC
for the latest -trtllm-python-py3 tag. For gated models, set your token first:
export HF_TOKEN=hf_...
If the server later fails with ImportError: cannot import name 'PartReasoningText', the container’s openai package is too old — run
pip install -U openai and try again.
2. Get the model repository#
The Triton model repository for the LLM API backend lives in the TensorRT-LLM
repo. Clone the tag matching the tensorrt_llm version in your container:
python3 -c "import tensorrt_llm; print(tensorrt_llm.__version__)" # e.g. 1.2.1
git clone --depth 1 --branch v1.2.1 https://github.com/NVIDIA/TensorRT-LLM.git
Use the version the first command reports as the tag for the second. If you
change RELEASE above, re-run both so the model repository stays in step with
the library in the container.
3. Configure your model#
Edit TensorRT-LLM/triton_backend/all_models/llmapi/tensorrt_llm/1/model.yaml
and set model: to a Hugging Face model ID or a local path:
model: nvidia/DeepSeek-R1-0528-FP4-V2
backend: "pytorch"
tensor_parallel_size: 8
moe_expert_parallel_size: 8
max_seq_len: 4096
max_num_tokens: 8192
kv_cache_config:
free_gpu_memory_fraction: 0.7
triton_config:
max_batch_size: 0
decoupled: False
All keys outside triton_config map directly to the
LLM() constructor arguments.
This is where you configure KV cache, quantization, and parallelism.
4. Launch the server#
Run the launch script from the parent of TensorRT-LLM/. Running it from inside
the cloned folder makes Python import the source tree instead of the installed
package and fails with ModuleNotFoundError: No module named 'tensorrt_llm.bindings':
python3 TensorRT-LLM/triton_backend/scripts/launch_triton_server.py \
--model_repo=TensorRT-LLM/triton_backend/all_models/llmapi/
You should see the following logs once the server is ready:
I0803 18:43:44.778509 1525575 grpc_server.cc:2579] "Started GRPCInferenceService at 0.0.0.0:8001"
I0803 18:43:44.778681 1525575 http_server.cc:4961] "Started HTTPService at 0.0.0.0:8000"
I0803 18:43:44.819624 1525575 http_server.cc:400] "Started Metrics Service at 0.0.0.0:8002"
On an 8x B200 node this configuration takes a few minutes to become ready and uses roughly 143 GiB of each GPU’s 179 GiB, with 81.83 GiB left for the paged KV cache (2,500,608 tokens).
Send an inference request#
generate is a raw completion endpoint and does not apply the model’s chat
template, so format the prompt using the template from the checkpoint’s
tokenizer_config.json:
curl -X POST localhost:8000/v2/models/tensorrt_llm/generate -d '{
"text_input": "<|begin▁of▁sentence|><|User|>How do I count to nine in French?<|Assistant|>",
"sampling_param_max_tokens": 512,
"sampling_param_exclude_input_from_output": true }' | jq
DeepSeek-R1 emits its reasoning in a <think> block before the answer:
<think>
Okay, the user is asking how to count to nine in French. That seems
straightforward—they probably need the French numbers from one to nine.
...
Sampling options are passed as sampling_param_* inputs — see the input
section of
TensorRT-LLM/triton_backend/all_models/llmapi/tensorrt_llm/config.pbtxt for the
full list.
Streaming responses#
Streaming requires decoupled mode. Set it in model.yaml:
triton_config:
max_batch_size: 0
decoupled: True
Then restart the server and use the generate_stream endpoint:
curl -N -X POST localhost:8000/v2/models/tensorrt_llm/generate_stream \
-d '{"text_input": "Count to three:", "sampling_param_max_tokens": 10, "streaming": true}'
Benchmark#
Install the Triton client in the server container and run the backend’s
benchmarking client against the model, with decoupled: False:
pip install "tritonclient[grpc,http]"
python3 TensorRT-LLM/triton_backend/tools/inflight_batcher_llm/benchmark_core_model.py \
--max-input-len 500 \
--tensorrt-llm-model-name tensorrt_llm \
--test-llmapi \
dataset --dataset TensorRT-LLM/triton_backend/tools/dataset/mini_cnn_eval.json \
--tokenizer-dir nvidia/DeepSeek-R1-0528-FP4-V2
[INFO] Warm up for benchmarking.
[INFO] Start benchmarking on 38 prompts.
[INFO] Total Latency: 1694.09 ms
[!NOTE] The shipped
model.yamlsetsmax_batch_size: 0, so the backend serves requests without batching.