Skip to content
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
2 changes: 1 addition & 1 deletion .github/workflows/scripts/run_notebooks.sh
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ cd docs/examples
notebook="$1"

# Check if the notebook should be processed
invalid_notebooks=("valid_chess_moves.ipynb" "llamaindex-output-parsing.ipynb" "competitors_check.ipynb")
invalid_notebooks=("llamaindex-output-parsing.ipynb" "competitors_check.ipynb" "guardrails_server.ipynb")
if [[ ! " ${invalid_notebooks[@]} " =~ " ${notebook} " ]]; then
echo "Processing $notebook..."
# poetry run jupyter nbconvert --to notebook --execute "$notebook"
Expand Down
22 changes: 22 additions & 0 deletions docs/api_reference/async_guard.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<!-- ::: my_library.my_module.my_class -->


::: guardrails.guard.AsyncGuard
options:
members:
- "__init__"
- "from_rail"
- "from_rail_string"
- "from_pydantic"
- "from_string"
- "configure"
- "use"
- "use_many"
- "__call__"
- "parse"
- "validate"
- "error_spans_in_output"
- "add_json_function_calling_tool"
- "to_dict"
- "from_dict"
- "to_runnable"
7 changes: 7 additions & 0 deletions docs/api_reference/errors.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<!-- ::: my_library.my_module.my_class -->


::: guardrails.errors
options:
members:
- "ValidationError"
8 changes: 5 additions & 3 deletions docs/api_reference/guard.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,14 @@
- "from_rail_string"
- "from_pydantic"
- "from_string"
- "configure"
- "use"
- "use_many"
- "to_runnable"
- "configure"
- "__call__"
- "parse"
- "validate"
- "history"
- "error_spans_in_output"
- "add_json_function_calling_tool"
- "to_dict"
- "from_dict"
- "to_runnable"
1 change: 1 addition & 0 deletions docs/api_reference/types.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
::: guardrails.types
18 changes: 0 additions & 18 deletions docs/api_reference/validators.md

This file was deleted.

