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.
- pylattice_db-0.1.2/.github/workflows/ci.yml +143 -0
- pylattice_db-0.1.2/.gitignore +38 -0
- pylattice_db-0.1.2/CMakeLists.txt +16 -0
- pylattice_db-0.1.2/LICENSE +21 -0
- pylattice_db-0.1.2/PKG-INFO +281 -0
- pylattice_db-0.1.2/README.md +243 -0
- pylattice_db-0.1.2/app/.gitkeep +0 -0
- pylattice_db-0.1.2/app/chunker.py +104 -0
- pylattice_db-0.1.2/app/cli.py +100 -0
- pylattice_db-0.1.2/app/embedder.py +48 -0
- pylattice_db-0.1.2/app/gui.py +217 -0
- pylattice_db-0.1.2/app/requirements.txt +5 -0
- pylattice_db-0.1.2/app/reranker.py +48 -0
- pylattice_db-0.1.2/app/store.py +197 -0
- pylattice_db-0.1.2/app/synthesizer.py +87 -0
- pylattice_db-0.1.2/bench/.gitkeep +0 -0
- pylattice_db-0.1.2/bench/baseline.json +11 -0
- pylattice_db-0.1.2/bench/check_regression.py +82 -0
- pylattice_db-0.1.2/bench/current.json +11 -0
- pylattice_db-0.1.2/bench/fvecs.py +51 -0
- pylattice_db-0.1.2/bench/requirements.txt +3 -0
- pylattice_db-0.1.2/bench/results-ef10.md +18 -0
- pylattice_db-0.1.2/bench/results-ef100.md +18 -0
- pylattice_db-0.1.2/bench/results-sift1m.md +18 -0
- pylattice_db-0.1.2/bench/results.md +16 -0
- pylattice_db-0.1.2/bench/run.py +367 -0
- pylattice_db-0.1.2/bindings/.gitkeep +0 -0
- pylattice_db-0.1.2/bindings/CMakeLists.txt +13 -0
- pylattice_db-0.1.2/bindings/dist/lattice_db-0.1.0.tar.gz +0 -0
- pylattice_db-0.1.2/bindings/lattice_py.cpp +89 -0
- pylattice_db-0.1.2/cli/CMakeLists.txt +2 -0
- pylattice_db-0.1.2/cli/main.cpp +116 -0
- pylattice_db-0.1.2/core/CMakeLists.txt +39 -0
- pylattice_db-0.1.2/core/include/lattice/concurrent_index.hpp +69 -0
- pylattice_db-0.1.2/core/include/lattice/database.hpp +61 -0
- pylattice_db-0.1.2/core/include/lattice/distance.hpp +17 -0
- pylattice_db-0.1.2/core/include/lattice/flat_store.hpp +31 -0
- pylattice_db-0.1.2/core/include/lattice/hnsw.hpp +100 -0
- pylattice_db-0.1.2/core/include/lattice/planner.hpp +42 -0
- pylattice_db-0.1.2/core/include/lattice/quantizer.hpp +56 -0
- pylattice_db-0.1.2/core/include/lattice/search.hpp +29 -0
- pylattice_db-0.1.2/core/include/lattice/segment.hpp +65 -0
- pylattice_db-0.1.2/core/include/lattice/vector.hpp +19 -0
- pylattice_db-0.1.2/core/include/lattice/wal.hpp +41 -0
- pylattice_db-0.1.2/core/src/concurrent_index.cpp +35 -0
- pylattice_db-0.1.2/core/src/database.cpp +124 -0
- pylattice_db-0.1.2/core/src/distance.cpp +19 -0
- pylattice_db-0.1.2/core/src/flat_store.cpp +34 -0
- pylattice_db-0.1.2/core/src/hnsw.cpp +323 -0
- pylattice_db-0.1.2/core/src/main.cpp +278 -0
- pylattice_db-0.1.2/core/src/quantizer.cpp +95 -0
- pylattice_db-0.1.2/core/src/search.cpp +64 -0
- pylattice_db-0.1.2/core/src/segment.cpp +151 -0
- pylattice_db-0.1.2/core/src/wal.cpp +76 -0
- pylattice_db-0.1.2/core/tests/CMakeLists.txt +24 -0
- pylattice_db-0.1.2/core/tests/test_hnsw.cpp +152 -0
- pylattice_db-0.1.2/core/tests/test_quantizer.cpp +114 -0
- pylattice_db-0.1.2/core/tests/test_search.cpp +86 -0
- pylattice_db-0.1.2/core/tests/test_segment.cpp +80 -0
- pylattice_db-0.1.2/core/tests/test_wal.cpp +104 -0
- pylattice_db-0.1.2/docs/.gitkeep +0 -0
- pylattice_db-0.1.2/docs/DESIGN.md +210 -0
- pylattice_db-0.1.2/docs/screenshots/gui-correct-answer.png +0 -0
- pylattice_db-0.1.2/docs/screenshots/gui-failure-example.png +0 -0
- pylattice_db-0.1.2/pyproject.toml +39 -0
- 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
|
+
[](https://github.com/amankarki151/lattice/actions/workflows/ci.yml)
|
|
42
|
+
[](https://pypi.org/project/lattice-db/)
|
|
43
|
+
[](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
|
+

|
|
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).
|