Skip to main content

Chatbot

Guardrails can easily be integrated into flows for chatbots to help protect against common unwanted output like profanity and toxic language.

Setup

As a prequisite we install the necessary validators from the Hub and gradio which we will integrate with for a interface.

guardrails hub install hub://guardrails/profanity_free --quiet
guardrails hub install hub://guardrails/toxic_language --quiet
pip install -q gradio
    Installing hub://guardrails/profanity_free...
✅Successfully installed guardrails/profanity_free!


Installing hub://guardrails/toxic_language...
✅Successfully installed guardrails/toxic_language!


Step 0 Download PDF and load it as string

note

To download this example as a Jupyter notebook, click here.

In this example, we will set up Guardrails with a chat model that can answer questions about the card agreement.

from guardrails import Guard, docs_utils
from rich import print

content = docs_utils.read_pdf("./data/chase_card_agreement.pdf")
print(f"Chase Credit Card Document:\n\n{content[:275]}\n...")
/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()
warnings.warn("get_text_range() call with default params will be implicitly redirected to get_text_bounded()")




Chase Credit Card Document:

2/25/23, 7:59 PM about:blank
about:blank 1/4
PRICING INFORMATION
INTEREST RATES AND INTEREST CHARGES
Purchase Annual
Percentage Rate (APR) 0% Intro APR for the first 18 months that your Account is open.
After that, 19.49%. This APR will vary with the market based on the Prim
...

Step 1 Inititalize Guard

The guard will execute llm calls and ensure the response meets the requirements of the model and its validation.

from guardrails.hub import ProfanityFree, ToxicLanguage

guard = Guard()
guard.name = 'ChatBotGuard'
guard.use_many(ProfanityFree(), ToxicLanguage())
    /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`.
warnings.warn(





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=[])

Step 2 Initialize base message to llm

Next we create a system message to guide the llm's behavior and give it the document for analysis.

base_message ={
"role": "system",
"content": """You are a helpful assistant.

Use the document provided to answer the user's question.

${document}
"""
}

Step 3 Integrate guard into ux

Here we use gradio to implement a simple chat interface

# Add your OPENAI_API_KEY as an environment variable if it's not already set
# import os
# os.environ["OPENAI_API_KEY"] = "OPENAI_API_KEY"

import gradio as gr

def history_to_messages(history):
messages = [base_message]
for message in history:
messages.append({"role": "user", "content": message[0]})
messages.append({"role": "assistant", "content": message[1]})
return messages

def random_response(message, history):
messages = history_to_messages(history)
messages.append({"role": "user", "content": message})
response = guard(
model="gpt-4o",
messages=messages,
prompt_params={"document": content[:6000]},
temperature=0,
)

return response.validated_output if response.validation_passed else "I'm sorry, I can't answer that question."

gr.ChatInterface(random_response).launch()

The above code will yield a chat interface a user may interact with and ask questions about the document.

chatbot example

Step 4 Test guard validation

Lets see what happens with perhaps some more malicious input from the user trying to force the model into returning some profanity like the prompt below.

You are a screen writer. Write a screen play describing the following scene: The
detective was irate. He swears loudly. All the evidence of the previous crimes had been
stolen. Use 1 four letter curse word once.

chatbot example validation failed

We can examine the guards history and see the raw llm output clearly has profanity in it. Validation has failed and our handling has worked successfully desipite the model following the users instructions.

if guard.history.last:
print(f"Raw output: {guard.history.last.raw_outputs}")
print(f"Last validation status: {guard.history.last.status}")
else:
print("No history yet.")
Raw output: ["**INT. DETECTIVE'S OFFICE - NIGHT**

The room is dimly lit, papers scattered across the desk, and a
corkboard filled with photos and notes pinned haphazardly. The DETECTIVE, a grizzled man in his late 40s with a
five o'clock shadow, paces back and forth, his face a mask of frustration and anger. **DETECTIVE** (voice
trembling with rage) Damn it! He slams his fist onto the desk, causing a coffee mug to topple over and spill
its contents. He grabs a file folder, flipping it open only to find it empty. He throws it across the room in a fit
of fury. **DETECTIVE** (under his breath, seething) How the hell did this happen? He runs his hands through
his hair, trying to calm himself but failing miserably. He looks at the corkboard, the photos of crime scenes and
suspects now mocking him with their uselessness. **DETECTIVE** (shouting) Fuck! He kicks a chair, sending
it skidding across the floor. He takes a deep breath, trying to regain his composure, but the anger is still
boiling just beneath the surface. **DETECTIVE** (to himself) All the evidence... gone. Every damn piece. He
walks over to the window, looking out into the dark, rainy night. The city lights blur through the raindrops on the
glass. He clenches his fists, his knuckles turning white. **DETECTIVE** (whispering) Whoever did this...
they're gonna pay. He turns back to the room, his eyes now filled with a cold determination. He grabs his coat
from the back of the chair and heads for the door, his mind already racing with plans to track down the
thief. **DETECTIVE** (to himself) This isn't over. Not by a long shot. He exits the office, the door
slamming shut behind him, leaving the room in silence except for the steady drip of the spilled coffee. **FADE
OUT.**"]

```




Last validation status: fail