A milestone is complete only when its acceptance criteria, correctness evidence, and required measurements are recorded. Performance work must state a hypothesis, compare a baseline on the same hardware, and preserve deterministic correctness. GPU results record GPU, driver, CUDA, model and revision, dtype, input/output lengths, batch or concurrency configuration, commit hash, and build features.
Goal: Establish a maintainable project without premature crate or trait boundaries.
Dependencies: Stable Rust; no GPU required.
Deliverables:
- one Cargo package, typed CLI, typed errors, structured tracing, and feature-gated CUDA;
- architecture, roadmap, dependency policy, benchmark instructions, README, and contribution guide;
- CI for format, build, test, and Clippy;
- local/Hub artifact resolution, sharded index discovery, config parsing, tokenizer validation, and an explicit model registry;
- unresolved decisions listed in the architecture document.
Acceptance: cargo build --locked, cargo test --locked --all-targets,
cargo fmt --all --check, and strict Clippy pass on a non-CUDA host. The inspect
command recognizes a valid local fixture and rejects unsupported architectures
or missing/unsafe shard paths.
Benchmark deliverable: Define the result schema and measurement methodology; do not add meaningless microbenchmarks.
Status: CPU/F32 complete (July 2026). CUDA/BF16 runtime and benchmark validation pass on RTX 5090; exact PyTorch CUDA/BF16 greedy parity is pending.
Selected model: Qwen3-0.6B (Qwen/Qwen3-0.6B, commit
c1899de289a04d12100db370d81485cdf75e47ca), BF16 dtype at the checkpoint.
Deliverables:
- typed
Qwen3Configwith semantic validation for architecture, dimensions, GQA ratios, head_dim, dtypes, RoPE scaling, sliding window, token-ID bounds); - raw-tokenizer encoding with
add_special_tokens=false; - SafeTensors full-buffer loading and validation: 311 BF16 tensors, exact names
and shapes, tied-weight verification, and an owned
Vec<u8>before device transfer; - Candle primitives: RMSNorm, precomputed RoPE, GQA attention, SwiGLU MLP;
- 28-layer decoder with pre-norm residual structure and causal masked attention;
- preallocated contiguous per-layer KV cache (
[1, Hkv, capacity, Dh]), BF16 or F32, allocated once per request; - cached decode loop using the same
forward_cachedpath as prefill; generateCLI command:--model,--prompt,--max-new-tokens,--device,--dtype;- timing metrics:
model_load_ms,prefill_ms,ttft_ms,mean_tpot_ms,decode_tokens_per_sec, resolved device and dtype; - BF16 preflight probe on selected device before weight loading;
- eager-attention operational prefill cap of 2,048 prompt tokens, separate from the model's 40,960-position semantic limit;
- EOS token IDs loaded from
generation_config.json(falls back toconfig.json); - deterministic Python reference oracle (
tools/reference_qwen3.py) with pinned dependency versions and SHA-256 model identity validation.
Acceptance:
cargo run -- generate --model models/Qwen3-0.6B --prompt "Hello"prints a decoded continuation on stdout and metrics on stderr;- CPU/F32 tokenizer IDs, selected tensors, decoded text, and exact 32-token greedy output match the pinned reference fixture;
- cached decode matches full-context recomputation token-by-token;
- all quality gates pass on a non-CUDA host;
- CUDA/BF16 passes a preflight probe, generation smoke test, and recorded benchmark on RTX 5090;
- CUDA/BF16 is not considered numerically complete until its first divergence from the matching PyTorch oracle is localized and resolved or accepted through a documented backend-specific correctness policy.
Status: Complete (July 2026). See docs/milestone-2-report.md.
Goal: Separate model execution from request and sequence lifecycle.
Dependencies: Correct Milestone 1 generation path.
Implemented deliverables:
- a public library API with
EngineConfig,Engine,GenerationRequest,GenerationHandle, request IDs, greedySamplingParams, token events, terminal summaries/failures, and classified finish reasons; - a named dedicated model-runner thread with a capacity-one readiness handshake;
- one-time worker ownership of the tokenizer, Qwen3 model, device/dtype, EOS configuration, and startup metrics;
- a bounded capacity-eight Crossbeam command queue and bounded per-request event channels sized for all requested tokens plus one terminal event;
- serialized FIFO request execution: one active sequence, no batching or interleaving, with multiple sequential requests reusing the loaded model;
- a concrete worker-private
ModelRunnerthat owns Candle execution and exposes cache allocation, prefill, decode, and synchronization without CLI/channel dependencies; - a worker-private
Sequencestate machine with checkednum_computed_tokens, cache-length equality, and a fresh contiguous cache per request; - tokenizer-safe incremental text using
DecodeStream, plus final trailing-text reconciliation against a complete decode; - cooperative cancellation through
GenerationHandle, handle-drop cancellation, receiver-drop detection, explicit/idempotent shutdown, queued request draining, and worker joining; - startup, submission, recoverable request, fatal worker, and panic failure paths;
- worker-owned queue, tokenization, prefill, TTFT, per-step decode, TPOT, throughput, and total-generation metrics, with model-load time separated into startup metrics;
- a thin CLI that only starts the engine, submits, consumes events, prints the returned text/metrics, and shuts down.
Acceptance:
- the CLI has no direct tokenizer/model/cache/sampling calls;
- the model runner contains no CLI, channel, request-ID, or future HTTP types;
- public API integration tests preserve the canonical 32-token CPU/F32 output, exercise two sequential requests, reconstruct final text from streamed fragments, cancel after a token, and successfully execute a later request;
- sequence tests enforce
num_computed_tokens <= total tokensand cache length equality, including stale-cache rejection; - accepted attached requests emit ordered tokens and exactly one terminal event;
- shutdown rejects new submissions, cancels active/queued requests at safe boundaries, and joins the worker;
- all required repository gates and local ignored tests pass.
Benchmarks: The fake worker benchmark delivered 320,000 token events across
10,000 requests and measured first-event, buffered per-token/terminal receive,
shutdown/join, and queue-overload behavior. The CPU/F32 regression used one
warmup and five
candidate samples against the retained Milestone 1 artifact. Median TTFT was
68.3 ms versus 75.0 ms; median TPOT was 69.3 ms versus 74.2 ms. Both pass the
max(5%, 1 ms) regression threshold. The retained baseline has one sample, so
baseline spread and true interleaving could not be reconstructed.
Status: Complete (July 2026). See docs/milestone-3-report.md.
Goal: Expose the engine through an OpenAI-compatible network boundary.
Dependencies: Milestone 2 completion gates and a stable submit/event/cancel/shutdown lifecycle.
Implemented deliverables:
- Tokio/Axum server with
GET /health,GET /ready,GET /v1/models,POST /v1/completions, andPOST /v1/chat/completions; - strict OpenAI-shaped request/response DTOs, model identity, usage accounting, public request IDs, and stable structured public errors;
- streaming completion/chat SSE chunks with one terminal
[DONE], and matching non-streaming responses; - one finite
spawn_blockingevent consumer per accepted generation, forwarding into a bounded Tokio channel without moving model execution off its existing dedicated worker; - bounded HTTP admission, explicit
429overload, slow-consumer timeout, disconnect cancellation, task tracking, and no unbounded response buffer; - liveness separated from readiness, with readiness reading maintained engine and admission state without model execution;
- Qwen3
tokenizer_config.jsonchat-template compilation, text-only ordered roles, assistant generation prompt, and thinking disabled by default; - SIGINT/SIGTERM graceful shutdown that stops admission, cancels bridge and engine work cooperatively, joins the worker, and awaits tracked bridge tasks;
- local directory or Hugging Face model source configuration, with synchronous Hub resolution during worker startup;
- documented compatibility subset that rejects sampling controls,
stop, tools, multimodal content, multiple choices, prompt arrays, logprobs, response-format controls, and unknown fields.
Acceptance:
- fake-backend tests prove handlers use the engine boundary, structured errors
are stable, health/model routes never submit work, queue full maps to
429, streams are ordered and terminate once, body limits are enforced, and readiness observes fatal worker state; - bridge tests prove ordered bounded forwarding, terminal-event finality, receiver-drop cancellation, slow-consumer cancellation, and tracked cleanup;
- ignored local CPU/F32 HTTP tests verify completion/chat stream versus
non-stream text equality, the canonical direct Engine 32-token ID sequence,
[DONE], disconnect recovery, and graceful process shutdown with the pinned Qwen3 model; - fake HTTP collector tests record the exact ordered IDs consumed by JSON and
SSE and verify both translate
Hello, 32 tokens, and greedy sampling identically; - no Axum handler owns or invokes the tokenizer, Qwen3 model, Candle tensor, KV cache, device, or model runner;
- shutdown closes admission before engine cancellation and joins all owned worker/bridge tasks.
Benchmarks: The published v2 fake artifact records equivalent prebuilt and
full-handler JSON/SSE paths, direct bounded-bridge forwarding, 32-event
slow-consumer saturation, concurrency 1/8/32, cleanup latency, RSS, capacities,
and correctness. The canonical real CPU/F32 artifact uses prompt Hello and 32
tokens, reports fresh and verified persistent TCP separately, and defines TTFT,
TPOT, and output throughput at content-token boundaries. The two result classes
remain separate because the fake path excludes model, tokenizer, engine queue,
proxy, and external network costs; it includes a separate interleaved loopback
TCP health workload to isolate connection/request overhead. See
docs/milestone-3-report.md.
Status: Complete for serial one-shot prefill and variable-length batched decode with contiguous per-sequence caches. CPU/F32 correctness and a paired same-host CUDA/BF16 serial-versus-batched benchmark are recorded in the Milestone 4 report.
Goal: Execute multiple decode sequences in one model invocation and change active membership between iterations.
Dependencies: Engine ownership and stable single-sequence cache semantics.
Deliverables: Bounded FIFO pending admission, stable sequence identity, round-robin active selection, serial one-shot prefill, batched decode, variable context lengths, per-sequence positions and contiguous caches, valid-key masks, batched greedy selection, per-sequence streaming/stopping, and cancellation cleanup.
Acceptance: Batched CPU/F32 logits and exact greedy IDs match independent execution; batch size one preserves the prior path; concurrent engine requests retain independent ordered streams; one sequence finishing or cancelling does not corrupt others; fake scheduler tests prove batches larger than one and new admission while older sequences remain active.
Benchmarks: The initial batch-1/2/4 sweep at concurrency four records 33.6% and 109.8% aggregate throughput improvements for batch 2 and 4 respectively. Batch 2 improves TTFT and p95 completion latency but worsens per-request TPOT and median completion latency; batch 4 improves throughput and both completion latency summaries in this homogeneous workload. Continue mixed-length sweeps as the cache path evolves.
The core waiting/active lifecycle and continuous admission originally planned here were implemented in Milestone 4. There is no separate Milestone 5 code phase. Token-budget scheduling, mixed chunked prefill/decode, and bounded long-prompt interference remain part of the later chunked-prefill milestone.
Benchmark follow-up: Retain the concurrency sweep, burst/steady arrivals, aggregate tokens/s, queue delay, TTFT/TPOT, tail latency, batch distribution, and serial-baseline comparison as ongoing performance evidence.
Status: Complete (July 2026). The default is a Candle paged-reference path; the contiguous path remains selectable for differential tests and benchmarks.
Goal: Replace fixed maximum-context allocations with global physical blocks.
Dependencies: Stable sequence lifecycle and attention metadata; chosen block layout based on access measurements.
Deliverables: Global block pool, allocator, per-sequence block tables, allocation/release/rollback, mapped K/V writes and reads, memory accounting, and deterministic cleanup for finish/cancel/error. CPU allocator logic is isolated from GPU tensor storage for exhaustive testing.
Acceptance: No fixed max-context allocation per active sequence; allocator property tests cover uniqueness, reclaimability, rollback, and reference accounting; all blocks return after every lifecycle path; generated tokens match fixed-cache execution; concurrency improves under a fixed memory budget.
Benchmarks: Fixed versus paged allocation for memory utilization, maximum sequences, internal/external fragmentation, allocation overhead, attention latency, throughput, and block-size sweep.
Evidence: Pure allocator lifecycle/property tests, exact 32-token and
unequal-context CPU/F32 differential tests, paged Engine cancellation/recovery
tests, block-layout microbenchmarks, analytical workload accounting, and paired
CUDA/BF16 HTTP artifacts are summarized in docs/milestone-6-report.md.
Status: Complete (July 2026). The default scheduler uses chunked paged prefill; one-shot prefill remains selectable for differential validation.
Goal: Prevent long prompts from monopolizing scheduler iterations.
Dependencies: Continuous scheduler and a cache that safely grows by chunks.
Deliverables: Configurable per-iteration token budget and maximum prefill chunk, scheduler-level mixed decode/prefill work, correct positions/masks across chunks, decode-first fairness, full-prompt capacity guarding, and prompt-limit admission. The Candle runner uses separate decode and prefill model calls in a tick; it does not claim a fused heterogeneous batch.
Acceptance: Long prompts prefill incrementally; decode requests continue to make bounded progress; no scheduler budget violations; chunked and one-shot prefill produce identical greedy output; cancellation between chunks frees all resources.
Benchmarks: Large prompt plus concurrent decodes, chunk-size/token-budget sweep, prefill throughput, TTFT, decode TPOT and p99, GPU utilization, and comparison to unchunked continuous batching.
Evidence: Model-free scheduler tests prove shared-budget accounting and
decode progress across four prompt chunks. CPU/F32 tests compare chunk sizes 1,
5, 16, and 32 across page boundaries and require exact end-to-end greedy IDs
and text against one-shot execution. The workload driver and paired results are
described in docs/milestone-7-report.md.
Status: Complete (July 2026). Prefix reuse is disabled by default and may be
enabled for one trusted process-global isolation domain. See
docs/milestone-8-report.md.
Goal: Safely reuse previously computed KV prefixes.
Dependencies: Immutable paged blocks, block ownership/refcounts, and stable tokenizer/model identity.
Deliverables: Typed namespace identity for model source/revision, config/checkpoint/tokenizer artifacts, dtype/backend, KV layout/page size, prompt-format policy, and isolation scope; exact cumulative token-page lookup; immutable full-page sharing; cache and sequence reference accounting; bounded LRU eviction; exact full-prompt greedy sampling state; hit/miss/reused-token/ retained-byte metrics; and a conservative privacy policy.
Acceptance: Eligible identical prefixes avoid computation; ineligible or partially matching inputs do not collide; shared blocks survive one sequence finishing and are reclaimed after final ownership/eviction; exact greedy output is unchanged.
Benchmarks: Hit-rate sweep, cached versus uncached TTFT, lookup overhead, retained memory, eviction churn, maximum concurrency, and adversarial low-hit workload.
Evidence: Pure tests cover namespace sensitivity, exact collision verification, longest-prefix lookup, duplicate insertion, LRU removal, bounded retention, shared reference lifecycles, eviction with live leases, and 10,000 randomized lifecycles. The CPU/F32 model test requires exact cached/uncached greedy IDs and text for exact and partial hits. The CUDA/BF16 paired artifact records a 254.96 ms disabled warm median TTFT versus 1.02 ms for an exact warm hit, 0/25/50/75/100% requested-prefix sweeps, concurrent shared-page streams, eviction churn, and -1.63% median TTFT on a true no-hit workload.
Goal: Adopt only optimizations justified by profiles and serving goals.
Candidates: FlashAttention, paged decode attention, CUDA graphs, fused RMSNorm/RoPE/QKV, pinned memory, asynchronous copies, quantization, FlashInfer integration, custom CUDA, speculative decoding, then distributed execution.
Entry criteria for each candidate: A named bottleneck from profiles; a benchmark hypothesis and baseline; isolated correctness oracle; maintainability and portability assessment; rollback path.
Acceptance: Publish the measured result with confidence/variance where appropriate, exact environment metadata, numerical error, end-to-end serving impact, and any workload regression. Feature count is not acceptance.
Unit tests cover config parsing, sampling, sequence state/cache accounting, worker command handling, event-channel invariants, request IDs, metrics, and cancellation, allocator ownership, reservation transactions, block tables, and page gather isolation. The ignored local CPU/F32 integration suite loads the pinned model, compares deterministic IDs and selected tensors, exercises streaming, sequential reuse, cancellation, recovery, contiguous-versus-paged token parity, page boundaries, and unequal contexts, and remains separate from generic CI.