🧭 How toSoftwareBeginner✨ AI-assisted

How to Pin Python Dependencies for Reproducible AI Builds

WittyTech··2 min read
#python#dependencies#reproducibility

Python AI projects depend on many packages that release often: model SDKs, tokenizers, numerical libraries and their dependencies. If your requirements file says anthropic or numpy>=1.26, the next build may install different versions from the last one. Sometimes nothing changes. Sometimes a service starts failing, or behaves slightly differently, and nobody touched the code.

Locking dependencies makes every build install exactly the same versions.

Step 1: Separate what you want from what you get

Keep two files:

  • Direct dependencies with loose version ranges, in pyproject.toml.
  • A lock file listing every package, including indirect ones, with exact versions and hashes.

Step 2: Generate a lock file

With uv:

uv lock
uv sync --frozen

uv lock resolves all dependencies and writes uv.lock. uv sync --frozen installs exactly what the lock file says and fails if it's out of date, which is what you want in CI and Docker builds.

With pip-tools, the equivalent is:

pip-compile --generate-hashes requirements.in
pip install --require-hashes -r requirements.txt

Hashes make sure the downloaded files match what was locked, which protects against a package being replaced.

Step 3: Commit the lock file

The lock file belongs in version control. Changes to it appear in pull requests, so reviewers can see when an upgrade happens.

Step 4: Upgrade on purpose

Update dependencies in dedicated pull requests, weekly or monthly, with a tool such as Dependabot or Renovate. Run the full test and evaluation suite on those pull requests, since SDK upgrades can change default behavior.

Step 5: Pin the Python version too

Record the Python version in pyproject.toml or a .python-version file, and use the same version in local development, CI and the Docker base image.

Step 6: Watch platform differences

Some packages ship different builds for Linux, macOS and Windows, or for different CPU architectures. Make sure the lock file covers the platforms you deploy to. uv's lock file is cross-platform by default, which removes a common cause of builds that work on one machine only.

Things to watch

  • GPU packages. PyTorch builds differ by CUDA version. Pin the exact variant you need and the index it comes from.
  • Security fixes. Pinning doesn't mean never upgrading. Scan dependencies and apply security updates promptly.
  • Notebooks. Research notebooks often run in different environments. Before code moves to production, run it against the service's locked dependencies.

Add a lock file to one service this week, and switch its Docker build to install from it.

← More in Software