# Informers runs transformer models inside a Ruby process

> Informers is a Ruby gem from ankane that wraps transformers.js so embedding and reranking models run without leaving the application process. The gem covers a curated list of ONNX models, and its release history stops in 2020 even though the code was pushed to in 2026.

**ankane/informers** — Fast transformer inference for Ruby

- Repository: https://github.com/ankane/informers
- Stars: 615 · Forks: 17
- Language: Ruby
- License: Apache-2.0
- Published: 2026-10-22 · Updated: 2026-10-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/ankane-informers

## A gem that keeps the model inside the Ruby process

Informers is described as fast transformer inference for Ruby, and it is built on transformers.js. That single design choice defines its appeal and its ceiling. There is no Python service to deploy, no HTTP client with retries and timeouts to write, and no model server to keep warm. A Rails controller can load a pipeline and ask for embeddings directly. The consequence is that model inference runs inside the same process that serves requests, so a slow embedding call is a slow web request, and memory for the model comes out of the same pool as the rest of your app. For a background job or a data pipeline that is an easy trade. For a request path under load it is a decision, not a free win. The gem also declares a scope boundary. The documentation points readers who need non-ONNX models to a separate project, Transformers.rb. So Informers is not a general model runner. It is a specific path: JavaScript transformer models executed from Ruby, limited to models that have an ONNX form.

## One pipeline factory covers two task types

The public surface is a factory method called Informers.pipeline that takes a task name and a model identifier. Two task types are documented. Embedding is the first, and the model list covers a specific set of sentence embedding checkpoints including sentence-transformers/all-MiniLM-L6-v2, all-mpnet-base-v2, paraphrase-MiniLM-L6-v2, mixedbread-ai/mxbai-embed-large-v1, Supabase/gte-small, intfloat/e5-base-v2, nomic-ai/nomic-embed-text-v1, BAAI/bge-base-en-v1.5, jinaai/jina-embeddings-v2-base-en and Snowflake/snowflake-arctic-embed-m-v1.5. Reranking is the second, with mixedbread-ai/mxbai-rerank-base-v1, jinaai/jina-reranker-v1-turbo-en, BAAI/bge-reranker-base and Xenova/ms-marco-MiniLM-L-6-v2. A pipeline object is then called with input text and returns the task-appropriate output. Because the list is fixed and documented rather than pulled from a registry at runtime, the surface area you can rely on is knowable in advance. That is unusual for this kind of library and it cuts both ways: you can read the list and know what works, but a model that is missing from it is not merely undocumented, it is unsupported.

## The Gemfile line is the whole install

Installation is one line in the application Gemfile. There is no native build step, no model download step and no configuration file to write.

```ruby
gem "informers"
```

From there a first call is short enough to paste into a console. This is the embedding example the README gives, using the small all-MiniLM-L6-v2 model.

```ruby
sentences = ["This is an example sentence", "Each sentence is converted"]
model = Informers.pipeline("embedding", "sentence-transformers/all-MiniLM-L6-v2")
embeddings = model.(sentences)
```

The first call constructs the pipeline, which is where the model weights are fetched and prepared, and the second call returns one embedding per input sentence. Expect the first call in a process to be much slower than later ones. After that, a reranker works the same way, taking a query and a list of documents.

```ruby
query = "How many people live in London?"
docs = ["Around 9 Million people live in London", "London is known for its financial district"]
model = Informers.pipeline("reranking", "mixedbread-ai/mxbai-rerank-base-v1")
result = model.(query, docs)
```

The repository layout is correspondingly small: lib/, test/, a Rakefile, a Gemfile, an informers.gemspec and a CHANGELOG.md, with build automation in .github. A normal Ruby gem with a Ruby problem to solve.

## Prefix strings and pooling flags are where the models differ

The embedding examples differ in small ways that matter, and the differences reflect how each checkpoint was trained. Some models expect a prefix on the query but not on the documents. The e5 example uses a doc_prefix of "passage: " and a query_prefix of "query: ", while the nomic example uses "search_document: " and "search_query: ". The mixedbread and BGE examples add a single instruction prefix of "Represent this sentence for searching relevant passages: " to the query only. Skip the prefix and the retrieval quality degrades, and nothing in the gem will warn you, because the model has no way to know what it was handed. The same applies to keyword arguments. The paraphrase example passes normalize: false, the jina embeddings example points at a separate model file with model_file_name: "../model", and the Snowflake example sets model_output: "sentence_embedding" with pooling: "none". These are per model knobs exposed through the call, and the README is the only guide to them.

## Scoring by hand when you only have embeddings

