Skip to content

Commit 34fb4ca

Browse files
abbottdevJames Abbott
andauthored
Improved vector range argument parsing (#445)
* Better argument parsing for vector range expressions * Update contributors * Simplify expression cases, include test coverage for method expressions. * Reuse GetOperand for evaluating values --------- Co-authored-by: James Abbott <james.abbott@crispthinking.com>
1 parent cd8919a commit 34fb4ca

File tree

4 files changed

+86
-2
lines changed

4 files changed

+86
-2
lines changed

CONTRIBUTING.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ We welcome code contributions from the community, if you want to contribute code
2121
1. Fork this repo.
2222
2. Make your Code Changes.
2323
3. Write your tests.
24-
4. Use the `docker run -p 6379:6379 redis/redis-stack-server` as your local environment for running the functional tests.
24+
4. Use the `docker run -p 6379:6379 redis/redis-stack-server` as your local environment for running the functional tests. (Note: If your tests fail due to missing vocabulary, please run `fetch.models.sh` from the root directory until Git LFS has been resolved. These files are required for the tokenizers used by the functional tests)
2525
5. Verify the tests pass (there may be a couple of deployment-specific tests (e.g. Sentinel/Cluster) in Redis.OM which will fail outside of the GH environment we've setup so don't worry about those).
2626
6. If it's your first time contributing please add your Github handle the the Contributors section in the README.
2727
7. Push your changes to GitHub.

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -470,6 +470,7 @@ We'd love your contributions! If you want to contribute please read our [Contrib
470470
* [@mdrakib](https://github.com/mdrakib)
471471
* [@jrpavoncello](https://github.com/jrpavoncello)
472472
* [@axnetg](https://github.com/axnetg)
473+
* [@abbottdev](https://github.com/abbottdev)
473474

474475
<!-- Logo -->
475476
[Logo]: images/logo.svg

src/Redis.OM/Common/ExpressionParserUtilities.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1014,6 +1014,8 @@ private static object GetOperand(Expression expression)
10141014
{
10151015
MemberExpression me => GetValue(me.Member, ((ConstantExpression)me.Expression).Value),
10161016
ConstantExpression ce => ce.Value,
1017+
UnaryExpression ue when ue.NodeType == ExpressionType.Convert => Convert.ChangeType(GetOperand(ue.Operand), ue.Type),
1018+
MethodCallExpression me => me.Method.Invoke(me.Object, me.Arguments.Select(GetOperand).ToArray()),
10171019
_ => throw new InvalidOperationException("Could not determine value.")
10181020
};
10191021
}
@@ -1047,7 +1049,8 @@ private static string TranslateVectorRange(MethodCallExpression exp, List<object
10471049
bytes = vector.Embedding ?? throw new InvalidOperationException("Embedding was null");
10481050
}
10491051

1050-
var distance = (double)((ConstantExpression)exp.Arguments[2]).Value;
1052+
var distance = (double)GetOperand(exp.Arguments[2]);
1053+
10511054
var distanceArgName = parameters.Count.ToString();
10521055
parameters.Add(distance);
10531056
var vectorArgName = parameters.Count.ToString();

test/Redis.OM.Vectorizer.Tests/VectorizerFunctionalTests.cs

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ public VectorizerFunctionalTests()
1717
public void Test()
1818
{
1919
var connection = _provider.Connection;
20+
connection.DropIndex(typeof(DocWithVectors));
2021
connection.CreateIndex(typeof(DocWithVectors));
2122
connection.Set(new DocWithVectors
2223
{
@@ -33,6 +34,85 @@ public void Test()
3334
collection.NearestNeighbors(x => x.Sentence!, 5, "Hello world this really is Hal.");
3435
}
3536

37+
[Fact]
38+
public void VectorRangeUnaryExpressionTest()
39+
{
40+
var connection = _provider.Connection;
41+
connection.DropIndex(typeof(DocWithVectors));
42+
connection.CreateIndex(typeof(DocWithVectors));
43+
connection.Set(new DocWithVectors
44+
{
45+
Sentence = Vector.Of("Hello world this is Hal."),
46+
ImagePath = Vector.Of("hal.jpg")
47+
});
48+
49+
var variableRange = 5;
50+
var collection = new RedisCollection<DocWithVectors>(connection);
51+
52+
// images
53+
var res = collection.Where(x => x.Sentence!.VectorRange("Hal", variableRange, "score"));
54+
55+
Assert.NotNull(res.First().Scores!.RangeScore);
56+
Assert.InRange(res.First().Scores!.RangeScore!.Value, 0, 1);
57+
58+
// sentences
59+
collection.NearestNeighbors(x => x.Sentence!, variableRange, "Hello world this really is Hal.");
60+
}
61+
62+
[Fact]
63+
public void VectorRangeMemberExpressionTest()
64+
{
65+
var connection = _provider.Connection;
66+
connection.DropIndex(typeof(DocWithVectors));
67+
connection.CreateIndex(typeof(DocWithVectors));
68+
connection.Set(new DocWithVectors
69+
{
70+
Sentence = Vector.Of("Hello world this is Hal."),
71+
ImagePath = Vector.Of("hal.jpg")
72+
});
73+
74+
double variableRange = 5 + 5;
75+
var collection = new RedisCollection<DocWithVectors>(connection);
76+
77+
// images
78+
79+
var res = collection.Where(x => x.Sentence!.VectorRange("Hal", variableRange, "score"));
80+
81+
Assert.NotNull(res.First().Scores!.RangeScore);
82+
Assert.InRange(res.First().Scores!.RangeScore!.Value, 0, 1);
83+
84+
// sentences
85+
collection.NearestNeighbors(x => x.Sentence!, 5, "Hello world this really is Hal.");
86+
}
87+
88+
private static double GetVectorRange() => 5;
89+
private static int GetKnnNeighbours() => 5;
90+
91+
[Fact]
92+
public void VectorRangeMethodExpressionTest()
93+
{
94+
var connection = _provider.Connection;
95+
connection.DropIndex(typeof(DocWithVectors));
96+
connection.CreateIndex(typeof(DocWithVectors));
97+
connection.Set(new DocWithVectors
98+
{
99+
Sentence = Vector.Of("Hello world this is Hal."),
100+
ImagePath = Vector.Of("hal.jpg")
101+
});
102+
103+
var collection = new RedisCollection<DocWithVectors>(connection);
104+
105+
// images
106+
107+
var res = collection.Where(x => x.Sentence!.VectorRange("Hal", GetVectorRange(), "score"));
108+
109+
Assert.NotNull(res.First().Scores!.RangeScore);
110+
Assert.InRange(res.First().Scores!.RangeScore!.Value, 0, 1);
111+
112+
// sentences
113+
collection.NearestNeighbors(x => x.Sentence!, GetKnnNeighbours(), "Hello world this really is Hal.");
114+
}
115+
36116
[Fact]
37117
public void SemanticCaching()
38118
{

0 commit comments

Comments
 (0)