Skip to main content

libembedding

Forked from pacifio/libembedding. This fork adds Windows support (native DLL), PyPI packaging under the name libembedding-ng, local model loading, runtime introspection, similarity helpers, streaming, a multi-worker pool, an autotuner and automatic model selection. Imported as libembedding.

Fast ONNX-based text, image, and sparse embeddings for Python. Dynamic INT8 ONNX models are ~4x smaller, ~2x lighter in memory and ~1.7-2.0x faster than FP32 on CPU (measured; see Benchmarks below).

Built on a C/C++ backend using ONNX Runtime, exposed to Python via zero-overhead cffi bindings. The wheel bundles the compiled shared library (libembedding.so / .dylib / .dll) together with ONNX Runtime and libcurl, so no system ONNX Runtime install is required at runtime. Supports 44 text embedding models, 5 image models, 2 sparse models, and 4 rerankers with automatic model downloading from HuggingFace Hub.

Installation

pip install libembedding-ng

The PyPI package is named libembedding-ng (to avoid clashing with the original libembedding on PyPI); it is imported as libembedding. The wheel already bundles the native shared library and ONNX Runtime, so no separate system install is required.

Platforms: wheels exist for Windows x86-64, Linux x86-64 (manylinux), Linux aarch64 (manylinux_2_31: Raspberry Pi 3/4/5 under 64-bit Raspberry Pi OS, Ubuntu 20.04+, Graviton) and macOS arm64 (Apple Silicon, macOS 14 or later). The x86-64 wheels run on any x86-64 CPU, no AVX/AVX2 required: GGUF models load the ggml CPU library matching the machine at run time (libembedding.ggml_cpu_features() names it), and the aarch64 wheel does the same across eight ARM levels (armv8.0 to armv9.2). 32-bit ARM (armv7l) is not supported yet. On Linux, HTTPS downloads use the system CA bundle (SSL_CERT_FILE or CURL_CA_BUNDLE override it). The macOS wheel bundles its dependencies (ONNX Runtime, llama.cpp/ggml) under libembedding/.dylibs/ and uses the system libcurl.

Android: wheels for CPython 3.13 on Android 7.0+ (android_24_arm64_v8a, android_24_x86_64, PEP 738: BeeWare, Chaquopy). cffi and numpy come from Chaquopy's index: pip install --extra-index-url https://chaquo.com/pypi-13.1 libembedding-ng. Models download normally (static libcurl over mbedTLS, system certificate store). The x86_64 wheel is tested on an emulator in CI; the arm64 wheel has not been run on a device yet.

Requirements: ONNX Runtime must be installed on your system only if you build the package from source.

# macOS
brew install onnxruntime

# Ubuntu/Debian
apt install libonnxruntime-dev

# Or set ONNXRUNTIME_ROOT to your installation path

Quick Start

Text Embeddings

from libembedding import TextEmbedding

model = TextEmbedding("BAAI/bge-small-en-v1.5")
embeddings = model.embed(["Hello world", "How are you?"])

print(embeddings.shape)  # (2, 384)
print(embeddings.dtype)  # float32

Sparse Embeddings

from libembedding import SparseTextEmbedding

model = SparseTextEmbedding()
results = model.embed(["machine learning algorithms"])

for r in results:
    print(r.indices.shape, r.values.shape)

Image Embeddings

from libembedding import ImageEmbedding

model = ImageEmbedding()
embeddings = model.embed_files(["photo.jpg", "diagram.png"])

Reranking

from libembedding import Reranker

reranker = Reranker("BAAI/bge-reranker-base")
results = reranker.rerank(
    "What is deep learning?",
    [
        "Deep learning uses neural networks with many layers",
        "The weather is sunny today",
        "Neural networks are inspired by biological brains",
    ],
)
for r in results:
    print(f"doc[{r.index}] score={r.score:.4f}")

Model Discovery

import libembedding

for m in libembedding.list_text_models():
    print(f"{m.model_name:45} dim={m.dim:<5} {m.pooling}")

API Reference

Provider

TextEmbedding(
    model_name="BAAI/bge-small-en-v1.5",  # HuggingFace model name, repo code, or local dir path
    provider="cpu",  # "cpu", "cuda", "coreml", "directml", "tensorrt", "llamacpp"
    device_id=0,
    cache_dir=None,  # None = ~/.cache/libembedding
    max_length=0,  # 0 = model default
    threads=0,  # 0 = auto
    batch_size=256,  # internal batch size for embedding
    offline=False,  # True = use cache only, never download
    show_download_progress=True,
    dim=0,  # embedding dim for local models without config.json
    pooling="mean",  # "cls" or "mean" for local models
    num_threads=0,  # deprecated, use threads
)
Method Returns Description
embed(texts, batch_size=None) np.ndarray (n, dim) L2-normalized dense embeddings
embed_stream(texts, batch_size=None) generator Yields one embedding at a time (low memory)
dim int Embedding dimension
name str Model name or local path
info() ModelDesc Runtime model descriptor
max_length() int Max token length for the model
stats() Stats Runtime statistics (texts, batches, latency)
close() None Release resources
from_gguf(repo, filename=None, provider="llamacpp", ...) TextEmbedding Load a GGUF model from HuggingFace (requires llama.cpp build)
supports_llamacpp() bool (static) Check if llama.cpp backend is available

SparseTextEmbedding

SparseTextEmbedding(model_name="prithvida/SPLADE_PP_en_v1", ...)
Method Returns Description
embed(texts, batch_size=0) list[SparseEmbedding] Sparse vectors with .indices and .values
embed_stream(texts, batch_size=None) generator Yields one embedding at a time
dim int Embedding dimension (0 = dynamic)
name str Model name or local path
info() ModelDesc Runtime model descriptor
max_length() int Max token length
stats() Stats Runtime statistics

ImageEmbedding

ImageEmbedding(model_name="Qdrant/clip-ViT-B-32-vision", ...)
Method Returns Description
embed_files(paths, batch_size=0) np.ndarray (n, dim) Embed from file paths
embed_bytes(images, batch_size=0) np.ndarray (n, dim) Embed from raw bytes
dim int Embedding dimension
name str Model name or local path
info() ModelDesc Runtime model descriptor
stats() Stats Runtime statistics

Reranker

Reranker(model_name="BAAI/bge-reranker-base", ...)
Method Returns Description
rerank(query, documents, batch_size=0) list[RerankResult] Sorted by score descending
name str Model name or local path
info() ModelDesc Runtime model descriptor
max_length() int Max token length
stats() Stats Runtime statistics

All classes support context managers (with TextEmbedding(...) as model:).

Similarity Functions

from libembedding import cosine_similarity, dot_product, euclidean_distance
import numpy as np

a = np.array([1.0, 2.0, 3.0], dtype=np.float32)
b = np.array([1.0, 2.0, 3.0], dtype=np.float32)

print(cosine_similarity(a, b))  # 1.0 (identical)
print(dot_product(a, b))  # 14.0
print(euclidean_distance(a, b))  # 0.0

Streaming Embeddings

Process large document sets without allocating a single result array:

from libembedding import TextEmbedding

with TextEmbedding("BAAI/bge-small-en-v1.5") as model:
    for embedding in model.embed_stream(["doc1", "doc2", ...], batch_size=32):
        # Each iteration yields a single (dim,) numpy array
        process(embedding)

Runtime Statistics

with TextEmbedding("BAAI/bge-small-en-v1.5") as model:
    model.embed(["text 1", "text 2", "text 3"])
    stats = model.stats()
    print(
        f"Embedded {stats.texts_embedded} texts "
        f"({stats.batches_run} batches), "
        f"avg latency {stats.avg_latency_ms:.2f}ms"
    )

Data Types

ModelDesc — runtime model descriptor (returned by info()):

Field Type Description
name str Model name or local path
dimension int Embedding dimension
max_length int Max token length
pooling str "cls" or "mean"
num_threads int Threads configured
batch_size int Batch size configured
provider str Execution provider ("cpu", "cuda", "directml", "coreml", "llamacpp")
device_id int Device ID

Stats — runtime statistics (returned by stats()):

Field Type Description
texts_embedded int Total texts processed
batches_run int Total ONNX inference batches
avg_latency_ms float Average milliseconds per embed call

Local Model Loading

from libembedding import TextEmbedding

# Load from a local directory containing model.onnx + tokenizer.json (+ config.json)
model = TextEmbedding("/path/to/model_dir")

Available Models

44 text models including BGE, MiniLM, Nomic, E5, CLIP, Jina, GTE, Snowflake, ModernBERT (with quantized variants).

6 image models including CLIP ViT-B/32 (FP32 + INT8 quantized), ResNet-50, Unicom, Nomic Vision.

2 sparse models: SPLADE++, BGE-M3.

5 reranker models: BGE Reranker, Jina Reranker (including INT8 quantized variant).

GGUF/llama.cpp models: Run quantized GGUF models (Q4_K_M, Q8_0) via the llama.cpp backend.

Benchmarks

Comparison with fastembed — withdrawn

An earlier version of this file published a table claiming libembedding is 6.5-8.6x faster than fastembed, stated as "measured on Apple M-series". It has been removed. All four measurement harnesses hardcoded "platform": "macOS arm64" in their output, so no run could be traced to a machine, and the maintainer has no Mac to reproduce it on. The harnesses now report the real platform. See docs/archive/benchmarks/cross-implementation-macos-claim/ for the withdrawn figures and the reasoning.

