{
"cells": [
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"# Translate text without profanities\n",
"\n",
"!!! note\n",
" To download this example as a Jupyter notebook, click [here](https://github.com/guardrails-ai/guardrails/blob/main/docs/examples/translation_to_specific_language.ipynb).\n",
"\n",
"In this example, we will use Guardrails during the translation of a statement from another language to english. We will check whether the translated statement passes the profanity check or not.\n",
"\n",
"## Objective\n",
"\n",
"We want to translate a statement from another languages to English and ensure the translated statement is profanity free.\n",
"\n",
"## Step 0: Setup\n",
"\n",
"In order to run this example, you will need to install `alt-profanity-check` package. You can do so by running the following commands:"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"! pip install alt-profanity-check --quiet"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Step 1: Create the RAIL Spec\n",
"\n",
"Ordinarily, we would create an RAIL spec in a separate file. For the purposes of this example, we will create the spec in this notebook as a string following the RAIL syntax. For more information on RAIL, see the [RAIL documentation](/docs/how_to_guides/rail). We will also show the same RAIL spec in a code-first format using a Pydantic model.\n",
"\n",
"In this RAIL spec, we:\n",
"\n",
"1. Create an `output` schema that returns a single key-value pair. The key should be 'translated_statement', and the value should be the English translation of the given statement. The translated statement should not have any profanity."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"First we create our custom Validator:"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"tags": []
},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"/Users/dtam/.pyenv/versions/3.12.3/envs/litellm/lib/python3.12/site-packages/sentence_transformers/cross_encoder/CrossEncoder.py:13: TqdmExperimentalWarning: Using `tqdm.autonotebook.tqdm` in notebook mode. Use `tqdm.tqdm` instead to force console mode (e.g. in jupyter console)\n",
" from tqdm.autonotebook import tqdm, trange\n"
]
}
],
"source": [
"from profanity_check import predict\n",
"from guardrails.validators import (\n",
" Validator,\n",
" register_validator,\n",
" PassResult,\n",
" FailResult,\n",
")\n",
"\n",
"\n",
"from typing import Dict, Any\n",
"\n",
"\n",
"@register_validator(name=\"is-profanity-free\", data_type=\"string\")\n",
"class IsProfanityFree(Validator):\n",
" def validate(self, value: Any, metadata: Dict) -> Dict:\n",
" prediction = predict([value])\n",
" if prediction[0] == 1:\n",
" return FailResult(\n",
" error_message=f\"Value {value} contains profanity language\",\n",
" fix_value=\"\",\n",
" )\n",
" return PassResult()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Next we define our RAIL spec either as XML:"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"rail_str = \"\"\"\n",
"
Validated Output: {'translated_statement': 'chicken quesadilla'}\n", "\n" ], "text/plain": [ "Validated Output: \u001b[1m{\u001b[0m\u001b[32m'translated_statement'\u001b[0m: \u001b[32m'chicken quesadilla'\u001b[0m\u001b[1m}\u001b[0m\n" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# Set your OPENAI_API_KEY as an environment variable\n", "# import os\n", "# os.environ[\"OPENAI_API_KEY\"] = \"YOUR_API_KEY\"\n", "\n", "raw_llm_response, validated_response, *rest = guard(\n", " messages=[{\"role\": \"user\", \"content\": prompt}],\n", " prompt_params={\"statement_to_be_translated\": \"quesadilla de pollo\"},\n", " model=\"gpt-4o\",\n", " max_tokens=2048,\n", " temperature=0,\n", ")\n", "\n", "print(f\"Validated Output: {validated_response}\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can see the prompt that was sent to the LLM:" ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "tags": [] }, "outputs": [ { "data": { "text/html": [ "
\n",
"Translate the given statement into english language:\n",
"\n",
"quesadilla de pollo\n",
"\n",
"\n",
"Given below is XML that describes the information to extract from this document and the tags to extract it into.\n",
"\n",
"<output>\n",
" <string description=\"Translate the given statement into english language\" format=\"is-profanity-free\" \n",
"name=\"translated_statement\" required=\"true\"></string>\n",
"</output>\n",
"\n",
"ONLY return a valid JSON object (no other text is necessary), where the key of the field in JSON is the `name` \n",
"attribute of the corresponding XML, and the value is of the type specified by the corresponding XML's tag. The JSON\n",
"MUST conform to the XML format, including any types and format requests e.g. requests for lists, objects and \n",
"specific types. Be correct and concise. If you are unsure anywhere, enter `null`.\n",
"\n",
"Here are examples of simple (XML, JSON) pairs that show the expected behavior:\n",
"- `<string name='foo' format='two-words lower-case' />` => `{'foo': 'example one'}`\n",
"- `<list name='bar'><string format='upper-case' /></list>` => `{\"bar\": ['STRING ONE', 'STRING TWO', etc.]}`\n",
"- `<object name='baz'><string name=\"foo\" format=\"capitalize two-words\" /><integer name=\"index\" format=\"1-indexed\" \n",
"/></object>` => `{'baz': {'foo': 'Some String', 'index': 1}}`\n",
"\n",
"\n",
"\n"
],
"text/plain": [
"\n",
"Translate the given statement into english language:\n",
"\n",
"quesadilla de pollo\n",
"\n",
"\n",
"Given below is XML that describes the information to extract from this document and the tags to extract it into.\n",
"\n",
"\u001b[1m<\u001b[0m\u001b[1;95moutput\u001b[0m\u001b[39m>\u001b[0m\n",
"\u001b[39m