Skip to content

[None][fix] Support custom_tokenizer in KvCacheAwareRouter for disagg serving - #12990

Merged
longlee0622 merged 1 commit into
NVIDIA:mainfrom
lishicheng1996-nv:fix/disagg-router-custom-tokenizer-main
Apr 19, 2026
Merged

[None][fix] Support custom_tokenizer in KvCacheAwareRouter for disagg serving#12990
longlee0622 merged 1 commit into
NVIDIA:mainfrom
lishicheng1996-nv:fix/disagg-router-custom-tokenizer-main

Conversation

@lishicheng1996-nv

@lishicheng1996-nv lishicheng1996-nv commented Apr 13, 2026

Copy link
Copy Markdown
Collaborator

Summary

The KvCacheAwareRouter needs to tokenize incoming ChatCompletionRequests to compute block hashes for cache-aware routing. Models like DeepSeek-V3.2 use a custom tokenizer whose HF tokenizer lacks chat_template, causing apply_chat_template to fail.

Changes

  • router.py: Add custom_tokenizer parameter to KvCacheAwareRouter (passed via router_args in disagg server config). Resolve aliases using TOKENIZER_ALIASES from llm_args.py. Load custom tokenizer via from_pretrained. Handle apply_chat_template returning string instead of token IDs (some custom tokenizers ignore tokenize=True).
  • llm_args.py: Use existing module-level TOKENIZER_ALIASES in _setup_tokenizer (remove local duplicate).

Usage

In disagg server config:

context_servers:
  router:
    type: kv_cache_aware
    args:
      custom_tokenizer: deepseek_v32

Test plan

  • Tested on GB200 and GB300 with DeepSeek-V3.2-FP4-v2, disagg 1P1D (DEP4+TEP8)
  • Without fix: ValueError: chat_template is not set → 100% request failures
  • With fix: 100% success, kv_cache_aware router works correctly with custom tokenizer

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added support for custom tokenizers in the serving router configuration.
    • Enabled short aliases for built-in tokenizers (e.g., deepseek_v32, glm_moe_dsa).
  • Bug Fixes

    • Improved tokenizer output handling to ensure consistent token ID conversion in chat requests.

@coderabbitai

coderabbitai Bot commented Apr 13, 2026

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

The changes add support for custom tokenizers to the routing layer by introducing an optional custom_tokenizer parameter to KvCacheAwareRouter, which resolves tokenizer aliases defined in llmapi, and modifies tokenization logic to handle both string and token ID outputs from chat templates.

Changes

Cohort / File(s) Summary
Tokenizer Configuration
tensorrt_llm/llmapi/llm_args.py
Relocated TOKENIZER_ALIASES constant to a new position after Nvfp4Backend definition; added explanatory comment in BaseLlmArgs.validate_and_init_tokenizer() for alias resolution logic.
Router Tokenizer Support
tensorrt_llm/serve/router.py
Added optional custom_tokenizer parameter to KvCacheAwareRouter.__init__; updated _get_tokenizer to resolve custom tokenizers via TOKENIZER_ALIASES and dynamically import them; modified _tokenize to handle string outputs from apply_chat_template by encoding them to token IDs.

Sequence Diagram(s)

