MemoFSMemoFS
Adapters

Transformers.js Adapter

Local Hugging Face Transformers.js ONNX embedding adapter for 100% offline semantic recall in MemoFS.

The @memofs/adapter-transformers adapter runs vector embeddings 100% locally and offline in-process using ONNX runtime and Hugging Face's Transformers.js (@huggingface/transformers).

It requires no API keys, no external services, and zero network traffic after the initial model weights are downloaded and cached in a shared user-level cache ($XDG_CACHE_HOME/memofs/models, or ~/.cache/memofs/models) — one download per machine, shared across projects and runtimes.

Subpath Exports

Export PathTarget EnvironmentDescription
@memofs/adapter-transformersNode.js (>= 22)Root entry. Exposes TransformersEmbedder, createTransformersEmbedder, resolveModelCacheDir, error classes, and pipeline types.
@memofs/adapter-transformers/testingTest runnersExposes createFakePipeline and createFakePipelineFactory for deterministic testing without loading ONNX weights.

Installation

npm install @memofs/adapter-transformers

Requires Node.js >= 22 when running under the Node.js runtime.

Usage

Instantiate the local embedder with createTransformersEmbedder():

import { createNodeMemoFs } from "@memofs/core/node-fs";
import { createTransformersEmbedder } from "@memofs/adapter-transformers";

const memo = createNodeMemoFs({
  rootDir: ".",
  embedder: createTransformersEmbedder({
    model: "Xenova/bge-small-en-v1.5", // 384 dimensions
    device: "cpu",
    dtype: "q8",
  }),
});
import { MemoFS } from "@memofs/core";
import { createNodeFsMemoryStore } from "@memofs/core/node-fs";
import { createTransformersEmbedder } from "@memofs/adapter-transformers";

const memo = new MemoFS({
  store: createNodeFsMemoryStore({ rootDir: "." }),
  projectId: "offline-app",
  mode: "local",
  embedder: createTransformersEmbedder({
    model: "Xenova/bge-small-en-v1.5",
    device: "cpu",
    dtype: "q8",
  }),
});

Lazy Loading & Eager Prewarming

To ensure fast CLI and server startup, @memofs/adapter-transformers defers loading the heavy ONNX WebAssembly binary and model weights until the first embedTexts() call.

If your application requires deterministic latency on the first search request, you can explicitly prewarm the model pipeline at startup:

const embedder = createTransformersEmbedder({
  model: "Xenova/bge-small-en-v1.5",
});

// Eagerly compile the ONNX pipeline and load weights into memory
await embedder.prewarm();

Model Cache

Downloaded weights live in one shared, user-level directory resolved by the exported resolveModelCacheDir():

  • $XDG_CACHE_HOME/memofs/models when XDG_CACHE_HOME is set to a non-empty value
  • ~/.cache/memofs/models otherwise

MemoFS runs from several working directories over the lifetime of a machine (memofs init from a project root, an MCP server launched by an IDE, test runners), and Transformers.js's default cache is relative to the process working directory — without an explicit shared path, each directory would re-download the same weights. The shared cache means the model that memofs init predownloads is the exact one an MCP server finds on connect. Pass an explicit cacheDir to createTransformersEmbedder() to override the location.

Configuration API (TransformersEmbedderOptions)

The createTransformersEmbedder(options) factory accepts TransformersEmbedderOptions:

OptionTypeDefaultDescription
modelstring"Xenova/bge-small-en-v1.5"Hugging Face model repository identifier. Generates 384-dimensional vectors.
cacheDirstringresolveModelCacheDir()Directory used to cache downloaded ONNX weights. Defaults to a shared user-level cache so weights download once per machine.
device"cpu" | "gpu" | "wasm""cpu"Hardware backend target for the ONNX execution engine.
dtype"fp32" | "fp16" | "q8" | "int8""q8"Tensor precision format for model weights. "q8" (quantized) is ~4x smaller to download and faster on CPU with negligible retrieval-quality loss; "fp32" is the most conservative choice.
batchSizenumber32Maximum number of text chunks processed in a single pipeline pass.
retriesnumber2Maximum retry attempts when the initial model download/load fails with a transient network error. Set to 0 to disable.
onProgressTransformersProgressCallbackCallback invoked during model download with { status, file, progress }. Use it to show a one-time "warming up" notice.
pipelineFactoryFeatureExtractionPipelineFactoryCustom pipeline factory function (primarily used in testing).

Error Classes

All errors inherit from TransformersEmbedderError:

class TransformersEmbedderError extends Error {
  readonly cause?: unknown;
}
Error ClassCause
TransformersValidationErrorThrown when an input text string exceeds MAX_TEXT_LENGTH = 8192 characters or input structure is malformed.
TransformersInferenceErrorThrown when the ONNX runtime fails during forward inference or returns an unexpected tensor shape.

Unit Testing with Fake Pipeline

Use the @memofs/adapter-transformers/testing subpath to test embeddings logic without downloading or running ONNX models:

import { describe, it, expect } from "vitest";
import { TransformersEmbedder } from "@memofs/adapter-transformers";
import { createFakePipelineFactory } from "@memofs/adapter-transformers/testing";

describe("Local transformer pipeline", () => {
  it("generates deterministic embeddings with fake pipeline", async () => {
    const pipelineFactory = createFakePipelineFactory({
      dimensions: 384,
      deterministic: true,
    });

    const embedder = new TransformersEmbedder({
      pipelineFactory,
    });

    const result = await embedder.embedText("Refactor database pooling");
    expect(result.dimensions).toBe(384);
    expect(result.embedding).toHaveLength(384);
  });
});

See Also

On this page