Embedders — the opt-in RAG-corpus vector augmentation¶
The Embedder is an opt-in Export augmentation (ADR-0017): a corpus Export names an Embedder
Provider in its config['embedder'], and every exported row gets a fixed-width embedding vector a
vector DB can ingest. Embeddings are never required — a corpus Export with no embedder still
exports its cleaned/chunked/PII-handled text with full Provenance/Classification. The framework names
only the Embedder Capability (a dimension property + embed(texts) -> Iterator[list[float]]);
Providers fulfil it.
The three reference Providers (one Capability, one config line to swap)¶
| Provider | Package | What it is | License (code / weights) | Runs offline in CI |
|---|---|---|---|---|
embedding.hashing |
in-core | Deterministic, dependency-free token-hash bag-of-words (the CPU reference — not semantic) | Apache-2.0 / — | yes (real) |
embedding.sentence_transformers |
latence-embedder-st |
Learned in-process semantic embedder over sentence-transformers, default IBM Granite Embedding r2 — GPU tier granite-embedding-311m-multilingual-r2 (768-dim, bf16+FA2), CPU tier granite-embedding-97m-multilingual-r2 (384-dim, fp32) |
Apache-2.0 / Apache-2.0 | no (heavy dep; verified against a stub, real weights on a rig) |
embedding.endpoint |
latence-embedder-endpoint |
Any OpenAI-compatible / vLLM / Triton /embeddings endpoint (the served performance path) |
Apache-2.0 / — (calls a user endpoint) | no (endpoint; verified against a stub) |
Swapping is a one-line config change on the corpus Export (ADR-0007):
- name: export_corpus
capability: export
provider: export.jsonl_parquet
depends_on: [chunk] # or [redaction] for a PII-handled corpus
config:
basename: corpus
embedder:
provider: embedding.sentence_transformers # was: embedding.hashing
config:
# GPU tier (default): Granite r2 311m, Apache-2.0, 768-dim, bf16 + flash_attention_2.
model: ibm-granite/granite-embedding-311m-multilingual-r2
dimension: 768 # validated against the loaded model
device: cuda # bf16 auto on cuda (perf seam)
attn_implementation: flash_attention_2 # -> sdpa if flash_attn absent / load raises
# CPU tier: model: ibm-granite/granite-embedding-97m-multilingual-r2, dimension: 384, device: cpu
Granite r2 model-card convention (latence-embedder-st)¶
The default is IBM Granite Embedding r2 (Apache-2.0, ModernBERT-based, single-vector dense,
32,768-token context, 200+ languages). It needs NO instruction/query-document prefix — text is
encoded directly, unlike the e5 family's query:/passage:. So the default prefix is "". The
Provider passes normalize_embeddings=True so every exported vector is unit-length (cosine
convention, ADR-0017 uniform column). The GPU tier (granite-embedding-311m-multilingual-r2, 768-dim)
loads bf16 + flash_attention_2 with a graceful sdpa fallback (W8 perf seam); the CPU tier
(granite-embedding-97m-multilingual-r2, 384-dim) loads fp32 + sdpa. intfloat/multilingual-e5-small
(MIT, needs prefix: "passage: ") and sentence-transformers/all-MiniLM-L6-v2 (Apache-2.0) remain
documented tiny fallbacks — not the default. Cards:
https://huggingface.co/ibm-granite/granite-embedding-311m-multilingual-r2 and
https://huggingface.co/ibm-granite/granite-embedding-97m-multilingual-r2. See ADR-0045.
Bake-off¶
matrix/embed.yaml (stage: embedding, stage_name: export_corpus) compares the embedders by
swapping only the corpus Export's embedder, holding every other Stage constant. On a CPU-only host the
embedding.hashing row runs for real (measured, deterministic) and the learned/served candidates are
skipped-with-flag through the same select_device seam — never a fabricated number (#64). Run it
with latence bake-off matrix/embed.yaml.
Offline / CI discipline (learned + endpoint Providers)¶
The heavy/endpoint Provider packages are installed --no-deps in the CPU-first, offline test env
(ADR-0007/0016); their tests monkeypatch the heavy dep (SentenceTransformer / the openai client)
with a deterministic fake, and each ships a real path gated on the dep being importable (skipped
offline, run where the model/endpoint exists). The Provider Conformance suite verifies them against a
stub and flags the row conformance-verified against stub; live numbers need a rig.