Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,14 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

### Fixed

- **embedding**: stopped force-enabling `ort-load-dynamic` on the Linux/Windows `fastembed` target dependency by default (#50). `ort-load-dynamic` forwards to `ort-sys/disable-linking`, which makes `ort-sys`'s build script early-return and **skip the static-archive download step entirely** — so `ort-download-binaries-rustls-tls` was a silent no-op and the resulting binary expected `libonnxruntime.so` to be supplied externally at runtime. Since llm-kernel never ships that library, `embedding-fastembed` on Linux deadlocked silently on first `.embed()` instead of failing cleanly. The default build now statically links ONNX Runtime and produces self-contained binaries. **Caveat:** ort's prebuilt static archive requires glibc 2.38+, resolved against the executing host's libc at runtime — Linux hosts on glibc <2.38 (e.g. Ubuntu 22.04, Debian 12) will fail to load the statically-linked binary at first ONNX Runtime init. Such deployments should enable the new opt-in `embedding-fastembed-dynamic-linking` feature instead (forwards to `fastembed/ort-load-dynamic`) and ensure `libonnxruntime.{so,dll}` is present on the runtime host. Do not combine `embedding-fastembed-dynamic-linking` with a build that also enables plain `embedding-fastembed`/`full` elsewhere in the same feature graph — Cargo feature unification would re-merge both and silently reintroduce #50.
- **embedding**: `LazyFastembedProvider`'s model-load path is now **panic-safe** in builds that unwind on panic (the default `dev`/`test` profile, and any `release` profile that doesn't override `panic`). A panic during `FastembedProvider::new()` (e.g. a missing `libonnxruntime.so` under dynamic loading) is caught via `catch_unwind` and converted into a `ModelState::Failed(..)` transition that notifies all `Condvar` waiters, so concurrent callers receive a clean error instead of wedging forever on `futex` (confirmed in production via `/proc/PID/wchan`). Guards against any future ort/fastembed init failure mode, not just the dynamic-linking one. **Note:** this crate's own `[profile.release]` sets `panic = "abort"`, under which `catch_unwind` cannot intercept a panic — a panicking init in a release build of this crate still aborts the process rather than transitioning to `Failed`. This is an intentional tradeoff (a hard crash is a clearer failure signal than the previous silent deadlock), but it means the "clean error" guarantee above is scoped to unwinding builds; downstream crates that enable `panic = "abort"` in their own release profile inherit the same limitation.
- **embedding**: a load that fails with `ModelState::Failed` is no longer permanently stuck — `LazyFastembedProvider::reset()` clears a `Failed` state back to `NotLoaded`/`Cached` so a subsequent `ensure_model()` call retries the load (e.g. after a transient network failure during model download). `ModelState::Failed` now also exposes `is_panic()` so callers can distinguish "loader panicked" (ort/global state may be corrupted; retrying on the same process may not be safe) from an ordinary load error (safe to retry).

## [0.11.0] - 2026-07-01

### Added
Expand Down
12 changes: 6 additions & 6 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

40 changes: 35 additions & 5 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,21 @@ embedding-fastembed-nomic-moe = ["embedding-fastembed", "fastembed/nomic-v2-moe"
# DirectML GPU execution provider for FastembedProvider (Windows only)
embedding-fastembed-directml = ["embedding-fastembed", "dep:ort"]

# Opt-in dynamic ONNX Runtime linking (loads libonnxruntime.{so,dylib,dll} at
# runtime instead of statically linking a prebuilt archive at build time).
#
# Only use this if your deployment target cannot satisfy the static build's
# requirements — e.g. a glibc <2.38 Linux host (ort's prebuilt static archive
# needs glibc 2.38+; see #50) — and you can guarantee `libonnxruntime.*` is
# present on the runtime host. Do NOT combine this feature with a build that
# also depends on plain `embedding-fastembed` elsewhere in the same binary's
# feature graph: Cargo feature unification merges both `ort-load-dynamic` and
# `ort-download-binaries-*` into the shared `fastembed`/`ort-sys` crate,
# which silently turns the static path into a no-op again (the original #50
# failure mode). Enable this feature alone, or ensure nothing else in your
# build enables `embedding-fastembed`/`full` at the same time.
embedding-fastembed-dynamic-linking = ["embedding-fastembed", "fastembed/ort-load-dynamic"]

# Knowledge graph with async wrappers (requires tokio)
graph-async = ["graph", "dep:tokio"]

Expand Down Expand Up @@ -228,9 +243,24 @@ codegen-units = 4
inherits = "release"
lto = "thin"

# Windows needs ort-load-dynamic to avoid MSVC linker errors with ort-sys.
# Linux needs ort-load-dynamic because ort's prebuilt static libraries require
# glibc 2.38+ (__isoc23_strtol etc), which is not available on ubuntu-22.04.
# macOS uses static linking via ort-download-binaries (works reliably).
# Statically link ONNX Runtime by default via `ort-download-binaries-rustls-tls`:
# ort-sys downloads + links a prebuilt static archive at build time, producing a
# self-contained binary with no runtime dylib resolution.
#
# We do NOT enable `ort-load-dynamic` by default: that feature forwards to
# `ort-sys/disable-linking`, which makes ort-sys's build script early-return and
# SKIP the download step entirely — so `ort-download-binaries-*` becomes a silent
# no-op and the resulting binary expects `libonnxruntime.{so,dll}` to be supplied
# externally at runtime (which llm-kernel never ships). On Linux this previously
# manifested as a silent deadlock rather than a clean missing-library error
# (see #50).
#
# CAVEAT — static linking does not fully replace ort-load-dynamic: ort's
# prebuilt static archive requires glibc 2.38+ (`__isoc23_strtol` etc.), which
# is resolved against the *executing* host's libc at runtime, not the build
# host's. Linux hosts on glibc <2.38 (e.g. Ubuntu 22.04, Debian 12) will fail
# to load the statically-linked binary at first ONNX Runtime init. Such
# deployments should enable the `embedding-fastembed-dynamic-linking` feature
# instead (see above) and ensure `libonnxruntime.so` is present on the host.
[target.'cfg(any(target_os = "windows", target_os = "linux"))'.dependencies]
fastembed = { version = "5", default-features = false, features = ["hf-hub-rustls-tls", "ort-download-binaries-rustls-tls", "ort-load-dynamic"], optional = true }
fastembed = { version = "5", default-features = false, features = ["hf-hub-rustls-tls", "ort-download-binaries-rustls-tls"], optional = true }
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ Each module is gated behind a feature flag so you only pay for what you use.
| `embedding-fastembed` | Local ONNX embedding via fastembed-rs (44 models) | |
| `embedding-fastembed-qwen3` | Qwen3 embedding via candle backend | |
| `embedding-fastembed-nomic-moe` | Nomic V2 MoE embedding via candle backend | |
| `embedding-fastembed-dynamic-linking` | Dynamic ONNX Runtime linking (opt-in; for glibc <2.38 Linux hosts, see #50) | |
| `vector-index` | TurboQuant compressed vector index — 2-bit/4-bit, SIMD ANN search | |
| `qdrant` | Qdrant `AsyncVectorIndex` (`QdrantVectorIndex`) for remote vector search | |
| `elastic` | Elasticsearch `AsyncVectorIndex` (`ElasticsearchVectorIndex`) over a hand-rolled reqwest client | |
Expand Down
Loading
Loading