Skip to content

fix(grpc): router-authoritative string stop sequences for SGLang skip_tokenizer_init workers - #1877

Closed
gongwei-130 wants to merge 1 commit into
mainfrom
fix/sglang-string-stops
Closed

fix(grpc): router-authoritative string stop sequences for SGLang skip_tokenizer_init workers#1877
gongwei-130 wants to merge 1 commit into
mainfrom
fix/sglang-string-stops

Conversation

@gongwei-130

@gongwei-130 gongwei-130 commented Jul 4, 2026

Copy link
Copy Markdown
Collaborator

Summary

SGLang gRPC workers run with skip_tokenizer_init=True (the router owns the tokenizer). The router forwards string stop sequences as-is into the gRPC SamplingParams, and SGLang's SamplingParams.verify() rejects them in that mode:

stop=['.'] is unavailable when skip_tokenizer_init=True
(requires tokenizer to decode tokens to text for matching).

So any request carrying the OpenAI-compatible stop parameter against an SGLang gRPC worker gets a 400. This PR makes the router authoritative for string stops end to end: the 400 is gone, output text is trimmed correctly, finish_reason / matched_stop / Anthropic stop_reason+stop_sequence match what vLLM reports for the same request, and streaming requests abort the worker when the router matches a stop — so multi-token stops no longer over-generate to max_tokens (no inflated usage.completion_tokens, no wasted GPU time).

SGLang-specific: the vLLM servicer forces detokenize=bool(stop), TRT-LLM tokenizes stop words server-side, MLX has no string-stop field.

Design

The router already decodes worker output through a StopSequenceDecoder per request. This PR completes that into full ownership of string stops:

1. Drain string stops from SGLang requests (resolve_sglang_string_stops in common/stages/helpers.rs), called from the chat / completions / messages request-building stages — exactly the paths whose streaming and non-streaming handlers both run a trimming decoder. As an optimization, a stop string that encodes to a single token is forwarded as a stop_token_ids entry so the worker halts immediately (skipped when ignore_eos=true, where SGLang skips all stop_token_ids matching — see Req._check_token_based_finish).

2. Record what matchedStopSequenceDecoder now tracks MatchedStop::Sequence(String) | TokenId(u32) when it stops.

3. Refine response metadata (utils::refine_stop_metadata, applied at all six response sites: chat/completions/messages × streaming/non-streaming):

  • decoder matched a string stop → finish_reason="stop", matched_stop = the original stop string (was: "length" + null);
  • worker halted on a converted single-token stop and reported a numeric token id → mapped back to the user's stop string;
  • EOS and user-provided stop_token_ids pass through unchanged.
    Also gates the streaming Messages stop_reason on an actual string match (a numeric matched_stop is end_turn, not stop_sequence with a null sequence), and removes the completions endpoint's stream-vs-non-stream finish_reason divergence.

4. Streaming early termination — when the router decoder matches a string stop on an SGLang stream (n=1), the loop records usage from the chunk's cumulative counters, emits the final chunks, and breaks without mark_completed(); dropping the stream sends the Abort RPC (AbortOnDropStream). Gated to SGLang streams and actual Sequence matches — vLLM/TRT-LLM paths are untouched.

Deliberately not drained (documented NOTEs at the call sites)

  • Harmony (gpt-oss): no router-side decoder exists there, and injecting a user stop token can truncate before <|return|>/<|call|>, corrupting Harmony parsing. Keeps the pre-existing 400.
  • Native /generate: its streaming path has no decoder, so a cleared stop would stream untrimmed text. Keeps the pre-existing 400.

Known remaining limitations (in the helper docstring)

  • Non-streaming multi-token stops: finish_reason/matched_stop are correct, but the worker still generates to EOS/max_tokens before the response is assembled. Needs early abort in response_collection — follow-up.
  • SentencePiece leading-space tokenization can keep the single-token optimization from firing mid-sentence; correctness holds via the decoder.

Tests

  • resolve_sglang_string_stops: 12 unit tests (single/multi-token, mixed, dedup, empty/unknown, whitespace single-token via a wrapper tokenizer, two distinct single tokens, ignore_eos, missing sampling_params, no tokenizer, non-SGLang untouched)
  • refine_stop_metadata: 5 unit tests
  • StopSequenceDecoder::matched_stop: 2 unit tests
  • Full smg lib suite green; clippy/fmt clean

