kernel-memory icon indicating copy to clipboard operation
kernel-memory copied to clipboard

Add support for SQL Server Vector Search

Open marcominerva opened this issue 1 year ago • 5 comments

Motivation and Context (Why the change? What's the scenario?)

Azure SQL Database now provides Vector Support, currently in EAP (https://devblogs.microsoft.com/azure-sql/announcing-eap-native-vector-support-in-azure-sql-database). This PR extends SQL Server Memory DB with a flag that allows to use this new feature.

High level description (Approach, Design)

Just pass true to the new useVectorSearch argument:

builder.Services.AddKernelMemory(options =>
{
    options
      //..
      .WithSqlServerMemoryDb("connecstion_string", useVectorSearch: true)
      //...
      ;
});

With this value, the Memory will use the new Vector Support. In particular, the table KMEmbeddings_index will no longer be necessary, because vectors are now stored in binary format and vector distance can be performed using directly the embedding column in the KMMemories table.

In other words, SqlServerMemory will act differently based on the value of the useVectorSearch flag. I have chosen this approach, rather than creating a brand new MemoryDb implementation, because that are a lot of code in common. Of course, we can decide to split the implementation.

At this moment, vector dimension is limited to 1998, so we can use models like text-embedding-ada-002 or text-embedding-3-small. In case of text-embedding-3-large, we need to specify the value of vector dimension when configuring Kernel Memory.

[!IMPORTANT]
Remember that, at this time, Vector Support is available only on Azure SQL Database. On the other hand, the current SQL Server Memory DB requires a COLUMNSTORE INDEX that, on Azure, is available only on vCore databases and Standard databases in S3 and above pricing tiers (https://azure.microsoft.com/en-us/blog/columnstore-support-in-standard-tier-azure-sql-databases).

marcominerva avatar Jul 30 '24 14:07 marcominerva

I think the amount of SQL strings in the code is getting to a very risky state, hard to review for SQL injections (something we keep getting security warnings about). Would it be hard to refactor out all the SQL manipulation in a dependency, having one class for the old SQL and one for the new SQL with vector support?

dluc avatar Jul 30 '24 18:07 dluc

@dluc I have extracted all the SQL manipulations in external dependencies (see https://github.com/microsoft/kernel-memory/blob/0d81477a626e55c3f8dbc38461cfa884749f6a6e/extensions/SQLServer/SQLServer/QueryProviders/ISqlServerQueryProvider.cs).

Here it is how it is used:

https://github.com/microsoft/kernel-memory/blob/0d81477a626e55c3f8dbc38461cfa884749f6a6e/extensions/SQLServer/SQLServer/SqlServerMemory.cs#L71)

Currently, there are some code duplication in the two implementations, but for the moment I would like to know if it is the correct approach. Then, we could optimize the code.

marcominerva avatar Jul 31 '24 09:07 marcominerva

@dluc I have extracted all the SQL manipulations in external dependencies (see https://github.com/microsoft/kernel-memory/blob/0d81477a626e55c3f8dbc38461cfa884749f6a6e/extensions/SQLServer/SQLServer/QueryProviders/ISqlServerQueryProvider.cs).

Currently, there are some code duplication in the two implementations, but for the moment I would like to know if it is the correct approach. Then, we could optimize the code.

yup, exactly what I was hoping for, thank you. Let me know when the PR is ready

dluc avatar Jul 31 '24 20:07 dluc

I have changed the ISqlServerQueryProvider interface to an abstract base class so that it can contain the common logic. Now the PR is ready for the review ;)

marcominerva avatar Aug 01 '24 08:08 marcominerva

What db do you use? For pgvector https://github.com/pgvector/pgvector-dotnet there is a client.

So it looks like it’s possible to use EntityFrameworkCore

KSemenenko avatar Aug 11 '24 21:08 KSemenenko