numpy-vector-store 0.3.1__tar.gz → 0.3.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- numpy_vector_store-0.3.2/.github/workflows/checks.yml +115 -0
- {numpy_vector_store-0.3.1 → numpy_vector_store-0.3.2}/.github/workflows/publish-pypi.yml +5 -0
- {numpy_vector_store-0.3.1 → numpy_vector_store-0.3.2}/.github/workflows/publish-testpypi.yml +5 -0
- numpy_vector_store-0.3.2/CHANGELOG.md +73 -0
- {numpy_vector_store-0.3.1 → numpy_vector_store-0.3.2}/PKG-INFO +52 -13
- {numpy_vector_store-0.3.1 → numpy_vector_store-0.3.2}/README.md +50 -11
- numpy_vector_store-0.3.2/ROADMAP.md +140 -0
- {numpy_vector_store-0.3.1 → numpy_vector_store-0.3.2}/pyproject.toml +4 -1
- {numpy_vector_store-0.3.1 → numpy_vector_store-0.3.2}/src/numpy_vector_store/__init__.py +1 -1
- {numpy_vector_store-0.3.1 → numpy_vector_store-0.3.2}/src/numpy_vector_store/vector_store.py +132 -45
- {numpy_vector_store-0.3.1 → numpy_vector_store-0.3.2}/tests/test_vector_store.py +345 -7
- {numpy_vector_store-0.3.1 → numpy_vector_store-0.3.2}/uv.lock +2 -2
- {numpy_vector_store-0.3.1 → numpy_vector_store-0.3.2}/.github/FUNDING.yml +0 -0
- {numpy_vector_store-0.3.1 → numpy_vector_store-0.3.2}/.gitignore +0 -0
- {numpy_vector_store-0.3.1 → numpy_vector_store-0.3.2}/LICENSE +0 -0
- {numpy_vector_store-0.3.1 → numpy_vector_store-0.3.2}/justfile +0 -0
- {numpy_vector_store-0.3.1 → numpy_vector_store-0.3.2}/src/numpy_vector_store/py.typed +0 -0
- {numpy_vector_store-0.3.1 → numpy_vector_store-0.3.2}/tests/__init__.py +0 -0
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
name: Checks
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_call:
|
|
5
|
+
pull_request:
|
|
6
|
+
push:
|
|
7
|
+
branches:
|
|
8
|
+
- main
|
|
9
|
+
workflow_dispatch:
|
|
10
|
+
|
|
11
|
+
concurrency:
|
|
12
|
+
group: checks-${{ github.workflow }}-${{ github.ref }}
|
|
13
|
+
cancel-in-progress: true
|
|
14
|
+
|
|
15
|
+
permissions:
|
|
16
|
+
contents: read
|
|
17
|
+
|
|
18
|
+
jobs:
|
|
19
|
+
quality:
|
|
20
|
+
name: Lint, format, and type-check
|
|
21
|
+
runs-on: ubuntu-latest
|
|
22
|
+
|
|
23
|
+
steps:
|
|
24
|
+
- name: Check out repository
|
|
25
|
+
uses: actions/checkout@v6
|
|
26
|
+
|
|
27
|
+
- name: Set up Python
|
|
28
|
+
uses: actions/setup-python@v6
|
|
29
|
+
with:
|
|
30
|
+
python-version: "3.13"
|
|
31
|
+
|
|
32
|
+
- name: Set up uv
|
|
33
|
+
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
|
|
34
|
+
with:
|
|
35
|
+
version: "0.11.32"
|
|
36
|
+
python-version: "3.13"
|
|
37
|
+
enable-cache: true
|
|
38
|
+
|
|
39
|
+
- name: Install project dependencies
|
|
40
|
+
run: uv sync --locked --group dev
|
|
41
|
+
|
|
42
|
+
- name: Run Ruff lint checks
|
|
43
|
+
run: uv run --locked ruff check .
|
|
44
|
+
|
|
45
|
+
- name: Check Ruff formatting
|
|
46
|
+
run: uv run --locked ruff format --check .
|
|
47
|
+
|
|
48
|
+
- name: Run mypy
|
|
49
|
+
run: uv run --locked mypy src/
|
|
50
|
+
|
|
51
|
+
tests:
|
|
52
|
+
name: Test Python ${{ matrix.python-version }}
|
|
53
|
+
runs-on: ubuntu-latest
|
|
54
|
+
strategy:
|
|
55
|
+
fail-fast: false
|
|
56
|
+
matrix:
|
|
57
|
+
python-version:
|
|
58
|
+
- "3.10"
|
|
59
|
+
- "3.11"
|
|
60
|
+
- "3.12"
|
|
61
|
+
- "3.13"
|
|
62
|
+
- "3.14"
|
|
63
|
+
|
|
64
|
+
steps:
|
|
65
|
+
- name: Check out repository
|
|
66
|
+
uses: actions/checkout@v6
|
|
67
|
+
|
|
68
|
+
- name: Set up Python
|
|
69
|
+
uses: actions/setup-python@v6
|
|
70
|
+
with:
|
|
71
|
+
python-version: ${{ matrix.python-version }}
|
|
72
|
+
|
|
73
|
+
- name: Set up uv
|
|
74
|
+
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
|
|
75
|
+
with:
|
|
76
|
+
version: "0.11.32"
|
|
77
|
+
python-version: ${{ matrix.python-version }}
|
|
78
|
+
enable-cache: true
|
|
79
|
+
|
|
80
|
+
- name: Install project dependencies
|
|
81
|
+
run: uv sync --locked --group dev
|
|
82
|
+
|
|
83
|
+
- name: Run tests
|
|
84
|
+
run: uv run --locked pytest
|
|
85
|
+
|
|
86
|
+
minimum-numpy:
|
|
87
|
+
name: Test minimum NumPy on Python 3.10
|
|
88
|
+
runs-on: ubuntu-latest
|
|
89
|
+
|
|
90
|
+
steps:
|
|
91
|
+
- name: Check out repository
|
|
92
|
+
uses: actions/checkout@v6
|
|
93
|
+
|
|
94
|
+
- name: Set up Python
|
|
95
|
+
uses: actions/setup-python@v6
|
|
96
|
+
with:
|
|
97
|
+
python-version: "3.10"
|
|
98
|
+
|
|
99
|
+
- name: Set up uv
|
|
100
|
+
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
|
|
101
|
+
with:
|
|
102
|
+
version: "0.11.32"
|
|
103
|
+
python-version: "3.10"
|
|
104
|
+
enable-cache: true
|
|
105
|
+
|
|
106
|
+
- name: Run tests with the minimum NumPy version
|
|
107
|
+
run: >-
|
|
108
|
+
uv run
|
|
109
|
+
--isolated
|
|
110
|
+
--no-project
|
|
111
|
+
--python 3.10
|
|
112
|
+
--with-editable .
|
|
113
|
+
--with numpy==1.21.3
|
|
114
|
+
--with pytest==8.4.2
|
|
115
|
+
python -m pytest
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
This changelog records user-visible changes to NumPy Vector Store. Earlier
|
|
4
|
+
release notes remain available on the
|
|
5
|
+
[GitHub releases page](https://github.com/tvanreenen/numpy-vector-store/releases).
|
|
6
|
+
|
|
7
|
+
## 0.3.2 - 2026-07-27
|
|
8
|
+
|
|
9
|
+
This reliability and performance patch makes existing vector storage, search,
|
|
10
|
+
metadata, and persistence behavior safer and more predictable. It does not
|
|
11
|
+
intentionally break valid existing usage or change the `.npz` archive format.
|
|
12
|
+
|
|
13
|
+
### Numerical reliability
|
|
14
|
+
|
|
15
|
+
- Reject vectors, queries, and search thresholds that contain non-finite values
|
|
16
|
+
or cannot remain finite when represented as `float32`. Invalid input now
|
|
17
|
+
fails before it can corrupt stored state or ranking.
|
|
18
|
+
- Calculate norms and raw metric intermediates with `float64` where `float32`
|
|
19
|
+
could overflow or underflow. Large and very small finite vectors can now be
|
|
20
|
+
normalized and compared reliably.
|
|
21
|
+
- Allow zero vectors in stores created with `normalize=False`, where they are
|
|
22
|
+
valid for dot-product and Euclidean search.
|
|
23
|
+
- Raise a clear error if a raw cosine search includes a zero vector, because
|
|
24
|
+
cosine similarity is undefined for that row.
|
|
25
|
+
- Avoid duplicate full-size `float64` buffers when calculating raw Euclidean
|
|
26
|
+
distance.
|
|
27
|
+
|
|
28
|
+
### Persistence
|
|
29
|
+
|
|
30
|
+
- Resolve a path without an `.npz` suffix to the same archive for both saving
|
|
31
|
+
and loading. For example, `file_path="vectors"` consistently uses
|
|
32
|
+
`vectors.npz`.
|
|
33
|
+
- Allow `load()` to be retried when the persistence file did not exist during
|
|
34
|
+
an earlier attempt.
|
|
35
|
+
- Reset load state in `clear()` so a subsequent explicit `load()` can restore
|
|
36
|
+
the saved rows.
|
|
37
|
+
- Keep repeated `load()` calls idempotent after a successful load.
|
|
38
|
+
|
|
39
|
+
### Metadata
|
|
40
|
+
|
|
41
|
+
- Preserve each item in the outer metadata sequence as one opaque row payload.
|
|
42
|
+
Tuples and lists are no longer mistaken for extra NumPy array dimensions.
|
|
43
|
+
- Support dictionary, dataclass, tuple, list, string, integer, and other scalar
|
|
44
|
+
payloads consistently through insertion, search results, saving, and loading.
|
|
45
|
+
- Continue rejecting explicitly multidimensional NumPy metadata arrays rather
|
|
46
|
+
than silently flattening ambiguous input.
|
|
47
|
+
|
|
48
|
+
### Search memory use
|
|
49
|
+
|
|
50
|
+
- Search the stored vector matrix directly when `within_rows` is omitted,
|
|
51
|
+
avoiding an unnecessary full-matrix copy on every unfiltered query.
|
|
52
|
+
- Preserve original store indexes and metadata when `within_rows` selects a
|
|
53
|
+
filtered subset.
|
|
54
|
+
- Document that filtered searches allocate a temporary matrix proportional to
|
|
55
|
+
the selected row count and vector dimensions.
|
|
56
|
+
|
|
57
|
+
### Compatibility and validation
|
|
58
|
+
|
|
59
|
+
- Test Python 3.10 through 3.14 in GitHub Actions.
|
|
60
|
+
- Test the minimum supported NumPy version in a dedicated Python 3.10 job.
|
|
61
|
+
- Raise the minimum NumPy requirement from 1.20 to 1.21.3 so it is compatible
|
|
62
|
+
with the oldest supported Python version.
|
|
63
|
+
- Require linting, formatting, type checking, and the full Python test matrix
|
|
64
|
+
before publishing to PyPI.
|
|
65
|
+
|
|
66
|
+
### Upgrade notes
|
|
67
|
+
|
|
68
|
+
- No public method signatures or persisted field names changed.
|
|
69
|
+
- Existing trusted `.npz` archives with `vectors` and `metadata` remain
|
|
70
|
+
readable.
|
|
71
|
+
- Environments using NumPy 1.20 must upgrade to NumPy 1.21.3 or newer.
|
|
72
|
+
- Inputs that previously produced `nan`, `inf`, or unreliable rankings now
|
|
73
|
+
raise `ValueError` instead.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: numpy-vector-store
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.2
|
|
4
4
|
Summary: A fast, lightweight, and zero-setup in-memory vector store powered by NumPy
|
|
5
5
|
Project-URL: Homepage, https://github.com/tvanreenen/numpy-vector-store
|
|
6
6
|
Project-URL: Repository, https://github.com/tvanreenen/numpy-vector-store
|
|
@@ -19,7 +19,7 @@ Classifier: Programming Language :: Python :: 3.12
|
|
|
19
19
|
Classifier: Programming Language :: Python :: 3.13
|
|
20
20
|
Classifier: Programming Language :: Python :: 3.14
|
|
21
21
|
Requires-Python: >=3.10
|
|
22
|
-
Requires-Dist: numpy>=1.
|
|
22
|
+
Requires-Dist: numpy>=1.21.3
|
|
23
23
|
Description-Content-Type: text/markdown
|
|
24
24
|
|
|
25
25
|
# NumPy Vector Store
|
|
@@ -89,9 +89,10 @@ for hit in hits:
|
|
|
89
89
|
print(f"{hit.metadata['title']}: {hit.value:.3f}")
|
|
90
90
|
```
|
|
91
91
|
|
|
92
|
-
`metadata` is an
|
|
93
|
-
dataclass, string, integer row ID, or
|
|
94
|
-
application.
|
|
92
|
+
`metadata` is an outer sequence with one opaque payload for each vector row.
|
|
93
|
+
Each payload can be a dict, dataclass, tuple, list, string, integer row ID, or
|
|
94
|
+
another Python object that fits your application. Tuple and list payloads remain
|
|
95
|
+
single row values rather than being interpreted as additional array dimensions.
|
|
95
96
|
|
|
96
97
|
## Normalization
|
|
97
98
|
|
|
@@ -107,8 +108,23 @@ which is the common case for semantic embeddings. Use `normalize=False` when
|
|
|
107
108
|
vector length matters, such as when magnitude encodes strength, confidence,
|
|
108
109
|
counts, scale, or raw geometry.
|
|
109
110
|
|
|
110
|
-
Zero vectors are rejected
|
|
111
|
-
for
|
|
111
|
+
Zero vectors are rejected when `normalize=True` because they cannot be scaled to
|
|
112
|
+
unit length. Raw stores accept zero vectors for dot-product and Euclidean
|
|
113
|
+
search. Because cosine similarity is undefined for zero vectors,
|
|
114
|
+
`cosine_search` raises an error when its selected rows include one; use
|
|
115
|
+
`within_rows` to exclude zero rows when needed.
|
|
116
|
+
|
|
117
|
+
### Numerical inputs
|
|
118
|
+
|
|
119
|
+
Stored vectors use `float32` to keep the store compact. Vectors and queries must
|
|
120
|
+
remain finite when converted to `float32`, and search thresholds must also be
|
|
121
|
+
finite. Invalid values are rejected before they can affect stored state or
|
|
122
|
+
ranking.
|
|
123
|
+
|
|
124
|
+
Norms and raw metric values use `float64` accumulation where `float32`
|
|
125
|
+
intermediate calculations could overflow or underflow. This allows finite
|
|
126
|
+
`float32` vectors across the representable magnitude range to be normalized and
|
|
127
|
+
compared reliably.
|
|
112
128
|
|
|
113
129
|
| Method | `normalize=True` default | `normalize=False` |
|
|
114
130
|
|---|---|---|
|
|
@@ -160,6 +176,13 @@ rows = [
|
|
|
160
176
|
hits = store.cosine_search(query, top_k=10, within_rows=rows)
|
|
161
177
|
```
|
|
162
178
|
|
|
179
|
+
Searches without `within_rows` compute directly against the stored vector matrix
|
|
180
|
+
and do not make a full copy of it. A filtered search gathers the selected rows
|
|
181
|
+
into a temporary matrix, so its additional memory use scales with the number of
|
|
182
|
+
selected rows and the vector dimensions. Omit `within_rows` when every row
|
|
183
|
+
should be searched; passing every row explicitly would create an unnecessary
|
|
184
|
+
full-size temporary matrix.
|
|
185
|
+
|
|
163
186
|
For structured NumPy metadata, use NumPy to produce the row indexes:
|
|
164
187
|
|
|
165
188
|
```python
|
|
@@ -198,6 +221,9 @@ loaded = VectorStore[dict[str, str]](dimensions=1536, file_path="vectors.npz")
|
|
|
198
221
|
loaded.load()
|
|
199
222
|
```
|
|
200
223
|
|
|
224
|
+
The `.npz` suffix may be omitted. An extensionless path such as `"vectors"` is
|
|
225
|
+
resolved to `"vectors.npz"` for both saving and loading.
|
|
226
|
+
|
|
201
227
|
If you save with `normalize=False`, load with `normalize=False` too:
|
|
202
228
|
|
|
203
229
|
```python
|
|
@@ -227,16 +253,29 @@ with VectorStore[dict[str, str]](dimensions=1536, file_path="vectors.npz") as st
|
|
|
227
253
|
Persistence uses a minimal NumPy `.npz` contract with `vectors` and `metadata`
|
|
228
254
|
arrays. The `.npz` file does not encode the `normalize` setting; choose the same
|
|
229
255
|
setting when loading that you used when saving. Loading validates shape,
|
|
230
|
-
dimensions, row counts, and zero-norm vectors.
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
256
|
+
dimensions, row counts, and zero-norm vectors. A `load()` call made before the
|
|
257
|
+
file exists can be retried after the file is created. Repeated calls after a
|
|
258
|
+
successful load do nothing unless `clear()` resets the in-memory store. Opaque
|
|
259
|
+
metadata values remain individual row payloads across save/load round trips.
|
|
260
|
+
Persistence uses `allow_pickle=True` for flexible Python metadata payloads, so
|
|
261
|
+
only load files generated by your own application or another trusted local
|
|
262
|
+
process. Loading untrusted `.npz` files is not a supported security model.
|
|
234
263
|
|
|
235
264
|
## Compatibility
|
|
236
265
|
|
|
237
266
|
This project is still pre-1.0, so occasional breaking changes are expected while
|
|
238
|
-
the API stabilizes.
|
|
239
|
-
Deprecated APIs will keep warning for at least one point
|
|
267
|
+
the API stabilizes. Changes are documented in the [changelog](CHANGELOG.md) and
|
|
268
|
+
GitHub release notes. Deprecated APIs will keep warning for at least one point
|
|
269
|
+
release before removal.
|
|
270
|
+
|
|
271
|
+
Supported Python versions are listed in the package classifiers and exercised
|
|
272
|
+
in CI. The project generally retains stable CPython versions until their
|
|
273
|
+
upstream end-of-life, adds new versions after its dependencies and CI support
|
|
274
|
+
them, and drops versions only in minor releases.
|
|
275
|
+
|
|
276
|
+
See the [changelog](CHANGELOG.md) for release history and the
|
|
277
|
+
[project roadmap](ROADMAP.md) for the planned path to stable API and persistence
|
|
278
|
+
contracts.
|
|
240
279
|
|
|
241
280
|
## Contributing
|
|
242
281
|
|
|
@@ -65,9 +65,10 @@ for hit in hits:
|
|
|
65
65
|
print(f"{hit.metadata['title']}: {hit.value:.3f}")
|
|
66
66
|
```
|
|
67
67
|
|
|
68
|
-
`metadata` is an
|
|
69
|
-
dataclass, string, integer row ID, or
|
|
70
|
-
application.
|
|
68
|
+
`metadata` is an outer sequence with one opaque payload for each vector row.
|
|
69
|
+
Each payload can be a dict, dataclass, tuple, list, string, integer row ID, or
|
|
70
|
+
another Python object that fits your application. Tuple and list payloads remain
|
|
71
|
+
single row values rather than being interpreted as additional array dimensions.
|
|
71
72
|
|
|
72
73
|
## Normalization
|
|
73
74
|
|
|
@@ -83,8 +84,23 @@ which is the common case for semantic embeddings. Use `normalize=False` when
|
|
|
83
84
|
vector length matters, such as when magnitude encodes strength, confidence,
|
|
84
85
|
counts, scale, or raw geometry.
|
|
85
86
|
|
|
86
|
-
Zero vectors are rejected
|
|
87
|
-
for
|
|
87
|
+
Zero vectors are rejected when `normalize=True` because they cannot be scaled to
|
|
88
|
+
unit length. Raw stores accept zero vectors for dot-product and Euclidean
|
|
89
|
+
search. Because cosine similarity is undefined for zero vectors,
|
|
90
|
+
`cosine_search` raises an error when its selected rows include one; use
|
|
91
|
+
`within_rows` to exclude zero rows when needed.
|
|
92
|
+
|
|
93
|
+
### Numerical inputs
|
|
94
|
+
|
|
95
|
+
Stored vectors use `float32` to keep the store compact. Vectors and queries must
|
|
96
|
+
remain finite when converted to `float32`, and search thresholds must also be
|
|
97
|
+
finite. Invalid values are rejected before they can affect stored state or
|
|
98
|
+
ranking.
|
|
99
|
+
|
|
100
|
+
Norms and raw metric values use `float64` accumulation where `float32`
|
|
101
|
+
intermediate calculations could overflow or underflow. This allows finite
|
|
102
|
+
`float32` vectors across the representable magnitude range to be normalized and
|
|
103
|
+
compared reliably.
|
|
88
104
|
|
|
89
105
|
| Method | `normalize=True` default | `normalize=False` |
|
|
90
106
|
|---|---|---|
|
|
@@ -136,6 +152,13 @@ rows = [
|
|
|
136
152
|
hits = store.cosine_search(query, top_k=10, within_rows=rows)
|
|
137
153
|
```
|
|
138
154
|
|
|
155
|
+
Searches without `within_rows` compute directly against the stored vector matrix
|
|
156
|
+
and do not make a full copy of it. A filtered search gathers the selected rows
|
|
157
|
+
into a temporary matrix, so its additional memory use scales with the number of
|
|
158
|
+
selected rows and the vector dimensions. Omit `within_rows` when every row
|
|
159
|
+
should be searched; passing every row explicitly would create an unnecessary
|
|
160
|
+
full-size temporary matrix.
|
|
161
|
+
|
|
139
162
|
For structured NumPy metadata, use NumPy to produce the row indexes:
|
|
140
163
|
|
|
141
164
|
```python
|
|
@@ -174,6 +197,9 @@ loaded = VectorStore[dict[str, str]](dimensions=1536, file_path="vectors.npz")
|
|
|
174
197
|
loaded.load()
|
|
175
198
|
```
|
|
176
199
|
|
|
200
|
+
The `.npz` suffix may be omitted. An extensionless path such as `"vectors"` is
|
|
201
|
+
resolved to `"vectors.npz"` for both saving and loading.
|
|
202
|
+
|
|
177
203
|
If you save with `normalize=False`, load with `normalize=False` too:
|
|
178
204
|
|
|
179
205
|
```python
|
|
@@ -203,16 +229,29 @@ with VectorStore[dict[str, str]](dimensions=1536, file_path="vectors.npz") as st
|
|
|
203
229
|
Persistence uses a minimal NumPy `.npz` contract with `vectors` and `metadata`
|
|
204
230
|
arrays. The `.npz` file does not encode the `normalize` setting; choose the same
|
|
205
231
|
setting when loading that you used when saving. Loading validates shape,
|
|
206
|
-
dimensions, row counts, and zero-norm vectors.
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
232
|
+
dimensions, row counts, and zero-norm vectors. A `load()` call made before the
|
|
233
|
+
file exists can be retried after the file is created. Repeated calls after a
|
|
234
|
+
successful load do nothing unless `clear()` resets the in-memory store. Opaque
|
|
235
|
+
metadata values remain individual row payloads across save/load round trips.
|
|
236
|
+
Persistence uses `allow_pickle=True` for flexible Python metadata payloads, so
|
|
237
|
+
only load files generated by your own application or another trusted local
|
|
238
|
+
process. Loading untrusted `.npz` files is not a supported security model.
|
|
210
239
|
|
|
211
240
|
## Compatibility
|
|
212
241
|
|
|
213
242
|
This project is still pre-1.0, so occasional breaking changes are expected while
|
|
214
|
-
the API stabilizes.
|
|
215
|
-
Deprecated APIs will keep warning for at least one point
|
|
243
|
+
the API stabilizes. Changes are documented in the [changelog](CHANGELOG.md) and
|
|
244
|
+
GitHub release notes. Deprecated APIs will keep warning for at least one point
|
|
245
|
+
release before removal.
|
|
246
|
+
|
|
247
|
+
Supported Python versions are listed in the package classifiers and exercised
|
|
248
|
+
in CI. The project generally retains stable CPython versions until their
|
|
249
|
+
upstream end-of-life, adds new versions after its dependencies and CI support
|
|
250
|
+
them, and drops versions only in minor releases.
|
|
251
|
+
|
|
252
|
+
See the [changelog](CHANGELOG.md) for release history and the
|
|
253
|
+
[project roadmap](ROADMAP.md) for the planned path to stable API and persistence
|
|
254
|
+
contracts.
|
|
216
255
|
|
|
217
256
|
## Contributing
|
|
218
257
|
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
# Roadmap
|
|
2
|
+
|
|
3
|
+
NumPy Vector Store is intentionally small: it provides exact in-memory vector
|
|
4
|
+
search without adding a service, indexing system, or metadata query language.
|
|
5
|
+
This roadmap explains how the project will make that focused core safer and
|
|
6
|
+
more predictable on the way to a stable 1.0 release.
|
|
7
|
+
|
|
8
|
+
The roadmap describes direction rather than delivery dates. Priorities may
|
|
9
|
+
change as the library receives real-world feedback, and each release will have
|
|
10
|
+
its final scope documented in its release notes.
|
|
11
|
+
|
|
12
|
+
## Versioning approach
|
|
13
|
+
|
|
14
|
+
The project follows semantic versioning while it is pre-1.0:
|
|
15
|
+
|
|
16
|
+
- Patch releases such as 0.3.2 fix defects and improve existing documented
|
|
17
|
+
behavior without intentionally breaking valid usage.
|
|
18
|
+
- Minor releases such as 0.4.0 may change behavior or file formats when that is
|
|
19
|
+
necessary to establish safer long-term contracts. Those changes will be
|
|
20
|
+
called out clearly and will preserve compatibility where practical.
|
|
21
|
+
- The 1.0.0 release will mark a commitment to a stable public API and
|
|
22
|
+
persistence contract.
|
|
23
|
+
|
|
24
|
+
Deprecated APIs will continue to warn for at least one point release before
|
|
25
|
+
removal. Persisted data will receive an explicit compatibility and migration
|
|
26
|
+
story before the project reaches 1.0.
|
|
27
|
+
|
|
28
|
+
## Runtime support policy
|
|
29
|
+
|
|
30
|
+
The Python versions listed in the package classifiers are part of the public
|
|
31
|
+
compatibility contract and are exercised in CI. The project generally:
|
|
32
|
+
|
|
33
|
+
- Supports stable CPython versions until their upstream end-of-life.
|
|
34
|
+
- Adds a newly stable Python version after NumPy and the project's test suite
|
|
35
|
+
support it.
|
|
36
|
+
- Drops a Python version only in a minor release and calls out the change in
|
|
37
|
+
release notes.
|
|
38
|
+
|
|
39
|
+
The 0.3 series supports Python 3.10 through 3.14. Python 3.10 reaches upstream
|
|
40
|
+
end-of-life in October 2026 and is expected to be removed in 0.4.0 rather than
|
|
41
|
+
in a 0.3 patch release.
|
|
42
|
+
|
|
43
|
+
Supported NumPy versions are also part of the runtime contract. The declared
|
|
44
|
+
minimum should be installable on the oldest supported Python version and should
|
|
45
|
+
have a dedicated minimum-dependency CI check. The regular Python matrix will
|
|
46
|
+
continue to test the versions selected by the project's lockfile.
|
|
47
|
+
|
|
48
|
+
## 0.3.2: Reliability and performance
|
|
49
|
+
|
|
50
|
+
Status: complete
|
|
51
|
+
|
|
52
|
+
This patch release focuses on cases where the current API can silently produce
|
|
53
|
+
incorrect results, fail to reload data it saved, reject documented metadata
|
|
54
|
+
payloads, or allocate much more memory than an exact search requires.
|
|
55
|
+
|
|
56
|
+
Delivered changes:
|
|
57
|
+
|
|
58
|
+
- Validate vectors and queries for finite numeric values.
|
|
59
|
+
- Normalize large finite vectors without overflowing intermediate `float32`
|
|
60
|
+
calculations.
|
|
61
|
+
- Accumulate raw metric values in `float64` when `float32` intermediates could
|
|
62
|
+
overflow.
|
|
63
|
+
- Permit zero vectors in raw stores used for dot-product or Euclidean search,
|
|
64
|
+
while keeping cosine similarity's undefined zero-vector behavior explicit.
|
|
65
|
+
- Make extensionless persistence paths save and load the same `.npz` file.
|
|
66
|
+
- Allow loading to be retried when the persistence file was initially absent.
|
|
67
|
+
- Preserve tuple, list, dataclass, scalar, and dictionary metadata as individual
|
|
68
|
+
opaque row payloads.
|
|
69
|
+
- Avoid copying the complete vector matrix during an unfiltered search.
|
|
70
|
+
- Add continuous validation across every supported Python version and require
|
|
71
|
+
equivalent checks before publishing.
|
|
72
|
+
- Align the minimum NumPy requirement with Python 3.10 support and add a
|
|
73
|
+
minimum-dependency compatibility check.
|
|
74
|
+
|
|
75
|
+
These changes are intended to preserve results and behavior for valid existing
|
|
76
|
+
usage. Public state access, the persistence format, and context-manager
|
|
77
|
+
semantics will not change in this patch release.
|
|
78
|
+
|
|
79
|
+
## 0.4.0: Persistence and lifecycle
|
|
80
|
+
|
|
81
|
+
The persistence format currently stores only vectors and metadata. That format
|
|
82
|
+
is compact, but callers must separately remember dimensions and normalization
|
|
83
|
+
mode. A safer format should be self-describing and able to reject incompatible
|
|
84
|
+
configuration instead of silently changing vector semantics.
|
|
85
|
+
|
|
86
|
+
Planned direction:
|
|
87
|
+
|
|
88
|
+
- Introduce a versioned archive containing its dimensions and normalization
|
|
89
|
+
mode.
|
|
90
|
+
- Continue reading the existing two-array archive format.
|
|
91
|
+
- Write archives through a temporary file and replace the destination
|
|
92
|
+
atomically.
|
|
93
|
+
- Define the difference between initial loading and explicit reloading.
|
|
94
|
+
- Define whether context-manager exit saves after an exception.
|
|
95
|
+
|
|
96
|
+
## 0.5.0: State safety and ingestion
|
|
97
|
+
|
|
98
|
+
The current public NumPy arrays make inspection convenient, but they also let
|
|
99
|
+
callers mutate normalized vectors and break internal search assumptions.
|
|
100
|
+
Repeated small additions also copy all previously stored data.
|
|
101
|
+
|
|
102
|
+
Planned direction:
|
|
103
|
+
|
|
104
|
+
- Keep vector storage behind private state.
|
|
105
|
+
- Expose read-only views or snapshots for inspection.
|
|
106
|
+
- Make row retrieval safe from accidental mutation.
|
|
107
|
+
- Improve ingestion for repeated additions without penalizing batch insertion.
|
|
108
|
+
- Define deterministic ordering for equal search values.
|
|
109
|
+
- Document thread-safety guarantees and limitations.
|
|
110
|
+
|
|
111
|
+
## 0.6.0: API stabilization
|
|
112
|
+
|
|
113
|
+
This release is intended to consolidate the earlier changes rather than add a
|
|
114
|
+
new feature family.
|
|
115
|
+
|
|
116
|
+
Planned direction:
|
|
117
|
+
|
|
118
|
+
- Make validation and exception behavior consistent across methods.
|
|
119
|
+
- Add performance regression coverage for representative store sizes.
|
|
120
|
+
- Exercise persistence upgrades and backwards compatibility.
|
|
121
|
+
- Resolve known high- and medium-priority defects.
|
|
122
|
+
- Complete documentation of ordering, memory use, concurrency, and trusted-file
|
|
123
|
+
requirements.
|
|
124
|
+
|
|
125
|
+
## 1.0.0: Stable contracts
|
|
126
|
+
|
|
127
|
+
The project will be ready for 1.0 when:
|
|
128
|
+
|
|
129
|
+
- The public API has completed at least one minor release cycle without
|
|
130
|
+
structural redesign.
|
|
131
|
+
- Public access cannot silently invalidate vector-store invariants.
|
|
132
|
+
- Persistence is self-describing and has a documented migration policy.
|
|
133
|
+
- Supported numeric inputs behave reliably across supported Python and NumPy
|
|
134
|
+
versions.
|
|
135
|
+
- Search and ingestion complexity are documented and covered by regression
|
|
136
|
+
tests.
|
|
137
|
+
|
|
138
|
+
Reaching 1.0 does not require turning the project into a vector database. The
|
|
139
|
+
library will continue to favor a small exact-search API over indexing services,
|
|
140
|
+
framework integrations, or a built-in metadata query language.
|
|
@@ -25,7 +25,7 @@ classifiers = [
|
|
|
25
25
|
"Programming Language :: Python :: 3.14",
|
|
26
26
|
]
|
|
27
27
|
dependencies = [
|
|
28
|
-
"numpy>=1.
|
|
28
|
+
"numpy>=1.21.3",
|
|
29
29
|
]
|
|
30
30
|
|
|
31
31
|
|
|
@@ -37,6 +37,9 @@ Issues = "https://github.com/tvanreenen/numpy-vector-store/issues"
|
|
|
37
37
|
[tool.hatch.build.targets.wheel]
|
|
38
38
|
packages = ["src/numpy_vector_store"]
|
|
39
39
|
|
|
40
|
+
[tool.hatch.build.targets.sdist]
|
|
41
|
+
exclude = ["/.codex"]
|
|
42
|
+
|
|
40
43
|
[tool.hatch.version]
|
|
41
44
|
path = "src/numpy_vector_store/__init__.py"
|
|
42
45
|
|
|
@@ -5,7 +5,7 @@ This package provides a lightweight vector store implementation for storing
|
|
|
5
5
|
and searching vector embeddings using NumPy arrays.
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
|
-
__version__ = "0.3.
|
|
8
|
+
__version__ = "0.3.2"
|
|
9
9
|
__author__ = "Tim VanReenen"
|
|
10
10
|
|
|
11
11
|
from .vector_store import VectorHit, VectorStore
|