End-to-end verification (B200, real SGLang gRPC worker)

Same host, same engine image and weights, only the router build swapped:

  • stop=["."] (non-stream) → 200, finish_reason="stop", matched_stop="." (the string, not a token id), text trimmed at the stop
  • multi-token stop (non-stream) → finish_reason="stop", matched_stop=<stop string>, text trimmed exactly before the stop
  • multi-token stop (streaming) → stream terminates at the match with usage.completion_tokens=3 vs 488 for the identical request non-streamed (worker log shows Receive abort request: ...), confirming the Abort path works

This is the same change merged in our production deployment after review and e2e validation.

@github-actions github-actions Bot added grpc gRPC client and router changes model-gateway Model gateway crate changes labels Jul 4, 2026
@coderabbitai

coderabbitai Bot commented Jul 4, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 90187dfb-c5fa-43ad-8196-2814956a5365

📥 Commits

Reviewing files that changed from the base of the PR and between 5348041 and c07b7e9.

📒 Files selected for processing (5)
  • model_gateway/src/routers/grpc/common/stages/helpers.rs
  • model_gateway/src/routers/grpc/regular/stages/chat/request_building.rs
  • model_gateway/src/routers/grpc/regular/stages/completion/request_building.rs
  • model_gateway/src/routers/grpc/regular/stages/generate/request_building.rs
  • model_gateway/src/routers/grpc/regular/stages/messages/request_building.rs

📝 Walkthrough

Summary by CodeRabbit

  • Bug Fixes
    • Improved handling of stop sequences for SGLang requests.
    • Single-token string stops are converted to token IDs when supported.
    • Unsupported, unknown, or multi-token stops continue to be handled safely.
    • Applied consistent behavior across chat, completion, generate, and message requests.
    • Prevented duplicate stop token IDs and preserved requests for other backends.

Walkthrough

Adds resolve_sglang_string_stops for SGLang gRPC requests. The helper clears string stops and converts eligible single-token stops into deduplicated stop_token_ids. Chat, completion, generate, and messages stages invoke it before dispatch.

Changes

SGLang Stop Sequence Handling

Layer / File(s) Summary
Stop resolution helper and validation
model_gateway/src/routers/grpc/common/stages/helpers.rs
Adds tokenizer-based SGLang stop resolution. Single-token stops become deduplicated token IDs. Empty, multi-token, unknown, and unencodable stops remain router-side. Tests cover conversion, filtering, deduplication, missing tokenizers, and no-op behavior.
Request-building stage integration
model_gateway/src/routers/grpc/regular/stages/{chat,completion,generate,messages}/request_building.rs
Each request-building path resolves SGLang string stops before dispatch. Completion applies the same logic to single-item and batched requests.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant RequestBuildingStage
  participant StopResolver
  participant Tokenizer
  participant SGLangWorker

  RequestBuildingStage->>StopResolver: mutable request and tokenizer
  StopResolver->>Tokenizer: encode string stops
  Tokenizer-->>StopResolver: token IDs
  StopResolver-->>RequestBuildingStage: normalized request
  RequestBuildingStage->>SGLangWorker: dispatch request
Loading

Possibly related PRs

  • smg-project/smg#346: Both changes tokenize or transform stop sequences in regular gRPC request-building stages.
  • smg-project/smg#439: This change uses tokenizer token-ID lookup, which PR #439 expands for hub-loaded tiktoken tokenizers.
  • smg-project/smg#606: Both changes modify gRPC stop-sequence handling for backend dispatch.

Suggested labels: tests

Suggested reviewers: key4ng, catherinesue

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the main change: making the router authoritative for string stop sequences with SGLang workers.
Description check ✅ Passed The description directly explains the SGLang stop-sequence changes, affected behavior, design, tests, and validation.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/sglang-string-stops

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@claude

claude Bot commented Jul 4, 2026

Copy link
Copy Markdown

👋 The PR description doesn't fully follow
PULL_REQUEST_TEMPLATE.md:

  • Missing header: ## Description
  • Missing header: ### Problem
  • Missing header: ### Solution
  • Missing header: ## Changes
  • Missing header: ## Test Plan

Please update the PR description so reviewers have the context they need.

@gemini-code-assist gemini-code-assist 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.

Code Review

