WEBVTT

00:00.110 --> 00:02.900
Now it's time to write our react agent.

00:02.900 --> 00:05.960
So let's define a variable called agent.

00:05.960 --> 00:08.180
And it's going to take our prompt.

00:08.180 --> 00:10.790
And it's going to plug it in into our LM.

00:10.790 --> 00:13.940
Now you might be wondering what are those pipe thingies.

00:13.940 --> 00:19.250
So this is me using the Lang chain expression language or LCL.

00:19.250 --> 00:26.360
So the Lang chain expression language is a way for us to define declaratively and compose our chains

00:26.360 --> 00:27.050
together.

00:27.050 --> 00:30.780
So there are lots of benefits of using the LCL.

00:30.780 --> 00:36.390
It makes our code more readable, more composable, and it really helps us understand what's happening

00:36.390 --> 00:38.640
under the hood when we dive into internals.

00:38.640 --> 00:45.810
And it has a lot more benefits like parallel processing, batch and streaming support fallbacks, and

00:45.810 --> 00:47.940
we'll dive into it later in this course.

00:47.940 --> 00:54.470
By the way, one of the reason it was created was because people complained that all the chains and

00:54.470 --> 00:58.910
agents were too abstract, and they didn't understand what was going on under the hood.

00:58.910 --> 01:04.190
But with the help of the LKL, we can understand exactly what's happening in each step.

01:04.190 --> 01:08.120
And what's the chronological order of those executions.

01:08.150 --> 01:13.130
Okay, let's go back to our agent and let's now describe what are we doing here.

01:13.130 --> 01:21.150
The pipe operator takes the output of its left side and plugs it in into the input of its right side.

01:21.150 --> 01:26.700
So here it's going to run the prompt step, which is going to output us a prompt value.

01:26.700 --> 01:32.340
And it's going to input it into the LM because LMS receives a prompt value.

01:32.340 --> 01:38.010
So intuitively you can think about it that we're taking our prompt and plugging it into the LM and then

01:38.010 --> 01:38.760
running it.

01:38.760 --> 01:44.540
You can see in this description the building blocks of length chain and what would they output and what

01:44.540 --> 01:46.040
input do they need to receive.

01:46.580 --> 01:50.390
Here we can see that prompt outputs us a prompt value.

01:50.390 --> 01:53.390
And this is something that the LM can receive.

01:53.390 --> 01:56.480
It receives strings and it can receive a prompt value.

01:56.870 --> 02:02.810
But this prompt is not complete yet because we haven't supplied it with our question that we want to

02:02.810 --> 02:03.440
ask our agent.

02:03.440 --> 02:06.410
To do so, we need to plug it in its input.

02:06.410 --> 02:07.640
And what does it input?

02:07.640 --> 02:12.920
It comes in the form of a dictionary with the keyword, which is going to replace the placeholders,

02:12.920 --> 02:17.090
and the value is going to be what's going to replace those placeholders.

02:17.090 --> 02:24.050
So because we partially initialize this prompt with the tools and the tool names, we only need to populate

02:24.050 --> 02:25.790
the input placeholder.

02:25.790 --> 02:32.300
So we're going to input our prompt with a dictionary that's going to contain the key of input.

02:32.300 --> 02:38.480
And its value is going to hold eventually the question that we're going to be asking our agent.

02:38.690 --> 02:42.860
So because we want everything to be dynamic, we won't be passing right here.

02:42.860 --> 02:48.140
The prompt that we're going to send to the agent, we're going to pass it when we invoke all of this

02:48.140 --> 02:48.620
chain.

02:48.620 --> 02:55.120
And when we invoke the chain, we need to supply it with a dictionary of the keywords that we're going

02:55.120 --> 02:56.560
to replace the placeholders.

02:56.560 --> 03:01.810
So because of that, instead of putting here the input, we're going to write a lambda function that

03:01.810 --> 03:06.910
is receiving a dictionary and is accessing the input key of that dictionary.

03:06.910 --> 03:10.450
So this is how we're going to be tailoring everything together.

03:10.450 --> 03:16.720
Eventually we're going to have in our agent an LLM, which is going to receive our prompt filled with

03:16.720 --> 03:17.890
all the arguments.

03:17.890 --> 03:24.400
And when we'll use the invoke function, we'll populate the input keys with the value that we're going

03:24.400 --> 03:25.900
to be giving in the invoke.

03:25.900 --> 03:28.630
And this will propagate until the LLM call.

03:28.660 --> 03:33.550
So let's now use the invoke method of this agent.

03:33.550 --> 03:39.040
And we want to pass it a dictionary where the input is going to be what we're going to be asking for

03:39.040 --> 03:39.760
the agent.

03:39.760 --> 03:44.110
And here we're asking what is the length of dog in characters?

03:44.110 --> 03:46.810
Now notice the way that we write here.

03:46.810 --> 03:54.070
The prompt is super important because our agent is going to receive it, and it's going from that determined

03:54.070 --> 03:57.310
which tool to use and what input will it receive.

03:57.310 --> 04:02.770
And even it will affect the output parsing later when we parse the results of the LLM.

04:02.920 --> 04:05.500
So let's run it and see what we get.

04:05.500 --> 04:07.870
And we can see that the LM responded.

04:07.900 --> 04:13.060
I can use the Get text Links tool to determine the length of the text dog.

04:13.060 --> 04:19.570
I will parse the text dog as an input to the get text length function, and after that we can see we

04:19.570 --> 04:21.820
have a backslash n action colon.

04:21.820 --> 04:24.670
It's going to be the name of the function get text length.

04:24.670 --> 04:28.540
Then we're going to have a backslash n action input which is going to be dog.

04:28.750 --> 04:30.940
So this is what the LM responded.

04:30.940 --> 04:33.640
And this is actually the reasoning engine.

04:33.640 --> 04:39.820
The LM got our prompt and it responded us with exactly what needs to be run, what tool needs to be

04:39.820 --> 04:40.570
selected.

04:40.570 --> 04:46.240
And this covers in the react algorithm, the query part which we plug into the agent.

04:46.240 --> 04:51.340
And how does the agent comprise an elaborate prompt which is sent to the LM.

04:51.340 --> 04:57.610
Then the LM functions as a reasoning agent to select the correct tool, and returns us a response containing

04:57.610 --> 05:01.330
all the information about which tool is selected and need to be run.

05:01.330 --> 05:05.230
And now we'll need to go and parse this output that we just saw.

05:05.410 --> 05:08.650
And now we're going to see how we can take this response.

05:08.650 --> 05:11.320
And we can actually invoke this function.

05:11.950 --> 05:19.150
So to do that we'll need to parse this text and to retrieve from it the action and action input and

05:19.150 --> 05:23.830
translate it to it, to the function that we need to call and to the arguments that we need to supply

05:23.830 --> 05:24.100
it.

05:24.130 --> 05:26.530
So we're going to be implementing that.

05:26.530 --> 05:29.350
And we're going to do that by using regular expressions.

05:29.350 --> 05:32.050
So I hope you're ready to writing some regex.

05:32.050 --> 05:33.100
Just kidding.

05:33.100 --> 05:38.500
Linkchain is going to do all the work for us because they already implemented the output parser, which

05:38.500 --> 05:45.850
take the output of the LLM in the react agent and simply parse it into the components that we need.

05:45.850 --> 05:52.900
So this output we want to pass into something which is called the react single input output parser.

05:53.200 --> 05:55.840
And we're going to import it from link chain.

05:55.840 --> 05:57.580
And we want to invoke it.

05:57.670 --> 05:59.320
So let's run it.

06:01.810 --> 06:05.560
And we can see that when we run it we'll get an error.

06:05.560 --> 06:09.100
And we have the error of could not pass the LM output.

06:09.100 --> 06:12.430
And this is probably the most common error when it comes to agent.

06:12.430 --> 06:14.170
It's an output parsing error.

06:14.170 --> 06:20.980
So remember I told you that we have a lot of weight and a lot of impact on the text that we input our

06:20.980 --> 06:21.580
agent.

06:21.580 --> 06:23.230
So this is what I meant.

06:23.230 --> 06:29.560
And this error basically means that the LM responded to us, not something in the format that the output

06:29.560 --> 06:30.580
parser expects.

06:30.580 --> 06:36.040
So the output parser expects something to be in the format of backslash n action backslash n action

06:36.040 --> 06:36.700
input.

06:36.790 --> 06:38.830
So let's go to our input.

06:38.830 --> 06:42.460
And let's go to refine it a bit and remove text from it.

06:42.460 --> 06:46.060
So hopefully this would now work correctly.

06:49.390 --> 06:51.760
So we can see that we get a response back.

06:51.760 --> 06:57.760
And we can see now that the output parser gave us something in the format of tool, each get length

06:57.760 --> 06:59.620
and the tool input is doc.

06:59.800 --> 07:02.290
So this is exactly what we need.

07:02.290 --> 07:07.930
We can also see that in the log property we have a what the LLM responded.

07:07.930 --> 07:13.990
And we can indeed see that it's in indeed in the correct backslash in action and backslash in action

07:13.990 --> 07:16.780
input format that the output parser expects.

07:16.780 --> 07:19.670
So I've been mumbling about this output parser.

07:19.670 --> 07:22.460
So let's check out how does it look and what does it do.

07:22.490 --> 07:28.670
So according to the description it parses the react style LLM call that have a single tool input.

07:28.670 --> 07:33.380
So it expects the output of the LLM to be in one of two formats.

07:33.380 --> 07:36.260
And we'll be focusing on this video in the first format.

07:36.260 --> 07:39.770
And the second format will be focused on in the next video.

07:39.860 --> 07:45.060
So the first format is the format of action and action input.

07:45.060 --> 07:52.530
And this basically the case where the LLM tells us that we need to perform some kind of action, aka

07:52.530 --> 07:58.350
select a tool and then invoke it so it will come in the format of action, which is going to be the

07:58.350 --> 08:03.720
tool name and the action input, which is going to be the input that we're going to supply our tool.

08:05.010 --> 08:10.620
So in our example the action was get text length which is the name of the function.

08:10.620 --> 08:12.780
And the action input was dog.

08:13.410 --> 08:18.930
So now let's go and show you the logic of what length chain is doing with all that output parsing.

08:18.930 --> 08:24.270
It has a function called parse which is going to be executed, and it's going to return us something

08:24.270 --> 08:25.950
which is called an agent action.

08:25.950 --> 08:32.130
And this is simply a link chain object, which is going to hold the tool name and the tool input that

08:32.130 --> 08:34.380
we want to supply it after we passed it.

08:34.380 --> 08:40.050
And that is going to help us invoke the tool that the LM selected from the reasoning engine.

08:40.050 --> 08:44.220
And let's have a look at the parsing using regular expressions.

08:44.220 --> 08:51.060
So we can see we have a regular expressions that is supposed to extract the action and the action input.

08:51.060 --> 08:55.680
And you can see in the bottom lines over here that we take what we matched.

08:55.680 --> 09:01.380
If it was in that format and we place it in the action and action input variables.

09:01.380 --> 09:08.130
And the last thing I want to show you is that we return an agent action object, which is built from

09:08.130 --> 09:13.260
the action and the tool input and the text, which was the original answer from the LM.

09:13.260 --> 09:18.030
So by taking this we can select the tool that we want to run and run it.

09:18.720 --> 09:21.630
So right now we finished with the parsing part.

09:21.630 --> 09:24.690
And now we want to go to the tool execution.

09:24.690 --> 09:29.760
So we have now all the information about which tool we want to execute.

09:29.760 --> 09:32.640
So now we just need to execute this tool.

09:33.090 --> 09:37.560
Now let's change the name of the variable res to agent step.

09:37.890 --> 09:44.370
And it's going to be of the type of agent action or agent finish.

09:44.730 --> 09:47.730
So let's import those two long chain classes.

09:47.730 --> 09:51.030
We discussed a bit about Agent Action and Agent Finish.

09:51.030 --> 09:53.250
We're going to discuss soon.

09:53.250 --> 09:54.690
Let's add a print.

09:54.690 --> 10:01.380
And now if the agent step is the type of agent action, it will hold all the information of the tool

10:01.380 --> 10:06.900
we want to run and execute and get our observation which is the result of this tool.

10:06.900 --> 10:09.450
So we want to write this logic.

10:09.450 --> 10:15.330
So if we get back from the output parser, the agent step, which is going to be an instance of the

10:15.330 --> 10:19.770
class agent action, we want to extrapolate the tool to use.

10:19.770 --> 10:21.780
So we'll get the tool name.

10:21.780 --> 10:26.010
And from the tool name we're going to find from the list of tools the tools to run.

10:26.010 --> 10:28.020
So let's extrapolate the tool name.

10:28.020 --> 10:31.620
And it's going to be the agent stepped dot tool.

10:31.620 --> 10:35.070
We'll define a variable called tool to use.

10:35.070 --> 10:37.560
And this is going to be the function that will run.

10:37.560 --> 10:39.540
And now we need to take the tool name.

10:39.540 --> 10:41.790
And we need to find the tool from it.

10:41.790 --> 10:46.260
So we'll need to define a new function which is called find tool by name.

10:46.260 --> 10:50.190
It's going to receive the tools list that we defined earlier.

10:50.190 --> 10:53.280
And it's going to receive the tool name.

10:53.550 --> 10:55.470
So let's go and copy that.

10:55.470 --> 10:57.450
And let's define this function.

10:57.570 --> 11:04.500
And this function arguments is going to be tools which is going to be a list of tools.

11:07.500 --> 11:13.020
And the second argument is going to be a tool name that we're going to find which is going to be a string.

11:13.020 --> 11:16.080
This function is going to return us a tool.

11:17.070 --> 11:20.220
And the implementation is going to be very straightforward.

11:20.220 --> 11:22.290
We're going to be iterating through the tools.

11:22.290 --> 11:30.210
And if the tool dot name is equal to the tool name that we're searching for, then we want to return

11:30.210 --> 11:30.960
the tool.

11:32.310 --> 11:39.090
And if we finished iterating and we didn't find the tool, let's raise a value error and write that

11:39.090 --> 11:41.640
we couldn't find the tool with the tool name.

11:42.720 --> 11:49.650
So now that we finished implementing the fan tool by name function, we want now to run the tool.

11:49.650 --> 11:51.840
And for that we'll be needing the tool input.

11:51.840 --> 11:55.380
So we're going to get it from the agent step dot tool input.

11:55.380 --> 11:59.760
And now let's define a new variable and we'll call it observation.

12:00.060 --> 12:02.970
And it's going to be the results of us running the tool.

12:02.970 --> 12:05.520
So it's going to be the tool to use.

12:05.520 --> 12:08.760
And the tool has the attribute of function.

12:08.760 --> 12:12.000
And this is the function that we defined the tool on.

12:12.000 --> 12:15.630
And here we're simply going to plug in the tool input.

12:16.980 --> 12:18.180
Just to be safe.

12:18.180 --> 12:23.550
I converted it into a string because I know that the function is expecting to get a string.

12:23.670 --> 12:29.280
However, of course the length chain implementation is much more robust and can handle much more cases

12:29.280 --> 12:32.880
where we need special attributes and special types for our inputs.

12:32.910 --> 12:38.430
And now let's go and print our observation which is the result of running the tool.

12:38.910 --> 12:41.730
Now let's run it and let's see what we get.

12:44.820 --> 12:48.630
We can see we got a value error that it couldn't find the tool.

12:48.630 --> 12:56.460
And this is because I passed the wrong argument to this function I passed instead of tool name the list

12:56.460 --> 12:57.050
of tools.

12:57.050 --> 13:01.190
So I'm simply going to change the second argument to be the tool name.

13:02.120 --> 13:03.830
So let's rerun it.

13:05.780 --> 13:12.620
And we can see now that we get observation equal to five because we passed to our tool the argument

13:12.620 --> 13:14.330
of dog with quotes.

13:14.330 --> 13:16.340
And it also counted the quotes.

13:17.150 --> 13:22.820
And just to make it a bit more explicit, I'm going to add to our tool a print where we're printing

13:22.820 --> 13:27.950
the tool name, and we're also mentioning the argument that we entered with.

13:30.590 --> 13:32.570
So now let's rerun it.

13:33.620 --> 13:40.760
And indeed we can see we entered the function gettext length with the dog word and wrapped with the

13:40.760 --> 13:41.510
quotes.

13:42.650 --> 13:47.660
So if we just want to make it a bit more nicer, let's remove the quotes from the word dog.

13:47.840 --> 13:51.320
And I'm just want to refine a bit more the prompt.

13:51.320 --> 13:58.040
So I'm going to simply write the final prompt, which is going to be what is the length in characters

13:58.040 --> 13:59.450
of the text dog.

14:00.590 --> 14:06.770
And when we run the agent, we can see that we indeed chose the correct tool, ran it, and we got that

14:06.770 --> 14:12.860
the observation was three, So it counted the number of letters in the word dog.

14:12.950 --> 14:18.230
So in this video we reviewed a massive part of the react implementation of Lang Chain.

14:18.230 --> 14:24.470
We saw how we can start from a user query to count the number of letters in the word dog, how we plugged

14:24.470 --> 14:25.460
it into the agent.

14:25.460 --> 14:30.500
Then the agent wrapped it up in a special call of the react algorithm.

14:30.500 --> 14:33.590
Sent this LM call to GPT 3.5.

14:33.620 --> 14:40.850
We got back a response from the LM, which had the thought and all the information of the tool selection,

14:40.850 --> 14:44.450
and this was actually the reasoning engine of the LM.

14:44.480 --> 14:51.560
We then saw how link chain parses all of this information and all of this response, and we saw then

14:51.560 --> 14:57.020
how link chain transforms it into a tool to run and to execute that tool.
