Skip to content

feat(protocols): add serde(flatten) to ChatCompletionRequest for engine-specific fields#1119

Closed
DavidBellamy wants to merge 1 commit intolightseekorg:mainfrom
DavidBellamy:add-flatten-chat-completion-request
Closed

feat(protocols): add serde(flatten) to ChatCompletionRequest for engine-specific fields#1119
DavidBellamy wants to merge 1 commit intolightseekorg:mainfrom
DavidBellamy:add-flatten-chat-completion-request

Conversation

@DavidBellamy
Copy link
Copy Markdown
Contributor

@DavidBellamy DavidBellamy commented Apr 14, 2026

Summary

  • ChatCompletionRequest silently drops request fields not explicitly defined in the struct. This prevents engine-specific parameters (e.g. sglang's return_routed_experts for MoE routing replay) from passing through the gateway to backend workers.
  • CompletionRequest already has a #[serde(flatten)] pub other: Map<String, Value> catch-all. This PR makes ChatCompletionRequest consistent by adding the same pattern.
  • All existing construction sites use ..Default::default(), so the new field is automatically initialized to an empty map with no code changes needed elsewhere.

Fixes: sgl-project/sglang#22740

Summary by CodeRabbit

  • New Features
    • Chat completion requests and responses now accept and include additional engine-specific JSON properties. This improves compatibility with varied chat engines, lets custom parameters pass through unchanged, and increases flexibility without altering existing validation or normalization behavior.

@github-actions github-actions bot added the protocols Protocols crate changes label Apr 14, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 14, 2026

Warning

Rate limit exceeded

@DavidBellamy has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 55 minutes and 32 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 55 minutes and 32 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 80899985-29ca-4704-9e4e-9735c213363c

📥 Commits

Reviewing files that changed from the base of the PR and between 46fa164 and 8ac5695.

📒 Files selected for processing (1)
  • crates/protocols/src/chat.rs
📝 Walkthrough

Walkthrough

The ChatCompletionRequest struct in crates/protocols/src/chat.rs gained a flattened catch‑all field other: serde_json::Map<String, serde_json::Value> so unknown JSON properties are preserved during (de)serialization.

Changes

Cohort / File(s) Summary
Protocol Data Structure
crates/protocols/src/chat.rs
Imported serde_json::Map/Value and added #[serde(flatten)] pub other: Map<String, Value> to ChatCompletionRequest to capture and re-emit unknown engine-specific JSON fields.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

Suggested reviewers

  • key4ng

Poem

🐰
I nibble at bytes beneath moonlight's glow,
Extra fields now safe where wild JSON go.
Flattened and tucked in a cozy map,
No stray key lost on the forwarding lap.
Hoppity hooray — preserved in its wrap!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately and specifically describes the main change: adding serde(flatten) to ChatCompletionRequest for engine-specific fields.
Linked Issues check ✅ Passed The PR successfully implements the required fix by adding #[serde(flatten)] pub other: Map<String, Value> to ChatCompletionRequest, matching the pattern on CompletionRequest and addressing issue #22740's requirement.
Out of Scope Changes check ✅ Passed All changes are scoped to the stated objective: updating ChatCompletionRequest with a serde(flatten) field to preserve unknown JSON fields, with no unrelated modifications.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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 and usage tips.

@mergify
Copy link
Copy Markdown
Contributor

mergify bot commented Apr 14, 2026

Hi @DavidBellamy, the DCO sign-off check has failed. All commits must include a Signed-off-by line.

To fix existing commits:

# Sign off the last N commits (replace N with the number of unsigned commits)
git rebase HEAD~N --signoff
git push --force-with-lease

To sign off future commits automatically:

  • Use git commit -s every time, or
  • VSCode: enable Git: Always Sign Off in Settings
  • PyCharm: enable Sign-off commit in the Commit tool window

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

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 updates the ChatCompletionRequest struct in crates/protocols/src/chat.rs to include an other field of type Map<String, Value> with the #[serde(flatten)] attribute. This change allows the struct to capture additional, non-explicitly defined fields from incoming JSON requests. I have no feedback to provide as there were no review comments.

@slin1237
Copy link
Copy Markdown
Member

thanks for the fix, lgtm
please address ci failures

DavidBellamy added a commit to LLM360/sglang that referenced this pull request Apr 14, 2026
…uest

Adds a [patch.crates-io] override pointing openai-protocol at a fork
that adds serde(flatten) to ChatCompletionRequest, matching the existing
pattern on CompletionRequest. This allows engine-specific parameters
like return_routed_experts to pass through the gateway to workers.

Upstream PR: lightseekorg/smg#1119
Remove this patch once the upstream crate publishes with the fix.
@DavidBellamy DavidBellamy changed the title Add serde(flatten) to ChatCompletionRequest for engine-specific fields feat(protocols): add serde(flatten) to ChatCompletionRequest for engine-specific fields Apr 14, 2026
@DavidBellamy
Copy link
Copy Markdown
Contributor Author

@slin1237 Thanks for the review! I've addressed the CI failures:

  • DCO sign-off: Added via rebase
  • PR title: Updated to conventional commits format (feat(protocols): ...)

The new workflow runs need maintainer approval to execute (fork PR after force push). Could you approve them?

Re: the openai-responses failures from the previous run, all 5 were flaky MCP tool-calling tests (test_mcp_basic_tool_call_streaming, test_mcp_multi_server_tool_call, test_mcp_multi_server_tool_call_streaming, etc.) that failed after multiple retries. Unrelated to this one-line serde change. Should clear on re-run.

…ne-specific fields

ChatCompletionRequest silently drops any request fields not explicitly
defined in the struct. This prevents engine-specific parameters (e.g.
sglang's return_routed_experts for MoE routing replay) from passing
through the gateway to backend workers.

CompletionRequest already has this flatten catch-all (via its `other`
field). This commit makes ChatCompletionRequest consistent by adding
the same pattern.

Signed-off-by: David <12414531+DavidBellamy@users.noreply.github.com>
@DavidBellamy DavidBellamy force-pushed the add-flatten-chat-completion-request branch from 46fa164 to 8ac5695 Compare April 14, 2026 16:53
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

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 the current code and only fix it if needed.

Inline comments:
In `@crates/protocols/src/chat.rs`:
- Around line 320-322: Add a unit test that verifies serde(flatten) preserves
unknown fields: create a JSON string for the chat request that includes an extra
key like "return_routed_experts": true, deserialize it with serde_json::from_str
into the struct that defines the #[serde(flatten)] pub other: Map<String,
Value>, assert that request.other.get("return_routed_experts") exists and equals
Value::Bool(true), then re-serialize the struct with serde_json::to_string and
assert the resulting JSON contains the "return_routed_experts" key (or that
serde_json::from_str of the re-serialized JSON still yields the same other
entry). Use the struct with the other field and serde_json utilities to
implement the test.
🪄 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: 19466c72-c51d-4bb7-8982-e8ac869383e1

📥 Commits

Reviewing files that changed from the base of the PR and between ed64c29 and 46fa164.

📒 Files selected for processing (1)
  • crates/protocols/src/chat.rs

Comment on lines +320 to +322
/// Additional fields not explicitly defined above (e.g. engine-specific parameters)
#[serde(flatten)]
pub other: Map<String, Value>,
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Add a round-trip regression test for unknown-field preservation.

Please add a test that deserializes a request with an extra key (e.g., return_routed_experts), asserts it lands in other, and verifies it is present after re-serialization.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@crates/protocols/src/chat.rs` around lines 320 - 322, Add a unit test that
verifies serde(flatten) preserves unknown fields: create a JSON string for the
chat request that includes an extra key like "return_routed_experts": true,
deserialize it with serde_json::from_str into the struct that defines the
#[serde(flatten)] pub other: Map<String, Value>, assert that
request.other.get("return_routed_experts") exists and equals Value::Bool(true),
then re-serialize the struct with serde_json::to_string and assert the resulting
JSON contains the "return_routed_experts" key (or that serde_json::from_str of
the re-serialized JSON still yields the same other entry). Use the struct with
the other field and serde_json utilities to implement the test.

@DavidBellamy
Copy link
Copy Markdown
Contributor Author

Replaced by #1130 (branch renamed to conform to Mergify naming convention).

@DavidBellamy DavidBellamy deleted the add-flatten-chat-completion-request branch April 14, 2026 16:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

protocols Protocols crate changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

sgl-model-gateway drops return_routed_experts field from chat/completion requests

2 participants