Treat any cross-implementation speed claim about libembedding as unsubstantiated until it is re-measured on an identified machine.

Quantization — measured and reproducible

The quantization benchmark in the main README reports its full environment (CPU, ONNX Runtime version, execution provider) and reads the weight dtypes from the ONNX files, so its provenance is verifiable.

Unified Auto-Tuning

Auto-tune threads and batch_size (plus workers for text, max_tokens for the reranker) for any task type:

from libembedding import autotune, autotune_unified, clear_autotune_cache_unified

# Text embedding tune (QUICK by default; ~13 s cold on an i7-1065G7, indicative)
result = autotune("BAAI/bge-small-en-v1.5")

# Unified API for any task: "embedding", "reranking", "sparse", "image"
result = autotune_unified("embedding", "BAAI/bge-small-en-v1.5")

# Objective, custom workload and constraints (reranking: last text = the query)
result = autotune_unified(
    "reranking",
    "jinaai/jina-reranker-v1-turbo-en-quantized",
    objective="latency",              # "latency" | "throughput" | "balanced" | "memory"
    texts=[*documents, query],
    max_latency_ms=300.0,             # p95 budget for one tuning call (0 = none)
    min_tokens=128,                   # reranking only: floor for max_tokens
)
# Over budget? The best unconstrained config is returned: check result.p95_latency_ms.

clear_autotune_cache_unified("reranking")   # purge one task's cache

Results are cached per model, hardware, runtime, workload, objective, mode and constraints — a repeated call returns in milliseconds. For sparse models, top_k, min_weight and storage_format are not tuned (they change the output); the result reports the model defaults. See docs/performance_tuning.md for grids, methodology and measurements.

Error Handling

from libembedding import LembedError, LlamaError
from libembedding.exceptions import (
    ModelNotFoundError,
    OnnxRuntimeError,
    DownloadError,
)

try:
    model = TextEmbedding("nonexistent/model")
except ModelNotFoundError as e:
    print(f"Model not found: {e.detail}")
except LlamaError as e:
    print(f"llama.cpp error: {e.detail}")
except LembedError as e:
    print(f"Error [{e.status_code}]: {e.message}")

GGUF Models (llama.cpp)

Load quantized GGUF models:

from libembedding import TextEmbedding

# Check llama.cpp availability
if TextEmbedding.supports_llamacpp():
    model = TextEmbedding.from_gguf(
        repo="Xenova/all-MiniLM-L6-v2-GGUF",
        filename="all-MiniLM-L6-v2-Q4_K_M.gguf",
        provider="llamacpp",
    )
    embeddings = model.embed(["Hello world"])

Configuration

Environment Variable Purpose
LIBEMBEDDING_CACHE_DIR Override model cache directory
FASTEMBED_CACHE_DIR Alternative cache dir (fastembed compatibility)
HF_ENDPOINT Custom HuggingFace Hub endpoint

Building & Publishing

Prerequisites

pip install build twine

Build the shared library + wheel

cd python/

# Step 1: Build the C/C++ shared library and copy it into the package
./setup.sh --build-only

# Step 2: Build sdist and wheel
python -m build

This produces files in dist/ (versions follow the libembedding-ng package, e.g. 1.4.0):

dist/
  libembedding_ng-1.1.1.tar.gz                                # source distribution
  libembedding_ng-1.1.1-cp39-abi3-manylinux_2_28_x86_64.whl  # platform wheel (bundles libembedding.so + onnxruntime)

Upload to PyPI

