Skip to content

API Reference

The public surface is the typed Python facade. Each symbol below is rendered from its docstrings and type hints by mkdocstrings.

Store and handles

valise.Store

Store(native: '_native.Store')

A single-file Valise store.

:meth:open is open-or-create; :meth:create fails if the path exists. Declare collections with :meth:collection, then acquire a :class:Writer to ingest and a :class:Reader to query.

Example::

store = Store.open("kb.vls")
store.collection("notes", Schema().text("body").vector("embedding", Vector(dim=768)))
with store.writer() as w:
    w.put("notes", "doc-1", Record().text("body", "...").vector("embedding", emb))
    w.commit()
hits = store.search("notes", Search().text("body", "...").vector("embedding", emb))

open classmethod

open(path: _PathLike, durability: Durability = Durability.BUFFERED) -> 'Store'

Open an existing store, creating it if absent (open-or-create).

create classmethod

create(path: _PathLike, durability: Durability = Durability.BUFFERED) -> 'Store'

Create a fresh store at path, failing if it already exists.

collection

collection(name: str, schema: Schema) -> None

Create-or-open name, bind schema, and persist the schema in-file (it rides the next commit) — a later :meth:open restores it, so reopen needs no re-declaration.

Re-declaring is a no-op when identical and accepted when purely additive; anything else raises :class:valise.SchemaMismatchError. Names starting with ~ are reserved and rejected.

define_space

define_space(name: str, spec: Union[Text, Vector]) -> Space

Define (or return the existing) shared space from a field spec — Text() / Vector(dim=768, codec=Upq()) / … — then bind it in any schema with Text(space=...) / Vector(space=...).

Re-defining an existing name is a no-op for an identical spec and an error for a divergent one.

space

space(name: str) -> Optional[Space]

Look up a previously defined space by name, or None.

spaces

spaces() -> list[SpaceInfo]

All defined spaces — shared and ~auto/{collection}/{field} ones (the latter flagged auto) — sorted by name.

collections

collections() -> list[CollectionInfo]

All user collections (the hidden ~valise.schema store is never listed).

partitioned

partitioned(base: str, schema: Schema, by: Partition) -> Partitioned

Create-or-open a logical partitioned collection: records routed by by into physical collections ("{base}:{period}") that share one resolved schema.

reader

reader() -> Reader

Acquire a :class:Reader (live, last-committed-wins per operation — not a frozen snapshot).

writer

writer() -> Writer

Acquire the single :class:Writer (blocks until available).

get

get(coll: str, key: Key) -> Optional[Stored]

Fetch a single record, or None if absent.

search

search(coll: str, search: Search) -> SearchResult

Run a search; returns a :class:SearchResult in one native call.

search_view

search_view(view: View, search: Search) -> SearchResult

Search across a partitioned :class:View as one globally-fused query; hits carry their per-hit partition collection.

compact

compact(recalibrate: bool = False) -> CompactReport

Compact the store; returns a typed :class:CompactReport.

stats

stats() -> Stats

Return store-level :class:Stats (user data only).

valise.Reader

Reader(native: '_native.Reader')

A snapshot reader: get / get_many / search / search_view.

get

get(coll: str, key: Key) -> Optional[Stored]

Fetch a single record, or None if absent.

keys

keys(coll: str) -> list[Key]

Every committed key in coll, in unspecified order.

The building block for a full scan: pair it with :meth:get_many to walk a capsule end to end. Uncommitted records are excluded. Cost is O(records in coll) and the result holds one key per record, so chunk it for very large collections.

get_many

get_many(coll: str, keys: list[Key]) -> list[Optional[Stored]]

Fetch many records in one native call.

Returns a list aligned with keys; missing entries are None. The list comprehension wraps already-built native Stored objects — it is not a per-record native round-trip.

search

search(coll: str, search: Search) -> SearchResult

Run a search; returns a :class:SearchResult in one native call.

Example

import os, tempfile from valise import Store, Schema, Record, Search path = os.path.join(tempfile.mkdtemp(), "demo.vls") store = Store.open(path) store.collection("kb", Schema().text("body")) with store.writer() as w: ... w.put("kb", "a", Record().text("body", "the quick fox")) ... w.put("kb", "b", Record().text("body", "a lazy dog")) ... _ = w.commit() result = store.reader().search( ... "kb", Search().text("body", "fox").top_k(5) ... ) result[0].key 'a' len(result) 1 result.scores.dtype dtype('float32')

search_view

search_view(view: View, search: Search) -> SearchResult

