Building a Tesseract from a lockfile

View on GitHub

Context

Instead of a flat tesseract_requirements.txt, a Tesseract can install its dependencies from a PEP 751 lockfile (pylock.toml). A lockfile pins every dependency’s exact version, source index, and artifact hashes, so the build installs a fully resolved dependency set and performs no resolution of its own.

Point the build at a lockfile with requirements_file in tesseract_config.yaml:

name: "pylock"
version: "0.1.0"
description: |
  Tesseract whose dependencies are installed from a PEP 751 lockfile
  (build_config.requirements.requirements_file: pylock.toml) instead of a flat
  tesseract_requirements.txt. The committed pylock.toml spans two indexes (PyPI
  for numpy, the PyTorch CPU index for torch) with platform markers.

  See README.md for how to regenerate the lockfile from _pyproject.toml.

build_config:
  requirements:
    provider: uv-pip
    requirements_file: pylock.toml

Any PEP 751 filename is accepted, either pylock.toml or a named variant like pylock.prod.toml. The format is inferred from the name.

If you already have a pyproject.toml (or a uv.lock), export a lockfile with uv export:

$ uv export --format pylock.toml -o pylock.toml

Example Tesseract

The example computes a sum with torch and passes it through numpy, so both packages from the committed lockfile must be installed and importable for apply to succeed:

# Copyright 2025 Pasteur Labs. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0

from pydantic import BaseModel

#
# Schemas
#


class InputSchema(BaseModel):
    a: float
    b: float


class OutputSchema(BaseModel):
    # Sum computed with torch and passed through numpy, so both packages from the
    # committed pylock.toml must be installed and importable for apply to succeed.
    result: float


#
# Required endpoints
#


def apply(inputs: InputSchema) -> OutputSchema:
    import numpy as np
    import torch

    total = torch.tensor(inputs.a) + torch.tensor(inputs.b)
    return OutputSchema(result=float(np.asarray(total).item()))

Then build and run as usual:

$ tesseract build examples/pylock
$ tesseract run pylock apply '{"inputs": {"a": 2.0, "b": 3.0}}'
{"result":5.0}

The Tesseract runtime is installed on top

Warning

The build installs the lockfile first, then installs the Tesseract runtime and its dependencies into the same environment. If a runtime dependency requires a version outside the range your lockfile pins, that package is adjusted to satisfy the runtime, so a handful of packages in the final image may differ from the lockfile. Everything else is installed exactly as pinned. Keep this in mind if you rely on the image matching the lockfile byte-for-byte.

Private and multi-index lockfiles

A lockfile records each package’s index location and hashes, but never credentials. To install from an authenticated index (a private PyPI, an Azure Artifacts feed, etc.), declare the host under build_config.host_credentials and supply the token at build time with tesseract build --secret.