back to index

Variables and Flows for Chatbots | NeMo Guardrails #2


Chapters

0:0 NeMo Guardrails
0:47 Variables and Flows in Colang
2:50 Setting Variables with the Context Role
5:6 Setting Variables from User Input
7:25 How the Greeting Flow Works

Whisper Transcript | Transcript Only Page

00:00:00.000 | In this video, we're going to be exploring Kolang of Guardrails a little more
00:00:05.240 | and specifically focusing on the variables and flows within the Kolang modeling language.
00:00:11.940 | Now, Kolang is the modeling language that has been built specifically for building
00:00:18.100 | conversational flows for chatbots by NVIDIA and is used by the NVIDIA Nemo Guardrails library.
00:00:25.060 | Kolang is pretty simple and it's relatively easy to read, particularly if you know Python as well.
00:00:30.740 | But there are a few concepts and items that we need to figure out before we begin using Guardrails more.
00:00:38.440 | That being said, whilst we're figuring this out, we will be using Guardrails on top of these anyway.
00:00:45.060 | So we're kind of learning as we go.
00:00:47.500 | Now, we're going to be going through this notebook.
00:00:50.000 | There'll be a link to this notebook at the top of the video right now.
00:00:53.700 | And what we're going to do is just take a look at these variables, how we set them, and also the flows.
00:01:00.000 | So we have the definition of a flow that I've already shown you in a previous video,
00:01:06.460 | but we also want to take a look at the if/else within the flow and how we can use that.
00:01:12.760 | And that fits quite nicely with variables.
00:01:15.200 | So what I first want to do is we'll initialize our OpenAI API key,
00:01:22.760 | and we're going to initialize our Colang file and our config file, right?
00:01:27.200 | So let's just take a quick look at what we have here.
00:01:30.300 | We have a user greeting.
00:01:32.140 | This is our user message, canonical form.
00:01:35.640 | And these are some utterances that can define what that should look like.
00:01:40.500 | Then we have our bot message, canonical form here.
00:01:46.400 | And when this is called, we're going to return this, which is "Hey, name," right?
00:01:53.100 | And just note here that the name is preceded by this dollar symbol.
00:01:57.380 | That means that this is a context variable,
00:02:01.480 | so a variable within the context of our Colang file.
00:02:05.000 | And then we define a flow.
00:02:06.300 | So this flow is initialized if we see a user greeting,
00:02:09.500 | and we can see that we have an if/else statement in here.
00:02:12.700 | So if name, basically this is saying if the name exists,
00:02:18.280 | if that variable has been set,
00:02:20.480 | then the bot is going to use this greeting here.
00:02:23.940 | So it's going to use a name.
00:02:25.600 | Otherwise, the bot's just going to do a greeting, right?
00:02:28.600 | We haven't defined this canonical form here,
00:02:31.940 | but the way that Colang and Guardrails works is actually the bot
00:02:36.680 | can just read this and build its own sort of message from that.
00:02:41.340 | So it will basically create a greeting.
00:02:43.700 | So let's try this, right?
00:02:45.480 | So we're going to initialize our Rails using those configs.
00:02:49.880 | And now here we're doing something slightly different
00:02:52.780 | to what we were doing before.
00:02:54.480 | So before we were doing like this, we had instead of messages,
00:02:59.840 | we were just passing in a single prompt.
00:03:02.540 | And that's a completely valid way of doing this.
00:03:05.900 | But by passing in messages,
00:03:08.940 | we can also pass in conversational history,
00:03:12.440 | which one is very useful by itself,
00:03:15.440 | but also we can pass in this context role.
00:03:19.000 | And this context role, I haven't defined anything here yet,
00:03:22.660 | but it will allow us to pass in variables or set variables
00:03:28.440 | at the beginning of the conversation.
00:03:30.460 | So within the messages that we're using here,
00:03:34.560 | we're allowed to use three different roles.
00:03:36.460 | We have that context, we have the user and we have the assistant.
00:03:39.640 | I've commented this out because I want you to see an example
00:03:42.960 | of what that assistant role would look like,
00:03:45.460 | but we're not actually going to be using it, at least not yet.
00:03:48.540 | So we'll initialize those messages and we'll pass them into our Rails.
00:03:53.200 | And we get this response from the assistant role saying,
00:03:56.360 | "Hey there, how can I help you?"
00:03:59.160 | Very similar to the prompt approach.
00:04:01.740 | It just, we have that history in there and we have the content.
00:04:04.980 | So with this, the bot is just saying, "Hey there, how can I help you?"
00:04:10.540 | We kind of wanted to trigger this.
00:04:12.780 | So right now it's gone to else because there is no name defined.
00:04:16.640 | It's just created a bot greeting, right?
00:04:18.480 | It's generated the greeting by itself.
00:04:21.640 | So if we'd like it to trigger the name here
00:04:24.540 | and trigger the bot name greeting,
00:04:27.880 | we need to pass in a name.
00:04:30.340 | And we can do within the content.
00:04:32.140 | So within content, we're going to pass a dictionary.
00:04:34.780 | And that dictionary can contain our context variables and their values.
00:04:40.140 | So I'm going to pass in my name through this.
00:04:42.880 | And actually, I'm going to remove this middle message from the assistant.
00:04:46.380 | And now this is exactly the same as what we had up here.
00:04:49.840 | But now we just have the context variable and name for James.
00:04:54.020 | So let's run this.
00:04:56.840 | And we see now that it triggers the, "Hey, James."
00:04:59.920 | So that is the form that we specified here.
00:05:03.540 | Okay. So that's now working.
00:05:06.020 | Now let's try adding these context variables from within the conversation
00:05:10.340 | rather than just at the start of it because we can do that too.
00:05:13.380 | Okay. So what I'm going to do here is I'm going to define a few things.
00:05:18.720 | So I'm going to define the user giving a name.
00:05:21.680 | And there's a few examples here of what that would look like.
00:05:24.740 | We still have these. So these are from before.
00:05:27.580 | The user greeting and the bot name greeting.
00:05:30.280 | But then we define a new flow.
00:05:32.120 | This flow is when the user is giving a name.
00:05:34.640 | Okay. So initialize by this.
00:05:37.340 | And so this is kind of an interesting way of doing things.
00:05:41.420 | We can take the name from the input.
00:05:46.280 | And when we're using this syntax here,
00:05:48.320 | an LLM is actually going to extract the name.
00:05:51.720 | Okay. The way that I've written it here is very clear.
00:05:55.540 | I'm saying extract the name from the user's response.
00:05:59.540 | So an LLM will actually do that.
00:06:01.420 | And it will pass the name that it extracts into this name variable here.
00:06:07.240 | And then after that, we can actually call the bot name greeting.
00:06:10.940 | Right. Okay. So here we're just saying if the name does not already exist,
00:06:15.580 | which it won't do, just ask for the name.
00:06:20.320 | Okay. So let's see how that will work.
00:06:23.980 | Run this. We're going to have to remove the name parameter from the context.
00:06:28.580 | So let me move that as well.
00:06:31.520 | We reinitialize our Rails.
00:06:36.940 | And now we're going to generate.
00:06:39.380 | Okay. We see here that the assistant is saying,
00:06:42.140 | "Hi there. What's your name?"
00:06:43.680 | Okay. Why is it doing that? Let's take a look.
00:06:46.720 | We have our user greeting.
00:06:49.040 | This is being initialized because we say, "Hey there."
00:06:52.620 | If not name, so no name is defined, the bot will ask for the name.
00:06:57.720 | Okay. Which is what it does.
00:06:59.780 | "Hi there. What is your name?"
00:07:02.380 | Then we're going to respond.
00:07:03.640 | Okay. So first we want to add this response from the assistant to our messages.
00:07:09.180 | So we add that here.
00:07:10.640 | And then we also add our response.
00:07:13.640 | Okay. I'm going to say, "I'm James."
00:07:15.120 | Okay. We run that.
00:07:16.540 | And now, because we have the name,
00:07:20.420 | because that has been added, it will respond with, "Hey, James."
00:07:24.040 | Okay. So we come up to here.
00:07:26.720 | Our input is us giving the name.
00:07:28.980 | I said, "I'm James."
00:07:30.040 | So we trigger this flow, user give name.
00:07:35.220 | We extract the name from the user giving it using the LLM,
00:07:41.020 | and then the bot responds with this bot name greeting,
00:07:45.480 | which is, "Hey, name," which is exactly what we get down here.
00:07:49.340 | Okay. So that's just a quick introduction
00:07:54.040 | to how variables and flows work within Colang and Nemo guardrails.
00:08:00.680 | I just wanted that to be a very quick introduction to those.
00:08:03.540 | In the next video, what we're going to be looking at is something called actions.
00:08:08.940 | So the execution of actual code from within our guardrails,
00:08:14.580 | which will be pretty interesting.
00:08:16.340 | So for now, that's it for this video.
00:08:18.180 | I hope this has been useful and interesting.
00:08:20.180 | So thank you very much for watching,
00:08:22.180 | and I will see you again in the next one.
00:08:25.180 | [music]
00:08:30.180 | [music]
00:08:35.180 | [music]