[Docs] Add Qwen2.5-VL guide for the TRT-LLM PyTorch backend, deprecate Llava1.5 guide - #169
Conversation
Add Popular_Models_Guide/Qwen2.5-VL/qwen2_5_vl_trtllm_guide.md, documenting how to serve a multimodal (vision) model on Triton via the TensorRT-LLM PyTorch backend through the llmapi backend. No engine build is required. Also add a deprecation banner to the Llava1.5 TensorRT-LLM guide, whose prebuilt-engine multimodal path is end-of-life as of TensorRT-LLM v1.2. The multimodal image_url input and triton_config.multimodal opt-in used by the new guide are added by NVIDIA/TensorRT-LLM#18381, which is not yet merged; the guide states this prominently. Signed-off-by: Faradawn Yang <73060648+faradawn@users.noreply.github.com>
all_models/llmapi/ holds exactly one model directory, so it can be used as a Triton model repository directly instead of copying files into a new one. Give the concrete clone and model.yaml commands, and add a curl example with the response it returns. Signed-off-by: Faradawn Yang <73060648+faradawn@users.noreply.github.com>
…rch-backend-guide
The backend now accepts only http(s) URLs and inline data URIs; local filesystem paths and file:// are rejected because the input is client-controlled. Document that and drop the local-path example. Signed-off-by: Faradawn Yang <73060648+faradawn@users.noreply.github.com>
The backend rejects local paths, file:// and data: URIs, so document the http(s)-only scope and drop the data-URI examples. Signed-off-by: Faradawn Yang <73060648+faradawn@users.noreply.github.com>
The guide claimed validation on TensorRT-LLM 1.2.1, but following it verbatim
on nvcr.io/nvidia/tritonserver:26.07-trtllm-python-py3 -- the newest published
-trtllm-python-py3 tag -- fails every request that carries an image:
Error generating request: cannot import name
'async_build_multimodal_prompt' from 'tensorrt_llm.inputs'
The backend files readers clone call `async_build_multimodal_prompt`, which
NVIDIA/TensorRT-LLM#18381 adds to `tensorrt_llm/inputs/utils.py`. That module
ships inside the wheel, not in the `triton_backend/` tree, so on a 1.2.1
container the caller is present and the callee never is. The server still
starts, still logs `multimodal input enabled`, and still answers text-only
prompts, so the deployment looks healthy right up until the first image.
Add a "Patching model.py for TensorRT-LLM 1.2.1" section carrying the
replacement method and the call-site diff, gated behind a note to skip it once
a container ships with #18381 in it. Say in the validation table that 1.2.1
needs that patch, and record the torch build.
Also fix three things found while testing:
- The multiple-images example passed `/workspace/images/second.jpg`, a local
path the guide's own "Allowed scope of access" section says is rejected.
That example could only ever error. Use two live http URLs and show the
real two-image answer.
- Show the actual rejection and connection-failure responses, including the
`ssl:default [Name or service not known]` tail that was trimmed, as JSON
response bodies rather than log lines.
- Add troubleshooting rows for the ImportError and for a rejected scheme.
Verified on 1x B200 with Qwen/Qwen2.5-VL-3B-Instruct: single image returns the
answer this guide quotes, two images are described in order, and the rejection
and unreachable-host paths surface as errors rather than silently degrading to
text-only. Checked by applying the patch text extracted from this file to a
fresh clone, so what is documented is what was run.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…our files
Follow-up to the previous commit, which described the model.py change but left
the reader to make it by hand. model.py is ~790 lines, and splicing a 40-line
method into the right class at the right indentation is a reliable way to end up
with a broken model repository.
Ship the edit as trtllm_121_compat.py next to the guide instead, invoked in one
command. This is how this directory already works: the Llava1.5 guide being
deprecated here ships multi_modal_client.py beside it, and Llama2 ships
deploy_trtllm_llama.sh.
The script is defensive, because it edits a file the reader did not write:
it is idempotent, it refuses to write source that does not parse, and if the
call it targets is absent it explains that #18381 has probably merged and gives
the one-line import check to confirm, rather than corrupting the checkout.
The guide keeps the explanation -- the call-site diff and a table mapping each
1.3 API onto the 1.2.1 equivalent -- so a reader can still see what changes and
why, without having to type it.
Separately, replace the full clone with a blobless, LFS-skipped sparse checkout:
GIT_LFS_SKIP_SMUDGE=1 git clone --depth 1 --filter=blob:none --sparse ...
git -C ... sparse-checkout set triton_backend/all_models/llmapi
Four seconds and 9.1 MB, against roughly 900 MB of Git LFS payload for four
small text files.
Also state plainly that 1.2.1 is the standing target: every published
-trtllm-python-py3 image ships it, so #18381 merging upstream does not remove
the need for this patch. Only a new container image does.
Verified end to end on 1x B200 by running the guide's own commands, including
the shipped script against a fresh sparse clone with nothing hand-edited:
single image returns the quoted answer, two images are described in order, a
rejected scheme and an unreachable host both surface as errors.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…nd files
The guide cloned the #18381 branch, which targets TensorRT-LLM 1.3, and then
patched it back down to work against the 1.2.1 wheel in the container. That is
backwards: it carried 358 lines of difference from v1.2.1, of which only ~30 is
the image feature and the rest is unrelated 1.3 drift running against a 1.2.1
runtime.
Start from the v1.2.1 tag instead, which is exactly the TensorRT-LLM installed
in nvcr.io/nvidia/tritonserver:26.07-trtllm-python-py3, and add the image input
on top. That is 109 lines on a base that matches the wheel.
Two consequences:
- The guide no longer depends on a personal fork or an unmerged pull request.
Everything comes from the official NVIDIA v1.2.1 tag plus two files shipped
here, following the convention of the Llava1.5 guide next door.
- There is nothing for the reader to patch. model.py and config.pbtxt are
provided; helpers.py comes from v1.2.1 unchanged; model.yaml is written in
the guide. Copy two files instead of editing an 800-line one.
model.py carries a provenance header naming its v1.2.1 source, and
scripts that regenerate it are described in the guide.
Also rewrite the guide as plain steps -- container, openai, model repository,
serve, request -- following the structure of llava_trtllm_guide.md, and drop
the running commentary about what does not work. 480 lines to 231.
Verified on 1x B200 with Qwen/Qwen2.5-VL-3B-Instruct by running the guide's
commands as written: single image returns the quoted answer, two images are
described in order, a local path and an unreachable host both surface errors,
and text-only requests still work.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The header ended with "Regenerate with tutorials/Popular_Models_Guide/ Qwen2.5-VL, see the guide", which pointed at nothing: no generator is shipped and the guide does not describe one. model.py is a plain file to copy, and that is the whole intent. Replace that line with the two-command diff against the stock v1.2.1 file, and name the four additions, so a reader can audit what changed without needing any tooling from us. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Cut the framing that does not help someone deploying the model: the comparison with the deprecated engine-build path, the note that this supersedes the Llava1.5 guide, the tested-configuration paragraph, the MPI_ERR_SPAWN explanation, and the troubleshooting and references sections. Say only that the guide uses 26.07, which is the newest -trtllm-python-py3 tag on NGC. Reduce the openai section to why and how, one line each. NVIDIA/TensorRT-LLM#18381 has merged, so describe the two provided files by what they are rather than by a pending pull request: the 26.07 container ships TensorRT-LLM v1.2.1, whose llmapi backend has no image input, and these two files add it for that version, adapted from main. Once a container ships v1.3.0 or newer, take model.py and config.pbtxt from main and skip both. 231 lines to 198. Re-verified end to end on 1x B200 after the trim. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Drop the claim that 26.07 is the newest tag on NGC, which would go stale on the next release; name the container and leave it there. Drop the sentence about where the two provided files were adapted from, keeping only what a reader acts on: once a Triton container ships TensorRT-LLM v1.3.0, copy model.py and config.pbtxt from main and skip them. Drop the rationale behind the http(s) restriction and keep the rule itself. Prose only; no command changed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
| for config_key, (output_name, extractor) in output_fields.items(): | ||
| if output_config[config_key]: | ||
| tensor_data = [ | ||
| str(extractor(output)) for output in request_output.outputs | ||
| ] | ||
| response.append( | ||
| pb_utils.Tensor(output_name, | ||
| np.asarray(tensor_data, dtype=np.object_))) |
There was a problem hiding this comment.
Optional numeric outputs are constructed with string or object NumPy dtypes even though config.pbtxt declares them as TYPE_FP32, TYPE_INT32, or TYPE_INT64. For example, requesting return_cumulative_logprob emits an object/string tensor for a TYPE_FP32 output. The performance metrics have the same problem because they use self.output_dtype, which comes from the TYPE_STRING text_output configuration. Triton can therefore reject these responses instead of returning the requested metrics. Construct each tensor with the dtype declared for that output.
| > [!WARNING] | ||
| > **Deprecated.** This guide describes the prebuilt-TensorRT-engine multimodal | ||
| > path (`tensorrtllm_backend`'s `all_models/multimodal`), which TensorRT-LLM has | ||
| > declared end-of-life as of TensorRT-LLM v1.2. It is no longer maintained. |
There was a problem hiding this comment.
Deprecation names wrong architecture
The warning says this guide describes tensorrtllm_backend's all_models/multimodal path, but the guide actually builds TensorRT engines itself and serves a tutorial-local repository containing custom Python vision and wrapper models. This gives readers an inaccurate explanation of which deployment architecture reached end of life. Please describe the actual manual-engine, custom-repository path being deprecated or cite the precise upstream component that applies to it.
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
| --branch v1.2.1 https://github.com/NVIDIA/TensorRT-LLM.git /workspace/trtllm | ||
| git -C /workspace/trtllm sparse-checkout set triton_backend/all_models/llmapi | ||
|
|
||
| cp -r /workspace/trtllm/triton_backend/all_models/llmapi /workspace/model_repository |
There was a problem hiding this comment.
Repository copy is state-dependent
This command only creates the documented layout when /workspace/model_repository does not already exist. On a rerun or after a partial attempt, cp -r creates model_repository/llmapi/tensorrt_llm, while the following commands expect model_repository/tensorrt_llm and fail. Make the destination state explicit or copy the source directory's contents so readers can safely repeat the tutorial.
Related TRTLLM: NVIDIA/TensorRT-LLM#18381
Related Triton Docs Indexing: triton-inference-server/server#8950
Related issue: triton-inference-server/server#8945
Tested on B200 successfully