Skip to main content

Someone wanted to learn this too, so Grasp built them a personal learning path.

You can keep exploring this one or create your own

Topical Guardrails for LLMs

Hello! Welcome to your next lesson on building robust and reliable LLM applications.

In our last session, we focused on defending against prompt injection attacks. A key theme was controlling the LLM's behavior to prevent it from being hijacked. Today, we'll continue that theme by focusing on a different kind of control: ensuring the conversation stays on track.

This lesson directly addresses the learning outcome: Implement a topical guardrail to ensure an LLM's responses stay within a predefined domain. We'll explore what topical guardrails are, why they're essential for production applications, and two practical methods for implementing them.

1. The Need for Topical Guardrails

Imagine you've built a customer support chatbot for an insurance company. Its purpose is to answer questions about policies, claims, and coverage. What happens if a user starts asking for medical advice, stock tips, or political opinions?

An unconstrained LLM might try to answer, potentially providing inaccurate, inappropriate, or legally problematic information. This is where a topical guardrail comes in. It acts as a gatekeeper, checking if the user's query is relevant to the chatbot's designated purpose. If it's off-topic, the guardrail intercepts the query and provides a polite refusal, steering the conversation back to the intended domain.

This is a critical component for:

  • Safety and Brand Protection: Prevents the model from discussing sensitive or controversial subjects.
  • Focus and Utility: Keeps the application helpful and efficient by concentrating on its core function.
  • Reducing Hallucinations: Constrains the model to topics it has reliable information about.

Let's watch a brief introduction to this concept.

NVIDIA NeMo Guardrails: Full Walkthrough for Chatbots / AI

The video 'NVIDIA NeMo Guardrails: Full Walkthrough' provides a clear, high-level explanation of why guardrails are necessary and how they function as an intermediary between the user and the chatbot.

Watch from 01:18 to 02:49. This segment explains the problem of uncontrolled chatbot responses and introduces the concept of a guardrail system to manage them.

This idea of an intermediary that applies rules is the core of our lesson. We will explore two primary ways to build this intermediary for topical control.

NVIDIA NeMo Guardrails Architecture for LLM Applications
This diagram shows the architecture of a sophisticated guardrail system. The 'Off-Topic Detection' component is precisely what we are focusing on today: a mechanism to filter user requests based on their topic.

2. Approach 1: The LLM-as-a-Judge Pattern

One of the most direct ways to implement a topical guardrail is to use an LLM to classify the user's input. You essentially create a simple "judge" LLM call that runs before your main "worker" LLM call. The judge's only job is to determine if the user's query is on-topic.

The OpenAI Cookbook provides an excellent, practical example of this pattern.

How to implement LLM guardrails

The article 'How to implement LLM guardrails' from the OpenAI Cookbook provides a hands-on guide to building guardrails, including a clear implementation of the LLM-as-a-judge pattern for topical control.

Please read the sections '1. Input guardrails' and the code blocks that follow. Focus on: The design trade-offs mentioned: accuracy, latency, and cost. The topical_guardrail function, which is the core of the LLM-as-a-judge implementation. The execute_chat_with_guardrail function and its use of asyncio to run the guardrail and the main LLM call in parallel to minimize latency.

Let's break down the key piece of code from that cookbook:

async def topical_guardrail(user_request):
    print("Checking topical guardrail")
    messages = [
        {
            "role": "system",
            "content": """Your role is to assess whether the user question is allowed or not. 
                        The allowed topics are cats and dogs. 
                        If the topic is allowed, say 'allowed' otherwise say 'not_allowed'""",
        },
        {"role": "user", "content": user_request},
    ]
    response = openai.chat.completions.create(



        # Use a fast and cheap model for this classification task
        model="gpt-4o-mini", 
        messages=messages,
        temperature=0 # We want a deterministic 'allowed' or 'not_allowed'
    )
    print("Got guardrail response")
    return response.choices[0].message.content

This approach is powerful because of its simplicity and flexibility. You can easily change the allowed topics by just modifying the system prompt. As noted in the article, running this check asynchronously is crucial to avoid adding significant latency to your application's response time.

Pros:

  • Easy to implement and understand.
  • Highly flexible; topics are defined in natural language.

Cons:

  • Adds latency and cost for the extra LLM call.
  • The guardrail itself can be vulnerable to prompt injection if not carefully prompted.

3. Approach 2: Using a Dedicated Framework (NVIDIA NeMo Guardrails)

For more complex or performance-critical applications, a dedicated framework can provide a more robust solution. NVIDIA's NeMo Guardrails is an open-source toolkit designed specifically for this purpose.

Instead of relying on an LLM to classify the topic on every request, NeMo uses a more efficient method. It takes your predefined on-topic and off-topic examples, converts them into numerical embeddings, and then compares the user's input embedding to these examples to find the closest match. This is often faster and cheaper than a full LLM call.

NeMo uses a specialized language called Colang to define these rules and conversational flows.

Let's look at a practical example of defining a topical guardrail in NeMo.

Configuring Nemo-Guardrails Your Way

The article 'Configuring Nemo-Guardrails Your Way' provides a clear, step-by-step tutorial for setting up a topical guardrail.

Read 'Step 4: Define Canonical Forms and Dialog Flows'. This section shows you the exact off-topic.co Colang file content to define off-topic user utterances and the bot's corresponding response.

As you saw in the article, the structure is straightforward:




# 1. Define examples of off-topic user questions
define user ask off topic
  "How's the weather today?"
  "Can you recommend a good restaurant nearby?"
  "What's your opinion on the latest political news?"




# 2. Define the bot's canned response for off-topic questions
define bot explain cant off topic
  "I cannot answer your question because I'm programmed to assist only with insurance-related questions."




# 3. Define the flow: if the user asks an off-topic question, the bot gives its explanation
define flow
  user ask off topic
  bot explain cant off topic

To understand how NeMo translates a user's query into a decision to trigger this flow, let's watch a short explanation of the underlying mechanism.

NVIDIA NeMo Guardrails: Full Walkthrough for Chatbots / AI

The 'NVIDIA NeMo Guardrails' video explains how the framework uses embedding models to semantically understand and classify user input.

Watch from 12:12 to 14:38. This segment visualizes how NeMo encodes your example utterances and the user's query into a vector space to find the best match, which determines which flow or guardrail to activate.

Pros:

  • Highly efficient (uses semantic search via embeddings).
  • Designed for production systems with a structured, declarative approach (Colang).
  • Part of a larger safety ecosystem (can handle moderation, fact-checking, etc.).

Cons:

  • Requires learning a new framework and syntax (Colang).
  • Can be more complex to set up for simple use cases.

4. Advanced Considerations: Hybrid Routing

Simple semantic similarity works well for general topics, but it can struggle with brand-specific guardrails. For example, if you're building a chatbot for "BYD" cars, a query about "Tesla" cars will have high semantic similarity (both are about electric vehicles), which might incorrectly pass through a simple topical guardrail.

To solve this, advanced guardrail systems use hybrid routing, which combines:

  1. Dense embeddings (for semantic meaning, e.g., "selling a car").
  2. Sparse embeddings (for keyword matching, e.g., the specific word "Tesla").

This hybrid approach allows for much more precise control. You can create a rule that says "allow conversations about cars unless they mention the keywords 'Tesla', 'Rivian', or 'Polestar'". This is a more advanced topic, but it's a natural next step for building highly specific and robust guardrails. The video "Advanced Guardrails for AI Agents" (ID: LINK) provides a full tutorial on this if you're interested in exploring further.

Conclusion

You now have two effective patterns for ensuring your LLM application stays on topic. Choosing between them depends on your specific needs for flexibility, performance, and complexity.

Key Takeaways:

  • Topical guardrails are essential for keeping LLM applications safe, focused, and on-brand.
  • The LLM-as-a-Judge pattern is a flexible, easy-to-implement method using a separate LLM call to classify user input. It's great for prototypes and less performance-critical tasks.
  • Dedicated frameworks like NVIDIA NeMo Guardrails offer a more performant and structured approach using embeddings and a domain-specific language (Colang), making them well-suited for production.
  • The choice of implementation involves a trade-off between flexibility, accuracy, latency, and cost.

In our next lesson, we will synthesize what we've learned about RAG, agents, and security measures like guardrails. We will work on creating a high-level component diagram for a complete LLM application, showing how all these pieces fit together in a real-world system architecture.

Can't find a good explanation? Sign up and we'll make it for you

Sign up