Library / SDK
metaopt/torchopt avatar
metaopt/torchopt

TorchOpt: A Functional Optimizer and Differentiation Toolkit for Bi-Level PyTorch Workloads

TorchOpt is an efficient library for differentiable optimization built upon PyTorch.

637 stars44 forksPythonApache-2.0

At a glance

What is it?
TorchOpt is an Apache-2.0 Python library that turns optimizers into pure functions and adds explicit, implicit and zero-order differentiation to PyTorch. It targets meta-learning and bi-level optimization code where the inner loop itself needs gradients, and it is most defensible when that inner loop is expensive or distributed.
Who is it for?
Adopt TorchOpt when your training loop already looks like a bi-level problem (MAML-style meta-learning, meta-RL, hyperparameter gradients) and you want the optimizer to be a value you can pass into functorch transforms. Do not adopt it as a general replacement for torch.optim if you only need a single-level SGD or Adam loop, because the functional API adds a state-plumbing step with no payoff there.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 8 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

The inner-loop gradient problem TorchOpt was built to solve

Standard PyTorch optimizers mutate parameters in place and keep their state inside the optimizer object. That design works for single-level training and breaks down the moment you need to differentiate through the optimization step itself. Meta-learning, hyperparameter optimization and bi-level problems all require the same thing: compute an inner update, then take a gradient of an outer objective with respect to the inputs of that inner update. With torch.optim this means either hand-rolling the update math or relying on higher, and neither scales cleanly.

TorchOpt's answer is to make the optimizer a pure function over parameters and state. The README frames the library as an efficient library for differentiable optimization built upon PyTorch, and it lists three differentiation modes (explicit, implicit, zero-order) for different situations. The audience is narrow and identifiable: researchers and engineers writing meta-RL, MAML-style meta-learning, or any pipeline where the loss depends on the result of a training step. If your loop is a plain forward-backward-step, this library is solving a problem you do not have.

Functional optimizer state: how the data flow actually works

The README's Adam example shows the mechanism in five lines. You build the optimizer with torchopt.adam(), then call optimizer.init(params) to produce an opt_state. Gradients come from torch.autograd.grad(loss, params), and optimizer.update(grads, opt_state) returns a tuple of updates and a new opt_state. Nothing is mutated. The optimizer is a pair of functions, init and update, and the state travels explicitly.

That is the same shape as Optax in JAX, which the README names directly, and the library offers two API surfaces: an Optax-like functional API and a PyTorch-like API for users who prefer the familiar style. The example is coupled with functorch.make_functional(net), which splits an nn.Module into a function and a parameter container. This is the part that matters for adoption. TorchOpt does not replace functorch; it composes with it, and the README says the design follows the philosophy of functional programming aligned with functorch. If your model is not already expressed in that functional form, you are signing up for a refactor of the model, not just of the optimizer.

Three differentiation modes and what each one costs you

The README lists explicit gradient (EG), implicit gradient (IG) and zero-order differentiation (ZD). The distinction is not cosmetic. Explicit differentiation unrolls the inner optimization and backpropagates through every step, so memory grows with the number of inner iterations. Implicit differentiation, per the README's own framing of the modes, is the alternative for cases where unrolling is too expensive, since it avoids storing the full inner trajectory. Zero-order differentiation estimates gradients without backpropagating through the inner loop at all, which is the escape hatch when the inner objective is not differentiable or the unrolled graph is impractical.

Choosing among them is the main engineering decision in any TorchOpt project, and the README does not make that choice for you. It presents the three modes as coverage for different situations rather than recommending one. Treat that as a signal: the library gives you the primitives, and the memory-versus-accuracy trade-off is yours to measure on your own workload. The tutorials directory is where the worked comparisons live, not the README.

Getting it running: installation and the distributed path

The README points to an Installation section and a PyPI package named torchopt, and the badge in the header states Python 3.8+. The documented entry point is the torchopt namespace, with torchopt.adam() as the concrete constructor shown in the Adam illustration. Beyond that, the README's own organization lists a Changelog and a Citing TorchOpt section rather than a configuration reference, so there are no config keys to enumerate here; the API is the configuration surface.

