default and deep, and one profile can start from another profile’s results and re-rank them, within one time and cost budget.
Short names and full names
A retrieval plugin is the plugin that answers searches. Each profile it declares has a full name, the plugin’s id and the profile joined by a slash:core.retrieve/default. Clients usually send a short name, such as deep, and the deployment maps each short name to one full name. A search that names no profile uses default.
Two plugins can each declare a profile called deep, and they are different profiles:
core.retrieve ships with Quivr, and the make dev stack pins it: it lists it in Quivr’s startup configuration, which is how a deployment installs a plugin. Quivr’s API refuses to start without a pinned retrieval plugin. jev.rerank is optional. Pinning it beside core.retrieve makes a map of short names required, and deep means Jev only if that map says so.
A short name goes through the deployment’s map; a full name goes straight to its profile. Example deployment mapping, with Jev installed:
In words: Quivr looks up a short name in the deployment’s map. In this example, default reaches core.retrieve/default and deep reaches jev.rerank/deep. A full name skips the map, so core.retrieve/deep, which has no short name left, is reached by its full name.
How a deployment chooses
The map isretrieval.profiles in the startup configuration. This one makes deep mean Jev:
QUIVR_CONFIG (excerpt)
- One retrieval plugin and no map: its own profile names are the short names. It must declare
default. - Several retrieval plugins: the map is required and must contain
default. Each target must be a profile of an installed retrieval plugin. - Full names always work, including for profiles that no short name maps to.
See and call the profiles
GET /v0/search/profiles lists every installed profile, the one default maps to first. It needs a key with search:query. The make dev stack pins only core.retrieve and no map, so there deep is core.retrieve/deep:
aliases holds the short names that select a profile, and is empty for a profile reachable only by its full name. Each item also has name, the plugin’s own name for the profile: with Jev mapped, two items are named deep, and only jev.rerank/deep has deep in its aliases.
To call a profile, put either name in the search’s profile field, "profile": "deep" or "profile": "core.retrieve/deep". The response’s retrieval_profile.name echoes the name you sent, and usage.profiles lists the full name of each profile that ran. Choose a profile in the Search guide runs both. A name that maps to nothing is refused with 422 unsupported_profile.
One profile building on another
A profile can ask Quivr for another profile’s ranked results and re-rank them.jev.rerank/deep does this: it asks for core.retrieve/default’s hybrid results, which combine keyword and meaning matches, then sends each passage and the query to Jev, a paid model from TypeSafe that scores how well the passage answers. To find meaning matches, Quivr first turns the query into a vector with the ingestion plugin, the plugin that made the passages’ vectors.
Quivr runs the inner profile itself, so neither plugin sees a passage the caller may not read:
In words:
- Your app searches with
profile: deep, which the map resolves tojev.rerank/deep. - Quivr sends Jev the query and the time and cost left. Jev asks for the top results of
core.retrieve/defaultin hybrid mode, whatevermodeyour search sent. Itscandidate_countsetting sets how many: 30 by default. - Quivr runs
core.retrieve/defaultwith the same query, Corpora, filter and access. Quivr has the ingestion plugin encode the query, queries the index, drops passages the caller may not read or that were withdrawn, and reads the rest from storage. - Quivr hands Jev that ranking with each passage’s text and score. Jev scores the passages with the Jev model and returns its ranking and what it spent, or the hybrid order when it cannot score.
- Quivr returns the results.
usage.elapsed_msreports the whole search’s elapsed time, andusage.profileslists each profile’s rounds, paid calls and cost. Quivr does not report time per profile.
Time and cost budgets
Each profile declares a latency objective,max_latency_ms, and the most a search may spend on paid calls, max_cost_cents. The profile list shows both.
- The objective is a target, not a cutoff. A slower search still answers and is counted as over its objective. Quivr stops a search only at its hard limit, four times the objective, between 2 and 9 seconds. Past it, the search fails with
504 search_deadline_exceeded, or503 search_unavailablewhen the time ran out while Quivr served candidates. - The outer profile’s limit covers the chain. A
jev.rerank/deepsearch, inner profile included, has 9 seconds: four times 3 seconds, capped at 9. The inner profile gets the time left or its own hard limit, whichever is shorter: 2 seconds forcore.retrieve/default. - Spending counts at every level. Each plugin reports only its own paid calls. Quivr adds them up in
usage.paid_callsandusage.cost_cents, and lists each profile’s own share inusage.profiles, outer first. Inner spending counts against the inner profile’s allowance and the outer one’s. A plugin on Plugin API 0.12 or later receives the time and cost left each round, and a reported spend over an allowance fails the search with502 retrieval_plugin_invalid.
When Jev returns hybrid results
If hybrid retrieval succeeds and the Jev plugin can respond, the Jev plugin handles errors from the Jev model itself and returnscore.retrieve/default’s hybrid order instead of failing the search. This covers a missing TypeSafe key, provider errors, invalid answers, and a deadline or cost left too small for a call. Each hit’s explanation field then reads re-ranker unavailable: <reason> instead of Jev’s probability; without a key, the reason is API key not configured.
Retrieval or plugin outages can still fail the search: a Jev plugin that is down or unreachable, or an ingestion plugin that cannot encode the query, returns 503 search_unavailable.
Without a key, there is no paid call and no reported cost. With a key, a failed paid attempt can still report cost: an attempt that fails without usage from the provider reports a reserved upper-bound cost, not an invoice.
What composition does not do
- No automatic stacking. A profile builds on another only when its plugin declares that dependency in its manifest and asks for it. Mapping
deepto Jev does not changedefaultorcore.retrieve/deep. - Two levels at most. A profile that builds on another cannot itself be built on, and a chain cannot loop. Quivr refuses a missing or invalid dependency when the plugin is installed or activated.
- No wider access. The inner profile runs with the caller’s Corpora, filter and access. The outer and inner retrieval profiles use the same snapshot of retrieval plugin versions, even if an activation happens during the search.
Next
Re-rank with Jev
Run the Jev plugin beside core.retrieve and map deep to it.
Write a retrieval plugin
Declare profiles and start from another plugin’s ranking.