For the multi-qa MiniLM model the documented example does not rely on a similarity helper. It computes the score in plain Ruby, which tells you something about how little the gem abstracts. The query and the documents are embedded separately and then paired with a dot product, sorted by descending score.

```ruby
query = "How many people live in London?"
docs = ["Around 9 Million people live in London", "London is known for its financial district"]
model = Informers.pipeline("embedding", "sentence-transformers/multi-qa-MiniLM-L6-cos-v1")
query_embedding = model.(query)
doc_embeddings = model.(docs)
scores = doc_embeddings.map { |e| e.zip(query_embedding).sum { |d, q| d * q } }
doc_score_pairs = docs.zip(scores).sort_by { |d, s| -s }
```

The zip and sum pattern is a straightforward dot product, and the sort_by with a negated score puts the best match first. The visible consequence is that there is no built in cosine similarity or top k retrieval, even for a model named for cosine distance. You get vectors and you do the ranking. That is a defensible design for a thin gem, and it also means each application ends up with its own slightly different retrieval code. Anyone expecting a vector store or a similarity function will not find one here.

## The version story is the main risk

The maintenance picture is mixed and worth stating precisely. The repository is not archived and the last push was on 2026-06-29, so the code has been touched within the last few months and the project is not dead. However, the only recorded release is v0.1.0, tagged on 2020-10-02, and the release history in the project listing has not grown since. The repository also carries a CHANGELOG.md, which is where a maintainer would record what changed. The practical consequence is that when you install the gem from a package index, the version you receive may not correspond to the code on the default branch. There is no homepage and no separate documentation site, so the README on the default branch is the reference for the current state of the code, not necessarily the state of the published gem. Teams that pin versions and audit their dependency chain should check the gemspec and the CHANGELOG before assuming the published artifact matches the repository. The licence is Apache-2.0, which is permissive and requires notice retention.

## When a Python service is the better fit

The alternative approach worth comparing is Transformers.rb, the sibling project the project points to for non-ONNX models. The difference is not taste, it is model coverage. Informers goes through transformers.js, so it runs JavaScript transformer builds, which means the model list is bounded by what has been converted to ONNX. Transformers.rb exists for the cases where the checkpoint you need has no ONNX form. If your requirement is a named model that appears in the Informers list, the in-process Ruby path is the shorter one and avoids a network hop. If your requirement is any other checkpoint, the choice is between a second runtime and a separate inference service. A further alternative is running a Python inference server behind an HTTP interface and calling it from Ruby with a plain HTTP client. That costs you an extra deployment and a latency budget, but it keeps model memory and CPU out of the web process and lets the model scale independently, and it opens the door to any model the Python ecosystem can load rather than the ONNX subset.

## Conclusion

Informers fits Ruby applications that need semantic search or document reranking without standing up a separate inference service, and it suits teams comfortable with the curated model list rather than an open registry. It does not fit projects that need models outside the listed embedding and reranking set, and it does not fit teams that want a maintained gem release trail, since the only tagged release is v0.1.0 from 2020-10-02 even though the last push was on 2026-06-29. Before adopting it, confirm the specific model you need appears in the model list, read the gemspec dependencies for the transformers.js version it pins, and decide whether running the model in the web process is acceptable for your deployment.

## FAQ

### How do I install Informers for Ruby?

Add gem "informers" to your application Gemfile and bundle install. There is no native build or configuration step described in the documentation.

### Which models can Informers run?

The documented list covers embedding models such as sentence-transformers/all-MiniLM-L6-v2, intfloat/e5-base-v2 and BAAI/bge-base-en-v1.5, plus reranking models such as mixedbread-ai/mxbai-rerank-base-v1 and BAAI/bge-reranker-base. For non-ONNX models the README points to Transformers.rb.

### Does Informers have a similarity search or vector store built in?

No. The documented example computes similarity in application Ruby, zipping a document embedding with a query embedding and summing the products to get a dot product, then sorting by descending score.

### Why do some Informers embedding examples add a prefix string?

Each checkpoint expects specific prefixes, such as "query: " and "passage: " for intfloat/e5-base-v2 or "search_query: " and "search_document: " for nomic-ai/nomic-embed-text-v1. The prefix depends on how the model was trained, and the README shows a different prefix set per model.

### What licence is Informers released under?

The project is distributed under the Apache-2.0 licence, with the licence text stored in LICENSE.txt at the top of the repository.

## Sources

- [ankane/informers on GitHub](https://github.com/ankane/informers)
- [Issues](https://github.com/ankane/informers/issues)
- [License: Apache-2.0](https://github.com/ankane/informers/blob/master/LICENSE)
- [README](https://github.com/ankane/informers/blob/master/README.md)
- [Releases](https://github.com/ankane/informers/releases)

---

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