WEBVTT

00:00.000 --> 00:01.200
-: In this video we're gonna have a look at

00:01.200 --> 00:03.300
how you can customize LangGraph state

00:03.300 --> 00:05.490
beyond just using the messages key

00:05.490 --> 00:07.020
inside of the state graph.

00:07.020 --> 00:08.220
This is important because

00:08.220 --> 00:11.580
what you wanna do is not just have specifically

00:11.580 --> 00:14.220
the message history, but if you can have lots of other keys

00:14.220 --> 00:16.890
inside LangGraph, that's gonna give you the flexibility

00:16.890 --> 00:19.050
to have lots of different types of Boolean flags

00:19.050 --> 00:22.590
so that you can control different types of edges and nodes

00:22.590 --> 00:25.020
and conditional edges based on some Booleans

00:25.020 --> 00:26.550
or some state that's stored

00:26.550 --> 00:28.710
inside of the LangGraph state machine.

00:28.710 --> 00:30.480
We've got some imports that we do

00:30.480 --> 00:33.300
and we're also just setting up my Tavily key,

00:33.300 --> 00:36.030
and then we're gonna have a look at customizing the state.

00:36.030 --> 00:39.420
So again, the important point of this lesson is

00:39.420 --> 00:42.060
that we're doing exactly the same stuff we've done before,

00:42.060 --> 00:45.300
but we've got a new flag, which is to ask_human

00:45.300 --> 00:47.850
and the reason why we are using this ask flag,

00:47.850 --> 00:49.890
and you could have lots of different pieces of state here,

00:49.890 --> 00:53.083
so I could also have ask_for_final_review.

00:54.489 --> 00:56.580
And I could have a Boolean piece of state here,

00:56.580 --> 00:58.650
but we can add lots and lots of different pieces of state.

00:58.650 --> 01:00.750
But the important point is that you can,

01:00.750 --> 01:02.910
if you want to do more complex things outside

01:02.910 --> 01:05.610
of just the message history, then it can be useful

01:05.610 --> 01:08.280
to have extra bits of state inside of LangGraph

01:08.280 --> 01:09.600
that you can manipulate.

01:09.600 --> 01:12.481
So you can see here we have a RequestAssistance

01:12.481 --> 01:16.379
piece of schema and we are going to create a tool,

01:16.379 --> 01:18.829
and the tool that we have is TavilySearchResults.

01:19.778 --> 01:23.280
And we're also going to have this RequestAssistance

01:23.280 --> 01:25.950
as a separate tool that we use.

01:25.950 --> 01:28.187
So you can see where here we have a Pydantic model,

01:28.187 --> 01:30.720
which is escalate the conversation to an expert.

01:30.720 --> 01:33.510
Use this if you're unable to assist directly.

01:33.510 --> 01:35.670
And so we're binding the LLM with both

01:35.670 --> 01:38.093
the Tavily search tool and also the RequestAssistance tool.

01:39.959 --> 01:43.230
And we have a chatbot which will invoke with the tools

01:43.230 --> 01:45.690
and it sets the ask_human to false.

01:45.690 --> 01:47.070
If there are tool calls,

01:47.070 --> 01:51.525
and the tool calls name is the RequestAssistance name,

01:51.525 --> 01:55.339
we set the ask_human to true and then we return the messages

01:55.339 --> 01:57.750
and the ask_human.

01:57.750 --> 02:00.150
Now we then build the state graph

02:00.150 --> 02:02.970
and we have our chatbot node that we had before,

02:02.970 --> 02:04.860
which is now this Python function.

02:04.860 --> 02:06.060
And we have the tools

02:06.060 --> 02:10.080
and the tool node being just the Tavily search results.

02:10.080 --> 02:12.690
Now, when we have a response,

02:12.690 --> 02:14.850
we are also going to have a little helper message

02:14.850 --> 02:16.901
for returning a tool message,

02:16.901 --> 02:19.290
which will just return the response from the AI

02:19.290 --> 02:23.160
and the tool call from the first one inside of that AI.

02:23.160 --> 02:26.460
And we have a human node which is

02:26.460 --> 02:28.020
basically getting a list of messages.

02:28.020 --> 02:29.520
And if the messages,

02:29.520 --> 02:31.230
if there isn't any messages at the moment,

02:31.230 --> 02:33.420
then we don't have a response from the human.

02:33.420 --> 02:36.210
So typically the user will have updated the state

02:36.210 --> 02:37.050
during the interrupt.

02:37.050 --> 02:39.750
If they've chosen not to, we'll include a placeholder,

02:39.750 --> 02:42.750
a tool message just to let the LLM continue.

02:42.750 --> 02:45.360
So that's a nice way of us being able to

02:45.360 --> 02:47.850
always add a tool message on just in case

02:47.850 --> 02:50.210
of the human node doesn't have

02:50.210 --> 02:53.991
a response from the human from the new messages.

02:53.991 --> 02:56.670
But if it does, then what we're gonna do

02:56.670 --> 02:59.220
is then unset the flag to false.

02:59.220 --> 03:01.110
And we have this node now called human.

03:01.110 --> 03:02.160
So we've got a couple of different nodes.

03:02.160 --> 03:04.860
We've got the chatbot node, the tools node,

03:04.860 --> 03:06.750
and also the human node.

03:06.750 --> 03:09.731
And we need a function to define

03:09.731 --> 03:12.060
what is the next node going to be.

03:12.060 --> 03:15.630
So if the ask_humans flag in the LangGraph state

03:15.630 --> 03:19.290
is set to true, we are going to return the human.

03:19.290 --> 03:21.360
And otherwise we're going to have the tool condition,

03:21.360 --> 03:25.173
which will either go to tools or __end__.

03:27.360 --> 03:30.300
We then build our graph with the chatbots

03:30.300 --> 03:31.590
and we select the next node.

03:31.590 --> 03:33.090
And if it's returned to human,

03:33.090 --> 03:35.970
we're gonna go into the human node,

03:35.970 --> 03:37.350
and remembering that the human node

03:37.350 --> 03:39.270
will run this Python function.

03:39.270 --> 03:42.600
And if it's the tools, that will run the tools node,

03:42.600 --> 03:44.580
which we've defined up here.

03:44.580 --> 03:47.070
And remember that the tools node is only using

03:47.070 --> 03:48.840
the Tavily search results.

03:48.840 --> 03:51.690
We have bound two tools to the chat model,

03:51.690 --> 03:53.640
which is the RequestAssistance tool.

03:53.640 --> 03:56.550
But that is only being used not inside

03:56.550 --> 03:58.230
of the tool node directly.

03:58.230 --> 04:01.170
And we also have the end which gets mapped to the end.

04:01.170 --> 04:03.360
And so we've built our conditional edges

04:03.360 --> 04:06.000
and we then add the edges from the tool to the chatbot

04:06.000 --> 04:07.347
and the human to the chatbot.

04:07.347 --> 04:09.330
And we set the entry point to chatbot.

04:09.330 --> 04:12.030
And then we're using a chat pointer here

04:12.030 --> 04:13.740
whilst we compile our graph.

04:13.740 --> 04:16.980
And we are also interrupting before the human node.

04:16.980 --> 04:18.210
And this is important

04:18.210 --> 04:22.080
because we want to update the state of the human node,

04:22.080 --> 04:24.150
but if there wasn't a updated state,

04:24.150 --> 04:25.920
then we would have a placeholder.

04:25.920 --> 04:28.770
But you can assume that before this human node runs,

04:28.770 --> 04:30.300
we are actually gonna update it

04:30.300 --> 04:32.520
so that this one wouldn't happen.

04:32.520 --> 04:34.699
But we would actually have another message

04:34.699 --> 04:36.390
directly already updated.

04:36.390 --> 04:38.880
And then we would go from the human node onwards.

04:38.880 --> 04:41.040
So let's have a look at how this looks.

04:41.040 --> 04:42.360
So you can see this is what we have.

04:42.360 --> 04:44.250
So we've got the chatbot,

04:44.250 --> 04:46.050
which goes into the human if it needs it,

04:46.050 --> 04:47.400
and then goes back into the chatbot.

04:47.400 --> 04:49.290
We also have the tools.

04:49.290 --> 04:50.310
If there are tool calls,

04:50.310 --> 04:52.920
then those will get filtered into the tool node.

04:52.920 --> 04:54.930
And then after that, then it will end.

04:54.930 --> 04:58.320
Now you can say, I need some help guiding for assistance

04:58.320 --> 04:59.790
with an AI agent.

04:59.790 --> 05:01.590
We'll give a thread ID of one

05:01.590 --> 05:03.990
and we'll stream that with the user input.

05:03.990 --> 05:05.010
And let's see what happens.

05:05.010 --> 05:06.840
It's decided it wants to call

05:06.840 --> 05:09.531
the human RequestAssistance tool.

05:09.531 --> 05:14.340
And what we can then do is get the state of the graph

05:14.340 --> 05:17.190
and you can see that the next node is human.

05:17.190 --> 05:19.350
So we've essentially, if we scroll up a bit,

05:19.350 --> 05:21.060
we first enter the chatbot node

05:21.060 --> 05:22.860
and it decided to go to the human node,

05:22.860 --> 05:24.240
but we have interrupted it

05:24.240 --> 05:26.580
before it's gone into the human node.

05:26.580 --> 05:28.860
And then what we are then basically gonna do

05:28.860 --> 05:30.810
is create a tool message.

05:30.810 --> 05:33.150
So we'll get the values, the messages,

05:33.150 --> 05:35.250
the most recent message from the AI.

05:35.250 --> 05:37.020
And you can see this gives us things like

05:37.020 --> 05:40.410
the tool calls that we can get.

05:40.410 --> 05:42.630
And so what we want to do is

05:42.630 --> 05:46.350
we want to use this create_response function

05:46.350 --> 05:48.540
and we'll just have a look at that what that does again.

05:48.540 --> 05:50.310
So that will take the AI message

05:50.310 --> 05:52.770
and it will get the first tool call ID

05:52.770 --> 05:55.410
and it will have a response to that tool.

05:55.410 --> 05:58.020
So if we're gonna scroll down again,

05:58.020 --> 06:00.810
now that we know that it's gonna get the AI message ID

06:00.810 --> 06:03.900
and create a tool message for us, you can see that there.

06:03.900 --> 06:06.240
And then we have the human response,

06:06.240 --> 06:07.442
we are the experts here,

06:07.442 --> 06:09.960
recommend check out our LangGraph to build your agent,

06:09.960 --> 06:13.770
it's much more reliable and flexible and extensible.

06:13.770 --> 06:15.780
And then we're gonna update the state

06:15.780 --> 06:18.090
with the config and the messages.

06:18.090 --> 06:20.670
And we're gonna add on the tool message

06:20.670 --> 06:23.280
that comes back from the create_response.

06:23.280 --> 06:25.440
And now that we've done that, if we get the config,

06:25.440 --> 06:28.290
you'll see that we've also now got a tool message

06:28.290 --> 06:31.500
that has been added on after the AI has decided

06:31.500 --> 06:33.510
that it needed to request assistance.

06:33.510 --> 06:34.890
And so we've almost answered

06:34.890 --> 06:36.570
the request assistance from this.

06:36.570 --> 06:39.870
And therefore if we do a none configuration,

06:39.870 --> 06:41.580
it will resume the graph.

06:41.580 --> 06:44.790
So if we were to do, for example, graph dot,

06:44.790 --> 06:47.110
and then I could do get the state,

06:47.110 --> 06:50.820
and I just wanna prove to you that the next node here

06:50.820 --> 06:53.040
will still be the human node.

06:53.040 --> 06:57.853
But we already know that we've got a input for,

06:57.853 --> 07:00.540
if we just scroll up a bit, we already have an input

07:00.540 --> 07:02.760
for the messages being a tool message

07:02.760 --> 07:05.580
because you've added on a tool message specifically.

07:05.580 --> 07:07.440
And therefore we would skip this step

07:07.440 --> 07:08.820
and we would go straight here

07:08.820 --> 07:09.930
and we're just basically setting

07:09.930 --> 07:11.580
the ask_human flag to be false.

07:11.580 --> 07:14.220
And we've got the messages that are being returned.

07:14.220 --> 07:15.990
So that's basically how it's working

07:15.990 --> 07:18.090
is by adding on this extra tool message.

07:18.090 --> 07:20.400
When we go back into that human node,

07:20.400 --> 07:21.823
which is the next node,

07:21.823 --> 07:23.963
we're actually just gonna return the messages

07:23.963 --> 07:26.670
and then you'll see what happens from there.

07:26.670 --> 07:28.890
So we've got the tool message

07:28.890 --> 07:30.330
and then the AI has said,

07:30.330 --> 07:32.610
experts have recommended using LangGraph

07:32.610 --> 07:34.500
as a reliable and accessible tool.

07:34.500 --> 07:36.780
So then the graph has specifically ended.

07:36.780 --> 07:38.684
So what happened was we went into the chatbot,

07:38.684 --> 07:41.580
we interrupted before the human node,

07:41.580 --> 07:45.300
and then after that what we did was we added on a message,

07:45.300 --> 07:47.070
we then went into the human node,

07:47.070 --> 07:49.080
which went back into the chatbot.

07:49.080 --> 07:51.810
There was now no tools to be called.

07:51.810 --> 07:54.030
And so what we then did is we decided

07:54.030 --> 07:57.090
to end the LangGraph state machine.

07:57.090 --> 08:00.403
So, cool, so that's a bit of what we've done there.

08:00.403 --> 08:01.890
So hopefully that made sense.

08:01.890 --> 08:03.810
The important point here is you want

08:03.810 --> 08:05.520
to have your interrupt befores

08:05.520 --> 08:09.390
or interrupt afters as you build your state machine.

08:09.390 --> 08:12.450
And you could also have done it with an interrupt after.

08:12.450 --> 08:14.040
The important point here is if you did do

08:14.040 --> 08:16.200
an interrupt after, you would need to make sure

08:16.200 --> 08:18.120
that the node kind of handles for the fact

08:18.120 --> 08:21.960
that you wouldn't have that after inside the node.

08:21.960 --> 08:23.340
There's various different strategies.

08:23.340 --> 08:24.780
One is interrupting before the node

08:24.780 --> 08:26.760
and then resuming from there.

08:26.760 --> 08:28.170
One is interrupting after

08:28.170 --> 08:30.163
and then updating the previous bit of state.

08:30.163 --> 08:33.540
And again, we're using a checkpoint to which allows us

08:33.540 --> 08:34.950
to run different threads.

08:34.950 --> 08:38.160
And LangGraph is clever enough to allow us

08:38.160 --> 08:40.705
to specifically customize the state

08:40.705 --> 08:43.680
and we can use that customizable state

08:43.680 --> 08:46.020
to run different types of conditional edges.

08:46.020 --> 08:48.720
Cool, so in the next one we're gonna have a look at

08:48.720 --> 08:50.550
a concept called time travel.

08:50.550 --> 08:54.150
Time travel will allow you to specifically wind

08:54.150 --> 08:57.930
forwards or backwards graph state inside of LangGraph

08:57.930 --> 09:00.150
from using a check pointer.

09:00.150 --> 09:02.280
This can be useful if you want users to be able

09:02.280 --> 09:04.865
to undo changes they've had or revert changes,

09:04.865 --> 09:07.620
and having the version control over the graph

09:07.620 --> 09:09.630
as well as being able to update the graph.

09:09.630 --> 09:11.380
Cool, I'll see you in the next one.
