Skip to content

LangGraph Complete Course for Beginners – Complex AI Agents with Python

Complete beginner course on Langraph, teaching graph-based AI agents with Python, type annotations, and practical coding exercises.

Key Takeaways

  • Langraph enables scalable, robust conversational AI applications using graph-based design.
  • Type annotations are critical for ensuring data integrity and reducing bugs in AI projects.
  • Union and Optional types provide flexibility while maintaining type safety.
  • Lambda functions and map improve code efficiency and readability in AI workflows.
  • Practical coding exercises and GitHub resources enhance hands-on learning.

What the video covers

  • Introduction to Langraph, a Python library for building advanced conversational AI workflows using graph-based approaches.
  • Step-by-step explanation of type annotations in Python, including dictionaries, type dictionaries, union, optional, any, and lambda functions.
  • Emphasis on type safety and readability to reduce runtime errors in large AI projects.
  • Detailed coding examples and exercises provided, with answers available on GitHub.
  • Coverage of foundational concepts like AI agents, graph nodes, edges, and state management in Langraph.
  • Practical demonstrations of building basic to complex graphs and dialogue systems.
  • Integration of Langraph with other AI tools such as LangChain and handling conditional logic in graphs.
  • Focus on debugging, efficient coding practices, and human-AI collaboration.
  • Use of lambda functions and map for efficient data processing within AI workflows.
  • Encouragement for learners to progress at their own pace with options to speed up or slow down the video.

Answers

Questions about this video

What is Langraph and what can I learn from this course?

Langraph is a Python library for building complex conversational AI workflows using graph-based methods. This course teaches you how to design, implement, and manage AI agents and dialogue systems with Langraph from scratch.

Why are type annotations important in Langraph?

Type annotations ensure type safety and data integrity, reducing runtime errors and making debugging easier. Langraph extensively uses type dictionaries, unions, and optionals to maintain structured and reliable AI workflows.

Are there practical coding exercises included in the course?

Yes, the course includes many exercises with detailed explanations, and all answers are provided on GitHub to help reinforce learning through hands-on practice.

Full Transcript — Download SRT & Markdown

00:00
Speaker A
Welcome to this video course on Langraph, the powerful Python library for building advanced conversational AI workflows. In this course, Vbeca will teach you how to design, implement, and manage complex dialogue systems using a graph-based approach. By the end, you'll
00:18
Speaker A
be equipped to build robust, scalable, conversational applications that leverage the full potential of large language models. Hey guys, my name is Vava and I'm a robotics and AI student.
00:31
Speaker A
In this course, we're going to be learning all about the fundamentals of Langraph. Now, I assume you've heard of Langraph before, hence why you clicked on this course. But I'm also going to assume you have never coded in Langraph
00:44
Speaker A
before. Now, because of this assumption, I have explained every single thing in as much detail as I possibly can. Now, also this might mean that I might be going slow at times. So if you want you can always speed me up. Now what are we
00:58
Speaker A
going to be learning in this course? Well, to start we're going to be building a lot of graphs, a lot of AI agents.
01:05
Speaker A
We're going to be learning a lot about the theory and I've also provided exercises throughout the course in which all of the answers will be provided on the GitHub. With that being said, if you're ready to start on this journey with me,
01:18
Speaker A
let's go to our first section then. All right people. So welcome to the first section of this course. Now in this section we'll be covering something called type annotations. Now admittedly this is going to be a completely theoretical section but it
01:34
Speaker A
will be short and brief. I promise. The reason I've kept this specific section in the course is because when we do eventually go on to code our AI agents, our graphs and Langraph, these will start popping up everywhere. And I
01:47
Speaker A
don't really want you to start coding without ever having seen these before or really not knowing what these actually are. So that's why I've kept it here. But I promise this will be short and brief. Cool. Okay. Let's begin with
02:00
Speaker A
dictionaries. Now dictionaries are a data structure. Yes, but there's a reason I've kept it here. So let's see how a dictionary is described in Python.
02:09
Speaker A
You should already know this. So in this case, I've described a very simple dictionary called movie. It has two keys, the name and the year. And it has two values, Avengers Endgame and 2019. Now, dictionaries are awesome,
02:23
Speaker A
don't get me wrong. They allow for efficient data retrieval based on their unique keys. They're flexible and easy to implement, but there's a potential problem with them. See, it's a challenge to ensure that the data is a
02:36
Speaker A
particular structure. And this could be a huge problem in larger projects. So to put things in simple words, it doesn't really check if the data is the correct data type or structure and that could be the source of a lot of logical
02:50
Speaker A
errors in your project. And if your project is really, really large, then this could be quite a headache to identify, right? Because it's quite a small detail. So what is the solution for this? Well, it's something called a type
03:03
Speaker A
dictionary. Now, here is an example on how you create a type dictionary in Python. And I just want to emphasize that this type annotation is used extensively in Langraph. This will be used to define states. Now don't worry,
03:18
Speaker A
we haven't covered states yet. We will cover that in the next section. But just be mindful that this is quite important. So a type dictionary is quite easy to implement. You implement it as a class. In this case, I've implemented
03:31
Speaker A
the same example I showed you in the previous section where I described the movie with the same exact keys and values. So, it still has the name and the year. But notice in this class, I have defined the actual data
03:46
Speaker A
type of what that key should be. So, for example, the name is a string and the year is an integer, right? And to initialize a dictionary, I have done the exact same thing to have Avengers Endgame in 2019. So now there are two main
04:01
Speaker A
benefits of using a type dictionary: it's type safety because we've explicitly defined what should be in this data structure and so this will really reduce the runtime errors and obviously the readability is enhanced as well and this will make debugging easier
04:17
Speaker A
if something goes wrong within this type dictionary. Cool. So we've covered type dictionary now. Now we move on to another type of annotation which is union. Now you might have seen these future, these later types annotations before if you coded in Python but again
04:34
Speaker A
I'm just giving you a high-level overview of what these are. So union, take a look at this example. So I've created a very simple function which takes in a value and it squares it. Now in this case the input x could be either an integer or
04:49
Speaker A
float and union basically says that whatever value you have can be these data types only. So in this case x can only be integer or float. So if I pass in five or 1.234 this would be completely fine. It would square the
05:03
Speaker A
number and everything. But if I passed in a string like "I am a string" it would completely fail. Now admittedly yes this function is quite easy. If I passed in "I'm a string," it would have failed anyway. But in more complicated
05:15
Speaker A
applications, hopefully you can see how this actually is useful. In fact, the makers of LangChain and Langraph used Union quite extensively throughout making the actual library. So again, it's flexible and it's easy to code and it allows for type safety. So because it
05:33
Speaker A
can provide hints to help catch incorrect usage. Now something similar to union is another type annotation which is optional. Now optional is quite similar and in this case I've described another function nice_message. So you pass in a name. If you pass in a name it
05:51
Speaker A
will say "Hi there, name." So for example, let the name be Bob. If I pass in Bob to this function it would say "Hi there, Bob." But what if I don't pass in anything? Now if I don't pass anything,
06:04
Speaker A
optional because I've used optional says that the name parameter could either be a string or a None value. Now if I pass in nothing it will go in this if statement and say "Hey random person." But this is also important to emphasize that
06:18
Speaker A
it cannot be anything else. It can't be an integer or a boolean or a float or anything like that. It has to be either a string or a None value because that's what I've defined here. Cool. Now comes
06:31
Speaker A
another type annotation called any. And any is really the easiest one to understand. It literally means this value could be anything. It could be any data structure. So in this case I've created a simple function called print_value where it takes in something
06:48
Speaker A
and it prints that. And for example I passed in this string and it prints it and anything and everything is allowed.
06:57
Speaker A
Cool. One last type annotation I promise and it's the lambda function. So lambda functions are quite useful. For example, in this I'll give you two examples now.
07:08
Speaker A
So the first example is this really simple example. Now we've already, I already created a square function before, right? Where it takes in a value, it takes in a number and it squares it. So for example, if I passed
07:20
Speaker A
in square 10, it would give me 100. Quite an easy example. Now let me give you a second example. This. So if you've come from a LeetCode background, then you've probably seen or you've either used lambda before and you've definitely used map
07:36
Speaker A
before because it's quite efficient. So for example, if I pass in 1, 2, 3, 4, what this piece of code is saying is that it squares each number in nums. So this map function maps each value and performs
07:49
Speaker A
this function to it. So x * x. So 1, 4, 9, 16 and then converts that back into a list. Now lambda functions really are just a shortcut to writing small functions and they make everything quite efficient. Now obviously this could have
08:05
Speaker A
been done in one line as well but for example this a beginner programmer could have might have used a for loop but a more advanced programmer could have used this and this is obviously much more efficient. Ri
08:19
Speaker A
start to see what how powerful these type annotations are and these will be coming up. So again, no need to memorize this. Just need to have a highle overview what they are. Okay, cool. So now I'll see you in the next section.
08:32
Speaker A
See you there. All right, perfect. So let's continue on. In this section, we will look at the different elements in Langraph. So let's begin with our first element, one of the most fundamental elements in all of Langraph, the state.
08:50
Speaker A
So what is a state? Well, it's a shared data structure that holds the current information or context of the entire application. In simpler terms, it is like the application's memory where it keeps track of the variables, the data
09:04
Speaker A
that nodes can access and modify as they execute. Now, don't worry if you don't understand what a node is yet. That is what we will be talking in the next slide about. But as a good analogy, think of the whiteboard in a meeting
09:17
Speaker A
room analogy. Now imagine you're in a meeting room and there are different participants as well and every time you come up with something new or you want to record some new uh information or update some information you write it on the
09:29
Speaker A
whiteboard. In this case the whiteboard acts as your state and the participants act as a node. So the state shows us the updated content/in information of your entire application. Hopefully that made a bit of sense.
09:47
Speaker A
So let's move on to the node another fundamental element in lang graph. So these are just individual functions or operations that perform specific tasks within the graph. So each of these node receives an input which is often just
10:01
Speaker A
the current state of your application. It processes it and then produces an output or an updated state. So here's a good analogy of this.
10:12
Speaker A
The assembly line station analogy. Now look at this image. Each of these station does one specific job. It could be attaching a part. It could be painting it. It could be inspecting the quality and so on and so on. The point
10:27
Speaker A
is each of these stations represent a node because they do one specific task. So how do you actually connect these different nodes together? Well, before we go into that, I think it's important we understand the most important element of them all, the
10:46
Speaker A
graph. It is so important that it's even in the name Langraph. So, the graph is just the overarching structure and it maps out how different tasks aka nodes are connected and executed. So it visually represents the workflow showing
11:04
Speaker A
the sequence and the conditional parts between various operations. Now a graph is quite self-explanatory but you can think of it as a road map. On a road map you can see it display the different routes connecting cities with the different
11:18
Speaker A
intersections offering choices on which path to take next. Now, here's a great image of what a graph is, and these are the individual nodes, but you'll see they're connected somehow. So, how are these connected?
11:32
Speaker A
That brings us to the next element, edges. So, edges are just the connection between nodes and these determine the flow of execution. So, they tell us or tell the application which node should be executed next after the current one
11:48
Speaker A
completes its task. A really good analogy of this is imagining a train track. So this is the train track and think of it as an edge and think of it as connecting two stations one here and one here which represent nodes together
12:03
Speaker A
in a specific direction. Now the train which will go on the train track that acts as your state. So the state gets updated from one station to another.
12:17
Speaker A
But there is another type of an edge and it's called a conditional edge. So this is still not very complicated. It's quite simple to understand. These are just specialized connections that decide the next node to be executed based on the specific
12:32
Speaker A
condition or logic applied to the current state. Now a really good analogy for this is the traffic light analogy.
12:40
Speaker A
So green could mean to go one way, red could mean to stop. yellow could mean to slow down. The point I'm trying to make here is that the condition, in this case the light color, it decides the next
12:52
Speaker A
step. If you want to think even more simply, you could think about an if else statement. So that being said, we move on to the next element, the start point.
13:04
Speaker A
So the start point or the node, the start node is a virtual entry point in langraph and this marks where the workflow begins. Now it's important to note that it doesn't perform any operations itself but it serves as the
13:17
Speaker A
designated starting position for the graph's execution. Now in terms of analogy it is quite simple to understand but if you really want think of it as the starting line of race. Now if you have a start point well
13:32
Speaker A
you need an end point as well and that's where the end element comes in. So the end nodes just signifies the conclusion of the workflow in Langraph. So when the application reaches this node, the graph's execution completely stops and
13:47
Speaker A
it indicates that all intended processes have been completed. And again, a good analogy for this is just the finish line in a race. So nothing too hard yet. But now let's look at tools. So tools are specialized functions or utilities that nodes can
14:07
Speaker A
utilize to perform specific tasks. For example, it could be fetching data from an API. They basically enhance the capabilities of these nodes by providing additional functionalities. Now, one common question could be, well, what's the difference between a tool and a node?
14:23
Speaker A
The node is just the part of the graph structure. Whereas the tools, these guys are functionalities used within the nodes. Now, a really good analogy for this is just tools in a toolbox. So imagine a hammer for the nails, a
14:39
Speaker A
screwdriver for the screws, etc. The point is each tool has a distinct purpose. Again, don't worry. You will understand the differentiation between tools and nodes in a lot more detail later when we code this, but this is just for a general
14:54
Speaker A
overview. Now, another question you could be asking is, is there a middleman between a tool and a node? Short answer is yes. That's where tool node comes in.
15:05
Speaker A
So a tool node is just a special kind of a node whose main job is to run a tool. So for example, a tool node could be a node where its only job is to use a tool and that tool's job is to fetch
15:21
Speaker A
some data from an API. So it connects the tools output back into the state so other nodes can use that information.
15:31
Speaker A
So think about this analogy going back to the assembly line. In this case, imagine the operator as the tool node and it controls the machine which is the tool and then sends all of these results back into this assembly
15:47
Speaker A
line. Now if we progress further, let's look at the state graph. So this is quite an important element as well. This will be one of the first elements you actually interact with and its main purpose is to build and compile the
16:01
Speaker A
graph structure. So it's quite important. It manages the nodes, the edges, the overall state and it makes sure that the workflow operates in a unified way and all of the data flows correctly between components. So again it's quite an important element. You can
16:18
Speaker A
think about it as a blueprint of a building. So just as a blueprint outlines the design and the connections within a building, the state graph does exactly that, but it just defines the structure and the flow of your workflow
16:32
Speaker A
or application. Now here's where the runnable comes in. Now some of you will be coming from a lang chain background and runnable is quite common there and it's quite similar in langraph as well.
16:47
Speaker A
A runnable in langraph is just the standardized executable component that performs a specific task within an AI workflow. It basically acts as a fundamental building block allowing for us to create these modular systems. Now a question you could have
17:03
Speaker A
right now is well what's the difference between a runnable and a node? Short answer is a runnable can represent various operations whereas a node in lang lang graph typically receives a state performs an action on them and then updates the state. Now don't worry
17:22
Speaker A
if you didn't 100% get that when we go into the coding section you will get it a lot better. But a good analogy is a Lego brick. So just as how Lego bricks can be snapped together to build these
17:35
Speaker A
complicated structures, runnables can be combined to create sophisticated AI workflows. So now let's move on to the different types of messages. Now again, if you come from a lang chain background, you'll be quite familiar with these. If you haven't,
17:51
Speaker A
don't worry. We will look at the five most common message types in Langraph. So to start off, there's the human message which represents the input from a user. The AI message which represents responses generated by AI models. The
18:06
Speaker A
system message which is used to provide instructions or context to the model. Tool message which is similar to the function message but specific to tool usage. And the function message represents the tool of a function call.
18:20
Speaker A
If you've used an API like a large language model API before, such as OpenAI's API, a lot of these will be quite familiar, especially the system message, the AI message, and the human message. And that concludes this section. So, I will see you in the next
18:39
Speaker A
section. Awesome. So, now this is quite exciting. We're actually about to start coding in Langra for the very first time. Now that we've covered all the theory, admittedly the boring section, we're now actually going to code up some
18:52
Speaker A
graphs. And we're about to code up our very first graph in this sub section.
18:56
Speaker A
But um for this overall section, I have a slight confession to make, which is we're not going to be building any AI agents in this section. Why? because I thought that one we haven't really even seen uh how to
19:11
Speaker A
actually code in Langraph and combining all of these LLMs APIs and tools and all of that stuff which comes with it combining them together would be quite messy and it could be quite confusing at times especially the fact that we have
19:24
Speaker A
never coded in Langraph before again like I said at the beginning of the course this course is supposed to be beginner friendly detailed and comprehensive and we're going to go in steps like little by little so hopefully understand but don't worry we will be
19:38
Speaker A
coding AI agents soon we're just going to be building a couple of graphs right now uh understand lang graph better the syntax better and how to actually code up graphs and get confident with it and then we will actually build AI agents
19:51
Speaker A
okay cool so what is the graph which we're going to be building together in this section I call it the uh hello world graph mainly because it's the most basic form of graph we can actually code in lang graph so the objectives are
20:05
Speaker A
these So we're going to be understanding and defining the agent state structure and don't worry you'll understand what that is in a few minutes and we're going to be creating simple node functions nodes like we discussed in the previous
20:19
Speaker A
section uh and we're going to be processing them and updating the state. We're going to be building the first ever basic langraph structure and we will understand how to compile it, invoke it, process it, everything. And really the main goal of this section is
20:35
Speaker A
to really understand how data flows through a single node in langraph. Now just to give you a bit of a heads up as to what we'll actually be covering uh what we're going to be building I should say is this graph. Again like I said
20:50
Speaker A
this is the most basic form of graph you can build in langraph. It has a start point and an end point and this node sandwiched in between them. All right cool. So hopefully you've understood what the objectives are. It's quite
21:03
Speaker A
basic and yeah, I'll see you at the code. Okay, cool. Now let's actually code this very first graph. So I've imported three main things here. The dict, the type dict and the state graph.
21:19
Speaker A
The dict and type dict is obviously dictionary and type dictionary but um and state graph. These three are elements which we covered in the previous section. So I would highly recommend you going back there if these are completely unfamiliar. But again you
21:33
Speaker A
don't need to memorize what these are. Okay. But just to refresh your memory I've written in the comment here what the state graph is. So think of the state graph as a framework that helps you design and manage the flow of the
21:45
Speaker A
tasks in your application. Um again that might sound a bit complicated but it's not. Once we actually start coding you will it'll make more sense. So now the first thing we're going to do after importing everything is create the state
22:01
Speaker A
of our agent and let's call it agent state. And just to refresh your memory again what the state is. Think of the state as a shared data structure. And this keeps track of the your all of the information as the application runs. All
22:16
Speaker A
right cool. So now let's build the agent state. And the way we do this in Langraph is through a class. So let's build class agent state and in this in these parenthesis we will try to the the state needs to be in the form of a typed
22:33
Speaker A
dictionary. So that's why we specify type dictionary here. Now let's keep this very very fundamental and basic.
22:41
Speaker A
Let's just pass in one input. Let's call it something like message and obviously we put colon and the we specify the data type of that uh attribute. Now obviously the data type of message will be string right so
23:00
Speaker A
that's why we specify strl again this is just normal python so once we've done that we are now going to be coding our very first node again another very fundamental element in langraph so how do we actually define a node it's quite
23:17
Speaker A
simple it's just a normal standard python function and this is how you do it so let's say let's first try to find The objective um let's say we are trying to let's a greeting message a simple greeting message. So we'll write def
23:35
Speaker A
greeting node and we need to pass in an input and pass what the output type should be. Now the input type of a node needs to be the state and the output type also has to be the state because
23:49
Speaker A
remember the state keeps track of all of the information in your application right so obviously you need to pass that as an input and you need to pass out the or return the updated state. So here's how you do it. You pass in state and
24:05
Speaker A
what is the state of our application? Well, it's the agent state which we defined earlier, right? And the output is going to be agent state cuz we need to output the updated state. And our updated state will again just be the
24:18
Speaker A
agent state once we've done all of the um all of the mechanics we do in this function, the actions we perform in this function. All right. Okay. So now we need to do something very very important and it gets annoying sometimes but um
24:34
Speaker A
it's really a key habit which I want you to form and it is dog strings. Now dock strings and lang graph is quite important. Why? Because dock strings is what will tell your AI agents when we actually build the AI agents your LLMs
24:49
Speaker A
what that function actually does what that function's actions are what it performs. So in this case uh by the way to create a dock string is just three quotation marks three pairs of quotation marks. Uh let's call the dock string in
25:03
Speaker A
this case let's just write simple node that adds a greeting message to the state. Perfect. So now how do we actually refer to this message? Well again this is just normal Python code.
25:19
Speaker A
So we will pass in state and we will type in message. Now this specific part allows us to actually update the state or the message part of the state. And let's say let's come up with something like hey
25:37
Speaker A
plus state message. Um we can also add something like how is your day going something basic. Now what's the last thing which I need to do in this function? Think about it. Okay. So now remember in uh a few
25:56
Speaker A
moments ago I said we have to return the state or the updated state. Well the updated state we've already done we've just manipulated the state here. So all we have to do is just simply return the state. Cool. And yeah that runs without
26:10
Speaker A
any errors. Okay. Now let's actually build the graph uh which is again obviously very important. So how do we build the graph? Remember here I said state graph is a framework that helps us design and manage the flow of tasks as a
26:25
Speaker A
graph. Well that's exactly what we're about to do now. So hopefully it clicks now. So to create a graph in lang graph you use the state graph attribute and you pass in your state. You can see the state schema which VS code has uh asked
26:40
Speaker A
for what uh the description of what the parameters are. So our state schema in this case is just the agent state which we define right. So we pass an agent state. I will actually also write here our state
26:55
Speaker A
schema. So uh you can physically see what it is. Okay. And let's store this in a variable called graph or something. Okay. Now now here comes a very important method. How do we actually add a node to this graph?
27:12
Speaker A
Cuz this graph is completely like nothing right now. So to add a node we use the inbuilt function graph add node and it requires two main parameters. Now what VS code is suggesting is a god I don't even know what that all of all of
27:27
Speaker A
that is right it's very confusing. So to put things simply you require really two uh parameters the name of your node and what action it will perform. So let's go with the name. The name could be absolutely anything sensible of course.
27:43
Speaker A
Um let's call something like greeter. Cool. And you can see VS Code has also asked us to um input an action.
27:53
Speaker A
Now what's the action going to be? Well, the action will just be whatever your node will actually perform. And what action or mechanics will this node actually perform? Well, all of that is defined by this function, right? The
28:07
Speaker A
greeting node function. So we simply just put that the name of the greeting node function here and that's it. We've successfully added the greeting node to our function to our graph and it will be named as greater. So remember this
28:27
Speaker A
diagram in this diagram there is supposed to be a start and an end point.
28:32
Speaker A
We've done the node which is sandwiched in between these but we haven't really added the start and the end point yet.
28:38
Speaker A
So, how do we do that? Well, there's actually multiple ways to do that. In this subsection, in this graph, I'm going to teach you one way. Further down the line, I'll teach you another way.
28:47
Speaker A
So, but they're both they're quite easy. So, you simply just call the inbuilt function set entry point and as the parameter is just one parameter which is the key. Now, the key is the name of your node which you want
29:02
Speaker A
the start node to connect to. Again, visualize it. The start the start point is here and the node is here. Obviously you need to reference a node for it to create like an edge right. So we simply pass greater and similarly graph dot set
29:18
Speaker A
finish point. We will again pass greater here as well. Why? Because imagine again the node is here and your finish point is here and you need to connect some sort of connection between these two right and that's why we use uh greater
29:31
Speaker A
in this case. Don't worry, you will solidify this once you complete the exercises and as we go down building more graphs. All right. And one last thing which we need to do is actually compile this graph. So graph compile
29:43
Speaker A
using the inbuilt uh graph using the inbuilt compile function. And let's just store this in a variable. Cool. So that run without any errors. But just a word of caution here.
29:54
Speaker A
Just because the graph compiles without any error doesn't mean it will successfully run. I mean, God knows once we build like more complicated graphs, there could be so many logical errors.
30:04
Speaker A
So, that's just an important thing to know. So, don't get too happy once it compiles cuz there might be logical errors. Trust me, I know. Okay.
30:15
Speaker A
So, I want to write some code which will actually help you visualize this. And you can use the IPython library. So, you can use this uh this um piece of code here.
30:28
Speaker A
This code is awfully familiar with the first ever graph I showed you, right? I I'll put a picture somewhere here for you to compare. The only difference is really the name of the node which we've set. In this case, it's greater. Why is
30:41
Speaker A
it greater? Because that's the name we gave to this node, right? Cool. So that's looks pretty good. Let's actually run this. So to run you use the inbuilt method invoke. Um so let's pass in the message as something like Bob or something and
31:05
Speaker A
let's actually store this result in a variable. Okay. Now how can we actually specify uh how can we actually get the value of result?
31:19
Speaker A
So result we need to actually reference a certain attribute. Now the only attribute we have in uh the entire graph is message right. So we simply just put message and perfect you we get the final answer which is hey Bob how's your day
31:35
Speaker A
going now why is it like this because this is exactly how we set our act how we set our function to be what action it performs it says hey then concatenates the uh input message in this case it's
31:47
Speaker A
just the name and it says how's your day going now I could have changed this to absolutely anything else right uh what goes here like these functions are almost endless but That's the whole flow of how everything works. So hopefully
32:04
Speaker A
you understood how to build this very first hello world graph. It's quite simple. But um don't worry if you didn't fully 100% understand this. I'm now going to show you what exercise you need to complete uh to be able to solidify
32:18
Speaker A
this. All right. All right. I'll see you at the exercise. Okay. So time for your very first exercise. So the exercise for this graph is quite similar to what we just did, but I want you to create a
32:32
Speaker A
personalized compliment agent. So you should pass in your name as like something like Bob or something and then output something like Bob, you're doing an amazing job learning langraph. And to give you a hint as to what you need to
32:47
Speaker A
do again, you again have to concatenate the state, not replace it. All right, it's very similar to what we just did and it's quite basic. You should be able to do this, but um this is really just to get your hands dirty. All right.
33:00
Speaker A
Okay. Once you've completed this exercise, join me when we build the second graph. I'll see you there. Okay. So now we're about to build our second graph as you can see here.
33:13
Speaker A
And it's again quite similar to the first graph we built except now we're going to be able to pass multiple inputs as you can see here. So again, what are the objectives which you will be learning in this? Well, we're going to
33:26
Speaker A
build a more complicated agent state. Uh, and we're going to be creating a processing node that performs operations on list data. So now we're about to see how we can really work with different data types apart from just string. And
33:40
Speaker A
we're going to set up the entire graph that processes and outputs these and computes these results. And we're going to be able to invoke the graph with the structured inputs and retrieve the outputs. But the main goal which uh I
33:53
Speaker A
want you to be able to learn in this specific subsection is really how to handle multiple inputs. All right. Okay.
34:01
Speaker A
Let's code this. Okay. So now let's actually code the second graph up the second application up. So again I've just imported the same things again the type dictionary and the state graph. And I've also imported the list this time. But
34:15
Speaker A
list is just a simple data structure which you should know already. So if you remember from the previous graph we made we are supposed to uh implement the state schema first right. So how do we do that? Again we use the class agent
34:30
Speaker A
state uh type dictionary. Okay before I continue just a heads up I could have named the state schema anything I want. I could have named it uh something arbitrary completely like a bottle for example. In this case I've just said agent state
34:46
Speaker A
because one that's how I learned it. It's like a habit for me now. But it also really tells you what it actually is. It's the state of your agent, right?
34:54
Speaker A
So that's why I've just kept it like that. But again, just a heads up, you could have named this whatever you want.
34:59
Speaker A
Cool. Okay. So now let's the if you remember the main goal for this graph for this uh building this graph was to be able to handle and process multiple different inputs, right? So how do we actually assign and I really do that?
35:17
Speaker A
Well, the answer is in the state which is here's what uh which is what we're about to do now. So you really cuz remember this is just a type dictionary.
35:26
Speaker A
So you basically have multiple keys now you uh create that. So let's say something like values list integers.
35:37
Speaker A
So let's say one of our input is a list of integers and let's also pass in a name which will obviously be in a string and let's have the result in a string something completely random. But now you
35:53
Speaker A
can see we're now operating on two different types of data structures uh a a list of integers and a string. And we're handling three different uh different uh uh inputs values name result. Okay cool. So let's run this.
36:09
Speaker A
Perfect. So now let's actually build our node because in again in this uh graph we're just going to have a single node to keep things easy. Remember step by step. So let's call let's write dev process values and again what was what
36:24
Speaker A
needs to be here? Yeah. So we need to pass in the state and we need to return the updated state. So how do we do that? Well, we write state agent state and we pass out the agent state. Cool. Now, again,
36:41
Speaker A
building healthy habits. I know it's annoying. We have to write the dog string. So, let's just write something like this function process handles multiple different value in multiple different inputs. Cool. Again, I'm not being super specific here because one, uh, I don't
37:03
Speaker A
want to spend too long on writing doctrines and everything, and two, there's no AI or LLM here, right? So that's why it doesn't really matter. I'm just doing this to build healthy habits.
37:12
Speaker A
Okay, so now let's do something like whatever values we pass the list of integers. Let's sum them up. And let's also concatenate the name as well and store it in the result. Sound cool?
37:24
Speaker A
Okay, so how do we do that? We pass in state result cuz that's what we are uh the action we're performing is on result uh the attribute result and let's say something like hi there and then we refer to the name
37:41
Speaker A
um cool and your sum is equal to and let's just use the inbuilt Python function sum and we pass state values cool and lastly we obviously return the Okay, perfect. And that's that done.
38:00
Speaker A
Okay, so now we actually create the graph. Again, this is going to be very very similar to what we did in the previous section because again there's just a node, there's a start point and an endpoint. So like last time, we use
38:14
Speaker A
the state graph to initialize a graph and we pass in our state schema. So agent state and let's store this in the variable graph. Okay. Uh let's add our node. So graph add node and again remember it requires two
38:30
Speaker A
parameters. It requires the name and the action. So in this case the name will be let's call it processor for example.
38:38
Speaker A
Again this could be anything you want and your action will be performed by this function right process values. So we can just add that. Okay. Now I've already told you how to uh how to initialize a start point and an end
38:52
Speaker A
point and this is just given by that code. So you attach your entry point to your node. In this case it's just one node which is the processor node and again same goes with finish and you compile it using
39:06
Speaker A
graph.compile. Perfect. So take a moment now. How do you think this graph will look like? That again like I said very very similar on how the graph actually looks like but the only difference now is the name of the uh node which we've kept
39:27
Speaker A
this as processor. Okay. So now let's actually test this. Let's actually invoke this graph. So how do we do that?
39:35
Speaker A
Well, we use the invoke function. Now here's another important part which is quite a common mistake especially like I have done this many times. Make sure to store your compiled graph in a variable cuz if you invoke the graph i.e. if you
39:50
Speaker A
write something like graph.invoke that won't make sense cuz you haven't compiled the graph. That's why you need to uh invoke using app. That's why I've also done app here. If I did graph get graph. Oh, it's completely messed up.
40:06
Speaker A
Right? It says state graph object has no attribute because your graph hasn't been compiled yet. That's why when I do appget graph the uh process works. Cool.
40:16
Speaker A
So now let's again store this in uh let's store something like answers is equal to app.invoke. Cool. Let's pass in some values. Let's say something like values and let's have a list of integers. 1 2 3 4. Again, I'm just
40:36
Speaker A
trying to prove a point. I'm not trying to make a very complicated um graph yet.
40:40
Speaker A
And let's pass the name as something like Steve something. Okay. Uh cool. And let's print let's print answers. Let's see what happens. Perfect. So now you can see your values is 1 2 3 4. Your name is Steve. And your result is Hi there
41:01
Speaker A
Steve. Your sum is equal to 10. Again, why? because that's exactly what we uh asked the node the action to perform. Hi there, your name which in this case is Steve. Your sum is equal to the sum of
41:13
Speaker A
the values and 1 + 2 + 3 + 4 is 10. Right? And that's how you get this answer. Now what if I wanted to just access result? I didn't want any of this other uh nonsense. Well to do that you can again
41:29
Speaker A
just specify result and you will get it in a more clean manner. Cool. Okay. Now I want to try one more thing just to build your understanding a bit more. Uh let's put some print statements here. So let's have a print
41:48
Speaker A
state here. Then we perform the action and then we print the state here. This is really just to show you how the state gets updated and it should be easy like interpretable cuz this is quite a basic piece of code. Again, print stated
42:04
Speaker A
before the action and print state after. So there cool and here you go. So value is equal to 1 2 3 4 name is equal to Steve and these are the inputs we passed. Now notice I didn't pass results as an input
42:20
Speaker A
as well. I could have uh done that but Langraph automatically sets that as like a a none value in this case if you don't pass an input. Now here's where you need to be cautious. If I had actually used state
42:36
Speaker A
result here as well to uh update state result like I used state result to update either itself or something else then you would run into a problem because your state result has been initialized as none because you didn't
42:49
Speaker A
pass it as an input. So be mindful of that. But in this case it worked because we're only assigning state result. We're not using it to assign something. It's getting assigned. Cool. And you can see after the action has been performed uh
43:06
Speaker A
your operation has been performed and the thing has been concatenated. You can see result is here and that was exactly what we were getting before we cleaned this up. Cool. So hopefully you understood that. Again it should have
43:19
Speaker A
been quite intuitive and interpretable but um to solidify your understanding even more complete the exercise. So I'll see you at the exercise then. Okay. Welcome to the exercise, your second ever exercise. And for this exercise, I want you to create a graph
43:37
Speaker A
which passes in a single list of integers along with a name and uh an operation this time. And if the operation is a plus, you add the elements. And if a well times, you multiply all the elements all within the
43:54
Speaker A
same node. So don't create an extra node yet. So for example your input should could be jack sparrow your values 1 2 3 4 again and then your operation uh uh multiplication and your output should be in the format of hi jack sparrow your
44:08
Speaker A
answer is 24 so just to give you a hint as to how you would perform something like this uh you would need an if statement in your node so slightly more complicated but the whole concept is the same so once you've completed this
44:22
Speaker A
exercise I will see you in when where we build this third graph All right, see you there. Okay, welcome to your third graph. So, what are we going to do this time? Well, enough processing multiple values and everything. Let's actually
44:41
Speaker A
get the graph more complicated. So, that's why we're going to be building a sequential graph. So, all it all that basically means is we're going to be creating and handling multiple nodes that can sequentially process and update different parts of the state. So we will
44:56
Speaker A
learn how to connect nodes together in a graph through edges of course and we're going to invoke the graph and really see how the state gets transformed as we uh progress through our graphs step by step. So again your main goal is should
45:10
Speaker A
be to understand how to create and handle multiple nodes in langraph. Sounds cool. Okay I'll see you at the code. Cool. So now we're about to code up the third graph. Uh, and we're making quite fast progress. So well done on
45:27
Speaker A
that. So again, the imports are the same. State graph and type dictionary. Perfect. And like we've done in the previous two graphs, we're going to be coding the uh the state schema or the agent state first. So let's have class agent state.
45:47
Speaker A
And again, it needs to be in the form of a typed dictionary, right? And in this case, let's have the three attributes as all strings because we've already we already know how to handle multiple data types, right? So, let's keep it simple.
46:00
Speaker A
Name string, age string, and final string. Okay. Now, here's what we're going to build. Now, we're about to build our two node functions, uh, which are again the actions. Okay.
46:17
Speaker A
So again you simply write first well I'll name it first node in this case and like I mentioned before we pass in the state and we return the updated state.
46:30
Speaker A
Okay. So again healthy habits doc string again. So this is the first node of our sequence. Okay. And what do we want to do in this specific node? Well, I really just want to manipulate uh the final part. So, let's say something like
46:51
Speaker A
state final is equal to state or let's have an f string f state name.
47:06
Speaker A
Let's say something like hi that. Cool. And we'll just return the state. Perfect. And now again we create a new node. So state agent state. Return that. Perfect.
47:24
Speaker A
And I'm just going to copy this dock string and just change it. This is the second nerf. Perfect. Okay. To speed things up. And in this case I also want to have state final is equal to you are
47:43
Speaker A
state age years old. Again quite a simple example easy to follow. That's why I've kept it as quite a basic graph. I mean it's not going to solve the world's problems or anything but it will help you understand.
48:01
Speaker A
There is one logical error which I've put deliberately here. I want you to try to identify it. Okay. So the logical error in this case is the that once we've built our graph and everything what would have happened is we would have said hi to
48:24
Speaker A
whoever uh we pass in let's say Charlie or something. So, hi Charlie. And we store that in the final uh attribute in the state, which is what we want. But here's where things get like start to be well logically incorrect. Once we
48:39
Speaker A
finally get to our second node, again, we're updating state final, which you can do. You can repeat, you can um interact with these attributes at in in any node possible in all of the nodes.
48:53
Speaker A
And you can do it as many times as you want. But notice this part. What's happening here is we've completely replaced all of the content we had before. So remember how we had hi Charlie? We've just completely replaced
49:06
Speaker A
it with you are age years old. But we want both of them both of those stuff, right? So how do we get both of them?
49:15
Speaker A
Well, again we just concatenate them. So we can have something like state plus state file. And there we go.
49:25
Speaker A
Logical error should be now solved, right? Cuz now we have concatenated state final. Uh we're essentially just like adding on to uh we're preserving what we had before, right? Okay. Now let's get to the fun part. How do we
49:41
Speaker A
actually build this graph? And really it's quite similar to the previous two graphs except there is one new thing which you're about to learn. So like always we use state graph to start the framework. So agent state and let's
49:56
Speaker A
store it in graph. Again I could have had this name the width variable into anything. I've just kept it graph cuz it makes intuitive sense. Okay. Now we add our nodes. So we do graph add node. And for
50:12
Speaker A
simplicity sake I'm just going to have the name as the same name as the uh function. Okay. So that way it'll just be easy to follow. So graph add node and second node. Second node. Cool. Okay. Now that
50:32
Speaker A
we've added both nodes, we need to obviously s uh add the entry point and the end point, right? So we set the entry point like this. Again, quite self-explanatory because we wanted to connect to the first node, not the
50:46
Speaker A
second node, right? So it should be start uh first node, second node, end point. How do we connect the first node and the second node together though? Hopefully you had an answer for that. Uh if you remember or recall from
51:04
Speaker A
the previous section, theory section, there was an element in Langro called the edge. That's exactly what we're about to do right now. We're about to use edge and that was the new thing which I was talking about a few moments
51:15
Speaker A
ago which you're about to learn. So how do we use it? Well you use graph edge add edge and if we can hi perfect. So again it's quite simple you use a start key and end key. So sim similar to entry
51:30
Speaker A
point where but your in this case you need to pass two parameters. So the edge we want is between the first node and the second node right? Well that's exactly what we pass here. So first node and second node and like before we will
51:48
Speaker A
just set the finish point at second node and we will compile this. Now how will this graph look like? Take a moment to try to think of how it will look like like that. Start point end point and these two notes are sandwiched in
52:08
Speaker A
between. But now there is a edge. It should be called a directed edge if I'm being like quite picky. But yes, a directed edge cuz the flow of data or your flow of your state updates is from the first node to your second
52:22
Speaker A
node. Right? Cool. So now that we've built that, let's again invoke this. So I've got this code ready here. Uh let's invoke it. Let's pass the parameter as Charlie and let's pass the age as 20.
52:38
Speaker A
Cool. Print result. Perfect. Apart from the uh misalignment here which I can just change right now. Perfect. Okay. So now you can see it says hi Charlie you are 20 years old.
52:52
Speaker A
Now obviously we could have performed all of this in one single node which we have been doing in the previous subsection but the obviously the aim was to be able to create multiple nodes right and handle um the state how the
53:06
Speaker A
state progresses. So yes you one important thing which you've learned is obviously how to use the add edge method but another concept which you have solidified here is you can uh change these at these keys of your state at in
53:23
Speaker A
at any point in time like as long as as however many times you want cuz remember here we've passed in state final um we implemented state final here we implemented state final in the second node if we had more nodes in the
53:37
Speaker A
sequence. We could have done that again and again and again. And we also learned how to like one key logical error is sometimes a lot of people just accidentally replace uh their content in one of the attributes and that leads to
53:51
Speaker A
a lot of logical errors. So always be mindful of that. And yeah, that again was quite simple, not too hard and hopefully the exercise which I'm about to give you solidifies this. Cool. So I will see you at the exercise then.
54:06
Speaker A
Awesome. So now we will move on to the exercise for this third graph. And what I want you to do is really build on top of what we just covered. Instead of two nodes, I want you to build three nodes.
54:20
Speaker A
Again, in a sequence, don't need to go too fancy yet. We will again three nodes in a sequence. And we will have you will need to accept the user's name, their age, and a list of their skills. So the
54:34
Speaker A
first node will be specifically for personalizing the name field with a greeting. The second node will be describing the user's age. The third node will be listing all of the user skill in a formatted string. And then you'll need to combine this and uh store
54:49
Speaker A
it in a result field and output that. And this should be a combined message.
54:53
Speaker A
And the format I would like you to output is something like this. So let's say the name was Linda. And let's say Linda welcome to the system. You are 31 years old and you have skills in Python, machine learning and langraph. Okay. And
55:10
Speaker A
just as a hint for this exercise, I would you'll need to use the add edge method twice. So this will really solidify your understanding on how to build graphs in general. All right, cool. So once you've done that, again,
55:24
Speaker A
answers will be on GitHub for all of the exercises. Once you have uh cross referenced and checked that you've done it right, I will see you in the next section where we build our fourth graph.
55:35
Speaker A
All right, see you there. Welcome, welcome, welcome. Okay, I'm particularly excited for uh teaching you this graph, graph 4. Why? Because we're about to learn how to build a conditional graph. So for the very first time, we're about to implement
55:51
Speaker A
conditional logic. And obviously we've done it in a previous exercise before but that was within a single node. This is how to implement conditional logic in the overall graph structure. And so we will be implementing conditional logic to route the uh flow of data to
56:07
Speaker A
different nodes. We will be using the start and the end nodes to manage entry and exit points. We will be designing again using multiple nodes to perform different operations such as addition and subtraction. And we will be able to
56:21
Speaker A
create a router node to handle decision-m and control the graph flow. So the main goal is really to you how we can use this inbuilt function which uh allows you to create conditional edges in langraph. All right, exciting stuff.
56:35
Speaker A
I'll see you at the code. Okay, so let's actually code this up now and you'll see the imports are slightly modified this time. Again, type dictionary and state graph is there. But now I've also imported start and end
56:51
Speaker A
point. Again, if you remember a few subsections ago, I told you there are multiple ways to be able to initialize the start and the end point. And this is another way you could. Arguably, this is the easier way, but um whatever. I don't
57:06
Speaker A
really have a preference, but I'll teach you both ways regardless. Okay, let's import these. Successful. Okay. like standard procedure we will design we will um code up the uh the schema the state schema so class agent state and
57:23
Speaker A
let's again type dictionary in this case uh uh I want to be able to pass in two numbers and pass in an operation so a plus operation and a minus operation one of those two operations now obviously I
57:38
Speaker A
could have handled uh all of this within one single node But that's not the point here. I've kept it deliberately very very simple. So the main concept which you learn is how to uh implement conditional logic. Okay.
57:54
Speaker A
So let's code the different uh keys which we require. So number one will be an integer. Operation will be in the string a plus or a minus. Uh number two will be an integer and final number will be an integer. the final number will be
58:10
Speaker A
the result of either adding or subtracting the two numbers. Easy enough. We've done this multiple times now. Okay. Now, here's where things get interesting. Now, just a heads up. Initially, this won't make sense. But when we look at it from a
58:27
Speaker A
bird's eye view and we look back at all the code in this subsection again, uh everything will start to click. So again, it won't make sense initially, but it will once we look at it. Uh again, don't worry. All right. So let's
58:41
Speaker A
create our first node function. Let's call it adder. And it's again still a node. And we input the state schema. And we return the updated state schema and dock string again. But uh this time I'm just going to copy it from here. Uh it's
59:00
Speaker A
tells exactly what it does. This node adds the two numbers. Uh and easy enough, we just do state final number is equal to state uh number one plus state number two. Okay. And we just return the state. Quite simple, right? And just
59:20
Speaker A
like what we did with the addition, we need a node for subtraction as well. So def subtractor. Now uh I already implemented it to uh don't to not waste time but this node subtracts the two numbers. It's very similar to the
59:37
Speaker A
previous uh node function. Uh it just subtracts these two numbers. Again yes you could be saying what if number one is uh smaller than number two it'll give you a negative result. It that doesn't matter. The main aim again was to
59:51
Speaker A
implement the conditional logic not the um inner workings of each node. Okay. Okay. Now we built another type of node.
60:01
Speaker A
Uh and we initialize it the same way but this time let's call this node decide next node. Let's actually give it a name which actually says what it does. Right.
60:12
Speaker A
So again we use state agent state and we pass like this. Perfect. Okay. Now the dock string will be something like so.
60:23
Speaker A
So this node will select the next phase of the graph or well next node of the graph I should say.
60:30
Speaker A
Okay. Now we use an if statement and before I code something let's just try to map how this will work. This specific node will be at the start of our uh graph. So we will have the start node.
60:44
Speaker A
We will have this uh this specific node we'll call it the router. and this router because it routes uh the next uh to the next node depending on what the state schema is at that point. So we will have the uh I will put an image up
61:00
Speaker A
right now so you kind of get what I'm trying to say but we essentially will have the router decide whether we uh add the two numbers and subtract the two numbers and obviously this will be decided with the operation uh attribute
61:14
Speaker A
right which you should see from here. Okay, let's code this up now. So this is not the hard part. If state operation, if I can spell if state operation is equal to equal to plus. Okay, if state operation is equal
61:34
Speaker A
to equal to plus, we need to do a certain thing to pass it to the next node. Okay, now here's well your first guess could be okay. Well, we guess I guess just call this function, right? Not exactly. Not
61:50
Speaker A
in langraph. You actually return uh return the edge. Now, we haven't described the edge yet, right? But for now, I will just say the edg's name is addition operation. So, addition operation. Similarly, if it's subtraction, we will do this like so. So
62:12
Speaker A
just to reiterate we will uh you we will see what the um value is at the operation in the state schema. If it's a plus we call we will return the edge addition operation and if it's a subtraction we will use the subtraction
62:28
Speaker A
operation edge. Again we haven't described or defined these two edges yet. That's what I was saying earlier.
62:34
Speaker A
When we look at it from the bird's eye view later on in a few moments once we've built everything it will make much more sense. So stick with me for now.
62:43
Speaker A
Okay. And runs perfect. Now we build the graph. And now here's the exciting part.
62:50
Speaker A
So we again like normal standard procedure we use state graph to create the graph framework. So graph is equal to that. And let's add these nodes uh to the uh to our graph. So graph add node and let's say
63:12
Speaker A
router. Okay. And again we will pass this decide next node. Perfect. Okay. Now I have another confession to make. Lots of conventions. I know this won't work. I know I haven't built the rest of the graph yet but this
63:31
Speaker A
eventually will not work. And there is a subtle reason why this won't work. You know, it's mainly in this line. Add node router decide next node. The problem is with decide next node cuz oh, you can see that the dock string appears once we
63:50
Speaker A
press uh the decide next node. But the reason this won't work is look closely at these three functions. What are we doing in these two functions that we're not doing in this?
64:02
Speaker A
I'll give you a moment to try to analyze this. Okay. So, doesn't matter if don't worry if you didn't get that. The correct answer is we are returning this updated state in this one and this one.
64:22
Speaker A
But in this node, we're not. We're just returning the edge. Subtle difference I know but that's how Lang graph works and you will see why they do it like that uh right now. So how do we deal with
64:37
Speaker A
this? Now I obviously could have built this graph and then I would have shown you the error but then things would have just gotten messy. That's why from the get- go I have told you why this wouldn't work. So now that you know why
64:48
Speaker A
this won't work, how do you fix this? Simple. You use this code lambda state. Now, if you have used lambda functions before, this is quite easy to understand. If you haven't, don't worry.
65:01
Speaker A
All this is saying is your input state will be your output state. That's it. In even more simpler words, think of this as a pass through function. So, what it's saying is your input state will be passed, your state
65:18
Speaker A
will be inputed and your output will be the exact same state. Now, why is it the exact same state? because you're not changing the state at all. You're comparing stuff here, but you're not assigning anything. There's a difference
65:33
Speaker A
between comparison and um and assignment. Right? Again, even in this one, you're just comparing to see whether the operation is a minus, but no assignments been made at all. In fact, there's been no changes to this state whatsoever. That's why we can use this
65:50
Speaker A
as a pass through function. Now, hopefully that made sense. Okay, let's continue. Again, we will get a lot more practice. Don't worry, this is the first time you're seeing this.
66:02
Speaker A
Okay, so now we will add the edge. And this is just the normal edge we did last time. So, we will need the start key.
66:09
Speaker A
And now here's how you initialize differently. Remember how we used to do set entry point and set finish point? We don't do that anymore. Uh we use start the keyword cuz that's what we imported.
66:22
Speaker A
Make sure to import it if you do it this way. uh you use start and end. So your start will be a start point and your what do you want the start to be connected to? Well, we want it to be
66:33
Speaker A
connected to the router. If I put this in quotation marks, perfect. Now, why not add node or subtract node? Well, think again. Refer back to that diagram which I'll show in right here.
66:46
Speaker A
We if we connected the start point to the the add node or the subtract node, well then what's the point of the router in the first place, right? The whole point was the router decides what the inputs are and then from there it
66:59
Speaker A
branches off to the correct node. So that's why the router needs to be the first node we uh connect our start point to. Cool.
67:08
Speaker A
Okay. Perfect. Now we add the we now implement the main the new thing which we are going to learn in this section is graph dot add conditional edge. So graph dot add conditional edges. Now again wow looks really
67:26
Speaker A
confusing but it's actually much more simpler than it looks like. So the first uh part is your source which you can see here as well.
67:36
Speaker A
So the source will just simply be the name of the node. And what's the name of the node which we want the conditional edge to be? It's the router node, right?
67:45
Speaker A
So that's going to be the source part. Perfect. Now if you look here, it's asking for a path. What's the path you would like it to do? Now before we implement the path, we obviously need to per uh imple uh tell it what action what
67:59
Speaker A
what action it needs to do. And that's where this node will come in the decide next node part. So we pass that as the second parameter. So that's the path. And now we implement something called the path map which you should
68:13
Speaker A
have briefly saw here. Uh there path map. So we've implemented the source which is the router. We've implemented the path which is your uh decide next node function. Uh again don't need to worry about hashable runnable any and all of this stuff.
68:32
Speaker A
Okay, it's you don't need to over complicate it. Now it's time for the path map. Okay, so now your path map will be in a form of a dictionary. And remember how I said earlier that we had implemented addition operation and
68:44
Speaker A
subtraction operation. These were edges. So now we're about to implement those only. So we're about to create two new edges here. Let me just write this code up for you and then it will make sense.
68:58
Speaker A
Give me one second. Okay, so there we go. Now what is this code actually saying? Well, this is in a format of edge and node. Now the starting point of this edge will obviously be this router node and it's telling us where it will
69:19
Speaker A
connect to. This uh visualization will be it will be it'll be much easier to visualize when I actually show you the graph. Don't worry. But for now, addition operation and subtraction operation is the edge. And the two nodes
69:32
Speaker A
are add node and subtract node. Right? Okay. Uh lastly, we now we're now at the point where we need to create the end point. But obviously, we if you look back at this diagram which I've shown on the screen right now, you can see that
69:49
Speaker A
the we need two edges to connect to the end point, right? We need to we need an edge from the and node and we need an edge from the subtract node. So we can add two edges like this. graph
70:02
Speaker A
edge. Uh we uh start at the add node and then we end at the endpoint. Again similar subtract node and endpoint. And then we just compile this. So app is equal to graph.compile. Cool. No errors. Okay.
70:18
Speaker A
Now here comes the most exciting part. Again try to visualize what this graph will actually look like. Okay. So it should look something like that. Probably slightly different to what you initially anticipated but that's okay. We again have a start
70:38
Speaker A
point. We have the router and we have the our two nodes add node subtract node. And notice remember when I said addition operation and subtraction operation are the edges names. Well, here it is. Addition operation and subtraction operation. It's telling us
70:53
Speaker A
uh what the which direction to go into. Do we go how do we go to add node? Well, we use the addition operation. How do we go to subtract node? Well, we go to the subtract operation. And then obviously
71:04
Speaker A
we create these two edges, these two to connect to the endpoint. Awesome. So, we will once again look at it from a bird's eye view.
71:14
Speaker A
But let's actually invoke this graph to see what happens. So let's use this piece of code. So what it's saying is it's defining number one as 10, operation as minus and number two as five. So because we've used
71:30
Speaker A
subtraction, the final number should be 10 - 5 which is five. And we've printed the results and the answer is like such.
71:40
Speaker A
Uh number one is equal to 10, operation is equal to minus, number two is equal to 5 and final number is uh five.
71:46
Speaker A
Obviously the way I've invoked it is slightly different to what I have done before. Again, this is another way you can invoke. Okay, so not too hard. But let's just go through everything one more time to solidify everything. Okay, so we
72:02
Speaker A
imported everything. We created the state schema using agent state and a type dictionary. Then we created our three different nodes which is the add node, subtract node and the decide next node. And this is in within the decide
72:15
Speaker A
next node. You can see that if the operation is a plus, it goes to the addition operation edge which is this edge. And if it's subtraction operation, it goes to this side. And this is how we built the graph. We added the nodes. We
72:30
Speaker A
added the edge from the start point uh to the router. And then we added the conditional edge. the new thing which we've learned in this section uh which is we uh reference router and we use the edge node format. So the edge will be
72:44
Speaker A
addition operation uh to add node then it will be subtraction operation to subtract node. Visually speaking it will be addition operation to add node subtraction operation to subtract node.
72:55
Speaker A
Now, I know this will be quite confusing at first and don't worry, it took me quite a while to understand this myself as well, but hopefully the exercise I've given you will really be able to help you understand this much better. Okay,
73:09
Speaker A
so I will see you at the exercise then. Awesome. So, let's actually find out what the exercise is for this graph.
73:16
Speaker A
So, you need to make this monstrosity. Now at first glance it looks terrifying but if you analyze it a little bit closer all it is is what we just coded twice. So we coded this and we need to
73:31
Speaker A
replicate it once more. So in essence you need to actually input four numbers and two operations and you need to output their final results. For example number one, number two, number three, number four and the respective operation and the respective results. Right? So in
73:45
Speaker A
this case we would have to do 10 - 5 which is 5 and 7 + 7 + 2 aka 9 and those two numbers should be outputed. Now the reason I gave you this exercise to do is because this will really solidify your
73:58
Speaker A
understanding about conditional edges which will really be important for the next few next graph and the next AI agents we make. Okay. So once you have uh completed it by looking and cross referencing the answer on GitHub, I will
74:12
Speaker A
see you in the next graph. Okay. All right. Well done. We're almost at the end of this section and we're about to build our final graph aka graph 5. Now we've learned quite a lot about Langraph and its internal mechanisms.
74:28
Speaker A
And this will really help us in the next section where we finally build the AI agents you were looking for. Now in this section in this subsection sorry we're going to be learning an important concept. There's still one more concept
74:40
Speaker A
we haven't learned and that's about looping. So we're going to be creating well a simple looping graph. Now I kept the objectives to be quite small here.
74:48
Speaker A
There aren't that many objectives. It's essentially implementing logic uh which involves looping uh to route the flow of data back to the nodes. And we're going to be creating a single conditional edge which you know how to do in the previous
75:00
Speaker A
section. Regarding the previous section, however, I know the exercise. Please do complete that exercise. That exercise will be probably the hardest exercise you would have done until this point.
75:13
Speaker A
So, don't worry if you didn't get it. If you did, great job. You're doing really, really well. But if you didn't get it, look at the GitHub. Try to compare where you went wrong. Remember, in Langraph, there's more than one way of building
75:24
Speaker A
the graphs. Make sure the graphs are well built and it actually functions. And if you want an extension, try to make it even more robust than it is. All right, but back to this now. Final graph, I promise. The main goal really
75:38
Speaker A
is to code up the looping logic. So, with that out of the way, let's build a final code for this section. See you there. Awesome. So, final code we have to build for this section. And here we go. So, graph 5 squ. Now, I'm going to
75:55
Speaker A
take a slightly different approach this time. And I'm actually going to show you the graph we want to end up building from the get- go. And there's a reason I'm going to start that from now so we get in good practice. The reason is once
76:08
Speaker A
you finish this course and actually start either making your own AI agentic systems for someone else, for your clients or for yourself like make your own JavaS system or whatever. You obviously need to plan how it works, right? You need to see okay, what nodes
76:22
Speaker A
do I need? What edges do I need? Does is this does this need to be a conditional edge? where's the start point going to go, end point going to go etc etc and you can either do that via pen and paper
76:31
Speaker A
or software like I've used but point is you need some sort of blueprint and that's how really it works in the industry as well um you can you will obviously have a blueprint and then from there you will code up the graph similar
76:47
Speaker A
to how a UI designer for example uh renders um their UI designs and then sends that off to a software developer who uh well develops the application forwards. Right? So that's the habit I want to start uh creating with you. All
77:04
Speaker A
right. So this is the graph I want to build in this section. So there's obviously going to be a start and end point. And this really should be mostly familiar except for this loop. So there we're going to create a simple greeting
77:17
Speaker A
node and another node which is called the random node. So in the greeting note I essentially want the user to have uh stated their name and it should output a simple hi there your name and then the graph progresses to the random node and
77:34
Speaker A
in the random node I essentially want to generate five random numbers. Okay, now just as a heads up, yes, this graph in industry would be completely useless. I know, but I've deliberately kept it simple again so you know the
77:50
Speaker A
fundamentals. Like this loop is could have easily been avoided and transferred into a for loop for example, right? Like I could have had a for loop within this node and ran it five times to generate the numbers. I get it. But this is again
78:04
Speaker A
kept deliberately simple so you actually understand the concept. Okay, cool. So let's the usual inputs and the only difference is this time I've also imported random but if you have used Python before quite a lot you would have
78:18
Speaker A
come across this library right okay so let's start with our agent state so class agent state type dictionary and what's the first thing we're going to need well let's see we have the start point do we need anything
78:34
Speaker A
any keys that no for greeting note what did I say I want uh I wanted the user to be able to input their name. So, we need a name attribute or a key. And then for the random number, a random node, we
78:47
Speaker A
need some form of um a list to like actually store the numbers. So, we have number and list int. Okay, cool. And one more thing, look at this loop. How will we actually know when to stop? We need some form of
79:04
Speaker A
counter, right? So, counter int. Perfect. Now, obviously, just as a heads up, when you do go on to make your AI agents and everything, you're not going to know what attributes you need right from the get- go, unless if you planned
79:20
Speaker A
it like extremely extremely well. But chances are you won't get it. But don't worry, iteratively well, you'll obviously be better at speculating what attributes you need through practice.
79:31
Speaker A
But you can obviously do iterative development as well, right? Okay, cool. So now let's actually build these nodes. Okay. So let's start off with the uh greeting node. So how we normally define uh a function. So def greeting
79:47
Speaker A
node, we obviously need the agent states like such. Perfect. And the dock string. But uh luckily for me, I've already got that here. So I don't need to do it again. I know it's boring, but habits. Now let's update update the uh
80:06
Speaker A
name uh key. So how do we do that? Well, you should know by now state name is equal to let's say something like hi there. State name.
80:19
Speaker A
Perfect. So what will this do? I input a name and it'll replace that name with a string of hi there this person. Now let's also initialize the counter variable here. Now why am I doing that?
80:32
Speaker A
Let me just first write it and think about this. Okay. Now, obviously I'm changing I'm setting like the value. So, I will need to have passed in like an valid integer when I am passing the uh value when I'm
80:50
Speaker A
invoking the graph, right? But here's the thing. What if I pass in minus2 for example?
80:57
Speaker A
Well, as the counter value, as the initial counter value, if this line wasn't there, well, it would have just kept on incrementing until it got got to five cuz I want to have five numbers.
81:08
Speaker A
But if it starts at minus2, well, it would end up giving me seven numbers.
81:12
Speaker A
Now, that's not robust, right? So, this basically wipes out whatever rubbish integer the user even inputs. If they had put zero, well, okay, we replaced it to zero. If they put like minus 20 because they're greedy or something,
81:27
Speaker A
then we have made sure to like set that back to zero. So, so just a way to make it robust. That's all. Uh, return state.
81:36
Speaker A
Okay, cool. So, now let's create our second node which is a random node. So, we can say random node state agent state agent state. Perfect. Dog string.
81:50
Speaker A
Again the dog strings will be useful. I promise in the next section they will.
81:55
Speaker A
So this generates a number random number from 0 to 10. Now this piece of code here essentially appends the appends the randomly generated number to the number list. Okay, that's all it does. And what else do we need to do in this node?
82:14
Speaker A
Well, we need to increment the counter value right? So C uh plus equals to one. So this will increment uh the value by one and then we just return the state. Okay, cool. Now here's where we're how we're going to implement the
82:32
Speaker A
looping logic. Now just a warning here and please listen to this. Like in any software development uh program or programming language G2, there's more than one way of coding up an application, right? Same goes with Langraph as well. There is multiple
82:48
Speaker A
multiple different ways of coding like a looping code like this graph. I'm going to be showing you one of them. I obviously can't show you all of them cuz there it's just time constraint, right?
82:58
Speaker A
But obviously the more you practice the uh uh better ways you'll more efficient ways you'll find, right? But the way I'm going to show you is pretty efficient as well. Don't worry. Okay. Now, you might have speculated that I'm going to create
83:13
Speaker A
like a router node. It's close. I'm not going to create another router node. You can see in the graph the uh the client let's say the client wants this graph.
83:23
Speaker A
The client doesn't want another router node here. So how do we go about that?
83:28
Speaker A
Well, we could create a conditional edge. How do we do that? Okay, let's begin that. So let's write a new function say defaf should continue uh state agent state agent state and um let's create this block string um function to decide what to do
83:50
Speaker A
next something like that. Okay cool now here's where we set our looping logic and this should look quite familiar to you now. Perfect. So let's run that. Okay.
84:03
Speaker A
So what have I written here? Well, if the counter value is less than five because we're starting with zero, right?
84:09
Speaker A
So 0 1 2 3 4. That'll be five values. Um I've also written a print statement so like we can keep track of um um the progress. Also whenever I'm writing the code as well when you're uh coding with
84:23
Speaker A
me or doing the exercise, it's really helpful to print uh statements uh like put in print statements everywhere. Or you could also use break points as well.
84:32
Speaker A
So you know uh where to where the code failed if it fails. Okay. So here we return the loop a loop edge and the exit edge. So obviously we have the loop edge and this will be the exit edge. So everything is
84:47
Speaker A
going to plan so far but um so far is the key. You never know, right? Okay. Uh just as a heads up though, I want to show you this. So this is how the trajectory should follow. We start at
85:01
Speaker A
the greeting node. Why? Cuz we obviously go from the start to the greeting node.
85:05
Speaker A
And then we enter the random node. And we enter the random node and exit it five times. So 1 2 3 4 5. Why five times? Because we want five random numbers, right? By then this if statement will uh well it won't work. It
85:19
Speaker A
will fail. So we will go to the else statement and return exit. And if we return to exit, we'll go to the end node. Uh okay. endpoint. Okay, so that's how the general gist is. Okay, let's quickly make this graph. So you should
85:33
Speaker A
know how to initialize a graph agent graph and let's just add these nodes. So we have our two nodes which are here greeting and random which is exactly what we wanted, right? Greeting node and random node. Perfect. Okay. And
85:51
Speaker A
now we're going to add an edge between greeting and random. Uh why? Because well I've created this edge. You see this edge greeting node and random node.
86:00
Speaker A
This edge that's the edge I've created. Okay. Now I'm going to create the um the conditional edges which is done through here and I've written some comments here as well. So uh there will be the source node which is the random. So where I
86:21
Speaker A
want the conditional edge to start from and then the routing function or this tree I should have really written action here because is the action I want to perform the underlying mechanism or function which is going to which we're
86:33
Speaker A
going to um determine which edge to use and that's uh implemented by the should continue function right and notice how again these two edges are the same edges here. So if the loop is uh the one which um uh is outputed then we need to go
86:51
Speaker A
back into its random the random node which we've generate uh which we put there and if it doesn't we go to the end part. Okay and then obviously we set the entry point. Okay. So again you don't have to
87:08
Speaker A
set the exit point here uh or the finish point because we've already done it using end here. Okay, perfect. And then we just compile the graph app is equal to graph.compile and okay, it compiled.
87:23
Speaker A
That's a good sign. But let's see if we have got our graph to be the exact same. Now I'll put the graph image here so I don't keep scrolling back and forth. But you can see we have the start
87:36
Speaker A
point and the end point. We have the greeting and the random. And then we have our two condition edges. So we have the loop going back into the random node as we wanted and the exit which you can
87:48
Speaker A
see. So take a moment and you can see compare and contrast. Okay, let's continue. Okay, now I have this code. So I've given a name my name uh a r um a completely brand new list and I've set counter to minus
88:06
Speaker A
one. And as you can see it enters loop one, loop two, loop three, loop four because these are print statements we printed. Uh it says hi there v which is my name. Uh number 10 21026 just randomly generated and you can see the
88:21
Speaker A
counter value is five. Now remember what I was saying over the counter. We set the counter value to zero here to make it more robust. If we had not done that well it would have generated six times.
88:31
Speaker A
And now I can set this to minus 100. it will still obviously give me different random values but um the code is largely the same. So that's really the way which I personally use to create loops in langraph it's pretty easy right but um
88:49
Speaker A
obviously with practice you might even find some other ways if you do find other ways like obviously uh do let me know uh there's more than one way again you can send me a message on LinkedIn or Instagram or whatever but um yeah so
89:03
Speaker A
this is finally finally uh we have implemented the code for our final graph of the section So just complete the graph 5 exercise please and yeah we should be good to go to make AI agents. So I'll see you at
89:19
Speaker A
this codes exercise. Okay cool. Okay good job on that. Now for the exercise for this last graph uh you need to implement this graph on the right. So you need to implement an automatic higher or lower gain. So for context,
89:37
Speaker A
you need to set the bounce which we can guess between 1 to 20 integers of course and the graph has to keep guessing where the max number of guesses is 7 where if the guess is correct it stops but if not
89:50
Speaker A
we keep looping until we hit the max limit of seven. Now please note we don't have to pass any inputs the actual graph should automatically guess by itself. So there should be no human in the loop human intervention at all. So each time
90:04
Speaker A
a number is guessed the hint node aka this node should say either higher or lower and the graph should account for this information and guess the next guess according accordingly. So for example the input should be something like the player name student. The guess
90:20
Speaker A
should just be an empty list cuz we're initializing the list. Attempts should be set to zero and the lower bound and upper bound should be 1 to 20. Now the reason I've also passed these as inputs is because uh if you wanted to expand
90:33
Speaker A
this to maybe 1 to 50 numbers or whatever you can. It's quite easy to do that. So just as a hint uh it will need to adjust it its bounds after every guess based on the hint provided by the
90:45
Speaker A
hint though. So once you've completed this exercise you would have fully reinforced uh your understanding about loops in langraph. So once you've completed this, cross reference it.
90:56
Speaker A
Cross reference the answers on GitHub. I will see you in the next section where we finally begin AI agents. See you there. Okay people. So welcome back to this brand new section where we actually start learning about AI agents. Now we
91:14
Speaker A
finally are upgrading our ability in Langro. I even upgraded my clothing sense. Not really. But this is exciting times cuz we actually finally build AI agents. So, we're going to build a lot of AI agents in this section. And
91:28
Speaker A
starting off with the first agent. Well, technically it's not really an agent, but I just named it that because it sounds cool. But um technically it's not though. But let's see what we're going to actually learn in this section in
91:42
Speaker A
this subsection. So, we're going to build a simple bot. That's it. And these are the objectives. So we're going to define a state variable uh state structure which we're going to have a list of human message objects and I
91:55
Speaker A
briefly uh me uh mentioned what a human message was uh a long time ago in the course. Uh what it is it's well it's in the name it's a message prompt which is given by the human aka us to the AI. Uh
92:10
Speaker A
we're going to initialize the GPD40 model for this uh using lang chain's chat open AAI uh uh library. Uh we're going to send and handle different types of messages. We're going to build and compile the graph of the agent. But the
92:23
Speaker A
main goal really is how we can integrate LLMs into our graphs. So what is this sort of graph we actually going to end up building? Now it's very very simple.
92:34
Speaker A
It's going to look like this. And yes, this looks exactly like the graph we made in the uh first ever graph we actually ever made. But um the functionality will obviously be different cuz now we're actually integrating LM. So exciting stuff
92:48
Speaker A
people. Uh okay, I will see you at the code then. All right, coding time. So now we first code our well we code up our very first AI agent aka the simple what and um I've already imported all the
93:04
Speaker A
necessary libraries we'll need uh to not waste time. So while you're uh coding these up as well and copying these I'll also briefly explain what these are so we're at the same level. Okay, so we've already imported type dictionary and
93:18
Speaker A
list many times before but um these two we haven't sorry these two the lang chain codon messages import human message so I briefly mentioned this in the intro of this section of the subsection what a human message is right
93:33
Speaker A
and this is the library we get it from and similarly we're going to be using openai's lms so that's why we're going to use chat openai from the lang chain open aai uh library uh the langraph.graph. Uh these we were
93:47
Speaker A
familiar with and this is the env. Now just a few points. You could have been saying okay wait hold on I thought we were about to do a langraph stuff. Why is the lang chain stuff here? Now you
94:00
Speaker A
must know that langraph is built on top of lang chain and lang chain already has the sophisticated libraries right so why not actually use them that's how langraph is designed it's designed to use the robust sophisticated libraries which lang chain offers right so no I'm
94:18
Speaker A
not a trader we're still doing langraph stuff but we're also using leveraging lang chain strengths as well okay and um now this env file now it's okay if you haven't ever um encountered av file before. Essentially, it's just a file
94:32
Speaker A
used to store secret stuff like API keys or configuration values. So, it's really there for security purposes. Now, I have my own um file stored in my folder structure uh so that you don't see my API key uh
94:48
Speaker A
because if you do then I would go bankrupt. So, that's why. Now, you might also be wondering why do we need an API key here? We need the API key because we're doing calls to an external LLM. If
95:02
Speaker A
we were using our own LLM like through OAMA, then we would um not have an API key, right? We would just use like the Olama library integration with lang chain. So because we're using charges, we need an API to communicate with the
95:18
Speaker A
LLM in their cloud servers. Cool. So how do we actually load this? So to load our um API, we just use a simple Python uh code load. Env. All right. So now that we're at the same level, let's actually
95:33
Speaker A
code up our AI agent. Cool. So let's define the state like we always do. So this time class agent state type dictionary. Perfect. Okay. Now what are the attributes we need in this section uh in this uh state? Well really just
95:51
Speaker A
one the messages part right so messages but what form will it be well it will be in the form of a a list of human messages right so we'll have list human message why because we when we invoke
96:05
Speaker A
the graph we're inputting human messages right so to tell the large language model that this is a human message I i.e Uh this is a message from me the user aka human right. Um we need to actually mention human message that it's a human
96:20
Speaker A
message type. Cool. Okay. So now we actually initial initialize the large language model. So we just write lm is equal to chat openai. And now we specify what model we want. Now I'm going for GPD4er. Now yes there's also chat uh
96:40
Speaker A
anthropic. I think there's chat oama. Um there's a lot of like in-built um libraries which lang chain offers which is great. Personally I've used chat openai a lot. I've also used chat anthropic a lot as well. Uh personally I
96:55
Speaker A
like chat openai cuz it's just really simple to use. I've also used tried well tried to use chat oama before but really there's some difficulty in integrating it with lang. So that's why I've opted for openi. And if you're worried about
97:10
Speaker A
financial cost, don't worry, it's extremely cheap. Uh if you want, you could also go for the GPD 40 mini model as well if that's a concern. But trust me, it's extremely cheap. Like the input tokens, output tokens is like in like
97:24
Speaker A
tens of pennies for like a,000 tokens. So really, really cheap. Okay. So now let's actually define our node through our function. So process and we obviously define the state and then return the state like so. Perfect. Now how do we actually call the lm? Now lang
97:47
Speaker A
chain and the langraph team really like using the word invoke. You might have noticed that to call a graph or like to make the graph run we've used invoke.
97:54
Speaker A
Similarly to run the lm we use invoke as well. So we okay let's store the response we get in a variable. So uh lm.invoke and what do we invoke? Well, you can see from the uh hints here that
98:09
Speaker A
it requires an input of language model input. What's that basically saying is what what what do you want the LM to do?
98:16
Speaker A
Right? What's your question? Now what is our question? Well, that's in the messages. So we write state messages. So what will happen here is as soon as I've written state messages, let's say I have written hi or whatever uh we will pass
98:31
Speaker A
this to the LLM through the invoke method. The LLM will then generate a response from its cloud server through our API and it'll get it will give us back the um its response and then we'll store it in the response section uh the
98:46
Speaker A
response variable. Cool. And um let's actually print this like so and return the state like such. Okay, done. Now we obviously need to create the graph like such.
99:03
Speaker A
Okay. So uh what is it saying? Well, it's saying that there is we've created a node process which is that which where the action is the process function. The add we've added an edge. We've added an edit from the start to the end node end
99:18
Speaker A
point and we've compiled the graph. Okay. Um yeah. So let's now ask the for the user input. So user input is equal to input. We'll say enter something. And now we will invoke the agent cuz we need to invoke the agent of
99:39
Speaker A
course because we're creating a graph, right? And the graph is well like agent in this case. Cool. Let's actually run this code now. So, Python agentbot.
99:53
Speaker A
py and perfect. So, enter. Let's say hi. The AI message was hello, how can I assist you today? Now, I can reassure you I did not pre-code this or hardcode this. This is the actual LM. Let's run it uh one more time.
100:10
Speaker A
Let's come up with a different message like who are you and it'll say I'm an AI language model created by open AAI called chat GBT. So you can this basically pretty much confirms that yes this is GBT uh in
100:25
Speaker A
the background. Okay, but um why why just stick to one message, right? Why not uh be able to run multiple message like asking multiple messages kind of like a chatbot, right?
100:38
Speaker A
So this is the code which does this and I'll walk you through this what's happening here as well. So uh like before we input our query and now we basically say keep iterating through and as soon as the user has said like exit
100:53
Speaker A
or something then uh well you exit the while loop and that basically signifies that well you don't want to talk to the ailm anymore. So let's have get run this. So python agentbot py. Okay let's say hi again. Hello how
101:10
Speaker A
are you? But now we can run it again. It's just a simple y loop. It's nothing groundbreaking. So like who made you? Okay, perfect. What is 2 + 2? 2 + 2 equals 4. Okay. Uh let's say now, hi, I
101:26
Speaker A
am Bob. Okay, now watch this carefully. I'm about to ask what did I just well or I should say what is my name?
101:42
Speaker A
I'm sorry, but I don't have the ability to know your name or any personal information about you. Why is that? Why didn't it know what my name is? Well, even though I clearly specified it. So, let's quickly exit. Okay, now this is important.
102:01
Speaker A
Nowhere in the code have we actually created some sort of memory. That's why I called this subsection simple bot. And that's why I kept on saying AI agent because it's not even an agent yet. Uh it's just a simple
102:15
Speaker A
like the most basic LLM wrapper you can possibly have. But at least now you know how to actually integrate um LLMs in your graphs, right? And it's pretty straightforward. You just you um you just uh embed them within your
102:31
Speaker A
functions and then your functions obviously act as the actions in your notes. And that's it. It's quite an easy piece of code. Like it's only what 29 lines or 25 lines give or take. Uh but yeah, pretty simple. Um I don't think
102:47
Speaker A
there'll be any exercise for this cuz well there really isn't much to do with this. So I will see you in the introduction for the second AI agent we're going to build. Okay. So I'll see you there. Cool. Cool. Cool. Okay. So now
103:02
Speaker A
we're going to build our second AI system. And we're going to try to fix the problems we faced in the last uh AI system we built. And what was the problem? Well, the problem was it doesn't remember what we in what we had
103:16
Speaker A
said before, right? Why? Cuz we were calling separate API calls. So now we're going to try to create a chatbot with some sort of memory. That's why I included the brain emoji here. So let me walk through the objectives for this uh
103:29
Speaker A
subsection. So, we're going to use different message types in particular in particular the human message and the AI message. We're going to maintain a full conversation history using both of these message types. We're going to particularly use the GPD4 model again
103:44
Speaker A
using the lang chains uh chat open AI library and overall we're going to create a sophisticated conversation loop. So, what is the main goal goal of this um subsection? It's really to create a form of memory for our agent.
103:59
Speaker A
So if you're ready, let's go to the code. All right, awesome people. So let's begin coding our simple chatbot then. Okay, so like last time, I've already imported all of the uh necessary libraries and it's largely this exact
104:15
Speaker A
same except now I've added two more uh stuff. So the first is the AI message and I explained this in the introduction of this subsection why we need the AI message. And I've also imported the union type annotation. Now the union
104:30
Speaker A
type annotation is something we covered in the first chapter. So if you if this is the first time you are looking at it or hearing about it, I would recommend you going to the first chapter really understanding and watching the first two
104:42
Speaker A
chapters. They're quite short to be honest and then coming back. Okay. Now that being said, let's actually begin the uh coding then. Okay. So like always, we define the state. So class agent state uh typed dictionary. Perfect. Now last
105:01
Speaker A
time what did we define this as? Again we're only going to have messages again but uh last time we had list human message. Okay so that was what we had defined as our agent state previously. Now this time we also want
105:19
Speaker A
to include the AI message as well. We're building a more sophisticated chatbot. So how do we do that? Well, one way or the naive way is to really have it as messages AI list AI message or something like
105:35
Speaker A
that. Something like that. And don't get me wrong, this is still a valid approach. You can still build your graph and everything like that, but um I think it's a bit longer. So let me tell you another way which would actually be
105:49
Speaker A
better. So remove this. Instead, let's use the type annotation union like this. So, union like so. And let's include AI message. Now, what has this done?
106:06
Speaker A
Essentially, let me first tell you about a bit about human message and AI message. Human message and AI messages and like all of these like different structures are actually data types in Langraph and Langchain. That's what the developers of these libraries have got
106:20
Speaker A
them to be. And um when I write union human message AI message then that basically allows me to store uh either human messages or or AI messages in this uh key in the state the messages. So that's what that literally means in a
106:38
Speaker A
nutshell. Now, one important thing which I want to mention is this. All of these AI agentic libraries like Langchain, Langraph, Crew AI, Autogen, they're all great, but um you really can make your own AI agentic system by writing just
106:56
Speaker A
Python functions. You don't even need to use a library. Now that being said, I would still recommend using these libraries, especially Langraph because Langraph, well, because it's a personal favorite, no bias at all, but um it's Langraph really allows you to control
107:14
Speaker A
much more than other libraries would. Obviously, not as much control as if you were writing the Python functions yourself and everything, but I think it's a good balance of how much control you have and how much uh unnecessary
107:26
Speaker A
jargon you need to write. Because think about it, think about how much of um this unnecessary code which you would have had to write else otherwise uh langraph and lang chain support. So that's why I highly recommend using
107:39
Speaker A
these libraries and everything. So again human message and AI message are data types inbuilt data types within uh lang lang graph and lang chain. Cool. Okay.
107:50
Speaker A
Now let's again initialize the large language model as we did last time. And again we're only we're using GP4.
107:57
Speaker A
Okay, now we're going to create our node. Again, it's going to be the exact same graph structure, by the way. So, state agent state, but obviously the actions we perform will be slightly different. Now, um let's write a dock
108:12
Speaker A
string. This node will um this node will uh do solve the request you input something. Dog strings aren't really needed for this AI agent or this subsection because we're not going to use them. But um again, good habit.
108:32
Speaker A
Okay, cool. Let's invoke this. So what have I done here? This is exactly the same code which we did in the previous subsection. The l we invoke the lm uh with the state messages. And what are the state messages? Well, it's
108:48
Speaker A
could be either human message or an AI message. It's a list of those. Awesome.
108:53
Speaker A
So now we write this piece of code. Okay. State messages.appen AI message content equal to response.content. What on earth is happening there? Okay. Let's break this down. Response. Well, that's just extracting only the content part of the response aka the response being the
109:13
Speaker A
answer or the result after we make the uh API call from the large language model. And it only extracts the content.
109:19
Speaker A
So it only extracts like the important stuff, right? It removes all the unnecessary jargon which comes with it like the amount of tokens you use and all that. It removes that and that's uh gets stored in that gets converted to to
109:33
Speaker A
an AI message and that's appended to our state messages um in the state. Simple.
109:40
Speaker A
Okay. Uh now obviously to make it look pretty in the terminal we're going to print this and then we're going to return the state. That's it. That's how simple it was.
109:52
Speaker A
Okay, so now we're going to create this exact same graph. And that's why I've just copied and pasted it because it's a time waste of me rewriting the code in front of you again and again. So we can
110:02
Speaker A
just reuse the same code because it's the exact same graph uh graph structure as the previous subsection. Cool. Okay, now we're going to now here's where it actually starts working differently.
110:14
Speaker A
See, last time we didn't have this the conversation history. really this is what's going to be our memory in in um this uh setup. Okay, so we have now in initialized conversation history. Now again we're going to ask the user what
110:32
Speaker A
they want, right? What's their request? So now we use this Y loop and this Y loop was the exact same loop we had in the previous subsection as well. uh it only exits unless if the user has uh
110:46
Speaker A
inputed well exit obviously but now look at this the conversation history is appended with the human message and the human message is obviously the user input the reason I've kept on writing content is because well that's the parameter in human message as you can
111:03
Speaker A
see here okay cool uh and we've invoked the agent what is the agent well the agent is the compiled version of the graph the compiled graph uh with uh the entire conversation history. Now this is important. The entire conversation
111:21
Speaker A
history is sent, not just the current human message. So uh this will make more sense. Don't worry, I'm um trying my best to explain it right now, but obviously it will make much much more sense as soon as I start running it.
111:35
Speaker A
Okay? So bear with me if you didn't fully understand that. Don't worry. Let's remove that for now.
111:41
Speaker A
Uh, and then we replace the conversation history completely like wipe it with the result messages. Why? Don't worry, it's going to make sense as soon as I run it.
111:52
Speaker A
And I think yeah, we should be able to run this now. So, let's write python memory agent.py, which is the name of the file. Cool. Okay, let me just quickly write a hi just to see if the API is
112:05
Speaker A
working. It is perfect. Okay. Hello. How can I assist you today? Uh, now I'll say like, "Hi, my name is Steve." Hi Steve, it's great to meet you. How can I help you today? Okay, now remember from last time. Last time if I
112:24
Speaker A
asked it, hey, who am I? It didn't know. Do you think it will know now? Think about it. It does. you are Steve or at least that's the name you've chosen to share with me. Uh and the rest is yes
112:42
Speaker A
whatever. So it does know about what I have said but just looking at this code I guess you can try to like pick out okay how does it work and everything like why everything works like that but um I think we can add print statements
113:00
Speaker A
and everything. So let's try to add print statements now and see well how this is actually working. So let's exit the program.
113:10
Speaker A
Okay. Uh let's add a print statement here. Let me include this. Cool. So what is this saying? So this print statement actually kind think of it like a snapshot of what the current state is.
113:25
Speaker A
So as soon as it goes into a process note as just before it's about to finish by returning the state, we also print the current state as well. And this will literally just output whatever is stored in the messages attribute within our
113:39
Speaker A
state. Okay. So let's clear. There we go. Let's run this again. So hi, nice to meet you.
113:50
Speaker A
Something like that. Now take a look at the current state. See it outputed hello, nice to meet you. How can I see you today? Why did it output that? Well, because in our process function it we've asked it we formatted
114:05
Speaker A
it in a way so it says hey AI which is this part and the response or content is this part. Okay. Now this response or content is also what was stored remember how I said it's stored in the um in a
114:19
Speaker A
nice manner and was appended to our state messages. Now was it appended to the state messages? Yes. How do you know that? Because look at the human message.
114:27
Speaker A
The human message was what I wrote which was hi nice to meet you. Uh forget the additional keyword arguments and response metadata cuz I didn't provide any. Uh you don't need to worry about that. The main part is this part the
114:37
Speaker A
content. And then look at the AI message part. Uh it's the content is equals to hello nice to meet you. How can I see you today? Notice how it's the exact same thing as it was here. Okay. Now, now we're going to go
114:55
Speaker A
one step ahead and I'm going to ask it to say my name is Steve again. Now, think about how will this current state change? Pause the video and try to think about this like that. Okay. So, now the second
115:17
Speaker A
uh message I sent was my name is Steve. Its response for the second message was hi Steve. How can I help you today? Now look at the current state. It still begins with hi, nice to meet you, which
115:29
Speaker A
was the first ever message I inputed into this conversation and then its respective AI message. And then that gets uh appended. Why appended? Well, because we had appended the AI message and appended the human message. So that's why. Okay. And you
115:46
Speaker A
can see the human message is my name is Steve which is the most recent uh message which I put and then the AI message which is hi Steve how can I help you today? Perfect. And we can just keep
115:57
Speaker A
going and going and going. But uh for now I'll exit. Now here's the thing. This works well relatively well, right? We've got it like as a chatbot which is what we wanted. it has some recollection of memory or or like of what we what we are
116:14
Speaker A
who we are and everything. But there's two big problems here. Let's start with the first uh massive problem which is this. You know how I've exited the program right now. Yeah. Okay. I'm going to run the exact same program
116:31
Speaker A
again. Now I told it that my name is Steve. What is my name? and it says uh I'm sorry I don't have access to your personal data. Okay. And look at the current state completely wiped out.
116:50
Speaker A
Again, that's pretty self-explanatory as to why you exited the program and that's why obviously all the var the data was stored in the variables, right? The state was stored in the variables completely got wiped away. So what is
117:01
Speaker A
the solution? Think about it. Well, obviously one potential solution would be to store it in a database, like a large database, right? Or a vector database if you're trying to do some ragged applications. For now, I'm just going to store it in a very simple text
117:18
Speaker A
file. Why? Cuz it's really easy. And I've got the code as well. And usually, honestly, I just store it in a text file when I'm prototyping. Now, yes, obviously, storing it in a vector database or a database is much more
117:30
Speaker A
robust and sophisticated, and that is what you should do. But when you're prototyping and you want to really see uh try to build it quickly and fast, uh I just tend to use a text file. It still works uh still works great and
117:42
Speaker A
everything. So what is the code for the text file? Uh it's here. Okay. So what is this code saying? Well, essentially it's saying create me a text file called logging as a as a text file you see in write mode and a file. Write
118:01
Speaker A
your conversation log. This is just to like make it look better and more aesthetic. But this is the main part of the code which um you should actually try and understand for every single message in the conversation history.
118:12
Speaker A
Okay. Now note the conversation history was this variable which we had like initialized the conversation history uh stores the AI messages and the human messages. So that's where all of the um the information outside the graph actually is. Right? the state is locked
118:30
Speaker A
in within the graph now and uh the conversation history is just another I guess you can say a duplicate version of the state right because we've you we've appended the exact same human messages and AI messages and kept on updating it
118:46
Speaker A
through this line cool so what it says is that for every single message in the conversation history by the way a conversation is the duration between my first message and the last message I sent that entire thing is a
119:00
Speaker A
conversation. A conversation isn't just a single API call. It's the entire length. Okay? So, just to be mindful of that. So, uh it first checks if it's a human message, it writes that as you and then extracts that content and if it's
119:14
Speaker A
the AI message, it uh puts it under the AI stuff. So, let's run this again. So, let's exit this. Clear this. Okay.
119:25
Speaker A
Who? Okay, let's say hi, I am Steve. Again, I'm using Steve because a Minecraft movie just came out, so that's why. Okay, now I'm going to intentionally make a spelling mistake here. Good morning. It should obviously morning should have been spelled, right?
119:41
Speaker A
But I'm doing that for a reason. It gets no problem. Let's say tell me a joke.
119:47
Speaker A
Just another random thing. Sure. Why don't skeletons fight each other? They don't have the guts.
119:53
Speaker A
Um, really rubbish. My point is it works. Now I'll exit the program. And now it says conversation saved to login.xt. Now look at this. Remove that. Let me remove that.
120:06
Speaker A
Okay, perfect. So this is the conversation log. The first message I ever sent was, "Hi, I'm Steve." There, it's response. Now, good morning. Now, why did I spell it like wrong? Why did I do that? Because I wanted to show you
120:19
Speaker A
that this is the actual human message, my message being stored unaltered. So whatever I pass in the state as a human message that stays there. So it's unaltered. The AI message cannot or or anything can really change the previous
120:37
Speaker A
human messages at all. Right? So that's why. And you can see tell me a joke.
120:42
Speaker A
Sure. It's it's a rubbish joke is after that. And that's the end of the login.xt file. So that's a really fast efficient way, not the most robust way of course, but it is a fast efficient way to be
120:54
Speaker A
able to store your data outside um the application if it stops. Perfect. Now, what was the second problem that I was mentioning? It's this. Look at how I initially I say, "Hi, I'm Steve." I don't know why I
121:09
Speaker A
printed twice there. Weird, but whatever. Look at the current state length. Okay. Then I pass in another message, it becomes longer. I pass in another message, uh it gets longer. It keeps getting longer and longer and longer. That's a problem because think
121:28
Speaker A
about it, you will use these uh library uh you'll use these like large language models whether it's for your own AI agentic startup or your own mini Javas or your own projects or whatever it is.
121:39
Speaker A
You would obviously want to minimize cost, right? But using so many tokens uh using so many tokens like input tokens especially will really eat away uh your uh the amount of money you will uh spend like it will drastically increase it and
121:57
Speaker A
that's a huge problem right we want to try to be conservative a bit about our money and our financial our finances so what is one what is a way to solve this think about that Well, right off the bat, I can give
122:13
Speaker A
you an easy solution to implement which is within the code, write it, write some code where if the number of human messages exceeds five or something like that, then you remove the first human message in your uh history. Why remove
122:30
Speaker A
the first and not the latest? Well, because the latest is most likely to be more relevant, right? The first message could is most likely to be the one where um the one which is well not needed or it could have been like it can it has
122:45
Speaker A
more of a chance to be like a bit more less of an impact to have been removed.
122:52
Speaker A
So why did I pick five? Well, five is just a random number I thought of. You could do 10, 15, 20, 25, three, whatever. But that's a really easy solution to do. Okay, so we learned quite a lot there. We learned how to
123:07
Speaker A
integrate human message and AI message within a thing. And now we've created a somewhat of a sophisticated chatbot, right? It has a memory. It still talks to us. We if we define uh if we write who we are, it remembers that and
123:20
Speaker A
everything and it works great. Obviously, it has its flaws, but for now, it's pretty good. Okay, so now we're going to build our third AI agent.
123:29
Speaker A
And this is going to be a special type of an AI agent. The technical term for this type of agent is called a react agent and react stands for reasoning and acting. So this is a quite a common type of AI agent
123:43
Speaker A
which you will build. So how does it look like? Well, it looks something like this. So it's quite simple. There's a start point and then it's an end point obviously. Then you have your agent and then we use a loop where we attach it to
123:59
Speaker A
tools. Now, this could be one tool, two tools, a lot of tools. And it's the agent's job or the LLM in the background to be able to decide which tool to select. But not only that, it's all it's
124:11
Speaker A
also its job to be able to decide when there's no more tool calling left to do.
124:16
Speaker A
And when that happens, it goes to the end part. So that's the general gist of what a React agent is. It's a very very common and famous type of agent to make in Langraph. And that's exactly what we're going to be building in this
124:27
Speaker A
subsection. So what are the objectives? So to build a react agent, the objectives are learn how to really create tools in langraph. We're going to be creating a react graph. Of course, we're going to be working with different
124:41
Speaker A
types of messages such as tool messages. See, last subsection we've we covered AI messages, human messages, but now we're going to look at a lot more types of messages. for example, tool messages, system messages, base messages, and we're obviously going to test our
124:56
Speaker A
robustness um of our graph. So, the main goal is to create a robust React agent.
125:02
Speaker A
So, if you're excited, I'll see you at the code. Okay, people. So, now we're going to code up the React agent. And just a heads up, this is going to be quite a long subsection. So, get ready. You can
125:16
Speaker A
see it's going to be long because of how many imports I've done. But because I've done so many new imports, I actually want to take some time off and really explain each line so that we're all on the same page. Okay, let's go. So the
125:28
Speaker A
first line is from typing import annotated sequence and type dictionary. Now we obviously know what a type dictionary is, but we haven't come across annotated or sequence yet. So these are also type annotations. And I'll start off by explaining what an
125:41
Speaker A
annotated is. So annotated is a type annotation which provides additional context to your uh variable or your key without actually affecting the type itself, the data type itself. Now what exactly does that mean? Well, I'll give you an example. Let's say I am trying to
126:00
Speaker A
create a type dictionary where there is an email key in it. Okay? Now, obviously an email is string. So if I was to create a type dictionary, I would have written email colon string, right? Sl.
126:12
Speaker A
That's how we've been doing it. But here's the thing with certain keys like email, they have to be a certain uh format. But like for example, it has to be like abcgmail.com for example. But if I pass in
126:29
Speaker A
abcd-gmail.com or something like that, that's not a valid email format anymore, but it's still a string technically. So it would pass through. So how do we resolve that? Well, that's where annotated comes in. And I'll give you an
126:41
Speaker A
example here. Let's say email is equal to annotated. I'm not going to create the whole type dictionary to save time.
126:46
Speaker A
But for uh the example itself, you first pass in what data type you want it to be. So we want email to be a string, right? That's not changing. But here in quotation marks, I provide some more additional information, additional
126:59
Speaker A
context. And this is basically adding onto the metadata of this key or variable. For example, uh let's say this has to be a valid email format. Now, obviously, I should do it in more detail, but um that's how uh for
127:19
Speaker A
now, that's fine. So, how how can I actually see the metadata? So, if I want to, I would write print email metadata uh like that. And then I would press run. And here we go. You can see this
127:35
Speaker A
has to be a valid email format. That's the exact same thing which is which we wrote here. So that's annotated done.
127:42
Speaker A
But what about sequence? What does sequence mean? Well, sequence is also a type annotation. And the way I've described it is here. It basically automatically handles the state updates for sequences such as by adding new messages to a chat history. Now what
127:58
Speaker A
does that mean? Well, it's really just there to avoid any list manipulation to the graph nodes. Obviously, like when we're using graphs and nodes and all all of that stuff and updating the states, there's a lot of uh list manipulations
128:11
Speaker A
which we'll have to do. Sequence really handles a lot of that. So, that's really what it's there for. You don't really need to uh worry about it too much.
128:19
Speaker A
Okay. Now, if we continue, we have env uh from import loadenv. From last time, we know that this is just to store our API keys and I've done that here. That will load the API keys. But you'll see
128:32
Speaker A
now these three uh imports. We're importing some new message types here. So we're importing base message, tool message, and system message. I'll start off with the tool message. So it's essentially a type of message where where the data is passed back to the LM
128:49
Speaker A
after the tool has been called and like the information which is passed is like the content itself, the tool call ID. Uh that's what tool messages. It's pretty self-explanatory. Now for a system message, it's the it's a message for
129:03
Speaker A
providing instructions to the LLM. So like for example, if you've used uh LLM APIs before, you might have written you are a helpful assistant. That's exactly what a system message is. And don't worry, we're going to code this up as
129:15
Speaker A
well. So you'll actually see what they are. Now what's a base message? So in the comments, you can see that I've written the foundational class for all message types in Langraph. Now here's how this works. Think about the class
129:28
Speaker A
hierarchy. So you know how you have a parent class and then you have child classes as well. Well the base message would be the parent class and these uh AI message, human message, tool message, system message and all these other types
129:41
Speaker A
of message will be like the child classes and they will inherit all the properties of the base message cuz that's the parent one. I guess you can say the uh all father or something but the AI message, human message and all
129:53
Speaker A
these child uh classes obviously they'll have their own properties, right? For example, the tool message has its own content and tool call ID and all that stuff. So that's what the base message is. It's really the foundational class
130:05
Speaker A
for all the message types in Langraph. Cool. Okay. So now if we continue, you can see we've imported chat, openAI. Uh we've done state graph and M. These we've come across. We know what they are. And we've imported tool
130:19
Speaker A
and tool nodes which we cover in the second chapter or second section of this course. uh these are different elements which we're going to be uh using in langraph. Now what about this line from langraph dossage import add messages.
130:32
Speaker A
Now what does that mean? So this is a little bit um different. This add messages is a reducer function. Now if this is the first time you're hearing that don't panic. It's not that hard. So let's let me copy this one second. Okay.
130:49
Speaker A
So a reducer function is essentially just a rule that controls how updates from nodes are combined with the existing state. In simpler words, it really just tells us how to merge new data into the current state. Now here's
131:03
Speaker A
the thing. If we didn't have some sort of a reducer function, uh updates would have just replaced the existing value or state entirely. And I'll give you an example for this.
131:16
Speaker A
So let's say I had a state where it was just high. I had one attribute messages and high. Now obviously I should have created the type dictionary and everything and formalize it but just for simpler um for times saving purposes
131:29
Speaker A
I've done it like this. Now what if I had an update which says nice to meet you. If I didn't have a reducer function that would completely overwrite it. Now in the previous uh graphs and agents we've made we've appended it but now
131:44
Speaker A
that we're using so many different messages and calls and tool calling and what whatever we can't really always append everything like it will get far too complicated. So that's why we need to leverage reducer function. So if we
131:57
Speaker A
didn't use a reducer function it would just overwrite it completely. But if we did like hi nice to meet you it would append it. That's the key. So in a nutshell, the reducer function really just aggregates the uh data in the
132:11
Speaker A
state. This reducer function uh and the reducer function which I'm talking about is add messages. So once again, add messages is a reducer function that will really just allow us to append everything into the state without any overring happening cuz so we want to
132:26
Speaker A
preserve the state. Okay, cool. So now let's actually code this uh react agent. Okay. All right. Okay. Okay, I've cleared the screen now and let's actually begin like we how we always begin with the uh creation of our state
132:41
Speaker A
of our agent. So, type dictionary like such. Okay. And now we we'll only have one key in this uh in this example which is just messages. And now let's use the new type annotations we've learned. So, sequence base message and reducer
133:02
Speaker A
function add messages. So again this piece of code is saying to preserve the state by actually appending it rather than overwriting. That's what this reducer function does. Okay. All right.
133:15
Speaker A
Okay. Oh, and the sequence of base messages is the data type and this provides the metadata. That's why we have the annotated keyword here. That's really it. Okay. Uh now let's create our first ever tool. Now how do we do this?
133:31
Speaker A
Some of you who have a um who have come from lang chain might know how to do this already. We use a decorator and we define like this. Now this decorator basically tells Python that this function is quite is special. It does
133:46
Speaker A
something and well it is special because it's a tool which we're going to use. So let's define our tool as def. Let's create a simple addition tool. Okay. So we'll say a integer b integer.
133:59
Speaker A
It's basically going to add two numbers. And this is where doc strings actually come now. And I'll show you how important they are. For now, let's say uh this is an addition function that adds two numbers together.
134:15
Speaker A
Okay. All right. And we just return a plus b. Simple. Now, how can we actually infuse these tools to our large language model? Well, first let's create a list.
134:31
Speaker A
Add like such. Now, yes, at this current moment, I only have one tool, but in a few moments, we'll have multiple tools.
134:38
Speaker A
That's why I'm adding this uh list for now. And let's actually create our model. So, model is equal to chat openai. Model is equal to GPT40. Again, I'm using GPD40 because I've never had a problem with it to be
134:53
Speaker A
honest. So how can we tell our GPD40 large language model that these are the tools you can use? Well, we can use this inbuilt Python um inbuilt function called bind tools. Bind tools like that.
135:07
Speaker A
And we pass in the list of tools we have. So that's tools. Pretty simple, right? Okay. So now large language model will have access to all of our tools. Okay. So now we need to create a node which actually acts as the agent
135:22
Speaker A
within our graph. So how do we do that? Let me create just a simple function like def model call. We pass in the state agent state. Again it needs to return the agent state.
135:34
Speaker A
Okay. Now I'm going to quickly copy this piece of code. Give me a second. Okay. So what is this code doing?
135:47
Speaker A
uh you can see that we're invoking the model aka running the model and this is the system message which we are asking.
135:55
Speaker A
So we're explicitly saying the large language model that you are my a system please answer my query to the best of your ability. So that's what the large language model's task is to do. Now if we want to get technical here, you could
136:10
Speaker A
have written it in a slightly different way and that way is through this. So remove this. We could have said system prompt. Okay. So what's going on here?
136:25
Speaker A
Remember how I said system message is also something which we imported. Uh so the system message like I said is this line of uh is this line. You are my AS system. Please answer my query to the best of your
136:36
Speaker A
ability. Now, either way would have worked if we if I had just straight up passed this string into here. That would have worked as well. Personally, I think this way is better. Even though they achieve the exact same thing, I think
136:48
Speaker A
this way is better cuz it's more readable. Okay? And you're only adding just one more import. Okay? So, I would prefer you to I would really recommend you doing like uh like this so even the large language model knows that this is
137:01
Speaker A
a system message. Okay, cool. And this is uh just another way of writing like the updated state. You know how we've been writing state uh brackets messages is equal to something something something. Well, this is a more compact
137:16
Speaker A
way of updating the state as well. So return messages response. So we update the messages with the response. No plus equal to this this this or adding something we just we can simply just write it with the updated state. Why?
137:30
Speaker A
because the add messages aka the reducer function handles the appending uh for us. It doesn't overwrite it. Now, if I ran this code and I built the graph and everything, would it work? No. Why it wouldn't work? Because
137:45
Speaker A
think about it, the response when we've invoked the model and we store it in the response when we actually invoked it, we didn't actually pass in the query. How do we pass in the query? Think about it.
137:59
Speaker A
All I passed is my system message. Where does the query go? So to be able to add the query, I actually have to add like this. So state messages. The query it will be in the form of a human message.
138:12
Speaker A
And the human message will be stored in the messages attribute, right? And now that we've passed that into our model as well and we can invoke it. And now this should work.
138:26
Speaker A
Okay. Okay. Okay, so now we define the conditional edge. Now why do we need the conditional edge here? I'll put the picture of the react agent. Again here you can see that the looping part even like in the last one in the graph when
138:39
Speaker A
we made the loops for the first time you saw that was it was a conditional edge which we had to use and now that's actually going to come in play here.
138:46
Speaker A
That's why I took so time to build those graphs because now the concept is coming. So how do we define the conditional edge def should continue. Okay. So again like always we pass in the state and let's do it like
139:10
Speaker A
this like such else return continue. Okay. So as you know as you um might have guessed end and continue will be edges which I'll define later in the graph. But what is going on here? Well essentially when I'll pass in
139:29
Speaker A
the query uh when we've invoked the actual model you will know that we'll create a list of tools right so what we're going to be doing is we're going to be uh getting the last message and we're going to see if there's any more
139:42
Speaker A
tools needed to be ran. If there are then we'll go into the continue edge aka we'll go to the tool node and we'll select the tool and we'll do all this uh actions and then come back. If there's
139:54
Speaker A
no more tool calling left we will just end and we'll just exit the uh graph and that'll be the case. You'll get uh uh you'll understand more what I what I mean when we've actually test we're testing and running the graph. Okay. Now
140:08
Speaker A
let's just define the graph. So like always we create the graph we initialize the graph through the state graph and let's call the node R agent. So the action will be the model call aka the underlying function will be this.
140:23
Speaker A
Okay. Now we create something called a tool node which is also what we covered in the previous uh in the second section or second chapter in this course. The tool node essentially is just a singular node which contains all of the different
140:37
Speaker A
tools. So we only have one tool. If you see what this variable is tools, we only have one tool which is add. Don't worry, we'll add some more tools like subtracts and multiply in a bit. But I just want
140:47
Speaker A
to uh like really solidify your concept of how we can add these tools and how the graph will work. Okay. Now we obviously set our entry point and point it to the R agent. Now let's add our conditional
141:02
Speaker A
edge. So remember remember how I said there's two edges, continue and end. again continue and end and if it goes to the end we end it. If it goes to tools then we go to tool node which is
141:13
Speaker A
tools. Okay. Okay. So yeah this is pretty straightforward still. Right now we also need to add an edge which goes back from our tool to our agent cuz that's how we're going to create a circular connection.
141:27
Speaker A
Right? You can see that the conditional edge only provides a one-way directed edge from the from either the agent to the tool node or the agent to the endpoint. But we need another edge which will go back from the uh tool node back
141:44
Speaker A
to the agent. And that's what this um that's what this edge does. And lastly, we need to uh obviously compile it. So we'll just say app is equal to graph dompile. Perfect. That's it. Now I've just created a a new helper function
142:00
Speaker A
here which this isn't part of langraph. I've just written this code because it will make every like the tool calling and everything uh like output in a much better way. So you'll see what I mean in just one
142:13
Speaker A
second. Okay. So now we actually can begin. So let's say the input is uh something like this.
142:24
Speaker A
Let's say I want to add 3 + 4. Okay, simple. And this line of code basically streams the data. That's all it does.
142:33
Speaker A
So, let's actually run this. Clear. And let's do it. Okay. So, remember we wrote add 3+4. Wow, look at that. So, we've added 3+4. It calls the tool and it even knows what tool to pick. Add. Um, and it gives
142:51
Speaker A
us the result. The tool message as you can see is seven and the AI message the final AI message is the sum of three and four is seven. That's it. Let's try something harder now. Let's write add 34
143:04
Speaker A
+ 21. So if we run this you can see 55 cuz 34 + 21 is 55.
143:13
Speaker A
And you can also see again all the tool calls and everything that's done right.
143:17
Speaker A
I want to show you one two more things actually before we add some more tools which is this. If I remove this dock string here by commenting out for now. Let's clear and let's run that again. Error. Why? Because the function
143:34
Speaker A
must have a dock string if description is not provided. The dock string is necessary. That's why included otherwise the graph won't work. It's remember it tells the LM what that tool is for.
143:47
Speaker A
Okay. So now that we've have uh we've got that there, let's try this as well.
143:52
Speaker A
Add uh 3+ 4. Again, this time I want both of them to be executed. So clear now. Do you think this will work?
144:03
Speaker A
Let's see. Add 34 + 21. Add 3+ 4. Perfect. Brilliant. Okay. So you can see the result of adding 34 + 21 is 55. The result of adding 3+ 4 is 7. You can see how the tool was called twice this time
144:19
Speaker A
and that's the power of the loop which we created. Remember we created the conditional edge and then we also created that directed edge back from the tool node to the agent. Let's let's try to make it even uh give more um
144:32
Speaker A
complicated stuff. Let's say add add 12 + 12 something. So let me clear this.
144:40
Speaker A
Clear. Let's see what happens. Wow, look at this. If I press enter, sorry, I messed up there. But you can see the results of the addition as well as 34 + 21 is 55 7 24 or and you can
144:58
Speaker A
also see that I called the tool the sorry the AI called the tool three times.
145:05
Speaker A
Now these tool calls is also an indication that the LLM didn't use its own like information inbuilt information which it was trained on to come up with an answer. Right? Remember an LLM doesn't know how to do maths. It just
145:16
Speaker A
guesses the next output like through probability. But through this we were able to actually add the two numbers. So an important concept here is the LLM actually decides what should be passed as the arguments to each tool. So
145:33
Speaker A
3 + 4 like if I said add 3 + 4 it will actually uh create it will actually uh input the numbers 3 and four and then this tool will handle the uh information return it and it will go back to the
145:45
Speaker A
agent and then the AI agent will decide what's the answer and everything. So that's how it works. Awesome. Okay. Now let's make this even more complicated.
145:53
Speaker A
Let's add some more tools. Let's add subtract and multiply. Okay. And the only re change we have to do is instead of this one line we just now include subtract and multiply as well. That's it. Otherwise this line this code
146:14
Speaker A
largely stays the same. Now let's actually run this same command and see if it gets confused with the different um different tools we have it has access to. Now let's see. Okay.
146:30
Speaker A
You can see again that 55 724. Okay, it didn't get confused. Perfect. Let's now give it a different command. Let's say something like this. One second. Add 40 + 12 and then multiply the result by 6. So now it has to make
146:50
Speaker A
use of two different tools. Let's see if it gets that. Okay. Wow. Brilliant. So it first used the add tool and then used the multiplication tool and you can see all the queries or all the tool called and
147:04
Speaker A
everything and the final answer is 312. So 52 * 6 yes it is 312. Okay. Wow that works like brilliantly. So now that we know that this is robust what about if I add this let's say also tell me a joke
147:22
Speaker A
please. What do you think will happen? Do you think this will break? Let's see.
147:28
Speaker A
If I play this and run this. Let's see. Wow. Look at this. The result of 40 adding 14 and 12 is 52 multiplying that is by 6 is 312.
147:46
Speaker A
And here's a joke for you. Why don't skeletons fight each other? They don't have the gun. I swear to God, it's always the same dead joke. But you get the point. This is so robust. It can handle even queries where it doesn't
147:57
Speaker A
even need a tool and that ladies and gentlemen is the power of langraph. So it's it's so robust even if we don't need to use a tool it will still give us an answer and the reason it was able to
148:10
Speaker A
do that is once all the tool calling is done it passes it to the agent the agent checks again oh I need to tell it I need to tell the user a joke as well and adds that to the final information and then
148:20
Speaker A
ends it that's the power of lang okay so after all of that we finally now know how to create a react agent yes it was a simple react agent but the concepts the same. You can create your own external tools from now
148:34
Speaker A
onwards and you can create your own graph. And that was the whole point of this course, right? For you to actually understand how we can uh create these um how we can use different tools and then the rest is up to you. It's up to your
148:46
Speaker A
imagination. Okay, perfect. So now I will see you at the next subsection. All right, see you there. Okay, people. So we've made great progress so far. So well done on that. But now we make a fourth AI agent. And this time we'll do
149:03
Speaker A
things again slightly differently. Well, this time we're going to be making a mini project together. So the project's name is going to be called Drafter. And you'll see why in a minute. So picture this. Me and you are working in a
149:18
Speaker A
company together. And our boss comes up to us and she has a problem and some orders for us. So the problem is this.
149:27
Speaker A
Our company is not working efficiently. We spend way too much time drafting documents and this needs to be fixed.
149:33
Speaker A
Again, a valid problem. So, what are her orders? She says you need to create an AI agentic system that can speed up drafting documents, emails, etc. The AI agentic system should have human AI collaboration, meaning the human should
149:48
Speaker A
be able to provide continuous feedback and the AI agent should stop when the human is happy with the draft.
149:55
Speaker A
The system should also be fast and be able to save the drafts. Okay. So then me and you start discussing and we are going to use land graph obviously and we come up with a sketch. Now the sketch of
150:09
Speaker A
our graph is something like this. It obviously is going to have a start and an end point and it's going to have our agent and the agent will have access to tools aka the tool node. Now this looks
150:20
Speaker A
similar to a react agent which we covered in the last subsection. But there's a reason we don't we haven't chosen to do that. See we realize that one of the tools is the save tool. It will save the draft, right? That was one
150:33
Speaker A
of our requirements. But obviously when we once we've saved it, the process should end, right? But if you remember from a React agent, the tools always goes back to the AI agent, not directly to the endpoint. And we don't want that
150:48
Speaker A
anymore. So that's why as soon as the save tool is used because the save tool will be within tools right it ends. So that is the structure we have chosen to go with. So the only thing left is to
151:01
Speaker A
actually code this graph. So let's code this together then. Okay. So let's actually code up this drafter project then. So you can see I've already done all the imports and I've loaded up my env file. Now all of these imports are imports which
151:18
Speaker A
you've already uh encountered before. So there's no point in looking at them again. But the first thing which I'm going to do is I'm going to be defining the a global variable.
151:28
Speaker A
Now this global variable yes it's a bit odd defining global variables and there's a reason which I've done it and this will become more apparent as I go through the code but just as a heads up the reason I've defined a global
151:41
Speaker A
variable in this case is to actually pass in a state in tools the the correct way to do it in langraph is through something called injected state now injected state is beyond the scope of this uh course so the workound on that
151:58
Speaker A
is to use a global variable and what will happen is our tools will uh whatever updates are made uh we'll update the global variable and then when we go on to save it uh the save tool will use the contents in this global
152:15
Speaker A
variable and save that into a text file. So that's why this is included. Okay. So now let's define our agent state again.
152:24
Speaker A
And the way that's done is the exact same way we did last time. Uh class agent state messages annotated sequence base message add message as the reducer function. So now we define the tools and there will be two tools for this. The
152:39
Speaker A
first tool will be the update tool and the second tool will be the save tool.
152:43
Speaker A
So let's start off with the uh update tool and I will obviously use the decorator and then create def update and then we need to pass in uh pass in a parameter content. Now just as a refresher whatever parameters you
153:02
Speaker A
pass or you request who actually gets those parameters? Well, the LLM or your model in the background that's uh what will automatically pass the parameters for this model uh for this tool. So, uh in this case the content parameter will
153:18
Speaker A
be uh that will be provided by the lm in the background. So, you don't need to worry about that. Okay. So, now we need the dock string obviously and I've just created a simple dock string which just updates the document with the provided
153:30
Speaker A
content because that is exactly what it does. So now we define to interact with the global variable in Python, you obviously need to uh define it uh you need to code it like this and then you need to update
153:45
Speaker A
your document content aka the global variable with your current content and then you just return again a statement to the like the large language model telling it that we have successfully updated it. So I've written document has been updated successfully. The current
154:01
Speaker A
content is this which is the content which we store in the thing. Okay. So now we define our second tool which is the save tool. So again same decorator we use uh like this. And now we request the llm to give
154:19
Speaker A
us a file name as well. So it will it should give us a suitable file name uh which will be a suitable file name for the text file and uh it will and now this save tool will automatically handle
154:31
Speaker A
all the save logic. So uh as a dock string I pass like this. So saves the current document to a text file and finishes the process. And the arguments are file name which is the name for the text file. Now, I've specifically
154:47
Speaker A
mentioned that we're going to be using a text file so that the uh uh the LLM knows that the file name which it needs to pass has to have a txt in the end of it. Now, if it doesn't uh by any means
155:02
Speaker A
to make the uh graph to make the entire code more robust, I've also written this if statement such that if this file name doesn't end with a txt, just put a txt there just uh as robust as measure. Now
155:14
Speaker A
again we need to uh call the global variable again. So global document content. Okay. Now this next bit of code that's this is not langraph. This is just uh whatever you put in the tool. Uh it it doesn't have to it's not going to
155:28
Speaker A
be langraph related. Right. So this piece of code is just uh some code which allows you to save the uh contents a the the content store in in the global variable under the file name uh and as a
155:44
Speaker A
text file and I've also added this exception uh which is a good thing for debugging purposes where it if there's an error it will tell me exactly what the error is and then we can fix it.
155:55
Speaker A
Okay. So hopefully there won't be any errors. Now we create a list of tools which uh again will be update and save because we only have two tools. And now we actually call the uh model and how do
156:11
Speaker A
we call the model like such? Now let me ask you a question. Is this it for the model definition or do we need something else? Well, there's a reason I asked that question, right? We forgotten to do bind tools. So bind tools and tools. So
156:28
Speaker A
that will do. Okay. Now we actually initialize the agent itself or the function which will cuz remember the agent will be a node in our graph. And what will be the function behind that?
156:42
Speaker A
It will be this function which we're about to define. So let's write this as def r agent. And again we need to pass in the state the agent state and it'll return the agent state.
156:55
Speaker A
And okay so now this doc uh not doc string this we need to pass in a system message to our llm right now this llm this system prompt will be quite large so get ready uh like such so in this system prompt I
157:11
Speaker A
have specifically said this is a system message and the content is this you are drafter a helpful writing assistant you're going to help the user aka us to update and modify documents and I've also written some more stuff about what
157:26
Speaker A
the uh update or what what to do if the user wants to update. We use the update tool. Uh we need to use the save tool to save it and to always show the current document say after modifications and all
157:38
Speaker A
that stuff. Cool. Okay. So, oops. There we go. And now it's time for some robustness measures. So when we're first initializing the graph like when it's the first message we're writing obviously we're not going to straight up say uh how would you like to change the
157:57
Speaker A
document right because we haven't passed in a document yet. So if messages uh this part if that if there's nothing in it we will have to say something like an introduction message right. So this is how you can do that. So we can
158:15
Speaker A
say if not state messages aka if there's nothing in the state messages then we can say uh I'm ready to help you update a document. What would you like to create? and then it collects the user input and passes it as a put stores it
158:30
Speaker A
as a a human message in this user message variable. Now what if I've already passed it uh passed in a message or like we are on the process of updating our draft or drafting it. Well to do that we need this else statement
158:46
Speaker A
and what does this say? Well it says what would you like to do with the document? So this assume this says that there's already stuff in the messages uh state a messages key in the state how do you want to update it further and then
158:58
Speaker A
we also print it uh under this emoji uh in the terminal so the user can also see what they've inputed and then this is also stored in the user message. All right. Okay.
159:11
Speaker A
Now we combine all of this uh all messages aka the system prompt which was the system message uh and we create a list of uh list of the uh state messages and the user message the new message which we want the aka the update and
159:28
Speaker A
then we just invoke the model and how do we invoke the model you just use the uh model invoke okay so pretty basic code so far there's nothing hard or nothing uh extraordinary or something we haven't seen before. All of this we have seen
159:44
Speaker A
before. And now the rest of this function is just a print statement which I've included. This print statement is just for uh um making things look prettier on the terminal. That's all it is. You can see the true print
159:59
Speaker A
statements. There's the AI response which will be printed and then there'll be the tools uh whatever the tool messages are that's also printed. So that's the whole point of it. there's nothing like to really like talk about it here. Uh and then we also need to
160:12
Speaker A
obviously return the updated state. Now remember last time I showed you that this is also a really convenient concise way to uh update the states. So from now onwards we're only going to update the states like this. Okay. Now we create our
160:30
Speaker A
conditional edge function or the function behind the conditional edge cuz remember let me open this up. So the conditional edge which I'm talking about will be this this this conditional edge.
160:42
Speaker A
So there from tools there will be either the select the uh the choice of going to back to the agent or the choice of ending it. So we need to create the underlying function behind that. So let's create that now
160:58
Speaker A
uh under this. So should continue. We've done this many times before. it det will determine if we should continue or end the conversation and remember continue or end the conversation. Okay, makes total sense. Okay, so now we do this. So we get the messages
161:21
Speaker A
and if there's nothing in the messages, well obviously we'll need to continue, right? It won't go to the end part. Uh and this is just as like a robustness measure to be honest.
161:32
Speaker A
Okay. So now this piece of code is basically saying look at the most recent tool message or the uh recent tool we've used and we need to check if this tool uh has used the save tool. Now why remember how we have two tools we
161:51
Speaker A
have either the uh update tool or the save tool. If we use the update tool, well, we will obviously need to use the continue branch, right? But if we use the uh save tool, well, after you saved it, there's nothing else to do, right?
162:08
Speaker A
You finished your draft, you finished everything, so might as well end the program. That's why this end tool. So, for the continue, uh if to go to the continue um through the continue edge, we have to use the update tool. And to
162:22
Speaker A
go to the end uh edge you need to use the uh the save tool. So should make sense now but don't worry if it doesn't we will do some more print statements so you see the workflow. Don't worry. And
162:35
Speaker A
lastly we need to obviously return continue because by default it's checked here that it's used the save tool. The only other tool left is the right tool and uh sorry the update tool. And the update tool means that we have to go to the continue edge,
162:52
Speaker A
right? Okay. And that's that uh function done as well. So pretty easy still. Now this next function is again I only coded this just to make the print statements in a more readable message format uh when we printed on the terminal. So you
163:09
Speaker A
will see where this comes in play when we actually start uh invoking the graph and seeing how our process is going.
163:15
Speaker A
Okay, cool. Okay. So now we actually init uh create the graph. So how do we create the graph? We've done this many times. We will initialize it through a state graph. And now we will add the nodes. So agent and tools. And the tools
163:33
Speaker A
will be a tool node. And again if you notice back we had one node, two node, the agent node and the tools node.
163:41
Speaker A
I'm keep I'm like reflecting back and forth between this diagram and the code so I can show you exactly what we're coding. Okay. So again agent and tools node uh we've done now we will set the entry point at
163:54
Speaker A
agent which is the start point aka this part right and now we're going to add an edge between agent and tools. Now we need to obviously create this edge because the agent needs to go to the tools right and
164:09
Speaker A
then this edge this directed edge and this conditional edge creates the loop uh which will allow for the human AI collaboration. All right. Okay. So now we add the conditional edge and that's the conditional edge which I was talking
164:25
Speaker A
about the continue at the end aka this condition this conditional edge from tools. Okay.
164:32
Speaker A
And now the last thing we need to do is just compile it because we've finished the graph completely, right? There's nothing left. We've done the start point, we've done the end point, the end, this conditional edges done, the
164:44
Speaker A
nodes done, and then this directed edge is done and the start point is obviously done because we've uh created a directed. So you can see the entire graph we have created just like that. So again, nothing too hard. Cool. Okay. So now we actually run
164:59
Speaker A
the program. And to run it, I have just written this um function so that everything is in a more compact way.
165:07
Speaker A
This is just to invoke the graph. Okay. And let's do that. So that was the entire code. And this code will allow for human AI collaboration. Now, yes, we used a global variable. And again, there is nothing wrong with using a global
165:23
Speaker A
variable. I know some of you might frown upon it, but um again, there's nothing wrong with it. If we wanted to use more complicated uh form uh complicated uh stuff from langraph like the injected state or even using something like
165:37
Speaker A
commands and interrupts uh we would have to write the code slightly differently but because this is a beginner level course uh we've just disregarded that completely and we found another way of performing human AI collaboration.
165:51
Speaker A
Awesome. So let's actually run this now. So let's write python draft. py and you should be able to see all of the things. I made my face cam slightly smaller so you can hopefully see everything. Perfect. So you currently
166:06
Speaker A
have an empty document. Could you let me know what you like to add or create in the document? So what would you like? So let's say we are writing an email to our colleague Tom saying that we can't make
166:17
Speaker A
it to the meeting. So let's say write me an email. Let's say uh write me an email to Tom saying we I cannot make it to the meeting. Let's see what it says. So it says uh hi Tom I hope this message find you
166:37
Speaker A
well. Please let me know. Okay let's now give it some feedback on how we how we can improve. So and also you can also see that it's used the update tool as well. Perfect. So, let's say um make sure to also have specified that
166:57
Speaker A
the meeting was supposed to be at 1000 a.m. at some random negation. Canary Wolf.
167:09
Speaker A
Okay. Okay. Let's see the updated thing. Hi, Tom. Uh you can see message meeting at 10. Uh, can I wolf due to unforeseen circumstances? Uh, let's I don't like this uh your name part though. So, let's say my name is
167:27
Speaker A
V and it will update that as you can see. Perfect. Uh, what do what else do we want to change? We can also say something like uh let's say but tell him that I can make it at 12 p.m. in
167:48
Speaker A
um New York, some random location. Okay, I'm making this up, but you you get the uh plan. Uh the next day. So, let's see. And perfect. It's updated it.
168:03
Speaker A
However, I am available to meet at 12:00 p.m. in New York the next day.
168:06
Speaker A
Obviously, it's complete like rubbish like the timings of the location I've written. But you can see how we can just uh use human AI collaboration here. Uh one more thing which I don't like is this part. I don't like the fact that
168:20
Speaker A
it's not a new line. So, I mean I'm being a bit picky here. We can say something like uh put the II hope this message finds you well. Awesome. And as you can see that's done as well. So now let's say I like
168:41
Speaker A
it. Save it please. And what happens? You can see that uh it used the save tool. The tool results is document has been updated successfully. The current content is this and the document has been saved to unable to attend
168:59
Speaker A
meeting email. Now remember we never passed in the file name at all. That was all generated by the by the agent itself. And to check we need to go on unable to attend meeting. So let's see here it
169:12
Speaker A
is. And you can see it's the exact same meeting uh exact same email we said. So, subject, oops, best regards me. All the exact same content. Perfect. And we don't even need to uh make it so that we're drafting emails. We can even drop
169:29
Speaker A
short stories. We can drop whatever we want. In fact, we can also pass in uh a previous message. So, the reason it started off like with nothing is because we pass in an empty list. But if you wanted to, we could have written
169:45
Speaker A
something over here uh with our pre with a already existing email or already existing document and then it could the model the agentic system would know that this is what the content is the current content how would you like to uh change
170:00
Speaker A
that and that is exactly how uh we will be able to operate on our existing ones.
170:06
Speaker A
So you can see that this is quite a robust thing. If we want another example, for example, uh let's say python drafter.
170:17
Speaker A
py. Okay, now watch this as well. Look how robust this is. If I say something like write an email, it actually gives back questions.
170:28
Speaker A
So sure, what would you like the email to say? D. So remember, it didn't even go through any tool here. uh using langraph we can really make the agents quite robust and that's the thing which I wanted to show you it doesn't always
170:42
Speaker A
have to pick a tool its own like LLM like the agent itself cuz remember the agent node has an LLM in the background back end the bind tools function allows it allows it scope like it increases the scope of it uh by providing some tools
170:58
Speaker A
but that doesn't mean it has to use those tools if it doesn't feel like the need to use the tools it won't and in this case it wanted to ask us more questions about it. So it would say show
171:09
Speaker A
what would you like this email to say because to be fair I only wrote three words. Uh but that was what I was trying to show you. So let's just clear this now cuz we don't need to. And yeah you
171:20
Speaker A
can see perfectly works human AI collaboration in langraph and this is actually somewhat useful as well. Now yes of course you can use GPT4 canvas and all of that stuff of course but um this is how you would do it in Lagraph.
171:34
Speaker A
All right. So, if you would like an extension to this, what you could do is add a voice feature as well. So, maybe you could add use OpenAI whisper for uh speech to text conversion or add 11 laps
171:48
Speaker A
for text to speech conversion and maybe you can make it voice based cuz right now I'm giving it I'm how am I communicating it with text mode? What about voice mode? You could also include a GUI to this. There's a lot of stuff
172:02
Speaker A
which you can do on you can even have your own knowledge base as well and include that. So a lot of potential with this if you want a homework for this uh specific project that there you go. All
172:14
Speaker A
right. Okay. Cool. So that's the end of this subsection. Awesome. So now let's build our fifth AI agent. And some of you might have been looking forward to this.
172:25
Speaker A
It's retrieval augmented generation rag. So what will the graph look like? It will look something like this. Again, start point, end point, really similar to what a react agent was, right? But uh we have two agents in this case. We have
172:40
Speaker A
a retriever agent and we have our main agent LLM, right? So, and it will have obviously a conditional edge, a loop, and everything. Again, we're bringing everything we've learned so far and merging them into one. And we're also
172:52
Speaker A
going to be learning about a little bit about rag. Now, I'll assume you know what rag is. I'm not going to go too much in detail into like the nitty-gritty of it. But again, in the surface level, I will obviously explain
173:04
Speaker A
what rag is about and everything. Okay. So, if you're excited, let's uh let's jump to the code. Okay. So, now you can see that I've already done all of the imports which we'll need. But you'll notice how there are these four imports which we
173:18
Speaker A
haven't come across yet. Now, rather than explain them from the get- go, I will explain them as they come because it'll make more sense. uh it'll make more intuitive sense that way. Okay. So now I'm going to be loading our uh ENV
173:32
Speaker A
file which contains all the API keys. And this time I'm going to be initializing our LLM differently. Well, slightly differently. It's the same LLM, but why did I say differently? Because I've passed in a new parameter called temperature. Now for those of you who do
173:48
Speaker A
not know what temperature is, it's essentially a parameter which depicts how stochastic the model outputs how stoastic you want the model outputs to be. So because I've set it to be zero, temperature equal to zero makes the model output more deterministic.
174:03
Speaker A
Similarly, if I had set the temperature to be one, the model output would have been more stochastic. Okay. So now we create the embedding model. And the embedding model uh is what's going to convert our text into vector embeddings. Right? Uh so this
174:21
Speaker A
will be the layout for it. Now please note one important thing which is the embedding model has to be compatible with the LLM we're using. You can use whatever LLM you want but make sure the embedding model uh is compatible with
174:35
Speaker A
it. For example uh let's say we're using GBD40 uh an open model but the embedding model we're using is from Olama some random model. Now that they wouldn't most likely they're not going to be compatible. Why? Because there's so many
174:48
Speaker A
differences between them. One potential difference could be the vector dimension. So just a rule of thumb. Make sure the LLM and the embedding model is compatible. Okay. Awesome. So now we're going to specify the PDF part. So this
175:04
Speaker A
is the stock market performance 2024 PDF. And essentially this is just a document which I created which contains um a lot about the stock market performance. Okay. Uh I can show you that right now actually. So this contains nine pages and is just a
175:20
Speaker A
document containing about some stock market details in 2024. Okay. Awesome. So now um in case you've specified the uh you have put the PDF in a wrong directory or if it can't find it uh this error will pop up. So again I've just
175:38
Speaker A
put this for debugging purposes if you use the code which I provided on GitHub.
175:42
Speaker A
Okay. Now this will load the PDF and you can see pi PDF loader is one of the imports which we made here. So again it's in the name and the common. It just simply loads the PDF. Okay. Uh and this
175:58
Speaker A
try and accept command uh just checks if the PDF is there. And pages is equal to PDF loader.load. So this essentially says how many pages are there in the document. So you can see there's nine pages in our document. So if I run this
176:15
Speaker A
command, if I run this, so clear python rag agent.py py it should say nine pages.
176:28
Speaker A
So there we go. PDF has been loaded and has nine pages as expected. Right? Okay.
176:34
Speaker A
Now it's time for the chunking process. Now what is chunking? First look at this. There are two parameters which I've specified. Chunk size which is a,000 and chunk overlap which is 200. So let's break this down a bit. Going back
176:48
Speaker A
to our document. So chunk size was 1,000 tokens. So let's say that this was a chunk for example. Okay, obviously that's not going to be a thousand tokens, but just as like uh demonstration purposes, let's assume it is. So this is saying as soon as you've
177:05
Speaker A
reached 1,000 tokens, you create a new chunk. So let's say 1,000 tokens ended here. So this would be the start of a new chunk like such. Okay. And you keep going and going and going until the end of the document. But what if the what
177:17
Speaker A
about the second parameter? The second parameter is specified overlap and that's essentially saying let me use it in a different color that your chunks consecutive chunks should have some tokens um which are which exist in both for example because it was 200 the
177:33
Speaker A
second chunk is not going to start from here. It's actually going to start something like this. They're obviously going to be the same length uh in terms of tokens but they will have some tokens which will be in both chunks. So for example, this
177:48
Speaker A
part will be in both cuz that's the overlap. 200 tokens to be precise. Okay, so that was just a brief overview of what chunks are in uh rag. Okay, so that's that part done. And again, this recursive character text splitter is one
178:04
Speaker A
of the imports we did. Okay, so this text splitter um chunking process, we now apply it to all of the pages, all of our nine pages in our document. Okay.
178:19
Speaker A
And this piece of code essentially saying this, the chroma vector database, we're going to be using a chroma vector database to store all of our vector embeddings, by the way. But the uh the place where we want our chroma vector
178:34
Speaker A
database to be will be specified in this file path. And the collection's name will be called stock market. Now, you can specify it wherever you want obviously, but I've just specified it to be in the same folder. Okay.
178:47
Speaker A
So this is just an if statement to make sure that uh if this is the first time we're running this command uh if we're running this file uh if this collection doesn't exist we will create the um collection in the specified directory.
179:06
Speaker A
Okay, again not too hard yet. Now here comes a try except command u try accept block. So this is where we actually create the vector embedding uh where we create the chroma vector um database and these are just parameters
179:21
Speaker A
which I specify. So for example, how I want the pages to be split, what embeddings to use, where to store it and the collection name. The collection name being stock market, right? And if there is an error, it will throw an error and
179:33
Speaker A
if it's successful, it'll print on the terminal. Okay, awesome. So now we create something called a retriever. So the retriever is quite important in rag.
179:43
Speaker A
It's well obviously the first part of rag retrieval augmented generation. So the retriever is what actually well retrieves the chunks the most similar chunks. Um the search type which we're going to use similarity. It's just the default anyway. Uh you don't really need
179:58
Speaker A
to know how that works to be honest. But what you do need to know is this part.
180:03
Speaker A
So in this code I have made sure that every time uh it goes the amount of chunks it uh outputs back is five. Why?
180:14
Speaker A
Because k here is the amount of chunks to be returned. So I've set it as five.
180:19
Speaker A
Now I'm pretty sure if we go to the actual documents here the default the default is four. Okay. So uh this is just a parameter which you can uh set.
180:31
Speaker A
Now you don't want it to be too high of course or too low. So you want like a good middle ground and 405 is a good middle ground in my opinion. Okay. So now let's create our tool. So again we
180:42
Speaker A
use decorator tool. And the tool's name is going to be this retriever tool. It will input it will take in a query and it'll output a string. So the dock string is as follows. This tool searches and returns the information from our
180:56
Speaker A
document. Okay self-explanatory. uh and obviously we need to invoke it to the retriever. So whatever query we ask for example uh what was Apple's performance in 2024 that will be the query and that will be passed to our
181:13
Speaker A
retriever which will grab all the chunks the most the top five most similar chunks. Okay. Now if we don't if there's nothing similar uh which it finds for example if I say something like uh who's Bob the builder something like that
181:28
Speaker A
right obviously Bob the builder is not in this document uh so it will return as I found no relevance information in the document and uh this will be passed to our LLM agent okay if it does find it
181:41
Speaker A
though what we'll do is we'll create an empty list and we will store all of the similarity um us the all of the chunks which it found and then return those results uh through this. Okay, still it's quite
181:56
Speaker A
easy still uh and this piece of code we've already come across. There is only one tool. So we just bind that tool to our LLM. And this also code we have also we've uh done many times. It's the uh
182:14
Speaker A
creation of the agent state. And again we're using our add messages reducer function. All of this we've covered many times so you should be quite familiar with it. Okay. So now we create the should continue function and the should
182:27
Speaker A
continue function uh is going to be the underlying function between our conditional edge behind our conditional edge. So it will check if the last message contains any tool calls. If it does then we um proceed. If it doesn't
182:41
Speaker A
then we'll just end right. Okay. So now we specify the system prompt. Now this system prompt is going to be quite big. So let me copy and paste it here. Now the reason is quite big is I want to specify as much
182:56
Speaker A
information to the LLM so that it knows what to do. Right? So I've just said you're an intelligent AI assistant who answers questions about the document uh loaded into your knowledge base. Uh you can read the rest if you would like. But
183:09
Speaker A
I've also written this. Please always site the specific parts of the document you use in your answers. This is really just to make sure it's not hallucinating. Right? because as we know hallucination is quite a big problem with LLMs. So this is just to make sure
183:24
Speaker A
um hallucinations are kept to a bare minimum. Okay. All right. So now we create a dictionary of our tools and we now create the underlying function which will be our LLM agent. So this function will call the LLM with the current state
183:42
Speaker A
and you can see it converts the messages to a list passes the system messages and passes it to our LLM which is defined like this and it will just return the messages aka the updated state. Okay, this should be like such.
183:59
Speaker A
Okay, awesome. So now we create our second agent which will be the retriever agent which you saw on the in the graph which I showed you in the introduction.
184:09
Speaker A
So the retriever agent executes the tool calls from the LLM response. So what is this code actually saying? Well, all in all, this massive piece of code really just says if there is a tool, if the tool name is within the is a proper
184:27
Speaker A
specified tool, aka if it's retriever tool, then actually run it. If it's not, then we will output the result as input in incorrect tool name. Please retry and select the tool from list of available tools. It's just for checking if a if
184:42
Speaker A
the tool which is decided from the LLM is valid or not. So that's all what this is doing. If it is valid, it will invoke it and we will store the results uh like this and we will return that. Okay.
184:55
Speaker A
Again this should be agent state like such. Okay. So we've created all of our our two um AI agents now and now we're going to create the graph itself. So like how we've done initialize it through state graph and then we're going
185:14
Speaker A
to add our two AI agents as nodes with their respective actions and we are now going to add the conditional edge. So which will be llm which will be start from l lm and the should continue function is the function
185:30
Speaker A
which will be um the underlying function and this is a uh true false statement and this is the edge the set entry point all of this we've covered many times so again should be quite familiar to you and last but not least compile the graph
185:49
Speaker A
and store it in a ragation okay one last thing though uh I've created this function and this function is just a function which allows us to keep asking questions to our graph and keep receiving qu uh answers back and if you
186:05
Speaker A
want to exit we can write either exit or quit um and it's just a simple while loop that's all it is okay and it prints the answer okay so that's the actual code complete now we're going to test it and
186:20
Speaker A
see uh if the if this is reliable or not. Okay. Okay. So, let's actually test this now um by doing python rag agent.
186:32
Speaker A
py. Let's run this. Okay. PDF has been loaded and has nine pages. Created chromo vector data uh chroma database vector store. So, where is this stored? Well, you can see that this is uh by the way, this will all be
186:48
Speaker A
on GitHub as well. But this is the Chroma database and its respective um bin bin files. Okay. And we can even view it.
186:58
Speaker A
But it'll look something like that. Okay. But because this has been created, this is a good sign that everything is working. Okay. So, let's ask a simple question. Uh let's ask something like how was the S&P 500 uh performing in 2024? Enter. So it's
187:22
Speaker A
calling the retriever tool uh with the query this uh its result then puts that complete back to the model and the model has given us this. In 2024, the S&P 500 delivered a total return of this with a
187:34
Speaker A
23% increase late 1990s and all of that stuff uh magnificent 7 and has given us the uh respective uh citations as well.
187:42
Speaker A
Now, how can we verify this is uh correct? Let's see. So, notice how if you remember this part, the total return of approximately 25%.
187:55
Speaker A
Well, the reason I prom I asked it for this is because that's exactly what uh over here it stated the benchmark roughly at 25% 23%. Uh remember this late 1990s part that's exactly what this is saying here as well and this was
188:12
Speaker A
correctly defined in the first document. So this is clearly working now right it can't have made up this information. So that means our rag is successfully set up. Now I can ask as many questions I possib as I want now but now let's see
188:26
Speaker A
if there is something which is not included in the rag. So for example we can say something like how did open AI perform in 2024 retrieve a tool called back to the model. Okay, now look at this. Uh if I
188:46
Speaker A
do it like that, the documents do not provide specific information about OpenAI stock performance, which is true cuz OpenAI is not a publicly traded company. Uh and yeah, it got that correct. So no hallucination there. So you can clearly see that this is working
189:02
Speaker A
uh completely fine. And that ladies and gentlemen is how you create a retrieval augmented generation graph in Langraph.
189:11
Speaker A
Okay. Awesome. All right people. So that brings us to the end of this course and I hope you liked it and I hope you learned a lot about Langraph. Now although this course is finishing here, your journey in Langraph
189:25
Speaker A
is just beginning. Just think about how many cool AI projects, AI agent systems you can make now. Maybe your own Javis as well. Now, if you have any further questions related to the course material or just things in general or just want
189:39
Speaker A
to say hi, you can always message me on LinkedIn. With that being said, thank you so much for watching this course and I hope to see you in another course.
189:48
Speaker A
Take care.
Topics:LangraphPythonconversational AIgraph-based AItype annotationslambda functionsAI agentsLangChaincoding tutorialfreeCodeCamp

Get More with the SozAI App

Transcribe recordings, audio files, and YouTube videos — with AI summaries, speaker detection, and unlimited transcriptions.

Or transcribe another YouTube video here →