sequenceDiagram
    participant Router as KvCacheAwareRouter
    participant Aliases as TOKENIZER_ALIASES
    participant Importer as Dynamic Importer
    participant Tokenizer as Custom Tokenizer Class
    
    Router->>Router: __init__(custom_tokenizer)
    Router->>Router: store custom_tokenizer
    Router->>Router: _get_tokenizer()
    alt custom_tokenizer is set
        Router->>Aliases: lookup custom_tokenizer
        Aliases-->>Router: resolved class path
        Router->>Importer: dynamically import class
        Importer-->>Router: tokenizer class
        Router->>Tokenizer: from_pretrained(model)
        Tokenizer-->>Router: tokenizer instance
    else
        Router->>Router: use AutoTokenizer.from_pretrained()
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 20.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the main change: adding support for custom_tokenizer in KvCacheAwareRouter for disagg serving, which is the primary objective of the PR.
Description check ✅ Passed The PR description includes a clear summary of the problem, detailed changes to both files, usage example, and comprehensive test results, covering all essential template sections.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@tensorrt_llm/serve/router.py`:
- Around line 659-668: The dynamic custom-tokenizer import block (using
self._custom_tokenizer, TOKENIZER_ALIASES, tokenizer_path, module_path,
class_name, tokenizer_class, and assigning into self._tokenizers[model]) must be
wrapped in a try/except that catches errors from rsplit, import_module, and
getattr and raises a clear, deterministic configuration error (instead of
bubbling raw exceptions); mirror the pattern used in
tensorrt_llm/llmapi/llm_args.py and
tensorrt_llm/serve/scripts/backend_request_func.py: attempt to resolve
tokenizer_path and instantiate via tokenizer_class.from_pretrained(model) in the
try, and on exception raise a concise ValueError or custom config error with a
message that includes the invalid alias/import/class name and the original
exception message to aid diagnostics, while leaving the
AutoTokenizer.from_pretrained fallback branch unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 04cc2cf7-9a1c-4168-8b52-9ef56b13bb20

📥 Commits

Reviewing files that changed from the base of the PR and between f8edae4 and cf35b05.

📒 Files selected for processing (2)
  • tensorrt_llm/llmapi/llm_args.py
  • tensorrt_llm/serve/router.py

Comment thread tensorrt_llm/serve/router.py Outdated
@lishicheng1996-nv
lishicheng1996-nv force-pushed the fix/disagg-router-custom-tokenizer-main branch from cf35b05 to 8d8bd50 Compare April 13, 2026 08:23
@svc-trtllm-gh-bot svc-trtllm-gh-bot added the Community want to contribute PRs initiated from Community label Apr 13, 2026
@lishicheng1996-nv
lishicheng1996-nv force-pushed the fix/disagg-router-custom-tokenizer-main branch from 8d8bd50 to ee2a484 Compare April 14, 2026 09:23
@lishicheng1996-nv

Copy link
Copy Markdown
Collaborator Author

/bot run

@longlee0622
longlee0622 force-pushed the fix/disagg-router-custom-tokenizer-main branch from ee2a484 to 97cc478 Compare April 15, 2026 01:21
@longlee0622

Copy link
Copy Markdown
Collaborator

/bot run

@longlee0622
longlee0622 enabled auto-merge (squash) April 15, 2026 01:21
@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #43316 [ run ] triggered by Bot. Commit: 97cc478 Link to invocation

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #43316 [ run ] completed with state SUCCESS. Commit: 97cc478
/LLM/main/L0_MergeRequest_PR pipeline #33858 completed with status: 'FAILURE'

CI Report

⚠️ Action Required:

  • Please check the failed tests and fix your PR
  • If you cannot view the failures, ask the CI triggerer to share details
  • Once fixed, request an NVIDIA team member to trigger CI again

Link to invocation

@longlee0622
longlee0622 force-pushed the fix/disagg-router-custom-tokenizer-main branch from 97cc478 to fcf570a Compare April 15, 2026 03:46
@longlee0622

Copy link
Copy Markdown
Collaborator

/bot run

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #43371 [ run ] triggered by Bot. Commit: fcf570a Link to invocation

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #43371 [ run ] completed with state FAILURE. Commit: fcf570a
/LLM/main/L0_MergeRequest_PR pipeline #33906 completed with status: 'FAILURE'

CI Report

⚠️ Action Required:

  • Please check the failed tests and fix your PR
  • If you cannot view the failures, ask the CI triggerer to share details
  • Once fixed, request an NVIDIA team member to trigger CI again

Link to invocation

@longlee0622

Copy link
Copy Markdown
Collaborator

/bot run --disable-fail-fast

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #43397 [ run ] triggered by Bot. Commit: fcf570a Link to invocation

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #43397 [ run ] completed with state SUCCESS. Commit: fcf570a
/LLM/main/L0_MergeRequest_PR pipeline #33931 completed with status: 'FAILURE'

CI Report

⚠️ Action Required:

  • Please check the failed tests and fix your PR
  • If you cannot view the failures, ask the CI triggerer to share details
  • Once fixed, request an NVIDIA team member to trigger CI again

Link to invocation

@longlee0622

Copy link
Copy Markdown
Collaborator

/bot run --disable-fail-fast

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #43630 [ run ] triggered by Bot. Commit: fcf570a Link to invocation

@longlee0622
longlee0622 force-pushed the fix/disagg-router-custom-tokenizer-main branch from fcf570a to e0eec5b Compare April 16, 2026 04:59
@longlee0622

Copy link
Copy Markdown
Collaborator

/bot run --disable-fail-fast

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #43649 [ run ] triggered by Bot. Commit: e0eec5b Link to invocation

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #43649 [ run ] completed with state FAILURE. Commit: e0eec5b
/LLM/main/L0_MergeRequest_PR pipeline #34137 completed with status: 'FAILURE'

CI Report

⚠️ Action Required:

  • Please check the failed tests and fix your PR
  • If you cannot view the failures, ask the CI triggerer to share details
  • Once fixed, request an NVIDIA team member to trigger CI again

Link to invocation

… serving

The KvCacheAwareRouter needs to tokenize incoming ChatCompletionRequests
to compute block hashes for cache-aware routing. Models like
DeepSeek-V3.2 use a custom tokenizer whose HF tokenizer lacks a
chat_template, causing apply_chat_template to fail.

Add custom_tokenizer support to KvCacheAwareRouter:
- Accept custom_tokenizer parameter (e.g. 'deepseek_v32') passed via
  router_args in the disagg server config
- Load custom tokenizer via load_custom_tokenizer from tokenizer module
- Handle apply_chat_template returning a string instead of token IDs
  (some custom tokenizers ignore the tokenize=True flag)

Signed-off-by: Shicheng Li <shicli@nvidia.com>
@longlee0622
longlee0622 force-pushed the fix/disagg-router-custom-tokenizer-main branch from e0eec5b to 4ab90e5 Compare April 16, 2026 10:31
@longlee0622

Copy link
Copy Markdown
Collaborator

/bot run --disable-fail-fast

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #43762 [ run ] triggered by Bot. Commit: 4ab90e5 Link to invocation

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #43762 [ run ] completed with state SUCCESS. Commit: 4ab90e5
/LLM/main/L0_MergeRequest_PR pipeline #34243 completed with status: 'FAILURE'

CI Report

⚠️ Action Required:

  • Please check the failed tests and fix your PR
  • If you cannot view the failures, ask the CI triggerer to share details
  • Once fixed, request an NVIDIA team member to trigger CI again

Link to invocation

@longlee0622

Copy link
Copy Markdown
Collaborator

/bot run --disable-fail-fast

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #44007 [ run ] triggered by Bot. Commit: 4ab90e5 Link to invocation

@longlee0622

Copy link
Copy Markdown
Collaborator

/bot run --disable-fail-fast

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #44101 [ run ] triggered by Bot. Commit: 4ab90e5 Link to invocation

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #44101 [ run ] completed with state SUCCESS. Commit: 4ab90e5
/LLM/main/L0_MergeRequest_PR pipeline #34528 completed with status: 'FAILURE'

CI Report

⚠️ Action Required:

  • Please check the failed tests and fix your PR
  • If you cannot view the failures, ask the CI triggerer to share details
  • Once fixed, request an NVIDIA team member to trigger CI again

Link to invocation

@longlee0622

Copy link
Copy Markdown
Collaborator

/bot run --disable-fail-fast

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #44139 [ run ] triggered by Bot. Commit: 4ab90e5 Link to invocation

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #44139 [ run ] completed with state SUCCESS. Commit: 4ab90e5
/LLM/main/L0_MergeRequest_PR pipeline #34566 completed with status: 'SUCCESS'

CI Report

Link to invocation

@longlee0622
longlee0622 merged commit 137497d into NVIDIA:main Apr 19, 2026
5 checks passed
@lishicheng1996-nv
lishicheng1996-nv deleted the fix/disagg-router-custom-tokenizer-main branch April 27, 2026 11:36
nv-yna added a commit to nv-yna/TensorRT-LLM that referenced this pull request Apr 28, 2026
Mirror the change made on `main` in PR NVIDIA#12990 ("Support custom_tokenizer in
KvCacheAwareRouter for disagg serving"), which moved TOKENIZER_ALIASES from
a method-local variable inside `validate_and_init_tokenizer` to a top-level
module constant. This makes the dict importable by external code that
needs to resolve the same short aliases — for example, the Dynamo TRT-LLM
worker (`dynamo.trtllm.workers.llm_worker`, github.com/ai-dynamo/dynamo
PR NVIDIA#8079) does:

    from tensorrt_llm.llmapi.llm_args import TOKENIZER_ALIASES

so it can construct the V4 tokenizer ahead of LLM() init (Dynamo needs the
tokenizer object early to populate SamplingParams defaults and build its
logits processor). Without the lift, that import fails at module load time
with `ImportError: cannot import name 'TOKENIZER_ALIASES'` and the worker
crash-loops.

Difference vs PR NVIDIA#12990 on main: the dict here also includes
'deepseek_v4' → DeepseekV4Tokenizer, since DeepSeek-V4 lives on this
branch and isn't on main yet.

The function body stays behavior-equivalent — `validate_and_init_tokenizer`
now references the module-level constant instead of redefining its own
copy. No semantic change for existing callers.

Signed-off-by: Yuewei Na <nv-yna@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Community want to contribute PRs initiated from Community

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants