Skip to content

SGLang-Omni Refactoring Proposal #188

Description

@zhaochenyang20

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

  1. Eliminate at least two layers of excessive abstraction, reducing the request path from 8–10 layers to 6.
  2. Substantially reduce total code volume (target: from ~33K lines to under ~10K lines).
  3. Maintain existing functionality and performance — the refactoring must not introduce regressions.
  4. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions