RetrievalIndex#

class scikitplot.corpus.RetrievalIndex(config=None)[source]#

Multi-mode similarity index over CorpusDocument collections.

Parameters:
configRetrievalConfig or None, optional

Default search configuration. Can be overridden per query.

Parameters:

config (RetrievalConfig | None)

See also

scikitplot.corpus._schema.MatchMode

Enum of match modes.

scikitplot.corpus._adapters

Convert results to LangChain / MCP format.

Notes

User note: Build the index once, query many times:

index = RetrievalIndex()
index.build(documents)
results = index.search("What did Hamlet say about death?")

Developer note: The index stores references to the original documents. If documents are mutated after building, results are undefined.

Examples

>>> index = RetrievalIndex()
>>> # index.build(corpus_documents)
>>> # results = index.search("quantum computing")
property backend_name: str | None#

Name of the active dense ANN backend, or None if unbuilt.

build(documents)[source]#

Build the index from CorpusDocument instances.

Parameters:
documentsSequence[CorpusDocument]

Documents to index. Must have text (and optionally embedding, tokens, normalized_text).

Raises:
ValueError

If documents is empty.

Parameters:

documents (Sequence[Any])

Return type:

None

static check_score_fusion_allowed(hits)[source]#

Whether score-space fusion is defensible for these hits.

Parameters:
hitsiterable of RetrievalHit

Hits from every leg that would be combined.

Returns:
str or None

The shared native_metric when score fusion is permissible, or None when it is not and rank fusion must be used.

Parameters:

hits (Iterable[RetrievalHit])

Return type:

str | None

Notes

User-focused. Rank fusion is the default combiner. Score-space fusion is available only when every leg reports the same native_metric, because adding a BM25 score to a cosine similarity produces a number with no meaning.

Developer-focused. ADR-R07-003 inverts the dangerous default deliberately: the failure mode of unnecessary rank fusion is slightly worse ranking, while the failure mode of unjustified score fusion is confidently wrong ranking. §19 states the rule directly – “do not compare cosine, Euclidean, inner product and backend-specific relevance scores as if they share one scale.”

Note that a shared metric is necessary but not sufficient in general: a validated normalization is also required. R06 established none exists for any non-cosine metric today, which is why the cosine case is the only one this returns for.

property has_embeddings: bool#

Whether dense embeddings are indexed.

property index_generation: IndexGeneration | None#

Content-derived identity of the built index.

Returns:
IndexGeneration or None

None before the first build.

Notes

User-focused. Every RetrievalHit carries the generation active at query time, so a caller can detect a result computed against a different index – including one built in another process, which a counter could not express.

Developer-focused. Because the value is derived from content rather than incremented, rebuilding the same documents with the same configuration yields the same generation. That makes build() idempotent, removing the only NON_IDEMPOTENT operation R04 found in the package, and it turns rebuild-detection into the question a caller actually has: does this index match this content?

property n_documents: int#

Number of indexed documents.

query(vector, k=None)[source]#

Vector-level ANN query returning (doc_id, score) pairs.

This is the vector-index seam consumed by scikitplot.mcp (the VectorIndex protocol): it takes a query vector (already embedded) rather than a query string, and returns stable document identities instead of RetrievalHit objects.

Parameters:
vectorarray-like

Query embedding of the same dimension as the indexed vectors.

kint or None, optional

Number of neighbours to return. Defaults to config.top_k.

Returns:
list of (str, float)

(doc_id, cosine_score) pairs, best first. doc_id is the document’s doc_id attribute when present, else its stringified index. Empty if no dense index was built or the query is zero-norm.

Raises:
ValueError

If vector dimension mismatches the index or is non-finite.

Parameters:
Return type:

list[tuple[str, float]]

search(query, *, config=None, query_embedding=None)[source]#

Search the index.

Parameters:
querystr

Query text.

configRetrievalConfig or None, optional

Override default config for this query.

query_embeddingarray-like or None, optional

Pre-computed query embedding. Required for SEMANTIC mode if no embedding engine is attached.

Returns:
RetrievalResponse

Hits sorted by descending score, plus a per-leg account of how the search went. The response iterates, indexes and lens like the list of hits it replaced, so for hit in response is unchanged; consult RetrievalResponse.status to distinguish a complete result from a partial one.

Parameters:
Return type:

RetrievalResponse

Notes

Developer. Before this returned an envelope, a hybrid query without a query embedding silently dropped its dense leg and returned fused lexical-only results still labelled match_mode="hybrid" – fewer hits, every score halved by the missing hybrid_alpha contribution, and no signal (finding F-R09-01). That outcome is now DEGRADED with the dense leg marked FAILED.