# gpytorch: the version number is written by the build and grepped back out by setup.py

> A Gaussian process library for PyTorch that replaces the Cholesky solve with matrix-vector products and a LinearOperator interface, shipped with three install paths, six declared dependencies against three documented ones, and a version string generated at build time.

**cornellius-gp/gpytorch** — A highly efficient implementation of Gaussian Processes in PyTorch

- Repository: https://github.com/cornellius-gp/gpytorch
- Stars: 3,923 · Forks: 607
- Language: Python
- License: MIT
- Published: 2026-09-23 · Updated: 2026-09-23 · Language: en
- Canonical page: https://hysenlabs.com/projects/cornellius-gp-gpytorch

## The requirements list names three dependencies, setup.py declares six

The README states three requirements: Python >= 3.10, PyTorch >= 2.4.1 and NumPy >= 2.0. The packaging script declares six, and the three it adds are the interesting ones:

```python
install_requires = [
    "torch>=2.4.1",
    "numpy>=2.0",
    "mpmath>=0.19,<=1.3",  # avoid incompatibiltiy with torch+sympy with mpmath 1.4
    "scikit-learn",
    "scipy>=1.6.0",
    "linear_operator>=0.6.1",
]
```

mpmath carries the only upper bound in the list, and the comment beside it gives the reason: mpmath 1.4 conflicts with torch plus sympy. scikit-learn is the one dependency with no bound at all, so a fresh install can pair the library with whatever version the resolver turns up. linear_operator is a separate project from the same organisation, the interface the README credits with reducing a new scalable method to a single matrix multiplication, and the Requirements section never mentions it. Anyone reading only that section learns nothing about the operator layer the rest of the README is built on.

## The unstable install moves linear_operator before gpytorch

Two upgrade lines sit under the heading for the latest unstable version, and they install two different projects in a fixed order. The first upgrades linear_operator from its git repository, the second upgrades gpytorch from its own:

```bash
pip install --upgrade git+https://github.com/cornellius-gp/linear_operator.git
pip install --upgrade git+https://github.com/cornellius-gp/gpytorch.git
```

That order follows the dependency direction, since gpytorch declares linear_operator>=0.6.1, so the operator library is the one that has to move first when both are pulled from source. The README never says so, and it never says what to do afterwards either. No command anywhere in the documentation returns an environment to the released versions once those two lines have run, and the released channel is a different install line rather than a downgrade instruction. The section below it is a third path and the only one that installs extras: a contributor clones the repository and runs an editable install naming six of them, with a comment marking keops and pyro as optional. Three install routes in one file, and only the middle one is labelled unstable.

## The version string is generated into the package and grepped back out

The version number does not live in a file anybody edits. pyproject.toml turns on setuptools_scm with a local version scheme of node-and-date and a write_to path of ./gpytorch/version.py, so a build writes the version into a module inside the package directory. setup.py then opens that module, matches one line with a regular expression looking for an assignment of __version__ to a quoted string, and passes the captured group to setup() as the version argument.

Two things follow. The version a wheel carries is decided by git state at build time rather than by a constant, which is what the node-and-date scheme is for, appending local information instead of a clean number. And the extraction is a regex over a single line: find_version wraps the read in a try block that catches every exception and returns None, so a checkout where the generated file is missing, or where the line has been reformatted, produces a build with no version rather than a loud failure. A pip user never sees this, because the version comes from the tag instead.

## setup.py exits before setup() on anything older than Python 3.10

The interpreter check lives at module level, above the call to setup(). It compares sys.version_info against a required major of 3 and a required minor of 10, and on failure formats a message naming your own version and the requirement, then calls sys.exit with that string as the error text. Because the check runs while the module is being imported, an older interpreter never reaches the packaging call at all, which also means a harmless invocation such as asking the script for help fails on 3.9 before any argument is parsed.

The message is the friendly half of this. The placement is the strict half. The same floor is stated in the README as Python >= 3.10, so the documentation and the script agree with each other, and the script is the one that cannot be argued with. A project that hard fails this early is telling you something about which interpreter versions it intends to support, and 3.10 is the oldest one it will start talking to.

## The example folders skip a number where GPLVM sits

The examples directory is the closest thing the repository has to a map of its coverage, and it is numbered from 00 to 08: basic usage, exact GPs, scalable exact GPs, multitask exact GPs, variational and approximate GPs, deep Gaussian processes, PyTorch NN integration for DKL, Pyro integration, advanced usage. One folder breaks the sequence. 045_GPLVM sits between 03 and 04 rather than after 08, and it is the only entry carrying a three character numeric prefix, so anything that sorts or globs those directories will file it in the wrong place. A single script, LBFGS.py, also sits at the top of examples/ instead of inside a numbered folder, beside README.rst and index.rst.

