ef.embedder_adapters¶
Concrete Embedder adapters and the DI seam.
Adapters are lazily-imported factory functions — heavy dependencies
(openai, sentence-transformers) are imported inside the factory, never
at module load, and live in optional extras. Importing this module costs only
numpy + the stdlib.
openai_embedder()— OpenAI embeddings (sync + the async Batch API). Needsef[openai].sentence_transformers_embedder()— local PyTorch models. Needsef[sentence-transformers].http_embedder()— any remote HTTP embedding service (TEI, infinity, …). Stdlib-only.cohere_embedder(),voyage_embedder(),gemini_embedder()— the Cohere / Voyage / Gemini hosted embedding APIs, spoken over their REST endpoints directly. Stdlib-only (no SDK dependency); each needs only an API key. The whole point of these adapters is translating the canonicalInputTypevocabulary to the vendor’s own task name.as_embedder()— the single dependency-injection seam: turns a string (model name /openai:/cohere:/voyage:/gemini:prefix / URL), a bare callable, or an existing embedder into anEmbedder.
The canonical task vocabulary (InputType) is
translated to each vendor’s own name at the adapter boundary — that
translation is the whole point of having adapters.
Example — the DI seam in action (no network / no heavy deps needed):
>>> import numpy as np
>>> from ef.embedders import Embedder
>>> e = as_embedder(lambda ts: np.ones((len(ts), 5)), model_id='ones@5')
>>> isinstance(e, Embedder)
True
>>> e(['x', 'y']).shape
(2, 5)
>>> as_embedder(e) is e # an Embedder passes straight through
True
Functions
|
Build an OpenAI-embeddings |
|
Build a local sentence-transformers |
|
Build an |
|
Build a Cohere-embeddings |
|
Build a Voyage AI |
|
Build a Google Gemini |
|
Normalize |
- ef.embedder_adapters.as_embedder(x, **kwargs)[source]¶
Normalize
xinto anEmbedder— the DI seam.The single place every
efentry point coerces a user-supplied embedder argument. Accepts, in order:an existing
Embedder— returned unchanged;a URL string (
http:///https://) —http_embedder();a provider-prefixed string —
"openai:<model>","cohere:<model>","voyage:<model>"or"gemini:<model>"— the matching hosted-API adapter;the bare string
"hashing"— the dependency-freeHashingEmbedder(ef’s zero-install default);an
"st:<model>"string, or any other bare model name —sentence_transformers_embedder()(the local neural default);a bare callable — wrapped in
FunctionEmbedder(theimbed-embedder bridge).
Extra
**kwargsare forwarded to the chosen factory.>>> import numpy as np >>> e = as_embedder(lambda ts: np.zeros((len(ts), 2)), model_id='zero@2') >>> type(e).__name__ 'FunctionEmbedder'- Return type:
- ef.embedder_adapters.cohere_embedder(model='embed-v4.0', *, dim=None, api_key=None, batch_size=96, timeout=60.0)[source]¶
Build a Cohere-embeddings
Embedder.Talks to Cohere’s
/v2/embedREST endpoint directly — nocohereSDK, no extra dependency. Cohere’s v3+ models require a task hint; this adapter supplies one for every canonicalInputTypeand defaults to the document role when none is given.- Parameters:
model (
str) – A Cohere embedding model name.dim (
int|None) – Matryoshka-truncated width (embed-v4.0only). Omit for the model’s native width. The dim is part of the embedder’s identity — set it once here, not per call.api_key (
str|None) – Cohere API key. Falls back toCO_API_KEY/COHERE_API_KEY.batch_size (
int) – Texts per request (capped at Cohere’s 96 limit).timeout (
float) – Per-request timeout in seconds.
- Return type:
- Returns:
An
Embedderover the Cohere API.
- ef.embedder_adapters.gemini_embedder(model='gemini-embedding-001', *, dim=None, api_key=None, batch_size=100, timeout=60.0)[source]¶
Build a Google Gemini
Embedder.Talks to the Generative Language
batchEmbedContentsREST endpoint directly — nogoogle-genaiSDK, no extra dependency.- Parameters:
model (
str) – A Gemini embedding model name (a leadingmodels/is tolerated and stripped).dim (
int|None) – Matryoshka-truncated width (gemini-embedding-001only). Omit for the model’s native width. Note that Gemini, unlike OpenAI, does not re-normalize MRL-truncated output — a truncated embedder therefore reportsnormalized=False.api_key (
str|None) – Gemini API key. Falls back toGEMINI_API_KEY/GOOGLE_API_KEY.batch_size (
int) – Texts per request (capped at Gemini’s 100 limit).timeout (
float) – Per-request timeout in seconds.
- Return type:
- Returns:
An
Embedderover the Gemini API.
- ef.embedder_adapters.http_embedder(url, *, model_id=None, dim=None, normalized=False, batch_size=64, headers=None, timeout=30.0, payload_builder=<function _tei_payload>, response_parser=<function _tei_parse>)[source]¶
Build an
Embedderover a remote HTTP service.Defaults target the Text-Embeddings-Inference / infinity shape (a POST of
{"inputs": [...]}returning a JSON list of vectors). For a different service, overridepayload_builderand/orresponse_parser.- Parameters:
url (
str) – The embedding endpoint.model_id (
str|None) – Vector-identity string (defaults to"http:<url>").dim (
int|None) – Output width; inferred from the first response if omitted.normalized (
bool) – Whether the service returns unit vectors.batch_size (
int) – Texts per request (used with length-sorted batching).headers (
dict[str,str] |None) – Extra HTTP headers (e.g. an auth token).timeout (
float) – Per-request timeout in seconds.payload_builder (
Callable[[Sequence[str]],bytes]) –texts -> request body bytes.response_parser (
Callable[[Any],Any]) –decoded JSON -> array-like (n, dim).
- Return type:
Uses only the stdlib — no extra dependency.
- ef.embedder_adapters.openai_embedder(model='text-embedding-3-small', *, dim=None, api_key=None, client=None, batch_size=2048, poll_interval=30.0)[source]¶
Build an OpenAI-embeddings
Embedder.- Parameters:
model (
str) – An OpenAI embedding model name.dim (
int|None) – Matryoshka-truncated output width (text-embedding-3-*only). Omit for the model’s native dimension. The dim is part of the embedder’s identity — set it once here, not per call.api_key (
str|None) – OpenAI API key (else the SDK’s usual env-var resolution).client (
Any|None) – A pre-builtopenai.OpenAIclient (overridesapi_key).batch_size (
int) – Texts per request (capped at OpenAI’s 2048 limit).poll_interval (
float) – Seconds between polls when blocking on a Batch-API job.
- Return type:
- Returns:
An embedder whose
embed_batchuses the async OpenAI Batch API.
Requires the
openaipackage (pip install 'ef[openai]').
- ef.embedder_adapters.sentence_transformers_embedder(model_name='all-MiniLM-L6-v2', *, device=None, normalize=False, batch_size=128, model_path=None, query_prompt=None, document_prompt=None, prompt_names=None, **st_kwargs)[source]¶
Build a local sentence-transformers
Embedder.Instruction-tuned models (bge, gte, e5-instruct, Qwen3-Embedding…) are conditioned per
input_type: pass a literalquery_prompt(and, rarely,document_prompt), or map input types to prompts the model defines itself withprompt_names(e.g.{"query": "query"}for Qwen3-Embedding). Those roles are then advertised inhonored_input_types, and the prompt text is baked intomodel_id. Only trust prompts on genuinely instruction-tuned models; onall-MiniLMthey are expected to be a near no-op. Prefer these over wrapping the adapter inInstructionEmbedder: sentence-transformers knows the prompt’s length, so models that pool without the prompt tokens (INSTRUCTOR, GRIT) stay correct. Needs sentence-transformers >= 2.3.- Parameters:
model_name (
str) – A sentence-transformers model name (also used inmodel_id).device (
str|None) – Torch device ("cuda"/"cpu"/"mps");Noneauto-selects.normalize (
bool) – Whether to L2-normalize outputs. sentence-transformers does not normalize by default — set this truthfully.batch_size (
int) – Encoding batch size (smaller on CPU).model_path (
str|None) – A local filesystem path to load from instead of the hub — for air-gapped use. Loading still recordsmodel_nameinmodel_id.query_prompt (
str|None) – Prompt prepended toinput_type="query"texts (passed asencode(prompt=...)).document_prompt (
str|None) – Prompt forinput_type="document"texts (usually none: the asymmetric pattern leaves documents bare).""means an explicit empty prompt, which stops a model’sdefault_prompt_namefrom being applied to documents.prompt_names (
Optional[Mapping[str,str]]) –{input_type: name}of prompts defined in the model’s ownpromptsconfig (passed asencode(prompt_name=...)). An explicitprompt=/prompt_name=in a call overrides both.**st_kwargs (
Any) – Forwarded to theSentenceTransformerconstructor.
- Return type:
Requires
sentence-transformers(pip install 'ef[sentence-transformers]').
- ef.embedder_adapters.voyage_embedder(model='voyage-3.5', *, dim=None, api_key=None, batch_size=1000, timeout=60.0)[source]¶
Build a Voyage AI
Embedder.Talks to Voyage’s
/v1/embeddingsREST endpoint directly — novoyageaiSDK, no extra dependency. Voyage embeddings are L2-normalized. Voyage distinguishes onlyqueryfromdocument; aclassificationorclusteringhint is simply not sent.- Parameters:
model (
str) – A Voyage embedding model name.dim (
int|None) – Matryoshka-truncated width (thevoyage-3.5family andvoyage-code-3only). Omit for the model’s native width.api_key (
str|None) – Voyage API key. Falls back toVOYAGE_API_KEY.batch_size (
int) – Texts per request (capped at Voyage’s 1000 limit).timeout (
float) – Per-request timeout in seconds.
- Return type:
- Returns:
An
Embedderover the Voyage API.