Vector Search
Attach OpenAI embeddings to entries, reuse an internal embedding cache, and rank stored keys by cosine similarity.
Prerequisites
Vector operations require OPENAI_API_KEY. ToriiDB initializes the embedder when store.New succeeds in creating the OpenAI client; otherwise normal storage remains available and vector operations return a configuration error.
| Setting | Value |
|---|---|
| Model | text-embedding-3-small |
| Default dimension | 256 |
| Dimension override | TORIIDB_EMBED_DIM |
| HTTP endpoint | https://api.openai.com/v1/embeddings |
Attach a Vector
Add VECTOR to a top-level SET:
SET article:1 Redis-style embedded storage VECTOR
SET article:2 JSON document database VECTOR
SetVector first performs the normal Set, so the value is available immediately. It then starts a background job that:
- Checks the internal embedding cache.
- Calls OpenAI without holding the database lock on a cache miss.
- Stores the deterministic embedding in the cache.
- Attaches the vector only if the entry still exists and its value still equals the embedded text.
- Updates the entry file and emits an AOF
SETrecord with the encoded vector.
Close waits for these jobs before compacting databases. A plain later SET clears the vector.
Embedding Cache
Cache keys use this reserved form:
__torii:embed:<sha256(model|dimension|text)>
The payload records a base64 little-endian float32 vector, dimension, and model. Cache entries have no TTL because embeddings are treated as deterministic for the same model, dimension, and text.
Scan-style operations hide __torii:* keys. Point lookup remains possible for debugging.
Semantic Search
VSEARCH embedded database
VSEARCH embedded database MATCH article:* LIMIT 5
VSEARCH embedded database LIMIT 5 MATCH article:*
MATCH and LIMIT may appear in either order at the end. When no positive limit is provided, VSearch uses 10.
The query text is embedded synchronously unless its vector is already cached. Search scans the active database under a read lock and skips:
- Reserved internal keys.
- Expired entries.
- Entries without vectors.
- Entries whose vector length differs from the query vector.
- Keys that fail the optional Go
path.Matchpattern. - Zero vectors for which cosine similarity is undefined.
A min-heap keeps the top k candidates, and results are returned in descending similarity order.
Similarity and Vector Retrieval
VSIM article:1 article:2
VGET article:1
VSIM computes cosine similarity between two stored vectors. It returns (nil) when either key or vector is missing, and reports an error when dimensions differ.
VGET returns a JSON float array. The Go API returns a defensive copy, so callers cannot mutate the vector stored in an entry.
Consistency Notes
- Vector attachment is asynchronous; a successful
SET ... VECTORmay not be searchable immediately. - If the value changes before embedding completes, the old result is discarded.
- A failed background embedding does not remove the already stored text.
- Search only compares vectors with exactly matching dimensions.
- A query embedding request is synchronous and may return network or API errors.
Go API Example
ctx := context.Background()
if err := db.SetVector(ctx, "article:1", "embedded JSON database", store.SetDefault, nil); err != nil {
log.Fatal(err)
}
keys, err := db.VSearch(ctx, "local semantic storage", "article:*", 5)
if err != nil {
log.Fatal(err)
}
fmt.Println(keys)