در حال بارگذاری ...

Ticket triage goal0:00

The layer of all AI SDK gives us, well, it gives us a lot of things. It gives us the ability to include AI features in our applications. And we don't have to hope that the model says the right thing because we can actually force our agent to return structured data. So what we are going to ship in this episode is a ticket triage. We have a list of tickets. They all have a priority of three, but we don't want to have to manually just go into the ticket, decide, OK, what is the priority? What is the customer sentiment? What are the tags that we might need to also include here?

Install Laravel AI SDK0:42

What is the customer sentiment? What are the tags that we might need to also include here? And more importantly, what team we need to assign these tickets to. It would be nice if we could just ship that off to AI and then it could do it for us. It's a worthy goal. So let's try it. The first thing that we need to do is require the Laravel AI package. This is, of course, going to install the Laravel AI SDK so that we can use it within our application and build our own agents.

This is, of course, going to install the Laravel AI SDK so that we can use it within our application and build our own agents. But there are some config files and some migrations that we need to run. So let's vendor publish. And the provider is Laravel slash AI slash AI service provider. There is one migration file that we need to migrate. So let's go ahead and migrate that. And as far as that is concerned, we're done with the database. We're done with the command line for now. But this is going to give us a config file for our AI.

Configure AI providers1:40

We're done with the command line for now. But this is going to give us a config file for our AI. And if we open up AI.php, we see some defaults. So the default model is going to be open to AI. And of course, this is configurable. We can change this if we want to, but we can also see that there's a different default for images because right now Jim and I is really the best model for generating images. Then there's defaults for audio and transcription and things like that. We can scroll on down and here we can see the providers.

Then there's defaults for audio and transcription and things like that. We can scroll on down and here we can see the providers. So there's an anthropic provider. An Azure provider deep seek 11 Gemini. If we scroll on down to open to AI, which is what we're going to use for our ticket triage, we can see that the driver is open AI. We can also see that we need an open AI API key in our .env file. So if you don't have an API key, you need one. And then you need to add that to your .env file or, you know, whatever model that you want to use.

Build structured agent2:37

And then you need to add that to your .env file or, you know, whatever model that you want to use. The keys that you need to define inside of your .env file are all listed here. So choose whichever one that you want and then add that to your .env file. But then comes the fun parts. We get to make our agent. And as I said, we're going to make a ticket triage for the lack of a better word. And we want this to be a structured agent. This will the data that it's going to be working with is going to be structured

And we want this to be a structured agent. This will the data that it's going to be working with is going to be structured . So with that, let's open up the ticket triage and let's take a look at this class because there's a lot here. So, of course, we have the name of our class ticket triage and it implements agent conversational has tools for our purposes. I think all we need are the agents, which, you know, that pretty much marks this class as an AI agent. And then there's this has structured output.

this class as an AI agent. And then there's this has structured output. Now, this is important because this is going to allow us to get data from the model in a structured format, which means that we can use it programmatically. Not only would we be able to, you know, show that in the view, but we can also take that data and store it in the database, which is something that's we will do. Now this is going to use the promptable trait. And this is important because this is going to give us the ability to essentially

And this is important because this is going to give us the ability to essentially provide a prompt for this agent. So anytime that we want to use this agent, we will call a prompt method, pass in the prompt that we want. And then there we go. So here we can see that we have an instructions method. This is essentially the instructions for this agent. It is included with every prompt. So whenever we call the prompt method and provide our prompt, this

It is included with every prompt. So whenever we call the prompt method and provide our prompt, this instructions is also going to be supplied. And while, you know, it could be okay to say that you are a helpful assistant, we need a little bit more than that because we need to tell the model what we expect it to do. That is how we make AI work for us. So we're going to have our prompt and we're going to start off by saying that you are a support ticket triage assistant. We want to return structured data only and do not include extra keys.

you are a support ticket triage assistant. We want to return structured data only and do not include extra keys. Now we could say that's enough. Yeah, we could, but you know, we can also provide some more information like rules, because when it comes to our data, if we look at the schema here, this is where we get to define the schema that we want the model to return. Let's first of all, get rid of these other methods. We can talk about those at another time. For right now, we just want something a little simple.

We can talk about those at another time. For right now, we just want something a little simple. We want to prompt. We want to get data back. So our schema, you know, we are essentially triaging tickets and we need some information. We need to know the priority. We need to know the department that it needs to be assigned to. We need to know the customer sentiment. Are they neutral?

We need to know the customer sentiment. Are they neutral? Are they angry? Are they happy? If we have a ticket, they probably aren't happy, but, you know, that's the kind of thing that we want the AI to provide for us. And the thing is it doesn't matter if it's correct or not. We just need something to go ahead and give us those initial values, because then once it gets into, you know, a certain department's hands, then they can say, oh, this isn't ours.

because then once it gets into, you know, a certain department's hands, then they can say, oh, this isn't ours. This is someone else's triage doesn't have to be 100% correct. In this case, so we have a priority. Priority is going to be, you know, a range of one to five, I guess. So we're going to say that it is an integer with a min value of one and a max value of five, but the response needs to always include that. So that will be required. Let's break this up on to a couple of lines here. So that's our priority.

Let's break this up on to a couple of lines here. So that's our priority. We need the priority. The second thing we need is the department that is going to handle, or at least initially handle the ticket. So we use our schema to define department as a string. Then we need the sentiment. What is the user or what does the model think the user is currently feeling about what their ticket is? Because, you know, there's, there's the priority thing, but we also kind of

feeling about what their ticket is? Because, you know, there's, there's the priority thing, but we also kind of want to handle the customers that are. A little bit more angry, but two, you know, that could also say that, you know, this customer may be angry, you know, treat them with a little extra care. Yeah, whatever. So we need the priority. We need the department. We need the sentiment, but then, you know, we already have some tags for our tickets.

We need the sentiment, but then, you know, we already have some tags for our tickets. It would be nice though to let the AI build some tags too. So we're going to use our schema builder to say that this is going to be an array where the items are going to be strings. And, you know, this is kind of one of those things we don't always have to have tags. So we could say that there could be no tags or we could set a max. Let's say that we can have the max of six tags and this is going to be required

So we could say that there could be no tags or we could set a max. Let's say that we can have the max of six tags and this is going to be required . And then finally, we need the summary because, you know, if we take a look here , we already know what the user wants, but it would be nice for the system to kind of summarize it as well because maybe, you know, maybe there's something that's not parsed there by our brains, you know, having the system provide what it thinks could be useful as well.

that's not parsed there by our brains, you know, having the system provide what it thinks could be useful as well. So let's say that we'll have the schema string. Let's also say that that is required and there we go. So there's a couple of things that we could do here as far as our rules are concerned. You know, we could say that maybe summary is optional, but, you know, ideally, we should always have a summary. So one thing that we could say is that always provide a value for summary, even if it's empty or if it's an empty string.

So one thing that we could say is that always provide a value for summary, even if it's empty or if it's an empty string. Let's be specific when dealing with AI. Then, you know, tags, you know, maybe we ought to provide some kind of default. So maybe we need to do this. If you cannot determine a value, use, and then here, we'll say summary is going to be an empty string and then tags will just be an empty array. That way, you know, it doesn't matter. Even though we have said that summary is optional, we still want something there,

Even though we have said that summary is optional, we still want something there, even if it is just an empty string, in which case, you know, maybe we should go ahead and mark that as required as well. So we could say it's optional, but this way we always have a value, even if it's empty and then tags. And, you know, maybe we ought to do this always include every key in the schema . I mean, yes, we should because everything's marked as required, but this way we have the rules always include every key for the schema.

I mean, yes, we should because everything's marked as required, but this way we have the rules always include every key for the schema. If you can't determine a value for the summary, give us an empty string. If you can't for tags, give us an empty array. That way we always have something to work with. And that's our agent that that's that's basically it's kind of because we can mark our agent class with some attributes. Like, for example, we can use the provider attribute, in which case, we can say that this is going to use the open AI provider.

Like, for example, we can use the provider attribute, in which case, we can say that this is going to use the open AI provider. Now, lab here is an E-new, so we need to go ahead and add that. So we are essentially saying that for our ticket triage, use the open AI provider. This means that we can write many agents that use different providers and we don't really have to do anything at all, except to be sure that we have our configuration correct, as well as just, you know, define the provider that we want to use

configuration correct, as well as just, you know, define the provider that we want to use for a specific agent. But we can also do this. We can say that we want to use the cheapest model available for this particular provider, because, you know, every provider has different models. Some are more expensive than others. So, you know, for a ticket triage, again, we don't need something that's going to, you know, think forever and have to give us this very in-depth response.

to, you know, think forever and have to give us this very in-depth response. Just give us something quick so that we can triage these tickets and then get them, you know, at least to their respective departments as quickly as possible. But then, too, if we wanted to set a limit on the max amount of tokens, we could do that as well. Now, this is for the response, but it's going to cap the output length to whatever we

Now, this is for the response, but it's going to cap the output length to whatever we specify here. If we do something too small, then we're going to run into errors. So, you know, for this case, let's use a max token of 1,200. That's probably a little bit too big, but I would prefer to not have any issues because, you know, we are going to be dealing with the summaries. These summaries could be large depending upon the ticket text or the actual problem. So let's be a little liberal with our max tokens there.

Wire agent into controller12:18

problem. So let's be a little liberal with our max tokens there. And there's our agent. So now we need to use our agent and we're going to do this inside of a controller. Let's call it ticket triage controller. I'm going to make this invocable because we don't need, you know, the index, the store methods or anything like that. We just need to be able to invoke this particular controller. So let's open up the ticket triage controller and let's start by just,

We just need to be able to invoke this particular controller. So let's open up the ticket triage controller and let's start by just, you know, prompting our agent. So we are going to try to get a response from our new ticket triage, which is going to have a prompt method. Now, this prompt method is there because of that promptable trait that we have inside of our agent class. So we're going to prompt what? Well, it would be nice to have the ticket subject. So we can include the ticket subject, which, where do we get the ticket?

Well, it would be nice to have the ticket subject. So we can include the ticket subject, which, where do we get the ticket? Well, let's do it right here. So we have our tickets called ticket. And then after the subject, we will provide the latest message for that ticket. So we will once use our ticket to get the messages. We want the latest when we get the first of those and hopefully we'll have the body. So the idea is that whenever we submit this ticket to the model, we're going to include the subject.

So the idea is that whenever we submit this ticket to the model, we're going to include the subject. We're going to include whatever the latest message is, which, you know, ideally it would be the only message that's there because we are triaging these tickets so that whenever we get the response, we will update the ticket with the priority and the tags and everything that comes from the response. So the priority will come from the response priority, the department and everything. So basically what we have in our schema here, priority, department, sentiment,

everything. So basically what we have in our schema here, priority, department, sentiment, tags, summary, we want all of that. So we will have our department coming from the response. We will have the sentiment, sentiment coming from the response. And for these tickets beforehand, I went ahead and defined an AI tags column just so that we wouldn't have to see me make those changes. And then we need to check to see if we have a summary because if we do, then we want to add that summary as a message to the ticket.

And then we need to check to see if we have a summary because if we do, then we want to add that summary as a message to the ticket. So if the response message, or it's not message, it's summary. If the summary from the response is not empty, then we are going to add that response summary to the messages. So we'll call create the user ID will be known because there is no user there. This came from, I guess, we'll call it the system. That will be the role of that user and then the body will just say something like AI summary, and that's where we will tack on the response summary. Now, of course, this is just basic stuff right now.

Add UI route and test15:33

like AI summary, and that's where we will tack on the response summary. Now, of course, this is just basic stuff right now. Eventually, what I want to do is take this information and I want to store it in the database so that any time that we make, you know, any kind of AI inquiry , then we will store that in the database, giving us a way to track, you know, all of our AI interactions within our application. But for right now, this is going to be fun. Let's find the show for viewing an individual ticket. So let's see right here, if we don't have tags.

Let's find the show for viewing an individual ticket. So let's see right here, if we don't have tags. So we are outputting the tags here, then we have the conversation. So I want to add a button, it says base by five, and we are going to have a form. The method will be post, the action will be our route, which we need to define our route, but, you know, what should we call it? This is dealing with our tickets. We are triaging them with AI. So we'll say tickets, AI triage for the lack of a better term.

We are triaging them with AI. So we'll say tickets, AI triage for the lack of a better term. Then we need to include the tickets that we want to work with there, which is this ticket ID. And this is going to be a post request. So we need to include the CSRF token so that we actually make that request. So let's go ahead and inject that with CSRF. And then let's just grab somewhere where flux button is being used right there, post message. We'll copy that and we'll paste that here and we'll just say triage.

where flux button is being used right there, post message. We'll copy that and we'll paste that here and we'll just say triage. So our route is tickets, AI triage. Let's go ahead and copy that so that we can go to our routes. And we only want authenticated users to do this. And ideally, it would only be users that have the ability to do this. But for right now, it's going to be fine. So we'll have our route, post, our URL will be tickets. And then the ticket that we're working with. And let's just have it triage.

And then the ticket that we're working with. And let's just have it triage. Let's do this tickets and then ticket, then AI, then triage. That way, for any other AI things that we want to add, we have, you know, a convention there, if you will. So this is going to be our ticket triage controller. And let's set the name to that tickets, AI triage. All right, so as far as our controller is concerned, we do have an error here because we have a try. We need to catch a throwable E.

we do have an error here because we have a try. We need to catch a throwable E. Now, if we're successful, I guess we could return response Jason and we could say that the status is OK. And then we could include the data from the response. I like that. That way we can see that everything worked OK. Nothing went wrong, hopefully. But if it failed, we'll do something there. OK, so with that in place, there's still an error.

But if it failed, we'll do something there. OK, so with that in place, there's still an error. Well, Visual Studio thinks we have, we do have an error. We need to use statement for our ticket model. So with that, inside of the browser, we should see our button to triage. If we click this, then hopefully this will work. It does status OK, data, priority one, department billing, sentiment, negative duplicate charge. Now, of course, this is just the Jason structure that we have. We should have saved this as part of the ticket and sure enough, we have.

Now, of course, this is just the Jason structure that we have. We should have saved this as part of the ticket and sure enough, we have. So now we can see that the priority is one, highest priority, the billing department and the sentiment is negative because this person was charged twice for their pros subscription. And we can see that with the AI summary is customer reports, two identical charges for pros subscription this month, requests refund, blah, blah, blah. There we go. We have a quick way to triage our tickets. The next thing I want to do is track our AI interactions

There we go. We have a quick way to triage our tickets. The next thing I want to do is track our AI interactions because, you know, in a real application, that's exactly what we would do. So we will tackle that in the next episode.

دوست دارید گاهی خبرهای Laracasts را ایمیل کنیم؟