Quick Start¶
Ready to start slinging vectors at lightning speed? Let's get you up and running with Quiver in just a few minutes! ⚡
The 30-Second Version¶
package main
import (
"fmt"
"github.com/TFMV/quiver"
"go.uber.org/zap"
)
func main() {
// Create a logger
logger, _ := zap.NewDevelopment()
// Initialize Quiver
idx, _ := quiver.New(quiver.Config{
Dimension: 128,
StoragePath: "./quiver.db",
}, logger)
defer idx.Close()
// Add a vector
vector := []float32{0.1, 0.2, 0.3, /* ... */}
idx.Add(1, vector, map[string]interface{}{
"category": "example",
"name": "first vector",
})
// Search for similar vectors
results, _ := idx.Search(vector, 10, 1, 10)
fmt.Println("Found:", results[0].ID, results[0].Distance)
}
Step-by-Step Guide¶
1. Initialize Quiver¶
First, you need to create a Quiver index. This is where all your vectors and metadata will be stored.
// Create a logger (Quiver uses zap for logging)
logger, _ := zap.NewDevelopment()
// Configure Quiver
config := quiver.Config{
Dimension: 128, // Dimension of your vectors
StoragePath: "./data/quiver.db", // Where to store the data
Distance: quiver.Cosine, // Distance metric (Cosine or L2)
MaxElements: 1000000, // Maximum number of vectors
HNSWM: 16, // HNSW hyperparameter M
HNSWEfConstruct: 200, // HNSW construction quality
HNSWEfSearch: 100, // HNSW search quality
BatchSize: 1000, // Batch size for insertions
}
// Create the index
idx, err := quiver.New(config, logger)
if err != nil {
panic(err)
}
defer idx.Close() // Don't forget to close when done!
2. Add Vectors¶
Now let's add some vectors to the index. Each vector needs:
- A unique ID
- The vector data (a slice of float32)
- Optional metadata (a map of string to interface{})
// Create a vector (this would typically come from your embedding model)
vector := []float32{0.1, 0.2, 0.3, /* ... and so on for your dimension */}
// Add it to the index with metadata
err = idx.Add(1, vector, map[string]interface{}{
"category": "science",
"name": "black hole",
"tags": []string{"astronomy", "physics"},
})
if err != nil {
panic(err)
}
// Add more vectors
idx.Add(2, []float32{0.2, 0.3, 0.4, /* ... */}, map[string]interface{}{
"category": "science",
"name": "quantum mechanics",
"tags": []string{"physics", "quantum"},
})
3. Search for Similar Vectors¶
The moment you've been waiting for - searching for similar vectors!
// Create a query vector
queryVector := []float32{0.15, 0.25, 0.35, /* ... */}
// Search for the 5 most similar vectors
results, err := idx.Search(queryVector, 5, 1, 10)
if err != nil {
panic(err)
}
// Print the results
for i, result := range results {
fmt.Printf("%d. ID: %d, Distance: %.4f, Name: %s\n",
i+1, result.ID, result.Distance, result.Metadata["name"])
}
4. Hybrid Search (Vector + Metadata)¶
One of Quiver's superpowers is combining vector search with metadata filtering:
// Search for similar vectors that match a metadata filter
results, err := idx.SearchWithFilter(queryVector, 5,
"category = 'science' AND json_array_contains(tags, 'physics')")
if err != nil {
panic(err)
}
5. Search with Negative Examples¶
Want to find vectors similar to A but dissimilar to B? Use negative examples:
// Define what we like and what we don't like
positiveVector := []float32{0.1, 0.2, 0.3, /* ... */}
negativeVector := []float32{0.9, 0.8, 0.7, /* ... */}
// Search with negative examples
results, err := idx.SearchWithNegatives(
positiveVector, // What we're looking for
[][]float32{negativeVector}, // What we want to avoid
5, 1, 10) // k, page, pageSize
What's Next?¶
Now that you've got the basics down, check out:
- Configuration Guide - Fine-tune Quiver for your needs
- Vector Operations - Learn about all the vector operations
- Metadata & Filtering - Master the art of hybrid search
- HTTP API - Use Quiver as a service
Happy vector searching! 🚀