WEBVTT

00:00.020 --> 00:00.680
Hey, welcome.

00:00.680 --> 00:05.660
In this video, you're going to cover how you can get structured data out directly from OpenAI using

00:05.660 --> 00:06.920
their SDK package.

00:06.920 --> 00:09.050
We'll look at how you can do this with tool cooling.

00:09.050 --> 00:13.010
Also how you can do it using the response format parameters inside of OpenAI.

00:13.040 --> 00:17.420
Firstly, structured outputs give almost 100% accuracy.

00:17.420 --> 00:19.250
This is a massive improvement.

00:19.250 --> 00:23.180
Rather than relying on prompting to give a structured data back, we're going to look at two different

00:23.180 --> 00:27.740
ways that you can get structured outputs, both using function calling, which is using tools, and

00:27.740 --> 00:32.660
also then as well as that using a new option called the response format parameter.

00:32.690 --> 00:36.950
Firstly, we're going to import a couple of libraries and show you how to do it using the response format.

00:37.130 --> 00:40.190
So we will import Pydantic base model the field.

00:40.220 --> 00:47.180
We'll also import the OS and we'll also import the OpenAI package.

00:48.530 --> 00:53.870
Now once you've done this you will need to set your environment key so you can do that directly here.

00:53.870 --> 00:57.470
Or you can use an environment variable file or do it on your terminal.

00:57.500 --> 01:02.070
Also we're going to create a Pydantic model that will be used to extract some structured data.

01:02.070 --> 01:08.820
So we'll have a class of key points, which is a base model that will take key points, which is a list

01:08.850 --> 01:10.410
of strings.

01:10.410 --> 01:19.080
And each of these will be a field with a description equal to a list of key points extracted from the

01:19.080 --> 01:19.890
text.

01:20.010 --> 01:20.490
Okay.

01:20.520 --> 01:23.550
So we've given the description of what that field should do.

01:23.550 --> 01:26.370
And then we're going to set up an open AI client.

01:27.390 --> 01:30.360
And then once we've done that we're then going to create a completion request.

01:30.390 --> 01:32.790
Now to do the response format.

01:32.790 --> 01:37.710
At the moment at this current time of filming, you will need to do the client beta chat completion

01:37.980 --> 01:38.790
pass.

01:40.950 --> 01:46.380
And then you will then provide a model that will allow for structured outputs via the API.

01:46.410 --> 01:47.940
So we'll use GPT for a mini.

01:47.970 --> 01:52.050
We will also do a Messages Python list.

01:52.050 --> 01:56.610
And we will have one message in here, which is a role of user.

01:56.730 --> 01:59.340
And the content of that message will be.

02:00.130 --> 02:08.080
You know, I will say James is awesome and likes to learn code and new things.

02:09.820 --> 02:14.050
And then notice here we're going to add something new that you might not have seen before in OpenAI,

02:14.080 --> 02:15.880
which is this response format.

02:15.880 --> 02:18.370
And we're providing a format here.

02:18.370 --> 02:22.240
When we get our result back, we get a past chat completion.

02:22.240 --> 02:24.250
So let's go and have a look at what this is.

02:25.090 --> 02:27.460
You can see we've got this dot key points.

02:27.460 --> 02:29.920
So if we go in here we have a look.

02:29.920 --> 02:36.250
Notice how we've got the structured data that would allow us to form that Pydantic model.

02:36.250 --> 02:37.540
So I could do something like this.

02:37.570 --> 02:43.000
Key points dot model dot validate JSON.

02:43.000 --> 02:46.810
And you can see here we've then created a Key Points object.

02:46.810 --> 02:50.590
And we could store that directly inside of a variable.

02:50.590 --> 02:52.210
So we could put like key points.

02:53.080 --> 02:54.730
And then we can then print that out.

02:54.730 --> 03:00.440
And now we've got our structured data that we've got back which is returning a key point Pydantic model.

03:00.440 --> 03:07.700
So this is really great if you want to easily extract structured data from text, and you'll use it

03:07.700 --> 03:12.560
with this response format as a parameter that goes into the parse function.

03:12.590 --> 03:15.020
Be aware that you can inherit from other models.

03:15.020 --> 03:21.470
So we could have key points and summary which could inherit from the key points.

03:21.830 --> 03:28.070
And the key points could also then have a summary which will then have a description of.

03:28.160 --> 03:30.950
We'll put a summary of this text.

03:31.760 --> 03:37.520
And this can be quite useful because then we can change the response format to have key points and summary.

03:37.550 --> 03:39.470
Go in here into the response format.

03:39.470 --> 03:40.760
And then you'll see.

03:40.790 --> 03:45.920
Now what we would do is we would validate that model with the key points and summary.

03:45.950 --> 03:48.530
And you can see we've got both the key points.

03:48.530 --> 03:52.280
And we also have a summary of that specific piece of text.

03:52.280 --> 03:57.920
This is the quickest way to extract structured outputs using OpenAI's package.

03:57.960 --> 04:03.570
We'll have a look at a secondary way that you can do this by using OpenAI's tools, which allow you

04:03.570 --> 04:09.090
to do this whilst allowing you to answer original questions alongside structured outputs.

04:09.120 --> 04:13.650
We're going to build a database query analyzer, which will extract structured data.

04:13.650 --> 04:16.410
In order to get back that we can operate on our database.

04:16.440 --> 04:20.850
We'll give OpenAI some information about the different types of tables that we have.

04:20.850 --> 04:26.370
And also then we're going to build some dynamic pydantic models and enums so that we can encapsulate

04:26.370 --> 04:27.780
all of this with tool use.

04:27.810 --> 04:30.150
To start with, we need to import the enum.

04:31.500 --> 04:34.740
We also need to import typing modules for union.

04:35.730 --> 04:43.320
And then you'll also then going to need to import Pydantic and import OpenAI.

04:44.880 --> 04:48.630
And from OpenAI we're also going to import OpenAI.

04:48.930 --> 04:52.440
Now we're going to set up a client if you don't already.

04:52.470 --> 04:54.720
And I'm just going to put up here.

04:54.990 --> 05:01.540
Import OS If you don't already have an environment variable of your API key, you'll need to set this

05:01.540 --> 05:01.780
here.

05:01.780 --> 05:04.750
So remember to set your API key.

05:06.100 --> 05:10.630
I already have one set, so I'm going to leave this cell and I'm not going to execute it.

05:10.660 --> 05:15.880
The next thing that we're going to do is set up the specific type of table that we want OpenAI to query.

05:15.910 --> 05:20.590
The first thing that we're going to do is we're going to build our table and column enums, so that

05:20.590 --> 05:24.070
OpenAI knows easily what table and column values it's working with.

05:24.100 --> 05:28.360
Firstly, we'll create a new class called table which is a string of enum.

05:28.360 --> 05:32.350
And in there we're just going to put fruits is equal to fruits.

05:37.240 --> 05:42.490
Then we'll create a second class called column which is also going to be a string enum.

05:43.690 --> 05:48.430
And inside of that we're going to have a range of different column names such as the ID column name

05:48.430 --> 05:49.300
color.

05:49.930 --> 05:52.210
We're also going to have ripeness.

05:55.540 --> 05:57.710
We're going to have a picture.

06:01.730 --> 06:03.440
We're also going to have sold art.

06:06.260 --> 06:07.220
Stored art.

06:09.530 --> 06:10.700
And discarded art.

06:10.730 --> 06:15.020
Next you're going to set up a different type of enum, which is called an operator.

06:15.020 --> 06:20.450
And this is going to give the ability for you to extract what types of operations might need to be done

06:20.450 --> 06:22.910
to filter the data from the SQL database.

06:22.910 --> 06:27.650
So we're going to have a new class called operator which is a string of enum.

06:27.650 --> 06:31.820
And then we're going to list some of the normal edge cases that you would find when using a SQL database,

06:31.820 --> 06:38.210
such as equal to greater than is equal to greater than, we'll have less than is equal to less than.

06:38.210 --> 06:40.250
We'll also have less.

06:40.460 --> 06:43.250
Less than or equal to is equal to this.

06:43.430 --> 06:47.480
And we'll also have greater than or equal to is equal to this string operator.

06:47.480 --> 06:50.780
And we'll also have a not equal to operator as well.

06:50.780 --> 06:55.760
Now that we have our operator we're also going to create a order by string enum.

06:56.450 --> 06:59.570
And in that we're going to have two different types of keys.

06:59.570 --> 07:02.540
For our enum we're going to have the ask which stands for ascending.

07:03.320 --> 07:07.100
And we're also going to have the desk which stands for descending.

07:08.450 --> 07:09.110
Okay cool.

07:09.110 --> 07:13.220
So now that we've got the order done, the next thing that we're going to do is we're going to allow

07:13.220 --> 07:14.990
for a dynamic value.

07:14.990 --> 07:19.940
And that is basically just going to be a base model.

07:19.940 --> 07:24.770
So a Pydantic based model, and they're going to have a column name which will be equal to a type of

07:24.770 --> 07:25.550
string.

07:25.730 --> 07:26.000
Okay.

07:26.030 --> 07:28.010
So we've set up a dynamic value.

07:28.160 --> 07:33.170
The final two pydantic models that we need is a condition which will be a base model.

07:33.170 --> 07:36.620
And this is where we start integrating things which we've written before.

07:36.620 --> 07:38.780
So we have a column which will be a string.

07:38.780 --> 07:41.090
But we then also use the operator.

07:41.090 --> 07:44.570
So the operator here will be equal to a type of operator.

07:44.810 --> 07:51.200
And then as well as that we're going to have a value for this condition which will be either a string

07:53.000 --> 07:55.170
int or dynamic value.

07:58.440 --> 07:59.010
Okay.

07:59.010 --> 08:01.110
Now we can write the final thing which is the query.

08:01.110 --> 08:02.640
So we're going to have a query.

08:02.670 --> 08:07.470
And in our query what we're going to take is the table name which is the type of table.

08:07.500 --> 08:11.460
We are also going to take the columns which is a list of column.

08:12.210 --> 08:17.310
And then we also then have the conditions which is a list of conditions.

08:18.240 --> 08:23.610
And then we have a order by which is equal to an enum of order by.

08:25.260 --> 08:28.950
Once we've written all these Pydantic models, we can then query this directly.

08:28.950 --> 08:30.630
By using an open AI client.

08:30.660 --> 08:32.670
We'll create an open AI client here.

08:32.760 --> 08:36.420
Then the next thing that we're going to need to do is we're going to need to set up a completion.

08:36.420 --> 08:41.670
So I'm going to type completion is equal to client dot chat dot completions dot create.

08:41.670 --> 08:45.270
And then inside of here we're going to use the model GPT four zero.

08:46.170 --> 08:48.060
And then we're going to have messages.

08:49.830 --> 08:52.590
And then inside that we're going to have two Python dictionaries.

08:52.590 --> 08:56.410
The first one which is the role system setting the system message.

08:56.410 --> 09:02.830
And we have a content which is you are a helpful assistant that extracts information from a user request.

09:03.010 --> 09:06.820
We're going to have a second one which says Role User content.

09:06.820 --> 09:10.600
I want to query the fruits table to get all of the apples that are ripe and sold.

09:10.630 --> 09:13.150
After 2024 0101.

09:13.150 --> 09:16.450
We're then just going to print this message and see what comes out.

09:16.450 --> 09:19.570
And you can see we've got this information here.

09:19.600 --> 09:21.940
You'll notice is we haven't got the structured data back.

09:21.940 --> 09:25.420
And that's because we also have to add the tools to load the tools properly.

09:25.420 --> 09:26.920
We need to make a new tools.

09:26.920 --> 09:32.110
And then we'll do OpenAI dot Pydantic function tool.

09:32.110 --> 09:34.330
And then we put the query inside that.

09:34.960 --> 09:40.360
And then what you'll see is OpenAI is wrapping that Pydantic model and it's making it into a tool call.

09:40.360 --> 09:45.550
And then what you can see is if we look at the arguments, these are the arguments of the function.

09:45.550 --> 09:50.230
Also if we have a look at the tool call in general, you can see we've got things like the id, the

09:50.230 --> 09:53.320
function, the args that the function is going to be called.

09:53.390 --> 09:56.750
And also we can look at that as well in greater detail.

09:56.750 --> 09:59.330
So again you can see here these are the arguments.

09:59.330 --> 10:01.010
These are the bits of structured data.

10:01.010 --> 10:04.370
And returning that in a JSON format.

10:05.390 --> 10:10.610
Once we load the import JSON we can get these out by wrapping this with Json.loads.

10:10.610 --> 10:12.680
And you can see this is the structured data.

10:12.680 --> 10:15.080
So it's decided it needs to query the table name.

10:15.080 --> 10:18.320
It's going to use these columns and it's going to have these conditions.

10:18.320 --> 10:24.200
So the column which is a type of operator is equal to and the value is going to be an apple.

10:24.230 --> 10:29.450
It's also going to have another condition which is the ripeness operator is going to be equal to ripe.

10:29.450 --> 10:33.290
And then we've also got a column which is sold at.

10:33.290 --> 10:38.630
And the operator that we're going to use for that is greater than this value is 2024 0101.

10:38.630 --> 10:46.430
So you can quite easily see how we've made our own domain specific language using this Pydantic query,

10:46.430 --> 10:52.400
so that we're able to extract structured information from user requests about data in your back end.

10:52.400 --> 10:57.210
Now, the reason why you might want to use this way of extracting structured data specifically using

10:57.210 --> 11:03.450
Pydantic models is potentially you might use the same code to respond in a natural language way.

11:03.480 --> 11:06.270
So for example, if you copy the code above.

11:06.300 --> 11:08.250
Delete the client line.

11:08.280 --> 11:12.540
Then after that, all I want you to do is change the user to.

11:12.570 --> 11:14.370
Hi, how are you?

11:14.400 --> 11:21.450
So we're going to print the completion dot choices zero dot message.

11:22.530 --> 11:26.940
And what you'll see here is we get a chat completion message with the content.

11:26.940 --> 11:32.520
So I can then for example do the content and you'll see that we're getting a message back from OpenAI.

11:32.550 --> 11:39.570
So the fact is that you won't always call the tools, but these are able to be called if a specific

11:39.570 --> 11:41.460
query comes in that is useful for that.

11:41.460 --> 11:44.160
So that's why you would use the tools in this video.

11:44.160 --> 11:49.320
You've learned about both the response format and also how to do tool use, which can either respond

11:49.320 --> 11:53.010
to the user or it can extract structured data via tools.
