From e6067e271167ea8d202f6ac3aba5b963ce4ff10d Mon Sep 17 00:00:00 2001 From: Alex Garcia Date: Fri, 10 May 2024 20:51:42 -0700 Subject: [PATCH] start simple examples --- .github/workflows/test.yaml | 14 + examples/simple-bun/demo.ts | 49 +++ examples/simple-c/.gitignore | 1 + examples/simple-c/Makefile | 6 + examples/simple-c/demo.c | 81 ++++ examples/simple-deno/demo.ts | 48 +++ examples/simple-go/.gitignore | 1 + examples/simple-go/Makefile | 2 + examples/simple-go/demo.go | 96 +++++ examples/simple-go/go.mod | 10 + examples/simple-go/go.sum | 2 + examples/simple-node/.gitignore | 1 + examples/simple-node/demo.mjs | 48 +++ examples/simple-node/package-lock.json | 505 ++++++++++++++++++++++++ examples/simple-node/package.json | 16 + examples/simple-python/.gitignore | 1 + examples/simple-python/demo.py | 57 +++ examples/simple-python/requirements.txt | 1 + examples/simple-ruby/Gemfile | 6 + examples/simple-ruby/Gemfile.lock | 18 + examples/simple-ruby/demo.rb | 36 ++ examples/simple-rust/.gitignore | 1 + examples/simple-rust/Cargo.lock | 203 ++++++++++ examples/simple-rust/Cargo.toml | 12 + examples/simple-rust/demo.rs | 53 +++ examples/simple-sqlite/demo.sql | 24 ++ examples/simple-wasm/index.html | 52 +++ sqlite-vec.c | 12 +- 28 files changed, 1354 insertions(+), 2 deletions(-) create mode 100644 examples/simple-bun/demo.ts create mode 100644 examples/simple-c/.gitignore create mode 100644 examples/simple-c/Makefile create mode 100644 examples/simple-c/demo.c create mode 100644 examples/simple-deno/demo.ts create mode 100644 examples/simple-go/.gitignore create mode 100644 examples/simple-go/Makefile create mode 100644 examples/simple-go/demo.go create mode 100644 examples/simple-go/go.mod create mode 100644 examples/simple-go/go.sum create mode 100644 examples/simple-node/.gitignore create mode 100644 examples/simple-node/demo.mjs create mode 100644 examples/simple-node/package-lock.json create mode 100644 examples/simple-node/package.json create mode 100644 examples/simple-python/.gitignore create mode 100644 examples/simple-python/demo.py create mode 100644 examples/simple-python/requirements.txt create mode 100644 examples/simple-ruby/Gemfile create mode 100644 examples/simple-ruby/Gemfile.lock create mode 100644 examples/simple-ruby/demo.rb create mode 100644 examples/simple-rust/.gitignore create mode 100644 examples/simple-rust/Cargo.lock create mode 100644 examples/simple-rust/Cargo.toml create mode 100644 examples/simple-rust/demo.rs create mode 100644 examples/simple-sqlite/demo.sql create mode 100644 examples/simple-wasm/index.html diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 68944ee..c1e6682 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -57,3 +57,17 @@ jobs: with: name: sqlite-vec-windows-x86_64-extension path: dist/* + build-wasm32-emscripten: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: mymindstorm/setup-emsdk@v12 + with: + version: "latest" + - run: ./scripts/vendor.sh + - run: make sqlite-vec.h + - run: make wasm + - uses: actions/upload-artifact@v4 + with: + name: sqlite-vec-wasm32-emscripten + path: dist/* diff --git a/examples/simple-bun/demo.ts b/examples/simple-bun/demo.ts new file mode 100644 index 0000000..d33d9db --- /dev/null +++ b/examples/simple-bun/demo.ts @@ -0,0 +1,49 @@ +import { Database } from "bun:sqlite"; + +Database.setCustomSQLite("/usr/local/opt/sqlite3/lib/libsqlite3.dylib"); + +const db = new Database(":memory:"); +//sqliteVec.load(db); +db.loadExtension("../../dist/vec0"); + +const { sqlite_version, vec_version } = db + .prepare( + "select sqlite_version() as sqlite_version, vec_version() as vec_version;" + ) + .get(); + +console.log(`sqlite_version=${sqlite_version}, vec_version=${vec_version}`); + +db.exec("CREATE VIRTUAL TABLE vec_items USING vec0(embedding float[8])"); + +const insertStmt = db.prepare( + "INSERT INTO vec_items(rowid, embedding) VALUES (?, vec_f32(?))" +); + +const insertVectors = db.transaction((items) => { + for (const [id, vector] of items) { + insertStmt.run(BigInt(id), vector); + } +}); + +insertVectors([ + [1, new Float32Array([0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8])], + [2, new Float32Array([0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8])], +]); + +const query = new Float32Array([0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8]); +const rows = db + .prepare( + ` + SELECT + rowid, + distance + FROM vec_items + WHERE embedding MATCH ? + ORDER BY distance + LIMIT 5 +` + ) + .all(query); + +console.log(rows); diff --git a/examples/simple-c/.gitignore b/examples/simple-c/.gitignore new file mode 100644 index 0000000..1549b67 --- /dev/null +++ b/examples/simple-c/.gitignore @@ -0,0 +1 @@ +demo diff --git a/examples/simple-c/Makefile b/examples/simple-c/Makefile new file mode 100644 index 0000000..44cd0eb --- /dev/null +++ b/examples/simple-c/Makefile @@ -0,0 +1,6 @@ +demo: demo.c + gcc \ + -DSQLITE_CORE \ + -I../../ -I../../vendor \ + demo.c ../../sqlite-vec.c ../../vendor/sqlite3.c \ + -o $@ diff --git a/examples/simple-c/demo.c b/examples/simple-c/demo.c new file mode 100644 index 0000000..5d2c9f7 --- /dev/null +++ b/examples/simple-c/demo.c @@ -0,0 +1,81 @@ +#include "sqlite3.h" +#include "sqlite-vec.h" +#include +#include +#include + +int main(int argc, char *argv[]) { + int rc = SQLITE_OK; + sqlite3 *db; + sqlite3_stmt *stmt; + + rc = sqlite3_auto_extension((void (*)())sqlite3_vec_init); + assert(rc == SQLITE_OK); + + rc = sqlite3_open(":memory:", &db); + assert(rc == SQLITE_OK); + + rc = sqlite3_prepare_v2(db, "SELECT sqlite_version(), vec_version()", -1, &stmt, NULL); + assert(rc == SQLITE_OK); + + rc = sqlite3_step(stmt); + printf("sqlite_version=%s, vec_version=%s\n", sqlite3_column_text(stmt, 0), sqlite3_column_text(stmt, 1)); + sqlite3_finalize(stmt); + + rc = sqlite3_prepare_v2(db, "CREATE VIRTUAL TABLE vec_items USING vec0(embedding float[8])", -1, &stmt, NULL); + assert(rc == SQLITE_OK); + rc = sqlite3_step(stmt); + assert(rc == SQLITE_DONE); + sqlite3_finalize(stmt); + + + static const struct { + sqlite3_int64 id; + float vector[8]; + } items[] = { + {1, {0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8}}, + {2, {0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8}}, + }; + + rc = sqlite3_exec(db, "BEGIN", NULL, NULL, NULL); + assert(rc == SQLITE_OK); + rc = sqlite3_prepare_v2(db, "INSERT INTO vec_items(rowid, embedding) VALUES (?, ?)", -1, &stmt, NULL); + assert(rc == SQLITE_OK); + for (unsigned long i = 0; i < sizeof(items) / sizeof(items[0]); i++) { + sqlite3_bind_int64(stmt, 1, items[i].id); + sqlite3_bind_blob(stmt, 2, items[i].vector, sizeof(items[i].vector), SQLITE_STATIC); + rc = sqlite3_step(stmt); + assert(rc == SQLITE_DONE); + sqlite3_reset(stmt); + } + sqlite3_finalize(stmt); + rc = sqlite3_exec(db, "COMMIT", NULL, NULL, NULL); + assert(rc == SQLITE_OK); + + + rc = sqlite3_prepare_v2(db, + "SELECT " + " rowid, " + " distance " + "FROM vec_items " + "WHERE embedding MATCH ?1 " + "ORDER BY distance " + "LIMIT 5 " + , -1, &stmt, NULL); + assert(rc == SQLITE_OK); + + float query[8] = {0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8}; + sqlite3_bind_blob(stmt, 1, query, sizeof(query), SQLITE_STATIC); + + while(1) { + rc = sqlite3_step(stmt); + if(rc == SQLITE_DONE) break; + assert(rc==SQLITE_ROW); + sqlite3_int64 rowid = sqlite3_column_int64(stmt, 0); + double distance = sqlite3_column_double(stmt, 1); + printf("rowid=%lld distance=%f\n", rowid, distance); + } + sqlite3_finalize(stmt); + sqlite3_close(db); + return 0; +} diff --git a/examples/simple-deno/demo.ts b/examples/simple-deno/demo.ts new file mode 100644 index 0000000..18151a3 --- /dev/null +++ b/examples/simple-deno/demo.ts @@ -0,0 +1,48 @@ +import { Database } from "jsr:@db/sqlite@0.11"; +//import { loadablePath } from "npm:sqlite-vec"; + +const db = new Database(":memory:"); +db.enableLoadExtension = true; +db.loadExtension("../../dist/vec0"); +db.enableLoadExtension = false; + +const [sqlite_version, vec_version] = db + .prepare("select sqlite_version(), vec_version()") + .value<[string]>()!; +console.log(`sqlite_version=${sqlite_version}, vec_version=${vec_version}`); + +db.exec("CREATE VIRTUAL TABLE vec_items USING vec0(embedding float[8])"); + +const insertStmt = db.prepare( + "INSERT INTO vec_items(rowid, embedding) VALUES (?1, vec_f32(?2))" +); + +const insertVectors = db.transaction((items) => { + for (const [id, vector] of items) { + insertStmt.run(BigInt(id), new Uint8Array(vector.buffer)); + } +}); + +insertVectors([ + [1, new Float32Array([0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8])], + [2, new Float32Array([0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8])], +]); + +const query = new Float32Array([0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8]); +const rows = db + .prepare( + ` + SELECT + rowid, + distance + FROM vec_items + WHERE embedding MATCH ? + ORDER BY distance + LIMIT 5 +` + ) + .all([new Uint8Array(query.buffer)]); + +console.log(rows); + +db.close(); diff --git a/examples/simple-go/.gitignore b/examples/simple-go/.gitignore new file mode 100644 index 0000000..1549b67 --- /dev/null +++ b/examples/simple-go/.gitignore @@ -0,0 +1 @@ +demo diff --git a/examples/simple-go/Makefile b/examples/simple-go/Makefile new file mode 100644 index 0000000..dbb2cae --- /dev/null +++ b/examples/simple-go/Makefile @@ -0,0 +1,2 @@ +demo: demo.go + go build -o $@ diff --git a/examples/simple-go/demo.go b/examples/simple-go/demo.go new file mode 100644 index 0000000..ad134fd --- /dev/null +++ b/examples/simple-go/demo.go @@ -0,0 +1,96 @@ +package main + +import ( + "bytes" + "database/sql" + "encoding/binary" + "fmt" + "log" + + sqlite_vec "github.com/asg017/sqlite-vec/bindings/go/cgo" + _ "github.com/mattn/go-sqlite3" +) + +// #cgo LDFLAGS: -L../../dist +import "C" + +func serializeFloat32(vector []float32) ([]byte, error) { + buf := new(bytes.Buffer) + err := binary.Write(buf, binary.LittleEndian, vector) + if err != nil { + return nil, err + } + return buf.Bytes(), nil +} +func main() { + sqlite_vec.Auto() + db, err := sql.Open("sqlite3", ":memory:") + if err != nil { + log.Fatal(err) + } + defer db.Close() + + var sqliteVersion string + var vecVersion string + err = db.QueryRow("select sqlite_version(), vec_version()").Scan(&sqliteVersion, &vecVersion) + if err != nil { + log.Fatal(err) + } + fmt.Printf("sqlite_version=%s, vec_version=%s\n", sqliteVersion, vecVersion) + + _, err = db.Exec("CREATE VIRTUAL TABLE vec_items USING vec0(embedding float[8])") + if err != nil { + log.Fatal(err) + } + + items := map[int][]float32{ + 1: {0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8}, + 2: {0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8}, + } + + for id, values := range items { + v, err := serializeFloat32(values) + if err != nil { + log.Fatal(err) + } + _, err = db.Exec("INSERT INTO vec_items(rowid, embedding) VALUES (?, ?)", id, v) + if err != nil { + log.Fatal(err) + } + } + + q := []float32{0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8} + query, err := serializeFloat32(q) + if err != nil { + log.Fatal(err) + } + + rows, err := db.Query(` + SELECT + rowid, + distance + FROM vec_items + WHERE embedding MATCH ? + ORDER BY distance + LIMIT 5 + `, query) + + if err != nil { + log.Fatal(err) + } + + for rows.Next() { + var rowid int64 + var distance float64 + err = rows.Scan(&rowid, &distance) + if err != nil { + log.Fatal(err) + } + fmt.Printf("rowid=%d, distance=%f\n", rowid, distance) + } + err = rows.Err() + if err != nil { + log.Fatal((err)) + } + +} diff --git a/examples/simple-go/go.mod b/examples/simple-go/go.mod new file mode 100644 index 0000000..9c27a07 --- /dev/null +++ b/examples/simple-go/go.mod @@ -0,0 +1,10 @@ +module github.com/asg017/sqlite-vec/examples/go + +go 1.20 + +replace github.com/asg017/sqlite-vec/bindings/go/cgo => ../../bindings/go/cgo + +require ( + github.com/asg017/sqlite-vec/bindings/go/cgo v0.0.0-00010101000000-000000000000 + github.com/mattn/go-sqlite3 v1.14.22 +) diff --git a/examples/simple-go/go.sum b/examples/simple-go/go.sum new file mode 100644 index 0000000..e8d092a --- /dev/null +++ b/examples/simple-go/go.sum @@ -0,0 +1,2 @@ +github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU= +github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= diff --git a/examples/simple-node/.gitignore b/examples/simple-node/.gitignore new file mode 100644 index 0000000..c2658d7 --- /dev/null +++ b/examples/simple-node/.gitignore @@ -0,0 +1 @@ +node_modules/ diff --git a/examples/simple-node/demo.mjs b/examples/simple-node/demo.mjs new file mode 100644 index 0000000..9d276b7 --- /dev/null +++ b/examples/simple-node/demo.mjs @@ -0,0 +1,48 @@ +import * as sqliteVec from "sqlite-vec"; +import Database from "better-sqlite3"; + +const db = new Database(":memory:"); +//sqliteVec.load(db); +db.loadExtension("../../dist/vec0"); + +const { sqlite_version, vec_version } = db + .prepare( + "select sqlite_version() as sqlite_version, vec_version() as vec_version;" + ) + .get(); + +console.log(`sqlite_version=${sqlite_version}, vec_version=${vec_version}`); + +db.exec("CREATE VIRTUAL TABLE vec_items USING vec0(embedding float[8])"); + +const insertStmt = db.prepare( + "INSERT INTO vec_items(rowid, embedding) VALUES (?, vec_f32(?))" +); + +const insertVectors = db.transaction((items) => { + for (const [id, vector] of items) { + insertStmt.run(BigInt(id), vector); + } +}); + +insertVectors([ + [1, new Float32Array([0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8])], + [2, new Float32Array([0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8])], +]); + +const query = new Float32Array([0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8]); +const rows = db + .prepare( + ` + SELECT + rowid, + distance + FROM vec_items + WHERE embedding MATCH ? + ORDER BY distance + LIMIT 5 +` + ) + .all(query); + +console.log(rows); diff --git a/examples/simple-node/package-lock.json b/examples/simple-node/package-lock.json new file mode 100644 index 0000000..4adcba6 --- /dev/null +++ b/examples/simple-node/package-lock.json @@ -0,0 +1,505 @@ +{ + "name": "node", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "node", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "better-sqlite3": "^9.6.0", + "sqlite-vec": "latest" + } + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/better-sqlite3": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-9.6.0.tgz", + "integrity": "sha512-yR5HATnqeYNVnkaUTf4bOP2dJSnyhP4puJN/QPRyx4YkBEEUxib422n2XzPqDEHjQQqazoYoADdAm5vE15+dAQ==", + "hasInstallScript": true, + "dependencies": { + "bindings": "^1.5.0", + "prebuild-install": "^7.1.1" + } + }, + "node_modules/bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/detect-libc": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", + "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==", + "engines": { + "node": ">=8" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "node_modules/github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==" + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + }, + "node_modules/napi-build-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==" + }, + "node_modules/node-abi": { + "version": "3.62.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.62.0.tgz", + "integrity": "sha512-CPMcGa+y33xuL1E0TcNIu4YyaZCxnnvkVaEXrsosR3FxN+fV8xvb7Mzpb7IgKler10qeMkE6+Dp8qJhpzdq35g==", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/prebuild-install": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.2.tgz", + "integrity": "sha512-UnNke3IQb6sgarcZIDU3gbMeTp/9SSU1DAIkil7PrqG1vZlBtY5msYccSKSHDqa3hNg436IXK+SNImReuA1wEQ==", + "dependencies": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^3.3.0", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/sqlite-vec": { + "version": "0.0.1-alpha.3", + "resolved": "https://registry.npmjs.org/sqlite-vec/-/sqlite-vec-0.0.1-alpha.3.tgz", + "integrity": "sha512-CvVTkxW8QJa0xpP6lF/6UprLTS1DDUU1Q4mpju4KvuQ9DSSwvQObRoUa4oyD9rEl4ZOqZsEzbbYKftOlMgp8BA==", + "optionalDependencies": { + "sqlite-vec-darwin-arm64": "0.0.1-alpha.3", + "sqlite-vec-darwin-x64": "0.0.1-alpha.3", + "sqlite-vec-linux-x64": "0.0.1-alpha.3", + "sqlite-vec-windows-x64": "0.0.1-alpha.3" + } + }, + "node_modules/sqlite-vec-darwin-arm64": { + "version": "0.0.1-alpha.3", + "resolved": "https://registry.npmjs.org/sqlite-vec-darwin-arm64/-/sqlite-vec-darwin-arm64-0.0.1-alpha.3.tgz", + "integrity": "sha512-SDHxcCF+fFyHrjFloiAvbCMeVZ6H245JRg2vg2Vu8Ev3FWQfYSD+UsGTk0fl+HOB29yFEYi0w2i5N1m1V9yI+A==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/sqlite-vec-darwin-x64": { + "version": "0.0.1-alpha.3", + "resolved": "https://registry.npmjs.org/sqlite-vec-darwin-x64/-/sqlite-vec-darwin-x64-0.0.1-alpha.3.tgz", + "integrity": "sha512-IVOYcwHzEkKOQPn32zF5gOMyVVLu5vl4i2zTfupPM8MihuxF6+zTrQtxc5Wt0oI1xGtcV+XvIrXJ/HI6qA8vsw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/sqlite-vec-linux-x64": { + "version": "0.0.1-alpha.3", + "resolved": "https://registry.npmjs.org/sqlite-vec-linux-x64/-/sqlite-vec-linux-x64-0.0.1-alpha.3.tgz", + "integrity": "sha512-laTqlOYoYSnhS5jv2nYckTgZE6kHQUdTPI+VpAIRCpKJi8jpB9av6ZQRMA4Uv7dzYEIqS4LBOMUuoAvQP+hDuw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/sqlite-vec-windows-x64": { + "version": "0.0.1-alpha.3", + "resolved": "https://registry.npmjs.org/sqlite-vec-windows-x64/-/sqlite-vec-windows-x64-0.0.1-alpha.3.tgz", + "integrity": "sha512-5663ArvNat1NboOKMDIt6UVJrJuqX44o7eI2LLyYVVY7EBanuN7SohzBCaBcfPGq1sCQGxXBRDRKoFSEQgZnSg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "windows" + ] + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + } +} diff --git a/examples/simple-node/package.json b/examples/simple-node/package.json new file mode 100644 index 0000000..fbb2dde --- /dev/null +++ b/examples/simple-node/package.json @@ -0,0 +1,16 @@ +{ + "name": "node", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "license": "ISC", + "dependencies": { + "better-sqlite3": "^9.6.0", + "sqlite-vec": "latest" + } +} diff --git a/examples/simple-python/.gitignore b/examples/simple-python/.gitignore new file mode 100644 index 0000000..1d17dae --- /dev/null +++ b/examples/simple-python/.gitignore @@ -0,0 +1 @@ +.venv diff --git a/examples/simple-python/demo.py b/examples/simple-python/demo.py new file mode 100644 index 0000000..b7a2501 --- /dev/null +++ b/examples/simple-python/demo.py @@ -0,0 +1,57 @@ +import sqlite3 +import sqlite_vec + +from typing import List +import struct + + +def serialize_f32(vector: List[float]) -> bytes: + """serializes a list of floats into a compact "raw bytes" format""" + return struct.pack("%sf" % len(vector), *vector) + + +def serialize_int8(vector: List[int]) -> bytes: + """serializes a list of int8 into a compact "raw bytes" format""" + return struct.pack("%sb" % len(vector), *vector) + + +db = sqlite3.connect(":memory:") +db.enable_load_extension(True) +sqlite_vec.load(db) +db.enable_load_extension(False) + + +sqlite_version, vec_version = db.execute( + "select sqlite_version(), vec_version()" +).fetchone() +print(f"sqlite_version={sqlite_version}, vec_version={vec_version}") + + +db.execute("CREATE VIRTUAL TABLE vec_items USING vec0(embedding float[8])") + +items = [ + (1, [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8]), + (2, [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8]), +] +with db: + for item in items: + db.execute( + "INSERT INTO vec_items(rowid, embedding) VALUES (?, ?)", + [item[0], serialize_f32(item[1])], + ) + +query = [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8] +rows = db.execute( + """ + SELECT + rowid, + distance + FROM vec_items + WHERE embedding MATCH ? + ORDER BY distance + LIMIT 5 + """, + [serialize_f32(query)], +).fetchall() + +print(rows) diff --git a/examples/simple-python/requirements.txt b/examples/simple-python/requirements.txt new file mode 100644 index 0000000..5b32266 --- /dev/null +++ b/examples/simple-python/requirements.txt @@ -0,0 +1 @@ +sqlite-vec diff --git a/examples/simple-ruby/Gemfile b/examples/simple-ruby/Gemfile new file mode 100644 index 0000000..f123639 --- /dev/null +++ b/examples/simple-ruby/Gemfile @@ -0,0 +1,6 @@ +source 'https://rubygems.org' + +ruby '>= 3.0' + +gem 'sqlite3', '~> 2.0', '>= 2.0.1' +gem 'sqlite-vec' diff --git a/examples/simple-ruby/Gemfile.lock b/examples/simple-ruby/Gemfile.lock new file mode 100644 index 0000000..c2ff025 --- /dev/null +++ b/examples/simple-ruby/Gemfile.lock @@ -0,0 +1,18 @@ +GEM + remote: https://rubygems.org/ + specs: + sqlite-vec (0.0.1.alpha.3-x86_64-darwin) + sqlite3 (2.0.1-x86_64-darwin) + +PLATFORMS + x86_64-darwin-21 + +DEPENDENCIES + sqlite-vec + sqlite3 (~> 2.0, >= 2.0.1) + +RUBY VERSION + ruby 3.2.2p53 + +BUNDLED WITH + 2.4.10 diff --git a/examples/simple-ruby/demo.rb b/examples/simple-ruby/demo.rb new file mode 100644 index 0000000..1b90fde --- /dev/null +++ b/examples/simple-ruby/demo.rb @@ -0,0 +1,36 @@ +require 'sqlite3' +require 'sqlite_vec' + + +db = SQLite3::Database.new(':memory:') +db.enable_load_extension(true) +SqliteVec.load(db) +db.enable_load_extension(false) + +sqlite_version, vec_version = db.execute("select sqlite_version(), vec_version()").first +puts "sqlite_version=#{sqlite_version}, vec_version=#{vec_version}" + +db.execute("CREATE VIRTUAL TABLE vec_items USING vec0(embedding float[8])") + +items = [ + [1, [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8]], + [2, [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8]] +] +db.transaction do + items.each do |item| + db.execute("INSERT INTO vec_items(rowid, embedding) VALUES (?, ?)", [item[0], item[1].pack("f*")]) + end +end + +query = [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8] +rows = db.execute(<<-SQL, [query.pack("f*")]) + SELECT + rowid, + distance + FROM vec_items + WHERE embedding MATCH ? + ORDER BY distance + LIMIT 5 +SQL + +puts rows diff --git a/examples/simple-rust/.gitignore b/examples/simple-rust/.gitignore new file mode 100644 index 0000000..2f7896d --- /dev/null +++ b/examples/simple-rust/.gitignore @@ -0,0 +1 @@ +target/ diff --git a/examples/simple-rust/Cargo.lock b/examples/simple-rust/Cargo.lock new file mode 100644 index 0000000..64e6903 --- /dev/null +++ b/examples/simple-rust/Cargo.lock @@ -0,0 +1,203 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "ahash" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +dependencies = [ + "cfg-if", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "allocator-api2" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" + +[[package]] +name = "bitflags" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "cc" +version = "1.0.96" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "065a29261d53ba54260972629f9ca6bffa69bac13cd1fed61420f7fa68b9f8bd" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "fallible-iterator" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649" + +[[package]] +name = "fallible-streaming-iterator" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +dependencies = [ + "ahash", + "allocator-api2", +] + +[[package]] +name = "hashlink" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "692eaaf7f7607518dd3cef090f1474b61edc5301d8012f09579920df68b725ee" +dependencies = [ + "hashbrown", +] + +[[package]] +name = "libsqlite3-sys" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c10584274047cb335c23d3e61bcef8e323adae7c5c8c760540f73610177fc3f" +dependencies = [ + "cc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "pkg-config" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" + +[[package]] +name = "proc-macro2" +version = "1.0.81" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rusqlite" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b838eba278d213a8beaf485bd313fd580ca4505a00d5871caeb1457c55322cae" +dependencies = [ + "bitflags", + "fallible-iterator", + "fallible-streaming-iterator", + "hashlink", + "libsqlite3-sys", + "smallvec", +] + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[package]] +name = "sqlite-vec" +version = "0.1.0" +dependencies = [ + "cc", +] + +[[package]] +name = "sqlite-vec-demo" +version = "0.0.0" +dependencies = [ + "rusqlite", + "sqlite-vec", + "zerocopy", +] + +[[package]] +name = "syn" +version = "2.0.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "zerocopy" +version = "0.7.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "087eca3c1eaf8c47b94d02790dd086cd594b912d2043d4de4bfdd466b3befb7c" +dependencies = [ + "byteorder", + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f4b6c273f496d8fd4eaf18853e6b448760225dc030ff2c485a786859aea6393" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] diff --git a/examples/simple-rust/Cargo.toml b/examples/simple-rust/Cargo.toml new file mode 100644 index 0000000..8d63548 --- /dev/null +++ b/examples/simple-rust/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "sqlite-vec-demo" +edition = "2021" + +[dependencies] +sqlite-vec={path="../../bindings/rust"} +rusqlite = {version="0.31.0", features=["bundled"]} +zerocopy = "0.7.33" + +[[bin]] +name="demo" +path="demo.rs" diff --git a/examples/simple-rust/demo.rs b/examples/simple-rust/demo.rs new file mode 100644 index 0000000..f90a617 --- /dev/null +++ b/examples/simple-rust/demo.rs @@ -0,0 +1,53 @@ +use rusqlite::{ffi::sqlite3_auto_extension, Connection, Result}; +use sqlite_vec::sqlite3_vec_init; +use zerocopy::AsBytes; + +fn main() -> Result<()> { + unsafe { + sqlite3_auto_extension(Some(std::mem::transmute(sqlite3_vec_init as *const ()))); + } + + let db = Connection::open_in_memory()?; + let v: Vec = vec![0.1, 0.2, 0.3]; + + let (sqlite_version, vec_version, x): (String, String, String) = db.query_row( + "select sqlite_version(), vec_version(), vec_to_json(?)", + &[v.as_bytes()], + |x| Ok((x.get(0)?, x.get(1)?, x.get(2)?)), + )?; + + println!("sqlite_version={sqlite_version}, vec_version={vec_version}"); + + let items: Vec<(usize, Vec)> = vec![ + (1, vec![0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8]), + (2, vec![0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8]), + ]; + println!("{x}"); + + db.execute( + "CREATE VIRTUAL TABLE vec_items USING vec0(embedding float[8])", + [], + )?; + let mut stmt = db.prepare("INSERT INTO vec_items(rowid, embedding) VALUES (?, ?)")?; + for item in items { + stmt.execute(rusqlite::params![item.0, item.1.as_bytes()])?; + } + + let query: Vec = vec![0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8]; + let result: Vec<(i64, f64)> = db + .prepare( + r" + SELECT + rowid, + distance + FROM vec_items + WHERE embedding MATCH ?1 + ORDER BY distance + LIMIT 5 + ", + )? + .query_map([query.as_bytes()], |r| Ok((r.get(0)?, r.get(1)?)))? + .collect::, _>>()?; + println!("{:?}", result); + Ok(()) +} diff --git a/examples/simple-sqlite/demo.sql b/examples/simple-sqlite/demo.sql new file mode 100644 index 0000000..f64976b --- /dev/null +++ b/examples/simple-sqlite/demo.sql @@ -0,0 +1,24 @@ +.load ../../dist/vec0 +.mode box +.header on + +select sqlite_version(), vec_version(); + +CREATE VIRTUAL TABLE vec_items USING vec0(embedding float[8]); + +INSERT INTO vec_items(rowid, embedding) + select + value ->> 0, + value ->> 1 + from json_each('[ + [1, [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8]], + [2, [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8]] + ]'); + +SELECT + rowid, + distance +FROM vec_items +WHERE embedding MATCH '[0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8]' +ORDER BY distance +LIMIT 5; diff --git a/examples/simple-wasm/index.html b/examples/simple-wasm/index.html new file mode 100644 index 0000000..f88c8f5 --- /dev/null +++ b/examples/simple-wasm/index.html @@ -0,0 +1,52 @@ + + +

sqlite-vec demo/simple-wasm

+ +
+ + + +` diff --git a/sqlite-vec.c b/sqlite-vec.c index d5f8007..e7783ae 100644 --- a/sqlite-vec.c +++ b/sqlite-vec.c @@ -1783,7 +1783,10 @@ static sqlite3_module vec_eachModule = { /* xRelease */ 0, /* xRollbackTo */ 0, /* xShadowName */ 0, - /* xIntegrity */ 0}; + #if SQLITE_VERSION_NUMBER >= 3440000 + /* xIntegrity */ 0 + #endif + }; #pragma endregion @@ -2388,7 +2391,10 @@ static sqlite3_module vec_npy_eachModule = { /* xRelease */ 0, /* xRollbackTo */ 0, /* xShadowName */ 0, - /* xIntegrity */ 0}; + #if SQLITE_VERSION_NUMBER >= 3440000 + /* xIntegrity */ 0, + #endif + }; #pragma endregion @@ -4432,7 +4438,9 @@ static sqlite3_module vec0Module = { /* xRelease */ 0, /* xRollbackTo */ 0, /* xShadowName */ vec0ShadowName, + #if SQLITE_VERSION_NUMBER >= 3440000 /* xIntegrity */ 0, // TODO + #endif }; #pragma endregion