windlass.providers.vectordb.memory¶
memory
¶
An in-process vector store with optional JSON persistence.
This is the default store, and it is deliberately not a toy: it does exact nearest-neighbour search (no recall loss from approximation), supports the full metadata filter language, upserts by chunk id, and can save to and load from disk. For corpora up to roughly 100k chunks on a machine with NumPy installed it is genuinely fast enough for production.
Beyond that, switch to FAISS (local, approximate, millions of vectors) or Pinecone (managed, distributed). The interface does not change.
Example
from windlass.core.types import Chunk store = InMemoryVectorStore(dimensions=3) store.add([ ... Chunk(content="cats", embedding=[1.0, 0.0, 0.0], metadata={"topic": "pets"}), ... Chunk(content="ships", embedding=[0.0, 1.0, 0.0], metadata={"topic": "sea"}), ... ]) 2 store.search([1.0, 0.0, 0.0], k=1)[0].chunk.content 'cats' store.search([1.0, 0.0, 0.0], k=2, filters={"topic": "sea"})[0].chunk.content 'ships'
InMemoryVectorStore
¶
InMemoryVectorStore(
*,
collection: str = "windlass",
dimensions: int | None = None,
metric: str = "cosine",
persist_path: str | None = None,
autosave: bool = False,
**config: Any
)
Bases: VectorStore
Exact nearest-neighbour search over an in-memory list.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
collection
|
str
|
Logical collection name, used in the persistence filename. |
'windlass'
|
dimensions
|
int | None
|
Expected vector length. Inferred from the first write when omitted, then enforced on every subsequent write. |
None
|
metric
|
str
|
|
'cosine'
|
persist_path
|
str | None
|
Directory (or file) to save to. When it already contains data for this collection it is loaded on construction. |
None
|
autosave
|
bool
|
Persist after every write. Convenient for notebooks, slow for
bulk ingestion — leave it off and call :meth: |
False
|
**config
|
Any
|
Forwarded to :class: |
{}
|
Attributes:
| Name | Type | Description |
|---|---|---|
chunks |
dict[str, Chunk]
|
The stored chunks, keyed by id. |
Performance
Search is O(n) in the number of chunks. With NumPy installed the
whole matrix is scored in one vectorised operation, which keeps 100k
chunks in the low tens of milliseconds; without it, expect roughly two
orders of magnitude slower.
Thread safety
All mutating operations hold a re-entrant lock, so concurrent ingestion and search are safe.
Source code in src\windlass\providers\vectordb\memory.py
aadd
async
¶
Insert or update chunks.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
chunks
|
Sequence[Chunk]
|
Chunks with embeddings set. |
required |
Returns:
| Type | Description |
|---|---|
int
|
How many chunks were written. |
Raises:
| Type | Description |
|---|---|
ConfigurationError
|
If a chunk has no embedding. |
ProviderError
|
If a chunk's vector length disagrees with the collection's dimensionality — usually a sign that two different embedding models were used against one index. |
Source code in src\windlass\providers\vectordb\memory.py
adelete
async
¶
Delete by id or metadata filter.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ids
|
Sequence[str] | None
|
Chunk ids to remove. |
None
|
filters
|
MetadataFilter | None
|
Metadata constraints. |
None
|
Returns:
| Type | Description |
|---|---|
int
|
How many chunks were removed. |
Raises:
| Type | Description |
|---|---|
ValueError
|
When neither argument is supplied. |
Source code in src\windlass\providers\vectordb\memory.py
aclear
async
¶
asearch
async
¶
asearch(
vector: Sequence[float],
k: int = 5,
*,
filters: MetadataFilter | None = None,
**kwargs: Any
) -> list[ScoredChunk]
Return the k nearest chunks.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
vector
|
Sequence[float]
|
The query embedding. |
required |
k
|
int
|
How many results to return. |
5
|
filters
|
MetadataFilter | None
|
Metadata constraints applied before scoring, so a narrow filter makes search proportionally faster. |
None
|
**kwargs
|
Any
|
Ignored. |
{}
|
Returns:
| Type | Description |
|---|---|
list[ScoredChunk]
|
Ranked hits. Euclidean scores are negated distances, so higher is |
list[ScoredChunk]
|
always better regardless of metric. |
Source code in src\windlass\providers\vectordb\memory.py
aget
async
¶
Fetch chunks by id, skipping ids that are not present.
acount
async
¶
all_chunks
¶
Return every stored chunk.
Used by hybrid retrieval to build a lexical index over the same corpus.
Returns:
| Type | Description |
|---|---|
list[Chunk]
|
A snapshot list; mutating it does not affect the store. |
Source code in src\windlass\providers\vectordb\memory.py
apersist
async
¶
Write the collection to :attr:persist_path.
Raises:
| Type | Description |
|---|---|
ProviderError
|
When no path is configured or the write fails. |
Source code in src\windlass\providers\vectordb\memory.py
save
¶
Write the collection to a JSON file.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
str | Path
|
Destination file. Parent directories are created. |
required |
Returns:
| Type | Description |
|---|---|
Path
|
The path written. |
Raises:
| Type | Description |
|---|---|
ProviderError
|
When the file cannot be written. |
Example
import tempfile, pathlib from windlass.core.types import Chunk store = InMemoryVectorStore(dimensions=2) _ = store.add([Chunk(content="x", embedding=[1.0, 0.0])]) out = store.save(pathlib.Path(tempfile.mkdtemp()) / "i.json") InMemoryVectorStore().load(out).count() 1
Source code in src\windlass\providers\vectordb\memory.py
load
¶
Load a collection previously written by :meth:save.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
str | Path
|
The JSON file to read. |
required |
Returns:
| Type | Description |
|---|---|
InMemoryVectorStore
|
|
Raises:
| Type | Description |
|---|---|
ProviderError
|
When the file is missing or malformed. |