WEBVTT

00:00.160 --> 00:01.200
Hey there Eden here.

00:01.200 --> 00:04.600
And in this video we're going to be discussing structured output.

00:04.960 --> 00:10.600
So most of the time when we're going to be building agents and AI applications, we are going to be

00:10.600 --> 00:14.120
using lens and lens respond in text.

00:14.280 --> 00:20.160
Now if we want to take this text and we want to create a structure to it, and we want to downstream

00:20.160 --> 00:26.600
it into an application, maybe to serialize it, maybe to render it in the user interface, then we

00:26.600 --> 00:28.520
need to have structured output.

00:28.520 --> 00:36.120
So we don't just want text, we want maybe a JSON object or maybe a Pydantic object that we can go and

00:36.120 --> 00:41.560
we can downstream to our application and we can programmatically parse and work with.

00:41.600 --> 00:44.600
And this is what we're going to be doing in this video.

00:44.880 --> 00:49.520
And LinkedIn provides us a very easy way to do this with the create agent function.

00:49.560 --> 00:53.440
We need to simply add an argument which is called response format.

00:53.440 --> 00:57.520
And we're going to provide to this argument the schema that we want.

00:57.560 --> 00:59.000
It may be a JSON schema.

00:59.200 --> 01:01.280
It may be a Pydantic object.

01:01.560 --> 01:07.810
And then magically the response that the agent is going to output us, is going to adhere to that scheme

01:07.810 --> 01:09.530
or to that data object.

01:09.530 --> 01:14.530
So in this video, we're going to be creating a Pydantic object, and we're going to be creating a nested

01:14.530 --> 01:18.530
Pydantic object just to add a bit of complexity to what we're building.

01:18.530 --> 01:22.010
So the Pydantic object is going to be our agent response.

01:22.010 --> 01:24.850
And it's going to be the answer of the agent.

01:24.850 --> 01:26.610
So this is going to be one field.

01:26.610 --> 01:33.730
And it's also going to have a sources field which is going to be a list of sources Pydantic object as

01:33.730 --> 01:38.530
well, which is going to represent the URL where the agent took the answer from.

01:38.530 --> 01:41.850
So this is going to be where the agent grounded its answer from.

01:41.850 --> 01:46.610
And I want to remind you that in this video we're just reviewing interface.

01:46.890 --> 01:48.930
So we're going to see how we can use it.

01:48.930 --> 01:50.650
And to use the technology.

01:50.650 --> 01:54.530
And in the next section we're going to see how this is implemented under the hood.

01:54.850 --> 01:56.010
So let's go to the code.

01:58.530 --> 02:04.530
Let me go and import from typing the list type int.

02:05.290 --> 02:09.020
And I also want to import from pedantic.

02:09.580 --> 02:15.100
The base model class and the field class.

02:16.860 --> 02:23.740
And for those of you who are not familiar with pedantic, pedantic base model is going to give us a

02:23.740 --> 02:29.300
base class so we can inherit from in order to define a structured data scheme.

02:29.540 --> 02:37.980
So it's going to provide functionality like data parsing and serialization and automatic type validations.

02:38.180 --> 02:44.900
And the field class is going to allow us to add metadata to our models attribute.

02:44.900 --> 02:53.140
So we can add descriptions, which is going to be helpful for the Llms to understand what to put in

02:53.180 --> 02:53.860
that field.

02:54.580 --> 02:55.020
All right.

02:55.020 --> 02:59.180
So let me now go and create my pedantic object.

02:59.180 --> 03:06.180
And I want to start by writing an object to describe the sources that the agent use to get the answers.

03:06.540 --> 03:09.740
So I'm going to define a new class and I'm going to call it source.

03:10.180 --> 03:13.680
It's going to inherit from the pedantic base model.

03:14.080 --> 03:17.080
And let me write here in the description.

03:17.800 --> 03:21.600
Scheme for a source used by the agent.

03:22.360 --> 03:25.480
So now let me go and define the field.

03:25.480 --> 03:27.200
Let's call this field URL.

03:27.520 --> 03:29.360
And it's going to be a string.

03:29.640 --> 03:32.360
And here I'm going to use the field class.

03:32.360 --> 03:34.720
And I can add here a description.

03:34.960 --> 03:38.680
And here in the description I'm going to write the URL of the source.

03:40.600 --> 03:45.560
So the point of this class here is to represent the source of the answer.

03:45.960 --> 03:55.280
Now I want this source pedantic class to be a nested field in another pedantic class, which is going

03:55.280 --> 03:57.080
to be called agent response.

03:57.480 --> 04:04.920
So agent response is going to have a an answer, and it's going to have a list of a sources.

04:05.320 --> 04:05.840
All right.

04:05.840 --> 04:09.440
So let's go and create this agent response class.

04:09.640 --> 04:12.680
So I'm going to write class agent response.

04:12.920 --> 04:15.770
And it's going to also inherit from base model.

04:16.690 --> 04:20.690
And let's go and add the description for this class.

04:20.930 --> 04:26.170
So this is going to be the scheme for the agent response.

04:26.330 --> 04:30.810
So it's going to have an answer and it's going to have the sources.

04:31.410 --> 04:36.250
So let me now add the attribute of an answer which is going to be a string.

04:36.730 --> 04:45.250
And let me write in the description that this is going to be the agent's answer to the query.

04:46.170 --> 04:49.970
I have a typo here, but don't worry, the LLM can handle it easily.

04:50.850 --> 04:57.250
So the second attribute of this class is going to be the sources.

04:57.530 --> 05:00.490
So let me write here sources.

05:02.650 --> 05:05.090
And sources is going to be a list.

05:06.250 --> 05:09.050
And it's going to be a list of source.

05:09.530 --> 05:11.730
Now let me create a field class.

05:11.730 --> 05:17.170
And here let me write that the default factory is going to be list.

05:17.330 --> 05:21.620
And this will make that when we create an agent response class.

05:21.620 --> 05:27.220
If we don't provide the sources, then the sources attribute is going to be populated with an empty

05:27.220 --> 05:27.700
list.

05:28.140 --> 05:30.180
And let's add the description here.

05:30.500 --> 05:35.460
And here is going to be the list of sources used to generate the answer.

05:44.220 --> 05:44.860
Alrighty.

05:44.860 --> 05:53.100
So now we want our agent to not return us a string like we saw before, but we want our agent to return

05:53.100 --> 05:58.540
us an agent response object so we can then downstream it into an application.

05:58.540 --> 06:04.220
Maybe we want to serialize it and then return it in a response from a server.

06:04.220 --> 06:07.940
And then we want to render this response in the front end.

06:08.100 --> 06:10.980
So we want our agent to return this data structure.

06:11.180 --> 06:18.460
And to do that all we need to do is add to the create agent function the argument of response format.

06:18.660 --> 06:24.230
And we want the response format to be the agent response class that we created earlier.

06:24.550 --> 06:25.830
And that's it.

06:25.870 --> 06:27.510
It's going to work like magic.

06:27.710 --> 06:32.990
And the agent response now is going to be of type agent response here.

06:32.990 --> 06:35.790
So it's going to have all the fields that we requested.

06:35.790 --> 06:38.190
And this is going to work really really well.

06:38.190 --> 06:40.470
And we can downstream it into an application.

06:40.510 --> 06:40.990
Okay.

06:41.030 --> 06:42.590
So let's go and run it now.

06:42.590 --> 06:45.070
And let me show you how it's going to be looking like.

06:45.430 --> 06:47.750
So I'm going to run it in debug mode.

06:47.750 --> 06:51.310
And I'm going to put a breakpoint right before we print it.

06:52.070 --> 06:53.750
And let me fast forward it a bit.

06:54.150 --> 07:01.030
And now in the result we have now a new key here which is called structured response here.

07:01.190 --> 07:05.510
And the type of structured response is going to be agent response.

07:05.710 --> 07:12.070
So it's going to have the answer field and it's going to have the sources field which is going to be

07:12.070 --> 07:13.470
a list of sources.

07:14.030 --> 07:14.310
Right.

07:14.310 --> 07:19.350
So let me go now to the debug console and let me show you this in another eye.

07:19.670 --> 07:28.210
So let's get the type of results in the key of Structured response.

07:30.330 --> 07:32.490
So it's going to be agent response class.

07:32.770 --> 07:34.290
So let me go and print it.

07:34.290 --> 07:35.890
So let's go and sorry.

07:35.930 --> 07:41.090
Let's go and print this um this variable here.

07:41.650 --> 07:45.810
So now we can see all the information we have here the answer field.

07:46.090 --> 07:47.730
So let's go check this out.

07:47.730 --> 07:49.010
And this is the answer.

07:53.810 --> 07:59.810
And let's go and check out the sources so we can see the sources is a list.

07:59.810 --> 08:02.730
So let's go and check one element of the list.

08:03.170 --> 08:04.690
Let's go to that URL.

08:04.690 --> 08:05.770
Let's open it.

08:08.210 --> 08:12.250
We can see this is a job application which is not actually accepting candidates.

08:12.250 --> 08:15.650
But still it's looking for link chain developers.

08:16.930 --> 08:23.410
So this is how to use the response format argument in the link chain agent.

08:23.650 --> 08:26.650
So it's going to return us a structured response here.

08:27.050 --> 08:27.290
Right.

08:27.330 --> 08:34.020
So right now this works like a black box, so we do not know how it's working under the hood.

08:34.060 --> 08:37.220
We are going to figure this out in the next section.

08:37.420 --> 08:43.060
So right now I want to open the trace and show you how it's going to look there.

08:43.580 --> 08:49.620
So let me go and open blacksmith and let me go to the last trace here.

08:50.140 --> 08:51.780
And we can see.

08:51.780 --> 08:56.580
Let me go to the very bottom here to the last, last result here.

08:56.580 --> 08:58.620
So we can see we have this additional field.

08:58.620 --> 09:00.660
We have a structured response.

09:02.180 --> 09:04.460
So it's going to have the answer field.

09:04.460 --> 09:06.420
And this is going to contain the answer.

09:06.620 --> 09:12.620
And then we're going to have the sources field which is going to be a list of source objects.

09:12.860 --> 09:18.940
And each object has the URL field which is going to contain the LinkedIn URL for the job posting.

09:18.980 --> 09:19.300
Okay.

09:19.340 --> 09:22.540
So very similar to what we saw in the debugger.

09:22.540 --> 09:24.980
So now we're seeing it in the trace.

09:25.260 --> 09:27.220
Now how is this working under the hood?

09:27.260 --> 09:28.620
I'm going to give you a quick hint.

09:28.620 --> 09:30.580
It's going to be using function calling.

09:30.580 --> 09:33.460
But more on this on the next couple of sections.
