A high-throughput and memory-efficient inference and serving engine for LLMs
Mirrored from https://github.com/tduncan-lum/Nvidia-Optimization-Stack---VLLM.git
Synced Nov 6, 17:00 UTC
[Feature] Add Azure Blob Storage support for RunAI Model Streamer (#34614)
Signed-off-by: hasethuraman <hsethuraman@microsoft.com>
Hari committed
Mar 15, 2026 at 17:08 UTC
a3e2e250f09d7a347cfdccfe2f7b593edd1b7bce
14 files changed
+75
-17
docker/Dockerfile
+2
-2
@@ -620,7 +620,7 @@ RUN set -eux; \
620
ARG BITSANDBYTES_VERSION_X86=0.46.1
621
ARG BITSANDBYTES_VERSION_ARM64=0.42.0
622
ARG TIMM_VERSION=">=1.0.17"
623
-ARG RUNAI_MODEL_STREAMER_VERSION=">=0.15.3"
623
+ARG RUNAI_MODEL_STREAMER_VERSION=">=0.15.7"
624
RUN --mount=type=cache,target=/root/.cache/uv \
625
if [ "$TARGETPLATFORM" = "linux/arm64" ]; then \
626
BITSANDBYTES_VERSION="${BITSANDBYTES_VERSION_ARM64}"; \
@@ -628,7 +628,7 @@ RUN --mount=type=cache,target=/root/.cache/uv \
628
BITSANDBYTES_VERSION="${BITSANDBYTES_VERSION_X86}"; \
629
fi; \
630
uv pip install --system accelerate hf_transfer modelscope \
631
- "bitsandbytes>=${BITSANDBYTES_VERSION}" "timm${TIMM_VERSION}" "runai-model-streamer[s3,gcs]${RUNAI_MODEL_STREAMER_VERSION}"
631
+ "bitsandbytes>=${BITSANDBYTES_VERSION}" "timm${TIMM_VERSION}" "runai-model-streamer[s3,gcs,azure]${RUNAI_MODEL_STREAMER_VERSION}"
632
633
# ============================================================
634
# VLLM INSTALLATION (depends on build stage)
docker/versions.json
+1
-1
@@ -83,7 +83,7 @@
83
"default": ">=1.0.17"
84
},
85
"RUNAI_MODEL_STREAMER_VERSION": {
86
- "default": ">=0.15.3"
86
+ "default": ">=0.15.7"
87
}
88
}
89
}
docs/models/extensions/runai_model_streamer.md
+10
@@ -31,6 +31,16 @@ vllm serve gs://core-llm/Llama-3-8b \
31
--load-format runai_streamer
32
```
33
34
+To run model from Azure Blob Storage run:
35
+
36
+```bash
37
+AZURE_STORAGE_ACCOUNT_NAME=<account> \
38
+vllm serve az://<container>/<model-path> \
39
+ --load-format runai_streamer
40
+```
41
+
42
+Authentication uses `DefaultAzureCredential`, which supports `az login`, managed identity, environment variables (`AZURE_CLIENT_ID`, `AZURE_TENANT_ID`, `AZURE_CLIENT_SECRET`), and other methods.
43
+
44
To run model from a S3 compatible object store run:
45
46
```bash
requirements/nightly_torch_test.txt
+1
-1
@@ -42,7 +42,7 @@ tritonclient>=2.51.0
42
43
numba == 0.61.2 # Required for N-gram speculative decoding
44
numpy
45
-runai-model-streamer[s3,gcs]==0.15.3
45
+runai-model-streamer[s3,gcs,azure]==0.15.7
46
fastsafetensors>=0.2.2
47
instanttensor>=0.1.5
48
pydantic>=2.12 # 2.11 leads to error on python 3.13
requirements/rocm.txt
+1
-1
@@ -15,7 +15,7 @@ tensorizer==2.10.1
15
packaging>=24.2
16
setuptools>=77.0.3,<80.0.0
17
setuptools-scm>=8
18
-runai-model-streamer[s3,gcs]==0.15.3
18
+runai-model-streamer[s3,gcs,azure]==0.15.7
19
conch-triton-kernels==1.2.1
20
timm>=1.0.17
21
# amd-quark: required for Quark quantization on ROCm
requirements/test.in
+1
-1
@@ -56,7 +56,7 @@ grpcio-reflection==1.78.0
56
arctic-inference == 0.1.1 # Required for suffix decoding test
57
numba == 0.61.2 # Required for N-gram speculative decoding
58
numpy
59
-runai-model-streamer[s3,gcs]==0.15.3
59
+runai-model-streamer[s3,gcs,azure]==0.15.7
60
fastsafetensors>=0.2.2 # 0.2.2 contains important fixes for multi-GPU mem usage
61
instanttensor>=0.1.5
62
pydantic>=2.12 # 2.11 leads to error on python 3.13
requirements/test.txt
+38
-5
@@ -64,6 +64,14 @@ audioread==3.0.1
64
# via librosa
65
av==16.1.0
66
# via -r requirements/test.in
67
+azure-core==1.38.2
68
+ # via
69
+ # azure-identity
70
+ # azure-storage-blob
71
+azure-identity==1.25.2
72
+ # via runai-model-streamer-azure
73
+azure-storage-blob==12.28.0
74
+ # via runai-model-streamer-azure
75
backoff==2.2.1
76
# via
77
# -r requirements/test.in
@@ -103,8 +111,10 @@ certifi==2024.8.30
111
# rasterio
112
# requests
113
# sentry-sdk
106
-cffi==1.17.1
107
- # via soundfile
114
+cffi==2.0.0
115
+ # via
116
+ # cryptography
117
+ # soundfile
118
chardet==5.2.0
119
# via mbstrdecoder
120
charset-normalizer==3.4.0
@@ -148,6 +158,12 @@ coverage==7.10.6
158
# via pytest-cov
159
cramjam==2.9.0
160
# via fastparquet
161
+cryptography==46.0.5
162
+ # via
163
+ # azure-identity
164
+ # azure-storage-blob
165
+ # msal
166
+ # pyjwt
167
cuda-bindings==12.9.4
168
# via torch
169
cuda-pathfinder==1.3.3
@@ -379,6 +395,8 @@ iniconfig==2.0.0
395
# via pytest
396
instanttensor==0.1.5
397
# via -r requirements/test.in
398
+isodate==0.7.2
399
+ # via azure-storage-blob
400
isoduration==20.11.0
401
# via jsonschema
402
isort==5.13.2
@@ -492,6 +510,12 @@ more-itertools==10.5.0
510
# via lm-eval
511
mpmath==1.3.0
512
# via sympy
513
+msal==1.34.0
514
+ # via
515
+ # azure-identity
516
+ # msal-extensions
517
+msal-extensions==1.3.1
518
+ # via azure-identity
519
msgpack==1.1.0
520
# via
521
# librosa
@@ -828,6 +852,8 @@ pydantic-extra-types==2.10.5
852
# via mistral-common
853
pygments==2.18.0
854
# via rich
855
+pyjwt==2.11.0
856
+ # via msal
857
pyogrio==0.11.0
858
# via geopandas
859
pyparsing==3.2.0
@@ -945,6 +971,7 @@ regex==2024.9.11
971
# transformers
972
requests==2.32.3
973
# via
974
+ # azure-core
975
# buildkite-test-collector
976
# datasets
977
# diffusers
@@ -957,6 +984,7 @@ requests==2.32.3
984
# lightly
985
# lm-eval
986
# mistral-common
987
+ # msal
988
# mteb
989
# pooch
990
# ray
@@ -993,11 +1021,13 @@ rsa==4.9.1
1021
# via google-auth
1022
rtree==1.4.0
1023
# via torchgeo
996
-runai-model-streamer==0.15.3
1024
+runai-model-streamer==0.15.7
1025
# via -r requirements/test.in
998
-runai-model-streamer-gcs==0.15.3
1026
+runai-model-streamer-azure==0.15.7
1027
+ # via runai-model-streamer
1028
+runai-model-streamer-gcs==0.15.7
1029
# via runai-model-streamer
1000
-runai-model-streamer-s3==0.15.3
1030
+runai-model-streamer-s3==0.15.7
1031
# via runai-model-streamer
1032
s3transfer==0.10.3
1033
# via boto3
@@ -1266,6 +1296,9 @@ typing-extensions==4.15.0
1296
# aiosignal
1297
# albumentations
1298
# alembic
1299
+ # azure-core
1300
+ # azure-identity
1301
+ # azure-storage-blob
1302
# chz
1303
# fastapi
1304
# grpcio
setup.py
+1
-1
@@ -970,7 +970,7 @@ setup(
970
"tensorizer": ["tensorizer==2.10.1"],
971
"fastsafetensors": ["fastsafetensors >= 0.2.2"],
972
"instanttensor": ["instanttensor >= 0.1.5"],
973
- "runai": ["runai-model-streamer[s3,gcs] >= 0.15.3"],
973
+ "runai": ["runai-model-streamer[s3,gcs,azure] >= 0.15.7"],
974
"audio": [
975
"librosa",
976
"scipy",
tests/model_executor/model_loader/runai_streamer_loader/test_runai_utils.py
+1
@@ -19,6 +19,7 @@ from vllm.transformers_utils.runai_utils import (
19
def test_is_runai_obj_uri():
20
assert is_runai_obj_uri("gs://some-gcs-bucket/path")
21
assert is_runai_obj_uri("s3://some-s3-bucket/path")
22
+ assert is_runai_obj_uri("az://some-azure-container/path")
23
assert not is_runai_obj_uri("nfs://some-nfs-path")
24
25
tests/transformers_utils/test_utils.py
+9
@@ -11,6 +11,7 @@ from vllm.transformers_utils.gguf_utils import (
11
split_remote_gguf,
12
)
13
from vllm.transformers_utils.utils import (
14
+ is_azure,
15
is_cloud_storage,
16
is_gcs,
17
is_s3,
@@ -31,9 +32,17 @@ def test_is_s3():
32
assert not is_s3("nfs://nfs-fqdn.local")
33
34
35
+def test_is_azure():
36
+ assert is_azure("az://model-container/path")
37
+ assert not is_azure("s3://model-path/path-to-model")
38
+ assert not is_azure("/unix/local/path")
39
+ assert not is_azure("nfs://nfs-fqdn.local")
40
+
41
+
42
def test_is_cloud_storage():
43
assert is_cloud_storage("gs://model-path")
44
assert is_cloud_storage("s3://model-path/path-to-model")
45
+ assert is_cloud_storage("az://model-container/path")
46
assert not is_cloud_storage("/unix/local/path")
47
assert not is_cloud_storage("nfs://nfs-fqdn.local")
48
vllm/config/vllm.py
+3
-2
@@ -1574,8 +1574,9 @@ class VllmConfig:
1574
"runai_streamer_sharded",
1575
):
1576
raise ValueError(
1577
- f"To load a model from S3, 'load_format' "
1578
- f"must be 'runai_streamer' or 'runai_streamer_sharded', "
1577
+ f"To load a model from object storage (S3/GCS/Azure), "
1578
+ f"'load_format' must be 'runai_streamer' or "
1579
+ f"'runai_streamer_sharded', "
1580
f"but got '{self.load_config.load_format}'. "
1581
f"Model: {self.model_config.model}"
1582
)
vllm/model_executor/model_loader/runai_streamer_loader.py
+1
-1
@@ -21,7 +21,7 @@ from vllm.transformers_utils.runai_utils import is_runai_obj_uri, list_safetenso
21
class RunaiModelStreamerLoader(BaseModelLoader):
22
"""
23
Model loader that can load safetensors
24
- files from local FS or S3 bucket.
24
+ files from local FS, S3, GCS, or Azure Blob Storage.
25
"""
26
27
def __init__(self, load_config: LoadConfig):
vllm/transformers_utils/runai_utils.py
+1
-1
@@ -13,7 +13,7 @@ from vllm.utils.import_utils import PlaceholderModule
13
14
logger = init_logger(__name__)
15
16
-SUPPORTED_SCHEMES = ["s3://", "gs://"]
16
+SUPPORTED_SCHEMES = ["s3://", "gs://", "az://"]
17
18
try:
19
from runai_model_streamer import list_safetensors as runai_list_safetensors
vllm/transformers_utils/utils.py
+5
-1
@@ -23,8 +23,12 @@ def is_gcs(model_or_path: str) -> bool:
23
return model_or_path.lower().startswith("gs://")
24
25
26
+def is_azure(model_or_path: str) -> bool:
27
+ return model_or_path.lower().startswith("az://")
28
+
29
+
30
def is_cloud_storage(model_or_path: str) -> bool:
27
- return is_s3(model_or_path) or is_gcs(model_or_path)
31
+ return is_s3(model_or_path) or is_gcs(model_or_path) or is_azure(model_or_path)
32
33
34
def without_trust_remote_code(kwargs: dict[str, Any]) -> dict[str, Any]: