Skip to content

Commit fa68b88

Browse files
committed
support for index creation and vector search
1 parent ba6bc05 commit fa68b88

File tree

2 files changed

+84
-13
lines changed

2 files changed

+84
-13
lines changed

src/tools/misc.py

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,19 +14,6 @@ async def get_key_info(key: str) -> Dict[str, Any]:
1414
'type': key_type,
1515
'ttl': r.ttl(key)
1616
}
17-
18-
if key_type == 'string':
19-
info['value'] = r.get(key)
20-
elif key_type == 'list':
21-
info['value'] = r.lrange(key, 0, -1)
22-
elif key_type == 'hash':
23-
info['value'] = r.hgetall(key)
24-
elif key_type == 'set':
25-
info['value'] = r.smembers(key)
26-
elif key_type == 'zset':
27-
info['value'] = r.zrange(key, 0, -1, withscores=True)
28-
elif key_type == 'ReJSON-RL':
29-
info['value'] = r.json().get(key, "$")
3017

3118
return info
3219
except RedisError as e:

src/tools/redis_query_engine.py

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
from redis.exceptions import RedisError
44
from common.server import mcp
55
from redis.commands.search.query import Query
6+
from redis.commands.search.field import VectorField
7+
from redis.commands.search.indexDefinition import IndexDefinition
8+
import numpy as np
69

710

811
@mcp.tool()
@@ -49,3 +52,84 @@ async def get_indexed_keys_number(index_name: str) -> str:
4952
except RedisError as e:
5053
return f"Error retrieving number of keys: {str(e)}"
5154

55+
56+
@mcp.tool()
57+
async def create_vector_index_hash(index_name: str,
58+
prefix: str = "doc:",
59+
vector_field: str = "vector",
60+
dim: int = 1536,
61+
distance_metric: str = "COSINE") -> str:
62+
"""
63+
Create a Redis 8 vector similarity index using HNSW on a Redis hash.
64+
65+
This function sets up a Redis index for approximate nearest neighbor (ANN)
66+
search using the HNSW algorithm and float32 vector embeddings.
67+
68+
Args:
69+
index_name: The name of the Redis index to create.
70+
prefix: The key prefix used to identify documents to index (e.g., 'doc:').
71+
vector_field: The name of the vector field to be indexed for similarity search.
72+
dim: The dimensionality of the vectors stored under the vector_field.
73+
distance_metric: The distance function to use (e.g., 'COSINE', 'L2', 'IP').
74+
75+
Returns:
76+
A string indicating whether the index was created successfully or an error message.
77+
"""
78+
try:
79+
r = RedisConnectionManager.get_connection()
80+
81+
index_def = IndexDefinition(prefix=[prefix])
82+
schema = (
83+
VectorField(
84+
vector_field,
85+
"HNSW",
86+
{
87+
"TYPE": "FLOAT32",
88+
"DIM": dim,
89+
"DISTANCE_METRIC": distance_metric
90+
}
91+
)
92+
)
93+
94+
r.ft(index_name).create_index([schema], definition=index_def)
95+
return f"Index '{index_name}' created successfully."
96+
except RedisError as e:
97+
return f"Error creating index '{index_name}': {str(e)}"
98+
99+
100+
@mcp.tool()
101+
async def vector_search_hash(index_name: str,
102+
query_vector: list,
103+
vector_field: str = "vector",
104+
k: int = 5,
105+
return_fields: list = None) -> list:
106+
"""
107+
Perform a KNN vector similarity search using Redis 8 or later version on vectors stored in hash data structures.
108+
109+
Args:
110+
index_name: Name of the Redis index.
111+
vector_field: Name of the indexed vector field.
112+
query_vector: List of floats to use as the query vector.
113+
k: Number of nearest neighbors to return.
114+
return_fields: List of fields to return (optional).
115+
116+
Returns:
117+
A list of matched documents or an error message.
118+
"""
119+
try:
120+
r = RedisConnectionManager.get_connection()
121+
122+
# Convert query vector to float32 binary blob
123+
vector_blob = np.array(query_vector, dtype=np.float32).tobytes()
124+
125+
# Build the KNN query
126+
base_query = f"*=>[KNN {k} @{vector_field} $vec_param AS score]"
127+
query = Query(base_query).sort_by("score").paging(0, k).return_fields("id", "score", *return_fields or []).dialect(2)
128+
129+
# Perform the search with vector parameter
130+
results = r.ft(index_name).search(query, query_params={"vec_param": vector_blob})
131+
132+
# Format and return the results
133+
return [doc.__dict__ for doc in results.docs]
134+
except RedisError as e:
135+
return f"Error performing vector search on index '{index_name}': {str(e)}"

0 commit comments

Comments
 (0)