WEBVTT

00:00.200 --> 00:02.520
So I have good news and bad news for you.

00:02.520 --> 00:09.880
The good news is that today, the last day of week two, it's going to be quick and easy and satisfying.

00:09.880 --> 00:11.920
So there's going to be fun stuff right away.

00:12.040 --> 00:14.960
The bad news is there's going to be a really hard challenge at the end of it.

00:14.960 --> 00:18.360
It's going to be hard, but really big and juicy and good.

00:18.400 --> 00:21.680
So I do hope that you will take on the challenge that's coming up.

00:21.680 --> 00:24.400
But first, let's just talk about what we're going to do today.

00:24.400 --> 00:26.800
We're going to take our deep research.

00:27.120 --> 00:29.920
The agent that we built last time in a notebook.

00:29.920 --> 00:33.920
And we're going to turn it into proper Python code in modules.

00:33.960 --> 00:36.800
Yes, with a user interface featuring Gradio.

00:36.960 --> 00:38.240
Let's go and do that right now.

00:38.720 --> 00:42.800
And so here we are in cursor and we're going into the OpenAI folder.

00:42.800 --> 00:48.960
But now we're going into another folder into the deep research folder that is beneath it.

00:49.160 --> 00:52.880
And you will see that there are some Python modules you'll be happy to see.

00:52.920 --> 00:57.480
Because I know you like Python modules, and I'm going to just talk you through them, and I hope going

00:57.480 --> 01:03.840
to be pleasantly surprised how easy it is, and also how natural it is to move from a notebook world

01:03.840 --> 01:05.360
into proper modules.

01:05.360 --> 01:11.200
And again, one more sales pitch is where I like to work experimentally, first in a notebook and then

01:11.200 --> 01:12.680
turn it into modules.

01:12.680 --> 01:17.720
As you've built out your prompts, as you've experimented and refined your agent architecture.

01:18.040 --> 01:24.560
So what we've got in here are some agent classes, some agent modules with a single agent class, and

01:24.560 --> 01:27.000
then a manager that packages it all together.

01:27.000 --> 01:32.240
And then finally, deep research is the user interface, which is a very simple user interface.

01:32.280 --> 01:36.320
So let's start with the classes that represent the agents.

01:36.320 --> 01:37.800
And it's going to be really simple.

01:37.800 --> 01:42.760
We will start with the planner agent, which is exactly where we started when we were in the notebook

01:42.880 --> 01:44.560
the planner agent.

01:44.600 --> 01:45.240
We've got this.

01:45.240 --> 01:46.320
How many searches?

01:46.320 --> 01:52.240
I've got it set to 20 now, but I'll turn it back to three before I check this in so that no one racks

01:52.240 --> 01:53.040
up a big bill.

01:53.040 --> 01:59.800
If you use it, and you'll recognize the same old instructions and the same pedantic objects for a web

01:59.800 --> 02:06.800
search item and a web search plan, which is the list of web search items in the single field searches.

02:06.960 --> 02:14.760
And here is our planner agent that takes our instructions and it uses the web search plan.

02:15.320 --> 02:16.240
There we go.

02:16.560 --> 02:22.040
Okay, next up, the search agent and I need to make one little change to this guy.

02:22.440 --> 02:25.120
So this is the search agent.

02:25.160 --> 02:29.360
The instructions you'll see here your research assistant.

02:29.600 --> 02:31.600
And it's got got this this format.

02:31.600 --> 02:35.760
You'll remember that we stole that format from OpenAI's documentation.

02:35.840 --> 02:38.960
A very nice set of instructions right there.

02:39.200 --> 02:44.520
I don't know if you spot the little change I have to make, but the tools in here, I need to add in

02:44.520 --> 02:46.600
that parameter to make it nice and cheap.

02:46.600 --> 02:47.840
So let's go and do that together.

02:47.840 --> 02:55.320
If we go to this lab, if we look at what that parameter was, that parameter was actually near the

02:55.320 --> 02:55.560
top.

02:55.560 --> 02:57.880
I think we did at the very beginning.

02:57.880 --> 02:58.800
There we go.

02:59.000 --> 03:02.920
It is that the search context size is low.

03:03.200 --> 03:08.950
Let's go and put that in there right now so that no one spends unexpected amounts there.

03:08.950 --> 03:10.390
We have it done.

03:10.870 --> 03:15.910
Okay, so that is the search agent class in the search agent module.

03:16.230 --> 03:22.270
And now we've got a couple more, two more agents to talk about the writer agent again.

03:22.470 --> 03:24.950
And you know, the benefits certainly of having these in Python modules.

03:24.950 --> 03:26.750
It looks very crisp and simple.

03:26.750 --> 03:28.550
You can see exactly what's going on.

03:28.590 --> 03:30.190
We've got our instructions.

03:30.350 --> 03:38.150
We've got the pedantic report data that has a short summary, a markdown report and follow up questions.

03:38.430 --> 03:45.470
And then our writer agent, which is the agent that will take all of the information from all of the

03:45.470 --> 03:50.030
searches and turn it into a report data object.

03:50.550 --> 03:53.790
And the final agent, if you remember, is of course, the email agent.

03:53.790 --> 03:54.750
Here it is.

03:54.790 --> 03:57.150
This is stuff that you will recognize.

03:57.310 --> 04:02.030
This is just the same thing that is going to send the email.

04:02.070 --> 04:10.870
You must remember, please to change this to be your verified sender here, not make put your verified

04:10.870 --> 04:14.990
sender here and then put some other email here.

04:15.030 --> 04:17.590
Put your recipient here, not me.

04:17.630 --> 04:21.190
I think I might change this before I check it in, because otherwise someone's going to forget or many

04:21.190 --> 04:24.550
people will forget and I'll be overloaded with the spam email.

04:24.950 --> 04:26.990
All right, so this is the tool.

04:26.990 --> 04:37.310
And actually it's good to have a comment in here because that will send an email with the given subject

04:37.350 --> 04:38.310
and HTML body.

04:38.390 --> 04:39.350
Very nice.

04:39.750 --> 04:40.470
Okay.

04:40.670 --> 04:45.390
So that is our email agent and that is all four of our agents.

04:45.390 --> 04:49.470
What's coming next is research manager okay.

04:49.510 --> 04:51.830
So research manager is a class.

04:51.830 --> 04:59.190
And this contains those short functions that we had last time with a little bit of a twist spiced it

04:59.190 --> 04:59.550
up.

04:59.790 --> 05:05.350
So first of all there is a single method here run or it's a coroutine.

05:05.390 --> 05:11.630
If you want to be pedantic with me, this coroutine run an async def run.

05:11.830 --> 05:16.830
And this is just the same as the as the code that I had before.

05:16.870 --> 05:23.470
We've got a little trick here to, to generate a trace ID so that we can, we can print where to go

05:23.470 --> 05:27.310
to look at the precise trace that we're looking at here.

05:27.750 --> 05:31.710
Now you may wonder why we've got all of this yielding going on.

05:31.870 --> 05:38.630
We we're treating this as a generator that is going to yield various bits of text along the way.

05:38.990 --> 05:41.390
So that is going to become clear in a bit.

05:41.390 --> 05:43.590
But just take a look at what's going on here.

05:43.670 --> 05:47.630
I print some updates and I also yield those updates.

05:47.670 --> 05:51.190
And I end by yielding the full markdown report.

05:51.390 --> 05:53.990
Now hopefully you've done your intermediate.

05:53.990 --> 05:58.750
Either you already know all about generators or if you don't, then you've taken a look at the guide

05:58.750 --> 06:02.230
that explains generators so that there's no surprise.

06:03.070 --> 06:03.510
Okay.

06:03.550 --> 06:10.710
And then I've just got each of these functions plan searches, perform searches, search and write,

06:10.710 --> 06:12.670
report and send email.

06:12.950 --> 06:17.950
These are the five functions that are exactly the same as the five functions we talked through before,

06:17.990 --> 06:20.030
except a little bit beefed up.

06:20.030 --> 06:26.190
They've got more type hints put in, as one should do for proper checked in Python modules.

06:26.350 --> 06:28.670
And there's a bit more exception handling.

06:28.830 --> 06:34.950
And this is a little bit fancier to handle the being able to print a status update while it's going

06:34.950 --> 06:39.390
through the different searches, but otherwise it is much the same.

06:39.590 --> 06:45.710
So it's just a bit tidied up, which is the kind of practice you should do when you move from the notebook

06:45.710 --> 06:51.350
environment, when you're being more experimental into something that's more well baked code, but it's

06:51.350 --> 06:52.590
the same functionality.

06:53.230 --> 06:56.590
And that finally brings us to Deepresearch.

06:57.630 --> 06:58.390
Here we are.

06:58.430 --> 07:00.470
This is our Gradio app.

07:00.790 --> 07:03.550
This is where the magic happens.

07:03.710 --> 07:05.710
So Gradio which we import here.

07:05.990 --> 07:12.550
This is the the the package which you may know I love, which lets data scientists build great UIs without

07:12.550 --> 07:14.430
needing to know anything about front end.

07:14.740 --> 07:20.100
And I'm going to give you just some, some insights into how this works without I'm not giving you a

07:20.100 --> 07:21.260
full radio lesson here.

07:21.260 --> 07:22.420
And radio has great docs.

07:22.420 --> 07:25.220
It's really easy to read up about it and build build your own.

07:25.220 --> 07:29.180
But just very briefly, this this code here is where the user interface is defined.

07:29.300 --> 07:37.420
And we're used to using things like chat interface which is the super canned simple one where you just

07:37.420 --> 07:39.340
you can create an interface out of nothing.

07:39.340 --> 07:44.540
If you want to actually build your own user interface from scratch, then you have to use a slightly

07:44.540 --> 07:53.060
more detailed version when you do with docs as and then something like UI, and then you put your your

07:53.060 --> 07:59.100
code in there and then you say UI launch at the end and that that's the way to do it, that that will

07:59.140 --> 08:00.780
then build your user interface.

08:00.780 --> 08:02.780
So that is exactly what we've got here.

08:02.780 --> 08:05.020
We say with GR blocks.

08:05.380 --> 08:10.100
And then you can pass in a theme if you want to have a different theme to the to the standard theme,

08:10.100 --> 08:12.860
and you can find the different colors that you can have in here.

08:13.140 --> 08:16.740
And then you simply put down the fields that you want.

08:16.780 --> 08:21.980
So we're going to start with a heading GR markdown gives us a heading and we want to have the word deep

08:21.980 --> 08:23.220
research as a big heading.

08:23.380 --> 08:27.180
Then we want a text box that says what topic would you like to research.

08:27.300 --> 08:31.820
And we're associating that text box with a field called query.

08:31.820 --> 08:34.220
So this this is a is a field.

08:34.260 --> 08:38.100
It might be a bit clearer if we call this query text box.

08:38.500 --> 08:40.220
Let's say that query text box.

08:40.740 --> 08:46.180
And then here the next field we're going to put on a user interface is called run button.

08:46.180 --> 08:47.740
It's a great button.

08:47.740 --> 08:50.620
It says run on it and it's a primary button.

08:50.620 --> 08:55.020
So it'll be nice and blue because blue is the sky, blue is the color we've chosen.

08:55.620 --> 09:01.180
And then the next one is going to be report, which is going to be our actual report text.

09:01.220 --> 09:04.740
It's a markdown and its label is report.

09:05.460 --> 09:08.940
Okay I'm going to change this here to query text box.

09:09.420 --> 09:13.700
So what we can now do is register an event.

09:13.980 --> 09:17.900
We want to register an event with the run button.

09:18.220 --> 09:23.380
We're going to say if the run button is clicked and we register that event by calling a function, click

09:23.380 --> 09:28.420
on run button and we just have to tell Gradio we want you to call us back.

09:28.420 --> 09:31.420
If that run button is clicked, then call this callback.

09:31.420 --> 09:34.660
And that callback is going to be something called run.

09:34.940 --> 09:37.660
And spoiler alert, run is right up here.

09:38.220 --> 09:42.060
So if if run button is clicked then call that callback.

09:42.060 --> 09:42.620
Run.

09:42.820 --> 09:48.940
The inputs that you should use should be the contents of the query text box.

09:49.780 --> 09:55.980
So the inputs to this callback should be whatever's in the text box when they press the run button,

09:56.020 --> 10:01.340
when they click the run button, and the outputs, whatever comes out of this callback should go into,

10:01.380 --> 10:06.060
I want you to hook that up Gradio hook it up into this report markdown.

10:06.540 --> 10:09.900
And then for the this this next one is really the same thing.

10:09.940 --> 10:15.860
It's saying that if they're in the query text box and they hit the enter key to submit, then again

10:15.900 --> 10:16.780
call the run.

10:17.100 --> 10:22.860
The input should be the contents of the query text box, and the output should be the report.

10:23.220 --> 10:30.540
So this is a way that you can hook up gradio so that the widgets that you've constructed here get associated

10:30.540 --> 10:35.340
with inputs and outputs of a callback function that's getting called.

10:35.540 --> 10:40.740
And this this method here is going to generate front end code that's going to run in a browser.

10:40.740 --> 10:46.500
And when they press that button it's actually going to call back this Python code in our class populating

10:46.500 --> 10:48.340
it with the right the right fields.

10:48.940 --> 10:54.700
So it doesn't matter if you didn't follow all of that, or you don't get or even care how Gradio hooks

10:54.700 --> 11:00.740
things up together, just have some general intuition for it and know that UI launch is the thing that

11:00.740 --> 11:06.140
is then going to generate the front end code based on that, and figure out how to make sure that our

11:06.140 --> 11:11.580
callback gets called in browser equals true means that it's going to bring up a browser window right

11:11.580 --> 11:11.940
away.

11:11.980 --> 11:13.740
You don't need to have that if you don't wish.

11:14.220 --> 11:18.820
So the only remaining thing for me to mention is what then is this?

11:18.820 --> 11:22.060
What is going on with the with the run up here?

11:22.260 --> 11:25.810
So this is the callback that gets called.

11:26.210 --> 11:32.290
And you can see that as part of this I am calling the research manager Dot run.

11:32.290 --> 11:38.490
And that is the the long function that we looked at a moment ago that had lots of yields in there.

11:38.490 --> 11:43.010
And that brings me to the final part of the puzzle, which is normally in Gradio.

11:43.050 --> 11:48.530
With these callbacks, you just return a result, the chat function that we've worked on in the past.

11:48.530 --> 11:50.650
That's an example of a Gradio callback.

11:50.770 --> 11:57.570
Chat just returns the result, but you can also, instead of doing that, have your callback functions

11:57.610 --> 12:03.530
be generators that Gradio needs to needs to iterate over and they will yield back results.

12:03.530 --> 12:09.050
And if you do that, then Gradio will show that incrementally in the user interface, so that you don't

12:09.050 --> 12:12.170
have to sit there and wait for a long time and suddenly see an output.

12:12.210 --> 12:14.610
You can see interim results as well.

12:14.650 --> 12:20.570
And that is why we had a bunch of yields, and that is why we have them here in our callback.

12:20.890 --> 12:24.410
I hope that makes some sense, but it certainly will do when we actually see it.

12:24.450 --> 12:26.210
If it works, let's find out.
