sqlite-vec/site/using/go.md
Nuno Cruces 5163f8ea40
Update go docs (#56)
I'm guessing this version (from the CGO example) is more widely applicable (I ship a `database/sql` driver as well).

PS: if you find that all the copies and allocs are a bottleneck, I'm guessing an `buf, err := sqlite_vec .AppendFloat32(buf, values)`, or even an API change (on my side) that allows serializing directly into "native" memory, would help.
2024-08-05 16:00:19 -07:00

3.4 KiB

Using sqlite-vec in Go

There are two ways you can embed sqlite-vec into Go applications: a CGO option for libraries like github.com/mattn/go-sqlite3, or a WASM-based option with github.com/ncruces/go-sqlite3.

Option 1: CGO

Go Reference

If using github.com/mattn/go-sqlite3 or another CGO-based SQLite library, then use the github.com/asg017/sqlite-vec-go-bindings/cgo module to embed sqlite-vec into your Go application.

go get -u github.com/asg017/sqlite-vec-go-bindings/cgo

This will compile and statically link sqlite-vec into your project. The initial build will be slow, but later builds will be cached and much faster.

Use sqlite_vec.Auto() to enable sqlite-vec functions in all future database connections. Also sqlite_vec.Cancel() is available to undo Auto().

package main

import (
	"database/sql"
	"log"

	sqlite_vec "github.com/asg017/sqlite-vec-go-bindings/cgo"
	_ "github.com/mattn/go-sqlite3"
)

func main() {
	sqlite_vec.Auto()
	db, err := sql.Open("sqlite3", ":memory:")
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()

	var vecVersion string
	err = db.QueryRow("select vec_version()").Scan(&vecVersion)
	if err != nil {
		log.Fatal(err)
	}
	log.Printf("vec_version=%s\n",vecVersion)
}

See simple-go-cgo/demo.go for a more complete Go CGO demo.

Option 2: WASM based with ncruces/go-sqlite3

Go Reference

github.com/ncruces/go-sqlite3 is an alternative SQLite Go driver that avoids CGO by using a custom WASM build of SQLite. To use sqlite-vec from this library, use the specicial WASM binary provided in github.com/asg017/sqlite-vec-go-bindings/ncruces.

go get -u github.com/asg017/sqlite-vec-go-bindings/ncruces
package main

import (
	_ "embed"
	"log"

	_ "github.com/asg017/sqlite-vec-go-bindings/ncruces"
	"github.com/ncruces/go-sqlite3"
)

func main() {
	db, err := sqlite3.Open(":memory:")
	if err != nil {
		log.Fatal(err)
	}

	stmt, _, err := db.Prepare(`SELECT vec_version()`)
	if err != nil {
		log.Fatal(err)
	}

	stmt.Step()
	log.Printf("vec_version=%s\n", stmt.ColumnText(0))
	stmt.Close()
}

See simple-go-ncruces/demo.go for a more complete Go ncruces demo.

The github.com/asg017/sqlite-vec-go-bindings/ncruces package embeds a custom WASM build of SQLite, so there's no need to use github.com/ncruces/go-sqlite3/embed.

Working with vectors in Go

If vectors are provided as a list of floats, use SerializeFloat32(list) to serialize them into the compact BLOB format that sqlite-vec expects.

values := []float32{0.1, 0.1, 0.1, 0.1}
v, err := sqlite_vec.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)
}