pgvector support for Elixir
Add this line to your application’s mix.exs under deps:
{:pgvector,"~> 0.3.0"}And follow the instructions for your database library:
Or check out some examples:
- Embeddings with OpenAI
- Binary embeddings with Cohere
- Sentence embeddings with Bumblebee
- Hybrid search with Bumblebee (Reciprocal Rank Fusion)
- Sparse search with Bumblebee
- Horizontal scaling with Citus
- Bulk loading with
COPY
Create lib/postgrex_types.ex with:
Postgrex.Types.define(MyApp.PostgrexTypes,Pgvector.extensions()++Ecto.Adapters.Postgres.extensions(),[])And add to config/config.exs:
config:my_app,MyApp.Repo,types: MyApp.PostgrexTypesCreate a migration
mix ecto.gen.migration create_vector_extensionwith:
defmoduleMyApp.Repo.Migrations.CreateVectorExtensiondouseEcto.Migrationdefupdoexecute"CREATE EXTENSION IF NOT EXISTS vector"enddefdowndoexecute"DROP EXTENSION vector"endendRun the migration
mix ecto.migrateYou can now use the vector type in future migrations
createtable(:items)doadd:embedding,:vector,size: 3endAlso supports :halfvec, :bit, and :sparsevec
Update the model
schema"items"dofield:embedding,Pgvector.Ecto.VectorendAlso supports Pgvector.Ecto.HalfVector, Pgvector.Ecto.Bit, and Pgvector.Ecto.SparseVector
Insert a vector
aliasMyApp.{Repo,Item}Repo.insert(%Item{embedding: [1,2,3]})Get the nearest neighbors
importEcto.QueryimportPgvector.Ecto.QueryRepo.all(fromiinItem,order_by: l2_distance(i.embedding,^Pgvector.new([1,2,3])),limit: 5)Also supports max_inner_product, cosine_distance, l1_distance, hamming_distance, and jaccard_distance
Convert a vector to a list or Nx tensor
item.embedding|>Pgvector.to_list()item.embedding|>Pgvector.to_tensor()Add an approximate index in a migration
createindex("items",["embedding vector_l2_ops"],using: :hnsw)# orcreateindex("items",["embedding vector_l2_ops"],using: :ivfflat,options: "lists = 100")Use vector_ip_ops for inner product and vector_cosine_ops for cosine distance
Register the extension
Postgrex.Types.define(MyApp.PostgrexTypes,Pgvector.extensions(),[])And pass it to start_link
{:ok,pid}=Postgrex.start_link(types: MyApp.PostgrexTypes)Enable the extension
Postgrex.query!(pid,"CREATE EXTENSION IF NOT EXISTS vector",[])Create a table
Postgrex.query!(pid,"CREATE TABLE items (embedding vector(3))",[])Insert a vector
Postgrex.query!(pid,"INSERT INTO items (embedding) VALUES ($1)",[[1,2,3]])Get the nearest neighbors
Postgrex.query!(pid,"SELECT * FROM items ORDER BY embedding <-> $1 LIMIT 5",[[1,2,3]])Convert a vector to a list or Nx tensor
vector|>Pgvector.to_list()vector|>Pgvector.to_tensor()Add an approximate index
Postgrex.query!(pid,"CREATE INDEX ON items USING hnsw (embedding vector_l2_ops)",[])# orPostgrex.query!(pid,"CREATE INDEX ON items USING ivfflat (embedding vector_l2_ops) WITH (lists = 100)",[])Use vector_ip_ops for inner product and vector_cosine_ops for cosine distance
Create a vector from a list
vec=Pgvector.new([1,2,3])Or an Nx tensor
vec=Nx.tensor([1.0,2.0,3.0])|>Pgvector.new()Get a list
list=vec|>Pgvector.to_list()Get an Nx tensor
tensor=vec|>Pgvector.to_tensor()Create a half vector from a list
vec=Pgvector.HalfVector.new([1,2,3])Or an Nx tensor
vec=Nx.tensor([1.0,2.0,3.0],type: :f16)|>Pgvector.HalfVector.new()Get a list
list=vec|>Pgvector.to_list()Get an Nx tensor
tensor=vec|>Pgvector.to_tensor()Create a sparse vector from a list
vec=Pgvector.SparseVector.new([1,2,3])Or an Nx tensor
vec=Nx.tensor([1.0,2.0,3.0])|>Pgvector.SparseVector.new()Or a map of non-zero elements
elements=%{0=>1.0,2=>2.0,4=>3.0}vec=Pgvector.SparseVector.new(elements,6)Note: Indices start at 0
Get the number of dimensions
dim=vec|>Pgvector.SparseVector.dimensions()Get the indices of non-zero elements
indices=vec|>Pgvector.SparseVector.indices()Get the values of non-zero elements
values=vec|>Pgvector.SparseVector.values()Get a list
list=vec|>Pgvector.to_list()Get an Nx tensor
tensor=vec|>Pgvector.to_tensor()Lists must be converted to Pgvector structs for Ecto distance functions.
# beforel2_distance(i.embedding,[1,2,3])# afterl2_distance(i.embedding,^Pgvector.new([1,2,3]))View the changelog
Everyone is encouraged to help improve this project. Here are a few ways you can help:
- Report bugs
- Fix bugs and submit pull requests
- Write, clarify, or fix documentation
- Suggest or add new features
To get started with development:
git clone https://github.com/pgvector/pgvector-elixir.git cd pgvector-elixir mix deps.get createdb pgvector_elixir_test mix testTo run an example:
cd examples/loading mix deps.get createdb pgvector_example mix run example.exs