|
1 | 1 | @echo off |
2 | | -REM deploy.bat — Zero-assumption bootstrapper for Depth Estimation Skill (Windows) |
3 | | -REM |
4 | | -REM Probes the system for Python, GPU backends, and installs the minimum |
5 | | -REM viable stack. Called by Aegis skill-runtime-manager during installation. |
| 2 | +setlocal enabledelayedexpansion |
| 3 | +REM ═══════════════════════════════════════════════════════════════════ |
| 4 | +REM Depth Estimation Skill — Windows Deployment (ONNX Runtime) |
6 | 5 | REM |
7 | | -REM Uses skills\lib\env_config.py for hardware detection. |
| 6 | +REM GPU detection cascade: |
| 7 | +REM 1. nvidia-smi found → onnxruntime-gpu (CUDA + TensorRT EPs) |
| 8 | +REM 2. Non-NVIDIA GPU found (WMI) → onnxruntime-directml |
| 9 | +REM 3. No GPU → onnxruntime (CPU) |
8 | 10 | REM |
9 | | -REM Exit codes: |
10 | | -REM 0 = success |
11 | | -REM 1 = fatal error (no Python found) |
12 | | -REM 2 = partial success (CPU-only fallback) |
13 | | - |
14 | | -setlocal enabledelayedexpansion |
15 | | - |
16 | | -set "SKILL_DIR=%~dp0" |
17 | | -REM Remove trailing backslash |
18 | | -if "%SKILL_DIR:~-1%"=="\" set "SKILL_DIR=%SKILL_DIR:~0,-1%" |
19 | | -set "VENV_DIR=%SKILL_DIR%\.venv" |
20 | | -set "LOG_PREFIX=[Depth-deploy]" |
21 | | - |
22 | | -REM Resolve lib dir (two levels up + lib) |
23 | | -set "LIB_DIR=" |
24 | | -if exist "%SKILL_DIR%\..\..\lib\env_config.py" ( |
25 | | - pushd "%SKILL_DIR%\..\..\lib" |
26 | | - set "LIB_DIR=!CD!" |
27 | | - popd |
28 | | -) |
| 11 | +REM Then downloads ONNX model from HuggingFace. |
| 12 | +REM ═══════════════════════════════════════════════════════════════════ |
29 | 13 |
|
30 | | -REM ─── Step 1: Find Python ─────────────────────────────────────────────────── |
31 | | - |
32 | | -echo %LOG_PREFIX% Searching for Python...>&2 |
| 14 | +echo [DepthDeploy] Starting depth-estimation skill deployment... |
| 15 | +echo [DepthDeploy] Platform: Windows (%PROCESSOR_ARCHITECTURE%) |
33 | 16 |
|
| 17 | +REM ── 1. Find Python ───────────────────────────────────────────────── |
34 | 18 | set "PYTHON_CMD=" |
35 | 19 |
|
36 | | -REM Try the Windows Python launcher (py.exe) first — ships with python.org installer |
37 | | -for %%V in (3.12 3.11 3.10 3.9) do ( |
38 | | - if not defined PYTHON_CMD ( |
39 | | - py -%%V --version >nul 2>&1 |
40 | | - if !errorlevel! equ 0 ( |
41 | | - set "PYTHON_CMD=py -%%V" |
42 | | - ) |
43 | | - ) |
| 20 | +REM Try py launcher first (most reliable on Windows) |
| 21 | +py --version >nul 2>&1 |
| 22 | +if %ERRORLEVEL% equ 0 ( |
| 23 | + set "PYTHON_CMD=py" |
| 24 | + goto :found_python |
44 | 25 | ) |
45 | 26 |
|
46 | | -REM Fallback: bare python3 / python on PATH |
47 | | -if not defined PYTHON_CMD ( |
48 | | - python3 --version >nul 2>&1 |
49 | | - if !errorlevel! equ 0 ( |
50 | | - REM Verify version >= 3.9 |
51 | | - for /f "tokens=2 delims= " %%A in ('python3 --version 2^>^&1') do set "_pyver=%%A" |
52 | | - for /f "tokens=1,2 delims=." %%A in ("!_pyver!") do ( |
53 | | - if %%A geq 3 if %%B geq 9 set "PYTHON_CMD=python3" |
54 | | - ) |
55 | | - ) |
| 27 | +REM Try python (could be Python 3 on PATH) |
| 28 | +python --version >nul 2>&1 |
| 29 | +if %ERRORLEVEL% equ 0 ( |
| 30 | + set "PYTHON_CMD=python" |
| 31 | + goto :found_python |
56 | 32 | ) |
57 | 33 |
|
58 | | -if not defined PYTHON_CMD ( |
59 | | - python --version >nul 2>&1 |
60 | | - if !errorlevel! equ 0 ( |
61 | | - for /f "tokens=2 delims= " %%A in ('python --version 2^>^&1') do set "_pyver=%%A" |
62 | | - for /f "tokens=1,2 delims=." %%A in ("!_pyver!") do ( |
63 | | - if %%A geq 3 if %%B geq 9 set "PYTHON_CMD=python" |
64 | | - ) |
65 | | - ) |
66 | | -) |
| 34 | +echo [DepthDeploy] ERROR: Python not found. Install Python 3.9+ from python.org |
| 35 | +exit /b 1 |
67 | 36 |
|
68 | | -if not defined PYTHON_CMD ( |
69 | | - echo %LOG_PREFIX% ERROR: No Python ^>=3.9 found. Install Python 3.9+ and retry.>&2 |
70 | | - echo {"event": "error", "stage": "python", "message": "No Python >=3.9 found"} |
71 | | - exit /b 1 |
72 | | -) |
73 | | - |
74 | | -for /f "tokens=*" %%A in ('!PYTHON_CMD! --version 2^>^&1') do set "PY_VERSION=%%A" |
75 | | -echo %LOG_PREFIX% Using Python: %PYTHON_CMD% (%PY_VERSION%)>&2 |
76 | | -echo {"event": "progress", "stage": "python", "message": "Found %PY_VERSION%"} |
| 37 | +:found_python |
| 38 | +echo [DepthDeploy] Using Python: %PYTHON_CMD% |
| 39 | +%PYTHON_CMD% --version |
77 | 40 |
|
78 | | -REM ─── Step 2: Create virtual environment ──────────────────────────────────── |
79 | | - |
80 | | -if not exist "%VENV_DIR%\Scripts\python.exe" ( |
81 | | - echo %LOG_PREFIX% Creating virtual environment...>&2 |
82 | | - %PYTHON_CMD% -m venv "%VENV_DIR%" |
83 | | - if !errorlevel! neq 0 ( |
84 | | - echo %LOG_PREFIX% ERROR: Failed to create virtual environment>&2 |
85 | | - echo {"event": "error", "stage": "venv", "message": "Failed to create venv"} |
| 41 | +REM ── 2. Create venv ───────────────────────────────────────────────── |
| 42 | +if not exist ".venv\Scripts\python.exe" ( |
| 43 | + echo [DepthDeploy] Creating virtual environment... |
| 44 | + %PYTHON_CMD% -m venv .venv |
| 45 | + if %ERRORLEVEL% neq 0 ( |
| 46 | + echo [DepthDeploy] ERROR: Failed to create venv |
86 | 47 | exit /b 1 |
87 | 48 | ) |
88 | 49 | ) |
89 | 50 |
|
90 | | -set "PIP=%VENV_DIR%\Scripts\pip.exe" |
91 | | -set "VPYTHON=%VENV_DIR%\Scripts\python.exe" |
| 51 | +set "VENV_PIP=.venv\Scripts\pip.exe" |
| 52 | +set "VENV_PYTHON=.venv\Scripts\python.exe" |
92 | 53 |
|
93 | | -"%PIP%" install --upgrade pip -q >nul 2>&1 |
| 54 | +echo [DepthDeploy] Upgrading pip... |
| 55 | +%VENV_PYTHON% -m pip install --upgrade pip >nul 2>&1 |
94 | 56 |
|
95 | | -echo {"event": "progress", "stage": "venv", "message": "Virtual environment ready"} |
| 57 | +REM ── 3. Detect GPU ────────────────────────────────────────────────── |
| 58 | +echo [DepthDeploy] Detecting GPU hardware... |
96 | 59 |
|
97 | | -REM ─── Step 2.5: Bundle env_config.py alongside transform.py ───────────────── |
| 60 | +set "GPU_BACKEND=cpu" |
| 61 | +set "REQUIREMENTS_FILE=requirements_cpu.txt" |
98 | 62 |
|
99 | | -if defined LIB_DIR ( |
100 | | - if exist "%LIB_DIR%\env_config.py" ( |
101 | | - copy /Y "%LIB_DIR%\env_config.py" "%SKILL_DIR%\scripts\env_config.py" >nul 2>&1 |
102 | | - echo %LOG_PREFIX% Bundled env_config.py into scripts\>&2 |
103 | | - ) |
| 63 | +REM 3a. Check for NVIDIA GPU via nvidia-smi |
| 64 | +nvidia-smi --query-gpu=name --format=csv,noheader,nounits >nul 2>&1 |
| 65 | +if %ERRORLEVEL% equ 0 ( |
| 66 | + echo [DepthDeploy] NVIDIA GPU detected: |
| 67 | + nvidia-smi --query-gpu=name,memory.total --format=csv,noheader,nounits |
| 68 | + set "GPU_BACKEND=cuda" |
| 69 | + set "REQUIREMENTS_FILE=requirements_cuda.txt" |
| 70 | + goto :gpu_detected |
104 | 71 | ) |
105 | 72 |
|
106 | | -REM ─── Step 3: Detect hardware via env_config ──────────────────────────────── |
107 | | - |
108 | | -set "BACKEND=cpu" |
109 | | - |
110 | | -REM Find env_config.py — bundled copy or repo lib\ |
111 | | -set "ENV_CONFIG_DIR=" |
112 | | -if exist "%SKILL_DIR%\scripts\env_config.py" ( |
113 | | - set "ENV_CONFIG_DIR=%SKILL_DIR%\scripts" |
114 | | -) else if defined LIB_DIR ( |
115 | | - if exist "%LIB_DIR%\env_config.py" ( |
116 | | - set "ENV_CONFIG_DIR=%LIB_DIR%" |
117 | | - ) |
| 73 | +REM 3b. Check for any GPU via WMI (AMD, Intel, Qualcomm) |
| 74 | +for /f "tokens=*" %%G in ('powershell -NoProfile -Command "Get-CimInstance Win32_VideoController | Where-Object { $_.Name -notlike '*Microsoft*' -and $_.Name -notlike '*Remote*' } | Select-Object -ExpandProperty Name" 2^>nul') do ( |
| 75 | + echo [DepthDeploy] GPU found: %%G |
| 76 | + set "GPU_BACKEND=directml" |
| 77 | + set "REQUIREMENTS_FILE=requirements_directml.txt" |
118 | 78 | ) |
119 | 79 |
|
120 | | -if defined ENV_CONFIG_DIR ( |
121 | | - echo %LOG_PREFIX% Detecting hardware via env_config.py...>&2 |
122 | | - |
123 | | - REM Run env_config detection via Python (temp file avoids for /f quoting issues) |
124 | | - set "ENV_CONFIG_DIR=!ENV_CONFIG_DIR!" |
125 | | - set "_TMPBACK=%TEMP%\_aegis_detect_backend.txt" |
126 | | - "%VPYTHON%" -c "import sys,os; sys.path.insert(0, os.environ['ENV_CONFIG_DIR']); from env_config import HardwareEnv; env = HardwareEnv.detect(); print(env.backend)" > "!_TMPBACK!" 2>nul |
127 | | - if exist "!_TMPBACK!" ( |
128 | | - set /p DETECTED_BACKEND=<"!_TMPBACK!" |
129 | | - del "!_TMPBACK!" 2>nul |
130 | | - ) |
| 80 | +:gpu_detected |
| 81 | +echo [DepthDeploy] Selected backend: %GPU_BACKEND% |
| 82 | +echo [DepthDeploy] Requirements: %REQUIREMENTS_FILE% |
131 | 83 |
|
132 | | - REM Validate backend value (Windows: only cuda, intel, cpu are realistic) |
133 | | - if "!DETECTED_BACKEND!"=="cuda" ( |
134 | | - set "BACKEND=cuda" |
135 | | - ) else if "!DETECTED_BACKEND!"=="intel" ( |
136 | | - set "BACKEND=intel" |
137 | | - ) else if "!DETECTED_BACKEND!"=="cpu" ( |
138 | | - set "BACKEND=cpu" |
139 | | - ) else ( |
140 | | - echo %LOG_PREFIX% env_config returned '!DETECTED_BACKEND!', falling back to heuristic>&2 |
141 | | - set "BACKEND=cpu" |
142 | | - ) |
143 | | - |
144 | | - echo %LOG_PREFIX% env_config detected backend: !BACKEND!>&2 |
145 | | -) else ( |
146 | | - echo %LOG_PREFIX% env_config.py not found, using heuristic detection...>&2 |
147 | | - |
148 | | - REM Fallback: inline GPU detection via nvidia-smi |
149 | | - where nvidia-smi >nul 2>&1 |
150 | | - if !errorlevel! equ 0 ( |
151 | | - for /f "tokens=*" %%G in ('nvidia-smi --query-gpu^=driver_version --format^=csv^,noheader 2^>nul') do ( |
152 | | - if not "%%G"=="" ( |
153 | | - set "BACKEND=cuda" |
154 | | - echo %LOG_PREFIX% Detected NVIDIA GPU ^(driver: %%G^)>&2 |
155 | | - ) |
156 | | - ) |
157 | | - ) |
158 | | -) |
159 | | - |
160 | | -echo {"event": "progress", "stage": "gpu", "backend": "!BACKEND!", "message": "Compute backend: !BACKEND!"} |
161 | | - |
162 | | -REM ─── Step 4: Install requirements ────────────────────────────────────────── |
163 | | - |
164 | | -set "REQ_FILE=%SKILL_DIR%\requirements_!BACKEND!.txt" |
165 | | - |
166 | | -if not exist "!REQ_FILE!" ( |
167 | | - echo %LOG_PREFIX% WARNING: !REQ_FILE! not found, falling back to CPU>&2 |
168 | | - set "REQ_FILE=%SKILL_DIR%\requirements_cpu.txt" |
169 | | - set "BACKEND=cpu" |
170 | | -) |
171 | | - |
172 | | -echo %LOG_PREFIX% Installing dependencies from !REQ_FILE! ...>&2 |
173 | | -echo {"event": "progress", "stage": "install", "message": "Installing !BACKEND! dependencies..."} |
174 | | - |
175 | | -if "!BACKEND!"=="cuda" ( |
176 | | - REM CUDA on Windows: install torch with CUDA index, then remaining deps |
177 | | - "%PIP%" install torch torchvision --index-url https://download.pytorch.org/whl/cu124 -q 2>&1 | findstr /V "^$" >nul |
178 | | - if !errorlevel! neq 0 ( |
179 | | - echo %LOG_PREFIX% WARNING: CUDA torch install failed, trying cu121...>&2 |
180 | | - "%PIP%" install torch torchvision --index-url https://download.pytorch.org/whl/cu121 -q 2>&1 | findstr /V "^$" >nul |
181 | | - ) |
182 | | - REM Install remaining requirements (depth-anything-v2, tensorrt, etc.) |
183 | | - "%PIP%" install -r "!REQ_FILE!" -q 2>&1 | findstr /V "^$" >nul |
184 | | -) else ( |
185 | | - "%PIP%" install -r "!REQ_FILE!" -q 2>&1 | findstr /V "^$" >nul |
| 84 | +REM ── 4. Install dependencies ──────────────────────────────────────── |
| 85 | +if not exist "%REQUIREMENTS_FILE%" ( |
| 86 | + echo [DepthDeploy] WARNING: %REQUIREMENTS_FILE% not found, falling back to requirements_cpu.txt |
| 87 | + set "REQUIREMENTS_FILE=requirements_cpu.txt" |
186 | 88 | ) |
187 | 89 |
|
188 | | -REM ─── Step 5: Pre-build TensorRT engine (CUDA only) ───────────────────────── |
189 | | - |
190 | | -if "!BACKEND!"=="cuda" ( |
191 | | - echo %LOG_PREFIX% Pre-building TensorRT FP16 engine ^(30-120s one-time build^)...>&2 |
192 | | - echo {"event": "progress", "stage": "optimize", "message": "Building TensorRT FP16 engine (~30-120s)..."} |
193 | | - |
194 | | - "%VPYTHON%" -c "import sys,os; sys.path.insert(0, '%SKILL_DIR%\\scripts'); from transform import DepthEstimationSkill, PYTORCH_CONFIGS, TRT_CACHE_DIR; import torch; gpu_tag = torch.cuda.get_device_name(0).replace(' ', '_').lower(); cfg = PYTORCH_CONFIGS['depth-anything-v2-small']; engine_path = TRT_CACHE_DIR / f'{cfg[\"filename\"].replace(\".pth\", \"\")}_fp16_{gpu_tag}.trt'; print(f'Engine exists: {engine_path.exists()}') if engine_path.exists() else None; skill = DepthEstimationSkill(); config = {'model': 'depth-anything-v2-small', 'device': 'auto', 'colormap': 'inferno', 'blend_mode': 'depth_only'}; info = skill._load_tensorrt('depth-anything-v2-small', config); print(f'TensorRT engine built: {info}')" 2>&1 |
195 | | - |
196 | | - if !errorlevel! equ 0 ( |
197 | | - echo {"event": "progress", "stage": "optimize", "message": "TensorRT engine built successfully"} |
198 | | - ) else ( |
199 | | - echo %LOG_PREFIX% WARNING: TensorRT build failed, will use PyTorch CUDA at runtime>&2 |
200 | | - echo {"event": "progress", "stage": "optimize", "message": "TensorRT build failed — PyTorch CUDA fallback"} |
| 90 | +echo [DepthDeploy] Installing %REQUIREMENTS_FILE%... |
| 91 | +%VENV_PIP% install -r %REQUIREMENTS_FILE% |
| 92 | +if %ERRORLEVEL% neq 0 ( |
| 93 | + echo [DepthDeploy] WARNING: Install failed for %REQUIREMENTS_FILE% |
| 94 | + if not "%GPU_BACKEND%"=="cpu" ( |
| 95 | + echo [DepthDeploy] Falling back to CPU requirements... |
| 96 | + %VENV_PIP% install -r requirements_cpu.txt |
201 | 97 | ) |
202 | 98 | ) |
203 | 99 |
|
204 | | -REM ─── Step 6: Verify installation ─────────────────────────────────────────── |
205 | | - |
206 | | -echo %LOG_PREFIX% Verifying installation...>&2 |
| 100 | +REM ── 5. Download ONNX model ───────────────────────────────────────── |
| 101 | +echo [DepthDeploy] Downloading ONNX model from HuggingFace... |
207 | 102 |
|
208 | | -if defined ENV_CONFIG_DIR ( |
209 | | - "%VPYTHON%" -c "import sys,os,json; sys.path.insert(0, os.environ['ENV_CONFIG_DIR']); from env_config import HardwareEnv; env = HardwareEnv.detect(); print(json.dumps(env.to_dict(), indent=2))" 2>&1 |
| 103 | +%VENV_PYTHON% -c "from huggingface_hub import snapshot_download; snapshot_download('onnx-community/depth-anything-v2-small', local_dir='models/onnx/depth-anything-v2-small', allow_patterns=['onnx/*.onnx', 'onnx/*.json', 'preprocessor_config.json', 'config.json'])" |
| 104 | +if %ERRORLEVEL% equ 0 ( |
| 105 | + echo [DepthDeploy] ONNX model downloaded successfully |
210 | 106 | ) else ( |
211 | | - "%VPYTHON%" -c "import torch; print(f'torch={torch.__version__}, CUDA={torch.cuda.is_available()}')" 2>&1 |
| 107 | + echo [DepthDeploy] WARNING: Model download failed — will retry on first run |
212 | 108 | ) |
213 | 109 |
|
214 | | -"%VPYTHON%" -c "import sys; sys.path.insert(0, '%SKILL_DIR%\\scripts'); from transform import DepthEstimationSkill; print('transform.py: OK')" 2>&1 |
215 | | -if !errorlevel! neq 0 ( |
216 | | - echo %LOG_PREFIX% WARNING: transform.py import check failed>&2 |
| 110 | +REM ── 6. Verify installation ───────────────────────────────────────── |
| 111 | +echo [DepthDeploy] Verifying ONNX Runtime installation... |
| 112 | + |
| 113 | +%VENV_PYTHON% -c "import onnxruntime as ort; eps = ort.get_available_providers(); print(f'[DepthDeploy] Available EPs: {eps}')" |
| 114 | +if %ERRORLEVEL% neq 0 ( |
| 115 | + echo [DepthDeploy] ERROR: ONNX Runtime import failed |
| 116 | + exit /b 1 |
217 | 117 | ) |
218 | 118 |
|
219 | | -echo {"event": "complete", "backend": "!BACKEND!", "message": "Depth Estimation skill installed (!BACKEND! backend)"} |
220 | | -echo %LOG_PREFIX% Done! Backend: !BACKEND!>&2 |
| 119 | +REM Log detected execution providers |
| 120 | +%VENV_PYTHON% -c "import onnxruntime as ort; eps = ort.get_available_providers(); cuda = 'CUDAExecutionProvider' in eps; trt = 'TensorrtExecutionProvider' in eps; dml = 'DmlExecutionProvider' in eps; print(f'[DepthDeploy] CUDA EP: {cuda}, TensorRT EP: {trt}, DirectML EP: {dml}')" |
221 | 121 |
|
222 | | -endlocal |
| 122 | +echo [DepthDeploy] Deployment complete (%GPU_BACKEND% backend) |
223 | 123 | exit /b 0 |
0 commit comments