Nearest neighbor search for Ruby and Redis
Supports Redis 8 vector sets and RediSearch vector indexes
First, install Redis. With Docker, use:
docker run -p 6379:6379 redis:8
Add this line to your application’s Gemfile:
gem "neighbor-redis"
And set the Redis client:
Neighbor::Redis.client = RedisClient.config.new_pool
Create an index
index = Neighbor::Redis::VectorSet.new("items")
Add vectors
index.add(1, [1, 1, 1])
index.add(2, [2, 2, 2])
index.add(3, [1, 1, 2])
Search for nearest neighbors to a vector
index.search([1, 1, 1], count: 5)
Search for nearest neighbors to a vector in the index
index.search_id(1, count: 5)
IDs are treated as strings by default, but can also be treated as integers
Neighbor::Redis::VectorSet.new("items", id_type: "integer")
Add or update a vector
index.add(id, vector)
Add or update multiple vectors
index.add_all(ids, vectors)
Get a vector
index.find(id)
Remove a vector
index.remove(id)
Remove multiple vectors
index.remove_all(ids)
Count vectors
index.count
Add a vector with metadata
index.add(id, vector, metadata: {category: "A"})
Add multiple vectors with metadata
index.add_all(ids, vectors, metadata: [{category: "A"}, {category: "B"}, ...])
Get metadata for a vector
index.metadata(id)
Get metadata with search results
index.search(vector, with_metadata: true)
Set metadata
index.set_metadata(id, {category: "B"})
Remove metadata
index.remove_metadata(id)
create before searchingCreate a vector set
Neighbor::Redis::VectorSet.new(name)
Specify parameters
Neighbor::Redis::VectorSet.new(name, m: 16, ef_construction: 200, ef_search: 10)
Use quantization (int8 or binary)
Neighbor::Redis::VectorSet.new(name, quantization: "int8")
Use dimensionality reduction
Neighbor::Redis::VectorSet.new(name, reduce: 2)
Perform exact search
index.search(vector, exact: true)
Create a vector index (l2, inner_product, or cosine distance)
index = Neighbor::Redis::HnswIndex.new(name, dimensions: 3, distance: "cosine")
index.create
Store vectors as double precision (instead of single precision)
Neighbor::Redis::HnswIndex.new(name, type: "float64")
Store vectors as JSON (instead of a hash/blob)
Neighbor::Redis::HnswIndex.new(name, redis_type: "json")
HNSW
Neighbor::Redis::HnswIndex.new(name, m: 16, ef_construction: 200, ef_search: 10)
SVS Vamana - Redis 8.2+
Neighbor::Redis::SvsVamanaIndex.new(
name,
compression: nil,
construction_window_size: 200,
graph_max_degree: 32,
search_window_size: 10,
training_threshold: nil,
reduce: nil
)
Flat
Neighbor::Redis::FlatIndex.new(name)
You can use Neighbor Redis for online item-based recommendations with Disco. We’ll use MovieLens data for this example.
Create an index
index = Neighbor::Redis::VectorSet.new("movies")
Fit the recommender
data = Disco.load_movielens
recommender = Disco::Recommender.new(factors: 20)
recommender.fit(data)
Store the item factors
index.add_all(recommender.item_ids, recommender.item_factors)
And get similar movies
index.search_id("Star Wars (1977)").map { |v| v[:id] }
See the complete code for vector sets and vector indexes
Get index info
index.info
Check if an index exists
index.exists?
Drop an index
index.drop
View the changelog
Everyone is encouraged to help improve this project. Here are a few ways you can help:
To get started with development:
git clone https://github.com/ankane/neighbor-redis.git
cd neighbor-redis
bundle install
bundle exec rake test
Ruby
100.0%
Nearest neighbor search for Ruby and Redis
Supports Redis 8 vector sets and RediSearch vector indexes
First, install Redis. With Docker, use:
docker run -p 6379:6379 redis:8
Add this line to your application’s Gemfile:
gem "neighbor-redis"
And set the Redis client:
Neighbor::Redis.client = RedisClient.config.new_pool
Create an index
index = Neighbor::Redis::VectorSet.new("items")
Add vectors
index.add(1, [1, 1, 1])
index.add(2, [2, 2, 2])
index.add(3, [1, 1, 2])
Search for nearest neighbors to a vector
index.search([1, 1, 1], count: 5)
Search for nearest neighbors to a vector in the index
index.search_id(1, count: 5)
IDs are treated as strings by default, but can also be treated as integers
Neighbor::Redis::VectorSet.new("items", id_type: "integer")
Add or update a vector
index.add(id, vector)
Add or update multiple vectors
index.add_all(ids, vectors)
Get a vector
index.find(id)
Remove a vector
index.remove(id)
Remove multiple vectors
index.remove_all(ids)
Count vectors
index.count
Add a vector with metadata
index.add(id, vector, metadata: {category: "A"})
Add multiple vectors with metadata
index.add_all(ids, vectors, metadata: [{category: "A"}, {category: "B"}, ...])
Get metadata for a vector
index.metadata(id)
Get metadata with search results
index.search(vector, with_metadata: true)
Set metadata
index.set_metadata(id, {category: "B"})
Remove metadata
index.remove_metadata(id)
create before searchingCreate a vector set
Neighbor::Redis::VectorSet.new(name)
Specify parameters
Neighbor::Redis::VectorSet.new(name, m: 16, ef_construction: 200, ef_search: 10)
Use quantization (int8 or binary)
Neighbor::Redis::VectorSet.new(name, quantization: "int8")
Use dimensionality reduction
Neighbor::Redis::VectorSet.new(name, reduce: 2)
Perform exact search
index.search(vector, exact: true)
Create a vector index (l2, inner_product, or cosine distance)
index = Neighbor::Redis::HnswIndex.new(name, dimensions: 3, distance: "cosine")
index.create
Store vectors as double precision (instead of single precision)
Neighbor::Redis::HnswIndex.new(name, type: "float64")
Store vectors as JSON (instead of a hash/blob)
Neighbor::Redis::HnswIndex.new(name, redis_type: "json")
HNSW
Neighbor::Redis::HnswIndex.new(name, m: 16, ef_construction: 200, ef_search: 10)
SVS Vamana - Redis 8.2+
Neighbor::Redis::SvsVamanaIndex.new(
name,
compression: nil,
construction_window_size: 200,
graph_max_degree: 32,
search_window_size: 10,
training_threshold: nil,
reduce: nil
)
Flat
Neighbor::Redis::FlatIndex.new(name)
You can use Neighbor Redis for online item-based recommendations with Disco. We’ll use MovieLens data for this example.
Create an index
index = Neighbor::Redis::VectorSet.new("movies")
Fit the recommender
data = Disco.load_movielens
recommender = Disco::Recommender.new(factors: 20)
recommender.fit(data)
Store the item factors
index.add_all(recommender.item_ids, recommender.item_factors)
And get similar movies
index.search_id("Star Wars (1977)").map { |v| v[:id] }
See the complete code for vector sets and vector indexes
Get index info
index.info
Check if an index exists
index.exists?
Drop an index
index.drop
View the changelog
Everyone is encouraged to help improve this project. Here are a few ways you can help:
To get started with development:
git clone https://github.com/ankane/neighbor-redis.git
cd neighbor-redis
bundle install
bundle exec rake test
Ruby
100.0%