Commit Graph
119 Commits
Author SHA1 Message Date
1f60ddef5d [PD] Introduce runtime role switching between prefill and decode (#28403)
Signed-off-by: huanglong <huanglong@linux.alibaba.com>
Signed-off-by: inkcherry <mingzhi.liu@amd.com>
Co-authored-by: huanglong <huanglong@linux.alibaba.com>
Co-authored-by: Shangming Cai <csmthu@gmail.com>
Co-authored-by: Huang Long <121648372+LLLL114@users.noreply.github.com>
2026-09-18 01:45:12 +08:00
Liangsheng YinandBBuf 464fffbec8 dsv4.1: chat encoding and tool parsing (#39665)
Co-authored-by: BBuf <1182563586@qq.com>
2026-09-16 20:49:42 -07:00
William Arnoldandishandhanani f45aad44bd [gRPC] Expose native pause status (#37488)
Co-authored-by: ishandhanani <82981111+ishandhanani@users.noreply.github.com>
2026-09-16 15:16:52 -07:00
Liangsheng Yin 0dabef3d30 [misc] Fix tool-call index, graph padded-row count, and prefill-graph input_embeds refresh (#39574) 2026-09-15 16:37:22 -07:00
Yuxuan ZhangandXinyuan Tong 17ba2c2e7c Support non-strict GLM47 tool calls with EBNF constraints (#38890)
Co-authored-by: Xinyuan Tong <xinyuantong.cs@gmail.com>
2026-09-15 16:41:48 +08:00
raghothamandLianmin Zheng c0b8725f5a Fix /model_info serialization when a config value is a class (#39237)
Co-authored-by: Lianmin Zheng <lianminzheng@gmail.com>
2026-09-14 17:10:44 -07:00
Shangming CaiandXinyuan Tong 14a131ad5b [PD][OpenAI] Gate /v1/responses persistence behind --enable-response-store, default off (#39122)
Co-authored-by: Xinyuan Tong <xinyuantong.cs@gmail.com>
2026-09-13 21:20:47 +08:00
925e684a88 [Feat][Responses API] Support custom tools, encrypted reasoning replay, developer tier and model validation (#38690)
Co-authored-by: Xinyuan Tong <xinyuantong.cs@gmail.com>
Co-authored-by: Xinyuan Tong <115166877+JustinTong0323@users.noreply.github.com>
2026-09-12 21:29:12 +08:00
Xiaoyu ZhangandCursor 0a57403468 [Perf] Optimize Qwen3-VL unique-image serving on H100 (#36411)
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-12 15:16:59 +08:00
Jeremy Zhang f69d6fc28a [OpenAI] Propagate PD routing metadata through /v1/responses (#35503) 2026-09-12 01:33:38 +08:00
ad7f57c9ea [Responses] Fix empty-prompt routing for token-first chat encoders (kimi_k3, inkling) (#35486)
Co-authored-by: Xinyuan Tong <115166877+JustinTong0323@users.noreply.github.com>
Co-authored-by: Xinyuan Tong <xinyuantong.cs@gmail.com>
2026-09-11 01:06:20 +00:00
Cheng Wan f1a512c51c [Config] msgspec.Struct for the config tier (#38753) 2026-09-09 19:41:19 -07:00
Sage 8733da8cf4 [rust-server] Use node-local HTTP ports for DP attention (#34430)
Signed-off-by: Sage Ahrac <sagiahrak@gmail.com>
2026-09-10 02:22:44 +08:00
Xiaoyu ZhangandMick Qian 4d23a4fa6d [Test] Consolidate test cleanup and CI taxonomy (net -11.4K lines) (#37436)
Co-authored-by: Mick Qian <mickqian@users.noreply.github.com>
2026-09-07 15:13:59 +08:00
Cheng Wan aaf9a95763 [Config] Round 6.5: a namespace declares what it derives, next to what it derives it from (#38113)
Fifth of five; stacked on #38049. The split gave every namespace a file, but
only for the half an operator types. This is the other half.

## The parallel quotients are declared, not written out

`attn_tp_size` and its five siblings were sixty lines of near-identical
properties in the runtime context, a file away from the leaves they are
quotients of, so reading `parallel.py` told you what you could set and nothing
about what that decides.

They are declared in `Parallel` now, in the same class as those leaves. They
carry no annotation, so they are not dataclass fields and
`collect_input_fields` never puts them on the record -- the same mechanism that
already keeps `_NS_PATH` off it. That is the right exclusion: a quotient has no
operator input to preserve, and the record is what crosses a process boundary,
where a stamped width is one an elastic scale-up will not refresh.

## A quotient is a value in the bag, like every other derived one

`_derived_width` answered from a stamp or, failing that, a live process group.
The group read could never disagree with the stamp:

- `initialize_model_parallel` stamps all six as its last statement,
  unconditionally;
- an elastic scale-up restamps `attn_dp_size` through
  `update_dp_attention_post_scale` -- the comment claiming it does *not* was
  wrong;
- no hardware backend builds groups of its own;
- `multimodal_gen`, which has its own `initialize_model_parallel` and does not
  stamp, never reads a quotient.

So a built group was always already stamped, and the group read goes -- and with
it the last reason for a quotient to be resolved on every read.

Every input to `derive_parallel_widths` is a record field. `dcp_enabled` is
`decode_context_parallel_size > 1`, not a fact about a built group; it was
spelled `_DCP is not None`, which is a longer way to say the same thing. So the
six are fixed once the configuration is fixed -- the same test every other
`Derived(fn=...)` in this PR passes. They are declared the same way and computed
the same way: once, at publish, into ordinary bag leaves.

What remains is override -> stamp -> published leaf. The stamp stays above the
leaf because an elastic scale-up restamps `attn_dp_size`; the override stays on
top because that is how a test names a width.

## One answer for the config-derived predicates

`enable_mamba_extra_buffer` and its lazy variant, `is_ep_joiner`,
`is_ep_scale_joiner`, `is_startup_weight_load_overlap`: each existed as a
`ServerArgs` member for the resolution pipeline and, for most of them, again as
a `runtime_context` function for readers after publish. Three places to keep
saying the same thing.

A `Derived(fn=...)` is a pure function of the published configuration, so
`publish` computes it once and stores it as an ordinary bag leaf -- a plain
attribute load, which is what a read inside compiled model code needs. The
function is handed the whole resolved config rather than the bag it lands in,
because a derivation is free to span namespaces and the mamba one does: it
reads `memory.disable_radix_cache` alongside its own `exec.mamba` strategy,
which is why it could never have been a method on either bag.

The pre-publish helpers stay -- resolution needs the predicate before there is
a bag to read -- and three readers keep them, because they run before their own
process publishes: `initialize_dp_attention`, which the weight-cache daemon
calls while building its groups thirty lines before its `publish`, and
`PortArgs.init_new`, a factory handed the record that already reads eighteen
other fields off it.

## Notes for a reviewer

**Overriding a leaf does not move its quotient.** `override(tp_size=2)` leaves
`attn_tp_size` where the published config put it, because nothing is recomputed
on read. A test states a topology by publishing a config -- which is what a
real process does -- or by naming the width it wants, `override(attn_tp_size=2)`.
Six tests say it that way now. This is the price of having one answer computed
once, and it is the same price every other derived value in the config already
carries.

A caller that reads a quotient without publishing or overriding now gets an
explicit error naming the field, instead of a default that an uninitialised
group happened to supply. One fixture was in that state --
`TestMlaWriteDoorsUnderDcp` built a bare pool and asked whether DCP was on --
and it publishes a config now, which is what the process it stands in for
does.

Eighteen sites read these predicates without calling them. That is correct --
they are properties -- but it is worth saying they were checked, because a
census that assumes otherwise reports eighteen always-true conditions.

## The skill that documents this subsystem is updated with it

`.claude/rules/modify-component-must-read.md` points at
`.claude/skills/sglang-runtime-context/SKILL.md` before anyone touches these
files, so a stale sentence there is a wrong instruction rather than a stale
note. Four of its load-bearing statements stopped being true across this series
and are corrected here: `NS(...)` is no longer how a field states its namespace
(the declaring class is); the DCP degrade rule is gone, because the quotients
are not live reads; `mamba_extra_buffer_enabled()` and the other predicate
functions it named as the shape to copy no longer exist; and the
namespace-coverage ratchet is described in terms of the marker. The docstring of
`test_server_args_namespaces.py` said the same thing and is fixed too.

The consequence a test author actually trips over is stated there as well:
overriding a leaf no longer moves its quotient, so a topology is stated by
publishing a config or by naming the width.

## Verification

A full registered-unit sweep (648 files) against this stack's merge-base:
19 failures on both sides, the same 19 -- AMD `gfx950`, `modelopt`,
`cuda_vmm`, `weight_checker` and friends, none of them config. The narrower 139-file config sweep used earlier in this series
does not contain the files this change reaches -- `test_kv_index_translator`
never names `get_parallel()`, it constructs an object that does -- which is why
the baseline differential over everything is what is quoted here.
2026-09-06 21:44:24 -07:00
Cheng Wan b99175dc7d [Config] Round 6.4: the runtime reads the bags, not the record (#38049)
Last of four; stacked on #38048.

The record is the operator's input; the bags are what is in effect. A reader
that takes the record and reads a field off it gets the input, which is the
wrong one of the two whenever resolution decided something -- and the mistake is
silent, because for most fields and most launches the two agree. Several of
these files already read both ways, sometimes in the same expression:

```python
get_tokenizer(
    get_serving().tokenizer_path,
    tokenizer_mode=server_args.tokenizer_mode,   # the input, not the decision
    ...
)
```

Sixty-odd files convert. Record field reads in runtime code go from 199 to 11.
Nine parameters that the conversion emptied are dropped along with the argument
at every call site -- the dead-parameter ratchet is what names them.

### "Runs after its process publishes" is a per-entry-point claim

Most converted reads sit in the serving and model-executor layers, which only
exist after publication, or in the two subprocess entry points, which publish
first thing. Three places are not like that, and they keep reading the record
they were handed:

- **`HttpServerEngineAdapter`** launches the server as a *child*. The parent
  resolves the record and never publishes, so the adapter's own reads -- the
  launch banner, the API key in its readiness loop, the TP width in
  `update_weights_from_tensor` -- are of `self.server_args`. A bag read here
  fails closed in a bare process, or answers for an unrelated engine in one that
  happens to have published.
- **`serve_grpc`** reads its sidecar port before the integrated servicer builds
  the `Engine` that publishes. The comment above that line already said so and
  already bound `cfg = resolving_view(server_args)` for it; the sidecar port and
  the port it derives from read `cfg`.
- **`initialize_dp_attention`** runs from callers whose publish is not
  guaranteed, so its one predicate stays on the resolution view.

`ROLE_NAMESPACE_SETS["dp_controller"]` gains `observability` and `serving`,
because the controller's metrics gate, tracing setup and worker-port broadcast
now read those namespaces. Under `SGLANG_ROLE_NAMESPACES=enforce` that set is
what the process may read, so a conversion that reaches a new namespace has to
widen it in the same change.

## Three things worth a reviewer's attention

**Eleven reads were `getattr(record, "field", default)`.** An AST scan for
attribute access does not see those, so the census that said "43 readers" was
counting the shape it could match rather than the thing it was after.
`incremental_streaming_output` was read that way twice, and the transcription
tests were the only reason it surfaced.

**Not every record read is a bag read waiting to happen.** A multimodal
processor's `base_gpu_id` is the instance's, not the process's: two engines in
one process keep different ones, and
`test_publishing_another_config_does_not_move_the_device` exists to say so. It
stays on the record while `rl_on_policy_target` beside it moves.
`RequestMetricsExporter` is the same shape -- it is handed the directory it
writes to, and a test builds several with different ones. `configure_logger` is
a third: 17 call sites, one of which passes an `argparse.Namespace`, so it is
not a global-context reader at all. Those eleven remaining reads are the ones
with a reason.

**The fixtures move with the code.** Tests that hung config off a mock manager
now publish a record, which is what the serving layer reads; where a test states
a value it says so with `override_server_args` instead of assigning through the
mock. `test_hisparse_unit` is the last of them: it stubbed a `server_args` onto
a fake scheduler to say the decode radix cache was off, and the value it was
standing in for is the published default, so the stub goes and the class
publishes.

## Two things CI caught that a local sweep could not

**`unittest.TestCase.enterContext` is Python 3.11+.** The converted fixtures used
it at 18 sites; `requires-python` is `>=3.10` and CI runs 3.10, so every one of
them raised `AttributeError` there while passing on a newer local interpreter.
They call `enter_override(self, ...)` now -- a four-line helper in
`sglang/test/test_utils.py` over the override's own `install()` / `restore()`.

**A batched sweep cannot see a missing publish.** Three fixtures needed a
published config and did not have one; each *passed* inside a shard where some
other file had published, and failed when run alone. The affected cases are
`test_serving_completions` (which set `incremental_streaming_output` on the mock
manager's record, where nothing reads it now), `test_qwen3_vl_feature_materialization`
(same shape for `mm_enable_dp_encoder`), and the two Qwen Rust tests -- whose
fixture already carried the comment `# Non-auto: get_resolved_model_impl would
choke on a SimpleNamespace` next to the `model_impl` it sets, which is exactly
what happened once `get_mm_processor_cls` started reading that value from the
bag. Its `publish` mirrors `model_impl` now, like the four fields it already
mirrored.

## Verification

A full registered-unit sweep (648 files) against this stack's merge-base:
19 failures on both sides, the same 19, none of them config. That sweep is what
caught 23 failures the file-scoped runs missed -- and, later, that the narrower
139-file list did not even contain the files this change reaches. It is also
what caught the `test_hisparse_unit` fixture above: the file passes inside a
shard where something else published, and fails when it is run on its own,
which is why every failing file is re-run alone before it is counted.
2026-09-06 21:41:46 -07:00
sglang-botandsglang-bot 6252993afe chore: update CI test est_time values (#38238)
Co-authored-by: sglang-bot <sglang-bot@users.noreply.github.com>
2026-09-06 17:49:41 -07:00
55bf3380e0 Support Hy4-preview (#36805)
Co-authored-by: BBuf <1182563586@qq.com>
Co-authored-by: alphabetc1 <2508695655@qq.com>
2026-09-04 18:03:49 -07:00
Amy Chang 8a98f11078 [feature] Add response-level input/output token ids to chat completions via SglExt (#34488) 2026-09-04 16:45:13 -07:00
junduandMa Mingfei 8770c1db1f [CPU][CI]: rename Xeon CPU CI suites to stage-*-intel (#37395)
Co-authored-by: Ma Mingfei <mingfei.ma@intel.com>
2026-09-04 10:08:41 +08:00
3bac084d4e [Model] Add native IFM K2 Horizon serving support (#37654)
Co-authored-by: Xiaoyu Zhang <1182563586@qq.com>
Co-authored-by: Xinyuan Tong <xinyuantong.cs@gmail.com>
2026-09-03 16:39:43 +08:00
Alex NailsandAlison Shao 28262c20df [CI][RFC] Replace black-jupyter with ruff-format (#37210)
Co-authored-by: Alison Shao <a.shao@wustl.edu>
2026-09-02 19:46:08 -07:00
fbf909b460 [Fix] Alpha-channel images and tool-result media ordering (port of #36507) (#37320)
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: Xinyuan Tong <xinyuantong.cs@gmail.com>
Co-authored-by: Xinyuan Tong <115166877+JustinTong0323@users.noreply.github.com>
2026-09-02 18:23:06 -07:00
Eric Zhang 3904b309db Add configurable HTTP/2 connection window (#36920) 2026-08-29 13:18:42 +08:00
Cheng WanandClaude Opus 5 ef20fab38a config: the forwarding slots go; the dispatcher calls the family directly (#36792)
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-08-28 10:26:29 -07:00
97ba99067d Publish per-scheduler load on a dedicated socket for load-aware routers (#34608)
Co-authored-by: Kangyan Zhou <zky314343421@gmail.com>
Co-authored-by: Zhangheng <hzh0425@apache.org>
2026-08-27 19:33:18 +08:00
20621aa14b [Model] Support Ling-3.0-flash (BailingMoeV3) (#33561)
Signed-off-by: JustinTong <justintong0323@gmail.com>
Signed-off-by: Xinyuan Tong <xinyuantong.cs@gmail.com>
Co-authored-by: luoyuan.luo <luoyuan.luo@antgroup.com>
Co-authored-by: 得泽 <zhangkaihong.zkh@antgroup.com>
Co-authored-by: 翎悦 <vito.yy@antgroup.com>
Co-authored-by: 羽癫 <yudian.zy@antgroup.com>
Co-authored-by: tiwei.btw <tiwei.btw@antgroup.com>
Co-authored-by: Liangsheng Yin <hnyls2002@gmail.com>
Co-authored-by: 文赋 <zibin.zb@antgroup.com>
Co-authored-by: JustinTong <justintong0323@gmail.com>
2026-08-26 17:27:23 -07:00
Cheng Wan ae5feb4b9c config: stop handing the record to code that does not read it (#36252) 2026-08-26 05:02:17 -07:00
Cheng Wan d7b144f64e config: publishing is the process entry's job (#36251) 2026-08-26 04:58:41 -07:00
514b997e6c Register CPU CI for 17 e2e tests and partition xeon base-c suite (#35227)
Co-authored-by: Zhang, Mingxu <mingxu.zhang@intel.com>
Co-authored-by: MingxuZh <109504044+MingxuZh@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Claude <noreply@anthropic.com>
2026-08-24 10:49:38 +08:00
Cheng WanandClaude Opus 5 362c2ee849 config: borrowed-record reads follow the config bags (#35908)
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-08-23 01:19:20 -07:00
Connor Carpenter c3735625de fix(grpc): derive choice count before normalization (#35778)
Signed-off-by: Connor Carpenter <connorc@nvidia.com>
2026-08-21 11:29:52 -07:00
Mohammad Miadh AngkadandMohammad Angkad 61c2da42bb [Fix] Pass Anthropic thinking history as reasoning_content for custom chat encoders (#35480)
Co-authored-by: Mohammad Angkad <mohammad.angkad@radixark.ai>
2026-08-22 02:22:11 +08:00
Jiajun Li a4ef828207 fix(openai): avoid duplicate routed expert in response when return_meta_info = True (#35323) 2026-08-20 15:21:58 -07:00
Jason Wiemels defb2a3100 feat(openai): Accept the input_audio content part in chat completions (#33606) 2026-08-19 13:37:50 -07:00
Rohit Kumar SinghandSingh 3e5ce26c2d fix: fix transcription & audio-understanding for ASR/audio/speech models (#32611)
Co-authored-by: Singh <rohitsi2@iil-login.iind.intel.com>
2026-08-19 18:44:23 +08:00
Muqi LiandCodex 88f6074392 feat(api): add sglext_spec (#33518)
Signed-off-by: Muqi Li <muqi1029@gmail.com>
Co-authored-by: Codex <noreply@openai.com>
2026-08-19 11:54:18 +08:00
307a90f6d3 Stop losing Kimi-K3 tool calls to reasoning, constraint conflicts, and truncation (#34881)
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: Xinyuan Tong <xinyuantong.cs@gmail.com>
Co-authored-by: Xinyuan Tong <115166877+JustinTong0323@users.noreply.github.com>
2026-08-18 12:42:56 -07:00
Jiajun Li e6df23f3c2 refactor: rename chat response token IDs (#35225) 2026-08-17 23:07:43 -07:00
Cheng Wan b3c8f0d923 config: one control-plane log for the process (#35028) 2026-08-17 16:19:00 -07:00
Cheng Wan c70c7d72a8 config: the readback and the resolving view say what they are (#35027) 2026-08-17 16:18:19 -07:00
Cheng Wan a97bc8db32 config: the DP/EP topology reads come from the parallel bag (#35025) 2026-08-17 16:17:26 -07:00
Lianmin ZhengandYe Qi 32e6fb4fdc [Frontend] Apply request header overrides to chat completions (#35001)
Co-authored-by: Ye (Charlotte) Qi <ye.charlotte.qi@gmail.com>
2026-08-16 15:08:47 -07:00
cctryandYilong Zhao e5b3a48751 Add --http2-max-concurrent-streams server arg (#34796)
Co-authored-by: Yilong Zhao <74357408+happierpig@users.noreply.github.com>
2026-08-15 10:34:49 -07:00
Shenxiu Liu fb97be4359 Fix Whisper transcription for audio over 30 seconds (#33604) 2026-08-15 23:51:05 +08:00
gilfordtingandJames Liu 6f005e4da1 [Fix] Require JSON booleans for response_format json_schema.strict (#34777)
Co-authored-by: James Liu <jamesl@modal.com>
2026-08-14 16:46:27 -07:00
Nan Jiang be804c1b83 [RL] Expose top-p-only sampling masks (#33593) 2026-08-14 16:40:27 -07:00
Mick e8c7dddfa0 [VLM] add content-addressed preprocessing cache infrastructure (#34398) 2026-08-13 14:09:07 +08:00
jthomson04 385903b0ac feat: add cache salt support to KV cache events (#30827)
Signed-off-by: jthomson04 <jwillthomson19@gmail.com>
2026-08-12 16:14:04 -07:00
fde9ad2531 [Feature] Add Muse Glimmer model support (#34262)
Co-authored-by: sglang-bot <232288953+sglang-bot@users.noreply.github.com>
Co-authored-by: Brayden Zhong <brayden.zhong@radixark.ai>
Co-authored-by: Jimmy Shong <69131491+Jiminator@users.noreply.github.com>
Co-authored-by: hnyls2002 <lsyincs@gmail.com>
Co-authored-by: Alex Nails <alex.nails@radixark.ai>
Co-authored-by: Liangsheng Yin <hnyls2002@gmail.com>
2026-08-11 15:41:52 -07:00