Skip to content

fix(protocol): forward flat output top logprobs for chat completions - #24

Merged
guapisolo merged 1 commit into
radixark:mainfrom
HJSang:hejian/forward-flat-output-top-logprobs
Oct 14, 2026
Merged

guapisolo merged 1 commit into
radixark:mainfrom
HJSang:hejian/forward-flat-output-top-logprobs

Conversation

@HJSang

@HJSang HJSang commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Forward the two SGLang chat-completion extension fields added by sgl-project/sglang#42890 (merged to main; cherry-picked to sglang-miles as #42838, also merged):

  • return_flat_raw_output_top_logprobs
  • return_flat_raw_top_logprobs_b64

With these fields, SGLang returns output top-k candidates as base64 [tokens, k] float32/int32 arrays in choices[].meta_info. Without them it returns [logprob, token_id, text] rows. At 160 tokens × k=128 that's about 0.24 MB instead of about 2.6 MB of JSON, with no per-candidate detokenization, and -inf survives.

ChatCompletionRequest didn't declare either field. The HTTP router re-serializes the typed request, so serde dropped both and SGLang silently fell back to the nested rows. return_flat_raw_output_top_logprobs follows the template of #20 (return_sampling_mask): a #[serde(default)] boolean in the SGLang extension block. return_flat_raw_top_logprobs_b64 is an Option<bool> left out when unset: SGLang's chat default for it is true, and always sending false would override that.

Compatibility. return_flat_raw_output_top_logprobs is always serialized, false when unset; the b64 flag is sent only when the client set it. SGLang's ChatCompletionRequest ignores unknown fields, so older SGLang builds accept both.

Consumer: miles session server, which requests these fields for score-centering training (radixark/miles#3952).

Tests

  • tests/spec/chat_completion.rs: the SGLang extension round-trip and default-value tests now cover both fields, including that an omitted b64 flag stays omitted after re-serialization.
  • cargo test --test spec_test gives 98 passed and 0 failed (Linux x86_64, rustc 1.98.1).
  • End-to-end on H200: with this gateway in front of SGLang with [cherrypick from #42890] [Feature] Return output top logprobs as flat base64 arrays on request sgl-project/sglang#42838, a chat request with both flags returned output_top_logprobs_shape [32, 128] and no nested rows; the released 0.3.2 gateway dropped the flags and the engine returned nested rows. In three miles score-centering runs at k=128, all 1,212 session requests through this gateway carried both flags.
  • cargo fmt wasn't run because rustfmt isn't installed on that host. The edits copy the neighbouring fields' layout.

🤖 Generated with Claude Code

SGLang chat completions accept return_flat_raw_output_top_logprobs and
return_flat_raw_top_logprobs_b64 (sgl-project/sglang#42890, on
sglang-miles as #42838), which return output top-k candidates as base64
[tokens, k] arrays in meta_info instead of [logprob, token_id, text] rows.
ChatCompletionRequest did not declare them, so serde dropped both before
forwarding and SGLang fell back to the nested rows.

The b64 flag is Option<bool> and skipped when unset: SGLang's chat default
for it is true, and a #[serde(default)] bool would always forward false.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@HJSang
HJSang force-pushed the hejian/forward-flat-output-top-logprobs branch from 3dfad1e to c6e8955 Compare October 14, 2026 20:24
HJSang added a commit to radixark/miles that referenced this pull request Oct 14, 2026
Score-centering session requests asked SGLang for top_logprobs, which come
back as completion_tokens rows of k [logprob, token_id, text] triples.
SGLang detokenizes every candidate and the session server parses the rows
into Python objects, and JSON cannot carry -inf: a non-finite candidate
arrives as null and numpy stores it as NaN in rollout_topk_log_probs.

Chat training requests now also set return_flat_raw_output_top_logprobs
(sgl-project/sglang#42890, on sglang-miles as #42838), which returns the
candidates as float32/int32 [rows, k] arrays, base64 by default on chat,
and append_rollout_topk_logprobs decodes them. Without that SGLang or a
gateway that forwards the field (radixark/sgl-router-for-miles#24), the
response keeps the nested rows, which are still decoded as before. Native
/generate requests are unchanged because on-policy distillation reads the
nested student rows there.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@guapisolo
guapisolo merged commit 523e940 into radixark:main Oct 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants