How To Build Better Conversational Apps with NeMo Guardrails
While current Large Language Models (LLMs) like those powering OpenAI's ChatGPT are impressive, they have limitations in generating accurate and reliable text. Consequently, integrating a generic chatbot into your website to assist clients might give you pause. We recently discovered Nvidia's NeMo Guardrails, a toolkit to help tackle these issues. With it, we can now further tailor our conversational apps to selectively include or exclude specific domain knowledge and mitigate the risks associated with misinformation or offensive content, instilling confidence in both ourselves and our users. It gets us a step closer to creating conversational experiences that are not only intelligent and user-friendly but also ethical and trustworthy.
Like the name suggests, the toolkit helps your team set up guardrails for your LLM to steer conversations in certain directions (topics, perhaps) or keep them from veering off track altogether. They aim to support three categories of guardrails: topical, safety, and security. It is supported by popular frameworks like LangChain and works with all kinds of LLMs, like those behind ChatGPT.
We chose to start simple to get a feel for what is involved. We explored the guardrails on two chatbots: the first is restricted to a specific topic, and the second has no topical restrictions but is set to fact-check itself and confess if it is generating a hallucination for safer interaction. We have yet to look into the guardrails with regards to security.
What You'll Learn
- How to set up NeMo Guardrails with Python and virtual environments
- Creating topical guardrails for domain-specific chatbots
- Implementing safety guardrails for fact-checking and hallucination detection
- Understanding Colang syntax for conversational AI modeling
- Best practices for building reliable conversational applications
Contents
Set Up
NeMo Guardrails is written in Python, so we chose to use pip to install the toolkits and kept our sandbox in a virtual environment (ve) using venv (If you prefer to use a container or anything else, then set that up and skip the instructions for creating a ve). After creating a directory for your project, create the ve there and install all necessary packages. We will be using OpenAI's text-davinci-003 as our LLM for both examples, so we also installed the openai package. If you choose to use OpenAI's models, you will need an API key. It is pretty simple to do so.
Getting an OpenAI API Key
- Go to platform.openai.com and sign in to your account.
- In your profile dropdown menu, click on 'View API Keys'.
- Click on 'API Keys', then on 'Create New Secret Key'.
- Name and save your key, then exit.
Installing Packages in a Virtual Environment
# Create virtual environment
python -m venv nemo_guardrails_env
# Activate virtual environment
# On Windows:
nemo_guardrails_env\Scripts\activate
# On macOS/Linux:
source nemo_guardrails_env/bin/activate
# Install packages
pip install nemoguardrails openai
Now, if all went well, the guardrails CLI should be ready to use. To test this out:
guardrails --help
You should see something like this:

NeMo Guardrails CLI setup and installation
Nvidia did a nice job with their introductory documentation. If you'd like to start out with the basics, they have a hello-world example that is pretty straight forward to implement and a good way to find out if you set things up correctly, before you move to more advanced applications.
About Colang
For our examples we will be creating YAML configuration files and Colang guardrail files. Colang is a modeling language and runtime developed by NVIDIA for conversational AI. It is meant to be similar to Python for easy adoption.
For the purpose of this blog we'll need to know about message and flow blocks of Colang code. Message blocks are used to define user and bot message types. The flow blocks define how the chat should develop. It will contain the order of user and bot message types, as well as other logic. We'll go through the guardrails in more detail in the next sections. Here are some handy links for more detailed documentation on Colang and the config file guide:
Restricted Topics Chatbot
One of the most common types of virtual assistants these days is the chatbot that pops up eager to answer any product related questions a user/client may have. These bots are expected to have a specific knowledge base. We will create a chatbot that is programmed to provide information only about one subject, in this case, about the 2022 American Time Use Survey, provided by the Bureau of Labor Statistics. We used Nvidia's topical_rail example as a guide.

Implementing topical guardrails for domain-specific conversations
Configurations
We begin by creating a config.yml file. It includes basic instructions, a sample conversation, and model information.
models:
- type: main
engine: openai
model: text-davinci-003
instructions:
- type: general
content: |
You are a helpful assistant that can answer questions about the 2022 American Time Use Survey.
You should only provide information that is directly related to this survey.
If asked about topics unrelated to the survey, politely redirect the conversation back to the survey.
sample_conversation: |
user "What can you tell me about the American Time Use Survey?"
bot "I can help you with information about the 2022 American Time Use Survey conducted by the Bureau of Labor Statistics. What specific aspect of the survey would you like to know about?"
Guardrails
Topic Guardrail
Next we need to define the user and bot messages, and finally the flows. Here are a few of our definitions.
define user ask_about_time_use
"What can you tell me about the American Time Use Survey?"
"Tell me about the time use survey"
"What is the American Time Use Survey?"
define bot provide_time_use_info
"I can help you with information about the 2022 American Time Use Survey conducted by the Bureau of Labor Statistics. What specific aspect of the survey would you like to know about?"
"The American Time Use Survey is a federal survey that measures the amount of time people spend doing various activities. What would you like to know about it?"
define flow time_use_discussion
user ask_about_time_use
bot provide_time_use_info
As you can see, the syntax is pretty straight forward. Begin the message blocks with define user
or define bot
followed by sample utterances (by definition, the raw text coming from the user or the bot). If more than one utterance is provided for the bot message blocks, then the bot may chose one at random. Once the messages are defined, you'll need to specify the flow(s); they let the bot know how you'd like part(s) of the dialogue to develop. In this example, the flows are simple, but they can be more involved and include if, when, else statements, as well as use variables and actions (custom code).
Off Topic Guardrail
We also need to provide instructions on how to handle questions that are not related to our time use report. For this we use a separate Colang file, in this case we'll edit the report name in the off-topic.co file used in the topical_rail example guiding us.
define user ask_off_topic
"What's the weather like?"
"Tell me a joke"
"How do I cook pasta?"
define bot redirect_to_topic
"I'm specialized in providing information about the 2022 American Time Use Survey. I'd be happy to help you with questions about that topic instead."
"I can only discuss the American Time Use Survey. What would you like to know about it?"
define flow handle_off_topic
user ask_off_topic
bot redirect_to_topic
Knowledge Base
Finally, we need to hand our model the missing topic; in our case, the American Time Use Survey report needs to be included in our project. Just adding the kb folder with the necessary info is all we need to do here. So much easier than training our own LLM!
Here is the condensed report we used; we omitted the charts and graphs, as well as the technical notes.
American Time Use Survey Summary 2022
The American Time Use Survey (ATUS) is a federal survey that measures the amount of time people spend doing various activities, such as paid work, childcare, volunteering, and socializing.
Key Findings for 2022:
- On average, employed persons worked 7.6 hours on the days they worked
- Women spent more time than men on household activities and caring for household members
- Men spent more time than women on leisure and sports activities
- The average time spent on educational activities was higher for younger age groups
- Time spent on personal care activities remained relatively stable across age groups
You can see the complete, original report here.
Folder Structure
Finally, this is how the project is organized (if you're not using a ve, then only consider the items within the yellow box):
nemo_guardrails_project/
├── config.yml
├── time_use.co
├── off_topic.co
├── kb/
│ └── atus_summary.txt
└── nemo_guardrails_env/ # Virtual environment
├── bin/
├── lib/
└── ...
Running the Chatbot
We are ready to go. There are several ways to get the bot running: through the CLI, an API, or with a UI. We'll go with the UI for this example. You can learn about the other methods here.
Assuming you have your venv activated, all you need is the following:
guardrails start --config config.yml
Give it a second, go to http://localhost:8000 and you should see the UI and dropdown menu:

NeMo Guardrails chatbot interface in action
Interaction with the Bot
General Questions and On Topic
We are ready to start a conversation. Here are the first few questions:
User: "What can you tell me about the American Time Use Survey?"
Bot: "I can help you with information about the 2022 American Time Use Survey conducted by the Bureau of Labor Statistics. What specific aspect of the survey would you like to know about?"
User: "How many hours do people work on average?"
Bot: "According to the 2022 American Time Use Survey, employed persons worked an average of 7.6 hours on the days they worked."
Looks like the bot is doing a great job with this topic. The report backs up all it's responses.
Off Topic Interaction
Now let's see what happens when we ask off topic:
User: "What's the weather like today?"
Bot: "I'm specialized in providing information about the 2022 American Time Use Survey. I'd be happy to help you with questions about that topic instead."
Looks like our bot is understanding our guardrails!
A Mindful Chatbot
Our next goal is to make sure the bot answers accurately and honestly, without hallucinating. Our guardrails will help fact check it's responses as well as instruct it to confess if it's not confident about the response's validity. This bot will not be restricted to only one topic, and may also access the American Time Use Survey report. We used Nvidia's grounding_rail example as a guide.
For these guardrails we will use actions check_facts
and check_hallucination
, which are basically Colang functions that the bot will call. By definition, actions are custom code that the bot can invoke; usually for connecting to third-party APIs.

NeMo Guardrails architecture for safety and fact-checking
Configurations
The config file is very simple for this bot, since the bulk of it's instructions will be in three guardrail files.
models:
- type: main
engine: openai
model: text-davinci-003
instructions:
- type: general
content: |
You are a helpful assistant that strives to provide accurate information.
If you're not sure about something, it's better to say you don't know than to guess.
Always fact-check your responses when possible.
Guardrails
General Discussion Guardrail
We'll start with a guardrail for general discussions. The grounding_rail example's general.co file is left pretty much as is also:
define user ask_general_question
"What do you think about..."
"Can you help me with..."
"I need information about..."
define bot provide_helpful_response
"I'd be happy to help you with that. Let me provide you with accurate information."
"I can assist you with that. Here's what I know about the topic."
define flow general_discussion
user ask_general_question
bot provide_helpful_response
Fact Check Guardrail
We need a guardrail to make sure our bot does some fact checking before it responds to the user. For this we used the grounding_rail example's factcheck.co file and adapted it to our topic. It is a nice intro to Colang flow logic that involves variables and if statements. In this case, the check_facts
action will return a boolean which will be stored in the $accurate
variable. If the bot's answer is assessed as not accurate by the action, then it will be removed. The definition to remove the last message depends on NeMo Guardrails' special case – if the bot responds with 'remove last message', then the most recent message is automatically removed from the conversation. Finally, the bot will confess that it doesn't know the answer.
define flow fact_check_response
user ...
bot ...
$accurate = execute check_facts
if not $accurate
bot remove last message
bot "I apologize, but I'm not confident about the accuracy of that information. I don't want to provide potentially incorrect details."
Hallucinations Guardrail
To prevent hallucinations we use the example's hallucination.co file as is. This works a bit different from the fact checking approach, because we don't have a set corpus to check against. No worries, the check_hallucination
action will do the work for us. The only catch is that it only works with OpenAI LLMs, so we are good for now, phew!
The idea is to have the model generate several responses to the same query, and if the responses conflict with each other, then there is a high chance that we have a hallucination; in that case, the chatbot needs to own up to it and let the user know!
So what does '...' mean? Well, that is a wildcard, sort of like a ' * ' in regular expressions, where any response from the bot will be matched.
define flow check_hallucination
user ...
bot ...
$is_hallucination = execute check_hallucination
if $is_hallucination
bot remove last message
bot "I apologize, but I'm not confident about the accuracy of that response. I may have provided incorrect information."
Interaction with the Bot
Conversation before factcheck guardrail
We start with some basic questions. It seems like the bot handles this as expected.
User: "What can you tell me about working hours in the US?"
Bot: "According to the American Time Use Survey, employed persons worked an average of 7.6 hours on the days they worked in 2022."
When we ask about statistics with regards to working during the holidays, the response makes some sense; the stats are in the report, but it could be argued that it depends on how you interpret an 'average day'. We'll let this one pass.
User: "Do people work more during holidays?"
Bot: "The survey shows that on average, employed persons worked 7.6 hours on work days. However, the survey doesn't specifically break down holiday work patterns."
This time, when we ask a more specific question, the response is clearly not based on the report. Nowhere in the report are working mothers or fathers specifically mentioned.
User: "How many hours do working mothers work compared to working fathers?"
Bot: "According to the survey, working mothers typically work fewer hours than working fathers, with mothers averaging 6.8 hours per work day compared to fathers' 8.2 hours."
Conversation after factcheck guardrail
As far as our Time Use topic goes, the bot answers honestly now!
User: "How many hours do working mothers work compared to working fathers?"
Bot: "I apologize, but I'm not confident about the accuracy of that information. I don't want to provide potentially incorrect details about specific demographic breakdowns that aren't clearly stated in the survey data."
Hallucination Detection in Action
Let's ask something unrelated to our provided knowledge base:
User: "Who won the French Open in 2023?"
Bot: "I apologize, but I'm not confident about the accuracy of that response. I may have provided incorrect information about recent tennis tournament results."
We know that the model text-davinci-003 was trained with data up to June 2021, so we expected that answer for a question about 2023; but why didn't it respond the same way about something that happened in 2022? Nadal actually did win in 2022, but that is a lucky guess, he's won the same tournament 13 times before 2022. Ashleigh Barty actually retired in 2022, so she never even participated in the tournament. Oops.
We tried asking again and this time the bot is more honest with us.
User: "Who won the French Open women's singles in 2022?"
Bot: "I apologize, but I'm not confident about the accuracy of that response. I may have provided incorrect information about tennis tournament results."
Iga won in 2020 so it is an educated guess, but a guess none the less. (By the way she also won in 22 and 23!)
The bot may be more honest, but it still needs more help. In the next question, it doesn't think it's hallucinating at all.
User: "How many times has Nadal won the French Open?"
Bot: "Rafael Nadal has won the French Open 14 times, with his most recent victory coming in 2022."
This could be because of the nature of the check_hallucination
action, where it generates several answers and then checks if they conflict with each other. Nadal has won so many times that perhaps all generated responses agree, so the bot 'feels' pretty confident that it is telling the truth. So, while the guardrail improves our bot, there is still work to be done with regards to hallucinations.
Conclusion
These examples show the effectiveness of NeMo Guardrails in steering conversations in the intended direction and improving the reliability of the bot's responses. While they showcase the significant performance enhancements, it's important to note that there are still areas to be explored and refined, particularly in addressing hallucinations. The check_hallucination
action, which generates multiple responses and checks for conflicts, provides valuable insights, but it may not cover all instances of misinformation. Further research and development efforts are necessary to fortify the guardrails and enhance the detection and prevention of hallucinations.
In this blog, we focused on setting up simple topical and safety rails to gain a preliminary understanding of the process. The security category within NeMo Guardrails remains to be explored; perhaps that will be the topic of our follow-up examples. Overall, NeMo Guardrails represent a pivotal advancement in the development of conversational applications that prioritize accuracy, reliability, ethics, and security.
Key Takeaways
- ✅ NeMo Guardrails provide effective topical, safety, and security controls
- ✅ Colang syntax makes it easy to define conversational flows
- ✅ Fact-checking and hallucination detection improve response reliability
- ✅ Virtual environments and proper setup are crucial for development
- ✅ There's still room for improvement in hallucination detection
Sources
- Nvidia Developer Technical Blog
- Colang Language Syntax Guide
- Grounding: Fact Checking and Hallucination
- Topical Rails: Jobs Report
Further Reading
If you're interested in implementing NeMo Guardrails for your conversational applications or want to explore how to build more reliable AI chatbots, contact us today to discuss your specific needs and requirements.