The goal of this fork is to create a DevExpress XPO-compatible memory store, and in this case add MySQL support. Let’s see it in action:
Extending Semantic Kernel Memory with XPO
Semantic Kernel supports a variety of databases for memory extension through its connectors. Here is a list of supported databases:
- Connectors.Memory.AzureAISearch
- Connectors.Memory.AzureCosmosDBMongoDB
- Connectors.Memory.AzureCosmosDBNoSQL
- Connectors.Memory.Chroma
- Connectors.Memory.DuckDB
- Connectors.Memory.Kusto
- Connectors.Memory.Milvus
- Connectors.Memory.MongoDB
- Connectors.Memory.Pinecone
- Connectors.Memory.Postgres
- Connectors.Memory.Qdrant
- Connectors.Memory.Redis
- Connectors.Memory.Sqlite
- Connectors.Memory.SqlServer
- Connectors.Memory.Weaviate
Now, with the custom XPO memory provider created by Joche, we can connect to several additional databases:
- Connectors.Memory.Xpo
- Db2
- Db2i
- Firebird
- MySQL
- SapHanna
- Oracle
- Postgres
- SQLite
Battle Testing the XPO Memory Provider
We will begin by making a copy of the TextMemoryPlugin_MultipleMemoryStore.cs
file in the Concept project under Memory and renaming it to TextMemoryPlugin_XpoMemoryStoreMySql.cs
.
Below is the implementation of the RunAsync
method. In this example, we are using MySQL, but feel free to use any other connection string or any of the supported XPO connection strings. For more information, check out this link.
[Fact] public async Task RunAsync() { // Firebird // var cnx = "XpoProvider=Firebird;DataSource=localhost;User=SYSDBA;Password=masterkey;Database=MyDatabase.fdb;ServerType=0;Charset=NONE"; // Xpo Memory Store - using InMemoryDataStore, an in-memory store that is not persisted // var cnx = DevExpress.Xpo.DB.InMemoryDataStore.GetConnectionStringInMemory(true); // Xpo MySQL var cnx = "XpoProvider=MySql;Server=127.0.0.1;User ID=root;Password=1234567890;Database=XpoKernelMemory;Persist Security Info=true;Charset=utf8"; XpoMemoryStore store = await XpoMemoryStore.ConnectAsync(cnx); await RunWithStoreAsync(store); }
Using Embedding Generator and Chat Completion Services
Now let’s integrate the embedding generator and chat completion services with the XpoMemoryStore:
private async Task RunWithStoreAsync(IMemoryStore memoryStore) { var EmbeddingModelId = "text-embedding-3-small"; var ChatModelId = "gpt-4o"; var GetKey = () => Environment.GetEnvironmentVariable("OpenAiTestKey", EnvironmentVariableTarget.Machine); var kernel = Kernel.CreateBuilder() .AddOpenAIChatCompletion(ChatModelId, GetKey.Invoke()) .AddOpenAITextEmbeddingGeneration(EmbeddingModelId, GetKey.Invoke()) .Build(); // Create an embedding generator to use for semantic memory. var embeddingGenerator = new OpenAITextEmbeddingGenerationService(EmbeddingModelId, GetKey.Invoke()); // The combination of the text embedding generator and the memory store makes up the 'SemanticTextMemory' object used to // store and retrieve memories. SemanticTextMemory textMemory = new(memoryStore, embeddingGenerator); }
As you can see, the textMemory
object (SemanticTextMemory) now uses XpoMemoryStore
to save collections in a MySQL database. Changing the database is as easy as modifying the connection string.
Adding NuGet References
Finally, let’s add NuGet references for databases like Firebird and MySQL, which are not natively supported by Semantic Kernel:
<PackageReference Include="FirebirdSql.Data.FirebirdClient" /> <PackageReference Include="MySql.Data" />
You can see the full implementation in this link.
Stay tuned for more implementations of XPO with Semantic Kernel!