feat(embeddings): implement /v1/embeddings on the OpenAI-compatible adapter (#40) - #1714
Merged
Conversation
…dapter (#40) Routes continuum's neural recall embeddings through the unsloth gateway's OpenAI-compatible /v1/embeddings — the first half of #40 ("embeddings → unsloth"). The cognition NeuralEmbeddingProvider already calls adapter.create_embedding(); until now the OpenAICompatibleAdapter inherited the trait's default Err ("does not support embeddings"), so every neural embed silently degraded to the lexical fallback. This implements it. - create_embedding(): POSTs /v1/embeddings (same base_url / Bearer-auth / error-surfacing shape as generate_text). Degrades to Err — never panics — on an unreachable endpoint or non-embedding model, so recall falls back to the lexical embedder rather than crashing. - supports_embeddings now true for "unsloth" as well as "openai" (the gateway exposes OpenAI-compatible /v1/embeddings). - The model is required (no silent default among chat models, [[no-fallbacks-ever]]) — it IS the embedding-space identity the cache keys on. Pure helpers, TDD'd apart from the HTTP I/O: - build_embedding_body() — single → string, batch → array - parse_embedding_response() — orders vectors by the response `index` field (the spec does not guarantee input order; mis-ordering silently misaligns every vector with its source text), errors on missing data instead of fabricating a vector - parse_embedding_usage() — usage is observability, defaults to 0, never fails 5 new unit tests cover all of the above. This does NOT yet swap the live default off fastembed or delete the ort/fastembed embedder — that's the follow-up "trim" half of #40, which requires migrating the legacy sync memory/ consumers onto this async path. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Routes continuum's neural recall embeddings through the unsloth gateway's
OpenAI-compatible
/v1/embeddings— the first half of #40 ("embeddings → unsloth").The cognition
NeuralEmbeddingProvideralready callsadapter.create_embedding(),but the
OpenAICompatibleAdapterinherited the trait's defaultErr("does notsupport embeddings") — so every neural embed silently degraded to the lexical
fallback. This implements it.
How
create_embedding()— POSTs/v1/embeddingsusing the same base_url /Bearer-auth / error-surfacing shape as
generate_text. Degrades toErr(never panics) on an unreachable endpoint or non-embedding model, so recall
falls back to the lexical embedder rather than crashing.
supports_embeddingsnow true for"unsloth"as well as"openai".embedding-space identity the content-addressed cache keys on.
Pure helpers, TDD'd apart from HTTP I/O:
build_embedding_body()— single → string, batch → arrayparse_embedding_response()— orders vectors by the responseindex(the spec doesn't guarantee input order; mis-ordering silently misaligns every
vector with its source text), errors on missing
datainstead of fabricatingparse_embedding_usage()— usage is observability, defaults to 0, never fails5 new unit tests.
Scope
This does not yet swap the live default off fastembed or delete the
ort/fastembedembedder — that's the follow-up trim half of #40, whichneeds the legacy sync
memory/consumers migrated onto this async path. (Note:ortitself stays regardless — Piper TTS / Moonshine STT / Silero VAD depend onit; its retirement is #41.)
🤖 Generated with Claude Code