Skip to content

pgvector/pgvector-elixir

Repository files navigation

pgvector-elixir

pgvector support for Elixir

Supports Ecto and Postgrex

Build Status

Installation

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:

Ecto

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.PostgrexTypes

Create a migration

mix ecto.gen.migration create_vector_extension

with:

defmoduleMyApp.Repo.Migrations.CreateVectorExtensiondouseEcto.Migrationdefupdoexecute"CREATE EXTENSION IF NOT EXISTS vector"enddefdowndoexecute"DROP EXTENSION vector"endend

Run the migration

mix ecto.migrate

You can now use the vector type in future migrations

createtable(:items)doadd:embedding,:vector,size: 3end

Also supports :halfvec, :bit, and :sparsevec

Update the model

schema"items"dofield:embedding,Pgvector.Ecto.Vectorend

Also 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

Postgrex

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

Reference

Vectors

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()

Half Vectors

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()

Sparse Vectors

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()

Upgrading

0.3.0

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]))

History

View the changelog

Contributing

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/pgvector/pgvector-elixir.git cd pgvector-elixir mix deps.get createdb pgvector_elixir_test mix test

To run an example:

cd examples/loading mix deps.get createdb pgvector_example mix run example.exs

About

pgvector support for Elixir

Resources

License

Security policy

Stars

Watchers

Forks

Packages

No packages published

Languages