From 82d0f14b2af9f3059f34de9fcf406e8b92338fc3 Mon Sep 17 00:00:00 2001 From: Andrew Kane Date: Sun, 3 Dec 2023 00:18:07 -0800 Subject: [PATCH] Added Visual Basic example --- .gitignore | 1 + Pgvector.sln | 7 ++ README.md | 80 ++++++++++++++++++- .../Pgvector.VisualBasic.Tests/NpgsqlTests.vb | 67 ++++++++++++++++ .../Pgvector.VisualBasic.Tests.vbproj | 22 +++++ 5 files changed, 174 insertions(+), 3 deletions(-) create mode 100644 tests/Pgvector.VisualBasic.Tests/NpgsqlTests.vb create mode 100644 tests/Pgvector.VisualBasic.Tests/Pgvector.VisualBasic.Tests.vbproj diff --git a/.gitignore b/.gitignore index cd42ee3..62d1e79 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ bin/ obj/ +TestResults/ diff --git a/Pgvector.sln b/Pgvector.sln index 0ad9ae4..b3bead3 100644 --- a/Pgvector.sln +++ b/Pgvector.sln @@ -17,6 +17,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Pgvector.EntityFrameworkCor EndProject Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "Pgvector.FSharp.Tests", "tests\Pgvector.FSharp.Tests\Pgvector.FSharp.Tests.fsproj", "{2D51D6AE-2355-4BAE-8FDC-7001EBAE78BD}" EndProject +Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "Pgvector.VisualBasic.Tests", "tests\Pgvector.VisualBasic.Tests\Pgvector.VisualBasic.Tests.vbproj", "{1C52EAE5-7888-48E9-86E2-FADA289CE658}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -46,6 +48,10 @@ Global {2D51D6AE-2355-4BAE-8FDC-7001EBAE78BD}.Debug|Any CPU.Build.0 = Debug|Any CPU {2D51D6AE-2355-4BAE-8FDC-7001EBAE78BD}.Release|Any CPU.ActiveCfg = Release|Any CPU {2D51D6AE-2355-4BAE-8FDC-7001EBAE78BD}.Release|Any CPU.Build.0 = Release|Any CPU + {1C52EAE5-7888-48E9-86E2-FADA289CE658}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1C52EAE5-7888-48E9-86E2-FADA289CE658}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1C52EAE5-7888-48E9-86E2-FADA289CE658}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1C52EAE5-7888-48E9-86E2-FADA289CE658}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(NestedProjects) = preSolution {3C580CE2-B935-4656-BCC9-4FB4035089E4} = {B76AB67C-094F-433B-AF25-807B50D2888E} @@ -53,5 +59,6 @@ Global {FF6D3EDD-C96A-4AD5-A298-0A7E53BB3A07} = {B76AB67C-094F-433B-AF25-807B50D2888E} {4493B7D8-112B-4867-9373-C08B6F996875} = {B76AB67C-094F-433B-AF25-807B50D2888E} {2D51D6AE-2355-4BAE-8FDC-7001EBAE78BD} = {4C5546A5-6119-4D42-A65B-2327280E1881} + {1C52EAE5-7888-48E9-86E2-FADA289CE658} = {4C5546A5-6119-4D42-A65B-2327280E1881} EndGlobalSection EndGlobal diff --git a/README.md b/README.md index 7448fbb..d70d7be 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # pgvector-dotnet -[pgvector](https://github.com/pgvector/pgvector) support for .NET (C# and F#) +[pgvector](https://github.com/pgvector/pgvector) support for .NET (C#, F#, and Visual Basic) Supports [Npgsql](https://github.com/npgsql/npgsql), [Dapper](https://github.com/DapperLib/Dapper), [Entity Framework Core](https://github.com/dotnet/efcore), and [Npgsql.FSharp](https://github.com/Zaid-Ajaj/Npgsql.FSharp) @@ -10,14 +10,15 @@ Supports [Npgsql](https://github.com/npgsql/npgsql), [Dapper](https://github.com Follow the instructions for your database library: -- C# - [Npgsql](#npgsql), [Dapper](#dapper), [Entity Framework Core](#entity-framework-core) +- C# - [Npgsql](#npgsql-c), [Dapper](#dapper), [Entity Framework Core](#entity-framework-core) - F# - [Npgsql.FSharp](#npgsqlfsharp) +- Visual Basic - [Npgsql](#npgsql-visual-basic) Or check out an example: - [Embeddings](tests/Pgvector.Tests/OpenAITests.cs) with OpenAI -## Npgsql +## Npgsql (C#) Run @@ -375,6 +376,79 @@ Use `vector_ip_ops` for inner product and `vector_cosine_ops` for cosine distanc See a [full example](https://github.com/pgvector/pgvector-dotnet/blob/master/tests/Pgvector.FSharp.Tests/NpgsqlFSharpTests.fs) +## Npgsql (Visual Basic) + +Run + +```sh +dotnet add package Pgvector +``` + +Create a connection + +```vb +Dim dataSourceBuilder As New NpgsqlDataSourceBuilder(connString) +dataSourceBuilder.UseVector() +Dim dataSource = dataSourceBuilder.Build() + +Dim conn = dataSource.OpenConnection() +``` + +Enable the extension + +```vb +Using cmd As New NpgsqlCommand("CREATE EXTENSION IF NOT EXISTS vector", conn) + cmd.ExecuteNonQuery() +End Using + +conn.ReloadTypes() +``` + +Create a table + +```vb +Using cmd As New NpgsqlCommand("CREATE TABLE items (id serial PRIMARY KEY, embedding vector(3))", conn) + cmd.ExecuteNonQuery() +End Using +``` + +Insert a vector + +```vb +Using cmd As New NpgsqlCommand("INSERT INTO items (embedding) VALUES ($1)", conn) + Dim embedding As New Vector(New Single() {1, 1, 1}) + cmd.Parameters.AddWithValue(embedding) + cmd.ExecuteNonQuery() +End Using +``` + +Get the nearest neighbors + +```vb +Using cmd As New NpgsqlCommand("SELECT * FROM items ORDER BY embedding <-> $1 LIMIT 5", conn) + Dim embedding As New Vector(New Single() {1, 1, 1}) + cmd.Parameters.AddWithValue(embedding) + + Using reader As NpgsqlDataReader = cmd.ExecuteReader() + While reader.Read() + Console.WriteLine(reader.GetValue(0)) + End While + End Using +End Using +``` + +Add an approximate index + +```vb +Using cmd As New NpgsqlCommand("CREATE INDEX ON items USING hnsw (embedding vector_l2_ops)", conn) + cmd.ExecuteNonQuery() +End Using +``` + +Use `vector_ip_ops` for inner product and `vector_cosine_ops` for cosine distance + +See a [full example](https://github.com/pgvector/pgvector-dotnet/blob/master/tests/Pgvector.VisualBasic.Tests/NpgsqlTests.vs) + ## History - [Pgvector](https://github.com/pgvector/pgvector-dotnet/blob/master/src/Pgvector/CHANGELOG.md) diff --git a/tests/Pgvector.VisualBasic.Tests/NpgsqlTests.vb b/tests/Pgvector.VisualBasic.Tests/NpgsqlTests.vb new file mode 100644 index 0000000..791249f --- /dev/null +++ b/tests/Pgvector.VisualBasic.Tests/NpgsqlTests.vb @@ -0,0 +1,67 @@ +Imports Microsoft.VisualStudio.TestTools.UnitTesting +Imports Microsoft.VisualStudio.TestTools.UnitTesting.CollectionAssert +Imports Npgsql + +Namespace Pgvector.VisualBasic.Tests + + Public Class NpgsqlTests + + Sub TestSub() + Dim connString = "Host=localhost;Database=pgvector_dotnet_test" + + Dim dataSourceBuilder As New NpgsqlDataSourceBuilder(connString) + dataSourceBuilder.UseVector() + Dim dataSource = dataSourceBuilder.Build() + + Dim conn = dataSource.OpenConnection() + + Using cmd As New NpgsqlCommand("CREATE EXTENSION IF NOT EXISTS vector", conn) + cmd.ExecuteNonQuery() + End Using + + conn.ReloadTypes() + + Using cmd As New NpgsqlCommand("DROP TABLE IF EXISTS vb_items", conn) + cmd.ExecuteNonQuery() + End Using + + Using cmd As New NpgsqlCommand("CREATE TABLE vb_items (id serial PRIMARY KEY, embedding vector(3))", conn) + cmd.ExecuteNonQuery() + End Using + + Using cmd As New NpgsqlCommand("INSERT INTO vb_items (embedding) VALUES ($1), ($2), ($3)", conn) + Dim embedding1 As New Vector(New Single() {1, 1, 1}) + Dim embedding2 As New Vector(New Single() {2, 2, 2}) + Dim embedding3 As New Vector(New Single() {1, 1, 2}) + cmd.Parameters.AddWithValue(embedding1) + cmd.Parameters.AddWithValue(embedding2) + cmd.Parameters.AddWithValue(embedding3) + cmd.ExecuteNonQuery() + End Using + + Using cmd As New NpgsqlCommand("SELECT * FROM vb_items ORDER BY embedding <-> $1 LIMIT 5", conn) + Dim embedding As New Vector(New Single() {1, 1, 1}) + cmd.Parameters.AddWithValue(embedding) + + Using reader As NpgsqlDataReader = cmd.ExecuteReader() + Dim ids As New List(Of Integer) + Dim embeddings As New List(Of Vector) + + While reader.Read() + ids.Add(reader.GetValue(0)) + embeddings.Add(reader.GetValue(1)) + End While + + CollectionAssert.AreEqual(new Integer() {1, 3, 2}, ids.ToArray()) + CollectionAssert.AreEqual(new Single() {1, 1, 1}, embeddings(0).ToArray()) + CollectionAssert.AreEqual(new Single() {1, 1, 2}, embeddings(1).ToArray()) + CollectionAssert.AreEqual(new Single() {2, 2, 2}, embeddings(2).ToArray()) + End Using + End Using + + Using cmd As New NpgsqlCommand("CREATE INDEX ON vb_items USING hnsw (embedding vector_l2_ops)", conn) + cmd.ExecuteNonQuery() + End Using + End Sub + End Class +End Namespace diff --git a/tests/Pgvector.VisualBasic.Tests/Pgvector.VisualBasic.Tests.vbproj b/tests/Pgvector.VisualBasic.Tests/Pgvector.VisualBasic.Tests.vbproj new file mode 100644 index 0000000..a053472 --- /dev/null +++ b/tests/Pgvector.VisualBasic.Tests/Pgvector.VisualBasic.Tests.vbproj @@ -0,0 +1,22 @@ + + + + Pgvector.VisualBasic.Tests + net8.0 + + false + true + + + + + + + + + + + + + +