diff --git a/rust/Cargo.toml b/rust/Cargo.toml index af8dd531d..943cd515b 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -1,6 +1,10 @@ [workspace] resolver = "3" -members = ["sglang-grpc", "sglang-mm"] +members = [ + "sglang-grpc", + "sglang-mm", + "sglang-server" +] [workspace.package] version = "0.1.0" @@ -12,11 +16,16 @@ license = "Apache-2.0" # where needed). [workspace.dependencies] async-stream = "0.3" +bytes = "1" +futures = "0.3" pyo3 = { version = "0.29.0", features = ["extension-module"] } +serde = { version = "1", features = ["derive"] } serde_json = "1" +thiserror = "2" tokio = { version = "1", features = ["full"] } tokio-stream = { version = "0.1", features = ["net"] } tracing = "0.1" +tracing-appender = "0.2" tracing-subscriber = { version = "0.3", features = ["env-filter"] } uuid = { version = "1", features = ["v4"] } diff --git a/rust/sglang-server/Cargo.toml b/rust/sglang-server/Cargo.toml new file mode 100644 index 000000000..71f6023d1 --- /dev/null +++ b/rust/sglang-server/Cargo.toml @@ -0,0 +1,40 @@ +[package] +name = "sglang-server" +description = "Sglang server in rust" +version.workspace = true +edition.workspace = true +license.workspace = true + +# Consumed by python/setup.py: registers this crate as a PyO3 extension module. +[package.metadata.sglang] +python-module = "sglang.srt.server._core" + +[lib] +name = "sglang_server" +# cdylib: the pyo3 module imported by the (embedded) Python scheduler process. +# rlib: so optional standalone bins / integration tests can link the core. +crate-type = ["cdylib", "rlib"] + +[dependencies] +async-stream = { workspace = true } +bytes = { workspace = true } +futures = { workspace = true } +pyo3 = { workspace = true } +serde = { workspace = true } +serde_json = { workspace = true } +thiserror = { workspace = true } +tokio = { workspace = true } +tracing = { workspace = true } +tracing-subscriber = { workspace = true } +tracing-appender = { workspace = true } +uuid = { workspace = true } + +axum = { version = "0.8.9", features = ["json", "tokio"] } +core_affinity = "0.8" +# the dynamo-tokenizers is deps on hf-hub, should bump version together +dynamo-tokenizers = "1.5.3" +flume = "0.12.0" +hf-hub = { version = "0.4", default-features = false } +regex-syntax = "0.8" +rmp-serde = "1" +rmpv = { version = "1", features = ["with-serde"] } diff --git a/rust/sglang-server/pyproject.toml b/rust/sglang-server/pyproject.toml new file mode 100644 index 000000000..1d2c1c424 --- /dev/null +++ b/rust/sglang-server/pyproject.toml @@ -0,0 +1,16 @@ +[build-system] +requires = ["maturin>=1.13,<2.0"] +build-backend = "maturin" + +[project] +name = "sglang-server" +requires-python = ">=3.10" +classifiers = [ + "Programming Language :: Rust", + "Programming Language :: Python :: Implementation :: CPython", + "Programming Language :: Python :: Implementation :: PyPy", +] +dynamic = ["version"] + +[tool.maturin] +module-name = "_core" diff --git a/rust/sglang-server/src/lib.rs b/rust/sglang-server/src/lib.rs new file mode 100644 index 000000000..ab23f963c --- /dev/null +++ b/rust/sglang-server/src/lib.rs @@ -0,0 +1,19 @@ +//! sglang-server: a multi-threaded Rust frontend (API server → TokenizerManager +//! → Tokenizer/Detokenizer) embedded in the Python scheduler process. +//! +//! Pipeline stages 1–5 are pure Rust and never touch a `PyObject`, so they run +//! concurrently with the Python scheduler without contending for the GIL. The +//! only GIL crossings are the boundary methods on [`Server`]: +//! * `recv_requests` — Python scheduler thread drains the ingress ring. +//! * `push_batch` — Python scheduler thread pushes one output batch. +//! * `push_result` — Python scheduler thread pushes one control result. +//! +//! All are non-blocking, so the GIL is never held across a wait. +#![allow(dead_code)] // TODO: remove when the consumer PR lands + +use pyo3::prelude::*; + +#[pymodule] +fn _core(_m: &Bound<'_, PyModule>) -> PyResult<()> { + Ok(()) +}