Create Custom Validators
To make the implementation of custom validators easier, we have provided an interface in the OSS.
There are a few key steps to get up and running with a custom validator:
- Implementing the validator
- Conforming to the required interface
- Running Locally/Submitting to the Validator Hub
First, let's build out a simple custom validator. This validator will check if all text in the input is lowercase.
from typing import Any, Dict
import requests
from guardrails.validator_base import (
FailResult,
PassResult,
ValidationResult,
Validator,
register_validator,
ErrorSpan,
)
from typing import Optional, Callable
from rich import print
@register_validator(name="guardrails/lower_case", data_type="string")
class LowercaseValidator(Validator):
def __init__(
self,
on_fail: Optional[Callable] = None,
**kwargs,
):
super().__init__(on_fail=on_fail, **kwargs)
self.rail_alias = "lowercase"
def _validate(self, value: Any, metadata: Dict[str, Any]) -> ValidationResult:
if not isinstance(value, str):
return FailResult(
metadata=metadata,
error_message="Input must be a string.",
fix_value=None,
)
inference_result = self._inference(value)
if inference_result:
return PassResult()
else:
return FailResult(
metadata=metadata,
error_message="Input must be lowercase.",
fix_value=value.lower(),
)
def _inference_local(self, model_input: str) -> bool:
"""Implement a function to perform inference on a local machine."""
return model_input.islower()
def _inference_remote(self, model_input: str) -> bool:
"""Implement a function that will build a request and perform inference on a
remote machine. This is not required if you will always use local mode.
"""
response = requests.post(self.validation_endpoint, json={"inputs": model_input})
if response.status_code != 200:
raise Exception(
f"Remote inference failed with status code {response.status_code}"
)
return response.json().get("is_lowercase", False)
Simple usage running locally
If this validator was stored locally in your codebase, you would want to import it
from lowercase_validator import LowercaseValidator
# Usage example:
lowercase_validator = LowercaseValidator(use_local=True)
# Test cases for local validator
print(lowercase_validator.validate(value="hello world", metadata={})) # PassResult
print(lowercase_validator.validate("Hello World", {})) # FailResult
print(
lowercase_validator.validate("123", {})
) # PassResult (numbers are considered lowercase)
print(lowercase_validator.validate(123, {})) # FailResult (not a string)
PassResult(
outcome='pass',
value_override=<class 'guardrails.classes.validation.validation_result.PassResult.ValueOverrideSentinel'>,
metadata=None,
validated_chunk=None
)
```
FailResult(
outcome='fail',
error_message='Input must be lowercase.',
fix_value='hello world',
error_spans=None,
metadata={},
validated_chunk=None
)
```
FailResult(
outcome='fail',
error_message='Input must be lowercase.',
fix_value='123',
error_spans=None,
metadata={},
validated_chunk=None
)
```
FailResult(
outcome='fail',
error_message='Input must be a string.',
fix_value=None,
error_spans=None,
metadata={},
validated_chunk=None
)
The best practice would be to use the validator in a Guardrails.Guard()
# Make some imports
from rich import print
import guardrails as gd
import litellm
from IPython.display import clear_output
import time
prompt = """Tell me a short snippet about the company Apple.
Make sure the output is all in lowercase. Don't use any capital letters."""
guard = gd.Guard().use(LowercaseValidator, use_local=True)
Instantiate a guard object
result = fragment_generator = guard(
litellm.completion,
model="gpt-4o",
messages=[
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": prompt},
],
max_tokens=1024,
temperature=0,
)
print(result)
ValidationOutcome(
call_id='12637511488',
raw_llm_output="apple inc. is a multinational technology company headquartered in cupertino, california. it
designs, manufactures, and markets consumer electronics, software, and online services. some of its most well-known
products include the iphone, ipad, mac computers, apple watch, and apple tv. the company is also known for its
innovative software platforms like ios, macos, watchos, and tvos, as well as services such as the app store, apple
music, and icloud. founded in 1976 by steve jobs, steve wozniak, and ronald wayne, apple has grown to become one of
the world's most valuable and influential companies.",
validated_output="apple inc. is a multinational technology company headquartered in cupertino, california. it
designs, manufactures, and markets consumer electronics, software, and online services. some of its most well-known
products include the iphone, ipad, mac computers, apple watch, and apple tv. the company is also known for its
innovative software platforms like ios, macos, watchos, and tvos, as well as services such as the app store, apple
music, and icloud. founded in 1976 by steve jobs, steve wozniak, and ronald wayne, apple has grown to become one of
the world's most valuable and influential companies.",
reask=None,
validation_passed=True,
error=None
)
If you would like an improved implementation, you can implement the new ErrorSpan feature. This class provides a way to define the span of the error in the input.
@register_validator(name="guardrails/lower_case", data_type="string")
class LowercaseValidator(Validator):
def __init__(
self,
on_fail: Optional[Callable] = None,
**kwargs,
):
super().__init__(on_fail=on_fail, **kwargs)
self.rail_alias = "lowercase"
def _validate(self, value: Any, metadata: Dict[str, Any]) -> ValidationResult:
if not isinstance(value, str):
return FailResult(error_message="Input must be a string.", fix_value=None)
inference_result = self._inference(value)
error_spans = []
if inference_result:
for result in inference_result:
error_spans.append(
ErrorSpan(
start=result[0], end=result[1], reason="Input must be lowercase."
)
)
return FailResult(
error_message="Inputs must be lowercase.",
fix_value=value.lower(),
error_spans=error_spans
)
return PassResult()
def _inference_local(self, model_input: str) -> bool:
"""Implement a function to perform inference on a local machine."""
error_spans = []
start = None
for i, char in enumerate(model_input):
if char.isupper():
if start is None:
start = i
elif start is not None:
error_spans.append((start, i - 1))
start = None
if start is not None:
error_spans.append((start, len(model_input) - 1))
return error_spans
def _inference_remote(self, model_input: str) -> bool:
"""Implement a function that will build a request and perform inference on a
remote machine. This is not required if you will always use local mode.
"""
response = requests.post(self.validation_endpoint, json={"inputs": model_input})
if response.status_code != 200:
raise Exception(
f"Remote inference failed with status code {response.status_code}"
)
return response.json().get("is_lowercase", False)
guard = gd.Guard().use(LowercaseValidator, use_local=True)
prompt = """Tell me a short snippet about the company Apple. Make it all uppercase"""
result = guard(
litellm.completion,
prompt=prompt,
model="gpt-4o",
messages=[
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": prompt},
],
max_tokens=1024,
temperature=0,
)
print(result)
ValidationOutcome(
call_id='12637505888',
raw_llm_output="APPLE INC. IS A MULTINATIONAL TECHNOLOGY COMPANY HEADQUARTERED IN CUPERTINO, CALIFORNIA.
FOUNDED BY STEVE JOBS, STEVE WOZNIAK, AND RONALD WAYNE IN 1976, APPLE IS RENOWNED FOR ITS INNOVATIVE PRODUCTS SUCH
AS THE IPHONE, IPAD, MAC COMPUTERS, APPLE WATCH, AND APPLE TV. THE COMPANY IS ALSO KNOWN FOR ITS SOFTWARE
ECOSYSTEM, INCLUDING IOS, MACOS, WATCHOS, AND SERVICES LIKE THE APP STORE, APPLE MUSIC, AND ICLOUD. APPLE IS ONE OF
THE WORLD'S MOST VALUABLE COMPANIES AND A LEADER IN THE TECHNOLOGY INDUSTRY.",
validated_output="APPLE INC. IS A MULTINATIONAL TECHNOLOGY COMPANY HEADQUARTERED IN CUPERTINO, CALIFORNIA.
FOUNDED BY STEVE JOBS, STEVE WOZNIAK, AND RONALD WAYNE IN 1976, APPLE IS RENOWNED FOR ITS INNOVATIVE PRODUCTS SUCH
AS THE IPHONE, IPAD, MAC COMPUTERS, APPLE WATCH, AND APPLE TV. THE COMPANY IS ALSO KNOWN FOR ITS SOFTWARE
ECOSYSTEM, INCLUDING IOS, MACOS, WATCHOS, AND SERVICES LIKE THE APP STORE, APPLE MUSIC, AND ICLOUD. APPLE IS ONE OF
THE WORLD'S MOST VALUABLE COMPANIES AND A LEADER IN THE TECHNOLOGY INDUSTRY.",
reask=None,
validation_passed=False,
error=None
)