93 changes: 93 additions & 0 deletions docs/examples/constrained_decoding.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m A new release of pip is available: \u001b[0m\u001b[31;49m24.0\u001b[0m\u001b[39;49m -> \u001b[0m\u001b[32;49m24.1\u001b[0m\n",
"\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m To update, run: \u001b[0m\u001b[32;49mpip install --upgrade pip\u001b[0m\n",
"\n",
"\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m A new release of pip is available: \u001b[0m\u001b[31;49m24.0\u001b[0m\u001b[39;49m -> \u001b[0m\u001b[32;49m24.1\u001b[0m\n",
"\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m To update, run: \u001b[0m\u001b[32;49mpip install --upgrade pip\u001b[0m\n"
]
}
],
"source": [
"! pip install ipywidgets -q"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "81b91198c45249a2b0a7075d13ebf838",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"model.safetensors: 0%| | 10.5M/2.20G [00:00<?, ?B/s]"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"from guardrails import Guard\n",
"from pydantic import BaseModel\n",
"\n",
"class Dog(BaseModel):\n",
" name: str\n",
" color: str\n",
" weight_kg: float\n",
"\n",
"class NewFriends(BaseModel):\n",
" dogs: list[Dog]\n",
"\n",
"guard = Guard.from_pydantic(NewFriends, output_formatter=\"jsonformer\")\n",
"\n",
"# JSONFormer is only compatible with HF Pipelines and HF Models:\n",
"from transformers import pipeline\n",
"tiny_llama_pipeline = pipeline(\"text-generation\", \"TinyLlama/TinyLlama-1.1B-Chat-v1.0\")\n",
"\n",
"# Inference is straightforward:\n",
"response = guard(tiny_llama_pipeline, prompt=\"Please enjoy this list of good dogs:\")\n",
"\n",
"# `out` is a dict. Format it as JSON for readability:\n",
"import json\n",
"print(json.dumps(response.validated_output, indent=2))"
]
}
],
"metadata": {
"kernelspec": {
"display_name": ".venv",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.12.3"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
70 changes: 70 additions & 0 deletions docs/examples/data/config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
"""
All guards defined here will be initialized, if and only if
the application is using in memory guards.

The application will use in memory guards if pg_host is left
undefined. Otherwise, a postgres instance will be started
and guards will be persisted into postgres. In that case,
these guards will not be initialized.
"""

from typing import Any, Callable, Dict, Optional, Union
from guardrails import Guard, OnFailAction
from guardrails.validators import (
Validator,
register_validator,
FailResult,
PassResult,
ValidationResult,
)
from guardrails.hub import RegexMatch

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

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


@register_validator(name="custom/dynamic-enum", data_type="all")
class DynamicEnum(Validator):
def __init__(
self,
enum_fetcher: Callable,
on_fail: Optional[Union[Callable, OnFailAction]] = None,
):
super().__init__(on_fail=on_fail, enum_fetcher=enum_fetcher)
self.enum_fetcher = enum_fetcher

def validate(self, value: Any, metdata: Optional[Dict] = {}) -> ValidationResult:
enum_fetcher_args = metdata.get("enum_fetcher_args", [])
dynamic_enum = self.enum_fetcher(*enum_fetcher_args)

if value not in dynamic_enum:
return FailResult(
error_message="Value must be in the dynamically chosen enum!",
fix_value=dynamic_enum[0],
)
return PassResult()


valid_topics = ["music", "cooking", "camping", "outdoors"]
invalid_topics = ["sports", "work", "ai"]
all_topics = [*valid_topics, *invalid_topics]
Comment on lines +53 to +55
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well-deserved vacation hehe



def custom_enum_fetcher(*args):
topic_type = args[0]
if topic_type == "valid":
return valid_topics
elif topic_type == "invalid":
return invalid_topics
return all_topics


custom_code_guard = Guard(
name="custom",
description="Uses a custom callable init argument for dynamic enum checks",
).use(DynamicEnum(custom_enum_fetcher))
125 changes: 125 additions & 0 deletions docs/examples/guard_use.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Installing hub:\u001b[35m/\u001b[0m\u001b[35m/guardrails/\u001b[0m\u001b[95mregex_match...\u001b[0m\n",
"✅Successfully installed guardrails/regex_match!\n",
"\n",
"\n",
"Installing hub:\u001b[35m/\u001b[0m\u001b[35m/guardrails/\u001b[0m\u001b[95mvalid_range...\u001b[0m\n",
"✅Successfully installed guardrails/valid_range!\n",
"\n",
"\n"
]
}
],
"source": [
"! guardrails hub install hub://guardrails/regex_match --quiet\n",
"! guardrails hub install hub://guardrails/valid_range --quiet"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
"from pydantic import BaseModel, Field\n",
"from guardrails import Guard, OnFailAction\n",
"from guardrails.hub import RegexMatch, ValidRange\n",
"\n",
"class Person(BaseModel):\n",
" name: str\n",
" # Existing way of assigning validators\n",
" age: int = Field(validators=[ValidRange(0, 100, on_fail=OnFailAction.EXCEPTION)])\n",
" is_employed: bool"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Validation failed for field with errors: Value 101 is greater than 100.\n"
]
}
],
"source": [
"import json\n",
"from guardrails.errors import ValidationError\n",
"\n",
"\n",
"guard = Guard.from_pydantic(Person)\n",
"\n",
"try:\n",
" guard.validate(json.dumps({\n",
" \"name\": \"john doe\",\n",
" \"age\": 101,\n",
" \"is_employed\": False\n",
" }))\n",
"except ValidationError as e:\n",
" print(e)"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Validation failed for field with errors: Result must match ^(?:[A-Z][^\\s]*\\s?)+$\n"
]
}
],
"source": [
"# Now let's add a new validator to the name field\n",
"\n",
"guard.use(RegexMatch(\"^(?:[A-Z][^\\\\s]*\\\\s?)+$\", on_fail=OnFailAction.EXCEPTION), on=\"$.name\")\n",
"\n",
"try:\n",
" guard.validate(json.dumps({\n",
" \"name\": \"john doe\",\n",
" \"age\": 30,\n",
" \"is_employed\": True\n",
" }))\n",
"except ValidationError as e:\n",
" print(e)"
]
}
],
"metadata": {
"kernelspec": {
"display_name": ".venv",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.12.3"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
Loading