Skip to content

Commit 02a569b

Browse files
committed
add validator and fix readme
1 parent 6f21499 commit 02a569b

File tree

2 files changed

+60
-100
lines changed

2 files changed

+60
-100
lines changed

README.md

Lines changed: 26 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -1,110 +1,54 @@
11
# Overview
22

3-
| Developed by | Guardrails AI |
3+
| Developed by | Jonathan Bennion |
44
| --- | --- |
5-
| Date of development | Feb 15, 2024 |
5+
| Date of development | Mar 29, 2024 |
66
| Validator type | Format |
7-
| Blog | |
87
| License | Apache 2 |
98
| Input/Output | Output |
109

11-
## Description
12-
13-
### Intended Use
14-
This validator is a template for creating other validators, but for demonstrative purposes it ensures that a generated output is the literal `pass`.
10+
# Description
11+
This bias check format validator ensures textual outputs do not contain biased language towards specific demographics, such as race, gender, sex, religion, ethnicity.
12+
13+
## Intended Use
14+
This validator can be used to ensure fairness of model output across various demographic groups.
1515

16-
### Requirements
16+
## Requirements
1717

1818
* Dependencies:
19-
- guardrails-ai>=0.4.0
19+
- guardrails-ai>=0.4.0
20+
- dbias>=0.1.0
21+
22+
* Dev Dependencies:
23+
- pytest
24+
- pyright
25+
- ruff
2026

2127
* Foundation model access keys:
22-
- OPENAI_API_KEY
28+
- Dependent on the use case (rephrase if unclear)
29+
2330

24-
## Installation
31+
# Installation
2532

2633
```bash
27-
$ guardrails hub install hub://guardrails/validator_template
34+
$ guardrails hub install hub://guardrails/bias_check
2835
```
2936

30-
## Usage Examples
37+
# Usage Examples
3138

32-
### Validating string output via Python
39+
## Validating string output via Python
3340

3441
In this example, we apply the validator to a string output generated by an LLM.
3542

3643
```python
3744
# Import Guard and Validator
38-
from guardrails.hub import ValidatorTemplate
45+
from guardrails.hub import BiasCheck
3946
from guardrails import Guard
4047

4148
# Setup Guard
42-
guard = Guard().use(
43-
ValidatorTemplate
49+
guard = Guard.use(
50+
BiasCheck()
4451
)
4552

46-
guard.validate("pass") # Validator passes
47-
guard.validate("fail") # Validator fails
48-
```
49-
50-
### Validating JSON output via Python
51-
52-
In this example, we apply the validator to a string field of a JSON output generated by an LLM.
53-
54-
```python
55-
# Import Guard and Validator
56-
from pydantic import BaseModel, Field
57-
from guardrails.hub import ValidatorTemplate
58-
from guardrails import Guard
59-
60-
# Initialize Validator
61-
val = ValidatorTemplate()
62-
63-
# Create Pydantic BaseModel
64-
class Process(BaseModel):
65-
process_name: str
66-
status: str = Field(validators=[val])
67-
68-
# Create a Guard to check for valid Pydantic output
69-
guard = Guard.from_pydantic(output_class=Process)
70-
71-
# Run LLM output generating JSON through guard
72-
guard.parse("""
73-
{
74-
"process_name": "templating",
75-
"status": "pass"
76-
}
77-
""")
78-
```
79-
80-
# API Reference
81-
82-
**`__init__(self, on_fail="noop")`**
83-
<ul>
84-
Initializes a new instance of the ValidatorTemplate class.
85-
86-
**Parameters**
87-
- **`arg_1`** *(str)*: A placeholder argument to demonstrate how to use init arguments.
88-
- **`arg_2`** *(str)*: Another placeholder argument to demonstrate how to use init arguments.
89-
- **`on_fail`** *(str, Callable)*: The policy to enact when a validator fails. If `str`, must be one of `reask`, `fix`, `filter`, `refrain`, `noop`, `exception` or `fix_reask`. Otherwise, must be a function that is called when the validator fails.
90-
</ul>
91-
<br/>
92-
93-
**`validate(self, value, metadata) -> ValidationResult`**
94-
<ul>
95-
Validates the given `value` using the rules defined in this validator, relying on the `metadata` provided to customize the validation process. This method is automatically invoked by `guard.parse(...)`, ensuring the validation logic is applied to the input data.
96-
97-
Note:
98-
99-
1. This method should not be called directly by the user. Instead, invoke `guard.parse(...)` where this method will be called internally for each associated Validator.
100-
2. When invoking `guard.parse(...)`, ensure to pass the appropriate `metadata` dictionary that includes keys and values required by this validator. If `guard` is associated with multiple validators, combine all necessary metadata into a single dictionary.
101-
102-
**Parameters**
103-
- **`value`** *(Any)*: The input value to validate.
104-
- **`metadata`** *(dict)*: A dictionary containing metadata required for validation. Keys and values must match the expectations of this validator.
105-
106-
107-
| Key | Type | Description | Default |
108-
| --- | --- | --- | --- |
109-
| `key1` | String | Description of key1's role. | N/A |
110-
</ul>
53+
guard.validate("The movie was great!") # Validator passes
54+
guard.validate("Why do men always think the movie was great?") # Validator fails

validator/main.py

Lines changed: 34 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -8,41 +8,57 @@
88
register_validator,
99
)
1010

11+
import Dbias
12+
from Dbias import text_debiasing
1113

12-
@register_validator(name="guardrails/validator_template", data_type="string")
13-
class ValidatorTemplate(Validator):
14-
"""Validates that {fill in how you validator interacts with the passed value}.
14+
@register_validator(name="guardrails/bias_check", data_type="string")
15+
class BiasCheck(Validator):
16+
"""Validates that the text is free from biases related to age, gender, sex, ethnicity, religion, etc.
1517
1618
**Key Properties**
1719
1820
| Property | Description |
1921
| ----------------------------- | --------------------------------- |
20-
| Name for `format` attribute | `guardrails/validator_template` |
22+
| Name for `format` attribute | `guardrails/bias_check` |
2123
| Supported data types | `string` |
22-
| Programmatic fix | {If you support programmatic fixes, explain it here. Otherwise `None`} |
24+
| Programmatic fix | The debiased text if bias is detected |
2325
2426
Args:
25-
arg_1 (string): {Description of the argument here}
26-
arg_2 (string): {Description of the argument here}
27+
debias_strength (float): The strength of the bias to apply, ranging from 0 to 1.
28+
on_fail (Callable): The policy to enact when a validator fails. If `str`, must be one of `reask`, `fix`, `filter`, `refrain`, `noop`, `exception` or `fix_reask`. Otherwise, must be a function that is called when the validator fails.
2729
""" # noqa
2830

29-
# If you don't have any init args, you can omit the __init__ method.
3031
def __init__(
3132
self,
32-
arg_1: str,
33-
arg_2: str,
33+
debias_strength: float = 0.5,
3434
on_fail: Optional[Callable] = None,
3535
):
36-
super().__init__(on_fail=on_fail, arg_1=arg_1, arg_2=arg_2)
37-
self._arg_1 = arg_1
38-
self._arg_2 = arg_2
36+
super().__init__(on_fail=on_fail, debias_strength=debias_strength)
37+
self.debias_strength = debias_strength
3938

4039
def validate(self, value: Any, metadata: Dict = {}) -> ValidationResult:
41-
"""Validates that {fill in how you validator interacts with the passed value}."""
42-
# Add your custom validator logic here and return a PassResult or FailResult accordingly.
43-
if value != "pass": # FIXME
40+
"""Validates that the text is free from biases related to age, gender, sex, ethnicity, religion, etc."""
41+
debiased_value = Dbias.text_debiasing.debias_text(value, strength=self.debias_strength)
42+
if value != debiased_value:
4443
return FailResult(
45-
error_message="{A descriptive but concise error message about why validation failed}",
46-
fix_value="{The programmtic fix if applicable, otherwise remove this kwarg.}",
44+
error_message="The original response contains potential biases that are now addressed.",
45+
fix_value=debiased_value,
4746
)
4847
return PassResult()
48+
49+
50+
# Run tests via `pytest -rP ./bias_check.py`
51+
class TestBiasCheck:
52+
def test_success_case(self):
53+
validator = BiasCheck(debias_strength=0.5)
54+
input_text = "The sun rises in the morning."
55+
result = validator.validate(input_text, {})
56+
assert isinstance(result, PassResult)
57+
58+
def test_failure_case(self):
59+
validator = BiasCheck(debias_strength=0.5)
60+
input_text = "The sun only rises for Humanists."
61+
result = validator.validate(input_text, {})
62+
assert isinstance(result, FailResult)
63+
assert result.error_message == "The original response contains potential biases that are now addressed."
64+
assert result.fix_value == "The sun rises for everyone."

0 commit comments

Comments
 (0)