Planning Safety Guardrails0:00
You can't ship AI features without safety, and so we are going to implement some guard rails that screen prompts, filter outputs, and keep an audit trail so that the feature is safe to use in production. So we are going to create a creative assistant, and we are going to filter the input before it's sent to the prompt. We are going to filter the prompt when it comes back with some data, and then we are also going to be sure that the agent can only search certain domains that we want. So the first thing that we are going to do is just add some routes, because, well, it doesn't make sense to do this as the first thing, because we don't
Adding Routes and Agent0:44
So the first thing that we are going to do is just add some routes, because, well, it doesn't make sense to do this as the first thing, because we don't have the controller yet. But once we get this set up, then we will be able to move on. So let's go ahead and add the controllers, and then the name of this controller is going to be creative assistant controller. Of course, it's not going to work yet, but that's okay. And so now we need to create an agent, which we haven't made an agent in a while. So let's call this creative assistant, and this is going to be a promptable assistant. It's an agent.
So let's call this creative assistant, and this is going to be a promptable assistant. It's an agent. It's not going to be conversational. However, it will have middleware, which kind of sounds weird if you think about it, but, you know, it makes perfect sense. If we are going to have this pipeline of being able to take a prompt or create an agent that's going to send a prompt and then work with data coming back, it only makes sense that we would be able to, you know, insert ourselves into that pipeline and do whatever it is that we need to do at whatever stage.
pipeline and do whatever it is that we need to do at whatever stage. But first, let's add our provider attribute. Once again, lab, open AI. That's going to be our provider. And as far as the model is concerned, let's just use the cheapest model. We don't need any other attributes. This is going to be just fine for us. Now, of course, has middleware is an interface, and we haven't yet implemented that, which is why we see the red squiggly. But let's first of all set our instructions because we need that initial prompt so that the provider will know kind of what we wanted to do.
instructions because we need that initial prompt so that the provider will know kind of what we wanted to do. So this is a creative assistant. So let's say that you are a helpful creative writing assistant. We want you to keep content safe, professional and non sensitive. I don't really like using that, but, you know, I'm thinking in terms of sensitive information, credit card information, social security numbers, ident ifications, API keys, you know, those kinds of things. We don't want it to do. So that's going to give us a good start. But of course, we need some hard guardrails. So we don't need the messages method, but we do
Wiring Middleware Pipeline2:56
We don't want it to do. So that's going to give us a good start. But of course, we need some hard guardrails. So we don't need the messages method, but we do need the middleware method, because that is what we need to implement the has middleware interface. And this is going to not return void. This is going to return an array, and we can go ahead and we can return that array. But of course, we want to, you know, specify the middleware that we want to have. So the first is going to be a class called input safety middleware. The second is going to be output safety middleware. As our name implies, we are essentially going to be inspecting two things.
is going to be output safety middleware. As our name implies, we are essentially going to be inspecting two things. One, we are going to intercept before the provider sends the prompt. I was wrong. We are going to intercept the prompt before the agent sends it to the provider. So that will give us the opportunity to inspect, you know, the, the input. And then we will have one that inspects the output when it comes back. So of course , we need those files. So let's create these inside of app, AI, and then middleware. So we will create a new file called input safety middleware. Let's also go ahead and create
So let's create these inside of app, AI, and then middleware. So we will create a new file called input safety middleware. Let's also go ahead and create another file called output safety middleware. So there are some things we need to start off with, such as the namespace app AI middleware. And then we have the class of output safety middleware. So we have that. Let's just go ahead copy that paste it into the input safety. Of course, we need to change this to input safety. And let's start here. So this is middleware. It's going to behave like middle ware. It's going to be very similar to middleware. We're going to have this handle method and we will get an agent prompt.
Implementing Input Safety Filter4:51
ware. It's going to be very similar to middleware. We're going to have this handle method and we will get an agent prompt. But we will also get the closure of next. Now in the previous episode, whenever we created middleware, you know, it created middleware for our agent. And that that was already there. So that's where this comes from. We can create middleware for our agents. Now this is before data is sent or before the prompt is sent to the provider. So we want to first of all get the text of the prompt. And we can do that with the prompts prompt property. And then, you know, we just need to specify the things that we want to filter out, the things that we
And we can do that with the prompts prompt property. And then, you know, we just need to specify the things that we want to filter out, the things that we want to block. So let's say that we'd have password. Well, it's going to have credit card. I mean, this is very basic, but, you know, this is the idea. We have the things that we want to filter out the things that we want to prevent going to the provider. So of course, we're going to have just a simple array. And then all we will need to do here is iterate over our blocked array as word. And if the text from the prompt contains the word, and that's not false, then it's blocked.
need to do here is iterate over our blocked array as word. And if the text from the prompt contains the word, and that's not false, then it's blocked. So we want to throw a new exception, and we'll say input blocked by safety filter. But if we make it out of the for each loop, then we just want to return next passing in the prompt so that it goes on to the next middleware in the chain. All right, so we have our exception. That variable should be word. And that's that's that's how we look at incoming prompts before they go off to the provider. So now we have our output safety middleware. And let's just copy what we have
Implementing Output Safety Filter6:40
provider. So now we have our output safety middleware. And let's just copy what we have for the input, paste that in for the output, because it's going to be very similar. And that's we have our handle method. We are still going to get an agent prompt . But now we are dealing with output, which means that we don't want to deal with the prompt text. We want to actually execute the next piece in the chain of the middleware, which is going to be, you know, actually sending the prompt to the provider and getting a response back.
which is going to be, you know, actually sending the prompt to the provider and getting a response back. So this is now the response and blocked. Let's do something different, like social security number. Let's use something else fish. I don't know, just something that we can play around with. And then the idea is going to be very simple again, in that we need, first of all, the text. I forgot about the text, but we'll get the text from the response. So that's we will iterate over our blocked array, checking to see if the text has any one of those words. But if it does, we're not going to throw an
So that's we will iterate over our blocked array, checking to see if the text has any one of those words. But if it does, we're not going to throw an exception. Instead, we are going to return a new agent response, and we are going to use the invocation ID from the response that we retrieved from the provider. But in this case, we're going to say that the output was blocked by safety filter. And then we will have the usage. And then we want to also include the meta. So we're going to return that response. Otherwise, if we get out of this for each loop, we already have the response from sending it off to the provider.
response. Otherwise, if we get out of this for each loop, we already have the response from sending it off to the provider. So we will just return response. And that's it. Those are the two pieces of middleware. So very simple and straightforward. Of course, we can make this as complex as we want. But for our purposes, for this to show how this works, it's going to be fine. All right, so we need to include these classes now, and there's that. But input safety middleware isn't showing up. We don't need conversational, but let's copy this. Let's change this to input. Hopefully our red squigglies will go away. No, there's, there's something
let's copy this. Let's change this to input. Hopefully our red squigglies will go away. No, there's, there's something definitely wrong there. All right, so I. Middleware. Dare I leave it that way? Yes. Yes, I will. Okay, so we have our middleware all set up. So we're going to be filtering the input and the output. But we can also use tools here. And there's a built-in tool called web search. This is provided by the SDK. And this gives us the ability to limit things around searching for the web. But we're going to new up web search. And then we have an allow method so that
around searching for the web. But we're going to new up web search. And then we have an allow method so that we can allow, you know, certain domains. So we can include layercasts.com. Laravelle.com. Let's do PHP.net and so on. We can also filter by the user's location if we wanted to do that as well. So that's nice. But we're going to leave it as just the allow list. And that's going to be okay . And we still have a red squiggly. Why is that? Because we don't implement middleware because I can't spell apparently. So there we go. That is our agent. And so now it's just a matter of using our agent with our
Controller, View, and Testing10:16
middleware because I can't spell apparently. So there we go. That is our agent. And so now it's just a matter of using our agent with our controller. So let's make a controller called creative assistant controller. Let's open that up. And that may be your helpful AI assistant once again. So the index method is very simple. Handling the get request. We will return a view passing nothing for the answer the prompt in the error. That's all that the view needs. The answer is, of course, what we are going to display as well as the error. The prompt, though, is part of the request that's coming from a form. So when
display as well as the error. The prompt, though, is part of the request that's coming from a form. So when it comes time to actually handle the post request, we, of course, do our normal things. We validate the incoming information, such as the prompt. We then create our AI run, which that's normal. Then we create our agent so that we can send our prompt from the prompt of the form. If something goes wrong, we throw or no, I'm sorry, we don't throw. We update our run. Then we return a view with our error message. So this is for the input filtering.
our run. Then we return a view with our error message. So this is for the input filtering. You know, all we did was just throw an exception. That's what we are doing here . We are catching the exception so that we can just return a view that includes that error message. And then if we make it pass there, then the prompt succeeded, kind of, because there's the output filtering to take into account. But as far as that is concerned, we sent the prompt. We got the prompt back. And yeah, so then we provide the answer, the prompt and the error to our view. And that's it. So the only other thing that we need now is our view. And we'll
And yeah, so then we provide the answer, the prompt and the error to our view. And that's it. So the only other thing that we need now is our view. And we'll just paste that in. Nothing special about this. Here is our answer. Here is our error. Here is the text area for the prompt. So that's it, which means that we can test this out. I'm ready for bed because I am. So let's generate this. Let's see what happens. We get a target class, input safety middleware does not exist. Okay, I guess I 'm going to have to fix that. And so now that it's fixed, sweet dreams. If you'd like, I can help you wind down, blah, blah, hooray. So let's do, I'm getting fish. This is the output, I think. So we should see
like, I can help you wind down, blah, blah, hooray. So let's do, I'm getting fish. This is the output, I think. So we should see the result that the output blocked by safety filter. Great. So I want your credit card. I think that is for input. I think we used credit card for input. And there it is, input blocked by safety filter. So we didn't build just an AI feature with this creative assistant. We built a safe AI feature. We set up guardrails using middleware, which is really the right place to do that because we can filter the input. We can filter the output. And that's really going to be the first line of defense, if you will, for setting up safe boundaries for our agents.
We can filter the output. And that's really going to be the first line of defense, if you will, for setting up safe boundaries for our agents. But the SDK also gives us tools that we can use in our agents, such as the web search, which now that I think about it, we didn't actually test, but it's there. It works. So safety is a first class feature in the SDK. There's really no reason to not take advantage of it.
