EngineDriver trait)Make third-party inference engines (gr8, DGPP, future ones) first-class
engine values in a recipe — served/stopped/logged/health-probed/benched by
the same sm121 commands as vllm/sglang — instead of hand-deployed outside
the launcher. The operator directive: engines like dgpp/gr8 must be
"равноправные члены наравне с vllm/sglang/tmux".
engine is a free String (default "vllm"); only vllm/sglang have any
launcher logic, and it is duplicated across six sites, each branching on
recipe.engine == "sglang":
| Site | Engine-specific behaviour |
|---|---|
engine_flags.rs::build_engine_args |
model arg (--model-path vs positional), distributed rendezvous flags (vLLM set vs SGLang set), --headless for vLLM workers |
docker/command.rs::collect_nccl_env |
worker-IP env: SGLANG_WORKER_IP vs VLLM_HOST_IP |
tmux/commands.rs |
entrypoint fallback (python -m vllm… / python -m sglang…), port on all nodes (SGLang) vs head-only (vLLM) |
tmux/mod.rs::build_host_ip_export |
host-IP env var per engine |
doctor.rs |
install hint (pip install vllm / sglang) |
publish_render.rs |
SGLang special-case in the rendered bundle |
Three orthogonal axes, each a first-class concept:
engine → an EngineDriver (the inference-engine semantics).deploy → Docker | Tmux | Native (new) — how the process is
started on a host (container / tmux session / bare SSH command).launch_shape → PerNode (every launch node runs the engine; vLLM,
SGLang, gr8) | HeadCoordinated (rank 0 runs a cluster manager that
brings up the peers itself; DGPP).EngineDriver trait (in src/engine.rs)// Head-coordination is the deploy target (`deploy = "native"` = rank 0 runs
// the engine's cluster manager), not a separate trait axis.
pub trait EngineDriver: Send + Sync {
// Model argument (positional for vLLM, --model-path for SGLang,
// --model for gr8, none for DGPP — the cluster JSON carries it).
fn model_args(&self, recipe: &Recipe) -> Vec<String>;
// Distributed rendezvous flags (vLLM/SGLang/gr8 sets; DGPP: none — the
// JSON carries world_size + rendezvous).
fn distributed_args(&self, ctx: &EngineFlagsCtx, node: &Node) -> Vec<String>;
// Non-head workers run headless (vLLM yes; SGLang/gr8/DGPP no).
fn headless_workers(&self) -> bool { false }
// Env var carrying the node's bind IP (VLLM_HOST_IP / SGLANG_WORKER_IP / none).
fn engine_ip_env(&self) -> Option<&'static str> { None }
// Takes --host/--port (vLLM head, SGLang all). Engines with a fixed API
// port (gr8 :8100, DGPP :18080) return false — no --host/--port, and
// `validate` exempts them from the port-convention rule.
fn takes_host_port(&self) -> bool { true }
// tmux entrypoint fallback when the recipe sets none.
fn entrypoint_default(&self) -> Vec<String>;
// doctor install hint.
fn install_hint(&self) -> &'static str;
}
A registry driver_for(engine: &str) -> &dyn EngineDriver maps the recipe's
engine string to a driver (vllm, sglang, gr8, dgpp; unknown → the
vLLM driver, matching today's default). build_engine_args and the five other
sites delegate to it. Phase 1 is a pure refactor — vLLM/SGLang drivers
reproduce the current behaviour byte-for-byte, all existing tests stay green.
EngineFlagsCtx gains peersgr8 takes --peers <ip0>,<ip1>,… (the ordered launch-node IPs; each rank
finds itself in the list). Add peers: &[String] to the ctx (vLLM/SGLang
ignore it).
kindlingai/gr8)deploy = docker (image ghcr.io/kindlingai/gr8), per-node launch.["/opt/gr8/gr8", "glm53", "up"]; model_args → --model <repo>;
distributed_args → --tp <N> --peers <list>; no --headless, no engine-IP
env, takes_host_port = false (API :8100 on the first peer).--model-cache, --drafter, --shape in args; the
vm.compaction_proactiveness=0 prerequisite is a before_serve host hook.docker stop works (the container is the engine).HawkBearPig/dgpp)deploy = native (new), head-coordinated: rank 0 runs the manager.[dgpp] block carries http_port, dir (the DGPP checkout on
the nodes), optional release, and a free-form [dgpp.engine] table. The
launcher generates DGPP's cluster JSON (model, world_size, http, and
the engine table serialized verbatim) plus a sibling .env
(DGPP_NODES/DGPP_SSH_USER/ports), uploads both to <dir> on rank 0, and
runs scripts/dgpp-cluster up --config <file> there (nohup, log under
<dir>/log/). Stop runs scripts/dgpp-cluster down on rank 0./v1/models probe on http_port (default 18080).engine: Phase 1 commit)peers ctx + takes_host_port + a glm53-full-tp4-gr8
recipe; validate + dry-run render the exact gr8 glm53 up contract. ✅Native deploy (head-coordinated) + DGPP driver + [dgpp] config-JSON
generation + a qwen38-27b-nvfp4-dgpp recipe; dry-run renders the JSON/.env
upload + dgpp-cluster up/down. ✅ (native serve/stop live-tested on first
real DGPP deploy)engine.rs holds the trait + registry + the four drivers;
split drivers into engine/gr8.rs etc. if it grows.#[allow] for clippy — refactor instead.