Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

 loom-py

import loom

model = loom.Model.from_pretrained("loom-ai-org/lfm2-350m-monolithic-loom")
print(model.generate("The capital of France is", max_new_tokens=14))
# ':\nA) Paris\nB) Lyon\nC) Marseille\nD'

Text in, text out

generate tokenizes with the vocabulary the GGUF embeds, runs the driver, and detokenizes what comes back. The same steps are available separately when you want them:

model.tokenize("The capital of France is")   # [1, 1098, 5706, 803, 4481, 856]
model.detokenize([1, 1098, 5706])            # '<|startoftext|>The capital'
model.tokenizer                               # <loom.Tokenizer 'gpt2' size=64400>

The four vocabulary families a loom GGUF can carry — byte-level BPE, SentencePiece, WordPiece and byte-level — are dispatched on the file's own tokenizer.ggml.model, so this is one call whichever one a model uses.

For a speech model there is nothing to encode; detokenizing the driver's output is the other half of the same thing:

transcript = model.detokenize(model.infer(waveform=audio, audio_samples=len(audio)))

A TTS model has no generate, and that is a real limitation rather than a missing feature. Matcha, VITS, Kokoro and StyleTTS2 consume phoneme ids that a phonemiser produces outside the engine, so their GGUFs embed no vocabulary at all — model.tokenizer is None for them and they take ids directly:

audio = model.infer(tokens=[16, 40, 22, 30, 12, 3], n_steps=4, seed=1234)

Choosing a device

A wheel built with a GPU backend uses it by default; one built without has only a CPU to find, so nothing changes.

model = loom.Model.from_file("qwen3.gguf")                  # decide for me (or $LOOM_DEVICE)
model = loom.Model.from_file("qwen3.gguf", device="cpu")    # pin it
model = loom.Model.from_file("qwen3.gguf", device="gpu")    # demand one; raises if there is none
model.device, model.device_description   # ('Vulkan0', 'AMD Radeon Vega 3 Graphics (RADV RAVEN2)')

"gpu" raises rather than falling back, because a caller who spelled it out is asking a question about the machine and a silent CPU run is how a large slowdown goes unnoticed. "auto" — the default — is the one that falls back.

The base wheel is CPU-only, and an accelerator is a separate install rather than a different wheel:

pip install "loom-py-rt[vulkan]"

That adds one small package holding one libggml-vulkan.so, which this package finds at import; device="auto" then uses it and nothing about the base wheel changes. The reason it works this way — rather than a full wheel per accelerator, which is the more familiar shape — is that a Vulkan backend is 46.5 MB and CUDA is larger, so the per-accelerator matrix does not fit PyPI's 100 MB per-file ceiling. See packaging/README.md.

loom.devices()   # [{'name': 'Vulkan0', 'description': 'AMD Radeon Vega 3 Graphics (RADV RAVEN2)', ...}]

Worth calling after installing one, because a backend whose driver is too old — or which finds no supported device — loads without error and registers nothing, and the only other symptom is a model running at CPU speed. Note that with this build every backend is loaded at run time, the CPU included, so an empty device list means no backend library was found at all rather than no accelerator.

Which ops fall back to the CPU, and why some always will, is documented in loom.cpp's own build notes.

Why there is so little API

A loom GGUF carries its own graph topologies and its own driver script alongside its weights, so this package contains no per-architecture code at all. Loading a model registers whatever topologies the file declares and attaches a KV cache to the ones that say they need it; running one calls the driver the file shipped with. A model this library has never heard of works the day loom-exporter can produce it.

That is also why infer takes **kwargs: its arguments are the driver's arguments, and which ones a model takes is a property of the model. model.driver_source prints the Lua that will run, whose header comment documents its inputs — that is the authority.

model = loom.Model.from_file("granite_speech_mil.gguf")
model.architecture          # 'granite-speech'
model.topologies            # ['encoder', 'embed', 'decoder', 'lm_head']
model.hparam("samples_per_chunk")   # 192000
print(model.driver_source)  # what infer() will run, and what it accepts

Supported models

Seventeen, published at huggingface.co/loom-ai-org and loadable by id with from_pretrained (needs the [hub] extra). This package has no per-architecture code, so the list is a property of loom-exporter, not of anything here.

Language models

Model Exported from
loom-ai-org/qwen3-0.6b-base-loom Qwen/Qwen3-0.6B-Base
loom-ai-org/lfm2-350m-monolithic-loom LiquidAI/LFM2-350M
loom-ai-org/lfm2-350m-modular-loom LiquidAI/LFM2-350M
loom-ai-org/smollm2-360m-instruct-loom HuggingFaceTB/SmolLM2-360M-Instruct
loom-ai-org/gemma-3-270m-it-loom google/gemma-3-270m-it

These are the models generate works on.

Speech recognition

Model Exported from
loom-ai-org/whisper-small-loom openai/whisper-small
loom-ai-org/conformer-ctc-small-loom nvidia/stt_en_conformer_ctc_small
loom-ai-org/parakeet-tdt-0.6b-loom nvidia/parakeet-tdt-0.6b-v3
loom-ai-org/parakeet-rnnt-0.6b-loom nvidia/parakeet-rnnt-0.6b
loom-ai-org/gigaam-v3-rnnt-loom ai-sage/GigaAM-v3
loom-ai-org/qwen3-asr-0.6b-loom Qwen/Qwen3-ASR-0.6B
loom-ai-org/granite-speech-4.0-1b-loom ibm-granite/granite-4.0-1b-speech

model.detokenize(model.infer(waveform=audio, audio_samples=len(audio))) — the mel frontend is inside the graph, so a raw waveform is the input.

Speech synthesis

Model Exported from
loom-ai-org/kokoro-82m-loom hexgrad/Kokoro-82M
loom-ai-org/matcha-tts-ljspeech-loom Matcha-TTS (LJSpeech checkpoint)
loom-ai-org/supertonic-2-loom Supertone/supertonic-2
loom-ai-org/vits-piper-en-gb-miro-loom OpenVoiceOS/pipertts_en-GB_miro
loom-ai-org/styletts2-ljspeech-loom yl4579/StyleTTS2-LJSpeech

Supertonic is the one with a text door — model.tokenize works on it and is None for the other four, which take phoneme ids (see above). model.driver_source is the authority on what each accepts.

The three repos

loom.cpp the engine, vendored here as a submodule
loom-exporter produces the GGUFs this runs
loom-py this one

Installing

pip install loom-py-rt           # once published -- `loom-py` on PyPI clashes with `loompy`,
                                  # and `loom-engine` normalizes to the already-taken `loomengine`
pip install loom-py-rt[hub]      # + from_pretrained()

From a checkout — note --recursive, since the engine is a submodule:

git clone --recursive https://github.com/loom-ai-org/loom-py
cd loom-py && pip install -e .

No runtime dependencies. Arrays cross the boundary as plain sequences of floats, so numpy is something you may use rather than something this package makes you install — list, array.array, numpy arrays and torch tensors all work.

Testing

pytest tests/ci      # the Python layer: coercion and error paths. No model. What CI runs.
pytest tests/gate    # a real exported GGUF, end to end.
export LOOM_TEST_MODEL=~/loom-fixtures/matcha_mil.gguf
export LOOM_TEST_MODEL_INPUTS='{"tokens":[16,40,22,30,12,3],"n_steps":4,"seed":1234}'
pytest tests/gate -q

The gate suite is written against no particular architecture on purpose: it asserts the shape of what a loom model is, which is the whole of what this package knows. A test that expected one model's inputs would be this package learning about a model, which is the thing the design exists to avoid.

Roadmap

Shared with loom.cpp, because three of the four are the engine's and this package inherits them by having no per-architecture code of its own.

1. GPUs and NPUs — the packaging is built; the backends beyond Vulkan are what remain. The engine schedules a graph across a device backend and a CPU fallback, this package exposes the choice as device= (above), and the wheel shape that lets an accelerator ship at all now exists.

