Skip to content

Commit 7b4ff15

Browse files
authored
Merge branch 'master' into patch-4
2 parents 83a633e + 755a421 commit 7b4ff15

File tree

6 files changed

+91
-5
lines changed

6 files changed

+91
-5
lines changed

.github/workflows/integration.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ jobs:
7474
max-parallel: 15
7575
fail-fast: false
7676
matrix:
77-
redis-version: ['8.2-RC1-pre', '${{ needs.redis_version.outputs.CURRENT }}', '7.4.4', '7.2.9']
77+
redis-version: ['8.2', '${{ needs.redis_version.outputs.CURRENT }}', '7.4.4', '7.2.9']
7878
python-version: ['3.9', '3.13']
7979
parser-backend: ['plain']
8080
event-loop: ['asyncio']
@@ -99,7 +99,7 @@ jobs:
9999
fail-fast: false
100100
matrix:
101101
redis-version: [ '${{ needs.redis_version.outputs.CURRENT }}' ]
102-
python-version: ['3.9', '3.10', '3.11', '3.12', 'pypy-3.9', 'pypy-3.10']
102+
python-version: ['3.10', '3.11', '3.12', 'pypy-3.9', 'pypy-3.10']
103103
parser-backend: [ 'plain' ]
104104
event-loop: [ 'asyncio' ]
105105
env:

redis/commands/core.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4172,17 +4172,17 @@ def zadd(
41724172
the existing score will be incremented by. When using this mode the
41734173
return value of ZADD will be the new score of the element.
41744174
4175-
``LT`` Only update existing elements if the new score is less than
4175+
``lt`` only updates existing elements if the new score is less than
41764176
the current score. This flag doesn't prevent adding new elements.
41774177
4178-
``GT`` Only update existing elements if the new score is greater than
4178+
``gt`` only updates existing elements if the new score is greater than
41794179
the current score. This flag doesn't prevent adding new elements.
41804180
41814181
The return value of ZADD varies based on the mode specified. With no
41824182
options, ZADD returns the number of new elements added to the sorted
41834183
set.
41844184
4185-
``NX``, ``LT``, and ``GT`` are mutually exclusive options.
4185+
``nx``, ``lt``, and ``gt`` are mutually exclusive options.
41864186
41874187
See: https://redis.io/commands/ZADD
41884188
"""

redis/commands/vectorset/commands.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ def vsim(
129129
filter_ef: Optional[str] = None,
130130
truth: Optional[bool] = False,
131131
no_thread: Optional[bool] = False,
132+
epsilon: Optional[Number] = None,
132133
) -> Union[
133134
Awaitable[Optional[List[Union[List[EncodableT], Dict[EncodableT, Number]]]]],
134135
Optional[List[Union[List[EncodableT], Dict[EncodableT, Number]]]],
@@ -152,6 +153,9 @@ def vsim(
152153
``no_thread`` when enabled forces the command to execute the search
153154
on the data structure in the main thread.
154155
156+
``epsilon`` floating point between 0 and 1, if specified will return
157+
only elements with distance no further than the specified one.
158+
155159
For more information see https://redis.io/commands/vsim
156160
"""
157161

@@ -176,6 +180,9 @@ def vsim(
176180
if count:
177181
pieces.extend(["COUNT", count])
178182

183+
if epsilon:
184+
pieces.extend(["EPSILON", epsilon])
185+
179186
if ef:
180187
pieces.extend(["EF", ef])
181188

tests/test_asyncio/test_vsets.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,21 @@ async def test_vsim_truth_no_thread_enabled(d_client):
423423
assert isinstance(sim_no_thread, dict)
424424

425425

426+
@skip_if_server_version_lt("8.2.0")
427+
async def test_vsim_epsilon(d_client):
428+
await d_client.vset().vadd("myset", [2, 1, 1], "a")
429+
await d_client.vset().vadd("myset", [2, 0, 1], "b")
430+
await d_client.vset().vadd("myset", [2, 0, 0], "c")
431+
await d_client.vset().vadd("myset", [2, 0, -1], "d")
432+
await d_client.vset().vadd("myset", [2, -1, -1], "e")
433+
434+
res1 = await d_client.vset().vsim("myset", [2, 1, 1])
435+
assert 5 == len(res1)
436+
437+
res2 = await d_client.vset().vsim("myset", [2, 1, 1], epsilon=0.5)
438+
assert 4 == len(res2)
439+
440+
426441
@skip_if_server_version_lt("7.9.0")
427442
async def test_vdim(d_client):
428443
float_array = [1, 4.32, 0.11, 0.5, 0.9, 0.1, 0.2]

tests/test_search.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3802,3 +3802,52 @@ def test_svs_vamana_vector_search_with_parameters(client):
38023802
else:
38033803
assert res["total_results"] == 3
38043804
assert "doc0" == res["results"][0]["id"]
3805+
3806+
3807+
@pytest.mark.redismod
3808+
@skip_ifmodversion_lt("2.4.3", "search")
3809+
@skip_if_server_version_lt("8.1.224")
3810+
def test_svs_vamana_vector_search_with_parameters_leanvec(client):
3811+
client.ft().create_index(
3812+
(
3813+
VectorField(
3814+
"v",
3815+
"SVS-VAMANA",
3816+
{
3817+
"TYPE": "FLOAT32",
3818+
"DIM": 8,
3819+
"DISTANCE_METRIC": "L2",
3820+
"COMPRESSION": "LeanVec8x8", # LeanVec compression required for REDUCE
3821+
"CONSTRUCTION_WINDOW_SIZE": 200,
3822+
"GRAPH_MAX_DEGREE": 32,
3823+
"SEARCH_WINDOW_SIZE": 15,
3824+
"EPSILON": 0.01,
3825+
"TRAINING_THRESHOLD": 1024,
3826+
"REDUCE": 4, # Half of DIM (8/2 = 4)
3827+
},
3828+
),
3829+
)
3830+
)
3831+
3832+
# Create test vectors (8-dimensional to match DIM)
3833+
vectors = [
3834+
[1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0],
3835+
[2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0],
3836+
[3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0],
3837+
[4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0],
3838+
[5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0],
3839+
]
3840+
3841+
for i, vec in enumerate(vectors):
3842+
client.hset(f"doc{i}", "v", np.array(vec, dtype=np.float32).tobytes())
3843+
3844+
query = Query("*=>[KNN 3 @v $vec as score]").no_content()
3845+
query_params = {"vec": np.array(vectors[0], dtype=np.float32).tobytes()}
3846+
3847+
res = client.ft().search(query, query_params=query_params)
3848+
if is_resp2_connection(client):
3849+
assert res.total == 3
3850+
assert "doc0" == res.docs[0].id
3851+
else:
3852+
assert res["total_results"] == 3
3853+
assert "doc0" == res["results"][0]["id"]

tests/test_vsets.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -425,6 +425,21 @@ def test_vsim_truth_no_thread_enabled(d_client):
425425
assert isinstance(sim_no_thread, dict)
426426

427427

428+
@skip_if_server_version_lt("8.2.0")
429+
def test_vsim_epsilon(d_client):
430+
d_client.vset().vadd("myset", [2, 1, 1], "a")
431+
d_client.vset().vadd("myset", [2, 0, 1], "b")
432+
d_client.vset().vadd("myset", [2, 0, 0], "c")
433+
d_client.vset().vadd("myset", [2, 0, -1], "d")
434+
d_client.vset().vadd("myset", [2, -1, -1], "e")
435+
436+
res1 = d_client.vset().vsim("myset", [2, 1, 1])
437+
assert 5 == len(res1)
438+
439+
res2 = d_client.vset().vsim("myset", [2, 1, 1], epsilon=0.5)
440+
assert 4 == len(res2)
441+
442+
428443
@skip_if_server_version_lt("7.9.0")
429444
def test_vdim(d_client):
430445
float_array = [1, 4.32, 0.11, 0.5, 0.9, 0.1, 0.2]

0 commit comments

Comments
 (0)