Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

anet-sqlite-v

Pure-Go vector search — a clean-room, zero-dependency, zero-CGO reimplementation of the ideas in sqlite-vector. No C extension, no Elastic License — MIT, so it drops into open or closed products freely and cross-compiles to arm64 (Rockchip / edge) with GOOS=linux GOARCH=arm64 CGO_ENABLED=0 go build.

Built for the ANetOS smart frame's local memory store (see ANetOS Docs/AS015): one user.db holding prefs + chat + vectors, ≤64 MB with rolling deletion.

What it does

  • Encodings (wire-compatible blobs, little-endian): FLOAT32, FLOAT16 (IEEE-754 half), BFLOAT16, INT8 (per-vector scale), BIT (1 bit/dim). F32/F16/BF16 are byte-identical to sqlite-vector, so embeddings interoperate.
  • Distances: L2, SQUARED_L2, COSINE, DOT, L1, HAMMING (for BIT).
  • Brute-force top-k, no ANN index: Add/Delete take effect on the very next Search (true rolling-delete semantics — the reason sqlite-vector skips ANN too).
  • SQLite persistence (optional subpackage sqlitevec, pure-Go modernc.org/sqlite): vectors in a BLOB column, index rebuilt on open, PruneToBudget holds a byte cap.

Core API (zero deps)

import vec "github.com/ANetResearch/anet-sqlite-v"

ix, _ := vec.NewFromConfig("dimension=768,type=FLOAT16,distance=COSINE")
ix.Add(1, embedding)          // []float32, len 768
ix.Add(2, other)
hits := ix.Search(query, 10)  // []Result{RowID, Distance}, nearest first
ix.Delete(1)                  // reflected on next Search immediately

Single SQLite file (prefs+chat+vectors), 64 MB rolling:

import "github.com/ANetResearch/anet-sqlite-v/sqlitevec"

s, _ := sqlitevec.Open("user.db", "mem", "dimension=768,type=FLOAT16,distance=COSINE")
s.Add("chat", "we went to the beach with grandma", ts, emb)
hits, _ := s.Search(queryEmb, 8)       // []Hit{RowID, Distance, Kind, Text}
s.PruneToBudget(64 << 20)              // delete oldest by ts + reclaim, keep ≤64 MB

Benchmark vs sqlite-vector (same box, 10k × 768, cosine top-10)

impl ms/query stored
sqlite-vector (C + AVX2) 19.3 30.7 MB
anet-sqlite-v FLOAT32 (pure Go, no SIMD) 23.0 30.7 MB
anet-sqlite-v FLOAT16 23.0 15.4 MB
anet-sqlite-v INT8 23.0 7.7 MB
anet-sqlite-v BIT (Hamming) 1.9 1.0 MB

Pure Go is ~1.2× slower than hand-optimized C+AVX2 — while storing F16/BF16 at half the bytes and scanning at F32 speed (decoded cache). For the 64 MB / few-thousand-vector edge case both are sub-5 ms. Run it: go run ./cmd/bench -n 10000.

At 64 MB, FLOAT16 holds ~30k × 768-dim vectors; brute force is plenty fast — no ANN needed.

Notes vs sqlite-vector

  • No CGO / no C extension: usable with pure-Go modernc.org/sqlite (which cannot load C extensions — that's the gap this fills). No -lm link fix, no -mavx2 gotcha, no SIMD-dispatch stub returning scalar; arm64 just works.
  • TurboQuant (2/3/4-bit approximate) is not ported — at this scale exact scan wins and quantized scan needs full rebuild after edits (bad for rolling delete).
  • License: MIT (vs sqlite-vector's Elastic 2.0).

About

Pure-Go zero-CGO vector search — clean-room reimplementation of sqlite-vector ideas (MIT). F16/F32/BF16/INT8/BIT, brute-force top-k, SQLite persistence, ~1.2x of C+AVX2.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages