Skip to content

Commit 278b9cd

Browse files
authored
Merge pull request #981 from guardrails-ai/hub-contribution-doc
Validator Concept Doc
2 parents 17dcaf8 + 1a6e8f4 commit 278b9cd

File tree

1 file changed

+169
-0
lines changed

1 file changed

+169
-0
lines changed

docs/concepts/validators.md

Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
# Validators
2+
3+
Validators are how we apply quality controls to the outputs of LLMs. They specify the criteria to measure whether an output is valid, as well as what actions to take when an output does not meet those criteria.
4+
5+
## How do Validators work?
6+
Each validator is a method that encodes some criteria, and checks if a given value meets that criteria.
7+
8+
- If the value passes the criteria defined, the validator returns `PassResult`. In most cases this means returning that value unchanged. In very few advanced cases, there may be a a value override (the specific validator will document this).
9+
- If the value does not pass the criteria, a `FailResult` is returned. In this case, the validator applies the user-configured `on_fail` policies (see [On-Fail Policies](/docs/hub/concepts/on_fail_policies.md) for more details).
10+
11+
## Runtime Metadata
12+
13+
Occasionally, validators need additional metadata that is only available during runtime. Metadata could be data generated during the execution of a validator (*important if you're writing your own validators*), or could just be a container for runtime arguments.
14+
15+
As an example, the `ExtractedSummarySentencesMatch` validator accepts a `filepaths` property in the metadata dictionary to specify what source files to compare the summary against to ensure similarity. Unlike arguments which are specified at validator initialization, metadata is specified when calling `guard.validate` or `guard.__call__` (this is the `guard()` function). For more information on how to use metadata, see [How to use Metadata](/docs/hub/how_to_guides/metadata.md).
16+
17+
```python
18+
guard = Guard.from_rail("my_railspec.rail")
19+
20+
outcome = guard(
21+
llm_api=openai.chat.completions.create,
22+
model="gpt-3.5-turbo",
23+
num_reasks=3,
24+
metadata={
25+
"filepaths": [
26+
"./my_data/article1.txt",
27+
"./my_data/article2.txt",
28+
]
29+
}
30+
)
31+
```
32+
33+
## Custom Validators
34+
35+
If you need to perform a validation that is not currently supported by the hub, you can create your own custom validators.
36+
37+
A custom validator can be as simple as a single function if you do not require addtional arguments:
38+
39+
```py
40+
from typing import Dict
41+
from guardrails.validators import (
42+
FailResult,
43+
PassResult,
44+
register_validator,
45+
ValidationResult,
46+
)
47+
48+
@register_validator(name="starts-with-a", data_type="string")
49+
def starts_with_a(value: str, metadata: Dict) -> ValidationResult:
50+
if value.startswith("a"):
51+
return PassResult()
52+
53+
return FailResult(
54+
error_message=f"Value {value} does not start with a.",
55+
fix_value="a" + value,
56+
)
57+
```
58+
59+
:::note
60+
A fix_value was supplied in the FailResult in the example above. This value represents a programmatic fix that can be applied to the output if `on_fail='fix'` is passed during validator initialization.
61+
:::
62+
63+
If you need to perform more complex operations or require addtional arguments to perform the validation, then the validator can be specified as a class that inherits from our base Validator class:
64+
65+
```py
66+
from typing import Callable, Dict, Optional
67+
from guardrails.validators import (
68+
FailResult,
69+
PassResult,
70+
register_validator,
71+
ValidationResult,
72+
Validator,
73+
)
74+
75+
@register_validator(name="starts-with", data_type="string")
76+
class StartsWith(Validator):
77+
def __init__(self, prefix: str, on_fail: Optional[Callable] = None):
78+
super().__init__(on_fail=on_fail, prefix=prefix)
79+
self.prefix = prefix
80+
81+
def validate(self, value: str, metadata: Dict) -> ValidationResult:
82+
if value.startswith(self.prefix):
83+
return PassResult()
84+
85+
return FailResult(
86+
error_message=f"Value {value} does not start with {self.prefix}.",
87+
fix_value=self.prefix + value, # To enable the "fix" option for on-fail
88+
)
89+
```
90+
91+
Custom validators must be defined before creating a `Guard` or `RAIL` spec in the code,
92+
but otherwise can be used like built in validators. It can be used in a `RAIL` spec OR
93+
a `Pydantic` model like so:
94+
95+
Custom validators must be defined before creating a `Guard` in the code,
96+
but otherwise can be used just like built in validators.
97+
98+
### Guard.use Example
99+
```py
100+
from guardrails import Guard
101+
from .my_custom_validators import starts_with_a, StartsWith
102+
103+
guard = Guard().use(
104+
StartsWith("my-prefix")
105+
).use(
106+
starts_with_a()
107+
)
108+
```
109+
110+
### Pydantic Example
111+
```py
112+
from guardrails import Guard
113+
from pydantic import BaseModel, Field
114+
from .my_custom_validators import starts_with_a, StartsWith
115+
116+
class MyModel(BaseModel):
117+
a_string: Field(validators=[starts_with_a()])
118+
custom_string: Field(validators=[StartsWith("my-prefix")])
119+
120+
guard = Guard.from_pydantic(MyModel)
121+
```
122+
123+
### RAIL Example
124+
```xml
125+
<rail version="0.1">
126+
...
127+
<output>
128+
<string name="a_string" type="string" validators="starts-with-a">
129+
<string name="custom_string" type="string" validators="starts-with: my-prefix">
130+
</output>
131+
...
132+
</rail>
133+
```
134+
135+
## Submitting a Custom Validator to the Hub
136+
137+
There are two ways to create a new validator and submit it to the Hub.
138+
139+
1. For lightweight validators, use the `hub` CLI to create a new validator and submit it to the Hub.
140+
2. For more complex validators, clone the Validator-Template repository and register the validator via the Guardrails Hub website.
141+
142+
### Creating a new validator using the `hub` CLI
143+
144+
The `hub` CLI provides a simple way to create a new validator and submit it to the Hub. The `hub` CLI will create a new validator in the current directory and submit it to the Hub.
145+
146+
To create a new validator using the `hub` CLI, run the following command:
147+
148+
```bash
149+
guardrails hub create-validator my_validator
150+
```
151+
152+
This will create a new file called `my_validator.py` in the current directory. The file will contain a template and instructions for creating a new validator.
153+
154+
```bash
155+
guardrails hub submit my_validator
156+
```
157+
158+
### Creating a new validator using the Validator-Template repository
159+
160+
For more complex validators, you can clone the [Validator-Template repository](https://github.com/guardrails-ai/validator-template) and register the validator via a Google Form on the Guardrails Hub website.
161+
162+
```bash
163+
git clone git@github.com:guardrails-ai/validator-template.git
164+
```
165+
166+
Once the repository is cloned and the validator is created, you can register the validator via this [Google Form](https://forms.gle/N6UaE9611niuMxZj7).
167+
168+
169+

0 commit comments

Comments
 (0)