Open-source project
ankane/torch.rb avatar
ankane/torch.rb

torch.rb: the PyTorch API in Ruby, with the LibTorch build attached

Deep learning for Ruby, powered by LibTorch

842 stars38 forksRubyNOASSERTION

At a glance

What is it?
Torch.rb is a Ruby deep learning library powered by LibTorch, the C++ distribution of PyTorch, and it follows the PyTorch API closely enough that a tutorial can be ported line by line, with three Ruby-flavoured changes to the naming. The judgement is that the binding quality is the achievement, and that the price is a native build you have to point at a LibTorch directory yourself.
Who is it for?
torch.rb fits a Ruby team that needs tensors, autograd and neural network modules without leaving the language, especially one that already has a PyTorch model to port, since the API follows PyTorch so closely that a tutorial converts directly.
Can I use it commercially?
Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
Is it still maintained?
Yes. The repository last received commits 10 days ago.
What is it written in?
Mainly Ruby, according to GitHub's language statistics.

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

Editorial analysis

A Ruby binding to LibTorch, not a reimplementation

Torch.rb is deep learning for Ruby, powered by LibTorch, the C++ distribution that carries PyTorch's operators, autograd engine and optimiser implementations. That distinction decides what the project can and cannot do, because there is no Ruby reimplementation of the tensor library hiding underneath. Tensors, gradients and layers are the real PyTorch machinery called from Ruby. The API follows the PyTorch API, and the README says you can follow PyTorch tutorials and convert the code to Ruby in many cases, with an invitation to open an issue when you run into problems. Around the core sits a family of related projects by the same author, TorchVision for computer vision, TorchText for text and natural language work, TorchAudio, TorchCodec for audio and video encoding, TorchRec for recommendation systems, TorchData for data loading, Transformers for transformer models and Safetensors for storing tensors. If your problem has an upstream PyTorch implementation, the Ruby path is a porting question rather than a research question.

Three Ruby conventions on top of the PyTorch surface

The deviations from PyTorch are listed in the README and they are all naming, which is exactly what you want from a port that should feel native. Methods that perform in-place modifications end with an exclamation mark instead of an underscore, so add! rather than add_. Methods that return booleans use a question mark instead of the is_ prefix, so tensor? rather than is_tensor. And Numo is used instead of NumPy, so the array conversion is x.numo rather than x.numpy(). Those three changes are the entire delta, and they are enough that the code stops feeling like a translation. The one thing that does not survive the port unchanged is the tensor-to-array bridge, since Ruby's Numo library replaces NumPy, and a model trained in Python and consumed in Ruby has to be handled carefully, which the README covers separately when it talks about saving and loading.

Installing means getting LibTorch right first

The install order matters, because the gem is a native extension and it needs the C++ library on disk before it compiles. The first step is to download LibTorch from the official PyTorch download page. For Mac arm64 the README gives the archive and the two commands that fetch and unpack it:

sh
curl -L https://download.pytorch.org/libtorch/cpu/libtorch-macos-arm64-2.14.1.zip > libtorch.zip
unzip -q libtorch.zip

For Linux x86-64 the instruction is to use the build that matches your CUDA version, and for other platforms to build LibTorch from source. Then the bundler has to be told where that directory is, which is a single configuration command:

sh
bundle config set build.torch-rb --with-torch-dir=/path/to/libtorch

And the application needs the gem itself, added to the Gemfile as a line:

ruby
gem "torch-rb"

The README warns that the compilation can take 5 to 10 minutes, and that Windows is not currently supported, which is the single most important practical fact for anyone planning to use this.

Tensors, their four properties and the in-place style

The API tour in the README starts where most people start, with a tensor built from a Ruby array, and then with the shape. Creation goes through functions such as Torch.rand and Torch.zeros, and each tensor carries four properties. The dtype is one of :uint8, :int8, :int16, :int32, :int64, :float32, :float64 or :bool. The layout is :strided for dense or :sparse. The device is the compute device, CPU or GPU. And requires_grad decides whether gradients are recorded. All four can be set at creation time, so Torch.rand accepts a dtype, a layout, a device and requires_grad. Arithmetic follows the same shape as Python, with the result printed in the familiar tensor notation, and the in-place variants use the exclamation mark convention, so x.add!(5) mutates the tensor. There is also an out: option for writing the result into a tensor you allocate yourself, which is what you want when the allocation cost matters.

