fix: preserve JSON object key order in proxied payloads - #439
Conversation
serde_json's default Map is BTreeMap-backed, so every JSON object that passes through the router is re-serialized with alphabetized keys. Object key order is semantic for response_format.json_schema: order-enforcing structured-output backends (vLLM/xgrammar) use the properties declaration order as the generation order, so reordering silently changes what downstream models are forced to generate. Enable serde_json's preserve_order feature so payloads are forwarded with keys in the order the client sent them. Array order was already preserved. Signed-off-by: Hiroshi Morishige <hiroshi.morishige@gmail.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Enterprise Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (1)
WalkthroughThe workspace enables serde_json's ChangesJSON order preservation
Estimated code review effort: 1 (Trivial) | ~2 minutes Merge Risk: ⚪ Minimal · up to This localized dependency configuration change preserves client-supplied JSON object key order, with the stated workspace tests and verification passing; no actionable merge-blocking risk remains beyond normal checks and review. Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 inconclusive)
✅ Passed checks (4 passed)
Comment |
Fixes #438.
What
Enables serde_json's
preserve_orderfeature for the workspace, so JSON objects in proxied payloads are forwarded with their keys in the order the client sent them instead of alphabetized (the BTreeMap default). One line inCargo.toml, plus the lockfile update (indexmapwas already in the dependency tree).Why
Object key order is semantic for
response_format.json_schema: order-enforcing structured-output backends (vLLM with its default xgrammar backend) use thepropertiesdeclaration order as the generation order. The router currently re-serializes every object with alphabetized keys, silently changing what downstream models are forced to generate. A model-independent repro is in #438.With an order-sensitive fine-tuned judge behind an
llm_classifierroute we measured an 18% judgment-runaway rate (grammar/EOS whitespace deadlock atmax_tokens, each occurrence an invalid verdict and a fail-open); restoring key order drops it to zero.Verification
cargo test --workspacepasses with the feature enabledzebra/apple/mangoreaches the backend in that order (previouslyapple/mango/zebra)Notes
preserve_orderswaps serde_json's Map backing to IndexMap workspace-wide. Anything relying on alphabetical serialization would change behavior; the test suite passes, and for a proxy, forwarding payloads unmodified seems the safer default.RawValueinstead), happy to rework.Summary by CodeRabbit