The README's own pointer to all of this is a link to the hosted documentation, so the directory listing is the inventory a reader actually gets. The techniques it advertises by name, SKI and KISS-GP, stochastic Lanczos expansions, LOVE, SKIP, stochastic variational inference and deep kernel learning, have no folders named after them, and the one folder that is out of order is the least obvious one to find.

## black runs at 120 columns and three linters have their own config

The style tooling is configured in the repository rather than described in it. pyproject.toml sets black to a line length of 120 and marks gpytorch as the first party package for usort, so formatting runs through black while import order is sorted by a different tool. Three more configuration files sit at the top level for tools the README never mentions: a pre-commit configuration, a pylintrc and a pyre configuration, the last being a type checker. setup.cfg is there as well, alongside a .gitignore, a .readthedocs.yml for the documentation build and a .github/ directory.

None of this appears in the build or contributing sections, and the Contributing section is a single link to CONTRIBUTING.md. So the practical way to learn what a commit has to satisfy is to read those four files, or to make a commit and read what the hooks say about it. The 120 column setting is the one detail that shows up in the diff of any file you touch, since it is enforced on the code rather than described anywhere a reader is pointed at.

## The newest tag is a maintenance release and the branch moved on in February

The tag line and the default branch are seven months apart. v1.15 shipped on 2026-01-14, v1.15.1 on 2026-01-16, and v1.15.2 on 2026-02-28 under a title that calls it a maintenance release. The last push to main was 2026-10-02, so the version pip installs has not moved since February while the branch took commits for the rest of the year. The setup.py classifier still reads Development Status :: 5 - Production/Stable.

The README's answer to that gap is the unstable section, the git install, which is the honest route to the current state of the code and also the route with no documented way back. Two further signals sit in the same file. The license is MIT, and the acknowledgements name the Bill and Melinda Gates Foundation, the National Science Foundation, SAP, the Simons Foundation and the Gatsby Charitable Trust as funders, next to a hand written list of five maintainers with their university and company affiliations and seventeen other contributors named by hand.

## Conclusion

Choose between the two channels deliberately. pip hands you v1.15.2 from 2026-02-28 with a version file generated at build time, the git install gives you a moving target with no documented way back, and the project's own note calls the Arch package experimental. Before either, read install_requires in setup.py rather than the Requirements list, because linear_operator, scipy, scikit-learn and mpmath are declared there and nowhere else, and check the Python 3.10 floor against your environment, since the packaging script exits before it does anything else. For a map of what the library covers, the numbered directories under examples/ are the only inventory, and 045_GPLVM is filed out of order.

## FAQ

### How do I install gpytorch?

With pip or conda: pip install gpytorch, or conda install gpytorch -c gpytorch. The README lists Python >= 3.10, PyTorch >= 2.4.1 and NumPy >= 2.0 as requirements. A contributor clones the repository and runs pip install -e .[dev,docs,examples,keops,pyro,test], where keops and pyro are optional. There is also an experimental AUR package installed with yay -S python-gpytorch.

### What dependencies does gpytorch pull in beyond PyTorch and NumPy?

setup.py declares six in install_requires: torch>=2.4.1, numpy>=2.0, mpmath>=0.19,<=1.3, scikit-learn, scipy>=1.6.0 and linear_operator>=0.6.1. The README's requirements list names only the first two, and the comment beside the mpmath bound says it avoids an incompatibility with torch plus sympy at mpmath 1.4.

### Where does the gpytorch version number come from?

From the build. pyproject.toml enables setuptools_scm with a node-and-date local version scheme and writes the result to ./gpytorch/version.py, and setup.py reads that file with a regular expression and hands the captured string to setup() as the version. If the file is missing, find_version catches the exception and returns None.

### Does the gpytorch README explain what a Gaussian process is?

No. It starts from the assumption that you know, and spends its space on the difference from other GP libraries: inference by numerical linear algebra such as preconditioned conjugate gradients rather than a Cholesky solve, a matrix-vector product interface in place of explicit kernel matrices, and named implementations of SKI and KISS-GP, stochastic Lanczos expansions, LOVE, SKIP, stochastic variational inference and deep kernel learning. Model construction is left to the hosted documentation.

### What is 045_GPLVM and where does it sit in the gpytorch examples?

It is one of the numbered example directories, and it is the one filed out of sequence: it sits between 03_Multitask_Exact_GPs and 04_Variational_and_Approximate_GPs instead of after 08_Advanced_Usage. The README does not describe the directory, and the only inventory of examples is the directory listing itself, since the README links to the hosted documentation instead.

## Sources

- [cornellius-gp/gpytorch on GitHub](https://github.com/cornellius-gp/gpytorch)
- [Issues](https://github.com/cornellius-gp/gpytorch/issues)
- [License: MIT](https://github.com/cornellius-gp/gpytorch/blob/main/LICENSE)
- [README](https://github.com/cornellius-gp/gpytorch/blob/main/README.md)
- [Releases](https://github.com/cornellius-gp/gpytorch/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/cornellius-gp-gpytorch