This pull request resolves issue #227, where SGLang gRPC workers reject string stop sequences when running with skip_tokenizer_init=True. It introduces a helper function resolve_sglang_string_stops that clears string stops from SGLang requests and converts single-token stops into stop_token_ids as an optimization, leaving multi-token stops to be handled by the router-side decoder. This helper is integrated into the chat, completion, generate, and message request building stages, and is accompanied by comprehensive unit tests. There are no review comments, so we have no feedback to provide.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

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 current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@model_gateway/src/routers/grpc/regular/stages/chat/request_building.rs`:
- Around line 133-138: The repeated explanatory comment around
resolve_sglang_string_stops is duplicated across the request-building stages, so
trim the call site near proto_request handling to a short reference instead of
keeping the full 5-line block. Update the comment in the request_building stage
using the resolve_sglang_string_stops helper name as the anchor, and keep only a
brief note that points to its existing doc comment so the
chat/completion/generate/messages paths stay consistent.
🪄 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: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 0bbf22c3-3106-4500-b6e7-a40082c9b3ab

📥 Commits

Reviewing files that changed from the base of the PR and between 8155b1f and f9cf09a.

📒 Files selected for processing (5)
  • model_gateway/src/routers/grpc/common/stages/helpers.rs
  • model_gateway/src/routers/grpc/regular/stages/chat/request_building.rs
  • model_gateway/src/routers/grpc/regular/stages/completion/request_building.rs
  • model_gateway/src/routers/grpc/regular/stages/generate/request_building.rs
  • model_gateway/src/routers/grpc/regular/stages/messages/request_building.rs

Comment on lines +133 to +138
// issue #227: SGLang gRPC workers run with skip_tokenizer_init and
// reject string `stop` sequences. Resolve them router-side (drop the
// strings, convert single-token stops to stop_token_ids) before
// dispatch; the router-side StopSequenceDecoder handles text trimming.
helpers::resolve_sglang_string_stops(&mut proto_request, ctx.tokenizer_arc().as_ref());

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Correctly wired after sampling defaults, before PD metadata injection.

The repeated 5-line explanatory comment block is duplicated verbatim across all four request-building stages (chat/completion/generate/messages). Since resolve_sglang_string_stops already carries a thorough doc comment at its definition, consider trimming each call site to a one-line reference (e.g. // issue #227: see resolve_sglang_string_stops doc) to reduce comment-maintenance drift across 4 files.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@model_gateway/src/routers/grpc/regular/stages/chat/request_building.rs`
around lines 133 - 138, The repeated explanatory comment around
resolve_sglang_string_stops is duplicated across the request-building stages, so
trim the call site near proto_request handling to a short reference instead of
keeping the full 5-line block. Update the comment in the request_building stage
using the resolve_sglang_string_stops helper name as the anchor, and keep only a
brief note that points to its existing doc comment so the
chat/completion/generate/messages paths stay consistent.

