Skip to content

Search options

Vectrix.search takes a question and answers with Results: the chunks that match, best first, each with its text, its relevance and where it came from. Everything else is an option. This page is every option, every field of what comes back, and what the REST API offers for each.

from vectrixdb import Vectrix

db = Vectrix("handbook", mode="hybrid")
db.add(
    [
        "Refunds are paid within ten working days of the request.",
        "A refund goes back to the card that paid.",
        "Parental leave is eighteen weeks, on full pay.",
        "Expenses are claimed within thirty days.",
    ],
    metadata=[
        {"team": "finance", "year": 2026},
        {"team": "finance", "year": 2025},
        {"team": "people", "year": 2026},
        {"team": "finance", "year": 2026},
    ],
)

found = db.search("how long do refunds take", limit=3)
top = found.top
print(top.text, top.relevance, top.relevance_kind, top.readable_citation)

Every option

Option Default What it does
query The question, in words
limit 10 The most results to return; at least 1
mode the collection's "dense", "sparse", "hybrid", "ultimate" or "graph". A search may use the collection's mode or one below it: dense and sparse, then hybrid, ultimate and graph. See Search modes
rerank how the mode does it In dense and sparse modes nothing reranks unless asked: "mmr", "exact" or "cross-encoder". Hybrid, ultimate and graph rerank with the cross-encoder; False turns that off. "semantic" is Azure AI Search's semantic ranker, for sparse and hybrid searches on a collection stored there
filter none Keeps results whose metadata matches: {"team": "finance"}. The whole grammar is in Filters
diversity 0.7 For rerank="mmr", how far to trade relevance for variety, 0 to 1
token_budget none Stops adding results once their text would cost more than this many tokens. The top result always comes back
score_gap none Drops results scoring below this fraction of the top score, above 0 and up to 1. Cosine scores sit in a narrow band, so 0.9 is typical there; keyword and graph scores want about 0.2
explain False Puts the parts of each score in Result.explain: dense similarity, BM25, the fused score, ColBERT, the reranker, any graph boost
fusion "rrf" How hybrid and ultimate modes combine meaning and words: "rrf", by rank, or "weighted", scores blended by alpha
alpha 0.5 With fusion="weighted", the share of meaning, 0 to 1. Raise it when keyword matches drag results
expand none A function from the question to other phrasings. Each is searched and the lists are fused by rank. Pass any model call; nothing is bundled
hyde none A function from the question to a made-up answer, which is embedded in place of the question. Pass any model call; nothing is bundled
parents False For a document added with parent_size=, returns the section each hit belongs to instead of the chunk, once a section. A chunk with no section comes back as it is
vectors every one On a collection with more than one dense index, which answers: a model's name, "own", "image", or "all". On a store that holds two vectors, "vectrixdb", "azure" or "both"
homes the usual routing On a collection kept on Azure AI Search or OpenSearch: "store", "local" or "both". See Two homes

Who is searching is not an option. On a collection with an entitlement policy, a search reads as a principal, given once to a view of the collection: db.as_principal({"roles": ["analyst"]}).search(...). See Restrict what a search can see.

db.search("refunds", mode="dense")
db.search("refunds", mode="sparse")
db.search("refunds", rerank=False)
db.search("refunds", filter={"team": "finance", "year": {"$gte": 2026}})

cut = db.search("refunds", token_budget=20)
print(cut.truncated, cut.cut_count, cut.token_estimate)

strong = db.search("refunds", score_gap=0.9)
why = db.search("refunds", explain=True).top.explain
print(sorted(why))

Small chunks that find, sections that answer

policies = Vectrix("policies")
policies.add_document(
    "# Refunds\n\nRefunds are paid within ten working days. A refund goes back to the card that paid. "
    "A card that has expired is refunded by bank transfer instead.\n\n"
    "# Leave\n\nParental leave is eighteen weeks on full pay. It can be taken in one block or in two.\n",
    doc_id="policies.md",
    chunk_size=100,
    overlap=0,
    parent_size=1000,
)
print(policies.search("what if my card expired").top.text)                 # the chunk that matched
print(policies.search("what if my card expired", parents=True).top.text)   # its whole section

Several hits in one section come back as that section once, at the best of their scores.

What comes back

Results is a list of Result, best first. Iterate it, index it, take its length.

Results What it is
.top The best result, or None when nothing matched
.texts, .ids, .scores Lists of each, in order
.citations() Every distinct citation among the results, best first
.sources(max_chars=None) The results as a block for a prompt, one [citation]: text a result
.figures(top=None) The results that are figures, for a model that can see
.query, .mode, .time_ms What was asked, in which mode, and how long it took
.truncated, .cut_count Whether token_budget cut anything, and how many results
.token_estimate, .token_budget What the results cost in tokens, and the budget asked for. The estimate is there without a budget too
.degraded Why a search answered with less than it was asked for: graph mode from vectors alone, a store that did not answer under homes="both", an index slowed by deleted vectors. None otherwise
.decision_id Set when a search under a policy wrote a decision record: the id of that record in the audit trail
.to_dict(), Results.from_dict() Everything as plain data, and back
.to_pandas(), .to_polars() A table of id, score, text and metadata; needs pandas or polars
Result What it is
.id, .text, .metadata The chunk
.score What orders the list. Its scale depends on the mode and the engine, so do not put a threshold on it
.relevance How well it matches, 0 to 1, the same on every mode and engine, or None when there is no honest number. Put thresholds here
.relevance_kind What relevance is: "reranker", "similarity", "relative" or "distance"
.similarity The cosine similarity on its own, whenever it is known
.matched_by What found it: ["meaning"], ["keywords"] or both
.relevances The similarity from each dense vector, on a store that holds two
.citation What to write in square brackets to cite it: the citation add_document stamped, or one built from its source, page and heading, or its id
.readable_citation The same place as a person reads it: report.pdf, pp. 39-40, slide 3, 11:05 in a recording
.explain The parts of the score, with explain=True
for r in found:
    print(r.id, r.relevance, r.matched_by, r.citation)

if not found or (found.top.relevance or 0) < 0.45:
    print("I could not find that.")

Score and relevance says what each kind of relevance means and where to put a threshold.

Over REST

A server's search routes take a question in words and embed it for you. Each answers with results, each with id, score, text, metadata, relevance, relevance_kind and matched_by.

In the library Over REST
mode="dense" POST /api/v1/collections/{name}/text-search
mode="sparse" POST /api/v1/collections/{name}/keyword-search
mode="hybrid" POST /api/v1/collections/{name}/text-hybrid-search, on a collection made with its text index
rerank="cross-encoder" "rerank": true on text-search
query "query_text"
limit "limit", from 1 to 1000
filter "filter", the same grammar
none "score_threshold" on text-search: drops results scoring below it
none "include_highlights" on keyword-search: the matched words in each result
none ?snippet=N on any search: each result's text cut to N characters, 40 to 2000
.decision_id decision_id, when a policy judged the search
as_principal(...) Who the request comes from: its key, or the person's token, judged by the server

ultimate and graph modes, token_budget, score_gap, explain, fusion, alpha, expand, hyde, parents, vectors and homes are the library's alone. Every route and body is in the REST reference, and Call a server from your code has clients that call these routes for you.