Skip to content

Support client-side schema validation using Pydantic #304

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

Merged
merged 11 commits into from
Mar 31, 2025
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
7 changes: 7 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,11 @@ jobs:
with:
credentials_json: ${{ secrets.GOOGLE_CREDENTIALS }}

- name: Set HuggingFace token
run: |
mkdir -p ~/.huggingface
echo '{"token":"${{ secrets.HF_TOKEN }}"}' > ~/.huggingface/token

- name: Run tests
if: matrix.connection == 'plain' && matrix.redis-version == 'latest'
env:
Expand All @@ -149,6 +154,7 @@ jobs:
OPENAI_API_VERSION: ${{ secrets.OPENAI_API_VERSION }}
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
HF_TOKEN: ${{ secrets.HF_TOKEN }}
run: |
make test-all

Expand All @@ -173,6 +179,7 @@ jobs:
OPENAI_API_VERSION: ${{ secrets.OPENAI_API_VERSION }}
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
HF_TOKEN: ${{ secrets.HF_TOKEN }}
run: |
docker run -d --name redis -p 6379:6379 redis/redis-stack-server:latest
make test-notebooks
Expand Down
238 changes: 138 additions & 100 deletions docs/user_guide/01_getting_started.ipynb

Large diffs are not rendered by default.

562 changes: 547 additions & 15 deletions poetry.lock

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ tenacity = ">=8.2.2"
tabulate = "^0.9.0"
ml-dtypes = "^0.4.0"
python-ulid = "^3.0.0"
jsonpath-ng = "^1.5.0"

openai = { version = "^1.13.0", optional = true }
sentence-transformers = { version = "^3.4.0", optional = true }
scipy = [
Expand Down
34 changes: 28 additions & 6 deletions redisvl/exceptions.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,32 @@
class RedisVLException(Exception):
"""Base RedisVL exception"""
"""
RedisVL Exception Classes

This module defines all custom exceptions used throughout the RedisVL library.
"""

class RedisModuleVersionError(RedisVLException):
"""Invalid module versions installed"""

class RedisVLError(Exception):
"""Base exception for all RedisVL errors."""

class RedisSearchError(RedisVLException):
"""Error while performing a search or aggregate request"""
pass


class RedisModuleVersionError(RedisVLError):
"""Error raised when required Redis modules are missing or have incompatible versions."""

pass


class RedisSearchError(RedisVLError):
"""Error raised for Redis Search specific operations."""

pass


class SchemaValidationError(RedisVLError):
"""Error when validating data against a schema."""

def __init__(self, message, index=None):
if index is not None:
message = f"Validation failed for object at index {index}: {message}"
super().__init__(message)
13 changes: 6 additions & 7 deletions redisvl/extensions/llmcache/semantic.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,12 +95,8 @@ def __init__(
}

# Use the index name as the key prefix by default
if "prefix" in kwargs:
prefix = kwargs["prefix"]
else:
prefix = name

dtype = kwargs.get("dtype")
prefix = kwargs.pop("prefix", name)
dtype = kwargs.pop("dtype", None)

# Validate a provided vectorizer or set the default
if vectorizer:
Expand All @@ -111,7 +107,10 @@ def __init__(
f"Provided dtype {dtype} does not match vectorizer dtype {vectorizer.dtype}"
)
else:
vectorizer_kwargs = {"dtype": dtype} if dtype else {}
vectorizer_kwargs = kwargs

if dtype:
vectorizer_kwargs.update(**{"dtype": dtype})

vectorizer = HFTextVectorizer(
model="sentence-transformers/all-mpnet-base-v2",
Expand Down
13 changes: 10 additions & 3 deletions redisvl/extensions/router/semantic.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ def __init__(
connection_kwargs (Dict[str, Any]): The connection arguments
for the redis client. Defaults to empty {}.
"""
dtype = kwargs.get("dtype")
dtype = kwargs.pop("dtype", None)

# Validate a provided vectorizer or set the default
if vectorizer:
Expand All @@ -83,8 +83,15 @@ def __init__(
f"Provided dtype {dtype} does not match vectorizer dtype {vectorizer.dtype}"
)
else:
vectorizer_kwargs = {"dtype": dtype} if dtype else {}
vectorizer = HFTextVectorizer(**vectorizer_kwargs)
vectorizer_kwargs = kwargs

if dtype:
vectorizer_kwargs.update(**{"dtype": dtype})

vectorizer = HFTextVectorizer(
model="sentence-transformers/all-mpnet-base-v2",
**vectorizer_kwargs,
)

if routing_config is None:
routing_config = RoutingConfig()
Expand Down
9 changes: 6 additions & 3 deletions redisvl/extensions/session_manager/semantic_session.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ def __init__(
super().__init__(name, session_tag)

prefix = prefix or name
dtype = kwargs.get("dtype")
dtype = kwargs.pop("dtype", None)

# Validate a provided vectorizer or set the default
if vectorizer:
Expand All @@ -82,10 +82,13 @@ def __init__(
f"Provided dtype {dtype} does not match vectorizer dtype {vectorizer.dtype}"
)
else:
vectorizer_kwargs = {"dtype": dtype} if dtype else {}
vectorizer_kwargs = kwargs

if dtype:
vectorizer_kwargs.update(**{"dtype": dtype})

vectorizer = HFTextVectorizer(
model="sentence-transformers/msmarco-distilbert-cos-v5",
model="sentence-transformers/all-mpnet-base-v2",
**vectorizer_kwargs,
)

Expand Down
Loading