Skip to content

Commit cbb175a

Browse files
authored
ci: Add install check (#146)
* build: Add install check Signed-off-by: oliver könig <okoenig@nvidia.com> * ci: Add install test Signed-off-by: oliver könig <okoenig@nvidia.com> * f Signed-off-by: oliver könig <okoenig@nvidia.com> * f Signed-off-by: oliver könig <okoenig@nvidia.com> * f Signed-off-by: oliver könig <okoenig@nvidia.com> * update Signed-off-by: oliver könig <okoenig@nvidia.com> * requires-python Signed-off-by: oliver könig <okoenig@nvidia.com> * f Signed-off-by: oliver könig <okoenig@nvidia.com> * test Signed-off-by: oliver könig <okoenig@nvidia.com> * f Signed-off-by: oliver könig <okoenig@nvidia.com> * f Signed-off-by: oliver könig <okoenig@nvidia.com> * f Signed-off-by: oliver könig <okoenig@nvidia.com> * re-add torch Signed-off-by: oliver könig <okoenig@nvidia.com> * f Signed-off-by: oliver könig <okoenig@nvidia.com> * fix Signed-off-by: oliver könig <okoenig@nvidia.com> * f Signed-off-by: oliver könig <okoenig@nvidia.com> * guard triton Signed-off-by: oliver könig <okoenig@nvidia.com> * f Signed-off-by: oliver könig <okoenig@nvidia.com> * f Signed-off-by: oliver könig <okoenig@nvidia.com> * f Signed-off-by: oliver könig <okoenig@nvidia.com> * f Signed-off-by: oliver könig <okoenig@nvidia.com> * f Signed-off-by: oliver könig <okoenig@nvidia.com> * f Signed-off-by: oliver könig <okoenig@nvidia.com> * f Signed-off-by: oliver könig <okoenig@nvidia.com> * f Signed-off-by: oliver könig <okoenig@nvidia.com> * f Signed-off-by: oliver könig <okoenig@nvidia.com> * f Signed-off-by: oliver könig <okoenig@nvidia.com> * f Signed-off-by: oliver könig <okoenig@nvidia.com> * test Signed-off-by: oliver könig <okoenig@nvidia.com> * f Signed-off-by: oliver könig <okoenig@nvidia.com> * f Signed-off-by: oliver könig <okoenig@nvidia.com> * f Signed-off-by: oliver könig <okoenig@nvidia.com> * f Signed-off-by: oliver könig <okoenig@nvidia.com> * f Signed-off-by: oliver könig <okoenig@nvidia.com> * f Signed-off-by: oliver könig <okoenig@nvidia.com> * f Signed-off-by: oliver könig <okoenig@nvidia.com> * f Signed-off-by: oliver könig <okoenig@nvidia.com> * f Signed-off-by: oliver könig <okoenig@nvidia.com> * f Signed-off-by: oliver könig <okoenig@nvidia.com> * f Signed-off-by: oliver könig <okoenig@nvidia.com> * safe_import Signed-off-by: oliver könig <okoenig@nvidia.com> * f Signed-off-by: oliver könig <okoenig@nvidia.com> * f Signed-off-by: oliver könig <okoenig@nvidia.com> * f Signed-off-by: oliver könig <okoenig@nvidia.com> * f Signed-off-by: oliver könig <okoenig@nvidia.com> * f Signed-off-by: oliver könig <okoenig@nvidia.com> * f Signed-off-by: oliver könig <okoenig@nvidia.com> * f Signed-off-by: oliver könig <okoenig@nvidia.com> * f Signed-off-by: oliver könig <okoenig@nvidia.com> * f Signed-off-by: oliver könig <okoenig@nvidia.com> * f Signed-off-by: oliver könig <okoenig@nvidia.com> * f Signed-off-by: oliver könig <okoenig@nvidia.com> * f Signed-off-by: oliver könig <okoenig@nvidia.com> * f Signed-off-by: oliver könig <okoenig@nvidia.com> * build Signed-off-by: oliver könig <okoenig@nvidia.com> * f Signed-off-by: oliver könig <okoenig@nvidia.com> * f Signed-off-by: oliver könig <okoenig@nvidia.com> * f Signed-off-by: oliver könig <okoenig@nvidia.com> * fix Signed-off-by: oliver könig <okoenig@nvidia.com> * decord Signed-off-by: oliver könig <okoenig@nvidia.com> * f Signed-off-by: oliver könig <okoenig@nvidia.com> * f Signed-off-by: oliver könig <okoenig@nvidia.com> * f Signed-off-by: oliver könig <okoenig@nvidia.com> * f Signed-off-by: oliver könig <okoenig@nvidia.com> * f Signed-off-by: oliver könig <okoenig@nvidia.com> * ff Signed-off-by: oliver könig <okoenig@nvidia.com> * f Signed-off-by: oliver könig <okoenig@nvidia.com> * f Signed-off-by: oliver könig <okoenig@nvidia.com> * f Signed-off-by: oliver könig <okoenig@nvidia.com> * f Signed-off-by: oliver könig <okoenig@nvidia.com> * f Signed-off-by: oliver könig <okoenig@nvidia.com> * f Signed-off-by: oliver könig <okoenig@nvidia.com> * f Signed-off-by: oliver könig <okoenig@nvidia.com> * f Signed-off-by: oliver könig <okoenig@nvidia.com> * f Signed-off-by: oliver könig <okoenig@nvidia.com> * f Signed-off-by: oliver könig <okoenig@nvidia.com> * f Signed-off-by: oliver könig <okoenig@nvidia.com> * f Signed-off-by: oliver könig <okoenig@nvidia.com> * f Signed-off-by: oliver könig <okoenig@nvidia.com> * f Signed-off-by: oliver könig <okoenig@nvidia.com> * f Signed-off-by: oliver könig <okoenig@nvidia.com> * f Signed-off-by: oliver könig <okoenig@nvidia.com> * f Signed-off-by: oliver könig <okoenig@nvidia.com> * f Signed-off-by: oliver könig <okoenig@nvidia.com> * f Signed-off-by: oliver könig <okoenig@nvidia.com> * f Signed-off-by: oliver könig <okoenig@nvidia.com> * f Signed-off-by: oliver könig <okoenig@nvidia.com> * f Signed-off-by: oliver könig <okoenig@nvidia.com> * f Signed-off-by: oliver könig <okoenig@nvidia.com> * f Signed-off-by: oliver könig <okoenig@nvidia.com> * f Signed-off-by: oliver könig <okoenig@nvidia.com> * f Signed-off-by: oliver könig <okoenig@nvidia.com> * f Signed-off-by: oliver könig <okoenig@nvidia.com> * lock Signed-off-by: oliver könig <okoenig@nvidia.com> * f Signed-off-by: oliver könig <okoenig@nvidia.com> * add click Signed-off-by: oliver könig <okoenig@nvidia.com> * f Signed-off-by: oliver könig <okoenig@nvidia.com> * f Signed-off-by: oliver könig <okoenig@nvidia.com> * f Signed-off-by: oliver könig <okoenig@nvidia.com> * f Signed-off-by: oliver könig <okoenig@nvidia.com> * f Signed-off-by: oliver könig <okoenig@nvidia.com> * f Signed-off-by: oliver könig <okoenig@nvidia.com> * d Signed-off-by: oliver könig <okoenig@nvidia.com> * f Signed-off-by: oliver könig <okoenig@nvidia.com> * fix install Signed-off-by: oliver könig <okoenig@nvidia.com> * f Signed-off-by: oliver könig <okoenig@nvidia.com> * f Signed-off-by: oliver könig <okoenig@nvidia.com> * update Signed-off-by: oliver könig <okoenig@nvidia.com> --------- Signed-off-by: oliver könig <okoenig@nvidia.com>
1 parent 44ff314 commit cbb175a

36 files changed

+4387
-665
lines changed

.github/workflows/install-test.yml

Lines changed: 219 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,219 @@
1+
# Copyright (c) 2025, NVIDIA CORPORATION.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
# This workflow verifies that the basic install works across all supported platforms.
16+
# For basic install, all imports need to either be successful or appropriately guarded.
17+
18+
name: Installation Test
19+
20+
on:
21+
push:
22+
branches:
23+
- main
24+
- "pull-request/[0-9]+"
25+
env:
26+
UV_PROJECT_ENVIRONMENT: "./venv"
27+
28+
jobs:
29+
pip-test:
30+
runs-on: ${{ matrix.arch }}
31+
name: Pip - Python${{ matrix.python-version }} - ${{ matrix.arch == 'ubuntu-latest' && 'AMD64/Linux' || 'ARM64/Darwin' }} - No CUDA
32+
strategy:
33+
fail-fast: false
34+
matrix:
35+
arch: ["ubuntu-latest", "macos-latest"]
36+
python-version: ["3.10", "3.11", "3.12"]
37+
steps:
38+
- name: Checkout repository
39+
uses: actions/checkout@v4
40+
41+
- name: Set up Python ${{ matrix.python-version }}
42+
uses: actions/setup-python@v4
43+
with:
44+
python-version: ${{ matrix.python-version }}
45+
46+
- name: Upgrade pip
47+
run: |
48+
python -m pip install --upgrade pip
49+
50+
- name: Install project
51+
run: |
52+
pip install .
53+
54+
- name: Checkout check-imports
55+
uses: actions/checkout@v4
56+
with:
57+
repository: NVIDIA-NeMo/FW-CI-templates
58+
ref: v0.39.0
59+
path: FW-CI-templates
60+
61+
- name: Check imports for nemo_deploy
62+
uses: ./FW-CI-templates/.github/actions/check-imports
63+
with:
64+
package-name: nemo_deploy
65+
python-binary: python
66+
67+
- name: Check imports for nemo_export
68+
uses: ./FW-CI-templates/.github/actions/check-imports
69+
with:
70+
package-name: nemo_export
71+
python-binary: python
72+
73+
ngc-cuda-test:
74+
runs-on: linux-amd64-cpu16
75+
name: UV - Python${{ matrix.python-version }} - AMD64/Linux - NGC CUDA
76+
container:
77+
image: nvcr.io/nvidia/cuda:12.8.1-cudnn-devel-ubuntu24.04
78+
environment: nemo-ci
79+
strategy:
80+
fail-fast: false
81+
matrix:
82+
python-version: ["3.12"]
83+
steps:
84+
- name: Checkout repository
85+
uses: actions/checkout@v4
86+
87+
- name: Set up Python ${{ matrix.python-version }}
88+
uses: actions/setup-python@v4
89+
with:
90+
python-version: ${{ matrix.python-version }}
91+
92+
- name: Install wget
93+
run: |
94+
apt-get update
95+
apt-get install -y wget git libopenmpi-dev
96+
97+
- name: Upgrade pip
98+
run: |
99+
python -m pip install --upgrade pip
100+
101+
- name: Set up UV
102+
uses: astral-sh/setup-uv@v1
103+
with:
104+
version: 0.7.2
105+
106+
- name: Set up yq
107+
shell: bash
108+
run: |
109+
wget https://github.com/mikefarah/yq/releases/download/v4.45.4/yq_linux_amd64.tar.gz
110+
tar -xzf yq_linux_amd64.tar.gz
111+
mkdir -p ./bin
112+
mv yq_linux_amd64 ./bin/yq
113+
chmod +x ./bin/yq
114+
115+
- name: Install project
116+
env:
117+
PAT: ${{ secrets.PAT }}
118+
shell: bash
119+
run: |
120+
echo -e "machine github.com\n login token\n password ${{ secrets.PAT }}" > ~/.netrc
121+
chmod 600 ~/.netrc
122+
123+
uv venv ${UV_PROJECT_ENVIRONMENT} --system-site-packages
124+
source ./venv/bin/activate
125+
126+
export PATH="./bin/:$PATH"
127+
128+
uv sync --link-mode copy --locked --all-groups
129+
130+
bash ./docker/common/install_conflicting_deps.sh
131+
132+
uv pip install --no-deps -e .
133+
134+
- name: Checkout check-imports
135+
uses: actions/checkout@v4
136+
with:
137+
repository: NVIDIA-NeMo/FW-CI-templates
138+
ref: v0.39.0
139+
path: FW-CI-templates
140+
141+
- name: Check imports for nemo_deploy
142+
uses: ./FW-CI-templates/.github/actions/check-imports
143+
with:
144+
package-name: nemo_deploy
145+
python-binary: ./venv/bin/python
146+
147+
- name: Check imports for nemo_export
148+
uses: ./FW-CI-templates/.github/actions/check-imports
149+
with:
150+
package-name: nemo_export
151+
python-binary: ./venv/bin/python
152+
153+
uv-test:
154+
runs-on: ${{ matrix.arch }}
155+
name: UV - Python ${{ matrix.python-version }} - ${{ matrix.arch == 'ubuntu-latest' && 'AMD64/Linux' || 'ARM64/Darwin' }} - No CUDA
156+
environment: nemo-ci
157+
strategy:
158+
fail-fast: false
159+
matrix:
160+
arch: ["ubuntu-latest", "macos-latest"]
161+
python-version: ["3.12"]
162+
steps:
163+
- name: Checkout repository
164+
uses: actions/checkout@v4
165+
166+
- name: Set up UV
167+
uses: astral-sh/setup-uv@v1
168+
with:
169+
version: 0.7.2
170+
171+
- name: Set up Python ${{ matrix.python-version }}
172+
uses: actions/setup-python@v4
173+
with:
174+
python-version: ${{ matrix.python-version }}
175+
176+
- name: Install dependencies with UV
177+
env:
178+
PAT: ${{ secrets.PAT }}
179+
shell: bash
180+
run: |
181+
echo -e "machine github.com\n login token\n password ${{ secrets.PAT }}" > ~/.netrc
182+
chmod 600 ~/.netrc
183+
184+
export PATH="${UV_PROJECT_ENVIRONMENT}/bin/:$PATH"
185+
186+
uv venv ${UV_PROJECT_ENVIRONMENT} --system-site-packages
187+
188+
uv sync --link-mode copy --locked --only-group build
189+
190+
uv sync --link-mode copy --locked --all-groups
191+
192+
uv pip install --no-deps -e .
193+
194+
- name: Checkout check-imports
195+
uses: actions/checkout@v4
196+
with:
197+
repository: NVIDIA-NeMo/FW-CI-templates
198+
ref: v0.39.0
199+
path: FW-CI-templates
200+
201+
- name: Check imports for nemo_deploy
202+
uses: ./FW-CI-templates/.github/actions/check-imports
203+
with:
204+
package-name: nemo_deploy
205+
python-binary: ./venv/bin/python
206+
207+
- name: Check imports for nemo_export
208+
uses: ./FW-CI-templates/.github/actions/check-imports
209+
with:
210+
package-name: nemo_export
211+
python-binary: ./venv/bin/python
212+
213+
install-test-summary:
214+
needs: [pip-test, uv-test, ngc-cuda-test]
215+
runs-on: ubuntu-latest
216+
name: Install test summary
217+
steps:
218+
- name: Result
219+
run: echo Install check successful

docker/Dockerfile.ci

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,19 @@ RUN --mount=type=bind,source=pyproject.toml,target=/workspace/pyproject.toml \
5353
--extra te \
5454
--no-install-package torch \
5555
--no-install-package torchvision \
56+
--no-install-package triton \
57+
--no-install-package nvidia-cublas-cu12 \
58+
--no-install-package nvidia-cuda-cupti-cu12 \
59+
--no-install-package nvidia-cuda-nvrtc-cu12 \
60+
--no-install-package nvidia-cuda-runtime-cu12 \
61+
--no-install-package nvidia-cudnn-cu12 \
62+
--no-install-package nvidia-cufft-cu12 \
63+
--no-install-package nvidia-cufile-cu12 \
64+
--no-install-package nvidia-curand-cu12 \
65+
--no-install-package nvidia-cusolver-cu12 \
66+
--no-install-package nvidia-cusparse-cu12 \
67+
--no-install-package nvidia-cusparselt-cu12 \
68+
--no-install-package nvidia-nccl-cu12 \
5669
--all-groups \
5770
${INFERENCE_FRAMEWORK:+--extra $INFERENCE_FRAMEWORK}
5871

nemo_deploy/deploy_pytriton.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,19 @@
1515

1616
import logging
1717

18-
from pytriton.model_config import ModelConfig
19-
from pytriton.triton import Triton, TritonConfig
20-
2118
from nemo_deploy.deploy_base import DeployBase
19+
from nemo_export_deploy_common.import_utils import MISSING_TRITON_MSG, UnavailableError
2220

2321
LOGGER = logging.getLogger("NeMo")
2422

23+
try:
24+
from pytriton.model_config import ModelConfig
25+
from pytriton.triton import Triton, TritonConfig
26+
27+
HAVE_TRITON = True
28+
except (ImportError, ModuleNotFoundError):
29+
HAVE_TRITON = False
30+
2531

2632
class DeployPyTriton(DeployBase):
2733
"""Deploys any models to Triton Inference Server that implements ITritonDeployable interface in nemo_deploy.
@@ -99,6 +105,9 @@ def __init__(
99105

100106
def deploy(self):
101107
"""Deploys any models to Triton Inference Server."""
108+
if not HAVE_TRITON:
109+
raise UnavailableError(MISSING_TRITON_MSG)
110+
102111
try:
103112
if self.streaming:
104113
triton_config = TritonConfig(

nemo_deploy/deploy_ray.py

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,22 @@
1515

1616
import logging
1717

18-
import ray
19-
from ray import serve
20-
from ray.serve import Application
21-
2218
from nemo_deploy.ray_utils import find_available_port
19+
from nemo_export_deploy_common.import_utils import MISSING_RAY_MSG, UnavailableError
20+
21+
try:
22+
import ray
23+
from ray import serve
24+
from ray.serve import Application
25+
26+
HAVE_RAY = True
27+
except (ImportError, ModuleNotFoundError):
28+
from unittest.mock import MagicMock
29+
30+
ray = MagicMock()
31+
serve = MagicMock()
32+
Application = MagicMock()
33+
HAVE_RAY = False
2334

2435
LOGGER = logging.getLogger("NeMo")
2536

@@ -61,6 +72,9 @@ def __init__(
6172
Raises:
6273
Exception: If Ray is not installed.
6374
"""
75+
if not HAVE_RAY:
76+
raise UnavailableError(MISSING_RAY_MSG)
77+
6478
# Initialize Ray with proper configuration
6579

6680
try:

nemo_deploy/multimodal/query_multimodal.py

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,38 @@
1616

1717
import numpy as np
1818
import requests
19-
from PIL import Image
20-
from pytriton.client import ModelClient
2119

2220
from nemo_deploy.utils import str_list2numpy
21+
from nemo_export_deploy_common.import_utils import (
22+
MISSING_DECORD_MSG,
23+
MISSING_PIL_MSG,
24+
MISSING_TRITON_MSG,
25+
UnavailableError,
26+
)
27+
28+
try:
29+
from PIL import Image
30+
31+
HAVE_PIL = True
32+
except (ImportError, ModuleNotFoundError):
33+
HAVE_PIL = False
2334

2435
try:
2536
from decord import VideoReader
26-
except Exception:
27-
import logging
2837

29-
logging.warning("The package `decord` was not installed in this environment.")
38+
HAVE_DECORD = True
39+
except (ImportError, ModuleNotFoundError):
40+
HAVE_DECORD = False
41+
42+
try:
43+
from pytriton.client import ModelClient
44+
45+
HAVE_TRITON = True
46+
except (ImportError, ModuleNotFoundError):
47+
from unittest.mock import MagicMock
48+
49+
ModelClient = MagicMock()
50+
HAVE_TRITON = False
3051

3152

3253
class NemoQueryMultimodal:
@@ -57,16 +78,25 @@ def __init__(self, url, model_name, model_type):
5778
def setup_media(self, input_media):
5879
"""Setup input media."""
5980
if self.model_type == "video-neva":
81+
if not HAVE_DECORD:
82+
raise UnavailableError(MISSING_DECORD_MSG)
83+
6084
vr = VideoReader(input_media)
6185
frames = [f.asnumpy() for f in vr]
6286
return np.array(frames)
6387
elif self.model_type == "lita" or self.model_type == "vita":
88+
if not HAVE_DECORD:
89+
raise UnavailableError(MISSING_DECORD_MSG)
90+
6491
vr = VideoReader(input_media)
6592
frames = [f.asnumpy() for f in vr]
6693
subsample_len = self.frame_len(frames)
6794
sub_frames = self.get_subsampled_frames(frames, subsample_len)
6895
return np.array(sub_frames)
6996
elif self.model_type in ["neva", "vila", "mllama"]:
97+
if not HAVE_PIL:
98+
raise UnavailableError(MISSING_PIL_MSG)
99+
70100
if input_media.startswith("http") or input_media.startswith("https"):
71101
response = requests.get(input_media, timeout=5)
72102
media = Image.open(BytesIO(response.content)).convert("RGB")
@@ -106,6 +136,9 @@ def query(
106136
lora_uids=None,
107137
):
108138
"""Run query."""
139+
if not HAVE_TRITON:
140+
raise UnavailableError(MISSING_TRITON_MSG)
141+
109142
prompts = str_list2numpy([input_text])
110143
inputs = {"input_text": prompts}
111144

0 commit comments

Comments
 (0)