/// Only SGLang is affected: the vLLM servicer forces `detokenize=bool(stop)`,
/// TRT-LLM tokenizes stop words server-side, and the MLX proto has no
/// string-`stop` field. Non-SGLang requests are left untouched.
pub(crate) fn resolve_sglang_string_stops(

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔴 Important: HarmonyRequestBuildingStage also builds SGLang requests via build_generate_request_from_chatbuild_grpc_sampling_params_from_chat, which sets stop: stop_sequences (string stops extracted from the Chat request). But resolve_sglang_string_stops is never called on the Harmony path — so Harmony Chat requests carrying string stop sequences against an SGLang worker will still get the 400 rejection from SamplingParams.verify().

The Harmony stage (harmony/stages/request_building.rs) builds the proto at line 148, injects Harmony stop token IDs at line 334, then jumps to PD metadata — there's no call to this function in between. The Responses path is safe (it hardcodes stop: vec![] at sglang_scheduler.rs:445), but the Chat path is exposed.

Suggested fix: add a resolve_sglang_string_stops(&mut proto_request, ctx.tokenizer_arc().as_ref()) call in HarmonyRequestBuildingStage::execute after the proto is built (before or after the Harmony stop token injection block).

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f9cf09a1e8

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

// Always drop the string stops from the SGLang request: the worker cannot
// handle them under skip_tokenizer_init and the router-side decoder is the
// source of truth for string-stop matching/trimming.
let stop_strings = std::mem::take(&mut params.stop);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Preserve stop metadata when falling back to router trimming

When a SGLang request has a multi-token stop sequence, this removes it from the backend request and no replacement stop_token_id is added. I checked the regular response processors: they derive finish_reason/stop_reason from complete.finish_reason() and matched_stop_json(), not from StopSequenceDecoder::is_stopped, so these requests can be truncated by the router but still report length/end_turn and omit stop_sequence after the worker runs to max tokens or EOS. Please propagate the router-side stop match into the response metadata, or avoid clearing stops without an equivalent signal.

Useful? React with 👍 / 👎.

Comment on lines +324 to +326
let id = ids[0];
if !params.stop_token_ids.contains(&id) {
params.stop_token_ids.push(id);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Translate converted stop tokens back to message stop sequences

For Messages API stop_sequences that encode to one token, this appends only a numeric stop_token_id. The SGLang servicer returns that as a numeric matched token, but the non-streaming Messages processor only treats matched_stop_json().as_str() as a stop sequence, so a request stopped by a user sequence like "." is returned as end_turn with stop_sequence: null; streaming similarly cannot fill stop_sequence. Keep a mapping from the inserted token id to the original string, or skip this optimization for Messages.

Useful? React with 👍 / 👎.

@slin1237 slin1237 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

it doesn't look like the fix should be here?
And even if we wanna add a code like this for SGLang, the code shouldn't be in helper
Also. Please combine all the if statement to single if.
And follow pull request template.

@gongwei-130
gongwei-130 marked this pull request as draft July 6, 2026 18:04
@slin1237
slin1237 force-pushed the fix/sglang-string-stops branch from 1935463 to 3608abf Compare July 6, 2026 20:42
@gongwei-130 gongwei-130 changed the title fix(grpc): resolve string stop sequences for SGLang skip_tokenizer_init workers fix(grpc): router-authoritative string stop sequences for SGLang skip_tokenizer_init workers Jul 7, 2026
@gongwei-130
gongwei-130 force-pushed the fix/sglang-string-stops branch from 3608abf to 88f4402 Compare July 7, 2026 16:18
@github-actions github-actions Bot added the tokenizer Tokenizer related changes label Jul 7, 2026
…it workers

SGLang gRPC workers run with skip_tokenizer_init=True (the router owns the
tokenizer). The router forwarded string `stop` sequences as-is into the gRPC
SamplingParams, and upstream SGLang's SamplingParams.verify() rejects them in
that mode ("stop=[...] is unavailable when skip_tokenizer_init=True"),
returning a 400 for any request carrying the OpenAI-compatible `stop`
parameter.

The router already matches string stops itself via StopSequenceDecoder (it
detokenizes worker output and trims), so the worker never needs the raw
strings. Add resolve_sglang_string_stops(), applied after building the gRPC
request in the chat/completion/messages/generate stages, which:

  - clears the string `stop` list on SGLang requests (fixes the 400
    unconditionally; the router-side decoder still trims the text); and
  - converts any stop string that maps to a single token into stop_token_ids
    so the worker can still halt early for the common case (e.g. ["."], ["\n"]).
    Multi-token stops cannot be represented in the flat stop_token_ids field,
    so those rely on the router-side decoder.

Only SGLang is affected: the vLLM servicer forces detokenize=bool(stop),
TRT-LLM tokenizes stop words server-side, and MLX has no string-stop field.

Adds 8 unit tests covering single/multi-token, mixed, dedup, empty/unknown,
no-tokenizer, no-op, and non-SGLang-untouched cases.

Signed-off-by: gongwei-130 <56567052+gongwei-130@users.noreply.github.com>
@slin1237
slin1237 force-pushed the fix/sglang-string-stops branch from 88f4402 to c07b7e9 Compare August 3, 2026 20:43
@slin1237
slin1237 marked this pull request as ready for review August 3, 2026 20:43
@github-actions github-actions Bot removed the tokenizer Tokenizer related changes label Aug 3, 2026
// reject string `stop` sequences. Resolve them router-side (drop the
// strings, convert single-token stops to stop_token_ids) before
// dispatch; the router-side StopSequenceDecoder handles text trimming.
helpers::resolve_sglang_string_stops(&mut proto_request, ctx.tokenizer_arc().as_ref());

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔴 Important: The PR description says "Native /generate: its streaming path has no decoder, so a cleared stop would stream untrimmed text. Keeps the pre-existing 400." — but this call does the opposite: it clears string stops, removing the 400.

The non-streaming generate path has a StopSequenceDecoder (processor.rs:378), so text gets trimmed correctly there. But the streaming generate path (streaming.rs:834–945) directly accumulates decoded text with no stop-sequence matching at all:

// streaming.rs:867-873
let chunk_text = tokenizer
    .decode(chunk.token_ids(), true)
    .unwrap_or_default();
let accumulated_text = accumulated_texts.entry(index).or_default();
accumulated_text.push_str(&chunk_text);

For multi-token string stops on a streaming /generate request, this changes the behavior from:

  • Before: SGLang rejects the request with a 400 (explicit failure)
  • After: SGLang accepts it, generates past the stop sequence, and streams untrimmed text containing the stop string (silent incorrect output)

Single-token stops that convert to stop_token_ids are likely fine (worker halts before emitting that token), but any multi-token stop will silently produce wrong output.

Consider either (a) gating this call on !ctx.input.request_type.is_streaming() so streaming generate preserves the pre-existing 400, or (b) adding a StopSequenceDecoder to the generate streaming path to match chat/completions/messages.

slin1237 added a commit that referenced this pull request Aug 4, 2026
Engines that can't match string `stop` sequences server-side previously
handled them in three divergent ways: SGLang gRPC (skip_tokenizer_init)
had a dedicated resolver that dropped the strings and converted
single-token stops to stop_token_ids; the ZMQ vLLM path silently dropped
strings with no early-stop conversion; and the ZMQ TokenSpeed path
rejected any request carrying `stop` with a 400.

Consolidate all of them onto one helper, resolve_string_stops, applied
in the chat/completion/generate/messages request-building stages. For
backends whose engine sees token ids only — SGLang on any transport, and
every direct-ZMQ backend — it drops the string `stop` list (the
router-side StopSequenceDecoder trims the text) and forwards single-token
stops as stop_token_ids for early stopping; multi-token stops fall to the
decoder. gRPC vLLM (servicer detokenizes), TRT-LLM (server-side), and MLX
keep their strings untouched, gated by the backend's is_zmq() flag.

This fixes the TokenSpeed 400 (stop strings now work over ZMQ) and gives
the ZMQ vLLM path the single-token early-stop optimization it lacked. The
finish_reason=stop synthesis added earlier is already backend-neutral, so
the two halves together give consistent stop-string behavior across
gRPC-SGLang, ZMQ-vLLM, and ZMQ-TokenSpeed.

Supersedes #1877 (SGLang-only input-side fix). Adds unit tests for the
shared resolver and for TokenSpeed accepting residual stop strings.

Signed-off-by: Simo Lin <25425177+slin1237@users.noreply.github.com>
@github-actions

Copy link
Copy Markdown

This pull request has been automatically marked as stale because it has not had any activity within 14 days. It will be automatically closed if no further activity occurs within 16 days. Leave a comment if you feel this pull request should remain open. Thank you!

@github-actions github-actions Bot added the stale PR has been inactive for 14+ days label Aug 18, 2026
@gongwei-130

Copy link
Copy Markdown
Collaborator Author

Closing — superseded by #2057 (feat(zmq): forward EOS and resolve string stops for the direct backend), later refactored by #2068.

resolve_string_stops() in model_gateway/src/routers/grpc/common/stages/helpers.rs now does what this PR proposed, and generalises it:

ProtoGenerateRequest::Sglang(req) => {
    if let Some(params) = req.sampling_params.as_mut() {
        let stops = std::mem::take(&mut params.stop);
        encode_single_token_stops(stops.clone(), &mut params.stop_token_ids, tokenizer);
        return stops;
    }
}

Same approach — drop the string stop list that a skip_tokenizer_init=True worker rejects, forward single-token stops as stop_token_ids for early stopping, and leave multi-token stops to the router-side StopSequenceDecoder. Two improvements over what I had here:

  1. It covers every token-only wire, not just SGLang gRPC — the direct-ZMQ backends (vLLM EngineCore, TokenSpeed) receive token ids only and cannot match a stop string either. That path did not exist when this PR was opened.
  2. It returns the stripped stop strings, making the router's residual obligation explicit: response processing must trim them from the output text. This PR left that implicit in the decoder.

Nothing here is worth carrying forward on top of that. Thanks to whoever picked the approach up.

@lightseek-bot
lightseek-bot deleted the fix/sglang-string-stops branch August 26, 2026 01:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

grpc gRPC client and router changes model-gateway Model gateway crate changes priority:high High priority stale PR has been inactive for 14+ days

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants