Photo by Viktor Kiryanov on Unsplash

How To Build Better Conversational Apps with NeMo Guardrails

Mayra Quiroga
enfuse.io
Published in
18 min readJul 10, 2023

--

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.

If you prefer to watch instead of reading, check out my video tutorial which covers the set up and how to build the first chatbot on this article :

NVIDIA NeMo Guardrails — Restricted Topic Chatbot

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

mkdir my_project
cd my_project

python -m venv venv
source venv/bin/activate

pip install nemoguardrails
pip install openai

export OPENAI_API_KEY=<paste your key here>

Now, if all went well, the guardrails CLI should be ready to use. To test this out:

nemoguardrails --help

You should see something like this:

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

Photo by Nik on Unsplash

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.

Configurations

We begin by creating a config.yml file. It includes basic instructions, a sample conversation, and model information.

instructions:
- type: general
content: |
The following dialogue features a discussion between a user and a bot
regarding the American Time Use Survey or 2022.
The bot provides accurate and brief information.
Whenever the bot is unfamiliar with an answer, it honestly states that
it doesn't know.
sample_conversation: |
user "Hello"
express greeting
bot express greeting
"Hi there! How may I help you today?"
user "What can you do for me?"
ask about capabilities
bot respond about capabilities
"I can answer questions based on the topic 'American Time Use Survey
(ATUS) of 2022' gathered and published by the US Bureau of Labor
Statistics."
user "Can you give me a summary about ATUS?"
ask question about survey
bot response for question about survey
"The American Time Use Survey (ATUS) measures the amount of time people
spend doing various activities, such as paid work, childcare,
volunteering, and socializing."
user "Thanks"
express appreciation
bot express appreciation and offer additional help
"My pleasure. Please let me know if you have any other questions."
models:
- type: main
engine: openai
model: text-davinci-003

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 flow
user ask about headline numbers
bot response about headline numbers

define user ask about headline numbers
"What percentage of employed persons worked at home on the days they worked?"
"What percentage of employed persons worked at their workplace?"

define flow
user ask about leisure and sports activities data
bot response about leisure and sports activities data

define user ask about leisure and sports activities data
"What is the most popular leisure activity?"
"What can you tell me about reading as a leisure activity?"

define flow
user ask about care of household children data
bot response about care of household children data

define user ask about care of household children data
"What age group of children take up the most time spent on caring for them by their household?"
"Did employed adults spend more or less time caring for children than unemployed adults?"

And here is the complete file (be sure to edit the extension to .co before using it).

time-use.txt

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 stocks should I buy?"
"Can you recommend the best stocks to buy?"
"Can you recommend a place to eat?"
"Do you know any restaurants?"
"Can you tell me your name?"
"What's your name?"
"Can you paint?"
"Can you tell me a joke?"
"What is the biggest city in the world"
"Can you write an email?"
"I need you to write an email for me."
"Who is the president?"
"What party will win the elections?"
"Who should I vote with?"

define flow
user ask off topic
bot explain cant off topic

define bot explain cant off topic
"Sorry, I cannot comment on anything which is not relevant to the time use report."

define flow
user ask general question
bot respond cant answer off 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 (save as markdown) atus.md; we omitted the charts and graphs, as well as the technical notes.

# American Time Use Survey -- 2022 Results

For release 10:00 a.m. (ET) Thursday, June 22, 2023 USDL-23-1364 Technical information: (202) 691-6339
atusinfo@bls.gov
www.bls.gov/tus

Media contact: (202) 691-5902
PressOffice@bls.gov


In 2022, 34 percent of employed persons did some or all of their work at home on days they worked, and 69 percent of employed persons did some or all of their work at their workplace, the U.S. Bureau of Labor Statistics reported today.

These and other results from the American Time Use Survey (ATUS) were released today. They include the average amount of time per day in 2022 that individuals worked, did household activities, and engaged in leisure and sports activities. Additionally, measures of the average time per day spent providing childcare--both as a primary (or main) activity and while doing other things are provided. For a detailed description of ATUS data and methodology, see the Technical Note.

### Working (by Employed Persons) in 2022

On days they worked, 34 percent of employed persons did some or all of their work at home and 69 percent of employed persons did some or all of their work at their workplace. On average, those who worked at home did so for 5.4 hours on days they worked, and those who worked at their workplace did so for 7.9 hours.

The share of employed persons who spent time working at home on days worked decreased slightly from 38 percent in 2021 to 34 percent in 2022. However, workers were still more likely to work at home in 2022 than in 2019, before the COVID-19 pandemic (34 percent compared with 24 percent).

Workers with higher levels of education were more likely to work at home than were those who had less education. Among workers age 25 and over, 54 percent of employed persons with a bachelor's degree or higher performed some work at home on days worked, compared with 18 percent of those with a high school diploma and no college. Workers with a bachelor's degree or higher were equally likely to work on an average day as were those with a high school diploma and no college (68 percent).

On days they worked, employed men worked 32 minutes more than employed women. This difference partly reflects women's greater likelihood of working part time. However, even among full-time workers (those usually working 35 hours or more per week), men worked more per day than women--8.3 hours, compared with 7.8 hours.

On days they worked, employed women were more likely than employed men to do some or all of their work at home--41 percent of women, compared with 28 percent of men. On days they worked at home, employed women and men spent the same amount of time doing so (5.4 hours).

Many more people worked on weekdays than on weekend days: 81 percent of employed persons worked on an average weekday, compared with 29 percent on an average weekend day. Employed persons also spent more time working on weekdays than on weekend days--8.0 hours compared with 5.6 hours.

### Household Activities in 2022

On an average day, 85 percent of women and 70 percent of men spent some time doing household activities, such as housework, cooking, lawn care, or household management.

On the days they did household activities, women spent an average of 2.7 hours on these activities, while men spent 2.2 hours.

On an average day, 22 percent of men did housework--such as cleaning or laundry--compared with 47 percent of women.

On average, more people engaged in housework on weekend days than on weekdays: 40 percent compared with 33 percent. However, they were more likely to engage in food preparation and cleanup on weekdays (62 percent) than on weekend days (57 percent).

### Leisure and Sports Activities in 2022

On an average day, nearly everyone age 15 and over (95 percent) engaged in some sort of leisure and sport activity, such as watching TV, socializing, or exercising. Men spent more time in these activities than did women (5.6 hours, compared with 4.8 hours).

On average, adults age 75 and over spent 7.5 hours engaged in leisure and sports activities per day-- more than any other age group; those ages 25 to 54 averaged 4.2 hours doing leisure and sports activities per day--less than other age groups.

Watching TV was the leisure and sports activity that occupied the most time (2.8 hours per day), accounting for over half of all leisure time, on average.

Playing games and computer use for leisure, and socializing and communicating were the next most common leisure and sports activities after watching TV. On an average day, individuals spent 34 minutes playing games and using a computer for leisure and 34 minutes socializing and communicating. They spent twice as much time socializing on weekend days (53 minutes) as on weekdays (25 minutes).

Time spent reading for personal interest and playing games or using a computer for leisure varied greatly by age. On an average day, individuals age 75 and over spent 40 minutes reading while those ages 15 to 19 read for 13 minutes. Conversely, individuals age 15 to 19 spent 1 hour and 38 minutes playing games or using a computer on an average day, while those ages 75 and older spent 29 minutes doing so.

Employed adults living in households with no children under age 18 engaged in leisure and sports activities for 4.6 hours per day, over an hour more than did employed adults living with a child under age 6 (3.4 hours).

### Care of Household Children in 2022

Adults living in households with children under age 6 spent an average of 2.1 hours per day providing primary childcare to household children. Adults living in households where the youngest child was between the ages of 6 and 17 spent less than half as much time providing primary childcare to household children--49 minutes per day. Primary childcare is childcare that is done as a main activity, such as providing physical care or reading to children.

On an average day, among adults living in households with children under age 6, women spent 1.1 hours providing physical care (such as bathing or feeding a child) to household children; by contrast, men spent 31 minutes providing physical care.

On average, among adults living with children under age 6, those who were not employed spent nearly an hour more per day caring for and helping household children than did employed adults-- 2.6 hours versus 1.7 hours.

Adults living in households with at least one child under age 13 spent an average of 5.3 hours per day providing secondary childcare--that is, they had at least one child in their care while doing activities other than primary childcare. Secondary childcare provided by adults living in households with children under age 13 was most commonly provided while doing leisure activities (2.0 hours) or household activities (1.2 hours).

Adults living in households with children under age 6 spent about the same amount of time providing primary childcare on an average weekday and weekend day (2.2 hours and 2.0 hours, respectively). However, they spent less time providing secondary childcare on weekdays (4.7 hours) than on weekend days (7.6 hours).

### Additional Data

ATUS 2022 data files are available for users to do their own tabulations and analyses. In accordance with BLS and Census Bureau policies that protect the privacy of survey respondents, personally identifying information does not appear on the data files. The 2022 data files are available on the BLS website at www.bls.gov/tus/data.htm.

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):

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:

cd venv
nemoguardrails server

Give it a second, go to http://localhost:8000 and you should see the UI and dropdown menu:

Interaction with the Bot

General Questions and On Topic

We are ready to start a conversation. Here are the first few questions :

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:

Looks like our bot is understanding our guardrails!

A Mindful Chatbot

Photo by Colton Sturgeon on Unsplash

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².

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

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 express greeting
"hi"
"hello"
"hey"

define user ask name
"What is your name?"

define user ask capabilities
"What can you do?"
"help"

define bot inform capabilities
"I am an example bot that illustrates the fact checking and hallucination detection capabilities. Ask me about the documents in my knowledge base to test my fact checking abilities, or about other topics to test my hallucination detection."

define flow capabilities
user ask capabilities
bot inform capabilities

define user ask knowledge base
"What is in your knowledge base?"
"What do you know?"
"What can I ask you about?"

define bot inform knowledge base
"You can ask me about anything! My knowledge base includes information about the American time use report for 2022, which I can use for fact checking."

define flow knowledge base
user ask knowledge base
bot inform knowledge base

define user request repeat
"Please repeat that"
"repeat"
"What was that?"

define flow
user express greeting
bot express greeting

define bot offer additional help
"If you have any more questions or if there's anything else I can help you with, please don't hesitate to ask."

define user ask general question
"What stocks should I buy?"
"Can you recommend the best stocks to buy?"
"Can you recommend a place to eat?"
"Do you know any restaurants?"
"Can you tell me your name?"
"What's your name?"
"Can you paint?"
"Can you tell me a joke?"
"What is the biggest city in the world"
"Can you write an email?"
"I need you to write an email for me."
"Who is the president?"
"What party will win the elections?"
"Who should I vote with?"
define flow
user ask general question
bot provide 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 user ask about report
"Who worked from home more often?"
"What activitiy took up the most time?"
"What age group of children took up the most attention from their adult caretakers?"

define flow answer report question
user ask about report
bot provide report answer
$accurate = execute check_facts
if not $accurate
bot remove last message
bot inform answer unknown

define bot remove last message
"(remove last message)"

Conversation before factcheck guardrail

We start with some basic questions. It seems like the bot handles this as expected.

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.

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.

Conversation after factcheck guardrail

As far as our Time Use topic goes, the bot answers honestly now!

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
bot ...
$result = execute check_hallucination
if $result
bot inform answer prone to hallucination

define bot inform answer prone to hallucination
"The previous answer is prone to hallucination and may not be accurate. Please double check the answer using additional sources."
"The above response may have been hallucinated, and should be independently verified."

Folder Structure

Interaction with the Bot

Conversation before hallucination guardrail

Let’s ask something unrelated to our provided knowledge base:

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.

Conversation after hallucination guardrail

We tried asking again and this time the bot is more honest with us.

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.

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.

Sources

  1. Nvidia Developer Technical Blog
  2. Colang Language Syntax Guide
  3. Grounding: Fact Checking and Hallucination
  4. Topical Rails: Jobs Report

Further Reading

What is Conversational AI?

Large Language Models Explained

--

--