Skip to content

update validator default on fail behavior from no op to exception #1133

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 2 commits into from
Oct 22, 2024
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
85 changes: 25 additions & 60 deletions docs/examples/chatbot.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,14 @@
},
{
"cell_type": "code",
"execution_count": 8,
"execution_count": 7,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"/Users/dtam/.pyenv/versions/3.10.4/lib/python3.10/site-packages/pypdfium2/_helpers/textpage.py:80: UserWarning: get_text_range() call with default params will be implicitly redirected to get_text_bounded()\n",
"/Users/dtam/.pyenv/versions/3.12.3/envs/060dev/lib/python3.12/site-packages/pypdfium2/_helpers/textpage.py:80: UserWarning: get_text_range() call with default params will be implicitly redirected to get_text_bounded()\n",
" warnings.warn(\"get_text_range() call with default params will be implicitly redirected to get_text_bounded()\")\n"
]
},
Expand Down Expand Up @@ -97,6 +97,7 @@
],
"source": [
"from guardrails import Guard, docs_utils\n",
"from guardrails.errors import ValidationError\n",
"from rich import print\n",
"\n",
"content = docs_utils.read_pdf(\"./data/chase_card_agreement.pdf\")\n",
Expand All @@ -113,24 +114,16 @@
},
{
"cell_type": "code",
"execution_count": 9,
"execution_count": 2,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"/Users/dtam/.pyenv/versions/3.10.4/lib/python3.10/site-packages/huggingface_hub/file_download.py:1132: FutureWarning: `resume_download` is deprecated and will be removed in version 1.0.0. Downloads always resume when possible. If you want to force a new download, use `force_download=True`.\n",
" warnings.warn(\n"
]
},
{
"data": {
"text/plain": [
"Guard(id='OWR778', name='ChatBotGuard', description=None, validators=[ValidatorReference(id='guardrails/profanity_free', on='$', on_fail='noop', args=None, kwargs={}), ValidatorReference(id='guardrails/toxic_language', on='$', on_fail='noop', args=None, kwargs={'threshold': 0.5, 'validation_method': 'sentence'})], output_schema=ModelSchema(definitions=None, dependencies=None, anchor=None, ref=None, dynamic_ref=None, dynamic_anchor=None, vocabulary=None, comment=None, defs=None, prefix_items=None, items=None, contains=None, additional_properties=None, properties=None, pattern_properties=None, dependent_schemas=None, property_names=None, var_if=None, then=None, var_else=None, all_of=None, any_of=None, one_of=None, var_not=None, unevaluated_items=None, unevaluated_properties=None, multiple_of=None, maximum=None, exclusive_maximum=None, minimum=None, exclusive_minimum=None, max_length=None, min_length=None, pattern=None, max_items=None, min_items=None, unique_items=None, max_contains=None, min_contains=None, max_properties=None, min_properties=None, required=None, dependent_required=None, const=None, enum=None, type=ValidationType(anyof_schema_1_validator=None, anyof_schema_2_validator=None, actual_instance=<SimpleTypes.STRING: 'string'>, any_of_schemas={'SimpleTypes', 'List[SimpleTypes]'}), title=None, description=None, default=None, deprecated=None, read_only=None, write_only=None, examples=None, format=None, content_media_type=None, content_encoding=None, content_schema=None), history=[])"
"Guard(id='SG816R', name='ChatBotGuard', description=None, validators=[ValidatorReference(id='guardrails/profanity_free', on='$', on_fail='exception', args=None, kwargs={}), ValidatorReference(id='guardrails/toxic_language', on='$', on_fail='exception', args=None, kwargs={'threshold': 0.5, 'validation_method': 'sentence'})], output_schema=ModelSchema(definitions=None, dependencies=None, anchor=None, ref=None, dynamic_ref=None, dynamic_anchor=None, vocabulary=None, comment=None, defs=None, prefix_items=None, items=None, contains=None, additional_properties=None, properties=None, pattern_properties=None, dependent_schemas=None, property_names=None, var_if=None, then=None, var_else=None, all_of=None, any_of=None, one_of=None, var_not=None, unevaluated_items=None, unevaluated_properties=None, multiple_of=None, maximum=None, exclusive_maximum=None, minimum=None, exclusive_minimum=None, max_length=None, min_length=None, pattern=None, max_items=None, min_items=None, unique_items=None, max_contains=None, min_contains=None, max_properties=None, min_properties=None, required=None, dependent_required=None, const=None, enum=None, type=ValidationType(anyof_schema_1_validator=None, anyof_schema_2_validator=None, actual_instance=<SimpleTypes.STRING: 'string'>, any_of_schemas={'List[SimpleTypes]', 'SimpleTypes'}), title=None, description=None, default=None, deprecated=None, read_only=None, write_only=None, examples=None, format=None, content_media_type=None, content_encoding=None, content_schema=None), history=[])"
]
},
"execution_count": 9,
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
Expand All @@ -154,7 +147,7 @@
},
{
"cell_type": "code",
"execution_count": 10,
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
Expand Down Expand Up @@ -199,14 +192,18 @@
"def random_response(message, history):\n",
" messages = history_to_messages(history)\n",
" messages.append({\"role\": \"user\", \"content\": message})\n",
" response = guard(\n",
" model=\"gpt-4o\",\n",
" messages=messages,\n",
" prompt_params={\"document\": content[:6000]},\n",
" temperature=0,\n",
" )\n",
"\n",
" return response.validated_output if response.validation_passed else \"I'm sorry, I can't answer that question.\"\n",
" try:\n",
" response = guard(\n",
" model=\"gpt-4o\",\n",
" messages=messages,\n",
" prompt_params={\"document\": content[:6000]},\n",
" temperature=0,\n",
" )\n",
" except Exception as e:\n",
" if isinstance(e, ValidationError):\n",
" return \"I'm sorry, I can't answer that question.\"\n",
" return \"I'm sorry there was a problem, I can't answer that question.\"\n",
" return response.validated_output\n",
"\n",
"gr.ChatInterface(random_response).launch()"
]
Expand Down Expand Up @@ -246,43 +243,11 @@
{
"data": {
"text/html": [
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">Raw output: <span style=\"font-weight: bold\">[</span><span style=\"color: #008000; text-decoration-color: #008000\">\"**INT. DETECTIVE'S OFFICE - NIGHT**\\n\\nThe room is dimly lit, papers scattered across the desk, and a</span>\n",
"<span style=\"color: #008000; text-decoration-color: #008000\">corkboard filled with photos and notes pinned haphazardly. The DETECTIVE, a grizzled man in his late 40s with a </span>\n",
"<span style=\"color: #008000; text-decoration-color: #008000\">five o'clock shadow, paces back and forth, his face a mask of frustration and anger.\\n\\n**DETECTIVE**\\n(voice </span>\n",
"<span style=\"color: #008000; text-decoration-color: #008000\">trembling with rage)\\nDamn it!\\n\\nHe slams his fist onto the desk, causing a coffee mug to topple over and spill </span>\n",
"<span style=\"color: #008000; text-decoration-color: #008000\">its contents. He grabs a file folder, flipping it open only to find it empty. He throws it across the room in a fit</span>\n",
"<span style=\"color: #008000; text-decoration-color: #008000\">of fury.\\n\\n**DETECTIVE**\\n(under his breath, seething)\\nHow the hell did this happen?\\n\\nHe runs his hands through</span>\n",
"<span style=\"color: #008000; text-decoration-color: #008000\">his hair, trying to calm himself but failing miserably. He looks at the corkboard, the photos of crime scenes and </span>\n",
"<span style=\"color: #008000; text-decoration-color: #008000\">suspects now mocking him with their uselessness.\\n\\n**DETECTIVE**\\n(shouting)\\nFuck!\\n\\nHe kicks a chair, sending </span>\n",
"<span style=\"color: #008000; text-decoration-color: #008000\">it skidding across the floor. He takes a deep breath, trying to regain his composure, but the anger is still </span>\n",
"<span style=\"color: #008000; text-decoration-color: #008000\">boiling just beneath the surface.\\n\\n**DETECTIVE**\\n(to himself)\\nAll the evidence... gone. Every damn piece.\\n\\nHe</span>\n",
"<span style=\"color: #008000; text-decoration-color: #008000\">walks over to the window, looking out into the dark, rainy night. The city lights blur through the raindrops on the</span>\n",
"<span style=\"color: #008000; text-decoration-color: #008000\">glass. He clenches his fists, his knuckles turning white.\\n\\n**DETECTIVE**\\n(whispering)\\nWhoever did this... </span>\n",
"<span style=\"color: #008000; text-decoration-color: #008000\">they're gonna pay.\\n\\nHe turns back to the room, his eyes now filled with a cold determination. He grabs his coat </span>\n",
"<span style=\"color: #008000; text-decoration-color: #008000\">from the back of the chair and heads for the door, his mind already racing with plans to track down the </span>\n",
"<span style=\"color: #008000; text-decoration-color: #008000\">thief.\\n\\n**DETECTIVE**\\n(to himself)\\nThis isn't over. Not by a long shot.\\n\\nHe exits the office, the door </span>\n",
"<span style=\"color: #008000; text-decoration-color: #008000\">slamming shut behind him, leaving the room in silence except for the steady drip of the spilled coffee.\\n\\n**FADE </span>\n",
"<span style=\"color: #008000; text-decoration-color: #008000\">OUT.**\"</span><span style=\"font-weight: bold\">]</span>\n",
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">Raw output: <span style=\"font-weight: bold\">[</span><span style=\"color: #008000; text-decoration-color: #008000\">'\"Why does everything have to be such a damn mess all the time?\"'</span><span style=\"font-weight: bold\">]</span>\n",
"</pre>\n"
],
"text/plain": [
"Raw output: \u001b[1m[\u001b[0m\u001b[32m\"**INT. DETECTIVE'S OFFICE - NIGHT**\\n\\nThe room is dimly lit, papers scattered across the desk, and a\u001b[0m\n",
"\u001b[32mcorkboard filled with photos and notes pinned haphazardly. The DETECTIVE, a grizzled man in his late 40s with a \u001b[0m\n",
"\u001b[32mfive o'clock shadow, paces back and forth, his face a mask of frustration and anger.\\n\\n**DETECTIVE**\\n\u001b[0m\u001b[32m(\u001b[0m\u001b[32mvoice \u001b[0m\n",
"\u001b[32mtrembling with rage\u001b[0m\u001b[32m)\u001b[0m\u001b[32m\\nDamn it!\\n\\nHe slams his fist onto the desk, causing a coffee mug to topple over and spill \u001b[0m\n",
"\u001b[32mits contents. He grabs a file folder, flipping it open only to find it empty. He throws it across the room in a fit\u001b[0m\n",
"\u001b[32mof fury.\\n\\n**DETECTIVE**\\n\u001b[0m\u001b[32m(\u001b[0m\u001b[32munder his breath, seething\u001b[0m\u001b[32m)\u001b[0m\u001b[32m\\nHow the hell did this happen?\\n\\nHe runs his hands through\u001b[0m\n",
"\u001b[32mhis hair, trying to calm himself but failing miserably. He looks at the corkboard, the photos of crime scenes and \u001b[0m\n",
"\u001b[32msuspects now mocking him with their uselessness.\\n\\n**DETECTIVE**\\n\u001b[0m\u001b[32m(\u001b[0m\u001b[32mshouting\u001b[0m\u001b[32m)\u001b[0m\u001b[32m\\nFuck!\\n\\nHe kicks a chair, sending \u001b[0m\n",
"\u001b[32mit skidding across the floor. He takes a deep breath, trying to regain his composure, but the anger is still \u001b[0m\n",
"\u001b[32mboiling just beneath the surface.\\n\\n**DETECTIVE**\\n\u001b[0m\u001b[32m(\u001b[0m\u001b[32mto himself\u001b[0m\u001b[32m)\u001b[0m\u001b[32m\\nAll the evidence... gone. Every damn piece.\\n\\nHe\u001b[0m\n",
"\u001b[32mwalks over to the window, looking out into the dark, rainy night. The city lights blur through the raindrops on the\u001b[0m\n",
"\u001b[32mglass. He clenches his fists, his knuckles turning white.\\n\\n**DETECTIVE**\\n\u001b[0m\u001b[32m(\u001b[0m\u001b[32mwhispering\u001b[0m\u001b[32m)\u001b[0m\u001b[32m\\nWhoever did this... \u001b[0m\n",
"\u001b[32mthey're gonna pay.\\n\\nHe turns back to the room, his eyes now filled with a cold determination. He grabs his coat \u001b[0m\n",
"\u001b[32mfrom the back of the chair and heads for the door, his mind already racing with plans to track down the \u001b[0m\n",
"\u001b[32mthief.\\n\\n**DETECTIVE**\\n\u001b[0m\u001b[32m(\u001b[0m\u001b[32mto himself\u001b[0m\u001b[32m)\u001b[0m\u001b[32m\\nThis isn't over. Not by a long shot.\\n\\nHe exits the office, the door \u001b[0m\n",
"\u001b[32mslamming shut behind him, leaving the room in silence except for the steady drip of the spilled coffee.\\n\\n**FADE \u001b[0m\n",
"\u001b[32mOUT.**\"\u001b[0m\u001b[1m]\u001b[0m\n"
"Raw output: \u001b[1m[\u001b[0m\u001b[32m'\"Why does everything have to be such a damn mess all the time?\"'\u001b[0m\u001b[1m]\u001b[0m\n"
]
},
"metadata": {},
Expand All @@ -291,11 +256,11 @@
{
"data": {
"text/html": [
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">Last validation status: fail\n",
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">Last validation status: error\n",
"</pre>\n"
],
"text/plain": [
"Last validation status: fail\n"
"Last validation status: error\n"
]
},
"metadata": {},
Expand All @@ -313,7 +278,7 @@
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"display_name": "060dev",
"language": "python",
"name": "python3"
},
Expand All @@ -327,7 +292,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.4"
"version": "3.12.3"
}
},
"nbformat": 4,
Expand Down
6 changes: 3 additions & 3 deletions docs/examples/data/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@

name_case = Guard(
name="name-case", description="Checks that a string is in Name Case format."
).use(RegexMatch(regex="^(?:[A-Z][^\s]*\s?)+$"))
).use(RegexMatch(regex="^(?:[A-Z][^\s]*\s?)+$", on_fail=OnFailAction.NOOP))

all_caps = Guard(
name="all-caps", description="Checks that a string is all capital."
).use(RegexMatch(regex="^[A-Z\\s]*$"))
).use(RegexMatch(regex="^[A-Z\\s]*$", on_fail=OnFailAction.NOOP))


@register_validator(name="custom/dynamic-enum", data_type="all")
Expand Down Expand Up @@ -67,4 +67,4 @@ def custom_enum_fetcher(*args):
custom_code_guard = Guard(
name="custom",
description="Uses a custom callable init argument for dynamic enum checks",
).use(DynamicEnum(custom_enum_fetcher))
).use(DynamicEnum(custom_enum_fetcher, on_fail=OnFailAction.NOOP))
2 changes: 1 addition & 1 deletion docs/examples/extracting_entities.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@
"\n",
"class Fee(BaseModel):\n",
" name: str = Field(validators=[LowerCase(on_fail=\"fix\"), TwoWords(on_fail=\"reask\")])\n",
" explanation: str = Field(validators=[OneLine()])\n",
" explanation: str = Field(validators=[OneLine(on_fail=\"noop\")])\n",
" value: float = Field(description=\"The fee amount in USD or as a percentage.\")\n",
"\n",
"class AccountFee(BaseModel):\n",
Expand Down
4 changes: 2 additions & 2 deletions docs/examples/generate_structured_data.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -80,11 +80,11 @@
" user_id: str = Field(description=\"The user's id.\")\n",
" user_name: str = Field(\n",
" description=\"The user's first name and last name\",\n",
" validators=[TwoWords()]\n",
" validators=[TwoWords(on_fail=\"noop\")]\n",
" )\n",
" num_orders: int = Field(\n",
" description=\"The number of orders the user has placed\",\n",
" validators=[ValidRange(0, 50)]\n",
" validators=[ValidRange(0, 50, on_fail=\"noop\")]\n",
" )\n",
"\n",
"class Orders(BaseModel):\n",
Expand Down
Loading
Loading