Skip to content

pgvector support for .NET (C#, F#, and Visual Basic)

License

Notifications You must be signed in to change notification settings

pgvector/pgvector-dotnet

Repository files navigation

pgvector-dotnet

pgvector support for .NET (C#, F#, and Visual Basic)

Supports Npgsql, Dapper, Entity Framework Core, and Npgsql.FSharp

Build Status

Getting Started

Follow the instructions for your database library:

Or check out some examples:

Npgsql (C#)

Run

dotnet add package Pgvector

Create a connection

vardataSourceBuilder=newNpgsqlDataSourceBuilder(connString);dataSourceBuilder.UseVector();awaitusingvardataSource=dataSourceBuilder.Build();varconn=dataSource.OpenConnection();

Enable the extension

awaitusing(varcmd=newNpgsqlCommand("CREATE EXTENSION IF NOT EXISTS vector",conn)){awaitcmd.ExecuteNonQueryAsync();}conn.ReloadTypes();

Create a table

awaitusing(varcmd=newNpgsqlCommand("CREATE TABLE items (id serial PRIMARY KEY, embedding vector(3))",conn)){awaitcmd.ExecuteNonQueryAsync();}

Insert a vector

awaitusing(varcmd=newNpgsqlCommand("INSERT INTO items (embedding) VALUES ($1)",conn)){varembedding=newVector(newfloat[]{1,1,1});cmd.Parameters.AddWithValue(embedding);awaitcmd.ExecuteNonQueryAsync();}

Get the nearest neighbors

awaitusing(varcmd=newNpgsqlCommand("SELECT * FROM items ORDER BY embedding <-> $1 LIMIT 5",conn)){varembedding=newVector(newfloat[]{1,1,1});cmd.Parameters.AddWithValue(embedding);awaitusing(varreader=awaitcmd.ExecuteReaderAsync()){while(awaitreader.ReadAsync()){Console.WriteLine(reader.GetValue(0));}}}

Add an approximate index

awaitusing(varcmd=newNpgsqlCommand("CREATE INDEX ON items USING hnsw (embedding vector_l2_ops)",conn)){awaitcmd.ExecuteNonQueryAsync();}

Use vector_ip_ops for inner product and vector_cosine_ops for cosine distance

See a full example

Dapper

Run

dotnet add package Pgvector.Dapper

Import the library

usingPgvector.Dapper;

Create a connection

SqlMapper.AddTypeHandler(newVectorTypeHandler());vardataSourceBuilder=newNpgsqlDataSourceBuilder(connString);dataSourceBuilder.UseVector();awaitusingvardataSource=dataSourceBuilder.Build();varconn=dataSource.OpenConnection();

Enable the extension

conn.Execute("CREATE EXTENSION IF NOT EXISTS vector");conn.ReloadTypes();

Define a class

publicclassItem{publicintId{get;set;}publicVector?Embedding{get;set;}}

Also supports HalfVector and SparseVector

Create a table

conn.Execute("CREATE TABLE items (id serial PRIMARY KEY, embedding vector(3))");

Insert a vector

varembedding=newVector(newfloat[]{1,1,1});conn.Execute(@"INSERT INTO items (embedding) VALUES (@embedding)",new{embedding});

Get the nearest neighbors

varembedding=newVector(newfloat[]{1,1,1});varitems=conn.Query<Item>("SELECT * FROM items ORDER BY embedding <-> @embedding LIMIT 5",new{embedding});foreach(Itemiteminitems){Console.WriteLine(item.Embedding);}

Add an approximate index

conn.Execute("CREATE INDEX ON items USING hnsw (embedding vector_l2_ops)");// orconn.Execute("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

See a full example

Entity Framework Core

Run

dotnet add package Pgvector.EntityFrameworkCore

The latest version works with Entity Framework Core 9 and 10. For Entity Framework Core 8, use version 0.2.2 and this readme.

Import the library

usingPgvector.EntityFrameworkCore;

Enable the extension

protectedoverridevoidOnModelCreating(ModelBuildermodelBuilder){modelBuilder.HasPostgresExtension("vector");}

Configure the connection

protectedoverridevoidOnConfiguring(DbContextOptionsBuilderoptionsBuilder){optionsBuilder.UseNpgsql("connString", o =>o.UseVector());}

Define a model

publicclassItem{publicintId{get;set;}[Column(TypeName="vector(3)")]publicVector?Embedding{get;set;}}

Also supports HalfVector and SparseVector

Insert a vector

ctx.Items.Add(newItem{Embedding=newVector(newfloat[]{1,1,1})});ctx.SaveChanges();

Get the nearest neighbors

varembedding=newVector(newfloat[]{1,1,1});varitems=awaitctx.Items.OrderBy(x =>x.Embedding!.L2Distance(embedding)).Take(5).ToListAsync();foreach(Itemiteminitems){if(item.Embedding!=null){Console.WriteLine(item.Embedding);}}

Also supports MaxInnerProduct, CosineDistance, L1Distance, HammingDistance, and JaccardDistance

Get the distance

varitems=awaitctx.Items.Select(x =>new{Entity=x,Distance=x.Embedding!.L2Distance(embedding)}).ToListAsync();

Get items within a certain distance

varitems=awaitctx.Items.Where(x =>x.Embedding!.L2Distance(embedding)<5).ToListAsync();

Add an approximate index

protectedoverridevoidOnModelCreating(ModelBuildermodelBuilder){modelBuilder.Entity<Item>().HasIndex(i =>i.Embedding).HasMethod("hnsw").HasOperators("vector_l2_ops").HasStorageParameter("m",16).HasStorageParameter("ef_construction",64);// ormodelBuilder.Entity<Item>().HasIndex(i =>i.Embedding).HasMethod("ivfflat").HasOperators("vector_l2_ops").HasStorageParameter("lists",100);}

Use vector_ip_ops for inner product and vector_cosine_ops for cosine distance

See a full example

Npgsql.FSharp

Run

dotnet add package Pgvector

Import the library

openPgvector

Create a connection

letdataSourceBuilder=new NpgsqlDataSourceBuilder(connString) dataSourceBuilder.UseVector()use dataSource = dataSourceBuilder.Build()

Enable the extension

dataSource |> Sql.fromDataSource |> Sql.query "CREATE EXTENSION IF NOT EXISTS vector"|> Sql.executeNonQuery

Create a table

dataSource |> Sql.fromDataSource |> Sql.query "CREATE TABLE items (id serial PRIMARY KEY, embedding vector(3))"|> Sql.executeNonQuery

Insert a vector

letembedding=new Vector([|1f;1f;1f |])letparameter=new NpgsqlParameter("", embedding) dataSource |> Sql.fromDataSource |> Sql.query "INSERT INTO items (embedding) VALUES (@embedding)"|> Sql.parameters ["embedding", Sql.parameter parameter ]|> Sql.executeNonQuery

Get the nearest neighbors

typeItem={ Id:int Embedding:Vector} dataSource |> Sql.fromDataSource |> Sql.query "SELECT * FROM items ORDER BY embedding <-> @embedding LIMIT 5"|> Sql.parameters ["embedding", Sql.parameter parameter ]|> Sql.execute (fun read ->{ Id = read.int "id" Embedding = read.fieldValue<Vector>"embedding"})|> printfn "%A"

Add an approximate index

dataSource |> Sql.fromDataSource |> Sql.query "CREATE INDEX ON items USING hnsw (embedding vector_l2_ops)"|> Sql.executeNonQuery

Use vector_ip_ops for inner product and vector_cosine_ops for cosine distance

See a full example

Npgsql (Visual Basic)

Run

dotnet add package Pgvector

Create a connection

DimdataSourceBuilderAsNewNpgsqlDataSourceBuilder(connString)dataSourceBuilder.UseVector()DimdataSource=dataSourceBuilder.Build()Dimconn=dataSource.OpenConnection()

Enable the extension

UsingcmdAsNewNpgsqlCommand("CREATE EXTENSION IF NOT EXISTS vector",conn)cmd.ExecuteNonQuery()EndUsingconn.ReloadTypes()

Create a table

UsingcmdAsNewNpgsqlCommand("CREATE TABLE items (id serial PRIMARY KEY, embedding vector(3))",conn)cmd.ExecuteNonQuery()EndUsing

Insert a vector

UsingcmdAsNewNpgsqlCommand("INSERT INTO items (embedding) VALUES ($1)",conn)DimembeddingAsNewVector(NewSingle(){1,1,1})cmd.Parameters.AddWithValue(embedding)cmd.ExecuteNonQuery()EndUsing

Get the nearest neighbors

UsingcmdAsNewNpgsqlCommand("SELECT * FROM items ORDER BY embedding <-> $1 LIMIT 5",conn)DimembeddingAsNewVector(NewSingle(){1,1,1})cmd.Parameters.AddWithValue(embedding)UsingreaderAsNpgsqlDataReader=cmd.ExecuteReader()Whilereader.Read()Console.WriteLine(reader.GetValue(0))EndWhileEndUsingEndUsing

Add an approximate index

UsingcmdAsNewNpgsqlCommand("CREATE INDEX ON items USING hnsw (embedding vector_l2_ops)",conn)cmd.ExecuteNonQuery()EndUsing

Use vector_ip_ops for inner product and vector_cosine_ops for cosine distance

See a full example

Reference

Vectors

Create a vector from an array

varvec=newVector(newfloat[]{1,2,3});

Get an array

vararr=vec.ToArray();

Half Vectors

Create a half vector from an array

varvec=newHalfVector(newHalf[]{(Half)1,(Half)2,(Half)3});

Get an array

vararr=vec.ToArray();

Sparse Vectors

Create a sparse vector from an array

varvec=newSparseVector(newfloat[]{1,0,2,0,3,0});

Or a dictionary of non-zero elements

vardictionary=newDictionary<int,float>();dictionary.Add(0,1);dictionary.Add(2,2);dictionary.Add(4,3);varvec=newSparseVector(dictionary,6);

Note: Indices start at 0

Get the number of dimensions

vardim=vec.Dimensions;

Get the indices of non-zero elements

varindices=vec.Indices;

Get the values of non-zero elements

varvalues=vec.Values;

Get an array

vararr=vec.ToArray();

History

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-dotnet.git cd pgvector-dotnet createdb pgvector_dotnet_test dotnet test

To run an example:

cd examples/Loading createdb pgvector_example dotnet run

About

pgvector support for .NET (C#, F#, and Visual Basic)

Resources

License

Security policy

Stars

Watchers

Forks

Packages

No packages published

Contributors 6