soev for developers
soev-retrievalReference

soev_retrieval.engine

Search one or more vector stores, combine the results, and put your own rules around a store.

The searches are written once over VectorStore, so they work with every store.

A search embeds the query with the embedder of each index, searches each scope, and combines the lists into one ranking.

search_scopes

functionsearch_scopesasync (groups, query, *, limit, combine, alpha=None) -> Sequence[Hit]

Search every group's scopes for query and return one ranking from combine, best first.

Every search names one target of one store. Scopes in one target are one search, which matches any of their filters, so the store scores their hits against each other. An unfiltered scope makes its whole target unfiltered. Lists from different targets or stores meet only in combine, which receives one list per search, in group and scope order. Each search returns at most limit hits. The query is embedded once per group, with the group's own embedder. A group with no scopes embeds and searches nothing. Errors are the store's, as hybrid_search raises them.

Example

from soev_retrieval.domain import DeclaredFilter, SearchScope
from soev_retrieval.engine import Rrf, SearchGroup, search_scopes

hits = await search_scopes(
    [
        SearchGroup(
            store=policy_store,
            scopes=[SearchScope("policies", where=DeclaredFilter("year", "gte", 2020))],
            embed=embed_policy_query,
        ),
        SearchGroup(store=case_store, scopes=[SearchScope("cases")], embed=embed_case_query),
    ],
    "pension transfer rules",
    limit=10,
    combine=Rrf(),
)
paramgroupsSequence[SearchGroup]

The stores to search, each with its scopes and its embedder.

paramquerystr

The query text.

paramlimitint

The maximum number of hits of each search.

paramcombineCombine

The strategy that turns the lists of all searches into one ranking.

paramalphafloat | None
= None

The weight of the vector side for every search, or None for each store's own default.

Returns

Sequence[Hit]

The ranking that combine returns, or no hits when no group has a scope.

Raises:

  • InvalidQueryError: A store rejected a search.
  • StoreUnavailable: A store gave no answer.
  • Unconfigured: A group has no embedder, and its store cannot embed the query.

SearchGroup

dataclassSearchGroup(store, scopes, embed=None)

The scopes one store serves, with the embedder its index was built with (None leaves it to the store).

paramstoreVectorStore

The store that serves the scopes.

paramscopesSequence[SearchScope]

The scopes to search in the store.

paramembedEmbed | None
= None

The embedder of the store's index, or None to leave embedding to the store.

functionhybrid_searchasync (store, target, query, *, limit, alpha=None, vector=None, where=None, embed=None) -> Sequence[Hit]

Return at most limit chunks of target matching query, best first.

The query vector is vector when given, else embed(query) when an embedder is given, else left to the store, which raises Unconfigured if it cannot embed. alpha and where go to the store unchanged. See VectorStore.hybrid for their meaning and the errors raised.

paramstoreVectorStore

The store to search.

paramtargetTarget

The target to search.

paramquerystr

The query text.

paramlimitint

The maximum number of hits.

paramalphafloat | None
= None

The weight of the vector side, or None for the store's own default.

paramvectorSequence[float] | None
= None

The query embedding. When it is given, embed is not called.

paramwhereFilter | None
= None

The filter that restricts the candidates, or None to restrict nothing.

paramembedEmbed | None
= None

The embedder for the query when vector is None.

Returns

Sequence[Hit]

At most limit hits, best first.

Raises:

  • InvalidQueryError: The store rejected the call.
  • StoreUnavailable: The store gave no answer.
  • Unconfigured: No vector and no embedder are given, and the store cannot embed the query.

Embed

type aliasEmbed = Callable[[str], Awaitable[Sequence[float]]]

An async function that embeds one query text into one vector.

Give a search the embedder that the index of its store was built with, so that the query vector and the stored vectors compare.

Combine

protocolCombine

A strategy that turns the query and one ranked list of hits per search into one ranking, best first.

Scores from different searches do not compare (see Hit), so a strategy works from ranks, or rescores every hit on one scale. Hits with the same id are the same chunk and appear once.

search_scopes calls it. Rrf is the stock strategy.

method__call__async (query, ranked, /) -> Sequence[Hit]

Return one ranking of the hits in ranked, best first.

paramquerystr

The query text that the searches answered.

paramrankedSequence[Sequence[Hit]]

One list of hits for each search, each best first.

Returns

Sequence[Hit]

The combined ranking, with each chunk once.

Rrf

dataclassRrf(k=60)

Reciprocal rank fusion: a hit scores the sum of 1 / (k + rank) over the lists it appears in, rank from 1.

Uses ranks only, so lists whose scores do not compare can be fused. Each fused hit carries its fused score and the properties of its first appearance.

