ExAgent.Providers.JinaRerankerM0 (ExAgent v0.4.1)

Copy Markdown View Source

jina-reranker-m0 - a reranking-only provider for a self-hosted server.

provider = ExAgent.Providers.JinaRerankerM0.new(base_url: System.fetch_env!("RERANKER_URL"))

{:ok, result} = ExAgent.rerank(provider, "who restarts processes?", chunks, top_n: 5)

best = ExAgent.Reranking.take(result, chunks)

It implements ExAgent.Provider.rerank/4 only. chat/3 returns {:error, %ExAgent.Error{type: :unsupported}}, and there is no embed/3 - a reranker scores query/document pairs and has no single-text vector to give.

Where it belongs in retrieval

Reranking is the second stage, not a replacement for the first:

{:ok, hits} = ExAgent.embed(embedder, [query], task: :retrieval, args: [prompt_name: :query])
shortlist = vector_search(hits, limit: 100)

{:ok, ranked} = ExAgent.rerank(reranker, query, shortlist, top_n: 10)

Embeddings compare vectors computed independently, which is what makes them fast enough for a corpus. A cross-encoder reads the query and one document together - more accurate, and far too slow to run over everything. Batches are capped at 512 documents, which is the shape of the intended use.

Behind Modal's proxy auth

ExAgent.Providers.JinaRerankerM0.new(
  base_url: System.fetch_env!("MODAL_RERANKER_URL"),
  api_key: System.fetch_env!("MODAL_API_KEY"),
  headers: [
    {"Modal-Key", System.fetch_env!("MODAL_KEY")},
    {"Modal-Secret", System.fetch_env!("MODAL_SECRET")}
  ]
)

Scores

Higher is more relevant, and that is the only guarantee - see ExAgent.Reranking on why an absolute cutoff does not port between models.

The server contract

Verified against a running deployment. POST {base_url}/v1/rerank:

{"query": "...", "documents": ["..."], "top_n": 5, "return_documents": false}

answering

{"model": "...",
 "results": [{"index": 0, "relevance_score": 0.28, "document": {"text": "..."}}]}

Unknown body fields are rejected by the server, so unrecognized options are reported rather than forwarded. return_documents defaults to true there and false here: :index already identifies each document, and sending a corpus back to have it re-quoted is waste.

This is not the shape of Jina's hosted api.jina.ai/v1/rerank service, whose documents accept {"text": ...} / {"image": ...} objects for multimodal ranking. Pointing this provider there will not work.

Summary

Functions

Creates a provider with validated options and an initialized Req client.

Types

t()

@type t() :: %ExAgent.Providers.JinaRerankerM0{
  api_key: String.t() | nil,
  base_url: String.t(),
  headers: [{String.t(), String.t()}],
  model: String.t(),
  receive_timeout: pos_integer(),
  req: Req.Request.t() | nil
}

Functions

new(opts)

@spec new(keyword()) :: t()

Creates a provider with validated options and an initialized Req client.

Options

  • :base_url (String.t/0) - Required. Root URL of the reranker; requests go to #{base_url}/v1/rerank

  • :api_key - Sugar for an Authorization: Bearer header The default value is nil.

  • :model (String.t/0) - Sent in the request body and recorded on the result The default value is "jina-reranker-m0".

  • :headers (list of term/0) - Extra request headers, e.g. Modal's Modal-Key / Modal-Secret The default value is [].

  • :receive_timeout (pos_integer/0) - Milliseconds to wait for the response, per call; override per request with receive_timeout: on rerank/4 The default value is 300000.