Repository navigation
[Feat] sgl-router: Serve the remaining native gRPC inference RPCs - #42681
Merged
Merged
Conversation
sherlockwu
force-pushed
the
sgl-router-grpc-all
branch
from
October 5, 2026 23:37
af01f4b to
7e37fd5
Compare
sherlockwu
force-pushed
the
sgl-router-grpc-all
branch
from
October 6, 2026 00:07
7e37fd5 to
f2f98d7
Compare
sherlockwu
force-pushed
the
sgl-router-grpc-all
branch
2 times, most recently
from
October 6, 2026 00:44
f866fc8 to
82d1ee3
Compare
sherlockwu
requested review from
CatherineSue,
Fridge003,
HaiShaw,
JustinTong0323,
Kangyan-Zhou,
alexnails,
bingxche,
ishandhanani,
ispobock,
merrymercy,
rainj-me,
slin1237,
sogalin and
yctseng0211
as code owners
October 12, 2026 04:55
sherlockwu
force-pushed
the
sgl-router-grpc-all
branch
from
October 12, 2026 04:55
f9281dc to
e8b065b
Compare
`--grpc-port` serves the engine's own sglang.runtime.v1.SglangService, so a gRPC client can point at the router or at an engine. ChatComplete runs the same preparation and selection as /v1/chat/completions (rendering, input_ids forwarding, PD bootstrap, DP rank) and calls the selected engine's native ChatComplete, whose port comes from /server_info. HTTP is unchanged. Dispatch is generic over the transport, so PD, guards and metrics are shared; the SSE pump also carries gRPC chunks. Other RPCs are unimplemented. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…Docker builds - Abort an unfinished engine call by the router's rid, as /abort_request does over HTTP: a dropped call alone aborts an id of the engine's own. - Classify a status that ends a stream by its code, so backpressure (RESOURCE_EXHAUSTED) no longer opens the breaker. - Take an engine's plain response to a streaming call (one finished chunk with an HTTP status) as that status, for metrics and the breaker. - Keep the router's error code on streams it ends itself (idle timeout, stale expiry, prefill abort) as x-router-error-code. - Copy proto/ and rust/Cargo.toml into both router Docker builds, keeping the repo layout, and run router CI when they change. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A non-streaming call that exceeds the request timeout now returns DEADLINE_EXCEEDED with x-router-error-code: upstream_timeout, like the streaming timeouts, so clients can tell it from an engine deadline. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
sherlockwu
force-pushed
the
sgl-router-grpc-all
branch
from
October 13, 2026 20:51
e8b065b to
2e9f35c
Compare
Route Complete, Generate, TextGenerate, Embed, TextEmbed, Classify, OpenAIEmbed, OpenAIClassify and Rerank like their HTTP routes and forward each to the same engine RPC, in unified and PD fleets. OpenAI RPCs reuse the HTTP body as is. Typed RPCs are prepared through the JSON their HTTP route reads, and the router's additions (rid, PD bootstrap, DP rank, sampling defaults) are set back on the proto. HTTP /v1/completions is added beside Complete, sharing chat's preparation, so every routed RPC has an HTTP twin. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Typed RPCs no longer round-trip through JSON (2 ms at 32k prompt tokens, 9 ms at 128k): routing inputs come straight from the proto, and the router's additions (rid, PD bootstrap, DP rank, sampling defaults) are set as fields per leg. A text prompt is tokenized once, as its HTTP route forwards input_ids: TextGenerate is sent as Generate with return_text, TextEmbed as Embed, and Classify with ids. They stay text RPCs when ids are not forwarded. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Run the gRPC PD test on the legacy and the reorg (bucket-first) selection paths; both prepare and select through the same steps as HTTP. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Apply #42674's fixes to the generic engine RPC forwarding: abort an unfinished call by the engine rid, classify a stream-ending status by its code, take a plain response to a streaming call as its status, and keep the router's error code on streams it ends itself. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… code Carry #42674's fix to the generic forwarding, so a non-streaming call of any RPC that exceeds the request timeout returns upstream_timeout. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e; keep gRPC trace context - A completions prompt list is a batch the engine fans out, so it is no longer pinned to one DP rank in PD; token-id prompts count exactly. - Typed requests count the sampling contract's default n in load. - Typed sampling values compare as the decimal sent (0.7, not f32's 0.699999988), so exact and range contracts accept them. - Typed RPCs carry gRPC-metadata trace headers (not authorization) to the engine's trace_headers. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
When routing needs token counts, tokenize each text prompt of a completions batch, as /generate does, instead of estimating from bytes; the body is still forwarded as sent. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
sherlockwu
force-pushed
the
sgl-router-grpc-all
branch
from
October 13, 2026 21:18
2e9f35c to
7b02328
Compare
Resolve conflicts with #42674 (squash-merged), #42818 and #44072: - prepare() resolves OpenAI-route models with lookup_openai, so HTTP `model: "base:adapter"` keeps routing to the base model. - Leg::new passes the pinned prefill rank so decode still receives disagg_prefill_dp_rank under --dp-aware. - PreparedRequest::completion and ::typed set cache_namespace. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 task done
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Stacked on #42674 (gRPC
ChatComplete). That PR is stacked on #42673 (tonic 0.14).Complete the router's native gRPC API: each inference RPC behaves like its HTTP route, in both unified and PD fleets.
Changes
ChatComplete(#42674)/v1/chat/completionsComplete/v1/completions(new HTTP route too)Generate,TextGenerate/generateEmbed,TextEmbed,OpenAIEmbed/v1/embeddingsClassify,OpenAIClassify/v1/classifyRerank/v1/rerankOpenAI RPCs forward the HTTP route's JSON body as is.
Typed RPCs are prepared from their fields with the same rules as their HTTP route, with no JSON round trip. Routing inputs are read straight from the proto, and the router's additions (rid, PD bootstrap, DP rank, sampling defaults) are set as fields on each leg.
Text prompts are tokenized once, as their HTTP routes forward
input_ids:TextGenerategoes to the engine asGeneratewithreturn_text([gRPC] Move runtime.v1 bindings to tonic 0.14, report OpenAI status codes, return text on request #42673), so the engine still supplies the text and the router never detokenizes.TextEmbedgoes asEmbed, andClassifygoes with ids.--disable-input-ids-forwarding, without a tokenizer, or (forTextGenerate) whenreturn_text_in_logprobsis set.Shared code:
preparestep perEndpoint, and forwarding is generic over the engine RPC./v1/completionsshares chat's preparation but never forwardsinput_ids.Not served:
Tokenize,HealthCheck, model info and the admin RPCs still answerUNIMPLEMENTED.Scoredoes too, since it has no router HTTP route.Review fixes: [Feat] sgl-router: Serve native gRPC ChatComplete #42674's review fixes (abort by rid, breaker classification, streaming status, router error codes) are carried to the generic forwarding, so they cover every RPC.
Second review round:
promptlist is a fan-out batch, so it is no longer pinned to one DP rank in PD, and token-id prompts are counted exactly./generatedoes, instead of estimated from bytes. The body is still forwarded as sent.n.0.7, not the f32's0.699999988).trace_headers, exceptauthorization.Tests
tests/proxy/grpc_routing.rsuses mock engines, so CI needs no GPUs. It covers:Generate, under both legacy and reorg routing: the same bootstrap room on both legs, and the same rid;Embed;TextGenerate/TextEmbedreaching the engine asGenerate/Embedwith the router's ids;Generate,TextGenerate, streaming and non-streaming all match HTTP. The engine'sGeneratewithreturn_textreturns HTTP's text, and none without it. An over-long prompt gets the same 400.OpenAIEmbed,Embed,TextEmbed,ClassifyandOpenAIClassifyall match.--chat-routing reorg), unified and PD: 19/19 generation checks match HTTP and the unified outputs.Rerankmatches. The engine's own gRPCRerankserialization fix is in [gRPC] Move runtime.v1 bindings to tonic 0.14, report OpenAI status codes, return text on request #42673.CI States
Latest PR Test (Base): ✅ Run #38857817139
Latest PR Test (Extra): ❌ Run #38857817136
Latest PR Test (AMD ROCm 10): ➖ No AMD PR run found for this commit.