Repository navigation
v0.5.0
Summary
Version 0.5.0 makes VectorStore state harder to corrupt accidentally, removes the repeated full-store copies that previously made small incremental additions increasingly expensive, and gives tied search results a stable order. It also completes the persistence transition announced in 0.4, leaving one explicit create/open/save/reload lifecycle.
Safer state ownership
- Make
dimensions,normalize, andfile_pathread-only properties so store configuration cannot drift away from the vectors it describes. - Return zero-copy, non-writeable views from
vectorsandmetadata. Request a new view afteradd(),clear(), orreload(); an older view may still refer to the previous buffer. - Return an independent
float32vector copy fromget(), preventing changes to a retrieved vector from affecting later searches. - Continue preserving opaque metadata payloads by reference. The metadata array protects row alignment, but mutable dictionaries, lists, and other payload objects remain owned by the application.
These boundaries protect ordinary use of the public API. They are not intended to make NumPy storage tamper-proof against deliberate access through private attributes, .base, ctypes, or similar escape hatches.
Better incremental ingestion
Repeated calls to add() now reuse private contiguous capacity instead of concatenating and copying every earlier row on each call. When capacity must grow, vector and metadata storage grow together and active rows are copied once. Spare capacity remains invisible to len(), inspection, search, retrieval, filtered search, and saved archives.
The public add(vectors, metadata) API, validation, normalization, metadata behavior, and insertion order are unchanged. clear() returns the store to empty arrays and releases the capacity retained by the store itself.
Deterministic tied results
Exact search ties now resolve by ascending original store row index. This rule applies when selecting rows at the top_k boundary as well as when ordering the final result, and filtered searches use original indexes regardless of the order supplied in within_rows.
Cosine and dot-product searches still rank larger values first; Euclidean search still ranks smaller distances first. Only exactly equal computed values use the row-index tie break.
Persistence migration completed
The compatibility window provided by 0.4 is now closed:
- Constructor
file_path=is removed. Create an in-memory store and callsave(path)to write and bind it. - Instance
load()is removed. UseVectorStore.open(path)to construct a store orreload()to refresh a bound store. - Context-manager persistence is removed. Call
save()explicitly where the application intends to persist state. - The reader for old, unversioned archives containing only
vectorsandmetadatais removed.
Archive format version 1 is unchanged. Code already using VectorStore.open(), save(path), save(), and reload() needs no persistence migration. Unversioned archives must be converted with version 0.4 using their original dimensions and normalization mode, or recreated from source data, before upgrading. The persistence migration guide contains side-by-side replacements and conversion instructions.
Concurrency and trust boundaries
Concurrent searches, retrievals, and inspection are supported only while the store and shared metadata payloads remain unchanged. Applications must synchronize every access when any thread may add, clear, reload, save, or mutate shared metadata. The package does not provide internal locking, file locking, snapshots for concurrent writes, or multi-writer archive coordination.
Archives still contain NumPy pickle-backed object arrays for opaque metadata. Only open files produced by your application or another trusted source.
Compatibility
- Python 3.11 through 3.14
- NumPy 1.23.2 or newer
- Archive format version 1
See the repository changelog for the complete release record.
Full comparison: v0.4.0...v0.5.0