open-standards/jouleclaw/jouleclaw-rs/crates/jouleclaw-embed-api
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Transaction Science 732c0079cf jouleclaw: TEI embeddings + rerank backends
HuggingFace Text Embeddings Inference (TEI) is the canonical
local server for embeddings + cross-encoder rerank, supporting
any model whose architecture TEI handles (which is most of
them — TEI gets a new architecture in weeks, not quarters).
Closes the gap for models neither jouleclaw-embed-candle (Bert
only) nor jouleclaw-llm::ollama can serve, including NV-Embed-v2
+ bge-reranker-v2-m3 + GTE-Qwen2.

NEW

jouleclaw-embed-api:
  TeiTransport          sync trait, post_tei(url, api_key,
                        body). Optional bearer — None for
                        self-hosted, Some(key) for HF Inference
                        Endpoints.
  TeiEmbedBackend       POST <base>/embed
    new(transport, base_url)            self-hosted, no auth
    hf_endpoint(transport, url, key)    HF Inference Endpoints
    embed(text) -> Vec<f32>
    embed_batch(texts) -> Vec<Vec<f32>>
  parse_tei_shape       handles TEI's top-level array shape
                        ([[f32, ...], ...]) and the error
                        envelope ({error, error_type}).

jouleclaw-rerank-api:
  TeiTransport          parallel trait surface in this crate
                        (kept separate from the embed crate's
                        trait of the same name so consumers
                        don't get a cross-crate dependency).
  TeiRerankBackend      POST <base>/rerank
    new(transport, base_url)
    hf_endpoint(transport, url, key)
    rerank(query, documents, top_n) -> Vec<(usize, f32)>
  parse_results_tei     handles TEI's [{index, score}] shape
                        (and accepts `relevance_score` as an
                        alias since some TEI builds emit it).

WIRE FORMAT

  embed request:
    POST <base>/embed
    body: { "inputs": ["text", ...] }
  embed response:
    [[f32, ...], ...]

  rerank request:
    POST <base>/rerank
    body: { "query": "...", "texts": [...], "top_n": N? }
  rerank response:
    [{"index": N, "score": f32}, ...]

  errors: { "error": "<message>", "error_type": "..." }
          → EmbedApiError::Upstream(message)
          → RerankApiError::Upstream(message)

MODELS THIS NOW COVERS

Embed (via TEI):
  - BAAI/bge-large-en-v1.5
  - BAAI/bge-m3 (multilingual, dense)
  - nvidia/NV-Embed-v2          (decoder-style — not in candle)
  - intfloat/e5-mistral-7b-instruct
  - Alibaba-NLP/gte-Qwen2-7B-instruct (decoder-style)
  - Qwen/Qwen3-Embedding-0.6B/4B/8B   (when TEI ships support)
  - sentence-transformers/all-MiniLM-L6-v2
  - jinaai/jina-embeddings-v3
  - mxbai-embed-large-v1

Rerank (via TEI):
  - BAAI/bge-reranker-v2-m3        (xlm-roberta — not in candle)
  - BAAI/bge-reranker-large
  - cross-encoder/ms-marco-MiniLM-L-6-v2 / L-12-v2
  - mixedbread-ai/mxbai-rerank-large-v1
  - jinaai/jina-reranker-v2-base-multilingual

OPERATIONAL STATE — L2 + L2.5 + L3 + L3.5 NOW ALL HAVE FULL
LOCAL + CLOUD COVERAGE

  L2 embeddings:
    - jouleclaw-embed-candle           Bert family in-process
    - jouleclaw-embed-api::Ollama*     local Ollama, GGUF
    - jouleclaw-embed-api::Tei*        local TEI, any TEI model
    - jouleclaw-embed-api::OpenAi*     cloud
    - jouleclaw-embed-api::Voyage*     cloud
    - jouleclaw-embed-api::Cohere*     cloud
    - jouleclaw-embed-api::Jina*       cloud

  L2.5 rerank:
    - jouleclaw-rerank-candle          Bert family in-process
    - jouleclaw-rerank-api::Tei*       local TEI, any TEI model
    - jouleclaw-rerank-api::Cohere*    cloud
    - jouleclaw-rerank-api::Voyage*    cloud
    - jouleclaw-rerank-api::Jina*      cloud

  L3 LLM:
    - jouleclaw-llm::ollama            local Ollama, GGUF (text +
                                       vision attachments)
    - jouleclaw-llm::openai_compatible cloud + local OpenAI-shape
                                       (text + image + audio
                                       attachments)
    - jouleclaw-llm::anthropic         Claude (text + image)
    - jouleclaw-llm::gemini            Gemini (text + image + audio)

  L3.5 fresh retrieval:
    - jouleclaw-fresh::providers       Jina Reader / Jina Search /
                                       Wikipedia / arXiv / Crossref
                                       / OpenAlex / Brave / Tavily /
                                       Exa / Serper

14 new tests (6 embed-api + 7 rerank-api + 1 reused stable-sort
helper) cover: self-hosted no-auth path; HF Inference Endpoints
bearer-auth path; embed top-level array parsing; rerank
[{index, score}] parsing; top_n omitted when None; relevance_score
alias accepted; error envelope mapping; non-JSON mapping;
empty-input + empty-documents guards.

Total: jouleclaw-embed-api 32 tests, jouleclaw-rerank-api 19
tests. cargo check --workspace --all-targets clean.

Co-Authored-By: Claude Opus 4.7 <[email protected]>
2026-06-06 17:16:53 -04:00
..
src jouleclaw: TEI embeddings + rerank backends 2026-06-06 17:16:53 -04:00
Cargo.toml jouleclaw: jouleclaw-embed-api + jouleclaw-rerank-api 2026-06-06 11:00:36 -04:00