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

Vector Search and Semantic Caching #417

Merged
merged 39 commits into from
Dec 5, 2023
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
e6f3627
starting vectors
slorello89 Oct 6, 2023
241645c
working out vector strings
slorello89 Oct 6, 2023
9150f41
string arrays to object arrays
slorello89 Oct 10, 2023
a377faf
seralization/deserialization of vectors
slorello89 Oct 10, 2023
bc6ce05
initial queries working
slorello89 Oct 12, 2023
c257207
Vector Range, score binding
slorello89 Oct 19, 2023
feb0946
removing extra FromHashSet method
slorello89 Oct 19, 2023
04fbb90
hybrid queries
slorello89 Oct 19, 2023
2a9ad73
external-vectorizers
slorello89 Oct 25, 2023
f2866f0
semantic cache start
slorello89 Oct 26, 2023
21957f5
more vectorizers
slorello89 Oct 26, 2023
4fbd0bf
some semantic caching
slorello89 Oct 26, 2023
30aca01
azure openai vectorizer.
slorello89 Oct 30, 2023
57f4d13
merge
slorello89 Oct 30, 2023
06b888b
reorganizing vectorizers
slorello89 Oct 30, 2023
65272dc
updating nuget packaging
slorello89 Oct 30, 2023
16c694c
use Vector<T> instead of just the given type
slorello89 Nov 2, 2023
73c6c05
readme updates
slorello89 Nov 2, 2023
9a3a257
updating docker image to .NET 7
slorello89 Nov 2, 2023
ecc0a91
test cleanup
slorello89 Nov 3, 2023
9d09c3a
slight tweak to NearestNeighbors/VectorRange APIs
slorello89 Nov 3, 2023
980e737
updates per Tylers comments
slorello89 Nov 3, 2023
efa7d33
changing query -> CompletionResult and queryPrompt -> prompt
slorello89 Nov 3, 2023
d33e935
adding setter for embedding
slorello89 Nov 22, 2023
d7cdae8
Resnet18 and AllMiniLML6V2 vectorizers
slorello89 Nov 27, 2023
81db70d
removing dependency on ML Resnet project (to support transitive distr…
slorello89 Nov 29, 2023
8d68528
moving to file based validation
slorello89 Nov 29, 2023
18e212a
semantic caching for native vectorizers
slorello89 Nov 29, 2023
59c40f7
Merge branch 'main' into feature/vectors
slorello89 Nov 30, 2023
22e4978
normalizing vectorization pipelines
slorello89 Dec 1, 2023
2e9264c
Merge branch 'feature/vectors' of https://github.com/redis/redis-om-d…
slorello89 Dec 1, 2023
7b8f9c9
fixing csproj file
slorello89 Dec 1, 2023
1528684
fixing test host for Vectorizer tests
slorello89 Dec 4, 2023
e5aab0e
lfs
slorello89 Dec 4, 2023
59b2b13
removing System.Drawing dep, adding onnxruntime
slorello89 Dec 4, 2023
843a81d
removing warnings
slorello89 Dec 4, 2023
3fc563f
adding MIT licenses for sources
slorello89 Dec 4, 2023
4411d02
readme updates
slorello89 Dec 4, 2023
96eae51
Encode -> Vectorize
slorello89 Dec 5, 2023
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
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -388,3 +388,5 @@ FodyWeavers.xsd
# JetBrains Rider
.idea/
*.sln.iml

test/Redis.OM.Unit.Tests/appsettings.json.local
98 changes: 98 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,104 @@ customers.Where(x => x.LastName == "Bond" && x.FirstName == "James");
customers.Where(x=>x.NickNames.Contains("Jim"));
```

### Vectors

Redis OM .NET also supports storing and querying Vectors stored in Redis.

A `Vector<T>` is a representation of an object that can be transformed into a vector by a Vectorizer.

A `VectorizerAttribute` is the abstract class you use to decorate your Vector fields, it is responsible for defining the logic to convert your Vectors into Embeddings. In the package `Redis.OM.Vectorizers` we provide vectorizers for HuggingFace, OpenAI, and AzureOpenAI to allow you to easily integrate them into your workflows.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the phrase "convert your Vectors into Embeddings" is a bit misleading as those two terms are relatively interchangeable. I think we're essentially talking about the definition of the various vector field attributes like distance metric, data type, dims, etc? Some of those subsumed by the choice of vectorizer for sure

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

changed the verbiage a bit - hopefully this is better?


#### Define a Vector in your Model.

To define a vector in your model, simply decorate a `Vector<T>` field with and `Indexed` and a `Vectorizer` attribute (in this case we'll use OpenAI):

```cs
[Document(StorageType = StorageType.Json)]
public class OpenAIQuery
{
[RedisIdField]
public string Id { get; set; }

[Indexed(DistanceMetric = DistanceMetric.COSINE)]

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you also show how a few other vector field attributes like index type (HNSW vs FLAT) and related args are set here?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a couple of other parameters for the index definition, and explained it a bit better in the modeling section.

[OpenAIVectorizer]
public Vector<string> Prompt { get; set; }

public string Response { get; set; }

[Indexed]
public string Language { get; set; }

[Indexed]
public DateTime TimeStamp { get; set; }
}
```

#### Insert Vectors into Redis

With the vector defined in our model, all we need to do is create Vectors of the generic type, and insert them with our model. Using our `RedisCollection`, you can do this by simply using `Insert`:

```cs
var query = new OpenAIQuery

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

naming this query makes sense given the implied caching use case here. Maybe spell it out a bit so it's clear why we are inserting a "query" object into your vector database?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Query is confusing in this context, is OpenAICompletionResult & completionResult better? (It's something that's not query that you might actually do with these embeddings lol).

{
Language = "en_us",
Prompt = Vector.Of("What is the Capital of France?"),
Response = "Paris",
TimeStamp = DateTime.Now - TimeSpan.FromHours(3)
};
collection.Insert(query);
```

The Vectorizer will manage the embedding generation for you without you having to intervene.

#### Query Vectors in Redis

To query vector fields in Redis, all you need to do is use the `VectorRange` method on a vector within our normal LINQ queries, and/or use the `NearestNeighbors` with whatever other filters you want to use, here's some examples:

```cs
var queryPrompt = Vector.Of("What really is the Capital of France?");

// simple vector range, find first within .15
var result = collection.First(x => x.Prompt.VectorRange(queryPrompt, .15));

// simple nearest neighbors query, finds first nearest neighbor
result = collection.NearestNeighbors(x => x.Prompt, 1, queryPrompt).First();

// hybrid query, pre-filters result set for english responses, then runs a nearest neighbors search.
result = collection.Where(x=>x.Language == "en_us").NearestNeighbors(x => x.Prompt, 1, queryPrompt).First();

// hybrid query, pre-filters responses newer than 4 hours, and finds first result within .15
var ts = DateTimeOffset.Now - TimeSpan.FromHours(4);
result = collection.First(x=>x.TimeStamp > ts && x.Prompt.VectorRange(queryPrompt, .15));
```

#### What Happens to the Embeddings?

With Redis OM, the embeddings can be completely transparent to you, they are generated and bound to the `Vector<T>` when you query/insert your vectors. If however you needed your embedding after the insertion/Query, they are available at `Vector<T>.Embedding`, and be queried either as the raw bytes, as an array of doubles or as an array of floats (depending on your vectorizer).

#### Configuration

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add other vector field attribute level configuration details here too?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added details about index definition in the modeling section as that's more or less where it belongs (the configuration section is talking about configuring the vectorizers)


The Vectorizers provided by the `Redis.OM.Vectorizers` package have some configuration parameters that it will pull in either from your `appsettings.json` file, or your environment variables (with your appsettings taking precedence).

| Configuration Parameter | Description |
|-------------------------------- |-----------------------------------------------|
| REDIS_OM_HF_TOKEN | HuggingFace Authorization token. |
| REDIS_OM_OAI_TOKEN | OpenAI Authorization token |
| REDIS_OM_OAI_API_URL | OpenAI URL |
| REDIS_OM_AZURE_OAI_TOKEN | Azure OpenAI api key |
| REDIS_OM_AZURE_OAI_RESOURCE_NAME | Azure resource name |
| REDIS_OM_AZURE_OAI_DEPLOYMENT_NAME | Azure deployment |

### Semantic Caching
slorello89 marked this conversation as resolved.
Show resolved Hide resolved

Redis OM also provides the ability to use Semantic Caching, as well as providers for OpenAI, HuggingFace, and Azure OpenAI to perform semantic caching. To use a Semantic Cache, simply pull one out of the RedisConnectionProvider and use `Store` to insert items, and `GetSimilar` to retrieve items. For example:

```cs
var cache = _provider.OpenAISemanticCache(token);
cache.Store("What is the capital of France?", "Paris");
var res = cache.GetSimilar("What really is the capital of France?").First();
```

### 🖩 Aggregations

We can also run aggregations on the customer object, again using expressions in LINQ:
Expand Down
72 changes: 16 additions & 56 deletions Redis.OM.sln
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Redis.OM.POC", "src\Redis.O
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Redis.OM.Unit.Tests", "test\Redis.OM.Unit.Tests\Redis.OM.Unit.Tests.csproj", "{570BF479-BCF4-4D1B-A702-2234CA0A3E7D}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Redis.OM.Test.ConsoleApp", "test\Redis.OM.Test.ConsoleApp\Redis.OM.Test.ConsoleApp.csproj", "{FC7E5ED3-51AC-45E6-A178-6287C9227975}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Redis.OM.Vectorizers", "src\Redis.OM.Vectorizers\Redis.OM.Vectorizers.csproj", "{4B9F4623-3126-48B7-B690-F28F702A4717}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Redis.OM.Analyzer", "src\Redis.OM.Analyzer\Redis.OM.Analyzer.csproj", "{44FAD9BB-C6DF-402C-BCE7-64E7C674F8D1}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Redis.OM.AspNetCore", "src\Redis.OM.AspNetCore\Redis.OM.AspNetCore.csproj", "{230ED77D-D625-43BC-94D6-6BDBACEA3EAF}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Redis.OM.Test.AspDotnetCore", "test\Redis.OM.Test.AspDotnetCore\Redis.OM.Test.AspDotnetCore.csproj", "{3F609AB2-1492-4EBE-9FF2-B47829307E9E}"
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Vectorizers", "Vectorizers", "{452DC80B-8195-44E8-A376-C246619492A8}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Expand Down Expand Up @@ -64,63 +60,27 @@ Global
{570BF479-BCF4-4D1B-A702-2234CA0A3E7D}.Release|x64.Build.0 = Release|Any CPU
{570BF479-BCF4-4D1B-A702-2234CA0A3E7D}.Release|x86.ActiveCfg = Release|Any CPU
{570BF479-BCF4-4D1B-A702-2234CA0A3E7D}.Release|x86.Build.0 = Release|Any CPU
{FC7E5ED3-51AC-45E6-A178-6287C9227975}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FC7E5ED3-51AC-45E6-A178-6287C9227975}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FC7E5ED3-51AC-45E6-A178-6287C9227975}.Debug|x64.ActiveCfg = Debug|Any CPU
{FC7E5ED3-51AC-45E6-A178-6287C9227975}.Debug|x64.Build.0 = Debug|Any CPU
{FC7E5ED3-51AC-45E6-A178-6287C9227975}.Debug|x86.ActiveCfg = Debug|Any CPU
{FC7E5ED3-51AC-45E6-A178-6287C9227975}.Debug|x86.Build.0 = Debug|Any CPU
{FC7E5ED3-51AC-45E6-A178-6287C9227975}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FC7E5ED3-51AC-45E6-A178-6287C9227975}.Release|Any CPU.Build.0 = Release|Any CPU
{FC7E5ED3-51AC-45E6-A178-6287C9227975}.Release|x64.ActiveCfg = Release|Any CPU
{FC7E5ED3-51AC-45E6-A178-6287C9227975}.Release|x64.Build.0 = Release|Any CPU
{FC7E5ED3-51AC-45E6-A178-6287C9227975}.Release|x86.ActiveCfg = Release|Any CPU
{FC7E5ED3-51AC-45E6-A178-6287C9227975}.Release|x86.Build.0 = Release|Any CPU
{44FAD9BB-C6DF-402C-BCE7-64E7C674F8D1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{44FAD9BB-C6DF-402C-BCE7-64E7C674F8D1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{44FAD9BB-C6DF-402C-BCE7-64E7C674F8D1}.Debug|x64.ActiveCfg = Debug|Any CPU
{44FAD9BB-C6DF-402C-BCE7-64E7C674F8D1}.Debug|x64.Build.0 = Debug|Any CPU
{44FAD9BB-C6DF-402C-BCE7-64E7C674F8D1}.Debug|x86.ActiveCfg = Debug|Any CPU
{44FAD9BB-C6DF-402C-BCE7-64E7C674F8D1}.Debug|x86.Build.0 = Debug|Any CPU
{44FAD9BB-C6DF-402C-BCE7-64E7C674F8D1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{44FAD9BB-C6DF-402C-BCE7-64E7C674F8D1}.Release|Any CPU.Build.0 = Release|Any CPU
{44FAD9BB-C6DF-402C-BCE7-64E7C674F8D1}.Release|x64.ActiveCfg = Release|Any CPU
{44FAD9BB-C6DF-402C-BCE7-64E7C674F8D1}.Release|x64.Build.0 = Release|Any CPU
{44FAD9BB-C6DF-402C-BCE7-64E7C674F8D1}.Release|x86.ActiveCfg = Release|Any CPU
{44FAD9BB-C6DF-402C-BCE7-64E7C674F8D1}.Release|x86.Build.0 = Release|Any CPU
{230ED77D-D625-43BC-94D6-6BDBACEA3EAF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{230ED77D-D625-43BC-94D6-6BDBACEA3EAF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{230ED77D-D625-43BC-94D6-6BDBACEA3EAF}.Debug|x64.ActiveCfg = Debug|Any CPU
{230ED77D-D625-43BC-94D6-6BDBACEA3EAF}.Debug|x64.Build.0 = Debug|Any CPU
{230ED77D-D625-43BC-94D6-6BDBACEA3EAF}.Debug|x86.ActiveCfg = Debug|Any CPU
{230ED77D-D625-43BC-94D6-6BDBACEA3EAF}.Debug|x86.Build.0 = Debug|Any CPU
{230ED77D-D625-43BC-94D6-6BDBACEA3EAF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{230ED77D-D625-43BC-94D6-6BDBACEA3EAF}.Release|Any CPU.Build.0 = Release|Any CPU
{230ED77D-D625-43BC-94D6-6BDBACEA3EAF}.Release|x64.ActiveCfg = Release|Any CPU
{230ED77D-D625-43BC-94D6-6BDBACEA3EAF}.Release|x64.Build.0 = Release|Any CPU
{230ED77D-D625-43BC-94D6-6BDBACEA3EAF}.Release|x86.ActiveCfg = Release|Any CPU
{230ED77D-D625-43BC-94D6-6BDBACEA3EAF}.Release|x86.Build.0 = Release|Any CPU
{3F609AB2-1492-4EBE-9FF2-B47829307E9E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3F609AB2-1492-4EBE-9FF2-B47829307E9E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3F609AB2-1492-4EBE-9FF2-B47829307E9E}.Debug|x64.ActiveCfg = Debug|Any CPU
{3F609AB2-1492-4EBE-9FF2-B47829307E9E}.Debug|x64.Build.0 = Debug|Any CPU
{3F609AB2-1492-4EBE-9FF2-B47829307E9E}.Debug|x86.ActiveCfg = Debug|Any CPU
{3F609AB2-1492-4EBE-9FF2-B47829307E9E}.Debug|x86.Build.0 = Debug|Any CPU
{3F609AB2-1492-4EBE-9FF2-B47829307E9E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3F609AB2-1492-4EBE-9FF2-B47829307E9E}.Release|Any CPU.Build.0 = Release|Any CPU
{3F609AB2-1492-4EBE-9FF2-B47829307E9E}.Release|x64.ActiveCfg = Release|Any CPU
{3F609AB2-1492-4EBE-9FF2-B47829307E9E}.Release|x64.Build.0 = Release|Any CPU
{3F609AB2-1492-4EBE-9FF2-B47829307E9E}.Release|x86.ActiveCfg = Release|Any CPU
{3F609AB2-1492-4EBE-9FF2-B47829307E9E}.Release|x86.Build.0 = Release|Any CPU
{4B9F4623-3126-48B7-B690-F28F702A4717}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4B9F4623-3126-48B7-B690-F28F702A4717}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4B9F4623-3126-48B7-B690-F28F702A4717}.Debug|x64.ActiveCfg = Debug|Any CPU
{4B9F4623-3126-48B7-B690-F28F702A4717}.Debug|x64.Build.0 = Debug|Any CPU
{4B9F4623-3126-48B7-B690-F28F702A4717}.Debug|x86.ActiveCfg = Debug|Any CPU
{4B9F4623-3126-48B7-B690-F28F702A4717}.Debug|x86.Build.0 = Debug|Any CPU
{4B9F4623-3126-48B7-B690-F28F702A4717}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4B9F4623-3126-48B7-B690-F28F702A4717}.Release|Any CPU.Build.0 = Release|Any CPU
{4B9F4623-3126-48B7-B690-F28F702A4717}.Release|x64.ActiveCfg = Release|Any CPU
{4B9F4623-3126-48B7-B690-F28F702A4717}.Release|x64.Build.0 = Release|Any CPU
{4B9F4623-3126-48B7-B690-F28F702A4717}.Release|x86.ActiveCfg = Release|Any CPU
{4B9F4623-3126-48B7-B690-F28F702A4717}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{7994382C-28EF-4F55-9B6D-810D35247816} = {8D9ECCFF-E022-4B68-BB43-228CEA248DEC}
{E3A31119-E4F1-4793-B5C2-ED2D51502B01} = {8D9ECCFF-E022-4B68-BB43-228CEA248DEC}
{44FAD9BB-C6DF-402C-BCE7-64E7C674F8D1} = {8D9ECCFF-E022-4B68-BB43-228CEA248DEC}
{230ED77D-D625-43BC-94D6-6BDBACEA3EAF} = {8D9ECCFF-E022-4B68-BB43-228CEA248DEC}
{452DC80B-8195-44E8-A376-C246619492A8} = {8D9ECCFF-E022-4B68-BB43-228CEA248DEC}
{4B9F4623-3126-48B7-B690-F28F702A4717} = {452DC80B-8195-44E8-A376-C246619492A8}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {E5752441-184B-4F17-BAD0-93823AC68607}
Expand Down
2 changes: 1 addition & 1 deletion dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM mcr.microsoft.com/dotnet/sdk:6.0
FROM mcr.microsoft.com/dotnet/sdk:7.0


WORKDIR /app
Expand Down
4 changes: 2 additions & 2 deletions src/Redis.OM.POC/RedisCommands.cs
Original file line number Diff line number Diff line change
Expand Up @@ -565,7 +565,7 @@ public static long XAck(this IRedisConnection connection, string streamId, strin
public static async Task<string?> XAddAsync(this IRedisConnection connection, string streamId, object message, string messageId = "*", int maxLen = -1, string minId = "", bool trimApprox = true, bool makeStream = true)
{
var kvps = message.BuildHashSet();
var args = new List<string> { streamId };
var args = new List<object> { streamId };
if (!makeStream)
{
args.Add("NOMKSTREAM");
Expand Down Expand Up @@ -611,7 +611,7 @@ public static long XAck(this IRedisConnection connection, string streamId, strin
public static string? XAdd(this IRedisConnection connection, string streamId, object message, string messageId = "*", int maxLen = -1, string minId = "", bool trimApprox = true, bool makeStream = true)
{
var kvps = message.BuildHashSet();
var args = new List<string> { streamId };
var args = new List<object> { streamId };
if (!makeStream)
{
args.Add("NOMKSTREAM");
Expand Down
12 changes: 6 additions & 6 deletions src/Redis.OM.POC/RedisConnection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,19 +42,19 @@ public RedisList GetList(string listName, uint chunkSize = 100)
return new RedisList(this, listName, chunkSize);
}

public RedisReply Execute(string command, params string[] args)
public RedisReply Execute(string command, params object[] args)
{
var commandBytes = RespHelper.BuildCommand(command, args);
var commandBytes = RespHelper.BuildCommand(command, args.Select(x=>x.ToString()).ToArray());
_socket.Send(commandBytes);
return RespHelper.GetNextReplyFromSocket(_socket);
}

public async Task<RedisReply> ExecuteAsync(string command, params string[] args)
public async Task<RedisReply> ExecuteAsync(string command, params object[] args)
{
await _semaphoreSlim.WaitAsync();
try
{
var commandBytes = new ArraySegment<byte>(RespHelper.BuildCommand(command, args));
var commandBytes = new ArraySegment<byte>(RespHelper.BuildCommand(command, args.Select(x=>x.ToString()).ToArray()));
await _socket.SendAsync(commandBytes, SocketFlags.None);
return await RespHelper.GetNextReplyFromSocketAsync(_socket);
}
Expand All @@ -66,7 +66,7 @@ public async Task<RedisReply> ExecuteAsync(string command, params string[] args)
}

/// <inheritdoc/>
public RedisReply[] ExecuteInTransaction(Tuple<string, string[]>[] commandArgsTuples)
public RedisReply[] ExecuteInTransaction(Tuple<string, object[]>[] commandArgsTuples)
{
var transaction = _db.CreateTransaction();
var tasks = new List<Task<RedisResult>>();
Expand All @@ -81,7 +81,7 @@ public RedisReply[] ExecuteInTransaction(Tuple<string, string[]>[] commandArgsTu
}

/// <inheritdoc/>
public async Task<RedisReply[]> ExecuteInTransactionAsync(Tuple<string, string[]>[] commandArgsTuples)
public async Task<RedisReply[]> ExecuteInTransactionAsync(Tuple<string, object[]>[] commandArgsTuples)
{
var transaction = _db.CreateTransaction();
var tasks = new List<Task<RedisResult>>();
Expand Down
2 changes: 1 addition & 1 deletion src/Redis.OM.POC/RedisHash.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public RedisHash(IRedisConnection connection, string keyName)
public string this[string key]
{
get => _connection.HMGet(_keyName, key).FirstOrDefault() ?? "";
set => _connection.HSet(_keyName, new KeyValuePair<string, string>(key,value));
set => _connection.HSet(_keyName, new KeyValuePair<string, object>(key,value));
}

public ICollection<string> Keys => new RedisHashScanner(_keyName, this, _connection, false);
Expand Down
15 changes: 3 additions & 12 deletions src/Redis.OM.POC/XRangeResponse.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,6 @@ public class XRangeResponse<T>
{
public IDictionary<string,T> Messages { get; set; }

public XRangeResponse(StreamEntry[] entries)
{
Messages = new Dictionary<string, T>();
foreach(var entry in entries)
{
var innerDict = entry.Values.ToDictionary(x => x.Name.ToString(), x => x.Value.ToString());
Messages.Add(entry.Id, (T)RedisObjectHandler.FromHashSet<T>(innerDict));
}
}
public XRangeResponse(RedisResult[] vals, string streamName)
{
Messages = new Dictionary<string, T>();
Expand All @@ -43,10 +34,10 @@ public XRangeResponse(RedisResult[] vals, string streamName)
{
var id = (string)((RedisResult[])obj.ToArray()[0])[i];
var pairs = ((RedisResult[])((RedisResult[])obj.ToArray()[0])[i + 1]);
var messageDict = new Dictionary<string, string>();
var messageDict = new Dictionary<string, RedisReply>();
for (var j = 0; j < pairs.Length; j += 2)
{
messageDict.Add(((string)pairs[j]), ((string)pairs[j + 1]));
messageDict.Add(((string)pairs[j]), new RedisReply(pairs[j + 1]));
}
Messages.Add(id, (T)RedisObjectHandler.FromHashSet<T>(messageDict));
}
Expand All @@ -70,7 +61,7 @@ public XRangeResponse(RedisReply[] vals, string streamName)
{
var id = (string)obj.ToArray()[0].ToArray()[i];
var pairs = obj.ToArray()[0].ToArray()[i + 1].ToArray();
var messageDict = new Dictionary<string, string>();
var messageDict = new Dictionary<string, RedisReply>();
for (var j = 0; j < pairs.Length; j+=2)
{
messageDict.Add(pairs[j], pairs[j + 1]);
Expand Down
Loading
Loading