embroider — Jina v5 text embeddings (Rust core, PyO3)
embroider turns text into vectors — Jina v5 embeddings served through
ONNX Runtime from a Rust core, with optional PyO3 bindings for Python.
One frozen contract covers the whole path: task prefix → tokenize → ONNX
forward → last-token pooling → L2 → Matryoshka truncate → re-normalise,
so every consumer lands in the same vector space.
One engine, two consumers: bobine (PDF/Office → Markdown) reuses the
ONNX plumbing, okfgraph uses the full Jina v5 text-embedding contract.
It began as a clean move out of OKFgraph's rust/okf-embed — an exact
port of EmbeddingEngine._encode — and stays pinned against a
numpy/transformers replication by OKFgraph's parity harness
(tests/test_parity.py, max abs diff ≤ 1e-5).
Single backend, kept comparable: one lean runtime with no torch / transformers / optimum in the hot path, so every vector in an index stays directly comparable. If something can't be embedded exactly to contract, embroider errors loudly rather than quietly mixing vector spaces.
Install
PyPI wheels (Linux / Windows / macOS-arm64, Python 3.11–3.13) — okfgraph
pulls it in automatically; standalone:
pip install embroider
From source (Rust toolchain + maturin; maturin develop needs pip, which
uv venvs lack — build the wheel and install it instead):
maturin build --release
uv pip install --python <venv> target/wheels/embroider-*.whl --reinstall
Module layout
| Module | Role |
|---|---|
providers |
provider-name matrix (cuda/rocm/directml/openvino/coreml + implicit cpu) + clone-and-fallback application (apply_providers = arena on; apply_providers_with_arena carries the flag) |
probe |
corrected CUDA availability check (OnceLock-cached) |
policy |
DeviceReq (auto/cpu/cuda) + Precision (auto/fp32/fp16) + explicit SessionPolicy (text_embed() vs ort_defaults()) |
acquire |
validated owner/name parsing, HF client, tokenizer-only fetch, FP16-mirror selection for the default id |
error |
anyhow-based error plumbing (ort errors stringified at boundaries) |
diag |
OrtReport — ORT_DYLIB_PATH value + CUDA usability for logs |
jina |
JinaV5 + TokenizerHandle — the frozen embedding contract |
The default (pure-Rust) build is Python-free — no pyo3 in downstream
trees; the extension-module Cargo feature gates the PyO3 bindings and is
enabled only for wheel builds (maturin), the same pattern bobine uses.
Runtime: ONNX Runtime discovery
ort loads dynamically (load-dynamic, same pin as bobine:
2.0.0-rc.13). Resolution order: ORT_DYLIB_PATH first (user override
always wins), else the pip-installed onnxruntime/onnxruntime-gpu
build when unset. okfgraph's resolve_ort_dylib() runs before the native
module is imported, so bobine and embroider share one ORT binary — no
version/CUDA drift between ingest and import.
Lifecycle: lazy session, cheap tokenizer
JinaV5.open (model download + ONNX session build) is the single
expensive step. OKFgraph therefore holds a lazy proxy: construction
validates the wheel import and device string eagerly, but the session
opens on the first real encode — PPR search, budgeted reads, diff, and
doctor stay cold.
JinaV5.open(model_id, revision=None, cache_dir=None, truncate_dim=512, device="auto", max_length=None, precision=None, cpu_arena=False):
max_length caps encodes at 1..=32768 (None = 8192 compat default;
.max_length reports the effective limit), precision selects weights
(auto/fp32/fp16, None = auto; .precision reports the
effective choice), cpu_arena=False disables the CPU arena allocator
(8x lower peak RSS for ~1.4x encode time, measured on the FP32 text
model).
JinaTokenizer.open fetches only tokenizer.json for exact token counts
without the session. It never truncates, so counts report true length —
JinaV5.count_tokens() instead reflects the session's max_length.
A failed session open is cached and re-raised — configuration errors fail
fast once, not once per encode.
Weight precision (auto by default)
auto follows the resolved device (CUDA → FP16, CPU → FP32), so
CUDA-requested-but-missing degrades to FP32 weights instead of stranding
FP16 on CPU (FP16-on-CPU runs >40x slower than FP32-CPU — measured).
fp16 maps the default model id to the published FP16 mirror repo
(opticsWolf/jina-embeddings-v5-text-small-retrieval-onnx-fp16);
explicit model ids (omni tower, mirrors) always win untouched. An explicit
fp16-on-CPU warns loudly but is honoured. Do not mix precisions in one
index — FP32 vs FP16 weights shift vectors, same as mixing tuning levels.
Memory: CPU arena off by default
cpu_arena=False registers the CPU execution provider explicitly with
its arena allocator disabled — measured 8x lower peak RSS (15.3 → 1.9 GB
on FP32) for ~1.4x encode time. Pass True only when peak throughput
beats memory pressure.
Explicit local files (air-gapped)
JinaV5.open_files(onnx_path, tokenizer_path, truncate_dim=512, device="auto", max_length=None, cpu_arena=False) and
JinaTokenizer.open_files(tokenizer_path) skip every download. The
sidecar (model.onnx_data-style) must sit next to the ONNX file — ORT
resolves it relative to the model path, same as the HF cache layout.
Precision selection does not apply here — the files are what they are
(reported precision reads fp32; pass FP16 files explicitly for FP16
weights). OKFgraph's OKFRouter(model_path=..., tokenizer_path=...)
uses them (both or neither; missing files raise FileNotFoundError at
construction). Same bytes in → same vectors out (test-pinned against HF
acquisition).
Session/threading policy (measured)
Tuning is Level3, intra = physical-cores/2, inter = 1 — kept because it
measured fastest, not because it was inherited. Reference box: Windows,
32 logical cores, CPU-only ORT 1.29, warm model cache, best-of-5 reps on
4 fixed docs (short → ~400 tokens):
| Config | Session cold open | encode_batch (4 docs) |
Notes |
|---|---|---|---|
| Level3, intra=16, inter=1 (current) | 4.7 s | 375 ms | kept |
| Level1, intra=16, inter=1 | 5.5 s | 433 ms (+15%) | slower and bit-different vectors |
| Level3, intra=32, inter=1 | 4.5 s | 411 ms (+10%) | full-logical loses to phys/2 (SMT contention) |
4× encode_one vs 1× encode_batch |
— | 389 vs 375 ms | one boundary crossing saves ~3%; sequential stays |
| Tokenizer-only cold open | 0.5 s | — | 9× cheaper than session open; budgeted reads stay cold |
Two consequences:
- Do not mix tuning in one index. Level1 vs Level3 fuse the graph differently, so bits differ (hashes diverged at 1e-8 formatting). Same model + same build + same tuning, or re-embed.
- Sequential batching stays. Padded batching would waste attention on variable-length docs to save ~14 ms of boundary overhead — not worth the numerics risk.
SessionPolicy::ort_defaults() exists for consumers (bobine's vision
sessions) that never tuned — policy is data, never a forced default.
Re-measure on new hardware/ORT before changing the policy.
Pitfall: stale onnxruntime.dll on Windows
Windows boxes can carry a stale C:\Windows\System32\onnxruntime.dll
(v1.17.1 in the wild). With ORT_DYLIB_PATH unset, ort may load it and
die with BadVersion { version_str: "1.17.1" }, followed by an abort at
shutdown (fallout from ort's exit handler, not the root cause). Point
ORT_DYLIB_PATH at a modern build — e.g. the venv's
onnxruntime/capi/onnxruntime.dll. Same pitfall bobine documents in its
docs/benchmarks.md.
Failure policy
| Level | Behaviour |
|---|---|
| Install | The wheel is a core dependency of the consumer; if it is missing or fails to import, the consumer raises a clear RuntimeError with the install hint — never an ImportError from deep inside, never a silent fallback. |
| Device | Accelerators are opportunistic: auto/cuda use CUDA when the loaded ORT registers the EP, else warn (stderr) + CPU. used_cuda reports the outcome. Never fatal. Unknown provider names warn and are skipped; registration failure degrades to CPU. precision='auto' follows the landed device (CUDA→FP16, CPU→FP32); explicit fp16-on-CPU warns but is honoured. |
| Encode | Fail fast. No fallback at encode time — vectors must stay bit-comparable within one index. |
| Tokenizer | No transformers in the runtime path, anywhere: internal tokenize + count_tokens() (== tokenizer.encode(t, add_special_tokens=False)) feed the context-window guard. |
Contract notes
- Session IO is discovered at load (
input_ids+attention_maskrequired,token_type_idsfed only if declared — v5's export doesn't declare it, which is where generic runners fail). Output preferslast_hidden_state. truncate_dimvalidated (32–1024, warning off the Matryoshka ladder).max_lengthvalidated (1..=32768,None= 8192 compat default);MAX_LENGTH/MODEL_MAX_TOKENSare exposed for the window guard. Same (text,max_length) → same vector; short inputs are bit-identical at any limit, while longer inputs change once the old truncation lifts. A 32K-token forward is O(n²) memory — size the limit to the machine.- Batch encoding is sequential by design (padded batches waste attention compute on variable-length docs). GIL is released during encode.
input_ids/attention_maskfeed as int64; pooling takes the last attended token (mask_sum - 1, clamped ≥ 0).
Conformance
fixtures/golden_jina_v5_text_small.json pins the frozen vector space:
4 canonical texts × Query/Document prefixes × dims 64/512 (12 vectors) +
exact token counts, generated with embroider 0.1.3 / onnxruntime 1.29.0
CPU / text-embed policy. Unchanged by 0.1.4 (max_length) and 0.1.5
(precision, cpu_arena) for short inputs at defaults. Consumers vendor
this file and assert live vectors against it (abs=1e-6 — catches wrong
model, pooling, prefix, or truncation; immune to cross-CPU noise). Regenerate only on an
intentional contract change, which is a new minor version plus a
re-index-everything notice. See COMPAT.md for the release matrix.
Testing
-
Rust unit tests (28, pure — no network, no dylib, no tokenizer file): device/precision parsing, precision-follows-device resolution, FP16 repo selection, model-id parsing, provider-matrix mapping, task-prefix idempotence, the L2 → truncate → re-normalise math, contract constants, and
open()/open_files()validation (dims,max_length) firing before I/O.cargo test --locked
-
Python parity lives with the consumers: OKFgraph's
tests/test_parity.py(markedslow) pins Rust output against a numpy/transformers replication across dims × tasks × texts at ≤ 1e-5;tests/test_rust_backend.py/tests/test_rust_e2e.pycover the wheel import, the count-tokens contract, and real-model encodes.
Metadata
Release files for embroider 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| embroider-0.2.0.tar.gz | 91.0 kB | Details |
Built distributions (wheels)
| File | Reset | |||
|---|---|---|---|---|
| embroider-0.2.0-cp313-cp313-win_amd64.whl | CPython 3.13 | CPython 3.13 | Windows x86-64 | Details |
| embroider-0.2.0-cp313-cp313-manylinux_2_28_x86_64.whl | CPython 3.13 | CPython 3.13 | Linux glibc 2.28+ x86-64 | Details |
| embroider-0.2.0-cp313-cp313-macosx_11_0_arm64.whl | CPython 3.13 | CPython 3.13 | macOS 11.0+ ARM64 | Details |
| embroider-0.2.0-cp312-cp312-win_amd64.whl | CPython 3.12 | CPython 3.12 | Windows x86-64 | Details |
| embroider-0.2.0-cp312-cp312-manylinux_2_28_x86_64.whl | CPython 3.12 | CPython 3.12 | Linux glibc 2.28+ x86-64 | Details |
| embroider-0.2.0-cp312-cp312-macosx_11_0_arm64.whl | CPython 3.12 | CPython 3.12 | macOS 11.0+ ARM64 | Details |
| embroider-0.2.0-cp311-cp311-win_amd64.whl | CPython 3.11 | CPython 3.11 | Windows x86-64 | Details |
| embroider-0.2.0-cp311-cp311-manylinux_2_28_x86_64.whl | CPython 3.11 | CPython 3.11 | Linux glibc 2.28+ x86-64 | Details |
| embroider-0.2.0-cp311-cp311-macosx_11_0_arm64.whl | CPython 3.11 | CPython 3.11 | macOS 11.0+ ARM64 | Details |
Total release size: 58.1 MB
Release files / embroider-0.2.0.tar.gz
| Download URL | embroider-0.2.0.tar.gz |
|---|---|
| Size | 91.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
17710c5e271bbd2b89e4e9fea28d2e0a7dcff5490c2484121c7e9062fd99c42b
|
|
BLAKE2b-256 checksum How to use checksums |
ba75471b4965bccb523ba298ca7a158c5f3fd5b12de6694e4ac45093785f2b2a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 15, 2026.
Transparency logRelease files / embroider-0.2.0-cp313-cp313-win_amd64.whl
| Download URL | embroider-0.2.0-cp313-cp313-win_amd64.whl |
|---|---|
| Size | 5.8 MB |
| Tags | CPython 3.13 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
55b94cdd9e9a562f18407125fa399d151522185c4ba689d95dfa9a2ec583a2d1
|
|
BLAKE2b-256 checksum How to use checksums |
a3be6d94c384545d194736d5a9ca9bde442cb3894f5ea52377ff8bc5e06a3ed3
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 15, 2026.
Transparency logRelease files / embroider-0.2.0-cp313-cp313-manylinux_2_28_x86_64.whl
| Download URL | embroider-0.2.0-cp313-cp313-manylinux_2_28_x86_64.whl |
|---|---|
| Size | 7.2 MB |
| Tags | CPython 3.13 Linux glibc 2.28+ x86-64 |
|
SHA-256 checksum How to use checksums |
9e489bcd77400849c33c219bd884dd3e6b5a0029e275c11030649de90ad6aa6c
|
|
BLAKE2b-256 checksum How to use checksums |
67e7c0b625330175a756a31c2549d1ceaecadc0d5f380a59b22a2fcb28835934
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 15, 2026.
Transparency logRelease files / embroider-0.2.0-cp313-cp313-macosx_11_0_arm64.whl
| Download URL | embroider-0.2.0-cp313-cp313-macosx_11_0_arm64.whl |
|---|---|
| Size | 6.3 MB |
| Tags | CPython 3.13 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
ed8f61d77ee9946791af59cda16ff667a0f2582f0726c21a4c29fc5c51ac1e0e
|
|
BLAKE2b-256 checksum How to use checksums |
333aa50b3a90e46f8025df8a13609914520670e518426aae0d7fab594b384824
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 15, 2026.
Transparency logRelease files / embroider-0.2.0-cp312-cp312-win_amd64.whl
| Download URL | embroider-0.2.0-cp312-cp312-win_amd64.whl |
|---|---|
| Size | 5.8 MB |
| Tags | CPython 3.12 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
489647f60808ebaec293cd3303bbb25d1520d15d227adf991f41ea8c35bc968b
|
|
BLAKE2b-256 checksum How to use checksums |
df6b2f4907c37843acc191d3f4d1ee6964edd840427c25550c97cb003c330aa1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 15, 2026.
Transparency logRelease files / embroider-0.2.0-cp312-cp312-manylinux_2_28_x86_64.whl
| Download URL | embroider-0.2.0-cp312-cp312-manylinux_2_28_x86_64.whl |
|---|---|
| Size | 7.2 MB |
| Tags | CPython 3.12 Linux glibc 2.28+ x86-64 |
|
SHA-256 checksum How to use checksums |
b010e7647cb4b0ebf1cc98f368cbf6884c8d1e2c77d747b2620fc78c87999063
|
|
BLAKE2b-256 checksum How to use checksums |
9ad8de723e12c92ae5da45349ab32bab8d7a277b007aa60c787f15e97436f2aa
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 15, 2026.
Transparency logRelease files / embroider-0.2.0-cp312-cp312-macosx_11_0_arm64.whl
| Download URL | embroider-0.2.0-cp312-cp312-macosx_11_0_arm64.whl |
|---|---|
| Size | 6.3 MB |
| Tags | CPython 3.12 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
6415c174d299d0309b0cb36cb43c06a951dd04c2dd9d2985840d6e6364b002f3
|
|
BLAKE2b-256 checksum How to use checksums |
ddecb64b92b7a6d9e1a435ff7f15bb70181a09d5cf41fa6f139fcc333577b0aa
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 15, 2026.
Transparency logRelease files / embroider-0.2.0-cp311-cp311-win_amd64.whl
| Download URL | embroider-0.2.0-cp311-cp311-win_amd64.whl |
|---|---|
| Size | 5.8 MB |
| Tags | CPython 3.11 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
c0be190df5da9fc72d28371b84dc4854a3156750eb76c7bb328a6ea9c7be0d43
|
|
BLAKE2b-256 checksum How to use checksums |
492b56b971f39f92d37dde5d376b791746fc8085b1cb428ebf70870cb73ffa43
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 15, 2026.
Transparency logRelease files / embroider-0.2.0-cp311-cp311-manylinux_2_28_x86_64.whl
| Download URL | embroider-0.2.0-cp311-cp311-manylinux_2_28_x86_64.whl |
|---|---|
| Size | 7.2 MB |
| Tags | CPython 3.11 Linux glibc 2.28+ x86-64 |
|
SHA-256 checksum How to use checksums |
ae3a9a7a09de0023d93a7aa0bed28c19aed571b3c904b41da0e46b7cca447585
|
|
BLAKE2b-256 checksum How to use checksums |
0423de976ace01eac111bd8546db6b28d7069204299947daf10fa5a31f8bbaea
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 15, 2026.
Transparency logRelease files / embroider-0.2.0-cp311-cp311-macosx_11_0_arm64.whl
| Download URL | embroider-0.2.0-cp311-cp311-macosx_11_0_arm64.whl |
|---|---|
| Size | 6.3 MB |
| Tags | CPython 3.11 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
31390550633e60c97f19e78142718c0de3c5c48af322615e459be88fd63ba739
|
|
BLAKE2b-256 checksum How to use checksums |
803617f12f74c0748f95b2a97c0f5e6baf477ef16045838e1105990ee3a9f08a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 15, 2026.
Transparency log