paramkint
= 60

The rank constant. It damps the weight of the top ranks: a larger k makes the ranks count more equally.

method__call__async (query, ranked, /) -> Sequence[Hit]

Fuse the lists of ranked into one ranking, best first.

paramquerystr

Not read: the fusion uses ranks only.

paramrankedSequence[Sequence[Hit]]

One list of hits for each search, each best first.

Returns

Sequence[Hit]

Each hit once, with its fused score and the properties of its first appearance, highest score first.

Rules around a store

Each of these classes is a VectorStore over another store. It retries a call, rewrites a filter before the call, or drops results after the call.

Retrying

dataclassRetrying(inner, attempts, backoff=1.0, sleep=asyncio.sleep)

VectorStore over another, calling it up to attempts times while it raises StoreUnavailable.

Waits backoff seconds before the second attempt, doubling before each further one, and raises the last StoreUnavailable when every attempt failed. A rejected call (InvalidQueryError) or an Unconfigured store is raised at once: calling again would get the same answer.

paraminnerVectorStore

The store that answers each call.

paramattemptsint

The maximum number of calls to inner for one call. It must be at least 1.

parambackofffloat
= 1.0

The seconds to wait before the second attempt.

paramsleepCallable[[float], Awaitable[None]]
= asyncio.sleep

What waits. Tests pass a recorder.

Raises:

  • ValueError: When the instance is made: attempts is less than 1.
methodhybridasync (target, *, query, vector=None, limit, where=None, alpha=None) -> Sequence[Hit]

Call inner.hybrid with the same arguments, again while it raises StoreUnavailable.

paramtargetTarget

The target to search.

paramquerystr

The query text.

paramvectorSequence[float] | None
= None

The query embedding, or None to leave embedding to the inner store.

paramlimitint

The maximum number of hits.

paramwhereFilter | None
= None

The filter for the inner store, or None to restrict nothing.

paramalphafloat | None
= None

The weight of the vector side, or None for the default of the inner store.

Returns

Sequence[Hit]

The hits of the first attempt that the inner store answered.

Raises:

  • InvalidQueryError: The inner store rejected the call.
  • StoreUnavailable: The inner store gave no answer in any attempt.
  • Unconfigured: The inner store cannot serve the call.
methodnear_vectorasync (target, *, vector, limit, where=None) -> Sequence[Hit]

Call inner.near_vector with the same arguments, again while it raises StoreUnavailable.

paramtargetTarget

The target to search.

paramvectorSequence[float]

The query embedding.

paramlimitint

The maximum number of hits.

paramwhereFilter | None
= None

The filter for the inner store, or None to restrict nothing.

Returns

Sequence[Hit]

The hits of the first attempt that the inner store answered.

Raises:

  • InvalidQueryError: The inner store rejected the call.
  • StoreUnavailable: The inner store gave no answer in any attempt.
  • Unconfigured: The inner store cannot serve the call.
methodbm25async (target, *, query, limit, where=None) -> Sequence[Hit]

Call inner.bm25 with the same arguments, again while it raises StoreUnavailable.

paramtargetTarget

The target to search.

paramquerystr

The query text.

paramlimitint

The maximum number of hits.

paramwhereFilter | None
= None

The filter for the inner store, or None to restrict nothing.

Returns

Sequence[Hit]

The hits of the first attempt that the inner store answered.

Raises:

  • InvalidQueryError: The inner store rejected the call.
  • StoreUnavailable: The inner store gave no answer in any attempt.
  • Unconfigured: The inner store cannot serve the call.
methodfetchasync (target, *, where=None, limit, order_by=None, descending=False) -> Sequence[Chunk]

Call inner.fetch with the same arguments, again while it raises StoreUnavailable.

paramtargetTarget

The target to read.

paramwhereFilter | None
= None

The filter for the inner store, or None for every chunk.

paramlimitint

The maximum number of chunks.

paramorder_bystr | None
= None

A stored field to sort on, or None for the order of the inner store.

paramdescendingbool
= False

Whether to sort on order_by in descending order.

Returns

Sequence[Chunk]

The chunks of the first attempt that the inner store answered.

Raises:

  • InvalidQueryError: The inner store rejected the call.
  • StoreUnavailable: The inner store gave no answer in any attempt.
  • Unconfigured: The inner store cannot serve the call.
methodfieldsasync (target) -> FieldSpec

Return the field spec of target from the inner store, again while it raises StoreUnavailable.

paramtargetTarget

The target to describe.

Returns

FieldSpec

The field spec of the first attempt that the inner store answered.

