Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
118 changes: 118 additions & 0 deletions Dockerfile.quick-start-sglang
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
# syntax=docker/dockerfile:1.7
# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0

ARG SGLANG_IMAGE=lmsysorg/sglang:v0.5.21-cu130-runtime@sha256:797614a377ead47cf89ccaba810685b56a1bf0d6f0c45f84af2e8f42c198e104

FROM rust:1.96.1-bookworm@sha256:d99f7b31f49909348dc59b51f3c95d1efded1701ffb222f095aaab7de3c4abd8 AS sglang-dynamo-builder
RUN apt-get update && apt-get install -y --no-install-recommends \
cmake git libclang-dev libhwloc-dev libprotobuf-dev libssl-dev libudev-dev \
pkg-config protobuf-compiler python3-dev python3-pip python3-venv \
&& rm -rf /var/lib/apt/lists/*
ARG SGLANG_DYNAMO_REF=83ea37e849e883c27d7ed848e0f329961e1fb173
RUN git init /src/dynamo \
&& git -C /src/dynamo remote add origin https://github.com/ai-dynamo/dynamo.git \
&& git -C /src/dynamo fetch --depth 1 origin "${SGLANG_DYNAMO_REF}" \
&& git -C /src/dynamo checkout --detach FETCH_HEAD \
&& test "$(git -C /src/dynamo rev-parse HEAD)" = "${SGLANG_DYNAMO_REF}"
RUN python3 -m venv /venv \
&& /venv/bin/pip install --no-cache-dir 'maturin[patchelf]==1.9.6'
ENV CARGO_BUILD_JOBS=4
RUN cd /src/dynamo/lib/bindings/python \
&& /venv/bin/maturin build --locked --release --features select-service,kv-indexer --out /wheels
RUN /venv/bin/pip wheel --no-deps /src/dynamo --wheel-dir /wheels

FROM ${SGLANG_IMAGE} AS sglang
USER root
ARG SGLANG_REF=b0506add3eac49bbb2c303e83169ea19c907fb98
RUN test "$(uname -m)" = x86_64 \
&& apt-get update && apt-get install -y --no-install-recommends \
git curl libatomic1 libhwloc15 libnuma1 libssl3t64 libudev1 \
&& rm -rf /var/lib/apt/lists/*
RUN git init /opt/sglang-src \
&& git -C /opt/sglang-src remote add origin https://github.com/ziqifan617/sglang.git \
&& git -C /opt/sglang-src fetch --depth 1 origin "${SGLANG_REF}" \
&& git -C /opt/sglang-src checkout --detach FETCH_HEAD \
&& test "$(git -C /opt/sglang-src rev-parse HEAD)" = "${SGLANG_REF}"
# Install KVCR from the checkout used as the Docker build context.
COPY pyproject.toml README.md LICENSE /opt/kvcr-src/
COPY src /opt/kvcr-src/src
COPY --from=sglang-dynamo-builder /wheels /tmp/dynamo-wheels
COPY <<'EOF' /opt/sglang-constraints.txt
torch==2.14.1
transformers==5.19.0
flashinfer-python==0.7.2
nvidia-cutlass-dsl==4.8.0
sgl-deep-gemm==0.2.3
sglang-kernel==0.4.10
apache-tvm-ffi==0.1.11
nixl==1.5.0
msgspec==0.22.0
pyzmq==27.1.0
numpy==2.3.5
protobuf==7.36.2
EOF
ENV SGLANG_BUILD_RUST_EXTS=none SGLANG_RUST_BUILD_MODE=never \
SGLANG_UNIFIED_RADIX_TREE_CORE_BACKEND=python
RUN python3 -m pip install --no-cache-dir 'setuptools-rust==1.11.1' 'setuptools-scm==9.2.2' 'hatchling==1.27.0' \
&& python3 -m pip uninstall -y sglang \
&& python3 -m pip install --no-cache-dir --no-build-isolation \
--constraint /opt/sglang-constraints.txt \
--find-links https://pypi.nvidia.com/aisimulate/ \
/opt/sglang-src/python /opt/kvcr-src /tmp/dynamo-wheels/*.whl \
'nixl[cu13]==1.5.0' 'blake3==1.0.8' \
&& python3 -m pip install --no-cache-dir --no-deps \
--index-url https://flashinfer.ai/whl 'flashinfer-cubin==0.7.2' \
&& python3 -m pip install --no-cache-dir --no-deps \
--index-url https://flashinfer.ai/whl/cu130 'flashinfer-jit-cache==0.7.2'
COPY <<'EOF' /opt/sglang-router-policy.yaml
worker_selection:
aggregated: two-tier
instances:
- name: two-tier
type: dynamo-two-tier-cost-fn
parameters:
cache_threshold: 0.5
balance_abs_threshold: 4
balance_rel_threshold: 1.1
EOF
ENV DYN_REQUEST_PLANE=tcp DYN_EVENT_PLANE=zmq DYN_DISCOVERY_BACKEND=file \
DYN_FILE_KV=/tmp/dynamo-sglang-quick-start DYN_SYSTEM_HOST=127.0.0.1 \
DYN_RUNTIME_NUM_WORKER_THREADS=4 DYN_RUNTIME_MAX_BLOCKING_THREADS=8 \
TOKENIZERS_PARALLELISM=false PYTHONHASHSEED=0 RUST_LOG=info \
UCX_TLS=tcp,sm,self,cuda_copy OMP_NUM_THREADS=4
# Import/version canary only; model/peer-transfer acceptance is in the guide.
RUN python3 - <<'PY'
from importlib import metadata
from pathlib import Path
import tomllib
import dynamo.sglang
import torch
from dynamo.common.constants import KV_HINT_TRANSFER_CAPABILITY_KEY
from dynamo.llm import WorkerType
from dynamo.sglang import kv_hints
from dynamo.sglang.state_agent import StateAgentLifecycle
from kvcr import ZmqPeerControlChannel
from sglang.srt.mem_cache.hicache_storage import HiCacheStorage
from sglang.srt.mem_cache.storage.kvcr.kvcr_store import KVCRStore

for line in Path('/opt/sglang-constraints.txt').read_text().splitlines():
name, expected = line.split('==')
actual = metadata.version(name)
assert actual.split('+', 1)[0] == expected, (name, actual, expected)
print(f'{name}=={actual}')
assert torch.version.cuda == '13.0'
assert KV_HINT_TRANSFER_CAPABILITY_KEY == 'router_hint'
assert callable(KVCRStore.batch_get_v1)
assert callable(HiCacheStorage.get_kv_hint_source)
assert callable(StateAgentLifecycle.start)
assert callable(ZmqPeerControlChannel)
assert metadata.version('ai-dynamo') == '1.7.0'
assert metadata.version('ai-dynamo-runtime') == '1.7.0'
kvcr_project = tomllib.loads(Path('/opt/kvcr-src/pyproject.toml').read_text())['project']
assert metadata.version('kvcr') == kvcr_project['version']
print('SGLang HiCache import/version checks passed; GPU verification still required')
PY
RUN python3 -m pip freeze --all > /opt/sglang-installed-packages.txt
WORKDIR /workspace
ENTRYPOINT []
17 changes: 5 additions & 12 deletions Dockerfile.quick-start → Dockerfile.quick-start-vllm
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@

ARG VLLM_IMAGE=vllm/vllm-openai:nightly-edad8b03c5285a1c12e7e4f83c1af709b319a01b@sha256:2e735ffeef26457f8a3ff44a62ae182870b10af37adc06ecbb08baca152365c6

# The vLLM image, adapter source, and Dynamo revision below are one validated
# compatibility set. Change them together and repeat the end-to-end test.
# Keep the vLLM image, adapter source, and Dynamo revision compatible.
FROM rust:1.93-bookworm AS build-base
RUN apt-get update && apt-get install -y --no-install-recommends \
cmake git libclang-dev libhwloc-dev libprotobuf-dev libudev-dev pkg-config \
Expand All @@ -22,7 +21,7 @@ RUN git init /src/vllm-kvcr \
&& git -C /src/vllm-kvcr checkout --detach FETCH_HEAD \
&& test "$(git -C /src/vllm-kvcr rev-parse HEAD)" = "${KVCR_VLLM_REF}"
WORKDIR /src/vllm-kvcr
# Use the public channel export without changing the validated adapter revision.
# Use the public channel export.
RUN sed -i 's/^from kvcr\.control_channels import ZmqPeerControlChannel$/from kvcr import ZmqPeerControlChannel/' \
vllm/v1/kv_offload/tiering/kvcr/manager.py \
&& mkdir -p /overlay \
Expand Down Expand Up @@ -56,9 +55,7 @@ FROM ${VLLM_IMAGE}
USER root
ARG NCCL_VERSION=2.30.7

# KVCR's recovery journal reaches libatomic for the 8-byte acquire/release
# cursor operations CPython does not expose. The runtime image needs it even
# though it is not a Python distribution and cannot be a pyproject dependency.
# KVCR's recovery journal requires libatomic at runtime.
RUN apt-get update && apt-get install -y --no-install-recommends libatomic1 \
&& rm -rf /var/lib/apt/lists/*

Expand All @@ -79,9 +76,7 @@ RUN python3 -m pip install --no-cache-dir /opt/kvcr-src \
&& python3 -m pip install --no-cache-dir \
"nvidia-nccl-cu13==${NCCL_VERSION}"

# Overlay the six vLLM files fetched from the public KVCR integration commit.
# The quick start pins that commit and this base image as one validated
# compatibility set.
# Overlay the adapter files from the pinned vLLM integration commit.
COPY --from=vllm-kvcr-source /overlay/vllm /tmp/kvcr-vllm-overlay/vllm
RUN VLLM_DIR="$(python3 -c 'import os, vllm; print(os.path.dirname(vllm.__file__))')" \
&& cp -a /tmp/kvcr-vllm-overlay/vllm/. "${VLLM_DIR}/" \
Expand All @@ -94,9 +89,7 @@ ENV DYN_REQUEST_PLANE=tcp \
PYTHONHASHSEED=0 \
VLLM_KV_EVENTS_USE_INT_BLOCK_HASHES=1

# Fail the build if an incompatible source revision displaced any part of the
# serving path. The validated NCCL restore intentionally differs from the
# torch wheel's declared pin, so a global `pip check` is not a useful canary.
# Check serving-path compatibility; NCCL is pinned separately from torch.
RUN kvcr-service --help
RUN python3 - <<'PY'
from importlib import metadata
Expand Down
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,9 @@ A hint envelope may carry several hints. KVCR parses and dispatches each one ind

### Quick start

The [quick start](docs/quick-start.md) is a public preview that builds and runs KVCR with vLLM, Dynamo, and NIXL using pinned source revisions and a compatible base image. See the [developer guide](docs/dev-guide.md#integrate-with-vllm-and-dynamo-optional) for source installation and verification.
The [vLLM quick start](docs/quick-start-vllm.md) is a public preview that builds and runs KVCR with vLLM, Dynamo, and NIXL using pinned source revisions and a compatible base image. See the [developer guide](docs/dev-guide.md#integrate-with-vllm-and-dynamo-optional) for source installation and verification.

The [SGLang HiCache quick start](docs/quick-start-sglang.md) is a preview for building and running KVCR with SGLang and Dynamo.

### Development

Expand All @@ -91,7 +93,7 @@ KVCR package source files carry an SPDX Apache-2.0 identifier and the NVIDIA cop

## Third-party software

vLLM and Dynamo are installed separately in the quick-start image and are not bundled into the `kvcr` wheel. The build uses the public sources and pinned revisions described in the [quick start](docs/quick-start.md).
The quick-start images install the inference engine and Dynamo separately; they are not bundled into the `kvcr` wheel. See the [vLLM](docs/quick-start-vllm.md) and [SGLang](docs/quick-start-sglang.md) guides for the pinned sources.

KVCR declares runtime dependencies on `msgspec`, `pyzmq`, and `nixl`. Each is installed from its own distribution under its own license. None of them are redistributed by this repository or bundled into the `kvcr` wheel, which packages only `src/kvcr`.

Expand Down
6 changes: 3 additions & 3 deletions docs/dev-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

This guide is for developers who are comfortable with Python, Linux, and inference engines such as vLLM, but are new to KV Cache Runner (KVCR). It covers the local development path from environment setup through standalone validation.

To try the integrated stack without modifying source, follow the [quick start](quick-start.md).
To try the integrated stack without modifying source, follow the [vLLM quick start](quick-start-vllm.md) or [SGLang HiCache quick start](quick-start-sglang.md).

---

Expand Down Expand Up @@ -308,7 +308,7 @@ Validate that counters increase on both success and failure paths, byte counts a

Complete standalone setup and validation first. Use a separate shared environment for Dynamo, vLLM, and KVCR to keep integration dependencies out of the standalone development loop.

Select a vLLM revision that includes the merged KVCR 0.2.0 secondary-tier adapter (`"type": "kvcr"`), starting with [`fed7de9`](https://github.com/vllm-project/vllm/commit/fed7de909f894fbee0c45130376aed2e2c9bf0d3) on `main`. Pair it with a landed Dynamo revision such as [`ea23e51`](https://github.com/ai-dynamo/dynamo/commit/ea23e5130c1bfbadec477b99449d0cee5598caa0), which supports the versioned KV hint contract and one KVCR control port per local data-parallel rank. The [quick start](quick-start.md) records a pinned combination for its container.
Select a vLLM revision that includes the merged KVCR 0.2.0 secondary-tier adapter (`"type": "kvcr"`), starting with [`fed7de9`](https://github.com/vllm-project/vllm/commit/fed7de909f894fbee0c45130376aed2e2c9bf0d3) on `main`. Pair it with a landed Dynamo revision such as [`701da25`](https://github.com/ai-dynamo/dynamo/commit/701da25292ecca8f64d770cc0b17d389200019a1), which supports the versioned KV hint contract and one KVCR control port per local data-parallel rank. The [vLLM quick start](quick-start-vllm.md) records a pinned combination for its container.

### Build the integration environment

Expand Down Expand Up @@ -405,7 +405,7 @@ Run integration validation when changing public KVCR contracts, the vLLM tier ad

#### Minimal vLLM configuration

On a compatible vLLM revision, KVCR is a secondary tier behind `OffloadingConnector` and `TieringOffloadingSpec`. Use the quick start's [worker configuration](quick-start.md#4-start-a-kvcr-enabled-worker) for the `--kv-transfer-config` and `--kv-events-config` objects, adjusting capacities, ports, and local DP ranks for your environment.
On a compatible vLLM revision, KVCR is a secondary tier behind `OffloadingConnector` and `TieringOffloadingSpec`. Use the quick start's [worker configuration](quick-start-vllm.md#4-start-a-kvcr-enabled-worker) for the `--kv-transfer-config` and `--kv-events-config` objects, adjusting capacities, ports, and local DP ranks for your environment.

The important fields are:

Expand Down
Loading
Loading