Repository navigation
[#19510][feat] Add native Qwen3 reranking support #19550
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
anurags25
wants to merge
23
commits into
NVIDIA:main
Choose a base branch
from
anurags25:anurag/feat/qwen3-reranker
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+2,113
−104
Open
Changes from all commits
Commits
Show all changes
23 commits
Select commit
Hold shift + click to select a range
833b35f
Add native reranking support with Qwen3
anurags25 48f55ed
PR feedback
anurags25 4a64420
Truncate input to max_num_tokens
anurags25 351fa14
PR feedback
anurags25 b673539
Refactor _reject_embedding_extra_model_inputs
anurags25 640bf94
PR feedback
anurags25 aa933a8
Merge branch 'main' into anurag/feat/qwen3-reranker
anurags25 2a36938
Merge branch 'main' into anurag/feat/qwen3-reranker
anurags25 507c9e7
PR feedback
anurags25 4746116
Merge branch 'main' into anurag/feat/qwen3-reranker
anurags25 1a8d282
Merge branch 'main' into anurag/feat/qwen3-reranker
anurags25 aec0db4
Merge main and resolve Qwen3 reranker conflicts
allisonlim-nv 954158a
Merge main and resolve reranker integration conflicts
allisonlim-nv 6e032cf
fix: forward graceful shutdown timeout to rerank server
allisonlim-nv 8d8fc04
Merge branch 'main' into anurag/feat/qwen3-reranker
allisonlim-nv 0ad137e
style: format rerank server construction
allisonlim-nv 4ffd9a3
fix: reject oversized rerank requests before tokenization
allisonlim-nv 7550663
Merge main and resolve reranker server shutdown conflict
allisonlim-nv a54d108
test: construct reranker servers through isolated serve environment
allisonlim-nv 06f2022
[None][fix] Regenerate disagg server config schema for RERANK role
allisonlim-nv 537df01
Merge branch 'main' into anurag/feat/qwen3-reranker
allisonlim-nv f3c41dc
style: format reranker tests with pinned ruff
allisonlim-nv 119a7e7
Merge branch 'main' into anurag/feat/qwen3-reranker
allisonlim-nv File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,186 @@ | ||
| # Reranking | ||
|
|
||
| `trtllm-serve rerank` serves text reranking models through HTTP endpoints with | ||
| native dynamic batching. For each request, the server pairs the query with every | ||
| candidate document, evaluates the pairs in the encode-only path, and returns | ||
| the documents ordered by relevance. | ||
|
|
||
| The encode-only path performs one forward pass per batch, with no KV cache, | ||
| sampler, or decode loop. Concurrent query-document pairs are coalesced into | ||
| larger GPU batches. | ||
|
|
||
| ## Quick start | ||
|
|
||
| Launch a server with a [supported reranker checkpoint](#supported-model-architectures): | ||
|
|
||
| ```bash | ||
| trtllm-serve rerank <hf_model_or_path> \ | ||
| --max_batch_size 32 \ | ||
| --max_queue_delay 0.005 \ | ||
| --max_queue_size 2048 \ | ||
| --host 0.0.0.0 --port 8000 | ||
| ``` | ||
|
|
||
| For example, the Qwen3-Reranker family is supported: | ||
|
|
||
| ```bash | ||
| trtllm-serve rerank Qwen/Qwen3-Reranker-0.6B \ | ||
| --max_batch_size 32 \ | ||
| --max_queue_delay 0.005 \ | ||
| --host 0.0.0.0 --port 8000 | ||
| ``` | ||
|
|
||
| The server exposes the following routes: | ||
|
|
||
| | Route | Compatibility | | ||
| |---|---| | ||
| | `POST /rerank` | Jina/vLLM-style request and response | | ||
| | `POST /v1/rerank` | Alias of `/rerank` | | ||
| | `POST /v2/rerank` | Cohere v2-compatible request and response | | ||
|
|
||
| Send a request with `curl`: | ||
|
|
||
| ```bash | ||
| curl http://localhost:8000/v1/rerank \ | ||
| -H "Content-Type: application/json" \ | ||
| -d '{ | ||
| "model": "Qwen/Qwen3-Reranker-0.6B", | ||
| "query": "What is the capital of China?", | ||
| "documents": [ | ||
| "The capital of China is Beijing.", | ||
| "Bananas grow in tropical climates." | ||
| ], | ||
| "top_n": 1, | ||
| "return_documents": true | ||
| }' | ||
| ``` | ||
|
|
||
| Results are ordered by descending relevance score. `index` always refers to | ||
| the document's position in the original request. | ||
|
|
||
| ```json | ||
| { | ||
| "id": "rerank-...", | ||
| "model": "Qwen/Qwen3-Reranker-0.6B", | ||
| "results": [ | ||
| { | ||
| "index": 0, | ||
| "relevance_score": 0.98, | ||
| "document": {"text": "The capital of China is Beijing."} | ||
| } | ||
| ], | ||
| "usage": {"prompt_tokens": 91, "total_tokens": 91} | ||
| } | ||
| ``` | ||
|
|
||
| ## Request fields | ||
|
|
||
| The two API styles share the query, documents, and result-ordering semantics, | ||
| but differ in a few compatibility fields: | ||
|
|
||
| | Field | `/rerank` and `/v1/rerank` | `/v2/rerank` | | ||
| |---|---|---| | ||
| | `model` | Optional string | Required string | | ||
| | `query` | Required non-empty string | Required non-empty string | | ||
| | `documents` | Non-empty list of strings or `{"text": "..."}` objects | Non-empty list of strings | | ||
| | `top_n` | Optional non-negative integer; `0` returns all results | Optional positive integer | | ||
| | `return_documents` | Optional boolean; defaults to `false` | Not part of the v2 response | | ||
| | `max_tokens_per_doc` | Optional positive integer | Positive integer; defaults to `4096` | | ||
| | `priority` | Not supported | Only `0` is currently supported | | ||
| | `instruction` | Optional TensorRT-LLM extension | Optional TensorRT-LLM extension | | ||
|
|
||
| `max_tokens_per_doc` limits document content, not the complete model input. | ||
| The server preserves the query and any model-specific prompt suffix while | ||
| truncating a document. | ||
|
|
||
| ## Dynamic batching | ||
|
|
||
| The in-server batcher coalesces query-document pairs from concurrent HTTP | ||
| requests before running the encode-only forward pass. | ||
|
|
||
| | `trtllm-serve rerank` flag | Behavior | | ||
| |---|---| | ||
| | `--max_batch_size` | Maximum number of query-document pairs in one forward pass. A full batch is dispatched immediately. | | ||
| | `--max_num_tokens` | Maximum total number of input tokens in one batch. | | ||
| | `--max_queue_delay` | Maximum time, in seconds, that a pair waits for other work to join its batch. | | ||
| | `--max_queue_size` | Maximum number of queued pairs. Additional requests are rejected with HTTP 429. | | ||
|
|
||
| A batch is dispatched when it reaches `--max_batch_size`, adding another pair | ||
| would exceed `--max_num_tokens`, or the queue-delay window expires. Tune batch | ||
| size and delay together for the desired latency-throughput tradeoff. | ||
|
|
||
| ## Scoring contract | ||
|
|
||
| The reranking service expects the model implementation to emit one scalar, | ||
| pre-sigmoid relevance logit for each query-document pair. The server applies a | ||
| numerically stable sigmoid, sorts the resulting probabilities, and selects | ||
| `top_n` when requested. | ||
|
|
||
| The HTTP and batching layers are shared infrastructure. Supporting another | ||
| reranker family also requires model-specific input formatting and a TensorRT-LLM | ||
| architecture that satisfies this scalar-output contract. | ||
|
|
||
| ## Supported model architectures | ||
|
|
||
| The HTTP surface is designed for reranking generally. The model-specific | ||
| preprocessing and scoring implementation currently supports the | ||
| **Qwen3-Reranker family**: | ||
|
|
||
| - `Qwen3-Reranker-0.6B` | ||
| - `Qwen3-Reranker-4B` | ||
| - `Qwen3-Reranker-8B` | ||
|
|
||
| Only unquantized checkpoints are supported. Quantized checkpoints, including | ||
| FP8 and NVFP4, are not supported: the scalar scoring head is derived directly | ||
| from unquantized language-model or tied embedding weights. | ||
|
|
||
| Qwen3-Reranker checkpoints are published as causal language models that score | ||
| the tokens `yes` and `no`. TensorRT-LLM selects `Qwen3ForTextReranking` for | ||
| these checkpoints, reads the token IDs from `1_LogitScore/config.json` when | ||
| present, and derives a one-row scoring head at load time: | ||
|
|
||
| ```text | ||
| W_score = W_yes - W_no | ||
| relevance_logit = hidden_state_last @ W_score | ||
| relevance_score = sigmoid(relevance_logit) | ||
| ``` | ||
|
|
||
| This is mathematically equivalent to the checkpoint's two-token softmax while | ||
| avoiding a projection over the full vocabulary. The Qwen3 input formatter uses | ||
| the model's official query-document prompt. The optional `instruction` field | ||
| replaces its default web-search instruction. | ||
|
|
||
| ## Error handling | ||
|
|
||
|
anurags25 marked this conversation as resolved.
Resolved
|
||
| | Condition | HTTP status | | ||
| |---|---| | ||
| | Invalid request body or unsupported `priority` | 400 | | ||
| | Instruction and query alone exceed the model or batch token limit | 400 | | ||
| | Document count exceeds a positive `--max_queue_size` | 400 | | ||
| | Request queue full | 429 | | ||
| | Model does not return one scalar per pair | 500 | | ||
|
|
||
| Requests exceeding a positive `--max_queue_size` document count are rejected | ||
| before tokenization. Split these into smaller requests; retrying the same | ||
| oversized request will not help. This limit applies to all submitted documents, | ||
| even when `top_n` requests fewer results. | ||
|
|
||
| Over-long documents are truncated to fit the smaller of the model's sequence | ||
| limit and the batch token limit, while preserving the instruction, query, and | ||
| assistant suffix. Reranking responses are unary and non-streaming. | ||
|
|
||
| ## Deployment scope | ||
|
|
||
| - One reranker model is served by each server instance. Generation, embeddings, | ||
| and reranking modes are not mixed in one instance. | ||
| - The reranking command is single-GPU. Tensor, pipeline, and context parallel | ||
| values greater than one in `--config` are rejected at startup. | ||
| - A single worker drives the GPU because the underlying encode executor is not | ||
| safe for concurrent calls. Increase throughput with dynamic batching rather | ||
| than additional in-process workers. | ||
| - To scale across GPUs, run one server replica per GPU and distribute requests | ||
| across the replicas with a load balancer. | ||
|
|
||
| The server uses the same synchronous `llm.encode()` path as other encode-only | ||
| models, with an asynchronous batching layer and reranking HTTP APIs added on | ||
| top. | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.