Search across a partitioned :class:valise.View as ONE globally-fused multi-collection query; hits carry their per-hit partition collection.

valise.Writer

Writer(native: '_native.Writer')

A serialized writer holding the single-writer lock until closed.

put

put(coll: str, key: Key, record: Record) -> None

Stage a record under key (replacing any existing one).

put_auto

put_auto(coll: str, record: Record) -> Key

Stage a record under an auto-generated key; returns the key.

put_into

put_into(partitioned: Partitioned, key: Key, record: Record) -> None

Stage a record into a :class:valise.Partitioned logical collection.

The physical partition is derived from the record's created_at (set via :meth:valise.Record.at; defaults to now).

put_many

put_many(coll: str, keys: list[Key], vectors: ndarray, field: str = 'dense', texts: Optional[list[str]] = None, text_field: str = 'body') -> None

Bulk-stage len(keys) records in one native call.

vectors is a 2-D float32 ndarray [N, dim] borrowed zero-copy by native; there is no per-row Python loop.

Raises:

Type Description
ValueError

if vectors is not 2-D, or if its row count does not match len(keys), or if texts is given with a length other than len(keys). (dtype / contiguity are validated by the native layer.)

delete

delete(coll: str, key: Key) -> bool

Tombstone key; returns True if it existed.

commit

commit() -> int

Commit staged mutations; returns the new generation.

close

close() -> None

Release the single-writer lock (drops the native writer).

Schema

valise.Schema

Schema()

The set of named fields a collection's records may fill.

Built fluently and bound by :meth:valise.Store.collection::

Schema().text("body").vector("embedding", Vector(dim=768))

vector(name, 768) is accepted as an int shorthand for vector(name, Vector(dim=768)).

text

text(name: str, spec: Optional[Text] = None) -> 'Schema'

Add a text field. spec=None is the Rust default (Text::english()). At most one text field per collection in v1.

vector

vector(name: str, spec: Union[Vector, int]) -> 'Schema'

Add a vector field. The dimension is mandatory, so the spec is always explicit: Vector(dim=768), the int shorthand 768, or a shared binding Vector(space=...).

valise.Text dataclass

Text(lang: Optional[Lang] = None, space: Optional[Space] = None)

Text field spec: an inline analyzer choice or a shared-space binding.

Text() is the Rust default (Text::english(): NFKC, case-fold, Porter2 stemming, Lucene stopwords). Text(lang=Lang.RAW) is the pass-through whitespace tokenizer. Text(space=...) binds a shared space from :meth:valise.Store.define_space (mutually exclusive with lang).

valise.Vector

Vector(dim: Optional[int] = None, *, metric: Optional[Metric] = None, codec: Optional[Codec] = None, calibrate: Optional[Calibrate] = None, space: Optional[Space] = None)

Vector field spec: an inline (dim, metric, codec, calibrate) choice or a shared-space binding. Exactly one of dim/space.

Inline defaults are the Rust ones: cosine metric, Qam() codec, Auto() calibration. dim must be a positive multiple of 64 (checked at declaration). On a shared binding (space=...) the configuration arguments are rejected at declaration time — metric/codec/calibration belong to the space and are configured at :meth:valise.Store.define_space.

Parameters:

Name Type Description Default
dim Optional[int]

The vector dimension (inline spec).

None
metric Optional[Metric]

Distance metric, or None for cosine.

None
codec Optional[Codec]

:class:Qam / :class:Upq, or None for Qam().

None
calibrate Optional[Calibrate]

:class:Auto / :class:Now, or None for Auto().

None
space Optional[Space]

A shared vector :class:Space (instead of dim).

None

valise.Qam dataclass

Qam(amp_bits: Optional[int] = None, phase_bits: Optional[int] = None)

QAM Lloyd-Max codec.

Qam() is the production default operating point (Rust Codec::qam() = 5 amplitude + 6 phase bits). Pass both amp_bits and phase_bits to move it (Rust Codec::qam_bits); higher bits trade storage for recall.

Parameters:

Name Type Description Default
amp_bits Optional[int]

Bits per amplitude index, or None for the Rust default.

None
phase_bits Optional[int]

Bits per phase index, or None for the Rust default.

None

valise.Upq dataclass

Upq(cells: Optional[int] = None, design: Optional[Design] = None)

UPQ (unrestricted polar quantization) codec.

Upq() is the default operating point (Rust Codec::upq() = 2048 cells, empirical ring design). Upq(cells=...) mirrors Codec::upq_cells; a design requires an explicit cells budget (mirror of Codec::upq_with).

Parameters:

Name Type Description Default
cells Optional[int]

Total joint cells per complex pair (power of two), or None for the Rust default.

None
design Optional[Design]

Ring-design source (:class:valise.Design), or None for empirical.

None

valise.Design

Bases: _StrEnum

UPQ ring-design source (mirror of Rust UpqDesign).

valise.Auto dataclass

Auto(sample: Optional[int] = None)

Calibrate at the first commit that contains vectors for the field.

Auto() is the Rust default (Calibrate::auto(): fit from up to 50 000 staged vectors). Auto(sample=n) mirrors Calibrate::auto_sample(n).

Parameters:

Name Type Description Default
sample Optional[int]

Sample-size cap, or None for the Rust default.

None

valise.Now

Now(vectors: ndarray)

Calibrate eagerly at declaration from a representative sample (mirror of Rust Calibrate::now).

Parameters:

Name Type Description Default
vectors ndarray

A 2-D [n, dim] array of sample vectors. Coerced to C-contiguous float32.

required

valise.Space

Space(native: '_native.Space')

An opaque handle to a defined space, returned by :meth:valise.Store.define_space / :meth:valise.Store.space. Bind it in a schema with Text(space=...) or Vector(space=...).

name property

name: str

The space's name.

valise.Metric

Bases: _StrEnum

Vector-space distance metric.

valise.Lang

Bases: _StrEnum

Text-space analyzer language.

Records

valise.Record

Record()

Typed record builder.

Accumulates text/vector fields and metadata for a single record. Each method forwards one native call and returns self for chaining.

text

text(field: str, value: str) -> 'Record'

Set the value of a text field.

vector

vector(field: str, values: ndarray) -> 'Record'

Set a vector field (values borrowed zero-copy by native).

at

at(unix_secs: int) -> 'Record'

Set the record's created_at timestamp (unix seconds).

child_of

child_of(parent: Union[str, int, bytes]) -> 'Record'

Link this record as a child of parent.

valise.Stored dataclass

Stored(key: Key, collection: str, created_at: int, text: Optional[str], vectors: list[tuple[str, ndarray]])

A stored record as returned by get / get_many.

Attributes:

Name Type Description
key Key

The record key.

collection str

The owning collection.

created_at int

The record timestamp (unix seconds).

text Optional[str]

The text field value, if any.

vectors list[tuple[str, ndarray]]

An ordered list of (field_name, ndarray) pairs. The ndarrays are the moved arrays from native — not copied.

Equality is structural (np.array_equal over each vector, so shape and dtype count). Because it carries ndarrays, :class:Stored is unhashable — like the list / ndarray payloads it holds.

Example

import os, tempfile from valise import Store, Schema, Record path = os.path.join(tempfile.mkdtemp(), "demo.vls") store = Store.open(path) store.collection("kb", Schema().text("body")) with store.writer() as w: ... w.put("kb", "a", Record().text("body", "the quick brown fox")) ... _ = w.commit() got = store.reader().get("kb", "a") got.text 'the quick brown fox' got.created_at >= 0 True got == store.reader().get("kb", "a") True

valise.Search

Search()

Typed hybrid-search query builder.

Wraps a single owned native Search builder. Each builder method makes exactly one native call into that owned state and returns self for chaining; the facade never re-walks the query in Python.

Defaults (all applied by Rust): BM25 text scorer, ACCURATE vector rerank, RRF(60) fusion, top_k=10.

text

text(field: str, query: str, scorer: TextScorer = Bm25()) -> 'Search'

Add a lexical (text) channel.

Parameters:

Name Type Description Default
field str

The text field to query.

required
query str

The query string.

required
scorer TextScorer

A typed :data:TextScorer (default :class:Bm25). Raw strings are not accepted.

Bm25()

Returns:

Type Description
'Search'

self, for chaining.

vector

vector(field: str, query: ndarray, rerank: Rerank = Rerank.ACCURATE) -> 'Search'

Add a vector (nearest-neighbor) channel. May be called multiple times for multi-vector / multimodal search; each becomes a fusion channel.

Parameters:

Name Type Description Default
field str

The vector field to query.

required
query ndarray

A 1-D float32 ndarray (borrowed zero-copy by native).

required
rerank Rerank

Rerank fidelity (default Rerank.ACCURATE, mirroring Rust).

ACCURATE

Returns:

Type Description
'Search'

self, for chaining.

fuse

fuse(fusion: Fusion) -> 'Search'

Set the channel-fusion strategy.

Parameters:

Name Type Description Default
fusion Fusion

A typed :data:Fusion (:class:Rrf or :class:Weighted).

required

Returns:

Type Description
'Search'

self, for chaining.

recency

recency(recency: Recency) -> 'Search'

Set the recency strategy.

Parameters:

Name Type Description Default
recency Recency

A typed :data:Recency (:class:Range, :class:HalfLife, or :class:RrfChannel).

required

Returns:

Type Description
'Search'

self, for chaining.

top_k

top_k(k: int) -> 'Search'

Limit the result set to the top k hits.

now

now(unix_secs: int) -> 'Search'

Set the reference 'now' (unix seconds) for recency decay.

valise.SearchResult

SearchResult(keys: List[Key], scores: ndarray, collection: Union[str, List[str]])

The result of a search: parallel keys and scores.

Built from the native (keys: list, scores: np.ndarray[float32]) tuple in one native call. Both are held as-is (zero new allocation); the scores ndarray is the moved array, never copied. :class:Hit objects are materialized lazily — on indexing or iteration — so there is no eager per-hit loop over the result set.

For a single-collection :meth:valise.Store.search, collection is that collection's name. For :meth:valise.Store.search_view, hits span partitions: collection is None and the per-hit names are carried on each :class:Hit (and by :attr:collections).

keys property

keys: List[Key]

The result keys (the native list, returned as-is).

scores property

scores: ndarray

The result scores (the moved float32 ndarray, returned as-is).

collection property

collection: Optional[str]

The single collection these hits belong to, or None for a multi-collection (view) result — use :attr:collections then.

collections property

collections: List[str]

Per-hit collection names (uniform for a single-collection search).

valise.Hit dataclass

Hit(key: Key, score: float, collection: str)

A single search hit.

Attributes:

Name Type Description
key Key

The record key.

score float

The fused relevance score.

collection str

The collection the hit belongs to.

valise.Rerank

Bases: _StrEnum

Vector-search rerank fidelity. ACCURATE (full f32 rerank) is the default, mirroring Rust Rerank::Accurate.

valise.TfMode

Bases: _StrEnum

Term-frequency weighting mode for TF-IDF scoring.

valise.Bm25 dataclass

Bm25(k1: Optional[float] = None, b: Optional[float] = None)

Okapi BM25 lexical scorer — the default of :meth:Search.text.

Parameters:

Name Type Description Default
k1 Optional[float]

Term-frequency saturation, or None for the Rust default (1.2).

None
b Optional[float]

Length normalization, or None for the Rust default (0.75).

None

valise.TfidfCosine dataclass

TfidfCosine(tf_mode: TfMode = TfMode.LOG)

TF-IDF cosine-similarity lexical scorer.

Parameters:

Name Type Description Default
tf_mode TfMode

Term-frequency weighting mode.

LOG

valise.TfidfCosineApprox dataclass

TfidfCosineApprox(tf_mode: TfMode = TfMode.LOG)

Cheaper sqrt(doclen)-normalized TF-IDF cosine approximation.

Parameters:

Name Type Description Default
tf_mode TfMode

Term-frequency weighting mode.

LOG

valise.CountCosine dataclass

CountCosine()

Raw-count cosine-similarity lexical scorer.

valise.CountCosineApprox dataclass

CountCosineApprox()

Cheaper count-cosine approximation.

valise.Dice dataclass

Dice()

Sørensen–Dice set-overlap scorer.

valise.Overlap dataclass

Overlap()

Overlap-coefficient set scorer.

valise.Containment dataclass

Containment()

Containment (asymmetric overlap) set scorer.

valise.Rrf dataclass

Rrf(k: Optional[int] = None)

Reciprocal-rank fusion — the default with ≥2 channels.

Parameters:

Name Type Description Default
k Optional[int]

The RRF rank constant, or None for the Rust default (60).

None

valise.Weighted dataclass

Weighted(text: float, vector: float)

Linear weighted fusion of the text and vector channels (each channel min-max normalized to [0, 1] first).

Parameters:

Name Type Description Default
text float

Weight applied to the text channel.

required
vector float

Weight applied to every vector channel.

required

valise.Range dataclass

Range(from_: int, to: int)

Hard recency filter to the inclusive [from_, to] unix-second window (candidates outside it are pruned before fusion).

Parameters:

Name Type Description Default
from_ int

Inclusive lower bound (unix seconds). Named from_ because from is a Python keyword.

required
to int

Inclusive upper bound (unix seconds).

required

valise.HalfLife dataclass

HalfLife(days: float)

Exponential recency decay with the given half-life (soft post-fusion multiplier score * 0.5 ** (age / half_life)).

Parameters:

Name Type Description Default
days float

The decay half-life in days.

required

valise.RrfChannel dataclass

RrfChannel(half_life_days: float, weight: float)

Recency as an additional RRF channel (candidates ranked newest first, contributing weight / (k + rank + 1)). Requires :class:Rrf fusion.

Parameters:

Name Type Description Default
half_life_days float

The recency half-life in days.

required
weight float

The channel weight.

required

Partitions

valise.Partition

Bases: Enum

How records are routed to physical partitions (mirror of Rust Partition::ByDay / ByMonth).

valise.Window

Window()

A window of partitions for a view. Construct via the factory methods: :meth:last_days, :meth:range, :meth:partitions.

last_days classmethod

last_days(days: int) -> 'Window'

Partitions intersecting [now - days, now].

range classmethod

range(from_: int, to: int) -> 'Window'

Partitions intersecting [from_, to] (inclusive unix seconds).

partitions classmethod

partitions(suffixes: Sequence[str]) -> 'Window'

Explicit period suffixes (e.g. "2026-05-25"), resolved against the existing "{base}:{suffix}" collections.

valise.Partitioned

Partitioned(native: '_native.Partitioned')

A logical partitioned collection (cheap handle; see module docs).

view

view(window: Window, now: Optional[int] = None) -> View

Resolve the partitions intersecting window to a :class:View.

now (unix seconds) overrides the reference time of Window.last_days for deterministic results; it is ignored by the other window kinds.

all

all() -> View

A view over every existing partition.

forget_before

forget_before(cutoff: int) -> int

Soft-forget: tombstone every record in partitions whose entire period precedes cutoff (unix seconds). Returns the number of frames tombstoned. Bytes are reclaimed at compaction.

Acquires the single writer internally — do not call while holding an open :class:valise.Writer.

valise.View

View(native: '_native.View')

A resolved set of physical partition collections. Pass to :meth:valise.Store.search_view / :meth:valise.Reader.search_view.

collections property

collections: List[str]

The physical collection names in this view.

Maintenance and options

valise.Stats dataclass

Stats(frames_total: int, frames_active: int, vectors_total: int, vectors_active: int, file_bytes: int, tombstone_ratio: float)

Store-level statistics (user data only — the hidden ~valise.schema doc frames are excluded).

Attributes:

Name Type Description
frames_total int

Total frames ever written.

frames_active int

Live (non-tombstoned) frames.

vectors_total int

Total vectors ever written.

vectors_active int

Live vectors.

file_bytes int

On-disk file size in bytes.

tombstone_ratio float

Fraction of frames that are tombstones.

needs_compaction

needs_compaction(threshold: float) -> bool

Whether :attr:tombstone_ratio meets/exceeds threshold (e.g. 0.3). Mirrors Rust StoreStats::needs_compaction.

valise.CompactReport dataclass

CompactReport(compacted: bool, frames_before: int, frames_after: int, vectors_before: int, vectors_after: int, bytes_before: int, bytes_after: int)

The result of a compaction.

Attributes:

Name Type Description
compacted bool

Whether a rewrite actually occurred.

frames_before int

Frame count before compaction.

frames_after int

Frame count after compaction.

vectors_before int

Vector count before compaction.

vectors_after int

Vector count after compaction.

bytes_before int

File size before compaction.

bytes_after int

File size after compaction.

valise.Durability

Bases: _StrEnum

Commit durability mode.

FULL_SYNC maps to the Rust Durability::FullSync (the strongest hardware barrier, F_FULLFSYNC on macOS).

valise.CollectionInfo dataclass

CollectionInfo(name: str, id: int)

One row of :meth:valise.Store.collections (the hidden ~valise.schema store is never listed).

Attributes:

Name Type Description
name str

The collection name.

id int

The engine collection id.

valise.SpaceInfo dataclass

SpaceInfo(name: str, dim: Optional[int], auto: bool)

One row of :meth:valise.Store.spaces.

Attributes:

Name Type Description
name str

The space name. Auto spaces are named ~auto/{collection}/{field}.

dim Optional[int]

The vector dimension, or None for a text space.

auto bool

True for the private spaces auto-defined by inline field specs.

Errors

ValiseError is the base of the hierarchy; catching it catches everything this package raises.

valise.ValiseError

Bases: Exception

valise.NotCalibratedError

Bases: ValiseError

valise.SchemaMismatchError

Bases: ValiseError

valise.CorruptionError

Bases: ValiseError

valise.BusyError

Bases: ValiseError

valise.UnsupportedError

Bases: ValiseError

valise.ValidationError

Bases: ValiseError