The shape that is NOT wanted is a wheel per accelerator per architecture — PyPI's wheel tags have no accelerator dimension, so that is torch's cu121 arrangement, and it multiplies every future backend by every existing platform. GGML_BACKEND_DL makes the better shape possible and this package is now built that way: one arch-tagged base wheel, plus small backend packages that drop a .so where ggml looks for it, so pip install "loom-py-rt[cuda]" means "also fetch that backend", device="auto" finds it, and a Raspberry Pi installs nothing extra. packaging/rt-vulkan/ is the worked example; a CUDA package is that directory with two strings changed, waiting only on a machine with an NVIDIA GPU to build and test against. Tracked as BACKLOG.md P4.8, along with which backends are reachable at all (CUDA, OpenVINO and Qualcomm's are already in the pinned ggml; CoreML and RKNPU2 are not).

2. Wheels for more platforms. Linux x86-64 today; next macOS on Intel, macOS on Apple Silicon and Linux on ARM. This is the item most visible from here, since it is what pip install loom-py-rt can resolve to.

3. More models — P5 in the ledger, ordered by coverage per unit of effort: BERT token classifiers (the smallest possible template, and the first non-audio task) → codec decoders → CNN+CTC and SANM encoders → the remaining TTS families → text encoder-decoders → small classifiers → music. Each lands here for free: a model this package has never heard of works the day the exporter can produce it.

4. The follow-ups the docs already nameBACKLOG.md is the ledger for all three repos and the authority. The ones that would show up in this API: a permissively-licensed phonemiser, which is what would give the four phoneme-input TTS models a tokenize; and the KvCache memory redesign and quantized KV cache, which decide how large a model this can run on a given machine.

Licence

MIT — see LICENSE.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

loom_py_rt-1.0.0rc3.tar.gz (1.8 MB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

loom_py_rt-1.0.0rc3-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (7.5 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.27+ x86-64manylinux: glibc 2.28+ x86-64

loom_py_rt-1.0.0rc3-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl (4.2 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.27+ ARM64manylinux: glibc 2.28+ ARM64

loom_py_rt-1.0.0rc3-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (7.5 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.27+ x86-64manylinux: glibc 2.28+ x86-64

loom_py_rt-1.0.0rc3-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl (4.2 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.27+ ARM64manylinux: glibc 2.28+ ARM64

loom_py_rt-1.0.0rc3-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (7.5 MB view details)

Uploaded CPython 3.11manylinux: glibc 2.27+ x86-64manylinux: glibc 2.28+ x86-64

loom_py_rt-1.0.0rc3-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl (4.2 MB view details)

Uploaded CPython 3.11manylinux: glibc 2.27+ ARM64manylinux: glibc 2.28+ ARM64

loom_py_rt-1.0.0rc3-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (7.5 MB view details)

Uploaded CPython 3.10manylinux: glibc 2.27+ x86-64manylinux: glibc 2.28+ x86-64

loom_py_rt-1.0.0rc3-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl (4.2 MB view details)

Uploaded CPython 3.10manylinux: glibc 2.27+ ARM64manylinux: glibc 2.28+ ARM64

File details

Details for the file loom_py_rt-1.0.0rc3.tar.gz.

File metadata

  • Download URL: loom_py_rt-1.0.0rc3.tar.gz
  • Upload date:
  • Size: 1.8 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.11.2

File hashes

Hashes for loom_py_rt-1.0.0rc3.tar.gz
Algorithm Hash digest
SHA256 3991f0d04e0c80dbba89c6013a837d918c3e0f2791977b36316ebc8ddeeb200e
MD5 c587b709b6c30aae3b4a5959527db121
BLAKE2b-256 33642281de704b595d62fa29fc31bfaf1f0cd7549658e2f5fc672ecc95e5b4a1

See more details on using hashes here.

File details

Details for the file loom_py_rt-1.0.0rc3-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for loom_py_rt-1.0.0rc3-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 573099fc20b3d718af90650ac9c2d038b01c8b61625d724d50a61f3cf0b47772
MD5 f2010971547006b95acdb9aee95222de
BLAKE2b-256 239e270fcab570fa00a323786582360bef17129ff028995d4ce919a1585d2337

See more details on using hashes here.

File details

Details for the file loom_py_rt-1.0.0rc3-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for loom_py_rt-1.0.0rc3-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 b08c4f9a947d7cc309183812413b32f89d57b67b04a6c78640fb6b8cb4b5f215
MD5 de28aa9c5b8a4b266ee80e017b3d4617
BLAKE2b-256 f39d65696ea87a2339b266cfb865ea4e88e363bd504c62b6a54e48308465577f

See more details on using hashes here.

File details

Details for the file loom_py_rt-1.0.0rc3-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for loom_py_rt-1.0.0rc3-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 357b604031e4695f125bb3e405799c576ad58c47c9799a9435d3ad249a920e56
MD5 0913792c0f4b9b7aa194ab5f91fbaf68
BLAKE2b-256 107c952ef39185554d2a5eade3b5bcd1eb0adc6f4585786eb5f16e017aea26e9

See more details on using hashes here.

File details

Details for the file loom_py_rt-1.0.0rc3-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for loom_py_rt-1.0.0rc3-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 a3e805551277a9f117bd89723da131c32916326b39d9464e9e72bcdc1ba4ce77
MD5 476c1843d102f7d70e15f7667ca6fbdd
BLAKE2b-256 e92edbae8980ca8429bb98da3331a9cddf45bc9d6678b838dfa0ff6b6fcd44d2

See more details on using hashes here.

File details

Details for the file loom_py_rt-1.0.0rc3-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for loom_py_rt-1.0.0rc3-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 b8ecf32e6cdf7b0d13d45df911287a17cc3ee7aebe3a4d6a09f309f0efc5870c
MD5 4f5721430b91d9d9af325f3575a9c865
BLAKE2b-256 fb123982b1a04a44f62380d28b95fb2d3d4314e8cb6a03e4c91d08eadaecaede

See more details on using hashes here.

File details

Details for the file loom_py_rt-1.0.0rc3-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for loom_py_rt-1.0.0rc3-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 474bc63c798ac2652aaadb6e23c19486ffd6ee06b693430436e4780815c7adde
MD5 6bcf974e3d0d87ce61021b84f69415ff
BLAKE2b-256 63f8493e0f243777f7fea10e38f4bd8044716c389f27413ec78b9b04c9e5a113

See more details on using hashes here.

File details

Details for the file loom_py_rt-1.0.0rc3-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for loom_py_rt-1.0.0rc3-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 bf7952571d7893ccc81c110fd12b320345315cd756d597b4197819bd58d8b292
MD5 9e4449ba69fd51041312e6413598e65c
BLAKE2b-256 c2991c738418bff0299ece9c61000acb19ecb4b24ea6f7c683745a62b97c9931

See more details on using hashes here.

File details

Details for the file loom_py_rt-1.0.0rc3-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for loom_py_rt-1.0.0rc3-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 aef629de74ac199c6ab449bb2fafb9eb031c6bd9b3edd08a9bbe6450c546bc50
MD5 f07a53193ec4e8d6a89cc8862948f0d7
BLAKE2b-256 770da3f6fa7cd88df0ec8e772593b85e28a17270e85f37ed063fa0b11f45385d

See more details on using hashes here.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page