realtime_engine — a standalone realtime inference engine
A standalone realtime inference engine, driven entirely through inbox/outbox queues — so any caller matching the contract can run it.
This follows the design's build order: prove the engine on its own first (the queue boundary gives isolation now, and a path to a process/IPC split later without a process boundary today). Full design write-up lives in Notion.
Contents
- Layout
- Batched engines: the lockstep cohort
- Develop & test
- Contract recap
- Next (not built yet)
Layout
Standard src/ layout: src/realtime_engine/ (package) + tests/ + pyproject.toml.
| module | what |
|---|---|
contract.py |
RealtimeInterface (Protocol) + EngineManifest / SessionInit / StepResult / AdmissionError — Level 1: manifest/attach/step/finalize/detach |
queues.py |
the boundary: inbox msgs (Attach/Detach/Reset/Action) + Chunk; Inbox/Outbox (asyncio.Queue wrappers) |
serve.py |
default_serve — the Level-2 loop a Level-1 engine reuses (drain → batched step → outbox → finalize → tick; generate-from-default); run_engine picks an engine's own serve if it has one |
composed.py |
ComposedEngine — the generic lockstep-cohort batched engine (slot arena + two-stream output pipeline + isolated heavy-encode side lane), driven by a StageModel's lane-tagged Stage list (Lane / StageBatch) |
replica.py |
ReplicaEngine — one isolated child Level-1 engine per session, pooled after successful detach; the B=1 correctness oracle and non-batched fallback |
cpu_reference.py |
CpuReferenceEngine — numpy-only deterministic fake (no GPU/ML); proves admission, batching, invariance, distinctness |
cpu_stage_model.py |
CpuStageModel — numpy-only reference StageModel (+ worked example); its chunk is a pure function of (seed, age, cheap conditioning, applied heavy value), so the cohort semantics are equality-assertable |
tests/test_engine.py |
standalone tests that feed the inbox and drain the outbox |
tests/test_composed.py |
the cohort semantics: arena/admission, invariance, distinctness, membership boundaries, deferred lag, heavy-encode isolation, failure recovery |
tests/test_replica.py |
replica routing, pooling, B=1 parity, and per-child failure isolation |
Batched engines: the lockstep cohort
ComposedEngine is the batching machinery written once, so a model is just a
StageModel: a manifest, an ordered list of lane-tagged stages, and seed/detach.
- Lanes.
Lane.HOTis the critical path (denoise/KV-finalize) and produces the latent.Lane.DEFERREDdecodes chunk N-1 while HOT produces N: together they are the steady-state two-stream output pipeline.Lane.ENCODEbatches changed rows on an on-demand third stream, so an over-budget prompt/image encode cannot queue ahead of the next decode and stall unrelated rows. ENCODE stages must mutate only those rows and avoid unsynchronized shared workspaces. - Arena.
max_sessionsfixed rows;attachtakes the lowest free row (over capacity →AdmissionError= backpressure, and re-attaching an already-attached session is idempotent);detachfrees the row for reuse. - Arming. Rows accumulate as pending until the optional
StageModel.seed_ready(pending)says go (default: as soon as any row is pending); thenseedis called once for the whole pending set, on the HOT stream at a step boundary. This is a scheduler gate, not an application-input gate: the caller should sendAttachonly after required prompt/image/scene context exists. A join preserves residents' in-flight output. A detach drains all execution lanes before releasing its row and removes only that row from a deferred snapshot. Drain the arena and the next attach re-seeds — that is what makes Reset (detach + re-attach) work.midrun_attach=Falserejects a later arrival instead of seeding it incrementally. - Warm-up chunk. When pipelined,
DEFERRED(chunk N-1)runs on the overlap lane whileHOT(chunk N)runs on the hot lane, so the first step emits nothing andmanifest().pipeline_depth_chunksis 2 (else 1). This is distinct frominput_latency_chunks: a cheap action can still affect the next generated chunk. Non-pipelined the two stages run sequentially in one step and emit immediately — the b=1 shape. - Bystander isolation. A change to a heavy conditioning key (declared by the
optional
StageModel.heavy_keys()) batches all changed rows throughENCODE; each row sits out until its event completes (normally one chunk) and rejoins with the new value applied. A slow encode stays isolated while ready rows keep advancing. The default equality handles nested Python values and NumPy arrays; tensor/revision-heavy models can provideheavy_equal(). - Failure boundary.
seed,detach, and stage failures propagate after execution lanes are drained; the in-flight output batch is discarded rather than emitted stale or twice. Stage implementations must be boundary-atomic, because a generic scheduler cannot roll back a partially mutated KV/cache.ReplicaEnginecatches step/finalize failures per child so an unhealthy session cannot suppress bystanders; a failed detach retains ownership and is never pooled. - Torch-optional. A lane is a real CUDA stream when torch + CUDA are present
and a no-op passthrough otherwise, so there is exactly one step body and the CPU
path never imports torch.
torchis not a dependency: CUDA availability is probed cheaply at construction (so the manifest is stable), while stream creation is deferred to the firststep—torch.cuda.streamis thread-local and the engine is constructed on the load thread but stepped ondefault_serve's pinned worker thread.
Develop & test
cd backend/realtime_engine
pip install -e ".[dev]"
ruff check src tests && black --check src tests && isort --check-only src tests && mypy src/realtime_engine
pytest -q
Tests cover: distinctness (co-resident sessions differ), invariance (a session is
identical solo vs batched), admission (over-capacity attach raises
AdmissionError), finalize, and output shape — plus, for the batched engines, the
slot arena and row reuse, membership only at chunk boundaries, the deferred lane's
exactly-one-chunk lag, once-per-change heavy encodes with bystander isolation,
lossless pipelined join/detach, due-subset ages, NumPy conditioning equality,
over-budget encode isolation, lifecycle stream ordering, and stage failure
recovery, plus ReplicaEngine routing, pooling, B=1 parity, and failure isolation.
All run with the engine standalone. Lint/type/test also run in CI
(.buildkite/pipeline.yml).
Contract recap
- Level 1 (every engine):
manifest/attach/step(due) -> [StepResult]/finalize/detach.stepis batched (oneStepResultper due session). - Level 2 (the loop): optional
serve(inbox, outbox). Omit it →default_serve. Implement it → own loop (e.g. an sglang-style scheduler). - Conditioning arriving via
Actionis action-class (already client→action-translated by the caller); the engine stays ignorant of client semantics. - Latency uses separate manifest fields:
input_latency_chunksfor action-to-generation responsiveness andpipeline_depth_chunksfor output warm-up.
Next (not built yet)
- A real GPU model behind
ComposedEngine: the WaypointStageModellives in reactor-models, in a separate PR — this package stays ML-free (sole dep: numpy). - The runtime caller: a
ReactorModelthat pumps the inbox (state →Action) and routes the outbox into streaming. - Open validation item (flagged in review): measure whether the outbox queue adds latency vs a direct callback.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file reactor_realtime_engine-0.2.1.tar.gz.
File metadata
- Download URL: reactor_realtime_engine-0.2.1.tar.gz
- Upload date:
- Size: 33.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/6.2.0 CPython/3.10.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
08ab450e8aa17f26032a46c14007ad7d1236a5f6dc9aad8bc817920a3c694ac9
|
|
| MD5 |
b2cfa62fdce0cf03010dcf5fe62d2881
|
|
| BLAKE2b-256 |
65a484d96b1db5145f53294467c929915196ecf9e27ed85523c3011f48453c0c
|
File details
Details for the file reactor_realtime_engine-0.2.1-py3-none-any.whl.
File metadata
- Download URL: reactor_realtime_engine-0.2.1-py3-none-any.whl
- Upload date:
- Size: 30.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/6.2.0 CPython/3.10.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b53eb33799cc82c026822a081c26c5fbfeaf43c1d606542ea1887a0b4bd73ea3
|
|
| MD5 |
6dc8ba27ecc81bcf9044ed481425e519
|
|
| BLAKE2b-256 |
e4b0a0f4f4675a649aadaec7afe519b83f518f907adccb4c8cf15b9671cab3a9
|