Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RedisMemory #208

Merged
merged 2 commits into from
Jan 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
<PackageVersion Include="Pgvector" Version="0.2.0"/>
<PackageVersion Include="Polly.Core" Version="8.2.0"/>
<PackageVersion Include="RabbitMQ.Client" Version="6.8.1"/>
<PackageVersion Include="NRedisStack" Version="0.10.1"/>
<PackageVersion Include="Swashbuckle.AspNetCore" Version="6.5.0"/>
<PackageVersion Include="System.Linq.Async" Version="6.0.1"/>
<PackageVersion Include="System.Memory.Data" Version="8.0.0"/>
Expand Down
7 changes: 7 additions & 0 deletions KernelMemory.sln
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tools", "tools", "{CA49F1A1
tools\search.sh = tools\search.sh
tools\run-qdrant.sh = tools\run-qdrant.sh
tools\create-azure-webapp-publish-artifacts.sh = tools\create-azure-webapp-publish-artifacts.sh
tools\run-redis.sh = tools\run-redis.sh
EndProjectSection
EndProject

Expand Down Expand Up @@ -240,6 +241,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "packages", "packages", "{16
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Redis", "extensions\Redis\Redis.csproj", "{EC434C8D-4811-4B16-8F04-5E8FAD5BE233}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "redis-tests", "service\tests\redis-tests\redis-tests.csproj", "{A8EB745F-5767-42CC-9E3A-692060720F35}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -299,6 +302,7 @@ Global
{DD7ED79F-95D3-48AE-85AB-D7119F8530C2} = {5E7DD43D-B5E7-4827-B57D-447E5B428589}
{0675D9B5-B3BB-4C9A-A1A5-11540E2ED715} = {5E7DD43D-B5E7-4827-B57D-447E5B428589}
{EC434C8D-4811-4B16-8F04-5E8FAD5BE233} = {155DA079-E267-49AF-973A-D1D44681970F}
{A8EB745F-5767-42CC-9E3A-692060720F35} = {5E7DD43D-B5E7-4827-B57D-447E5B428589}
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{8A9FA587-7EBA-4D43-BE47-38D798B1C74C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
Expand Down Expand Up @@ -445,5 +449,8 @@ Global
{EC434C8D-4811-4B16-8F04-5E8FAD5BE233}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EC434C8D-4811-4B16-8F04-5E8FAD5BE233}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EC434C8D-4811-4B16-8F04-5E8FAD5BE233}.Release|Any CPU.Build.0 = Release|Any CPU
{A8EB745F-5767-42CC-9E3A-692060720F35}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A8EB745F-5767-42CC-9E3A-692060720F35}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A8EB745F-5767-42CC-9E3A-692060720F35}.Release|Any CPU.ActiveCfg = Release|Any CPU
EndGlobalSection
EndGlobal
63 changes: 63 additions & 0 deletions extensions/Redis/DependencyInjection.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// Copyright (c) Microsoft. All rights reserved.

using Microsoft.Extensions.DependencyInjection;
using Microsoft.KernelMemory.MemoryStorage;
using Microsoft.KernelMemory.MemoryDb.Redis;
using StackExchange.Redis;

#pragma warning disable IDE0130 // reduce number of "using" statements
// ReSharper disable once CheckNamespace - reduce number of "using" statements
namespace Microsoft.KernelMemory;

/// <summary>
/// DI pipelines for Redis Memory.
/// </summary>
public static partial class KernelMemoryBuilderExtensions
{
/// <summary>
/// Adds RedisMemory as a service.
/// </summary>
/// <param name="builder">The kernel builder</param>
/// <param name="connString">The Redis connection string based on <see href="https://stackexchange.github.io/StackExchange.Redis/Configuration">StackExchange.Redis' connection string</see></param>
public static IKernelMemoryBuilder WithRedisMemoryDb(
this IKernelMemoryBuilder builder,
string connString)
{
builder.Services.AddRedisAsMemoryDb(new RedisConfig { ConnectionString = connString });
return builder;
}

/// <summary>
/// Adds RedisMemory as a service.
/// </summary>
/// <param name="builder">The kernel builder</param>
/// <param name="redisConfig">Redis configuration.</param>
public static IKernelMemoryBuilder WithRedisMemoryDb(
this IKernelMemoryBuilder builder,
RedisConfig redisConfig)
{
builder.Services.AddRedisAsMemoryDb(redisConfig);
return builder;
}
}

/// <summary>
/// setup Redis memory within the semantic kernel
/// </summary>
public static partial class DependencyInjection
{
/// <summary>
/// Adds RedisMemory as a service.
/// </summary>
/// <param name="services">The services collection</param>
/// <param name="redisConfig">Redis configuration.</param>
public static IServiceCollection AddRedisAsMemoryDb(
this IServiceCollection services,
RedisConfig redisConfig)
{
return services
.AddSingleton(redisConfig)
.AddSingleton<IConnectionMultiplexer>(_ => ConnectionMultiplexer.Connect(redisConfig.ConnectionString))
.AddSingleton<IMemoryDb, RedisMemory>();
}
}
26 changes: 25 additions & 1 deletion extensions/Redis/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,28 @@

