Skip to content

fix(protocol): allow 128 chat top_logprobs and forward sampling_logprobs_mode - #21

Merged
guapisolo merged 1 commit into
mainfrom
jiajun/score-centering-router-fields
Sep 29, 2026
Merged

guapisolo merged 1 commit into
mainfrom
jiajun/score-centering-router-fields

Conversation

@guapisolo

Copy link
Copy Markdown
Collaborator

Summary

Accept 128 chat top_logprobs and forward sampling_logprobs_mode on chat and generate requests.

Symptom & Reproduction

  • Symptom: Miles score-centering rollouts through this router lose the sampler's candidate distribution: chat top_logprobs above 20 is rejected, while sampling_logprobs_mode: "support" never reaches SGLang on chat or /generate, so SGLang falls back to selected scalar sampling log-probs.
  • Reproduction: Temporary spec tests on 0e7c1ac show the failures: validating a chat request with "logprobs": true, "top_logprobs": 128 returns a top_logprobs range error (max: 20); deserializing then re-serializing a chat or generate request with "sampling_logprobs_mode": "support" yields null for that field instead of "support".

Root Cause

  1. ChatCompletionRequest::top_logprobs uses #[validate(range(min = 0, max = 20))], the OpenAI limit.
  2. Neither ChatCompletionRequest nor GenerateRequest declares sampling_logprobs_mode.
  3. route_typed_request forwards serde_json::to_value(typed_req), so undeclared fields are dropped.

Fix

Raise the chat bound to 128, the capacity of SGLang's PD logprob metadata (max_top_logprobs_num in disaggregation/utils.py), and add sampling_logprobs_mode: Option<String> to both requests, serialized only when set. This follows #20, which fixed the same field loss for return_sampling_mask. It ports the functional part of sgl-project/sglang#41373; input_ids and return_meta_info are already typed here. Requests without these fields serialize unchanged.

Verification

  • cargo test --test spec_test: 98 passed, including the new test_top_logprobs_accepts_up_to_128 (20, 21, 128 accepted; 129 rejected) plus the extended chat/generate extension-field tests (round-trip, defaults, omission).
  • cargo test --test routing_tests: 90 passed, 2 failed, both environmental or pre-existing: test_redis_server_start_stop needs redis-server, and test_manual_routing_without_header also fails 3/3 on 0e7c1ac.
  • cargo build --lib passed. cargo fmt was not run because rustfmt is not installed on the test host.

Not verified: an end-to-end Miles rollout through a rebuilt router wheel.

Review Focus

  • top_logprobs / src/protocols/chat.rs: 128 exceeds the OpenAI limit; values above 128, beyond SGLang's PD capacity, stay rejected here.
  • sampling_logprobs_mode: kept as a pass-through String, so SGLang remains the validator of its values.

Generated with Claude Code

…obs_mode

Miles score centering records the sampler's candidate probabilities at
generation time, and both of its request shapes were broken by typed
routing:

- Unfiltered session rollouts send top_logprobs=k to /v1/chat/completions
  (default k=128). The chat validator rejected any value above 20.
- Filtered rollouts send sampling_logprobs_mode="support" on chat and
  /generate. Neither typed request declared the field, so Serde dropped it
  before forwarding and SGLang fell back to "selected".

Raise the chat top_logprobs bound to 128, the capacity of SGLang's PD
logprob metadata, and add sampling_logprobs_mode to ChatCompletionRequest
and GenerateRequest so it is forwarded unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@guapisolo
guapisolo merged commit df2c790 into main Sep 29, 2026
guapisolo added a commit that referenced this pull request Oct 3, 2026
The Responses route still validated top_logprobs against OpenAI's limit
of 20, so requests for 21 to 128 candidates were rejected before routing.
The chat route accepts up to 128 since #21, and SGLang's ResponsesRequest
passes the value through as top_logprobs_num without an upper bound.

Raise the bound to 128, the SGLang PD logprob metadata capacity already
used for chat. Values above 128 stay rejected.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
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.

1 participant