pylattice-db 0.1.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.
Files changed (66) hide show
  1. pylattice_db-0.1.2/.github/workflows/ci.yml +143 -0
  2. pylattice_db-0.1.2/.gitignore +38 -0
  3. pylattice_db-0.1.2/CMakeLists.txt +16 -0
  4. pylattice_db-0.1.2/LICENSE +21 -0
  5. pylattice_db-0.1.2/PKG-INFO +281 -0
  6. pylattice_db-0.1.2/README.md +243 -0
  7. pylattice_db-0.1.2/app/.gitkeep +0 -0
  8. pylattice_db-0.1.2/app/chunker.py +104 -0
  9. pylattice_db-0.1.2/app/cli.py +100 -0
  10. pylattice_db-0.1.2/app/embedder.py +48 -0
  11. pylattice_db-0.1.2/app/gui.py +217 -0
  12. pylattice_db-0.1.2/app/requirements.txt +5 -0
  13. pylattice_db-0.1.2/app/reranker.py +48 -0
  14. pylattice_db-0.1.2/app/store.py +197 -0
  15. pylattice_db-0.1.2/app/synthesizer.py +87 -0
  16. pylattice_db-0.1.2/bench/.gitkeep +0 -0
  17. pylattice_db-0.1.2/bench/baseline.json +11 -0
  18. pylattice_db-0.1.2/bench/check_regression.py +82 -0
  19. pylattice_db-0.1.2/bench/current.json +11 -0
  20. pylattice_db-0.1.2/bench/fvecs.py +51 -0
  21. pylattice_db-0.1.2/bench/requirements.txt +3 -0
  22. pylattice_db-0.1.2/bench/results-ef10.md +18 -0
  23. pylattice_db-0.1.2/bench/results-ef100.md +18 -0
  24. pylattice_db-0.1.2/bench/results-sift1m.md +18 -0
  25. pylattice_db-0.1.2/bench/results.md +16 -0
  26. pylattice_db-0.1.2/bench/run.py +367 -0
  27. pylattice_db-0.1.2/bindings/.gitkeep +0 -0
  28. pylattice_db-0.1.2/bindings/CMakeLists.txt +13 -0
  29. pylattice_db-0.1.2/bindings/dist/lattice_db-0.1.0.tar.gz +0 -0
  30. pylattice_db-0.1.2/bindings/lattice_py.cpp +89 -0
  31. pylattice_db-0.1.2/cli/CMakeLists.txt +2 -0
  32. pylattice_db-0.1.2/cli/main.cpp +116 -0
  33. pylattice_db-0.1.2/core/CMakeLists.txt +39 -0
  34. pylattice_db-0.1.2/core/include/lattice/concurrent_index.hpp +69 -0
  35. pylattice_db-0.1.2/core/include/lattice/database.hpp +61 -0
  36. pylattice_db-0.1.2/core/include/lattice/distance.hpp +17 -0
  37. pylattice_db-0.1.2/core/include/lattice/flat_store.hpp +31 -0
  38. pylattice_db-0.1.2/core/include/lattice/hnsw.hpp +100 -0
  39. pylattice_db-0.1.2/core/include/lattice/planner.hpp +42 -0
  40. pylattice_db-0.1.2/core/include/lattice/quantizer.hpp +56 -0
  41. pylattice_db-0.1.2/core/include/lattice/search.hpp +29 -0
  42. pylattice_db-0.1.2/core/include/lattice/segment.hpp +65 -0
  43. pylattice_db-0.1.2/core/include/lattice/vector.hpp +19 -0
  44. pylattice_db-0.1.2/core/include/lattice/wal.hpp +41 -0
  45. pylattice_db-0.1.2/core/src/concurrent_index.cpp +35 -0
  46. pylattice_db-0.1.2/core/src/database.cpp +124 -0
  47. pylattice_db-0.1.2/core/src/distance.cpp +19 -0
  48. pylattice_db-0.1.2/core/src/flat_store.cpp +34 -0
  49. pylattice_db-0.1.2/core/src/hnsw.cpp +323 -0
  50. pylattice_db-0.1.2/core/src/main.cpp +278 -0
  51. pylattice_db-0.1.2/core/src/quantizer.cpp +95 -0
  52. pylattice_db-0.1.2/core/src/search.cpp +64 -0
  53. pylattice_db-0.1.2/core/src/segment.cpp +151 -0
  54. pylattice_db-0.1.2/core/src/wal.cpp +76 -0
  55. pylattice_db-0.1.2/core/tests/CMakeLists.txt +24 -0
  56. pylattice_db-0.1.2/core/tests/test_hnsw.cpp +152 -0
  57. pylattice_db-0.1.2/core/tests/test_quantizer.cpp +114 -0
  58. pylattice_db-0.1.2/core/tests/test_search.cpp +86 -0
  59. pylattice_db-0.1.2/core/tests/test_segment.cpp +80 -0
  60. pylattice_db-0.1.2/core/tests/test_wal.cpp +104 -0
  61. pylattice_db-0.1.2/docs/.gitkeep +0 -0
  62. pylattice_db-0.1.2/docs/DESIGN.md +210 -0
  63. pylattice_db-0.1.2/docs/screenshots/gui-correct-answer.png +0 -0
  64. pylattice_db-0.1.2/docs/screenshots/gui-failure-example.png +0 -0
  65. pylattice_db-0.1.2/pyproject.toml +39 -0
  66. pylattice_db-0.1.2/server/.gitkeep +0 -0
