Current Status
SGLang-Omni already has solid support for foundational omni models:
Leveraging SGLang's kernel-level optimizations, we have further applied torch.compile and CUDA Graph capture to many smaller components, yielding significant performance improvements.
Core Issues
The codebase exhibits clear signs of vibe coding — rapid iteration has accumulated substantial redundancy and over-abstraction. Specifically:
Excessive Abstraction Layers
A single request must pass through the following layers from HTTP API to torch.forward:
HTTP API → Client → Coordinator → Stage → Worker → Executor → Engine → Scheduler → ModelRunner → torch.forward
Among these, Stage → Worker → Executor → Engine are four consecutive layers whose responsibilities heavily overlap: each one essentially "receives a request, delegates execution, and returns results." Based on experience from the SGLang main repo, we should be able to go directly from Stage → Engine, eliminating the Worker and Executor layers entirely.
[We defined the Torch version first, then implemented the SGLang backend. As we will detach the torch implementation, we can make it rather concise.]
[TTS/ASR ModelRunner should be combined? Qwen-TTS using a diffusion-like ModelRunner. We should take into consideration. Adarsh's implementation of Qwen-TTS by Torch backend #76 . We need a dedicated RFC on what SGLang ModelRunner could support.]
[Should we remove the Torch backend or still have it?]
[(Least priority) Pipeline: trying to place multiple stages on a single GPU. Modify SGLang RunTime for this could work. Also considering the stage of fusing to cutting off communication.]
Conflicting Same-Named Concepts Create Cognitive Overhead
| Concept |
Instances |
Location |
Justified? |
Scheduler |
2 |
engines/omni/scheduler.py vs engines/ar/sglang_backend/scheduler/ |
Needs unified naming |
ModelRunner |
3 |
engines/omni/model_runner.py, engines/omni/runtime/sglang_ar.py, engines/ar/sglang_backend/model_runner.py |
Needs unified naming |
Message |
2 |
client/types.py vs fishaudio_s2_pro/fish_speech/conversation.py |
Justified — different domain concepts |
The Connection instances across different relay backends (nixl vs nccl) are justified, as they describe connection semantics for different transport protocols with naturally isolated namespaces. The real issues to address are the naming collisions for Scheduler and ModelRunner.
Too Many Adaptation Layers, Bloated Glue Code
EngineExecutor uses getattr to dynamically delegate prepare_stream, stream, start, and stop, essentially translating the Engine interface into the Executor interface — the two are nearly isomorphic. Any dynamic attribute delegation is a signal of bad design, indicating unclear interface definitions.
Engine(ABC) and Executor(ABC) have highly similar method signatures (add_request, get_result, abort), differing only in data types (StagePayload vs Any).
FusedExecutor chains multiple Executor instances, but in practice, stage fusion in the pipeline config already handles this at compile time.
Code Redundancy
| Redundancy |
Lines |
Description |
config/qwen3_omni.py |
~378 |
Entirely duplicates models/qwen3_omni/hf_config.py, with zero references across the codebase |
| Relay Put/Get pattern |
~400 |
Polling + timeout + callback pattern repeated across 4 relay implementations (shm, nccl, nixl, mooncake) |
| Test dummy classes |
~200 |
Duplicate definitions across test_scheduler.py, test_scheduler_streaming.py, test_factory.py |
_inject_multimodal_embeds |
~150 |
Highly similar mask-based embedding injection logic in sglang_ar.py and s2pro_sglang_ar.py |
Large File Concentration
Total codebase is ~33K lines (.py), with 15 files exceeding 500 lines. The largest, text2semantic/modeling.py, reaches 1,484 lines. sglang_ar.py (1,040 lines) consolidates BatchPlanner, ResourceManager, OutputProcessor, IterationController, and ModelRunner into a single file — far too many responsibilities.
Refactoring Goals
- Eliminate at least two layers of excessive abstraction, reducing the request path from 8–10 layers to 6.
- Substantially reduce total code volume (target: from ~33K lines to under ~10K lines).
- Maintain existing functionality and performance — the refactoring must not introduce regressions.
- Lower the cost of onboarding new models — adding a new model should only require implementing the model definition + pipeline config, without needing to understand this many middleware layers.
Current Status
SGLang-Omni already has solid support for foundational omni models:
talker_jingbranch) and needs to be rebased ontomain.Leveraging SGLang's kernel-level optimizations, we have further applied torch.compile and CUDA Graph capture to many smaller components, yielding significant performance improvements.
Core Issues
The codebase exhibits clear signs of vibe coding — rapid iteration has accumulated substantial redundancy and over-abstraction. Specifically:
Excessive Abstraction Layers
A single request must pass through the following layers from HTTP API to
torch.forward:Among these, Stage → Worker → Executor → Engine are four consecutive layers whose responsibilities heavily overlap: each one essentially "receives a request, delegates execution, and returns results." Based on experience from the SGLang main repo, we should be able to go directly from Stage → Engine, eliminating the Worker and Executor layers entirely.
[We defined the Torch version first, then implemented the SGLang backend. As we will detach the torch implementation, we can make it rather concise.]
[TTS/ASR ModelRunner should be combined? Qwen-TTS using a diffusion-like ModelRunner. We should take into consideration. Adarsh's implementation of Qwen-TTS by Torch backend #76 . We need a dedicated RFC on what SGLang ModelRunner could support.]
[Should we remove the Torch backend or still have it?]
[(Least priority) Pipeline: trying to place multiple stages on a single GPU. Modify SGLang RunTime for this could work. Also considering the stage of fusing to cutting off communication.]
Conflicting Same-Named Concepts Create Cognitive Overhead
Schedulerengines/omni/scheduler.pyvsengines/ar/sglang_backend/scheduler/ModelRunnerengines/omni/model_runner.py,engines/omni/runtime/sglang_ar.py,engines/ar/sglang_backend/model_runner.pyMessageclient/types.pyvsfishaudio_s2_pro/fish_speech/conversation.pyThe
Connectioninstances across different relay backends (nixl vs nccl) are justified, as they describe connection semantics for different transport protocols with naturally isolated namespaces. The real issues to address are the naming collisions forSchedulerandModelRunner.Too Many Adaptation Layers, Bloated Glue Code
EngineExecutorusesgetattrto dynamically delegateprepare_stream,stream,start, andstop, essentially translating theEngineinterface into theExecutorinterface — the two are nearly isomorphic. Any dynamic attribute delegation is a signal of bad design, indicating unclear interface definitions.Engine(ABC)andExecutor(ABC)have highly similar method signatures (add_request,get_result,abort), differing only in data types (StagePayloadvsAny).FusedExecutorchains multipleExecutorinstances, but in practice, stage fusion in the pipeline config already handles this at compile time.Code Redundancy
config/qwen3_omni.pymodels/qwen3_omni/hf_config.py, with zero references across the codebasetest_scheduler.py,test_scheduler_streaming.py,test_factory.py_inject_multimodal_embedssglang_ar.pyands2pro_sglang_ar.pyLarge File Concentration
Total codebase is ~33K lines (
.py), with 15 files exceeding 500 lines. The largest,text2semantic/modeling.py, reaches 1,484 lines.sglang_ar.py(1,040 lines) consolidates BatchPlanner, ResourceManager, OutputProcessor, IterationController, and ModelRunner into a single file — far too many responsibilities.Refactoring Goals
We move the design to https://njpxzlfqwrqq.jp.larksuite.com/wiki/VTcEwGVEuihm6xkquEdjc424pNb?from=from_copylink