Skip to main content
In this example we will use Guardrails to summarize text in terms of length, quality and output read time. In this example, we will use Guardrails in the summarization of a text document. We will check whether the summarized document has a high semantic similarity with the original document. We will ensure the output meets a certain range of length and read time.

Setup

In order to check semantic similarity we will need the numpy package. We will also install the validators we intend to use.
guardrails hub install hub://guardrails/reading_time --quiet --install-local-models
guardrails hub install hub://guardrails/similar_to_document --quiet --install-local-models
guardrails hub install hub://guardrails/valid_length --quiet --install-local-models

Step 1: Load data and create Pydantic model

Load our text with the code below:
with open("data/twain.txt", "r") as file:
    document = file.read()
    file.seek(0)
    content = "".join(line.strip() for line in file.readlines())
Next we can define our return output with a pydantic model:
from pydantic import BaseModel, Field
from guardrails.hub import SimilarToDocument, ValidLength, ReadingTime

prompt = """Summarize the following text faithfully:

${document}

${gr.complete_xml_suffix}"""

THREE_MINUTES = 180/60

class TextSummary(BaseModel):
    summary: str = Field(
        description="Faithful summary of the text",
        validators=[
            ReadingTime(reading_time=THREE_MINUTES, on_fail="exception"),
            ValidLength(min=100, max=1000, on_fail="exception"),
            SimilarToDocument(document=f"'{content}'", threshold=0.60, on_fail="filter")
        ],
    )

Step 2: Create Guard from pydantic

The guard we create will:
  1. Enforce reading time
  2. Enforce length
  3. Enforce similarity
import guardrails as gd
from guardrails.errors import ValidationError

guard = gd.Guard.for_pydantic(TextSummary)

Step 3: Call LLM via guard()

We use the tools API to ensure our data is returned in a structured form.
import os

# TODO: Replace OPENAI_API_KEY with your OpenAI API key, uncomment
# os.environ["OPENAI_API_KEY"] = "OPENAI_API_KEY"

response = guard(
    messages=[{"role": "user", "content": prompt}],
    prompt_params={"document": document},
    model="gpt-4o",
    tools=guard.json_function_calling_tool(),
    tool_choice="required",
)

print(f"Validated Output: {response.validated_output}")
Output:
Similarity: 0.818
Validated Output: {'summary': "Mark Twain discusses the art of storytelling, focusing on the humorous story, which he considers an American development. He contrasts it with the comic story, which is English, and the witty story, which is French. The humorous story relies on the manner of telling, allowing for length and meandering, while comic and witty stories depend on content and must be brief with a clear point. Twain emphasizes that telling a humorous story is a high art, requiring skill, unlike the comic and witty stories that anyone can tell. The humorous story is delivered gravely, with the teller pretending not to know it's funny, whereas the comic story is told with enthusiasm and obviousness. Twain notes that the humorous story often ends with a subtle point, requiring the audience's attention, a technique used by storytellers like Artemus Ward and others. In contrast, the comic story's punchline is emphasized and often exaggerated in print, which Twain finds disheartening."}
We can see the step-wise history of the Guard object below:
guard.history.last.tree

Benefits

Using Guardrails for summarization provides:
  1. Quality control - Ensures summaries maintain semantic similarity to source
  2. Length constraints - Enforces minimum and maximum length requirements
  3. Readability - Controls reading time for target audience
  4. Consistency - Produces reliable, validated summaries
  5. Debugging - Easy to trace validation failures

Customizing validators

You can adjust the validators to meet your needs:
class TextSummary(BaseModel):
    summary: str = Field(
        description="Faithful summary of the text",
        validators=[
            ReadingTime(reading_time=5.0, on_fail="reask"),  # 5 minutes
            ValidLength(min=200, max=500, on_fail="reask"),  # Different length
            SimilarToDocument(document=f"'{content}'", threshold=0.75, on_fail="exception")  # Higher threshold
        ],
    )

Use cases

This pattern is useful for:
  1. Document summarization - Condense long documents
  2. News aggregation - Create brief summaries of articles
  3. Meeting notes - Summarize meeting transcripts
  4. Research papers - Generate abstracts
  5. Customer feedback - Summarize reviews and feedback