@@ -0,0 +1,143 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ jobs:
10
+ build-and-test:
11
+ name: Build and test
12
+ runs-on: ubuntu-latest
13
+
14
+ steps:
15
+ - uses: actions/checkout@v4
16
+
17
+ - name: Install build dependencies
18
+ run: |
19
+ sudo apt-get update
20
+ sudo apt-get install -y cmake build-essential
21
+
22
+ - name: Set up Python
23
+ uses: actions/setup-python@v5
24
+ with:
25
+ python-version: "3.12"
26
+
27
+ - name: Install pybind11
28
+ run: pip install pybind11
29
+
30
+ - name: Configure
31
+ run: |
32
+ cmake -B build \
33
+ -DCMAKE_BUILD_TYPE=Release \
34
+ -DLATTICE_BUILD_TESTS=ON \
35
+ -Dpybind11_DIR=$(python -m pybind11 --cmakedir)
36
+
37
+ - name: Build
38
+ run: cmake --build build -j$(nproc)
39
+
40
+ - name: Run tests
41
+ working-directory: build
42
+ run: ctest --output-on-failure
43
+
44
+ benchmark:
45
+ name: Benchmark regression gate
46
+ runs-on: ubuntu-latest
47
+ needs: build-and-test
48
+
49
+ steps:
50
+ - uses: actions/checkout@v4
51
+
52
+ - name: Install build dependencies
53
+ run: |
54
+ sudo apt-get update
55
+ sudo apt-get install -y cmake build-essential
56
+
57
+ - name: Set up Python
58
+ uses: actions/setup-python@v5
59
+ with:
60
+ python-version: "3.12"
61
+
62
+ - name: Install Python dependencies
63
+ run: pip install pybind11 numpy
64
+
65
+ - name: Configure and build
66
+ run: |
67
+ cmake -B build \
68
+ -DCMAKE_BUILD_TYPE=Release \
69
+ -Dpybind11_DIR=$(python -m pybind11 --cmakedir)
70
+ cmake --build build -j$(nproc)
71
+
72
+ - name: Cache SIFT small dataset
73
+ id: cache-sift
74
+ uses: actions/cache@v4
75
+ with:
76
+ path: bench/data/siftsmall
77
+ key: siftsmall-v1
78
+
79
+ - name: Download SIFT small
80
+ if: steps.cache-sift.outputs.cache-hit != 'true'
81
+ run: |
82
+ mkdir -p bench/data
83
+ cd bench/data
84
+ curl -O ftp://ftp.irisa.fr/local/texmex/corpus/siftsmall.tar.gz
85
+ tar -xzf siftsmall.tar.gz
86
+
87
+ - name: Run benchmark
88
+ working-directory: bench
89
+ env:
90
+ LATTICE_BUILD_DIR: build
91
+ run: python run.py --skip qdrant,chroma --json current.json
92
+
93
+ - name: Check for regression
94
+ working-directory: bench
95
+ run: python check_regression.py --current current.json
96
+
97
+ coverage:
98
+ name: Test coverage
99
+ runs-on: ubuntu-latest
100
+ needs: build-and-test
101
+
102
+ steps:
103
+ - uses: actions/checkout@v4
104
+
105
+ - name: Install dependencies
106
+ run: |
107
+ sudo apt-get update
108
+ sudo apt-get install -y cmake build-essential lcov
109
+
110
+ - name: Set up Python
111
+ uses: actions/setup-python@v5
112
+ with:
113
+ python-version: "3.12"
114
+
115
+ - name: Install pybind11
116
+ run: pip install pybind11
117
+
118
+ - name: Configure with coverage
119
+ run: |
120
+ cmake -B build \
121
+ -DCMAKE_BUILD_TYPE=Debug \
122
+ -DLATTICE_BUILD_TESTS=ON \
123
+ -DLATTICE_COVERAGE=ON \
124
+ -Dpybind11_DIR=$(python -m pybind11 --cmakedir)
125
+
126
+ - name: Build and test
127
+ run: |
128
+ cmake --build build -j$(nproc)
129
+ cd build && ctest --output-on-failure
130
+
131
+ - name: Generate coverage report
132
+ run: |
133
+ lcov --capture --directory build --output-file coverage.info \
134
+ --ignore-errors mismatch,gcov
135
+ lcov --remove coverage.info '/usr/*' '*/_deps/*' '*/tests/*' \
136
+ --output-file coverage.info
137
+ lcov --list coverage.info
138
+
139
+ - name: Upload to Codecov
140
+ uses: codecov/codecov-action@v4
141
+ with:
142
+ files: coverage.info
143
+ fail_ci_if_error: false
@@ -0,0 +1,38 @@
1
+ # build output
2
+ # build output
3
+ build/
4
+ build-tsan/
5
+ build-test/
6
+ build-cov/
7
+ *.o
8
+ *.a
9
+ *.so
10
+ *.dylib
11
+
12
+ # editor / OS
13
+ .vscode/settings.json
14
+ .vscode/ipch/
15
+ .DS_Store
16
+
17
+ # python
18
+ __pycache__/
19
+ *.pyc
20
+ .venv/
21
+ venv/
22
+ .venv-tools/
23
+ bench/.venv/
24
+
25
+
26
+ # secrets
27
+ .env
28
+
29
+ # test scratch files
30
+ *.wal
31
+
32
+ notes.md
33
+
34
+ # benchmark datasets - large, downloadable, not ours to redistribute
35
+ bench/data/
36
+
37
+ app/.venv/
38
+ app/data/
@@ -0,0 +1,16 @@
1
+ cmake_minimum_required(VERSION 3.20)
2
+ project(lattice CXX)
3
+
4
+ set(CMAKE_CXX_STANDARD 20)
5
+ set(CMAKE_CXX_STANDARD_REQUIRED ON)
6
+ set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
7
+
8
+ if(NOT CMAKE_BUILD_TYPE)
9
+ set(CMAKE_BUILD_TYPE Debug)
10
+ endif()
11
+
12
+ enable_testing()
13
+
14
+ add_subdirectory(core)
15
+ add_subdirectory(cli)
16
+ add_subdirectory(bindings)
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Aman Karki
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,281 @@
1
+ Metadata-Version: 2.2
2
+ Name: pylattice-db
3
+ Version: 0.1.2
4
+ Summary: An embedded vector database with a from-scratch HNSW index
5
+ Keywords: vector-database,hnsw,similarity-search,embeddings
6
+ Author: Aman Karki
7
+ License: MIT License
8
+
9
+ Copyright (c) 2026 Aman Karki
10
+
11
+ Permission is hereby granted, free of charge, to any person obtaining a copy
12
+ of this software and associated documentation files (the "Software"), to deal
13
+ in the Software without restriction, including without limitation the rights
14
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15
+ copies of the Software, and to permit persons to whom the Software is
16
+ furnished to do so, subject to the following conditions:
17
+
18
+ The above copyright notice and this permission notice shall be included in all
19
+ copies or substantial portions of the Software.
20
+
21
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27
+ SOFTWARE.
28
+ Classifier: Development Status :: 3 - Alpha
29
+ Classifier: Intended Audience :: Developers
30
+ Classifier: License :: OSI Approved :: MIT License
31
+ Classifier: Programming Language :: C++
32
+ Classifier: Programming Language :: Python :: 3
33
+ Classifier: Topic :: Database :: Database Engines/Servers
34
+ Project-URL: Homepage, https://github.com/amankarki151/lattice
35
+ Project-URL: Repository, https://github.com/amankarki151/lattice
36
+ Requires-Python: >=3.10
37
+ Description-Content-Type: text/markdown
38
+
39
+ # Lattice
40
+
41
+ [![CI](https://github.com/amankarki151/lattice/actions/workflows/ci.yml/badge.svg)](https://github.com/amankarki151/lattice/actions/workflows/ci.yml)
42
+ [![PyPI](https://img.shields.io/pypi/v/lattice-db.svg)](https://pypi.org/project/lattice-db/)
43
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
44
+
45
+ An embedded vector database, written from scratch in C++ — a
46
+ hand-implemented HNSW index, a disk-backed storage engine with
47
+ write-ahead logging, scalar quantization, and a concurrent query path.
48
+
49
+ Most vector databases are services you run. Lattice is a library you
50
+ link against — closer to SQLite than to Postgres. Single node, no
51
+ cluster, no network hop unless you want one.
52
+
53
+ On SIFT (10,000 vectors, 128 dimensions, k=10), Lattice answers
54
+ queries in **583µs at 95.4% recall** — about 3.5x faster than Qdrant's
55
+ in-memory mode on the same data. Full numbers, including where it
56
+ loses, are below.
57
+
58
+ ## Contents
59
+
60
+ - [Installing](#installing)
61
+ - [Usage](#usage)
62
+ - [Benchmarks](#benchmarks)
63
+ - [Document assistant](#document-assistant)
64
+ - [Building from source](#building-from-source)
65
+ - [Repository layout](#repository-layout)
66
+ - [Status](#status)
67
+ - [Known limitations](#known-limitations)
68
+ - [Writing](#writing)
69
+ - [License](#license)
70
+
71
+ ## Installing
72
+
73
+ ```bash
74
+ pip install lattice-db
75
+ ```
76
+
77
+ Or [build from source](#building-from-source) if you want the CLI,
78
+ the test suite, or you're on a platform without a prebuilt wheel.
79
+
80
+ ## Usage
81
+
82
+ ### Python
83
+
84
+ ```python
85
+ import lattice
86
+
87
+ db = lattice.Database("/path/to/db")
88
+ db.insert(lattice.Vector(1, [1.0, 0.0, 0.0]))
89
+ db.insert(lattice.Vector(2, [0.0, 1.0, 0.0]))
90
+
91
+ hits = db.search([1.0, 0.0, 0.0], k=5)
92
+ for h in hits:
93
+ print(h.id, h.distance)
94
+ ```
95
+
96
+ ### Command line (built from source)
97
+
98
+ ```bash
99
+ lattice /path/to/db insert 1 1.0,0.0,0.0
100
+ lattice /path/to/db query 1.0,0.0,0.0 5
101
+ lattice /path/to/db checkpoint
102
+ lattice /path/to/db stats
103
+ ```
104
+
105
+ ### HTTP
106
+
107
+ ```bash
108
+ cd server
109
+ python3 -m venv .venv && source .venv/bin/activate
110
+ pip install -r requirements.txt
111
+ uvicorn main:app --port 8000
112
+ ```
113
+
114
+ Interactive API docs at `http://localhost:8000/docs`.
115
+
116
+ ## Benchmarks
117
+
118
+ SIFT (10,000 base vectors, 128 dimensions, k=10), against Qdrant
119
+ (in-memory mode) and Chroma. Ground truth is SIFT's own precomputed
120
+ neighbour list, not derived from any of the systems being compared.
121
+
122
+ | system | ef | build (s) | recall | p50 (µs) | p99 (µs) |
123
+ |---|---|---|---|---|---|
124
+ | Lattice | 10 | 18.5 | 0.8980 | 237 | 407 |
125
+ | Lattice | 50 | 18.5 | 0.9540 | 583 | 799 |
126
+ | Lattice | 100 | 19.0 | 0.9590 | 934 | 1234 |
127
+ | Qdrant (in-memory) | — | 0.6 | 1.0000 | 2094 | 2621 |
128
+ | Chroma | — | 0.4 | 0.9970 | 311 | 361 |
129
+
130
+ At every ef tested, Lattice beats Qdrant's query latency by 2x or
131
+ more while closing most of the recall gap. Chroma is faster on raw
132
+ query latency in this run — that's a real result, not omitted.
133
+
134
+ Where Lattice loses: build time, by a wide margin (18–19s vs under a
135
+ second for both competitors). The gap is partly architectural —
136
+ Lattice inserts one vector at a time through an exclusive lock, with
137
+ no batch-insert path yet — and partly a benchmark-harness limitation,
138
+ since Qdrant and Chroma are both inserted here via their bulk APIs.
139
+
140
+ ### SIFT1M (1,000,000 base vectors, 128 dimensions, k=10, ef=50)
141
+
142
+ | system | build (s) | recall | p50 (µs) | p99 (µs) |
143
+ |---|---|---|---|---|
144
+ | Lattice | 3954.1 | 0.8831 | 1325 | 2045 |
145
+ | Qdrant (in-memory)* | 333.7 | 0.9993 | 232946 | 1728312 |
146
+ | Chroma | 105.1 | 0.9775 | 471 | 577 |
147
+
148
+ \* Qdrant's own client warned before this run started: *"Local mode
149
+ is not recommended for collections with more than 20,000 points."*
150
+ A p99 of 1.7 seconds confirms it — this reflects local mode's storage
151
+ backend at 50x its recommended limit, not Qdrant's real capability.
152
+ Measuring Qdrant fairly at this scale would require Docker or Cloud
153
+ mode. This row is included for completeness, not as a fair
154
+ comparison.
155
+
156
+ Chroma's numbers here are a legitimate comparison point and it holds
157
+ up well at this scale. Lattice's recall dropped from 0.9540 (at 10k
158
+ vectors) to 0.8831 (at 1M vectors) at the same ef — consistent with
159
+ more vectors meaning more true neighbours competing for the same
160
+ top-k slots; a higher ef would recover recall at this size. The
161
+ build-time gap seen at 10k also holds at 1M scale — Lattice takes
162
+ 3954s against Chroma's 105s — confirming this is a systemic
163
+ architectural cost, not an artifact of the smaller dataset.
164
+
165
+ This is not a like-for-like comparison. Qdrant and Chroma are full
166
+ services with networking, persistence policies, filtering, and
167
+ metadata support. Lattice is an embedded library. Some of their
168
+ latency is buying features Lattice doesn't have. Qdrant runs in
169
+ `:memory:` mode here specifically to remove the network hop, as the
170
+ closest available approximation to comparing against a library.
171
+
172
+ Full methodology and raw output in [bench/results.md](bench/results.md).
173
+
174
+ ## Document assistant
175
+
176
+ A local-first assistant built on top of the database: ingest notes or
177
+ PDFs, ask questions in plain language, get answers with citations.
178
+ Everything — embedding, retrieval, re-ranking, and answer generation
179
+ — runs on-device. No API keys, no network calls.
180
+
181
+ ```bash
182
+ cd app
183
+ python3.12 -m venv .venv && source .venv/bin/activate
184
+ pip install -r requirements.txt
185
+
186
+ python cli.py ingest /path/to/your/notes
187
+ python cli.py ask "what did I write about X"
188
+
189
+ python gui.py # then open http://127.0.0.1:8080
190
+ ```
191
+
192
+ ![The assistant answering a question with citations](docs/screenshots/gui-correct-answer.png)
193
+
194
+ ## Building from source
195
+
196
+ Requires CMake 3.20+, a C++20 compiler, and Python 3.10+.
197
+
198
+ ```bash
199
+ git clone https://github.com/amankarki151/lattice.git
200
+ cd lattice
201
+
202
+ pip install pybind11
203
+ cmake -B build -Dpybind11_DIR=$(python -m pybind11 --cmakedir)
204
+ cmake --build build
205
+ ```
206
+
207
+ To build and run the test suite:
208
+
209
+ ```bash
210
+ cmake -B build-test -DLATTICE_BUILD_TESTS=ON \
211
+ -Dpybind11_DIR=$(python -m pybind11 --cmakedir)
212
+ cmake --build build-test
213
+ cd build-test && ctest --output-on-failure
214
+ ```
215
+
216
+ ## Repository layout
217
+
218
+ ```
219
+ core/ the database itself - storage, index, search
220
+ core/tests/ 30 tests covering storage, search, indexing, quantization
221
+ cli/ command-line tool
222
+ bindings/ pybind11 Python module
223
+ server/ FastAPI HTTP wrapper
224
+ bench/ benchmark harness and results
225
+ app/ local-first document assistant built on the database
226
+ docs/ design decisions and known limitations
227
+ ```
228
+
229
+ ## Status
230
+
231
+ Storage, search, indexing, quantization, concurrency, interfaces,
232
+ CI, and a working document assistant:
233
+
234
+ - Append-only write-ahead log with replay
235
+ - Memory-mapped segment files for settled data
236
+ - Recovery on open: load the segment, replay the WAL on top
237
+ - Checkpointing folds the WAL into a new segment via atomic rename
238
+ - Brute-force k-nearest-neighbour search over squared L2 distance
239
+ - HNSW index: layered graph construction, neighbour pruning, and
240
+ coarse-to-fine search, with recall measured against the exact path
241
+ - Scalar quantization: float32 to uint8, 4x smaller, with the recall
242
+ and speed cost measured rather than assumed
243
+ - Concurrent query path: many readers alongside a single writer,
244
+ verified clean under the thread sanitizer
245
+ - Python bindings via pybind11, with the GIL released around calls,
246
+ published on [PyPI](https://pypi.org/project/lattice-db/)
247
+ - A FastAPI HTTP server wrapping the bindings
248
+ - GoogleTest suite: 30 tests covering storage, search, indexing, and
249
+ quantization
250
+ - CI that runs the tests and fails the build on a benchmark regression
251
+ - A local-first document assistant: retrieve, re-rank with a
252
+ cross-encoder, synthesize an answer, and cite every source —
253
+ entirely offline
254
+
255
+ ## Known limitations
256
+
257
+ - **Build time is slow.** 66 minutes for a million vectors, against
258
+ Chroma's 105 seconds. Partly architectural (single-writer, no batch
259
+ insert path), partly a benchmark artifact (competitors are fed
260
+ through bulk APIs, Lattice isn't).
261
+ - **Single node only.** No sharding, no replication. This is a
262
+ library, not a cluster.
263
+ - **The assistant produces nonsense for out-of-scope questions.**
264
+ Asked something the documents don't cover, the local synthesis
265
+ model returns malformed text rather than refusing. Real example and
266
+ screenshot in the design doc.
267
+ - **Citation precision is imperfect.** Of four cited sources,
268
+ typically one or two are directly relevant and the rest are
269
+ topically adjacent.
270
+ - **No per-record checksums.** Torn writes are caught; silent bit
271
+ corruption inside an otherwise-valid record isn't.
272
+
273
+ Full detail and reasoning in [docs/DESIGN.md](docs/DESIGN.md).
274
+
275
+ ## Writing
276
+
277
+ - [Building an HNSW index from scratch](https://amankarki.hashnode.dev/building-an-hnsw-index-from-scratch)
278
+
279
+ ## License
280
+
281
+ MIT — see [LICENSE](LICENSE).