Raises:

  • InvalidQueryError: The inner store does not know the target.
  • StoreUnavailable: The inner store gave no answer in any attempt.

PreFiltered

dataclassPreFiltered(inner, rewrite)

VectorStore over another, calling it with every predicate of the filter replaced by what rewrite returns.

rewrite sees the target and each predicate of the filter of each method (the three searches and fetch), wherever it sits in the expression, and the expression around it is kept. It is for an operator the store cannot serve itself: a folder scope (under) resolved through a catalog into the document ids it covers, a name looked up into a key.

A predicate rewritten to NOTHING matches nothing, so its branch of an AnyOf drops out, its AllOf matches nothing, and its Not matches everything. When the whole filter comes to match nothing, the call answers an empty sequence without the inner store being called. Every other argument reaches the inner store unchanged, results come back untouched, and fields passes through. PostFiltered acts on the results instead. The two compose in either order.

paraminnerVectorStore

The store that answers each call.

paramrewriteRewrite

The rule that replaces each predicate.

methodhybridasync (target, *, query, vector=None, limit, where=None, alpha=None) -> Sequence[Hit]

Rewrite and fold where, and call inner.hybrid with it and the other arguments unchanged.

paramtargetTarget

The target to search.

paramquerystr

The query text.

paramvectorSequence[float] | None
= None

The query embedding, or None to leave embedding to the inner store.

paramlimitint

The maximum number of hits.

paramwhereFilter | None
= None

The filter whose predicates rewrite replaces, or None to restrict nothing.

paramalphafloat | None
= None

The weight of the vector side, or None for the default of the inner store.

Returns

Sequence[Hit]

The hits of the inner store, or no hits when the rewritten filter matches nothing.

Raises:

  • InvalidQueryError: The inner store rejected the call.
  • StoreUnavailable: The inner store gave no answer.
  • Unconfigured: The inner store cannot serve the call.
methodnear_vectorasync (target, *, vector, limit, where=None) -> Sequence[Hit]

Rewrite and fold where, and call inner.near_vector with it and the other arguments unchanged.

paramtargetTarget

The target to search.

paramvectorSequence[float]

The query embedding.

paramlimitint

The maximum number of hits.

paramwhereFilter | None
= None

The filter whose predicates rewrite replaces, or None to restrict nothing.

Returns

Sequence[Hit]

The hits of the inner store, or no hits when the rewritten filter matches nothing.

Raises:

  • InvalidQueryError: The inner store rejected the call.
  • StoreUnavailable: The inner store gave no answer.
  • Unconfigured: The inner store cannot serve the call.
methodbm25async (target, *, query, limit, where=None) -> Sequence[Hit]

Rewrite and fold where, and call inner.bm25 with it and the other arguments unchanged.

paramtargetTarget

The target to search.

paramquerystr

The query text.

paramlimitint

The maximum number of hits.

paramwhereFilter | None
= None

The filter whose predicates rewrite replaces, or None to restrict nothing.

Returns

Sequence[Hit]

The hits of the inner store, or no hits when the rewritten filter matches nothing.

Raises:

  • InvalidQueryError: The inner store rejected the call.
  • StoreUnavailable: The inner store gave no answer.
  • Unconfigured: The inner store cannot serve the call.
methodfetchasync (target, *, where=None, limit, order_by=None, descending=False) -> Sequence[Chunk]

Rewrite and fold where, and call inner.fetch with it and the other arguments unchanged.

paramtargetTarget

The target to read.

paramwhereFilter | None
= None

The filter whose predicates rewrite replaces, or None for every chunk.

paramlimitint

The maximum number of chunks.

paramorder_bystr | None
= None

A stored field to sort on, or None for the order of the inner store.

paramdescendingbool
= False

Whether to sort on order_by in descending order.

Returns

Sequence[Chunk]

The chunks of the inner store, or no chunks when the rewritten filter matches nothing.

Raises:

  • InvalidQueryError: The inner store rejected the call.
  • StoreUnavailable: The inner store gave no answer.
  • Unconfigured: The inner store cannot serve the call.
methodfieldsasync (target) -> FieldSpec

Return the field spec of target from the inner store, unchanged.

paramtargetTarget

The target to describe.

Returns

FieldSpec

The field spec that the inner store returns.

Raises:

  • InvalidQueryError: The inner store does not know the target.
  • StoreUnavailable: The inner store gave no answer.

Rewrite

protocolRewrite

The rule that gives the filter to put in the place of one predicate of the caller's filter.

It gets the target and one predicate, and returns the predicate itself, a replacement the inner store can serve, or NOTHING when no chunk could match it.

PreFiltered calls it once for each predicate of each filter.

method__call__async (target, term, /) -> Filter

