mirror of
https://github.com/jamiepine/voicebox.git
synced 2026-09-29 15:15:27 -07:00
Update provider documentation and enhance build configurations
- Clarified the bundling of PyTorch CPU providers for Windows and macOS Intel builds in documentation. - Improved handling of platform-specific dependencies in the build process, including asyncio support for PyInstaller. - Updated backend logic to gracefully handle missing dependencies and provide clearer error messages. - Enhanced progress management to ensure compatibility with PyInstaller's async handling. - Removed unnecessary exclusions from the build scripts for PyTorch providers to streamline the build process.
This commit is contained in:
+4
-3
@@ -148,9 +148,10 @@ Voicebox uses a modular provider system to support different inference backends.
|
|||||||
**Hybrid Provider:**
|
**Hybrid Provider:**
|
||||||
|
|
||||||
- `pytorch-cpu` — Can be bundled OR downloaded depending on platform
|
- `pytorch-cpu` — Can be bundled OR downloaded depending on platform
|
||||||
- **Bundled** with macOS Intel builds (`.dmg` for x64)
|
- **Bundled** with Windows and macOS Intel builds
|
||||||
- Configured in `.github/workflows/release.yml` with `backend: "pytorch"`
|
- macOS Intel: `.dmg` for x64 with `backend: "pytorch"`
|
||||||
- **Downloaded** on first use for Windows/Linux builds (~300MB)
|
- Windows: `.exe` installer with PyTorch CPU included
|
||||||
|
- **Downloaded** on first use for Linux builds (~300MB)
|
||||||
- Falls back to bundled version if external binary not found
|
- Falls back to bundled version if external binary not found
|
||||||
|
|
||||||
**External-Only Providers:**
|
**External-Only Providers:**
|
||||||
|
|||||||
@@ -205,14 +205,14 @@ Voicebox uses a modular provider system to support different inference backends:
|
|||||||
|
|
||||||
- **`pytorch-cpu`** — Universal CPU provider (bundled or downloaded)
|
- **`pytorch-cpu`** — Universal CPU provider (bundled or downloaded)
|
||||||
|
|
||||||
- Bundled with macOS Intel builds
|
- Bundled with Windows and macOS Intel builds
|
||||||
- Downloaded on first use for Windows/Linux (~300MB)
|
- Downloaded on first use for Linux (~300MB)
|
||||||
|
|
||||||
- **`pytorch-cuda`** — Optional NVIDIA GPU-accelerated provider
|
- **`pytorch-cuda`** — Optional NVIDIA GPU-accelerated provider
|
||||||
- Windows/Linux only (~2.4GB)
|
- Windows/Linux only (~2.4GB)
|
||||||
- 4-5x faster inference on CUDA-capable GPUs
|
- 4-5x faster inference on CUDA-capable GPUs
|
||||||
|
|
||||||
macOS builds work out of the box with bundled providers. Windows and Linux users download a provider on first launch. The app automatically detects your hardware and recommends the best option. All downloadable providers are distributed via Cloudflare R2 for fast, global delivery.
|
macOS and Windows builds work out of the box with bundled providers. Linux users download a provider on first launch. The app automatically detects your hardware and recommends the best option. All downloadable providers are distributed via Cloudflare R2 for fast, global delivery.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -118,22 +118,37 @@ _stt_backend: Optional[STTBackend] = None
|
|||||||
def get_tts_backend() -> TTSBackend:
|
def get_tts_backend() -> TTSBackend:
|
||||||
"""
|
"""
|
||||||
Get or create TTS backend instance based on platform.
|
Get or create TTS backend instance based on platform.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
TTS backend instance (MLX or PyTorch)
|
TTS backend instance (MLX or PyTorch)
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
ImportError: If required dependencies (mlx or torch) are not available
|
||||||
"""
|
"""
|
||||||
global _tts_backend
|
global _tts_backend
|
||||||
|
|
||||||
if _tts_backend is None:
|
if _tts_backend is None:
|
||||||
backend_type = get_backend_type()
|
backend_type = get_backend_type()
|
||||||
|
|
||||||
if backend_type == "mlx":
|
if backend_type == "mlx":
|
||||||
from .mlx_backend import MLXTTSBackend
|
try:
|
||||||
_tts_backend = MLXTTSBackend()
|
from .mlx_backend import MLXTTSBackend
|
||||||
|
_tts_backend = MLXTTSBackend()
|
||||||
|
except ImportError as e:
|
||||||
|
raise ImportError(
|
||||||
|
f"MLX backend dependencies not available. "
|
||||||
|
f"Please install mlx and mlx_audio or download a provider. Error: {e}"
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
from .pytorch_backend import PyTorchTTSBackend
|
try:
|
||||||
_tts_backend = PyTorchTTSBackend()
|
from .pytorch_backend import PyTorchTTSBackend
|
||||||
|
_tts_backend = PyTorchTTSBackend()
|
||||||
|
except ImportError as e:
|
||||||
|
raise ImportError(
|
||||||
|
f"PyTorch backend dependencies not available. "
|
||||||
|
f"Please download a TTS provider (pytorch-cpu or pytorch-cuda) from the Downloads page. Error: {e}"
|
||||||
|
)
|
||||||
|
|
||||||
return _tts_backend
|
return _tts_backend
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+29
-5
@@ -59,9 +59,16 @@ def build_server():
|
|||||||
# Fix for pkg_resources and jaraco namespace packages
|
# Fix for pkg_resources and jaraco namespace packages
|
||||||
'--hidden-import', 'pkg_resources.extern',
|
'--hidden-import', 'pkg_resources.extern',
|
||||||
'--collect-submodules', 'jaraco',
|
'--collect-submodules', 'jaraco',
|
||||||
|
# Asyncio and threading support for PyInstaller
|
||||||
|
'--hidden-import', 'asyncio',
|
||||||
|
'--hidden-import', 'asyncio.subprocess',
|
||||||
|
'--hidden-import', 'concurrent.futures',
|
||||||
|
'--hidden-import', 'concurrent.futures.thread',
|
||||||
])
|
])
|
||||||
|
|
||||||
# Platform-specific TTS backend handling
|
# Platform-specific TTS backend handling
|
||||||
|
system = platform.system()
|
||||||
|
|
||||||
if is_apple_silicon():
|
if is_apple_silicon():
|
||||||
print("Building for Apple Silicon - including MLX dependencies (bundled)")
|
print("Building for Apple Silicon - including MLX dependencies (bundled)")
|
||||||
args.extend([
|
args.extend([
|
||||||
@@ -79,13 +86,30 @@ def build_server():
|
|||||||
'--collect-data', 'mlx',
|
'--collect-data', 'mlx',
|
||||||
'--collect-data', 'mlx_audio',
|
'--collect-data', 'mlx_audio',
|
||||||
])
|
])
|
||||||
else:
|
elif system == "Windows" or (system == "Darwin" and not is_apple_silicon()):
|
||||||
print("Building for Windows/Linux - excluding PyTorch/Qwen-TTS (providers downloaded separately)")
|
# Windows and Intel macOS: Bundle PyTorch CPU provider
|
||||||
# Note: PyTorch and Qwen-TTS are NOT included - users will download providers separately
|
print(f"Building for {system} - including PyTorch CPU provider (bundled)")
|
||||||
# Only include backend abstraction (no actual TTS implementation)
|
|
||||||
args.extend([
|
args.extend([
|
||||||
'--hidden-import', 'backend.backends',
|
'--hidden-import', 'backend.backends',
|
||||||
'--hidden-import', 'backend.backends.pytorch_backend', # Keep for reference, but won't work without PyTorch
|
'--hidden-import', 'backend.backends.pytorch_backend',
|
||||||
|
'--hidden-import', 'torch',
|
||||||
|
'--hidden-import', 'transformers',
|
||||||
|
'--hidden-import', 'qwen_tts',
|
||||||
|
'--hidden-import', 'qwen_tts.inference',
|
||||||
|
'--hidden-import', 'qwen_tts.inference.qwen3_tts_model',
|
||||||
|
'--hidden-import', 'qwen_tts.inference.qwen3_tts_tokenizer',
|
||||||
|
'--hidden-import', 'qwen_tts.core',
|
||||||
|
'--hidden-import', 'qwen_tts.cli',
|
||||||
|
'--copy-metadata', 'qwen-tts',
|
||||||
|
'--collect-submodules', 'qwen_tts',
|
||||||
|
'--collect-data', 'qwen_tts',
|
||||||
|
])
|
||||||
|
else:
|
||||||
|
# Linux: No bundled provider - users download providers separately
|
||||||
|
print("Building for Linux - no bundled provider (users download separately)")
|
||||||
|
args.extend([
|
||||||
|
'--hidden-import', 'backend.backends',
|
||||||
|
'--hidden-import', 'backend.backends.pytorch_backend',
|
||||||
])
|
])
|
||||||
|
|
||||||
args.extend([
|
args.extend([
|
||||||
|
|||||||
+57
-30
@@ -14,7 +14,6 @@ from datetime import datetime
|
|||||||
import asyncio
|
import asyncio
|
||||||
import uvicorn
|
import uvicorn
|
||||||
import argparse
|
import argparse
|
||||||
import torch
|
|
||||||
import tempfile
|
import tempfile
|
||||||
import io
|
import io
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
@@ -23,6 +22,14 @@ import asyncio
|
|||||||
import signal
|
import signal
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
# Optional torch import - not available on all platforms (e.g. Windows/Linux without bundled provider)
|
||||||
|
try:
|
||||||
|
import torch
|
||||||
|
TORCH_AVAILABLE = True
|
||||||
|
except ImportError:
|
||||||
|
torch = None # type: ignore
|
||||||
|
TORCH_AVAILABLE = False
|
||||||
|
|
||||||
from . import database, models, profiles, history, tts, transcribe, config, export_import, channels, stories, __version__
|
from . import database, models, profiles, history, tts, transcribe, config, export_import, channels, stories, __version__
|
||||||
from .database import get_db, Generation as DBGeneration, VoiceProfile as DBVoiceProfile
|
from .database import get_db, Generation as DBGeneration, VoiceProfile as DBVoiceProfile
|
||||||
from .utils.progress import get_progress_manager
|
from .utils.progress import get_progress_manager
|
||||||
@@ -72,20 +79,32 @@ async def shutdown():
|
|||||||
@app.get("/health", response_model=models.HealthResponse)
|
@app.get("/health", response_model=models.HealthResponse)
|
||||||
async def health():
|
async def health():
|
||||||
"""Health check endpoint."""
|
"""Health check endpoint."""
|
||||||
from huggingface_hub import hf_hub_download, constants as hf_constants
|
from huggingface_hub import constants as hf_constants
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import os
|
|
||||||
|
|
||||||
tts_model = await tts.get_tts_model_async()
|
# Try to get TTS model provider, but it may not be available if dependencies aren't installed
|
||||||
|
tts_model = None
|
||||||
|
try:
|
||||||
|
tts_model = await tts.get_tts_model_async()
|
||||||
|
except ImportError as e:
|
||||||
|
# Provider dependencies not available (e.g., PyTorch not bundled on this platform)
|
||||||
|
# This is expected on Windows/Linux builds without a bundled provider
|
||||||
|
print(f"Provider not available: {e}")
|
||||||
|
|
||||||
backend_type = get_backend_type()
|
backend_type = get_backend_type()
|
||||||
|
|
||||||
# Check for GPU availability (CUDA or MPS)
|
# Check for GPU availability (CUDA or MPS)
|
||||||
has_cuda = torch.cuda.is_available()
|
# PyTorch might not be available if no provider is bundled
|
||||||
has_mps = hasattr(torch.backends, 'mps') and torch.backends.mps.is_available()
|
has_cuda = False
|
||||||
|
has_mps = False
|
||||||
|
if TORCH_AVAILABLE and torch is not None:
|
||||||
|
has_cuda = torch.cuda.is_available()
|
||||||
|
has_mps = hasattr(torch.backends, 'mps') and torch.backends.mps.is_available()
|
||||||
|
|
||||||
gpu_available = has_cuda or has_mps
|
gpu_available = has_cuda or has_mps
|
||||||
|
|
||||||
gpu_type = None
|
gpu_type = None
|
||||||
if has_cuda:
|
if has_cuda and torch is not None:
|
||||||
gpu_type = f"CUDA ({torch.cuda.get_device_name(0)})"
|
gpu_type = f"CUDA ({torch.cuda.get_device_name(0)})"
|
||||||
elif has_mps:
|
elif has_mps:
|
||||||
gpu_type = "MPS (Apple Silicon)"
|
gpu_type = "MPS (Apple Silicon)"
|
||||||
@@ -93,26 +112,27 @@ async def health():
|
|||||||
gpu_type = "Metal (Apple Silicon via MLX)"
|
gpu_type = "Metal (Apple Silicon via MLX)"
|
||||||
|
|
||||||
vram_used = None
|
vram_used = None
|
||||||
if has_cuda:
|
if has_cuda and torch is not None:
|
||||||
vram_used = torch.cuda.memory_allocated() / 1024 / 1024 # MB
|
vram_used = torch.cuda.memory_allocated() / 1024 / 1024 # MB
|
||||||
|
|
||||||
# Check if model is loaded - use the same logic as model status endpoint
|
# Check if model is loaded - use the same logic as model status endpoint
|
||||||
model_loaded = False
|
model_loaded = False
|
||||||
model_size = None
|
model_size = None
|
||||||
try:
|
if tts_model is not None:
|
||||||
# Use the same check as model status endpoint
|
try:
|
||||||
if tts_model.is_loaded():
|
# Use the same check as model status endpoint
|
||||||
model_loaded = True
|
if tts_model.is_loaded():
|
||||||
# Get the actual loaded model size
|
model_loaded = True
|
||||||
# Check _current_model_size first (more reliable for actually loaded models)
|
# Get the actual loaded model size
|
||||||
model_size = getattr(tts_model, '_current_model_size', None)
|
# Check _current_model_size first (more reliable for actually loaded models)
|
||||||
if not model_size:
|
model_size = getattr(tts_model, '_current_model_size', None)
|
||||||
# Fallback to model_size attribute (which should be set when model loads)
|
if not model_size:
|
||||||
model_size = getattr(tts_model, 'model_size', None)
|
# Fallback to model_size attribute (which should be set when model loads)
|
||||||
except Exception:
|
model_size = getattr(tts_model, 'model_size', None)
|
||||||
# If there's an error checking, assume not loaded
|
except Exception:
|
||||||
model_loaded = False
|
# If there's an error checking, assume not loaded
|
||||||
model_size = None
|
model_loaded = False
|
||||||
|
model_size = None
|
||||||
|
|
||||||
# Check if default model is downloaded (cached)
|
# Check if default model is downloaded (cached)
|
||||||
model_downloaded = None
|
model_downloaded = None
|
||||||
@@ -1836,11 +1856,12 @@ async def get_active_tasks():
|
|||||||
def _get_gpu_status() -> str:
|
def _get_gpu_status() -> str:
|
||||||
"""Get GPU availability status."""
|
"""Get GPU availability status."""
|
||||||
backend_type = get_backend_type()
|
backend_type = get_backend_type()
|
||||||
if torch.cuda.is_available():
|
if TORCH_AVAILABLE and torch is not None:
|
||||||
return f"CUDA ({torch.cuda.get_device_name(0)})"
|
if torch.cuda.is_available():
|
||||||
elif hasattr(torch.backends, 'mps') and torch.backends.mps.is_available():
|
return f"CUDA ({torch.cuda.get_device_name(0)})"
|
||||||
return "MPS (Apple Silicon)"
|
elif hasattr(torch.backends, 'mps') and torch.backends.mps.is_available():
|
||||||
elif backend_type == "mlx":
|
return "MPS (Apple Silicon)"
|
||||||
|
if backend_type == "mlx":
|
||||||
return "Metal (Apple Silicon via MLX)"
|
return "Metal (Apple Silicon via MLX)"
|
||||||
return "None (CPU only)"
|
return "None (CPU only)"
|
||||||
|
|
||||||
@@ -1879,8 +1900,14 @@ async def shutdown_event():
|
|||||||
"""Run on application shutdown."""
|
"""Run on application shutdown."""
|
||||||
print("voicebox API shutting down...")
|
print("voicebox API shutting down...")
|
||||||
# Unload models to free memory
|
# Unload models to free memory
|
||||||
tts.unload_tts_model()
|
try:
|
||||||
transcribe.unload_whisper_model()
|
tts.unload_tts_model()
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Warning: Failed to unload TTS model: {e}")
|
||||||
|
try:
|
||||||
|
transcribe.unload_whisper_model()
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Warning: Failed to unload Whisper model: {e}")
|
||||||
|
|
||||||
|
|
||||||
# ============================================
|
# ============================================
|
||||||
|
|||||||
@@ -171,15 +171,12 @@ class ProviderManager:
|
|||||||
machine = platform.machine()
|
machine = platform.machine()
|
||||||
|
|
||||||
if system == "Darwin" and machine == "arm64":
|
if system == "Darwin" and machine == "arm64":
|
||||||
# Apple Silicon gets MLX
|
# Apple Silicon gets MLX bundled
|
||||||
installed.append("apple-mlx")
|
installed.append("apple-mlx")
|
||||||
|
elif system == "Windows" or (system == "Darwin" and machine != "arm64"):
|
||||||
# PyTorch CPU is available on all platforms (check if bundled or downloaded)
|
# Windows and Intel macOS get PyTorch CPU bundled
|
||||||
# For now, assume it's bundled on macOS Intel, Windows, Linux
|
|
||||||
# Downloaded binaries will be detected below
|
|
||||||
if not (system == "Darwin" and machine == "arm64"):
|
|
||||||
# Non-Apple Silicon systems have PyTorch CPU bundled
|
|
||||||
installed.append("pytorch-cpu")
|
installed.append("pytorch-cpu")
|
||||||
|
# Linux: no bundled provider - users must download
|
||||||
|
|
||||||
# Check for downloaded providers (Phase 2)
|
# Check for downloaded providers (Phase 2)
|
||||||
providers_dir = _get_providers_dir()
|
providers_dir = _get_providers_dir()
|
||||||
|
|||||||
@@ -49,11 +49,17 @@ class ProgressManager:
|
|||||||
queue.put_nowait(progress_data.copy())
|
queue.put_nowait(progress_data.copy())
|
||||||
except RuntimeError:
|
except RuntimeError:
|
||||||
# Not in async context (running in background thread)
|
# Not in async context (running in background thread)
|
||||||
# Use call_soon_threadsafe to safely put on queue
|
# Use asyncio.run_coroutine_threadsafe for better PyInstaller compatibility
|
||||||
if self._main_loop and self._main_loop.is_running():
|
if self._main_loop and self._main_loop.is_running():
|
||||||
self._main_loop.call_soon_threadsafe(
|
async def put_data_async():
|
||||||
lambda q=queue, d=progress_data.copy(): q.put_nowait(d) if not q.full() else None
|
try:
|
||||||
)
|
queue.put_nowait(progress_data.copy())
|
||||||
|
except asyncio.QueueFull:
|
||||||
|
pass # Queue full, drop update
|
||||||
|
try:
|
||||||
|
asyncio.run_coroutine_threadsafe(put_data_async(), self._main_loop)
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning(f"Failed to schedule progress update: {e}")
|
||||||
else:
|
else:
|
||||||
logger.debug(f"No main loop available for {model_name}, skipping notification")
|
logger.debug(f"No main loop available for {model_name}, skipping notification")
|
||||||
except asyncio.QueueFull:
|
except asyncio.QueueFull:
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ from PyInstaller.utils.hooks import collect_data_files
|
|||||||
from PyInstaller.utils.hooks import collect_submodules
|
from PyInstaller.utils.hooks import collect_submodules
|
||||||
|
|
||||||
datas = []
|
datas = []
|
||||||
hiddenimports = ['backend', 'backend.main', 'backend.config', 'backend.database', 'backend.models', 'backend.profiles', 'backend.history', 'backend.tts', 'backend.transcribe', 'backend.platform_detect', 'backend.providers', 'backend.providers.base', 'backend.providers.bundled', 'backend.providers.types', 'backend.utils.audio', 'backend.utils.cache', 'backend.utils.progress', 'backend.utils.hf_progress', 'backend.utils.validation', 'fastapi', 'uvicorn', 'sqlalchemy', 'librosa', 'soundfile', 'pkg_resources.extern', 'backend.backends', 'backend.backends.mlx_backend', 'mlx', 'mlx.core', 'mlx.nn', 'mlx_audio', 'mlx_audio.tts', 'mlx_audio.stt']
|
hiddenimports = ['backend', 'backend.main', 'backend.config', 'backend.database', 'backend.models', 'backend.profiles', 'backend.history', 'backend.tts', 'backend.transcribe', 'backend.platform_detect', 'backend.providers', 'backend.providers.base', 'backend.providers.bundled', 'backend.providers.types', 'backend.utils.audio', 'backend.utils.cache', 'backend.utils.progress', 'backend.utils.hf_progress', 'backend.utils.validation', 'fastapi', 'uvicorn', 'sqlalchemy', 'librosa', 'soundfile', 'pkg_resources.extern', 'asyncio', 'asyncio.subprocess', 'concurrent.futures', 'concurrent.futures.thread', 'backend.backends', 'backend.backends.mlx_backend', 'mlx', 'mlx.core', 'mlx.nn', 'mlx_audio', 'mlx_audio.tts', 'mlx_audio.stt']
|
||||||
datas += collect_data_files('mlx')
|
datas += collect_data_files('mlx')
|
||||||
datas += collect_data_files('mlx_audio')
|
datas += collect_data_files('mlx_audio')
|
||||||
hiddenimports += collect_submodules('jaraco')
|
hiddenimports += collect_submodules('jaraco')
|
||||||
|
|||||||
@@ -55,23 +55,7 @@ def build_provider():
|
|||||||
'--hidden-import', 'numpy',
|
'--hidden-import', 'numpy',
|
||||||
'--hidden-import', 'librosa',
|
'--hidden-import', 'librosa',
|
||||||
])
|
])
|
||||||
|
|
||||||
# Exclude large unused modules to reduce binary size
|
|
||||||
args.extend([
|
|
||||||
'--exclude-module', 'torch.utils.tensorboard',
|
|
||||||
'--exclude-module', 'tensorboard',
|
|
||||||
'--exclude-module', 'triton',
|
|
||||||
'--exclude-module', 'torch._dynamo',
|
|
||||||
'--exclude-module', 'torch._inductor',
|
|
||||||
'--exclude-module', 'torch.utils.benchmark',
|
|
||||||
'--exclude-module', 'IPython',
|
|
||||||
'--exclude-module', 'matplotlib',
|
|
||||||
'--exclude-module', 'PIL',
|
|
||||||
'--exclude-module', 'cv2',
|
|
||||||
'--exclude-module', 'torchvision',
|
|
||||||
'--exclude-module', 'torchaudio',
|
|
||||||
])
|
|
||||||
|
|
||||||
args.extend([
|
args.extend([
|
||||||
'--noconfirm',
|
'--noconfirm',
|
||||||
'--clean',
|
'--clean',
|
||||||
|
|||||||
@@ -57,23 +57,7 @@ def build_provider():
|
|||||||
'--hidden-import', 'numpy',
|
'--hidden-import', 'numpy',
|
||||||
'--hidden-import', 'librosa',
|
'--hidden-import', 'librosa',
|
||||||
])
|
])
|
||||||
|
|
||||||
# Exclude large unused modules to reduce binary size
|
|
||||||
args.extend([
|
|
||||||
'--exclude-module', 'torch.utils.tensorboard',
|
|
||||||
'--exclude-module', 'tensorboard',
|
|
||||||
'--exclude-module', 'triton',
|
|
||||||
'--exclude-module', 'torch._dynamo',
|
|
||||||
'--exclude-module', 'torch._inductor',
|
|
||||||
'--exclude-module', 'torch.utils.benchmark',
|
|
||||||
'--exclude-module', 'IPython',
|
|
||||||
'--exclude-module', 'matplotlib',
|
|
||||||
'--exclude-module', 'PIL',
|
|
||||||
'--exclude-module', 'cv2',
|
|
||||||
'--exclude-module', 'torchvision',
|
|
||||||
'--exclude-module', 'torchaudio',
|
|
||||||
])
|
|
||||||
|
|
||||||
args.extend([
|
args.extend([
|
||||||
'--noconfirm',
|
'--noconfirm',
|
||||||
'--clean',
|
'--clean',
|
||||||
|
|||||||
Binary file not shown.
Reference in New Issue
Block a user