0078: Jina Retrieval-Provider Wire Mapping (rerank + embedding)¶
- Status: Accepted
- Author: Chris Colinsky
- Created: 2026-06-21
- Accepted: 2026-06-22
- Targets: spec/retrieval-provider/spec.md §8 Wire-format mappings (the section introduced by
0077) — add §8.2 Jina covering
/v1/rerankand/v1/embeddingson the hosted Jina API, and realizing 0077'sinput_typeknob via Jina's native wiretaskparameter. No protocol change (theinput_typefield and the §8 section are both 0077's); no renumber (§8.2 appends after §8.1 TEI). Plus new conformance fixtures underspec/retrieval-provider/conformance/. This proposal also corrects the §2return_documentsparenthetical (text from 0060) in the same spec edit — Jina's wire default istrue, notfalse(see Note on 0060); the factual fix is folded into this proposal's accept, not a separate PATCH. - Related: 0077 (introduces §8 Wire-format mappings + §8.1 TEI + the
input_typeknob this reuses — 0078 depends on 0077 and is accepted after it), 0059 (embedding protocol), 0060 (rerank protocol — Jina/v1/rerankrealizes it near 1:1), 0037 / 0038 (llm-provider per-vendor wire-mapping precedent) - Supersedes:
Summary¶
The second retrieval-provider wire mapping (after 0077's TEI), and the first hosted-vendor one:
Jina AI's /v1/rerank and /v1/embeddings. Three things make it a tight follow-on to 0077:
-
Jina rerank maps almost 1:1 onto 0060. 0060's
RerankProvidershapes were modeled on the hosted-vendor wire (Cohere / Voyage / Jina), and Jina is the closest fit: request{model, query, documents, top_n, return_documents}and response{results: [{index, relevance_score, document?}], usage: {total_tokens}}line up directly with 0060'squery/documents/top_k/return_documents/results/ScoredDocument{index, relevance_score, document}. No client-side batch chunking (Jina is hosted and batches server-side — the mandatory chunk-and-stitch was a TEI-specific concern). -
It realizes 0077's
input_typeon a wire parameter — the cross-vendor payoff. Where TEI realizedinput_typevia a server-sideprompt_name, Jina realizes it via its nativetaskfield (input_type="query"→task="retrieval.query";"document"→task="retrieval.passage"). Same declaredEmbeddingRuntimeConfig.input_typeknob (0077), a second wire realization — demonstrating the knob was correctly placed on the protocol, not in a single mapping. -
Hosted-vendor construction. Unlike self-hosted TEI (per-deployment
base_url), Jina is one hosted API (https://api.jina.ai) reached with aBearerAPI key; the provider binds the API key - the bound model, with
base_urldefaulting to the Jina endpoint (override for proxies / private gateways). A JinaEmbeddingProviderand a JinaRerankProviderremain distinct instances (one model each), but share the one hosted endpoint.
Motivation¶
Completes the rerank/embed mapping catalog across the self-hosted ↔ hosted axis. 0077 lands the self-hosted runtime (TEI); 0078 lands a major hosted vendor (Jina), giving adopters a clean OA-native path whether they self-host or call a managed API — the retrieval-provider analogue of llm-provider covering both the OpenAI-compatible §8.1 surface and the hosted Anthropic / Gemini §8.2 / §8.3 mappings.
Proves the input_type knob generalizes. A cross-vendor knob justified by "Cohere / Voyage / Jina
all have it" should be demonstrated on at least one hosted vendor's wire, not only TEI's client-side
prefix. Jina's task is that demonstration, and it is the idiomatic, server-side realization the
hosted vendors share.
Jina is a first-class retrieval vendor. Jina ships both a competitive reranker family
(jina-reranker-v2 / -v3, multilingual) and a strong asymmetric embedding family
(jina-embeddings-v3 / -v4 / -v5, with task-driven query/passage representations and Matryoshka
dimensions) — exactly the two-stage retrieval surface 0059 / 0060 target.
Proposed change¶
Add §8.2 Jina to the §8 Wire-format mappings section (0077). Jina's gen_ai.system identifier
is "jina" (per the observability §5.5.8 / §5.5.13 "identify the wire surface, not the model
developer" convention). Wire shapes below were verified against the Jina OpenAPI on 2026-06-21;
the verified versions are recorded in docs/compatibility.md at Accept.
- Construction. A Jina provider instance binds an API key (sent as
Authorization: Bearer <key>) + the bound model identifier (§3 / §5 per-instance binding), withbase_urldefaulting tohttps://api.jina.ai(override for a proxy / private gateway). A JinaEmbeddingProvider(/v1/embeddings) and a JinaRerankProvider(/v1/rerank) are distinct instances (one model each) sharing the hosted endpoint. /v1/rerank—POST {base_url}/v1/rerankwith{"model": str, "query": str, "documents": [str], "top_n"?: int, "return_documents": <bool>, "truncation": false}. Maps onto 0060:documents←documents,top_n←top_k,return_documents← theRerankRuntimeConfig.return_documentsvalue (sent explicitly — see Note on 0060). Response{model, usage: {total_tokens}, results: [{index, relevance_score, document?}]}maps onto 0060'sresults(index→ScoredDocument.index,relevance_score→relevance_score,document→document);usage.total_tokens→RerankUsage.input_tokens(Jina meters rerank by tokens, not search units). Results are returned ranked, but the mapping applies 0060's "sort if the provider didn't" invariant regardless./v1/embeddings—POST {base_url}/v1/embeddingswith{"model": str, "input": [str], "task"?: str, "dimensions"?: int, "truncate": false}.input_typerealization: the mapping sets Jina's nativetaskfrominput_type—"query"→"retrieval.query","document"→"retrieval.passage"— so Jina applies the model-appropriate query/passage representation server-side;input_typeabsent ⇒taskomitted (Jina's model default). The mapping recognizes a closedinput_typeset (query/documentonly); an unrecognized value is a pre-sendprovider_invalid_request(§7), and Jina's non-retrieval tasks (text-matching/classification/separation) are reached via the extras-pass-through bag (ataskpassthrough), notinput_type— wideninginput_type's normative value space is a protocol-level (0077) change, deferred until a consumer needs it.EmbeddingRuntimeConfig.dimensions→ Jina'sdimensions(Matryoshka truncation) when set. Response{model, usage, data: [{index, embedding}]}→ theEmbeddingResponsevectors in input order.truncation/truncate(fail-loud). Jina names the flagtruncationon/v1/rerankandtruncateon/v1/embeddings(vendor inconsistency); the mapping sends the per-endpoint flagfalseso an over-length input errors rather than being silently truncated (consistent with 0077 §8.1's TEI fail-loud posture).- Errors — Jina HTTP failures map to the §7 categories per the shared enumeration:
401→provider_authentication;429(rate limit) /5xx→provider_unavailable; unknown model (422/404) →provider_invalid_model; over-length / malformed request (422) →provider_invalid_request; malformed response →provider_invalid_response.
Note on 0060 (return_documents default)¶
0060 §2 states "Cohere, Voyage AI, Jina AI all expose return_documents defaulting False." Verified
2026-06-21: Cohere and Voyage default false, but Jina's wire return_documents defaults true.
This does not change any normative OA behavior — RerankRuntimeConfig.return_documents still
defaults False (0060) — but the Jina mapping MUST send return_documents explicitly (not rely
on Jina's wire default) so OA's default-False is honored. This proposal folds in the correction:
the editable spec §2 wording is fixed in the same accept that adds §8.2 — 0060's immutable proposal
text is untouched; only the spec's §2 parenthetical changes. Corrected reading: Cohere and Voyage
expose return_documents defaulting false, Jina defaults true, and OA's
RerankRuntimeConfig.return_documents defaults False with mappings sending it explicitly where the
wire default differs.
Conformance test impact¶
New fixtures under spec/retrieval-provider/conformance/ (numbers assigned at Accept; appended after
the 0077 TEI set):
- Jina
/v1/rerankmapping — request carriesAuthorization: Bearer,query,documents,return_documents(explicit),truncation: false; responseresultsassemble to 0060's sort + valid-index invariants;usage.total_tokens→RerankUsage.input_tokens. - Jina
return_documentshonors the OA default — OAreturn_documents=False⇒ the wire request sendsreturn_documents: false(overriding Jina'struewire default);True⇒trueand the echoeddocumentpopulatesScoredDocument.document. - Jina
/v1/embeddingsinput_type→task—input_type="query"⇒ wiretask="retrieval.query";"document"⇒"retrieval.passage"; absent ⇒taskomitted.dimensions→ wiredimensions. - Jina
truncation/truncatefail-loud — an over-length input surfacesprovider_invalid_request.
Versioning¶
MINOR bump (pre-1.0), additive only: §8.2 is a new wire mapping; no protocol surface changes
(input_type and §8 are 0077's), no renumber. The reference implementation gains a Jina embed +
rerank provider (HTTP client + API-key auth + the task realization). Tentative spec version target
deferred to Accept (sequenced after 0077's accept, since §8 must exist first).
Alternatives considered¶
- Rerank-only (defer embed). Reasonable — rerank is the near-1:1 win — but Jina's embedding
family is first-class and its
taskparameter is precisely the secondinput_typerealization that justifies 0077's knob, so covering both in one mapping is higher-value and not much larger. input_type→taskvia the extras bag instead of the declared knob. Reject — defeats the purpose of 0077's declaredinput_type; the whole point is one declared knob realized per mapping.- A dedicated
jina-providercapability. Reject — Jina is a wire mapping of the existingEmbeddingProvider/RerankProvidercontracts, exactly as TEI (§8.1) and the llm-provider §8.2 / §8.3 hosted mappings are. - Relying on Jina's wire defaults (
return_documents,task). Reject — sendreturn_documentsexplicitly (Jina'struedefault disagrees with OA'sFalse) and derivetaskfrominput_type; relying on vendor defaults would silently diverge from the OA contract.
Open questions¶
None remaining at draft time. Both surfaced during drafting are resolved in the §8.2 text above (collected here for retrieval).
Resolved at Draft:
usage.total_tokens→RerankUsage— maps toinput_tokens(rerank has no output tokens, so all tokens are input; Jina meters by tokens, not Cohere-stylesearch_units, which is left unset). NoRerankUsagechange.- Embedding
taskvalue space — the Jina mapping recognizes a closedinput_typeset (query/document→retrieval.query/retrieval.passage); an unrecognized value is a pre-sendprovider_invalid_request(0077's closed-set option). Jina's non-retrieval tasks (text-matching/classification/separation) ride the extras bag (taskpassthrough); wideninginput_type's normative value space is a protocol-level (0077) change, deferred until a consumer needs it.
Out of scope¶
- Multi-modal Jina inputs — Jina accepts image / PDF / video / audio docs (
jina-clip,jina-embeddings-v4/v5omni) andjina-colbertmulti-vector / late-interaction outputs. Text + dense vectors only, per 0059 / 0060. late_chunking,embedding_type(binary / base64 / ubinary),normalized=false— Jina-specific knobs ride the extras-pass-through bag; not declared protocol fields.- Other hosted vendors — Cohere, Voyage AI rerank/embed mappings remain deferred (retrieval-provider
§11 Out of scope); each realizes
input_typeon its own wire.