Return the filter to put in the place of term.

paramtargetTarget

The target that the call named.

paramtermDeclaredFilter

One predicate of the caller's filter.

Returns

Filter

term itself, a filter that the inner store can serve, or NOTHING when no chunk can match term.

PostFiltered

dataclassPostFiltered(inner, keep)

VectorStore over another, returning only what keep returns.

keep sees every result the inner store answered with (Hits from a search, Chunks from a fetch) and returns those to pass on. It runs after the inner store applied limit, so a call can return fewer results than asked for. The store does not fetch more results to replace them. It is for a rule the index cannot apply itself: a revocation the index does not know about yet, a blocklist, a score floor, deduplication. Every argument reaches the inner store unchanged, and fields passes through untouched.

paraminnerVectorStore

The store that answers each call.

paramkeepKeep

The rule that picks the results to return.

methodhybridasync (target, *, query, vector=None, limit, where=None, alpha=None) -> Sequence[Hit]

Call inner.hybrid with the same arguments, and return the hits that keep returns.

paramtargetTarget

The target to search.

paramquerystr

The query text.

paramvectorSequence[float] | None
= None

The query embedding, or None to leave embedding to the inner store.

paramlimitint

The maximum number of hits that the inner store returns, before keep drops any.

paramwhereFilter | None
= None

The filter for the inner store, or None to restrict nothing.

paramalphafloat | None
= None

The weight of the vector side, or None for the default of the inner store.

Returns

Sequence[Hit]

The hits that keep returns.

Raises:

  • InvalidQueryError: The inner store rejected the call.
  • StoreUnavailable: The inner store gave no answer.
  • Unconfigured: The inner store cannot serve the call.
methodnear_vectorasync (target, *, vector, limit, where=None) -> Sequence[Hit]

Call inner.near_vector with the same arguments, and return the hits that keep returns.

paramtargetTarget

The target to search.

paramvectorSequence[float]

The query embedding.

paramlimitint

The maximum number of hits that the inner store returns, before keep drops any.

paramwhereFilter | None
= None

The filter for the inner store, or None to restrict nothing.

Returns

Sequence[Hit]

The hits that keep returns.

Raises:

  • InvalidQueryError: The inner store rejected the call.
  • StoreUnavailable: The inner store gave no answer.
  • Unconfigured: The inner store cannot serve the call.
methodbm25async (target, *, query, limit, where=None) -> Sequence[Hit]

Call inner.bm25 with the same arguments, and return the hits that keep returns.

paramtargetTarget

The target to search.

paramquerystr

The query text.

paramlimitint

The maximum number of hits that the inner store returns, before keep drops any.

paramwhereFilter | None
= None

The filter for the inner store, or None to restrict nothing.

Returns

Sequence[Hit]

The hits that keep returns.

Raises:

  • InvalidQueryError: The inner store rejected the call.
  • StoreUnavailable: The inner store gave no answer.
  • Unconfigured: The inner store cannot serve the call.
methodfetchasync (target, *, where=None, limit, order_by=None, descending=False) -> Sequence[Chunk]

Call inner.fetch with the same arguments, and return the chunks that keep returns.

paramtargetTarget

The target to read.

paramwhereFilter | None
= None

The filter for the inner store, or None for every chunk.

paramlimitint

The maximum number of chunks that the inner store returns, before keep drops any.

paramorder_bystr | None
= None

A stored field to sort on, or None for the order of the inner store.

paramdescendingbool
= False

Whether to sort on order_by in descending order.

Returns

Sequence[Chunk]

The chunks that keep returns.

Raises:

  • InvalidQueryError: The inner store rejected the call.
  • StoreUnavailable: The inner store gave no answer.
  • Unconfigured: The inner store cannot serve the call.
methodfieldsasync (target) -> FieldSpec

Return the field spec of target from the inner store, unchanged.

paramtargetTarget

The target to describe.

Returns

FieldSpec

The field spec that the inner store returns.

Raises:

  • InvalidQueryError: The inner store does not know the target.
  • StoreUnavailable: The inner store gave no answer.

Keep

protocolKeep

The rule that picks, from the results a store answered with, the ones to return.

It gets the target and the results, in order, and returns the ones to pass on.

PostFiltered calls it with the hits of each search and with the chunks of each fetch.

method__call__async [R: Hit | Chunk](target, results, /) -> Sequence[R]

Return the results to pass on, in the order to return them.

paramtargetTarget

The target that the call named.

paramresultsSequence[R]

What the inner store answered with, in its order: hits from a search, chunks from a fetch.

Returns

Sequence[R]

The results to return to the caller. They are of the same type as results.

On this page