zeppelin-embed-text 0.8.0

Local text embedding and retrieval for Zeppelin Embed on macOS and Apple silicon
docs.rs failed to build zeppelin-embed-text-0.8.0
Please check the build logs for more information.
See Builds for ideas on how to fix a failed build, or Metadata for how to configure docs.rs builds.
If you believe this is docs.rs' fault, open an issue.

Zeppelin Embed Text

Local text embedding and dense (vector), lexical (BM25), or hybrid retrieval without supplying your own vectors. Requires macOS on Apple silicon; source builds need Xcode with the Metal toolchain.

xcodebuild -downloadComponent MetalToolchain
cargo add zeppelin-embed-text

Open the published default model, ingest, query every leg, and delete:

use zeppelin_embed_text::{
    IngestOptions, Legs, ModelOpenOptions, ModelRef, QueryOptions, TextDocument, TextStore,
};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let store = TextStore::open_model(
        "text-store", &ModelRef::default_model(), ModelOpenOptions::default(),
    )?;
    store.ingest_text(
        &[TextDocument::new(1, 1, "The bronze zeppelin flies above the city.")],
        IngestOptions::default(),
    )?;
    for legs in [Legs::Dense, Legs::Lexical, Legs::Hybrid] {
        let hits = store.query_text("bronze zeppelin", QueryOptions::new(5).with_legs(legs))?;
        println!("{hits:?}");
    }
    store.delete_text(&[1])?; // deletes every chunk of this caller document
    store.close()?;
    Ok(())
}

ModelRef::default_model() uses the published model card at revision d64b817c4021a3f1b9bded3152d9afdf9ac813e7. The first open downloads and verifies the pinned model; subsequent opens reuse the verified cache. Set ModelOpenOptions.cache_dir to override ZE_MODEL_CACHE and the default ~/Library/Caches/zeppelin-embed/models. Set offline: true or ZE_MODEL_OFFLINE=1 to prohibit networking; a cache miss returns TextError::ModelResolution(ModelError::OfflineMiss). ZE_MODEL_ENDPOINT or ModelOpenOptions.endpoint overrides the download endpoint.

MLX keeps a process-global buffer cache, capped at 4 GiB by default during text ingest. On an Apple M3 Max with 128 GiB, a full FiQA ingest (57,638 documents) with the release FP16 default model peaked at about 7.3 GB process footprint (about 112 GB before the cap), with max RSS about 4.8 GB (ZE-528). Override the cap with TextOpenOptions::with_mlx_cache_limit_bytes or ZE_MLX_CACHE_LIMIT_BYTES (bytes), set before the first text open. Invalid values are errors; the first setter in a process wins.

ModelOpenOptions.progress receives synchronous byte counts on the calling thread. Intermediate reports require both at least 64 KiB and at least 100 ms since the last report; each verified file also reports completion. Initial (0, 0) means fetching the manifest. Do not reenter model resolution from the callback.

For a preinstalled bundle, TextStore::open(path, bundle_path, options) remains available. Caller document IDs must fit in 96 bits; a higher revision replaces the previous document and its chunks. See the root text API guide for tower details, download size, and measured performance.

Licensed under GPL-3.0-only.

CI and the local text release gate

.github/workflows/text-ci.yml builds and lints text and FFI with text enabled on hosted macos-14, runs every non-ignored test in both crates, and builds the full graph+text XCFramework to run all Swift TextStoreTests. Rust releases require these checks before publishing either crate.

The dedicated real-model job runs default_model::real_default_model_downloads_verifies_and_reopens_offline and release_tokenizer::release_tokenizer_ids_match_hf_0_19_1_for_both_towers. It downloads through resolve_model from HF, caches ZE_MODEL_CACHE keyed on DEFAULT_MODEL_REVISION, and verifies cache hits. Locally the resolver uses ZE_MODEL_CACHE or ~/Library/Caches/zeppelin-embed/models.

Only the following ignored tests require the local release gate. Run from the repository root outside the sandbox with the named fixtures and native MLX/CoreML available. Historical LEAF/Arctic/FP32 goldens require their original models; substituting the published FP16 default would invalidate the assertions.

Ignored tests Required inputs Local command
Default-model inference Verified HF cache or network cargo test --locked -p zeppelin-embed-text --test default_model real_default_model_downloads_and_answers_queries -- --ignored --exact
LEAF/Arctic parity and placement ZE_TEXT_TEST_BUNDLE_DIR: original LEAF v1.5 pair and Arctic v2 symmetric bundles; LEAF .mlmodelc beside them or ZE_COREML_QUERY_MODEL cargo test --locked -p zeppelin-embed-text --test arch --test placement -- --ignored
clean71 FP32 parity ZE_CLEAN71_PACK, ze-model Python dependencies cargo test --locked -p zeppelin-embed-text --test arctic_query -- --ignored
clean71 CoreML plan and parity ZE_CLEAN71_COREML_MODEL, ZE497_PACK, ZE497_COREML, ZE497_PYTHON cargo test --locked -p zeppelin-embed-text --test clean71_coreml -- --ignored
Release smoke and FP16 document parity HF cache or ZE498_RELEASE; ZE498_PACK, ZE498_PYTHON; ZE_QUERY_COREML unset cargo test --locked -p zeppelin-embed-text --test release -- --ignored
30,001-document maintenance Unsandboxed MLX runtime cargo test --locked -p zeppelin-embed-text --test text_api -- --ignored

model_cache::measure_large_cache_open is an ignored manual benchmark, not a correctness gate: cargo test --locked -p zeppelin-embed-text --test model_cache measure_large_cache_open -- --ignored --exact.