[![Discord](https://img.shields.io/discord/1063152441819942922?label=Discord&logo=discord&logoColor=white&color=d82679)](https://aka.ms/KMdiscord)

This project will contain the [Redis](https://redis.io) adapter allowing to use Kernel Memory with Redis.
## Notes about Redis Vector Search:

Redis Vector search requires the use of
Redis' [Search and Query capabilities](https://redis.io/docs/interact/search-and-query/).

This is available in:

* [Redis Stack](https://redis.io/docs/about/about-stack/)
* [Azure Cache for Redis](https://azure.microsoft.com/en-us/products/cache) - Enterprise Tier only
* [Redis Cloud](https://app.redislabs.com/)
* [Redis Enterprise](https://redis.io/docs/about/redis-enterprise/)

You can run Redis Stack locally in docker with the following command:

```sh
docker run -p 8001:8001 -p 6379:6379 redis/redis-stack
```

## Configuring Tag Filters

Using tag filters with Redis requires you to to pre-define which tag fields you want. You can
do so using the `RedisMemoryConfiguration.Tags` property (with the characters being the tag separators)
while creating the dependency-injection pipeline. It's important that you pick a separator that will
not appear in your data (otherwise your tags might over-match)

13 changes: 6 additions & 7 deletions extensions/Redis/Redis.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
<RollForward>LatestMajor</RollForward>
<AssemblyName>Microsoft.KernelMemory.MemoryDb.Redis</AssemblyName>
<RootNamespace>Microsoft.KernelMemory.MemoryDb.Redis</RootNamespace>
<NoWarn>$(NoWarn);CA1724;CS1591;</NoWarn>
<NoWarn>$(NoWarn);CA1724;CS1591;CA1308;CA1859;</NoWarn>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
Expand All @@ -14,10 +16,7 @@

<ItemGroup>
<PackageReference Include="System.Linq.Async"/>
</ItemGroup>

<ItemGroup>
<InternalsVisibleTo Include="Microsoft.UnitTests"/>
<PackageReference Include="NRedisStack"/>
</ItemGroup>

<Import Project="../../code-analysis.props"/>
Expand All @@ -29,11 +28,11 @@
<PackageId>Microsoft.KernelMemory.MemoryDb.Redis</PackageId>
<Product>Redis connector for Kernel Memory</Product>
<Description>Redis connector for Microsoft Kernel Memory, to store and search memory using Redis vector search and other Redis features.</Description>
<PackageTags>Memory, RAG, Kernel Memory, Redis, HNSW, AI, Artificial Intelligence, Embeddings, Vector DB, Vector Search, ETL</PackageTags>
<PackageTags>Redis Memory, RAG, Kernel Memory, Redis, HNSW, AI, Artificial Intelligence, Embeddings, Vector DB, Vector Search, ETL</PackageTags>
</PropertyGroup>

<ItemGroup>
<None Include="README.md" Link="README.md" Pack="true" PackagePath="." Visible="false"/>
</ItemGroup>

</Project>
48 changes: 46 additions & 2 deletions extensions/Redis/RedisConfig.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,54 @@
// Copyright (c) Microsoft. All rights reserved.
// Copyright (c) Microsoft. All rights reserved.

#pragma warning disable IDE0130 // reduce number of "using" statements
// ReSharper disable once CheckNamespace - reduce number of "using" statements
namespace Microsoft.KernelMemory;

/// <summary>
/// Lays out the tag fields that you want redis to index.
/// </summary>
public class RedisConfig
{
// TODO
/// <summary>
/// Connection string required to connect to Redis
/// </summary>
public string ConnectionString { get; set; } = string.Empty;

/// <summary>
/// Gets the Prefix to use for prefix index names and all documents
/// inserted into Redis as part of Kernel Memory's operations.
/// </summary>
public string AppPrefix { get; }

/// <summary>
/// The Collection of tags that you want to be able to search on.
/// The Key is the tag name, and the char is the separator that you
/// want Redis to use to separate your tag fields. The default separator
/// is ','.
/// </summary>
public Dictionary<string, char?> Tags { get; } = new()
{
{ Constants.ReservedDocumentIdTag, '|' },
{ Constants.ReservedFileIdTag, '|' },
{ Constants.ReservedFilePartitionTag, '|' },
{ Constants.ReservedFileTypeTag, '|' },
};

/// <summary>
/// Initializes an instance of RedisMemoryConfiguration.
/// </summary>
/// <param name="appPrefix">The prefix to use for the index name and all documents inserted into Redis.</param>
/// <param name="tags">The collection of tags you want to be able to search on. The key</param>
public RedisConfig(string appPrefix = "km", Dictionary<string, char?>? tags = null)
{
this.AppPrefix = appPrefix;

if (tags is not null)
{
foreach (var tag in tags)
{
this.Tags[tag.Key] = tag.Value;
}
}
}
}
11 changes: 11 additions & 0 deletions extensions/Redis/RedisEmbeddingExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// Copyright (c) Microsoft. All rights reserved.

namespace Microsoft.KernelMemory.MemoryDb.Redis;

/// <summary>
/// Helper method for Embeddings.
/// </summary>
internal static class RedisEmbeddingExtensions
{
public static byte[] VectorBlob(this Embedding embedding) => embedding.Data.ToArray().SelectMany(BitConverter.GetBytes).ToArray();
}
2 changes: 0 additions & 2 deletions extensions/Redis/RedisException.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
// Copyright (c) Microsoft. All rights reserved.

using System;

namespace Microsoft.KernelMemory.MemoryDb.Redis;

public class RedisException : KernelMemoryException
Expand Down
Loading