In this chapter we are going to introduce agents. Now agents I think are one of the most important components in the world of AI and I don't see that going away anytime soon. I think the majority of AI applications, the intelligent part of those will be almost always an implementation of an AI agent or most of all AI agents.
So in this chapter we are just going to introduce agents within the context of linechain. We're going to keep it relatively simple. We're going to go into much more depth in agents in the next chapter where we'll do a bit of a deep dive but we'll focus on just introducing the core concepts and of course agents within linechain here.
So jumping straight into our notebook, let's run our prerequisites. You'll see that we do have an additional prerequisite here which is Google search results. That's because we're going to be using the SERP API to allow our LLM as an agent to search the web which is one of the great things about agents that they can do all of these additional things and LLM by itself obviously cannot.
So we'll come down to here we have our Linesmith parameters again of course so you enter your linechain API key if you have one and now we're going to take a look at tools which is a very essential part of agents. So tools are a way for us to augment our LLMs with essentially anything that we can write in code.
So we mentioned that we're going to Google search tool, that Google search tool is some code that gets executed by our LLM in order to search Google and get some results. So a tool can be thought of as any code logic or any function indicate in the case of Python and a function that has been formatted in a way so that our LLM can understand how to use it and then actually use it although the LLM itself is not using the tool it's more our agent execution logic which uses the tool for the LLM.
So we're going to go ahead and actually create a few simple tools we're going to be using what is called the tool decorator from Langchain and there are a few things to keep in when we're building tools. So for optimal performance our tool needs to be just very readable and what I mean by readable is we need three main things.
One is a dot string that is written in natural language and it is going to be used to explain to the LLM when and why and how it should use this tool. We should also have clear parameter names. Those parameter names should tell the LLM okay what each one of these parameters are they should be self-explanatory.
If they are not self-explanatory we should be including an explanation for those parameters within the dot string. Then finally we should have type annotations for both our parameters and also what we're returning from the tool. So let's jump in and see how we would implement all of that. So come down to here and we have linechain core tools import tools okay so these are just four incredibly simple tools.
We have the addition or add tool, multiply, the exponentiate and the subtract tools. Okay so a few calculator s tools. Now when we add this tool decorator it is turning each of these tools into what we call a structured tool object. So you can see that here we can see we have this structured tool we have a name description okay and then we have this arg schema we'll see this in a moment and a function right so this function is literally just the original function it's a mapping to the original function so in this case it's the add function.
Now the description we can see is coming from our dot string and of course the name as well is just coming from the function name. okay and then we can also see let's just print the name and description but then we can also see the args schema right we can so this thing here that we can't read at the moment to read it we're just going to look at the model.json schema method and then we can see what that contains which is all of this information.
So this actually contains everything includes properties so we have the x it creates a little title for that and it also specifies the type okay so the type that we define is float float for openai gets mapped to number rather than just being float and then we also see that we have this required field so this is telling our lm which parameters are required which ones are optional so we you know in some cases you would we can even do that here let's do z that is going to be float or none okay and we're just going to say it is 0.3 all right wait i'm going to remove this in a minute because it's kind of weird but let's just see what that looks like so you see that we now have x y and z but then in z we have some additional information okay so it can be any of it can be a number or it can just be nothing the default value for that is 0.3 okay and then if we look here we can see that the required field does not include z so it's just x and y so it's describing the full function schema for us but let's remove that okay and we can see that again with our exponentiate tool similar thing okay so how how are we going to invoke our tool so the lm the underlying lm is actually going to generate a string okay so we'll look something like this this is going to be our lm output so it is is a string that is some json and of course to load a string into a dictionary format we just use json loads okay so let's see that so this could be the output from our lm we load it into a dictionary and then we get an actual dictionary and then what we would do is we can take our exponentiate tool we access the underlying function and then we pass it the keyword arguments from our dictionary here okay and that will execute our tool that is the tool execution logic that line chain implements and then later on in the next chapter we'll be implementing ourselves cool so let's move on to creating an agent now we're going to be constructing a simple tool calling agent we're going to be using line chain expression language to do this now we will be covering line chain expression language or else more in a upcoming chapter but for now all we need to know is that our agent will be constructed using syntax and components like this so we would start with our input parameters that is going to include our user query and of course the chat history because we need our agent to be conversational and remember previous interactions within the conversation these input parameters will also include a placeholder for what we call the agent scratch pad now the agent stretch pad is essentially where we are storing the internal thoughts or the internal dialogue of the agent as it is using tools getting observations from those tools and working through those multiple internal steps so in the case that we will see it will be using for example the addition tool getting the result using the multiply tool getting the result and then providing a final answer towards as a user so let's jump in and see what it looks like okay so we'll just start with defining our prompt so our prompt is going to include the system message that's nothing we're not putting anything special in there we're going to include the chat history which is a messages placeholder then we include our human message and then that we include a placeholder for the agent scratchpad now the way that we implement this later is going to be slightly different for the scratchpad we would actually use this message's placeholder but this is how we use it with the built-in create tool agent from blank train next we'll define our lm we do need our open API key for that so we'll enter that here like so okay so come down okay so we're being going to be creating this agent we need conversation memory and we are going to use the older conversation buffer memory class rather than the newer runnable with message history class that's just because we're you also using this older create tool calling agent and this is this is the older way of doing things in the next chapter we are going to be using the more recent basically what we already learned on chat history we're going to be using all of that to implement our chat history but for now we're going to be using the older method which is deprecated just as a pre-warning but again as i mentioned at the very solid of course we're starting abstract and then we're getting into the details so we're going to initialize our agent for that we need these four things lm as we defined tools as we have defined prompt as we have defined and then the memory which is our old conversation buffer memory so with all of that we are going to go ahead and we create a tool calling agent and then we just provide it with everything okay there we go now you'll see here i didn't pass in the memory i'm passing it in down here instead so we're going to start with this question which is what is 10.7 multiplied by 7.68 okay so given the precision of these numbers our normal lm would not be able to answer that or almost definitely would not be able to answer that correctly we need a external tool to answer that accurately and we'll see that that is exactly what it's going to do so we can see that the tool agent action message here we can see that i decided okay i'm going to use the multiply tool and here are the parameters i want to use for that tool okay we see x is 10.7 and y is 7.68 you can see here that this is already a dictionary and that is because lang chain has taken the string from our lm call and already converted it into a dictionary for us okay so that's just it's happening behind the scenes there and you can actually see if we go into the details a little bit we can see that we have these arguments and this is the original string that was coming from our lm okay which has already been of course processed by lang chain so we have that now the one thing missing here is that okay we've got that the lm wants us to use multiply and we've got what the lm wants us to put into multiply but where's the answer all right there is no answer because the tool itself has not been executed because it can't be executed by the lm but then okay didn't we already define our agent here yes we defined the part of our agent that is how lm has our tools and it is going to generate which tool to use but it actually doesn't include the agent execution part which is okay the agent executor is a broader thing it's it's broader logic like just code logic which acts as a scaffolding within which we have the iteration through multiple steps of our lm calls followed by the lm outputting what tool to use followed by us actually executing that for the lm and then providing the output back into the lm for another decision or another step so the agent itself here is not the full agentic flow that we might expect instead for that we need to implement this agent executor class this agent executor includes our agent from before then it also includes the tools and one thing here is okay we we already passed the tools to our agent why do we need to pass them again well the tools being passed to our agent up here that is being used so that is essentially extracting out those function schemas and passing it to our lm so that our lm knows how to use the tools then we're down here we're passing the tools again to our agent executor and this is rather than looking at how to use those tools this is just looking at okay i want the functions for those tools so that i can actually execute them for the lm or for the agent okay so that's why it's happening there now we can also pass in our memory directly so you see if we scroll up a little bit here i actually had to pass in the memory like this with our agent that's just because we weren't using the agent executor now we have the agent executor it's going to handle that for us and another thing that's going to handle for us is intermediate steps so you'll see in a moment that when we invoke the agent executor we don't include the intermediate steps and that's because it that is already handled by the agent executor now so we'll come down we'll set verbose equal to true so we can see what is happening and then we can see here there's no intermediate steps anymore and we we do still pass in the chat history like this but then the addition of those new interactions to our memory is going to be handled by the executor so in fact let me actually share that very quickly before we jump in okay so that's currently empty we're going to execute this okay we entered that new agent execute chain and let's just have a quick look at our messages again and now you can see that agent executor automatically handled the addition of our human message and then the responding ai message for us okay which is useful now what happened so we see that the multiply tool was in vote with these parameters and then this pink text here that we got that is the observation from from the tool so they spot the tool output back to us okay then this final message here is not formatted very nicely but this final message here is coming from our lm so the green is our lm output the pink is our tool output okay so the lm after seeing this output says 10.7 multiplied by 7.68 is approximately 82.18 okay cool you saw and then we can also see the the chat history which we we already just saw great so that has been used correctly we can just also confirm that that is correct okay 82.1759 recurring which is exactly what we get here okay and we the reason for that is obviously how multiply tool is just doing this exact operation cool so let's try this with a bit of memory so i'm going to ask or i'm going to state to the agent hello my name is james we'll leave that as the it's not actually the first interaction because we already have these but it's an early interaction with my name in there then we're going to try and perform multiple tool calls within a single execution loop and what you'll see with when it is calling these tools is that you can actually use multiple tools in parallel so for sure i think two or three of these were used in parallel and then the final subtract had to wait for those previous results so it would have been executed afterwards and we should actually be able to see this in langsmith so if we go here yeah we can see that we have this initial call and then we have add a multiply and exponentially or use in parallel then we have another call which you subtract and then we get the response okay which is pretty cool and then the final result there is negative 11.
now when you look at whether the answer is accurate i think the order here of calculations is not quite correct so if we put the actual computation here it gets it right but otherwise if i use natural language it's like i'm doing maybe i'm phrasing it in a in a poor way okay so i suppose that is pretty important so okay if we put the computation in here we get the negative 13.
so something to be careful with and probably requires a little bit of prompting to prompting and maybe examples in order to get that smooth so that it does do things in the way that we might expect or maybe we as humans are just bad and misuse the systems one or the other okay so now we've gone through that a few times let's go and see if our agent can still recall our name okay and it remembers my name is james good so it still has that memory in there as well that's good let's move on to another quick example where we're just going to use google search so we're going to be using the serp api you can okay you can get the api key that you need from here so serpapi.com slash user slash sign in and just enter that in here so you will get it's up to 100 searches per month for free so just be aware of that if you overuse it i don't think they charge you because i don't think you enter your card details straight away but yeah just be aware of that limit now there are certain tools that linechain have already built for us so they're pre-built tools and we can just load them using the load tools function so we do that like so we have our load tools i'm just passing the serp api tool only we can pass in more there if we wanted to and then we also pass in our lm now i'm going to one use that tool but i'm also going to define my own tool which is to get the current location based on the ip address now this is we're in collab at the moment so it's actually going to get the ip address for the collab instance i'm currently on and we'll find out where that is so that is going to get the ip address and then it's going to provide the data back to our lm in this format here so we're going to latitude longitude city and country okay we're also going to get the current day and time so now we're going to redefine our prompt i'm not going to include chat history here i just want this to be like a one-shot thing i'm going to redefine our agent and agent executor using our new tools which is our serp api plus the get current date time and get location from ip then i'm going to invoke our agent executor with i have a few questions what is the date and time right now how is the weather where i am and please give me degrees in celsius so when it gives me that weather okay and let's see what we get okay so apparently we're in council bluffs in the us it is 13 degrees fahrenheit which i think is absolutely freezing oh my gosh it is yes minus 10.
so it's super cold over there and you can see that okay did give us fahrenheit so that's that is because the tool that we're using provided us with fahrenheit which is fine but it did translate that over into a estimate of celsius force which is pretty cool so let's actually output that so we get this which i is correct for the us approximately this and we also get a description of the conditions as well as partly cloudy with zero percent precipitation lucky for them and humidity of 66 okay all pretty cool so that is it for this introduction to line chain agents as i mentioned next chapter we're going to dive much deeper into agents and also implement that for line chain version 0.3 so we'll leave this chapter here and jump into the next one so you