Autograd, modules and the manual training loop

Autograd works as it does in PyTorch. You create a tensor with requires_grad set to true, run operations on it, call backward, and read the gradients, and a Torch.no_grad block suspends the tracking so that inference does not build a history. Networks are classes that inherit from Torch::NN::Module, with the layers assigned in the constructor and the computation written in a forward method, and the README's network is a small convolutional stack built from Torch::NN::Conv2d, Torch::NN::Linear and the functional helpers for relu and max_pool2d. Training follows the familiar sequence. Call the network, compare the output with a target using a criterion such as MSELoss, call backward, then step an optimiser, with Torch::Optim::SGD taking the parameters and a learning rate. The README also shows the update written out by hand over net.parameters, which is a useful thing to read once, because it makes clear that the optimiser is a thin layer over the gradient buffers rather than a separate system.

Saving a model and reading one back

Models are saved as a state dictionary, with Torch.save taking net.state_dict and a path, and loading is the mirror image, with net.load_state_dict taking the loaded object and net.eval switching the module to evaluation mode. The cross language case is the interesting one. When you save a model in Python in order to load it in Ruby, the README says you must convert the parameters to tensors, and it gives the reason: outstanding bugs in LibTorch. The conversion is a dictionary comprehension that unwraps any nn.Parameter into its data tensor before saving. That is a small detail, and it is the kind of detail that costs an afternoon if nobody wrote it down, which is why the README does. The runnable programs that ship with the project cover image classification with MNIST, collaborative filtering with MovieLens, and generative adversarial networks, and there is a Japanese version of the MNIST program linked as well.

Repository layout, licence and the state of the work

The tree tells you how the binding is put together. There is an ext directory for the native extension, lib for the Ruby layer, codegen for the parts that are generated rather than written by hand, test for the suite, a directory of runnable programs, tutorials for the guides, a Rakefile, a Gemfile and the torch-rb.gemspec, plus a CHANGELOG.md. The tutorials named in the README are Deep Learning with Torch.rb, A 60 Minute Blitz as the suggested starting point, then transfer learning, sequence models and word embeddings. The licence is recorded in the repository metadata as a custom one that GitHub cannot classify, with the text in LICENSE.txt, so that file is the one to read before you ship it. The project publishes no GitHub releases, the last push was on 2026-10-17, and the repository is not archived, so the work is still landing on the master branch with a build workflow badge showing the continuous integration status.

Editorial conclusion

torch.rb fits a Ruby team that needs tensors, autograd and neural network modules without leaving the language, especially one that already has a PyTorch model to port, since the API follows PyTorch so closely that a tutorial converts directly. It is the wrong choice if you need GPU support out of the box on a machine without a matching LibTorch build, and it is a poor fit for a team that will not maintain a native extension, because the gem compiles against LibTorch and takes minutes to build. Before you adopt it, download the LibTorch build that matches your platform and CUDA version, point the bundler at it with the build.torch-rb configuration, and confirm that a model saved from Python loads correctly after the parameter conversion the README describes.

Frequently asked questions

How does the Torch.rb API differ from the PyTorch API?

Three naming changes. Methods that modify a tensor in place end with an exclamation mark instead of an underscore, so add! rather than add_. Methods that return booleans use a question mark instead of the is_ prefix, so tensor? rather than is_tensor. And Numo is used in place of NumPy, so the array conversion is x.numo rather than x.numpy().

How do I install torch-rb on macOS or Linux?

Download LibTorch first, the macOS arm64 archive is fetched with curl and unpacked with unzip, Linux x86-64 needs the build matching your CUDA version, and other platforms need LibTorch built from source. Then point the bundler at it with bundle config set build.torch-rb --with-torch-dir=/path/to/libtorch and add gem "torch-rb" to the Gemfile. Compiling the extension takes 5 to 10 minutes, and Windows is not currently supported.

Can I load a model saved from PyTorch in Python with torch.rb?

Yes, with one adjustment. The README says that when saving a model in Python in order to load it in Ruby you must convert the parameters to tensors, because of outstanding bugs in LibTorch, and then load it with net.load_state_dict(Torch.load("net.pth")) and call net.eval.

Official sources

  1. ankane/torch.rb on GitHub
  2. Issues
  3. README
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/ankane-torch-rb.svg)](https://hysenlabs.com/projects/ankane-torch-rb)

Was this useful?