How UV Custom Indexes Work with PyTorch: A Complete Configuration Guide
UV custom indexes let you configure multiple PyTorch wheel sources in a single pyproject.toml, enabling seamless switching between CPU-only and CUDA-enabled builds using the --extra flag.
The baonguyen6742/uv-install-torch repository demonstrates how uv custom indexes solve PyTorch's split distribution model—where CPU and GPU wheels live on separate URLs—without maintaining multiple configuration files. By mapping specific package versions to distinct index URLs based on optional dependencies, UV resolves the correct wheel architecture automatically.
Declaring PyTorch Index URLs with [tool.uv.index]
In pyproject.toml, UV custom indexes are defined under the [tool.uv.index] table. For PyTorch, you must register both the CPU and CUDA wheel repositories hosted by PyTorch.org.
The configuration defines two named indexes:
pytorch-cpu:https://download.pytorch.org/whl/cpupytorch-cu124:https://download.pytorch.org/whl/cu124
These entries appear at lines 53-62 in the repository's pyproject.toml:
[[tool.uv.index]]
name = "pytorch-cpu"
url = "https://download.pytorch.org/whl/cpu"
[[tool.uv.index]]
name = "pytorch-cu124"
url = "https://download.pytorch.org/whl/cu124"
Mapping Packages to UV Custom Indexes with [tool.uv.sources]
The [tool.uv.sources] table tells UV which index to query for each package based on the active optional dependency (extra). This mapping connects the torch, torchvision, and torchaudio packages to their respective CPU or CUDA indexes.
According to the source configuration at lines 37-50:
[tool.uv.sources]
torch = [
{ index = "pytorch-cpu", extra = "cpu" },
{ index = "pytorch-cu124", extra = "cu124" },
]
torchvision = [
{ index = "pytorch-cpu", extra = "cpu" },
{ index = "pytorch-cu124", extra = "cu124" },
]
torchaudio = [
{ index = "pytorch-cpu", extra = "cpu" },
{ index = "pytorch-cu124", extra = "cu124" },
]
Each source object contains:
index: The name matching a[tool.uv.index]entryextra: The optional-dependency group that activates this source
Preventing Mixed Environments with Conflicts
To ensure users don't accidentally install both CPU and CUDA variants simultaneously, the repository declares these extras as mutually exclusive using the conflicts setting at lines 30-33:
[tool.uv]
conflicts = [
[
{ extra = "cpu" },
{ extra = "cu124" },
],
]
This prevents the resolver from selecting both the cpu and cu124 extras in the same environment.
Defining Version-Pinned Optional Dependencies
The actual package versions are pinned under [project.optional-dependencies]. Both extras reference identical version constraints—UV selects the correct wheel based on the index mapping rather than version differences:
[project.optional-dependencies]
cpu = ["torch==2.4.1", "torchvision==0.19.1", "torchaudio==2.4.1"]
cu124 = ["torch==2.4.1", "torchvision==0.19.1", "torchaudio==2.4.1"]
Installing PyTorch Using UV Custom Indexes
With the configuration in place, installing PyTorch requires only selecting the appropriate extra:
CPU-only installation:
uv sync --extra cpu
CUDA 12.4 installation:
uv sync --extra cu124
When you run these commands, UV:
- Activates the specified extra from
[project.optional-dependencies] - Looks up each package in
[tool.uv.sources]to find the matching index for that extra - Queries the URL defined in
[tool.uv.index]to resolve the wheel - Records the exact download URL in
uv.lockfor reproducibility
Cache Management for PyTorch Reinstallations
If you need to force a reinstall after driver updates or architecture changes, clear the UV cache before re-syncing:
uv cache clean torch
uv sync --extra cu124
The uv cache clean torch command removes only the cached torch wheels, while uv cache prune removes all unused entries.
Summary
- UV custom indexes are declared in
[tool.uv.index]with named URLs pointing to PyTorch's CPU and CUDA wheel repositories. - The
[tool.uv.sources]table maps packages to specific indexes based on optional dependency extras. - The
conflictssetting prevents simultaneous installation of incompatible CPU and CUDA variants. - Version pinning occurs in
[project.optional-dependencies], while wheel selection happens via index mapping. - UV records the resolved URLs in
uv.lock, ensuring reproducible installations across different machines.
Frequently Asked Questions
How do UV custom indexes differ from standard PyPI configuration?
Unlike pip's global index URL or extra index URLs, UV custom indexes allow per-package index selection based on conditional extras. This lets you define both CPU and CUDA PyTorch sources in the same file, whereas pip would require separate requirements files or manual URL specification.
Can I install both CPU and CUDA PyTorch using UV custom indexes simultaneously?
No. The repository explicitly prevents this using the conflicts array in [tool.uv], which makes the cpu and cu124 extras mutually exclusive. Attempting to sync with both extras (uv sync --extra cpu --extra cu124) will result in a resolution error.
How do I verify which index UV used to install PyTorch?
Check the uv.lock file generated after syncing. This lockfile records the exact URL from which each wheel was downloaded, confirming whether the package came from https://download.pytorch.org/whl/cpu or https://download.pytorch.org/whl/cu124.
What happens if I run uv sync without specifying an extra?
Without the cpu or cu124 extra, UV will not activate the custom index mappings in [tool.uv.sources]. The resolver will attempt to find PyTorch packages on the default PyPI index, which typically lacks the platform-specific wheels or contains different builds than the official PyTorch indexes.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →