WEBVTT

00:00.360 --> 00:01.440
Pressing on.

00:01.760 --> 00:06.040
So what we're now going to do is call this.

00:06.080 --> 00:10.040
It looks like I'm going to need to import async IO there.

00:10.080 --> 00:10.640
Hang on.

00:10.680 --> 00:11.640
Let's do that.

00:12.640 --> 00:14.240
Missed an import at the start.

00:14.640 --> 00:15.960
Actually let's do this properly.

00:15.960 --> 00:18.360
I'm going to take this out just so that it's nice and clean for you.

00:18.360 --> 00:23.240
I'm going to put that async import right up at the top there and rerun that cell.

00:23.560 --> 00:25.120
I like to do my imports at the top.

00:25.120 --> 00:27.520
I know people have different views on this stuff.

00:27.960 --> 00:33.520
Okay, so we are now going to say we want to write a cold sales email.

00:33.520 --> 00:35.240
That's going to be our instruction.

00:35.240 --> 00:38.720
And what we're going to do now is we're going to call this async IO.

00:39.920 --> 00:40.640
Do you remember this?

00:40.640 --> 00:46.800
I showed this to you back when we had the async briefing, that this is where you start to see the power

00:46.800 --> 00:47.800
of async IO.

00:47.920 --> 00:52.520
We're going to be running three different runs at the same time.

00:52.720 --> 00:54.680
And of course again it's not multithreading.

00:54.680 --> 00:58.200
It's not like the CPU is actually time slicing between them in some ways.

00:58.400 --> 01:03.900
But but rather it's going to be using an event loop, which will run each one, and whenever it's pausing

01:03.900 --> 01:06.420
waiting on I o it will let another one run.

01:06.420 --> 01:11.820
And because most of what these things are doing is pausing on I o that will allow all three of them

01:11.820 --> 01:20.820
to sort of alternate and be talking to to an LLM to open AI in parallel, and then we will collect back

01:20.860 --> 01:21.860
the results.

01:21.900 --> 01:27.300
What comes back from this await gather is a collection of results.

01:27.300 --> 01:30.660
And we will call final output on each one and print it.

01:30.980 --> 01:32.820
So we will let that run.

01:33.020 --> 01:39.220
And you can see that I've wrapped all of this in a trace, which means that we should see all of this

01:39.260 --> 01:40.420
in one trace.

01:40.460 --> 01:43.500
We will do in a little bit, but no surprise.

01:43.500 --> 01:49.420
Hopefully what you'll see down here is I have to click here to get a scrollable element, and you'll

01:49.420 --> 01:53.660
see that we can scroll through and read a bunch of emails.

01:54.460 --> 02:00.260
And the third one, of course, is very concise because we asked our third email writer to be concise.

02:01.040 --> 02:05.280
Okay, so so far all we've really done is multiple calls to LMS.

02:05.320 --> 02:07.640
And now the final piece of the puzzle.

02:07.640 --> 02:11.680
This is just a simple workflow of calling LMS.

02:11.720 --> 02:17.520
See if you can remember which one of the patterns this is, but it's a sort of variety of one of them.

02:17.560 --> 02:20.560
And we are going to create a new agent called sales picker.

02:20.840 --> 02:26.240
And sales picker picks the best cold sales email from the given options.

02:26.560 --> 02:27.720
Imagine you're a customer.

02:27.720 --> 02:30.400
Pick the one you're most likely to respond to.

02:30.560 --> 02:31.920
Don't give an explanation.

02:31.920 --> 02:35.000
Reply with the email you select only.

02:35.040 --> 02:37.080
It's a classic kind of prompting.

02:37.240 --> 02:40.040
You know that you often end with the constraint.

02:40.040 --> 02:44.480
With any limitation is a good way to end a system prompt.

02:44.920 --> 02:45.800
All right.

02:45.920 --> 02:50.600
So that's the message the user prompt writer called sales email.

02:50.840 --> 02:53.080
We again we have this same construct.

02:53.080 --> 02:59.560
We're going to run three agents in parallel to craft three messages.

02:59.560 --> 03:04.820
We're going to gather the outputs and then we just simply call another agent.

03:04.980 --> 03:07.740
So this is just Python code step by step.

03:07.780 --> 03:09.340
Call three agents in parallel.

03:09.380 --> 03:10.260
Take the output.

03:10.300 --> 03:11.540
Call another agent.

03:11.580 --> 03:18.220
It's just a Python script that runs these things in order, and it will then print the best email at

03:18.220 --> 03:19.140
the end of it.

03:19.500 --> 03:26.780
And because we've got the whole thing under one trace, we hope to see all of this in a single trace.

03:27.700 --> 03:31.860
So this is probably going to take I think like 30s in total.

03:31.860 --> 03:35.060
So I'll have to keep the sentence running if we want to see this live.

03:35.380 --> 03:39.100
And at the end of it we'll be able to go into the trace is run.

03:39.140 --> 03:41.980
So here is a single email that's been returned.

03:42.140 --> 03:45.220
And it is apparently the best one.

03:45.380 --> 03:48.620
But let's now go and have a look at the trace to see if we believe it.

03:49.060 --> 03:49.500
Okay.

03:49.500 --> 03:51.020
So this was our email.

03:51.060 --> 03:54.540
Now this is a link to go to see the traces in OpenAI.

03:54.860 --> 03:55.820
Here it comes.

03:56.020 --> 03:59.540
So at the top trace is selection from salespeople.

03:59.540 --> 04:01.680
Let's go and have a look into this trace.

04:01.680 --> 04:07.160
What you'll see is that, sure enough, it called the professional sales agent, and you can read the

04:07.200 --> 04:10.840
actual prompts that went in it called the engaging sales agent.

04:10.880 --> 04:15.160
It called the Busy sales agent, and then it called the sales picker.

04:15.320 --> 04:18.280
And you can go through this in the trace and see what's going on.

04:18.840 --> 04:22.560
So it's worth pointing out that we've really not done anything very magical so far.

04:23.000 --> 04:23.680
It's nice.

04:23.680 --> 04:28.200
It's elegant that we've had these wrappers, these agent constructs around things, but they're very

04:28.200 --> 04:29.160
lightweight wrappers.

04:29.160 --> 04:32.720
We've essentially simply called a total of four LMS.

04:32.720 --> 04:38.200
We've called the three sales LMS, and then we've called the one at the end to pick the email it preferred.

04:38.200 --> 04:41.800
And it's sort of elegant that you can go into the traces and see what's going on.

04:41.800 --> 04:46.000
But now it's time to get a bit more agentic and start talking about tools.

04:46.840 --> 04:52.200
So as we get into tools, let me remind you, have a think back to what we did in week one, when we

04:52.200 --> 04:58.520
had to build some boilerplate JSON to describe a function that we wanted to use as like a tool.

04:58.800 --> 05:04.050
It's quite chunky JSON that described the parameters and various other things about it.

05:04.050 --> 05:10.050
And then we had to write a function called handle tool calls, which is the one that had the the hokey

05:10.090 --> 05:14.810
if statement that I then tried to write into something a bit more fancy, but which was still a fair

05:14.810 --> 05:17.650
amount of sort of gunk, to use a technical word.

05:17.690 --> 05:23.690
And what we're now going to see is how that whole stuff can be, can be super simplified without taking

05:23.690 --> 05:25.370
any flexibility away from us.

05:25.930 --> 05:28.530
So first of all, we're just going to recap.

05:28.530 --> 05:34.130
We've got these three sales agents the professional, the engaging and the busy ones.

05:34.130 --> 05:35.210
And there they are.

05:35.450 --> 05:38.850
And let me just look at one of these sales agents.

05:38.930 --> 05:41.850
So if I look into it you can see that it's got a name.

05:41.850 --> 05:43.610
It's got the instructions.

05:43.610 --> 05:50.850
And you can see that it has things like tool choice tools, and it has like a list of tools that it

05:50.850 --> 05:53.130
has access to, which right now is empty.

05:53.290 --> 05:57.370
So just to give you a sense of what's going on under the covers, it's perfectly simple.

05:57.370 --> 05:59.450
But these are the constructs we're working with.

05:59.950 --> 06:03.910
So what we're now going to do is have a tool.

06:04.350 --> 06:07.550
So this is a function send email.

06:07.550 --> 06:10.470
It takes an email body which is a string.

06:10.710 --> 06:13.830
And it has a like a doc string.

06:13.990 --> 06:17.830
Send out an email with the given body to all sales prospects.

06:18.150 --> 06:21.950
Now what I've got in here is the from email.

06:21.950 --> 06:28.710
And this email needs to be what's called the verified sender, the email address that you've set up

06:28.710 --> 06:31.230
in SendGrid that you're allowed to send from.

06:31.270 --> 06:33.030
Otherwise it won't actually send.

06:33.110 --> 06:36.230
So you'll need to update this and then two email.

06:36.230 --> 06:40.030
You should put that to be an email where you don't mind it receiving an email.

06:40.070 --> 06:42.910
I would prefer that you change it from my Gmail here.

06:42.910 --> 06:46.350
Otherwise I will get flooded with emails from people doing this.

06:46.350 --> 06:49.990
So maybe I'll change it before I commit this to GitHub.

06:49.990 --> 06:52.670
But yes, send that to another of your email addresses.

06:52.670 --> 06:54.430
Or you could probably just send it to yourself.

06:54.470 --> 07:00.290
I'm not sure, but send it to somewhere where you don't mind receiving cold sales emails, there'll

07:00.290 --> 07:00.970
only be 1 or 2.

07:00.970 --> 07:02.730
We're not going to send a mass of them.

07:03.210 --> 07:05.730
And then this is Sendgrid's API.

07:05.770 --> 07:07.170
It's perfectly simple.

07:07.170 --> 07:07.890
It's SendGrid.

07:10.290 --> 07:13.130
And you give it a body so you can look through this.

07:13.130 --> 07:20.890
But it's honestly it's just a boilerplate to send an email to a recipient and we respond with success.

07:21.130 --> 07:24.410
So this is very much like the tools that we wrote last time.

07:24.410 --> 07:25.570
It's like a function to do it.

07:25.610 --> 07:29.930
And if you remember, the next step was to write a ton of JSON to describe this.

07:29.930 --> 07:36.650
But all we need to do with OpenAI is put one of these decorators above it at function tool.

07:36.770 --> 07:41.850
If you're not sure how decorators work, again, that's in the guides, or just ask ChatGPT to explain

07:41.850 --> 07:42.290
it.

07:42.290 --> 07:48.290
But that allows OpenAI to write some code to sort of do something with this function.

07:48.330 --> 07:54.930
And but all we need to care about is we simply put that decorator above the function that we want to

07:54.970 --> 07:56.530
treat as a tool.

07:57.050 --> 08:03.110
And so we will just simply define that function doesn't look like we've done anything, but let's look

08:03.150 --> 08:05.150
at this thing called send email.

08:05.190 --> 08:07.270
Now we think it's a function, right?

08:07.510 --> 08:10.870
But no, it's not a function because we have this decorator.

08:10.870 --> 08:14.670
It's been converted into something called a function tool.

08:15.110 --> 08:17.390
It has a name send email.

08:17.710 --> 08:19.030
It has a description.

08:19.030 --> 08:24.070
And that description is taken from the docstring comment we had right here.

08:24.070 --> 08:24.870
Look at that.

08:24.870 --> 08:27.150
It's just turned that into a tool description.

08:27.150 --> 08:31.790
And then and this is the great stuff params JSON schema.

08:32.030 --> 08:37.990
This stuff is all of the boilerplate JSON that we had to write last time.

08:37.990 --> 08:42.190
It's just done it for us because it's read this and it's figured out what's needed.

08:42.390 --> 08:44.230
And and that's basically it.

08:44.390 --> 08:51.790
So just by simply adding that decorator function tool, all of the work of faffing around with these

08:51.790 --> 08:55.430
JSON objects has been taken away from us, which is great.

08:55.430 --> 08:56.950
That's what a good framework should do.

08:56.990 --> 08:59.990
Take out the boilerplate but leave us in full control.
