Repository navigation
fix(trtllm): tokenize and inject user stop sequences for TRT-LLM requests - #346
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughThis PR implements stop sequence tokenization and injection for TRT-LLM requests across chat and generate request builders. A utility function tokenizes stop sequences into token IDs, which are then injected into the proto request's stop_words field. Tests and utility logic for reasoning parser handling were also added. Changes
Estimated Code Review Effort🎯 3 (Moderate) | ⏱️ ~22 minutes Possibly Related Issues
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 inconclusive)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches🧪 Generate unit tests (beta)
Comment |
Summary of ChangesHello @ppraneth, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request enhances the TRT-LLM request handling within the Harmony pipeline by introducing robust support for user-defined stop sequences. It ensures that custom stop strings provided by users are correctly tokenized upstream and then seamlessly injected into the TRT-LLM generation requests, providing more precise control over model output termination. Highlights
Changelog
Activity
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
Code Review
This pull request correctly implements the tokenization and injection of user-defined stop sequences for TRT-LLM requests. The changes are well-structured, propagating the tokenized sequences through the Harmony pipeline. I've included a couple of suggestions to improve code clarity and conciseness by using more idiomatic Rust iterator patterns. Overall, this is a solid implementation that addresses the issue effectively.
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Fix all issues with AI agents
In `@model_gateway/src/routers/grpc/harmony/builder.rs`:
- Around line 253-254: build_from_responses() is silently dropping user-supplied
stop sequences by hardcoding additional_stop_sequences: vec![]; replicate the
chat-path behavior by extracting and tokenizing the stop sequences from
request.stop (the ResponsesRequest.stop: Option<StringOrArray>) using
extract_and_tokenize_stop_sequences(request.stop.as_ref()) and set
additional_stop_sequences to the result, or if Responses cannot support stops,
validate request.stop and return an explicit error/log; update the function
build_from_responses() to reference extract_and_tokenize_stop_sequences and
populate additional_stop_sequences accordingly (or validate and fail fast).
In `@model_gateway/src/routers/grpc/harmony/stages/request_building.rs`:
- Around line 251-274: The user stop sequences are only added when the internal
Harmony stops exist because the user-stop injection is inside the if let
Some(harmony_stops) guard; move the user stop injection out so it always runs:
keep the loop that pushes internal Harmony stop tokens inside the if let
Some(harmony_stops) block (iterating over harmony_stops and pushing
TokenSequence into req.stop_words), then after that block (outside it) check
prep.harmony_stop_sequences and extend req.stop_words with mapped TokenSequence
entries from each seq, and update the debug logging to report the final
total_stop_count and user_stop_count where appropriate; reference symbols:
harmony_stops, prep.harmony_stop_sequences, req.stop_words, TokenSequence.
CatherineSue
left a comment
There was a problem hiding this comment.
I think the original issues means the regular gRPC. This PR focuses on Harmony pipeline.
CatherineSue
left a comment
There was a problem hiding this comment.
A few notes:
-
Harmony doesn't support user-provided stop strings — this is intentional for now, even for SGLang/vLLM. The Harmony pipeline only injects its own internal stop tokens (
<|return|>,<|call|>). We can revisit later if needed. -
Please continue working on this PR to make it consistent with issue #221. The fix should handle stop sequences at the router level (post-build injection into the proto request) rather than threading a new field through pipeline structs. See how the regular gRPC path and Harmony path already do post-build injection for reference.
-
After making relevant changes, we should turn on relevant unit tests if possible in the CI, or add them. Make sure the stop sequence tokenization and injection logic is covered by tests.
CatherineSue
left a comment
There was a problem hiding this comment.
A few issues with the current state:
-
Dead code in
trtllm_service.rs:extract_stop_words(line 482) takes a request, ignores it, and returnsvec![]. Now that stop sequences are tokenized and injected in
the request building stage, this dead code should be cleaned up — remove the method and replace the call site withlet stop_words = vec![];directly. -
Silent error swallowing:
tokenize_stop_sequencesdrops encoding failures silently via.filter_map(Result::ok). Please add awarn!per failed encoding so we have
visibility in production. -
Remove tests: The 142-line test in
generate/preparation.rsis vestigial — it no longer tests stop sequences after the logic moved to request building. The
MockTokenizeris also duplicated across two files. Please drop both.
|
Hey @ppraneth, thanks for working on this — I appreciate the effort you put in to tackle #221. After reviewing the changes, I have a few concerns I want to share: 1. Leaky abstraction with
|
…ests (#346) Co-authored-by: Chang Su <chang.s.su@oracle.com> Signed-off-by: ppraneth <pranethparuchuri@gmail.com>
Description
Problem
closes #221
TRT-LLM requires stop words as tokenized
TokenSequenceentries (token IDs), unlike SGLang/vLLM which handle stop strings at the client level. Previously, theextract_stop_wordsmethod inTrtllmServiceClientwas a no-op that always returned an empty vec, meaning user-provided stop sequences were silently ignored.Solution Implementation
Stop sequences are now tokenized and injected during the Request Building Stage, right after the proto request is constructed and before it is dispatched. A single helper function handles both tokenization and injection in one step, keeping the logic encapsulated and avoiding leaky abstractions.
Key Changes:
Removed dead code in
grpc_clientextract_stop_wordsmethod fromTrtllmServiceClient— it always returnedvec![]with a comment saying "the router should handle this".vec![]directly with a comment explaining that stop words are injected by the router post-build.Single-responsibility helper:
inject_trtllm_stop_wordsutils::inject_trtllm_stop_words(&mut req, tokenizer, stop)that takes a mutable reference to the TRT-LLM request, tokenizes each stop string, and pushesTokenSequenceentries directly — no intermediate allocations or conversions needed at the call site.Request Building Stages
inject_trtllm_stop_wordsafter constructing the proto request, gated onProtoGenerateRequest::Trtllmand the presence of a tokenizer + stop sequences.E2E Tests
test_stop_sequencesandtest_stop_sequences_streamto the chat completions e2e test suite, verifying that stop sequences cause generation to halt (both non-streaming and streaming) and that the stop token does not appear in the output.Verification
cargo clippy --all-targets --all-features -- -D warningspassescargo +nightly fmtpassesChecklist
cargo +nightly fmtpassescargo clippy --all-targets --all-features -- -D warningspasses