On performance, the README claims three things: CPU/GPU accelerated differentiable optimizers, an RPC-based distributed training framework, and Fast Tree Operations, described as increasing training efficiency for bi-level problems. The distributed framework is the item to scrutinize before adopting. An RPC-based path changes your deployment topology, not just your import statements, and the README does not spell out the failure modes of that path. If you only need single-process meta-learning, the functional optimizer and the differentiation modes are the parts you will actually use.

Where TorchOpt is the wrong tool

The clearest limitation is scope. TorchOpt is built for differentiable optimization, and the README positions it as an addition to PyTorch rather than a drop-in replacement for torch.optim. If your training is single-level, swapping in torchopt.adam() buys you explicit state threading and a functorch dependency in exchange for nothing. The functional style is a cost, not a feature, in that setting.

A second constraint is the version surface. The most recent release listed in the repository metadata is v0.7.3, tagged 2023-11-10, with v0.7.2 and v0.7.1 before it. The default branch shows a push in 2026, which means development activity on main is not reflected in a tagged release in the supplied material. Anyone pinning to a release should expect the documented API to track the tag they install, and anyone tracking main is accepting unreleased changes. The README does not state a compatibility matrix for PyTorch or functorch versions, so the Python 3.8+ badge is the only version constraint visible here. That is thin for a library whose entire value proposition is composing with functorch internals.

The real alternative, and the actual difference

The honest comparison is Optax in JAX, and the README makes it itself: TorchOpt lets users conduct neural network optimization in PyTorch with a functional style optimizer, similar to Optax in JAX. The difference is not the API shape, which is deliberately close. It is the surrounding ecosystem. Optax sits inside JAX, where functional purity, jit and vmap are the default execution model, so a functional optimizer is the native idiom. TorchOpt brings that idiom into PyTorch, where modules, in-place parameter updates and autograd are the native idiom, and the bridge is functorch. That means TorchOpt carries the cost of both worlds: you write functional code to satisfy the optimizer, and you still depend on PyTorch's eager autograd for the rest.

If your team is already on JAX, Optax is the lower-friction choice and TorchOpt has no argument. TorchOpt's case is specifically for teams committed to PyTorch who need bi-level gradients and do not want to port their models.

Licence and maintenance posture

TorchOpt is Apache-2.0, which permits commercial use and modification and includes an explicit patent grant. That is the permissive end of the spectrum and places no copyleft obligation on your codebase. This is a description of the licence text, not legal advice; if you are redistributing or modifying the library inside a product, have counsel read the NOTICE and attribution requirements rather than relying on a summary.

Maintenance cost is the harder question. The release cadence visible in the metadata shows three tagged releases across 2023 and then a gap, with branch activity continuing afterward. A library that depends on functorch, which is itself a moving part in the PyTorch ecosystem, inherits upstream churn. Budget for the possibility that a PyTorch upgrade forces you to move off a pinned TorchOpt tag before a matching release exists. That risk is manageable if TorchOpt sits behind a thin internal wrapper around init and update, and much less manageable if torchopt calls are scattered through your training code.

Editorial conclusion

Adopt TorchOpt when your training loop already looks like a bi-level problem (MAML-style meta-learning, meta-RL, hyperparameter gradients) and you want the optimizer to be a value you can pass into functorch transforms. Do not adopt it as a general replacement for torch.optim if you only need a single-level SGD or Adam loop, because the functional API adds a state-plumbing step with no payoff there. Before committing, verify three things against your own environment: that your PyTorch and functorch versions satisfy the install constraints in the docs, that the differentiation mode you intend to use (explicit, implicit, or zero-order) matches the memory and compute profile of your inner loop, and whether you need the RPC distributed path, since that pulls in a different set of operational concerns than the single-process optimizer. The repository's most recent tagged release listed is v0.7.3 from November 2023, while the default branch was pushed in 2026, so pin a tag or a commit rather than tracking main if you need reproducibility.

Official sources

  1. License: Apache-2.0
  2. metaopt/torchopt on GitHub
  3. Project website
  4. README
  5. Releases
Community notes

Community notes