# Upload to TestPyPI first to verify
twine upload --repository testpypi dist/*

# Install from TestPyPI to verify
pip install --index-url https://test.pypi.org/simple/ libembedding

# Upload to production PyPI
twine upload dist/*

One-liner (build + upload)

./setup.sh --build-only && python -m build && twine upload dist/*

Platform-specific wheels

The wheel is platform-tagged (e.g. manylinux, macosx, win_amd64) because it bundles the compiled shared library (libembedding.so / .dylib / .dll) along with ONNX Runtime and libcurl. python -m build produces a wheel for the current build platform. To build wheels for other platforms, build on that platform or use cibuildwheel:

# macOS (current arch)
./setup.sh --build-only
python -m build

# For other platforms, build on that platform or use cibuildwheel:
pip install cibuildwheel
cibuildwheel --platform linux   # builds manylinux wheels
cibuildwheel --platform macos   # builds macOS wheels

License

MIT

Metadata

Release files for libembedding-ng 1.13.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Built distributions (wheels)

Table of built distributions (wheels) for libembedding-ng 1.13.0
File Actions
libembedding_ng-1.13.0-py3-none-win_amd64.whl Python 3 none Windows x86-64 Details for libembedding_ng-1.13.0-py3-none-win_amd64.whl
libembedding_ng-1.13.0-py3-none-manylinux_2_34_x86_64.whl Python 3 none Linux glibc 2.34+ x86-64 Details for libembedding_ng-1.13.0-py3-none-manylinux_2_34_x86_64.whl
libembedding_ng-1.13.0-py3-none-manylinux_2_31_aarch64.whl Python 3 none Linux glibc 2.31+ ARM64 Details for libembedding_ng-1.13.0-py3-none-manylinux_2_31_aarch64.whl
libembedding_ng-1.13.0-py3-none-macosx_14_0_arm64.whl Python 3 none macOS 14.0+ ARM64 Details for libembedding_ng-1.13.0-py3-none-macosx_14_0_arm64.whl
libembedding_ng-1.13.0-cp313-cp313-android_24_x86_64.whl CPython 3.13 CPython 3.13 Android API level 24+ x86-64 Details for libembedding_ng-1.13.0-cp313-cp313-android_24_x86_64.whl
libembedding_ng-1.13.0-cp313-cp313-android_24_arm64_v8a.whl CPython 3.13 CPython 3.13 Android API level 24+ ARM64 v8a Details for libembedding_ng-1.13.0-cp313-cp313-android_24_arm64_v8a.whl

Total release size: 194.7 MB

Release files / libembedding_ng-1.13.0-py3-none-win_amd64.whl

Download URL libembedding_ng-1.13.0-py3-none-win_amd64.whl
Size 11.9 MB
Tags Python 3 Windows x86-64
SHA-256 checksum
How to use checksums
447ac868b6fe93242188da13017e45368c75f8eed0005a750cae68fa99669cf4
BLAKE2b-256 checksum
How to use checksums
43cb83a560ff20383750eb8552236b64a16a8fc08a3d0f0b30bf2cd155c6d88e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.16

Release files / libembedding_ng-1.13.0-py3-none-manylinux_2_34_x86_64.whl

Download URL libembedding_ng-1.13.0-py3-none-manylinux_2_34_x86_64.whl
Size 38.9 MB
Tags Linux glibc 2.34+ x86-64 Python 3
SHA-256 checksum
How to use checksums
1ac4cb528f524566cfcac7ceb99499829faae5cf0ab9922d1b8afd7b7a5d3375
BLAKE2b-256 checksum
How to use checksums
174316788614e8ca85e2e70272b39695a7fce28aecefefa0f3db1e5db542a528
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.16

Release files / libembedding_ng-1.13.0-py3-none-manylinux_2_31_aarch64.whl

Download URL libembedding_ng-1.13.0-py3-none-manylinux_2_31_aarch64.whl
Size 30.2 MB
Tags Linux glibc 2.31+ ARM64 Python 3
SHA-256 checksum
How to use checksums
73694051b2bbf40d82969243258a2576808e0da353b50cb1c0b127c2af7040d2
BLAKE2b-256 checksum
How to use checksums
4d6819423ca728dac101ac4f09194afdfe1bd65c7dd1a24a1560b875f76dc37c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.16

Release files / libembedding_ng-1.13.0-py3-none-macosx_14_0_arm64.whl

Download URL libembedding_ng-1.13.0-py3-none-macosx_14_0_arm64.whl
Size 15.9 MB
Tags Python 3 macOS 14.0+ ARM64
SHA-256 checksum
How to use checksums
80d091c6de37625a0a12b2cd2478e561c92878d18d6a568ffb3874a0eee1bf6d
BLAKE2b-256 checksum
How to use checksums
a7705754276840681fc2c59d38a9a9d31d015be222451c97f92a3a24db6e3eef
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.16

Release files / libembedding_ng-1.13.0-cp313-cp313-android_24_x86_64.whl

Download URL libembedding_ng-1.13.0-cp313-cp313-android_24_x86_64.whl
Size 58.1 MB
Tags Android API level 24+ x86-64 CPython 3.13
SHA-256 checksum
How to use checksums
634b990b199db1354be5889338baf31d9f93abd2cc4ad0ab89e6b5f22110a83e
BLAKE2b-256 checksum
How to use checksums
21a0982cf13b36c42138b61683e258bf5a9c59b52b103d167d0fd374722e6e82
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.16

Release files / libembedding_ng-1.13.0-cp313-cp313-android_24_arm64_v8a.whl

Download URL libembedding_ng-1.13.0-cp313-cp313-android_24_arm64_v8a.whl
Size 39.7 MB
Tags Android API level 24+ ARM64 v8a CPython 3.13
SHA-256 checksum
How to use checksums
1f34559af16c48737413e1d49dd7b833968de1c02a877a76889bdafaea38902f
BLAKE2b-256 checksum
How to use checksums
7e914c095e8d6d75e8974e1d71f9e565a7fd2a234af9e9859cbbac9c2626744b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.16

Security for libembedding-ng 1.13.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

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