Hello, guys, and welcome back.
In the session, we'll see how to build our own APIs using the first API framework and Python language.
Previously we had seen that we could wrap our deep learning model or more precisely, our object detection
model into an API and then let this clients consume this API.
That is, allow them send requests like this and then get responses.
So here in black we have the requests and then now we have the responses in red.
And all this is done using the HTTP protocol.
And so now that we understand the concept of an API and how this can interact with millions of clients
everywhere in the world, we are going to move straight to build in our own API and to build our own
API.
We are going to make use of this Python framework known as Fast API.
Now other python based frameworks which can be used in building APIs are Django and flask.
But in the recent years, the first API framework has gained much popularity amongst Python developers,
thanks to the fact that it comes with some key features like speed.
So it's a high performance framework.
Time taken to code is reduced that now developers could now build features even faster.
With fast API, you even have fewer bugs.
It's more intuitive, it's easy, it's kind of short, robust and is standards based.
So because we need all these features while building our object detection API, we kind of have little
or no choice but to turn to the fast API framework and you're going to see how easy it is to create
or build a fast, highly performant and robust API very easily using the fast API framework.
First and first, feel free to check out this documentation at fast API tango dot com.
Working with the fast API documentation doesn't really feel like a usual documentation as most of the
concepts are well explained and broken down to enable just anybody with minimal python knowledge, understand
and use fast API efficiently.
So right here we have the features for API people.
You could get straight into this tutorial, your user guide.
You see you have this well written user guide, you also have the advanced guide.
So once you're done with this user guide, you could get to the advanced user guide.
You have special topics like Concurrency Deployment, Project Generation, and all this.
And so before we move on, don't forget to star the Fast API GitHub repository.
One of those course prerequisites is having used Python at a very basic level.
And so we're supposing that you've already installed python without which you could head on to python
dot org download and install python based on your own operating system.
So here you could see we have Python installed Python version, check that out 2.7 and then python three
version we have 3.6.
This should be 3.6.
Okay, there's an error there.
We have 3.6.
Okay.
Now the next step will be to install fast API.
So we head back to the documentation.
You have your this installation.
All you need to do is PIP install fast API or you could do pip install fast API all so you get other
optional dependencies and features.
We'll start by installing fast API.
We have pip three install fast API.
There we go.
API now installed.
We could do python three and then you import fast API.
You could check out the version right here.
We have fast API and then we have the version OC.
So that's it.
0.78.0.
So the next problem we may face will be what if we have this project, this object detection project
in which we have the fast API version 0.73.0, for example, installed, let's say 0.73.8 installed.
You have this other project on optical character recognition, which needs a different version of fast
API that is 0.75.0.
You find that with this there will be a conflict.
As what?
Have installed is this 0.78.0 version.
Now, the way we could solve this is by making use of virtual environments.
The way virtual environments work is you could have this project, this object detection YOLO X project
have its own.
Isolated Python environment with its own interpreter where you can install this libraries.
In this Python environment without it affecting this other project, which is with another or which
is built in another virtual environment where we have a different set of libraries and library versions
installed.
So this means that in this environment here we could install a version of non pi C, let's say whatever
version.
And then here again we could install another version of Non Pi, which could even be the same as this
version.
But the difference now is in this virtual environment here we have a version of Fast API which is 0700780
and in this other virtual environment we have this other version which is 0750 and now this problem
of conflict at the level of the dependencies is resolved now that we want to create our Python virtual
environments, we are going to make use of this python module, which is the Python vamp module.
So you will simply do apt install the python python three valve and that's it.
So you're yours.
Okay.
And that should be installed.
Now we have the valve installed.
Let's get into our neural learning projects directory and then from here what we'll do is we are going
to create our virtual environment.
We have Python two V valve, and then let's call our virtual environment valve, emotion detection,
the detection.
There we go.
We should have this created.
And from here you could do this.
And you see that we have this valve motion detection here created.
Let's get into this valve emotional detection directory.
So let's do valve emotion detection.
And there we go.
You see, we have been include leap leap 64 by Valve and share.
Now let's get into the the bean.
So there we go.
We have been and then you see we have this activate right here.
Now let's get out of this and then let's do source.
Well, let's get back again another step.
So let's do source bean activate and we get in this error.
Well, let's get back into valve emotions detection and then let's reduce source bean activate.
And there we go.
So one thing you can notice now is the fact that previously we had this root and this, but now we have
this valve before this.
So we see that everything we're going to be doing from now, henceforth will be in the context of this
virtual environment.
Now, let's do Python three.
There we go.
Let's import fast API.
You can see that we have modeled, not found.
So it's telling us that fast API is not installed.
Now let's get let's exit and then deactivate the way we deactivated by simply typing in deactivate.
And you find that when you deactivate you do not have this any longer.
So we are no more in the context of the virtual environment.
So now let's do again Python three and then let's import fast API.
You find that here we have fast API installed.
You see, we could also get the version you see we have fast API installed, but in this virtual environment
Fast API isn't installed.
Now let's exit and get back to our virtual environment.
So we have source being activate.
There we go.
And now let's do PIP install fast API.
So one thing you could note is the fact that out of the scope of this virtual environment, we have
this version of API and now we could install another even different version of the first API.
So that's it.
We install fast API and now that fast API has been installed, we could do that in this virtual environment.
We could do import or let's do Python three and then let's import the first API and there we go.
So we have fast API now installed.
We could get this version and you could see clearly that this version is different from the other version
of fast API.
Another thing we could do is create our virtual environments with a specific version of Python.
So yeah, we could have Python 3.8 and then we have Valve, let's say emotion or let's say IMO detection.
Okay, so there we go, we run that and then we create this.
New virtual environment where the default version of Python is that of 3.8.
Now let's again have this.
You see, we have this year we have IMO detection and then we could get into that IMO detection.
And then let's activate this.
There we go and see this right here.
Now when you do Python, you see that the default version is this 3.8.13.
So again here, if you try to import fast API, you see model not found.
Let's exit and then peep install fast API all and run that.
You'll get to see now with this pip freeze that we have many more dependencies installed because we
decided to do that.
So here you see we have type extensions, toilets and if I go pedantic, which is very useful and this
others.
Now the next step will be to install unicorn and unicorn is an s g server, so as g here signifies asynchronous
server gateway interface Being a HTTP server, this unicorn right here is responsible for taking requests
from different users.
So supposing we have this three users right here, the one to get, for example, some predictions from
a model which is here in our fast API, which we have bundled in this Alphas API code.
So what will go on here is this user for example, will make a request, see to this server and then
the server gets that request, interacts with fast API, obtains a response and then sends back this
response to this user.
Now if you want to connect with this web server locally, we could pass in this IP address here, which
is that of the local host.
And then we specify a specific part such that we now here does the client sends the request which contains
the method, which could be, for example, let's say a post method and then the request body and headers
such that once this web server received this, it processes the information and produces the required
responses.
We are now going to dive straight away into some protocols.
So here you get this fast API, you have this simple tutorial here which we are going to follow and
see how to easily work with fast API.
Right here we have this which we are going to copy to open up the code with Visual Studio.
We will get back and then we'll just write code and there we go.
So now let's actually get out of the superuser mode and then we get back in here, learn.
There we go.
And then now let's just do this again.
And you see we have our Visual Studio, which pops up.
We have our neural and projects folder and we could create this new file.
So here we have main P, we create this new file and then we paste out that code.
Now, if you're working with VTS code, it's recommended to install this Python extension, so we just
go ahead and install this extensions.
See, we have that installing.
Let's get back to the code or let's just get back to this.
So here, for example, let's analyze this with Claire here, for example, you see, we told to create
a file in the PR y and with this code we are going to put in there now to keep things simple.
We are going to command this region and then also command this right here.
So we're not going to make use of this.
We're going to command that and that should be fine.
Okay.
So we just have this portion of this part here.
Now, you see here we have this app, which is an instance of fast API.
C, we've imported this from first API, and then we have this decorator here and we have this read
Root Method.
Now this root method, we could actually change this so we could say read neural learn route or whatever
name you want to give it.
So let's call that learn or let's just keep it short.
Let's just say read.
So we have this read method takes a nothing and then it returns this dictionary or this JSON halo for
the key and word for the value.
We have this.
The corridor right here where we specify the method type recall.
We had different methods like the get the post, put the delete and so on and so forth.
So you have, for example, we specify this method, so this is the get method.
And so if we are making use of this metal right here, we have this path, here we have this path.
And then this means that if our web server is hosted on an address, for example, let's say HTTP s,
whatever or whatever dot com, then this route path will correspond to this path right here.
And then if we want to do say a login, then we'll have your login.
This login path will correspond to having this logging right here.
Obviously we'll have a post, so change this to post and that's basically how it works.
You see how easy it is for us to create these kinds of paths with Fast API and also specify the methods
very easily.
So here we have that and we could have slash or let's say a whatever we want to have there.
And then all we need to do here is to have this here.
A Now obviously we could have some variables here and we're going to look at that shortly with this
other example below.
Anyways, we we understand that we want to get to an address or your whatever dot com or let's, let's
even say google.com, let's say we're trying to build google.com.
Then we will just have here this and that will be it.
And so with this now specifying this is going to get into this method and return this JSON now to run
this, we'll just use what we've been given here in the documentation.
Let's copy this out and simply paste this out here.
So here we're going to open up the terminal.
So we open up this new terminal.
There we go.
Claire That's it.
And we in project.
So make sure that you're in the same folder as where your main copy is found.
We could do you've con and we run that error in the app attribute app not final model mean.
So let's check this out.
Let's save this and then run this again.
There we go.
See, now it works.
We have started server process with the application startup application startup complete.
So we wait and then it's completed.
And now you've gone running on this address on our local host.
So what we could do here is we simply control and we click open this.
So control click and it opens up this page right here.
There we go.
The first thing we notice is this message where we have method not allowed, but why?
Where will we have this method not allowed message.
The reason why we have this is because your let's open this.
The reason why we have this is because you're in the code.
We actually use this wrong method.
See, we're supposed to use a gate method instead, so we should change this and have this get.
So let's save that again and then we'll stop this and then run that again.
Click on this, open this up.
And there we go.
We have, as we expected, the JSON output.
Here we have the ID or the key.
Hello and the value world.
Now another thing we could do is we could get back here.
Let's stop this.
So we stop that and then let's do, let's say entry point, let's have that.
And we save this.
So we save this and then we run this again, and then we click on this and you see that are not found
So here because we do not have this path, we outputs, not found.
So let's let's do this, let's say entry points and run that.
And you should have an answer.
Let's check this out here.
We have entry point and then here we have entry point.
Let's get back here.
And then we should have this to resolve this issue.
We have to put the slash before the entry point.
So you have to be very careful with the way you write this.
Now you save that again and then you reload.
But aren't you tired of always having to reload?
I guess as myself, you would also get tired of doing this.
So let's do this.
Instead of having that, we would add this reload your search that once we save or do modifications
and save here, automatically our server is reloaded.
So now we will run this.
Uh, application start up started.
Let's click on that.
We have this and then we do entry points.
That should be fine.
So that's it.
We have Hello World, as we expect.
Now, let's go ahead and update this.
Let's just say entry.
You see, when you save now use here.
You see it's shutting down.
Waiting for application shutdown, application shutdown, complete finished server process start is
have a process within for application startup and application startup completed.
So now we have this which has been reloaded.
So unlike previously where we had to stop and then start again.
Now once we make the modifications, it's automatically reloaded.
So let's get back here or not here, let's get back here.
Oh yeah, actually, let's get back here.
And then we are going to have let's run this, you see, doesn't work.
But when we do entry, it works now.
And we didn't have to stop the server for that.
The next thing we'll look at is another interesting feature of fast API, which is the swagger UI.
So here we've saved this, reloaded our server and then we get into this and then instead of having
that, we'll do docs.
So you see we have DOCS, so we have this page which pops up and you'll notice that we didn't need to
specify that in our code.
So let's get back here.
And what we see is we have this method here and then when we open this up, see that does a path and
then we have the parameters, there are no parameters.
So we have this simple get request and then we have the response.
So we are the the code 200 and the successful response and then the major type JSON and that's it.
So now let's go ahead and try this out.
So we see when we try it out, we click on try that out and then this comes up, we click on Execute.
And what we have is this output right here.
So here you can see the response body and then you can have the response headers.
So that's it.
You could also repeat this on the postman.
So we have that, you see the request URL and then you have the URL.
This you could use also to make the API calls.
So that's it.
We see how to make use of this docs.
And now what we'll do is we are going to uncomment this to parts here.
So here we recommend this and then we'll uncomment this part and then we save this.
And then you see here we have this items.
Now we will notice that when we get back to our code and then we refresh this, we have this automatically
put out here.
So this means that no matter the number of different paths we create, we can automatically test them
without any extra effort thanks to this fast APIs swagger UI.
So like your for example, you not only can test, but you can also see the documentation.
Like here we told that this is an item, ID is an integer is required.
Then this is a string cure query.
It is optional because here you see is not required and then you could try this out.
So let's go again.
Try that out.
We see, well, let's cancel and then you see, you cannot do anything here.
Once you want to try out, you can put in an ID, So let's let's not put anything there.
Let's just execute.
You see, we must put something.
So let's have that 20, 20, the string, let's, let's leave that for now and execute.
So what do we get as results?
Is this output item ID 20 cure null.
Now if we modify the code right here, so let's modify the code and then let's just say item ID, save
that we get back here and then let's re execute.
Actually, let's we execute.
What do we get?
You see it's automatically we have this modifications and then now we could do this, let's say hello,
we execute that and you see here we have our optional string which has been shown to us in this JSON.
So we had seen the JSON format already.
Here we have the key, we have the value, the key, we have the value and so on and so forth.
And then also we have the response headers.
Getting back to the documentation, you could see here the scroll back up.
No, let's, let's get down.
You could open this up.
You see the main, the file, the ab, the object created inside of main pie with a line of API reload.
Make the server.
Start after chord changes only do this for development.
So they're saying that if you're in a production setting, that if you've deployed this as we'll see
in the next sections where you want to deploy this, you don't want a situation where you get to have
this reloads automatically.
So from this now you see this.
Basically, we explained what we've said already receives HTTP requests in this path and in this other
path.
So we seen this already.
Now both packets get requests.
So we have the gate methods.
The path this path has a parameter item ID that should be an instance or a path has an optional string
query cure.
So that's it.
And then you're you you get to talk about the swagger UI, and then you also have this alternative doc
API docs here, which is re doc.
So basically what we'll do is we just get here and then instead of having all this, let's say we have
that, we just do re doc, we run that and you have this alternative UI, here's where you could still
again test this APIs.
So that's it.
You could test this very easily.
You see we have that and then you should be able to test this.
Now you have the response samples from your SO for this, you have this response sample, you have the
others, a successful response or the response is unsuccessful.
Where we have this photo to now, you could check out in the Mozilla platform where you see the exact
meaning of this photo to.
So let's let's check out developer Mozilla 422.
So you could always get back to all this so you don't have any issues understanding any code you receive
as output.
So here you see unprocessed possible entity and that's it.
That's it for this.
Here we have different responses.
That's fine.
The next feature we'll be looking at will be that of schemas.
What we'll do here is we'll simply take this off.
We'll keep it simple.
We will not use this and then we'll change this into a post request.
So we have this post request right here which takes in a body.
Obviously we have a body and then it returns the elements in this body.
Now here will take this off and then we have our post request.
So there we go, we have our post request.
It's no more read item, but now add item.
Now here we're going to have an item which is going to be of type item.
So this is going to be a special type we're going to create.
Now here we are going to import pedantic or from from pedantic, we're going to import the base model.
So that's what we're going to do.
We're going to import this base model from pedantic, and then we're going to create this item, this
class item, which is going to be a subclass of this base model class right here.
So we have this item and then we have base model.
So that's it.
And then here we're going to say, okay, we want that an item should have a name and a price.
So we have name which is a string, and we have a price price.
Let's, let's say integer, let's say our price an integer.
So that's it.
So there we go.
What we're going to receive here is this item of type item.
It's no longer the usual types, but now this special type item which we just created.
So now here we have item.
And then what we'll do is we're going to return this, so let's call this item name here.
So we have item dot name.
So we get the item, we return it's name and then we also have the items price, So item price, and
then we return the item price.
Okay, so that looks fine.
Let's save this and check our code here or check this API.
Let's refresh this and then you see we have our post.
We could check that out or let's try this out, execute.
Or do we get we get in response body item string item price zero.
Now if we come here, if we get here, you see a level of this name and then we put, let's say back
and then price, let's say 20, and then here we execute.
What do we get?
You see, we have back 20.
If there's something you can notice is the fact that this request body here automatically takes this
name and price.
So let's get back to the code.
You see that if we modify this, let's let's say we want to get the name, want to get a price or let's
say we want to get the cost or let's say we want to get a discount.
So let's say there's a discount on the item discounts and then let's put this in.
Okay, We save that and then we get back here, we refresh this, try that out and you see discount
automatically is here.
So the role of this schemas is to provide a model which the request body has to always follow.
So this means that if you get back here, let's get back here and let's take one of this off.
You see, we take one of them off, we execute, take out the response.
You see here, expecting our property name, enclosing double quotes, all of that you see here we have
this unprocessed double entity error.
Now, this is because you're at the level of the request body.
We didn't specify the discount, which we've already said in the schema that we need to always have.
So doing this means that each time anyone has to make a call on this API, on this endpoint right here,
that person has to specify the name, the price and the discount for the request body.
Now, we could also enforce this kind of measure at the level of the output, so we could specify a
response, body response, body.
And then we define say, let's say, let's say this is input item, let's call this input item, and
then yeah, we'll have output item.
So we want to create another schema here.
Let's copy this and then we're going to say that, okay, we want this output to be the price minus
the discount.
So here we have output out put and then instead of the price and the discount, we just want the selling
price.
So here we have selling price and that will be an integer.
So we have that.
Now we have the output, we have the input and we have the output schemas.
There are both subclasses of base model.
And then here's what we'll do is we'll say, okay, we want to have the selling price, will define
the selling price to be the item price minus the item discount.
Okay, So we have that.
So we have this now.
And then here we have the item name still, and then we have the item.
We have to be careful the same as this.
So we have to say selling price anyhow, let's leave that for now.
Let's just say we have here selling price.
So let's say we have selling price and then let's save this and check this out.
You see already post got an unexpected keyword argument response body.
This is actually a response model, not a response body.
So that's the output response model.
Let's let's let's change this to input.
So now this input item for the request and then this output for the response.
Now let's save this.
That's fine.
Let's go ahead and check this out.
So here we try this out.
There we go.
You see, as usual, that's fine.
And then let's let's give this a price.
Let's say 20 and no discount and then we execute.
So what do we get?
Your internal server error.
Now let's get back to our code and check out what's going on here.
If you required this mission.
Now you see that everything looks like normal, but we saw that there's a field that required a level
of the output.
And the reason why we have this is simply because this output expects to see selling price.
You see it expects to have certain price.
So because we do not have selling price here, we get that error.
Now, let's save this get back here.
I'll refresh that and then try this out again.
Execute.
Now let's let's put you at 20 anyway.
You should it should be the same.
It's just that we want to have to see the difference in the order to see how the selling price is computed.
Here again, we have internal server error.
Now this looks funny.
Let's get back and see where we get an error.
We told field required and it happens that we even did not specify this correctly.
So here's this year's name price discount and this is name.
So yeah, we should also have name so not item name.
See if that again, we go ahead and check this out here.
Let's refresh that.
Try this out.
Let's just execute and that's fine.
So you see, we have that now.
And this is because we've put out our outputs correctly.
So let's have your C to 100 and then 180 or let's say 20, and then we execute that and see we have
this output.
So that's it.
We see how thanks to the schemas, you could now build APIs which permit the developer or whoever making
use of your API to have to specify this, without which nothing is really going to work.
So this means that you could have a situation like here.
Let's, let's see, we have this input item and then we let's, let's see if that again and get back
here.
We refresh the page and then we'll try out while taking off this.
So we take this one off and then we go ahead and we execute.
You see that the output here for two two is a client error.
So this means that the client knows that this error is coming from here.
So our side now we get back here and then before we move on, we are going to define this structure
or this code structure for our first API projects we'll be working with.
So what we want to do is separate the APIs.
That's actually the endpoints from the core.
Now when we talk about core, we're talking about let's get back here, we're talking about carrying
out computation like this.
So you see this computation.
We want to have some separate file which is in charge of doing this.
In the case of some deep learning model, one, to have a separate file which will be in charge of,
say, taking the inputs, loading the inputs, passengers input to a model, doing some post processing.
And then from there, now the output, the output from that is passed onto this endpoints because here
this one endpoint and this another endpoint.
So just like read this add item.
Now getting back here, you see this is like having read here this one endpoint, read this endpoint
at item, just maybe on the endpoint, say update item.
So like routes you have get items, post items and so on and so forth.
So now at the level of the core one one half, our business logic in our case, for this simple example,
our business logic was basically just taking the, the price and then subtracting the discount.
So that was our business logic.
But we, we, we want to have this in a separate file.
Now for the schemas.
We want to also have this in some separate files.
So we want to have this kind of structure where we have the car that's business logic schemas and then
we have the API in charge of all the different endpoints.
Now to do that, we are going to create our service.
So from here we have we're going to add a new folder which will call service.
And then in the service we're going to add a new file which is now basically let's copy this main into
the service here so we could do this, we could copy that, move that.
Now let's stop the server.
We've moved this into our service and then in the service we have a new folder which we'll call API,
and then we'll create another new folder which we'll call the car.
Now in this call we have a new folder which we'll call the logic, and we also have another folder which
is called the Schemas.
Schemas.
Okay, So we have this this no, this is this is this call has this new folder which is called schemas
and not the logic.
So let's, let's delete this folder here.
Let's delete this move to trash.
Okay.
So we have that, we have the car which has logic and schemas and then we have the API now which will
have different endpoints.
Now, given that we need to carry out our inference making use of this quantized Onix model, we are
going to start by PIP installing on x runtime.
So yeah, we have PIP install x run time and there we go.
Now we get in this error, so you have to make sure you run this as a super user.
We now run this as a super user.
We have PIP installed on x run time that's now installed.
You see, we could do Python and then in part on x ray.
On time, and that's fine.
Okay.
That said, let's do pip install OpenCV python.
We could also check that out.
Let's clear this and a python and in part cv2.
And there we go.
So you see we have now the Onyx runtime and open C installed.
We then move on to create the endpoints.
So in this API, we have this new folder which will call end points.
And then here we'll create new file which will call detect pi.
And in here again we have another file which will call test py.
Now this detect the prior will play the role of actually being that endpoints through which we are going
to carry out a detections.
And then this one will be the endpoints true which will test if our API is alive or not.
Now in our detect py, we are going to import the API router.
So from first API import API router, there we go.
So previously we had imported first API, but this time around we'll be working with this API router
then.
Now we'll create this object IMO router of the API router class where this will play the role of routing
information from the detect the API to the main API.
Now we have our IMO router decorator and then we have we specified I want to have this get method and
our path will be detect.
Okay.
So here's our path.
And then now we could define this detect method in your with this detect method.
Given that we want to carry out detections based on input images, we're going to have as input this
time around this image and then you find that given that it's an image, it is going to be a type upload
file because the user will have to upload this.
So that's the type upload file we we have that we could simply import this from your upload file.
There we go.
And then once we once we define this, we can now get into the body of our method.
So from here we could start by just let's say we output return, return, say hello, Hello world.
So let's just return this.
So now we have this method which takes in the image which is uploaded by the user and then returns Hello
World.
Now to diving into what this detect is going to be doing, we'll need to import this image from pill.
So from pill you're going to import image.
There we go.
So we have that imported and then we are going to open up the file.
So let's let's say we have our image.
We want to get our image image.
There we go.
We open up the file so we have image open the file which has been uploaded by the user.
So we have M, which is this dot file dot read.
But this open method here takes in bytes.
So we have your bytes bytes IO to convert this to byte form and then you would simply import that.
So we have from IO, we import bytes IO and that should be fine.
So that's it.
We now have our image which would then convert into a non pi array.
So now we have image equal non pi array which takes in this image.
And then now instead of returning this, we could have this method emotions detector, emotions detector
which takes in the image.
So it takes in this non pi array or basically takes in our image and then is going to tell us what class
that image belongs to.
So for now we have this let's import non pi that's important on pi.
So we have import non pi as MP.
Okay, so that's it.
We now have this imported.
We are also going to check if the image or whatever file we are uploading is actually an image file.
So we get the file name, we have the file name and then once we obtain the file name we try to get
this extension.
So right here, stick this off.
We have that split method, then we obtain the extension.
And if this is.
Or is part of this that if it's jpg g pack or PNG G, then we know that this is an image and so we're
simply going to pass.
If this is not the case, then we'll raise an exception.
So here we have raise raise HTTP ec ception and then we will make sure we import this HTTP exception.
Then we specify the status code as 415 and our detail is not an image.
So that's what we're going to do before calling on this emotional detector matter right here.
Now, before we move on, let's let's keep install on pillow, because you could see here that we have
this.
We have the pillar library, which is yet to be installed.
So we're just going to do your peep install pillow.
There we go while there's installing.
Also take note of the fact that this is meant to be a post request and not get requests.
So we replace this with post.
Now that we have pillow installed, you see, we do no longer have the one we had before.
So that's it.
Now we could take out on our test pie.
This time around we're going to create this test router.
So here we go.
We have a test router, and then we just call this test testing.
And your could take this off and this is a get request.
So here we have this get request and we would have this test.
So this is our entry point and then we could take all this off.
There we go.
Here we now have we're going to return
testing or let's see.
Yeah, testing,
testing.
So that's it.
We have testing, testing.
Our iPad is working.
So this is what we're going to output when we have this all pass this through the browser.
Now that we have this two endpoints defined as this test and this detect right here, what we are going
to do is we are going to create in this API folder the API API file.
So let's create this new file API API.
Notice how this tool in this endpoint.
So detect and the pie and the endpoints folder or directory.
And then this API, the pie is found in this API directory.
So now in this API API, what we're going to do is we are going to create this main router and the role
of the main router will be to include this detect router and the test router, which itself now will
be included in the main app.
So as usual we have to import this API router from first API and then once we have this imported we
are going to import the detect router and the test router.
So from service, remember we've created this already.
API endpoints detect our detect API right here.
We are going to import detect router and then let's copy this piece out here.
Now we're going to import the test router from test.
So there we go.
So we have the detect and the test routers now imported.
The next thing to do would be to create our main router.
We have this main router API router which was imported already, and then now the main router is going
to include the detect router and it's also going to include the test router.
So we have main router including the detect and the test router.
So there we go again, we can access the app via the detect or test or maybe some other let's say some
lambda lambda router right here.
And then all of this get included in our main router, which now is also included in the app.
Back to our main API we have from Fast API.
This time around we're going to import fast API, take that off and then now we import the main router.
So we have service API to the API in part main router.
There we go.
So we have this main router imported as usual, we have the app first API, then we could specify the
project name.
There we go, emotions detection and then we have to include now our main router.
So this time on our app.
Now with our app we have the include router method which takes in the main router.
So that's it.
We have this now included and we will now turn all this into packages.
So this endpoints, we're going to create a new file in neat dot pie.
There we go on the API API, new file we have in neat dot pie.
Then for the car we have under logic we are going.
Create this new file in it.
Dot pie schemas.
New file.
You need the pi on the car, hoops car, new file.
You need that pi.
Then finally, for the service itself, we create this new file we have init pi.
So we have our service package, API package and core package.
Now remember we have this emotion detector or matter layer which we had to define.
We are going to get that defined in the logic.
So on the logic, we're going to create a new file.
We'll call this Onyx in France PI There we go.
And then here will simply create this method.
Emotions detector, emotion detector, which takes in the image array.
And then we're going to follow up this simple steps we had seen already from the lab notebook.
We start by the import, then we specify the providers.
Then there we go.
We have the quantized model, the image path, the test image which is created.
And then now we finally run to obtain our predictions.
So let's just copy all this out and then put out in the code.
There we go.
Let's pass it out here.
Back here.
There we go.
And then finally, we have this predictions.
So that's it.
Now let's make sure we import on X time, C on x, import on x, runtime on X run time.
And then also we'll need to import OpenCV.
And what do we need again, we need non py.
So import non py as MP.
There we go.
So we we import on x runtime import opencv and then non py.
Now this is our method which we are about to define.
Send this this way.
There we go.
And then now we're going to return this output.
Actually it's practically this year.
So let's copy this from here.
Let's copy this from here and then paste out here.
Well, so that's it.
We have this.
Now let's modify.
Remember, what we're getting here will be the image re.
And so we no longer need to specify this image path.
Let's take all this off.
Take this off.
And then from here would have this quantized model.
There we go.
We have our quantized model.
We've already specified the the providers.
So this are quantized model for our test image.
You see, we're going to take this image array and then resize it.
So let's take this off from here.
We have 256.
By 256, we take all this off and there we go.
Now import this on this runtime as our TT.
So there should be fine.
Now, that said, let's get in here and see what we have.
We print this out.
Let's well, let's just let that for now.
And then we see we have our predictions as we know already.
And then from here we have the output.
Now, one thing which is left out is this this file actually we had to get or put this file in this
right position.
We've copied this on this file here, which we trained already.
And then let's update this then once is fine, let's get back to our detect that py and make sure that
we import this emotion's detector.
So here we have from service dot core, dot logic, dot onex in France we're going to import emotions
detector.
So that should be fine.
We have now import this imported that's check that out and then let's let's save this get back to our
own inference.
And then now at this point, we're going to say if if NPR marks unexpressed, which is this year, let's
copy this and paste out your if this is equal zero, then what we'll do is we're going to have the emotion
here.
Let's have emotion
set.
So angry, happy or sad.
So here we have emotion equal, angry here that's angry.
And then let's copy this.
Well, let's say let's have this here.
Let's copy this year piece out here.
Now, leaf leaf.
This is equal one.
Then this is happy and else the emotion is sad.
Okay, so that's it.
We have angry, Happy or sad?
And then what?
We're going to return your would be this dictionary where we have emotion and then the output will be
simply the emotion.
So that's it.
Let's take this off now.
There we go.
We have that set.
And when we get back to the detector pie, you see that this fine, we're going to pass the image and
we're going to get the corresponding emotion.
Now we have all this set.
What we could simply do is run our server before launching the server.
Let's add this root endpoint right here.
And then now let's do let's launch the server.
You've called service main app Reload.
So that's what we have we get in this error cannot import name detect, detect route from service API
endpoints detect.
Well what we'll do now is we're going to create this new folder and we'll well, this shouldn't be in
here.
This is going to be here.
So in neural projects we'll create this new folder, new folder which will call emotion detection.
And then now we'll copy the service in our emotional detection folder.
Let's move that.
There we go.
So now we have an emotional detection.
We have the service.
We're going to relaunch the server again.
You see, we still get this error.
Now let's get into this detect file.
You see here we have this.
You see it's actually email, router and now detect router.
So if you get your we should have IMO router there we go e mail router and here we have IMO router.
Okay.
So we load that we cannot import name test router.
Well let's get into tests.
We have test router right here.
This should be fine.
Now that we're getting this error, let's make sure we have this here.
So we we created this main router which is an object of API router class.
We save that and then this should be fine this time around.
So application startup complete.
Get into the local host.
You see we get what we expect we have Hello world.
So this is what we get when we pass this in our browser.
We now open up the swagger UI.
You see, we have this detect here as expected, we have testing and then we have the root.
Okay, so that's it.
Let's open up this detect and you see, we could try this out.
Then we could pick out a file which we could actually test.
So let's go ahead and test with this file.
Let's open this up and now let's execute.
So let's check out the output, fail to execute this.
And so that's what we get in.
We get in an error.
Let's get back here.
Once you could see the fact that this request, you are error right here isn't what we expect.
We expect to have a slash before the detect.
So let's get back to the code and then modify this.
So take this up from here, save this and that should be fine.
So we should have the same with test.
Save that and you're okay.
So that's fine.
So let's now get back and then test this out.
Let's refresh.
There we go.
We have the text.
We want to try this out.
We want to choose a file.
Let's go ahead and pick a file, this file and then let's execute.
Okay.
So let's check this out.
We get an internal server error.
Let's get back here and try to see where we have the problem.
So we've been told that this file doesn't exist.
What we'll do is we'll make sure that we put out the right path.
Now we have service and there we go.
So we have this efficient, quantized Onix model which is in our service directory.
You could find service right here.
So that is it.
Let's save this.
I saved this and then let's go ahead and retest this.
So reset console, try out and then let's retest this once more.
Execute.
Seems like it's going to work this time around.
Let's go ahead.
We still have an error.
Now let's get back to the code and try to understand why we have this arrow.
We told invalid rank for inputs input got three expected for Please fix either the inputs or the model.
So this is what we are getting here.
Now let's get back again to our code.
We thought that what the model gets isn't what is expected.
So let's print out the shape of this image array right here, this print out shape, image array, shape.
And let's save this and then try out run this again, Research council try out, and then we test this
once more.
Just execute that.
And obviously we.
Have the internal several error.
But now we want to see exactly what gets into the model.
So let's scroll and we should get the output.
Okay, so this is the output we get.
Now you notice that here we have this image which is of shape 90 by 90, but what we would have expected
here should have been 90 by 90 by three.
So it's a grayscale image when we expect an RGV image.
Now what we'll do is we'll say here if the shape is grayscale or rather if the image is grayscale,
then we are going to make sure we modify that.
So if the length of image array shape is equal to, then what we'll do is we'll ensure that we convert
this from gray to RGV.
So let's do this, scroll this way, let's do this, and then let's print what we have from here.
So copy this and then paste out here.
Okay, So there we go.
We're going to paste this again.
So we see what we get after we convert the gray to RGV.
So that's it.
Let's save this again.
Let's save this.
This should be fine.
So we save that, then we get back here.
Okay, so let's test this again out, reset console, try out, pick the image, execute.
And there we go.
You see, we have the emotion happy right here.
So we have the expected response.
So we have here emotion happy.
Now let's get back here and see.
You see we have 90 by 90.
Now it's 90 by 90 by three after the conversion.
And then we have after resize, we now pass into the model and we have the expected output.
So that's it.
Let's take this off and that's it.
So there we go.
We've just tested our API and we see that it works just fine.
Now we could take off whatever prints we have here, take this off, take this off, and there we go.
We then move on to our schemas where right here will create this input of and this output of p file.
Now, in our output of P file, we'll start by importing base model.
Then we'll create this API output class which inherits from base model, and then we'll specify what
we want our output to look like.
Now, given that we've seen already from here, our output is this string emotion.
So let's get back to the code and see that this is exactly what we want to have.
So let's save this or let's, let's say we put this as an int and save this.
Then let's go ahead and test.
So let's well, before doing any testing, we have to make sure we integrate this with the detector.
PI So let's get into this here.
Endpoints detect pi.
Well you have this response model here, but normally this isn't there.
So before we did, we didn't have this.
So we have we should have this now you see response model and then specify API output.
So you are controlling what or how this output here should look like.
So now we have that make sure you you import API output from here and that should be it.
So let's save now again and then let's test this out.
So we execute and then we check out the response.
You see, we get a response internal server arrow, which makes sense.
Value is not a valid integer.
So you see that we are able to tell our API what we want our output to look like.
Now let's get back to our schemas.
Let's take down here output and then modify this and say we want to string.
So let's save that now and then go ahead and retest this.
So there we go.
We execute and we check all the response.
You see now we have exactly what we expect.
So that's the role of the schemas.
Now we are going to do the same for the inputs, just we just do only for the output.
And then from here we'll move on to the next part.
We'll then go ahead to measure our the time taken by the model to produce the output.
So we get into this Onix inference of pi and then just before this well let's say at this level once.
Obtain our image.
We're going to have time in its time it needs, which is going to be equal time, the time so we get
a time.
This initial time, let's impart time.
Right?
Your import time.
There we go.
And then once we import time and we have set this time it needs we want to get the time elapsed.
So after we've gotten a prediction, we want to get a time elapsed.
You have time elapsed, which is simply the current time minus that initial time.
And then for the outputs, we want to have this emotion and also want to get the time elapsed.
So let's have this well, let's return emotion.
And then we also want to return this time elapsed, which is simply our time elapsed.
We'll convert this into a string.
So we have that.
Now let's save this.
Well, this should be time elapsed, let's save this.
And then now let's go ahead and retest.
So right here we're going to execute and see what we get.
We get in this output, but we are not getting this here.
So let's let's reduce this and save this again.
Let's get back here.
Let's save this again.
We run this.
Execute.
There we go.
We're still getting this.
We doubt the time elapsed.
Well, what we'll do now is we'll get back to our schemas to get back to the output and then include
this time elapsed and it's a string.
So let's save that and then check back here.
Um, there we go.
We are going to execute.
And we should get this response.
You see, it takes about one second to produce our output.
Now that we've seen that, it takes us about a second to produce the output.
What if we look for means to reduce this time?
So let's get back into our code.
You see, we have the provider specified, we have the model from here, and then we pre process the
image and then pass the model, pass this input into the model, and then we obtain the output, which
is this Now this model loading process here, we don't know exactly how much time it takes.
So what we'll do is we are going to include this time elapsed loading.
So we have time elapsed as the total time elapsed for loading and running.
Now, I want to also get the time elapsed for just loading the model like this.
So what we'll do is now we're going to include this in the output we have time elapsed loading and then
we have time elapsed loading.
Okay.
So we'll include this in the output.
Let's see if that even output of P, we have this already, so we have time elapsed and tab elapsed
loading.
Let's save this and then get back here.
We execute and let's check out the output.
Okay.
So you see here we have about 1.1 second total time, but the time for loading is 0.72.
So this tells us clearly that a huge portion of this time taken to produce the output is wasted on the
model loading.
See, this is about 66% of the time is for model loading, even though this is one, this is 0.66.
So let's see how to load this model once we launch our API.
So instead of loading the model each and every time we make an API call, what if we take this off from
here?
So instead of having this year, let's take this off, we are going to put this in our mean p y mean
that pie year, we will have the min, we have our model loading.
So import import on x runtime as our T, there we go.
Then year now we're going to load our model.
So we have our model now loaded year.
We'll save that and then get it back right year and then say, okay, every time I want to make use
of this, we're going to have this year we're going to import, import.
We impart service doesn't mean as se.
So we have that service with Manus and then you will have se dot model quantized.
So we taken this from our main pie from year.
So that is it.
We save this now.
And we had we still we took off let's take off this time elapsed loading.
We don't need this any longer because we we no longer load the model.
Well let's, let's cut this from here and compute the time it takes to reprocess this image here.
So time elapsed pre process took that off.
Then let's modify this here time elapsed pre process well let's pre process so we have now just taken
off pre process okay so let's get into the schemas we have output time elapsed pre process save that
then go ahead and run this right here.
So let's execute once more.
There we go.
We execute and we check out the output.
You can see here time elapsed now is 0.4 5 seconds, which is about half or more than half of the time
we were taken previously.
So all less than half of the time was taken previously actually.
So yeah we have the time elapsed for pre process is actually very small.
So all of this was on, most of this was for the model to compute the output.
So let's, let's rerun this again.
Let's execute that again.
See 0.4 9 seconds.
Now we've we understand how this works.
Let's stop this, run this again and then check out the time when we just start our server execute and
let's go ahead and check the time.
Okay?
So you see you have 0.41 second.
That's practically about 400.
Well, 450 milliseconds.
So that is the time it takes to produce the output.
Now, we went we left from one second to now 0.4 5 seconds.
One other great advantage of working with a fast API and building your APIs.
The fact that you could build asynchronous API is very easily and it's just by simply specifying your
this async sync keyword.
So here we have async save that test your async.
There we go.
And the main we have async and that should be it.
So that's all you need to do to make your code asynchronous.
And so this means that when working with fast API, if we have this task, for example, this one which
takes much time to be completed, what goes on is this other tasks can be run asynchronously.
And so while waiting for this text, for example, let's do it here.
While waiting for this task, we could already start working on this other task and then while waiting
for this other task to be completed, we could also start working on some other tasks.
This means that overall we have taken up this time to complete this three tasks, whereas for synchronous
code we have to wait for each and every tag to be completed before taking on the next one.
So you see the time difference between these two different methods.
We have your the difference.
We see this difference here.
So this is our gain in time when working with fast APIs, asynchronous manner of running code.
Nonetheless, it should be noted that there are some tasks which are compute bound that's actually CPU
bound, meaning that even if you have to run this code asynchronously, this first task will still take
up so much time.
So you would end up with something like this.
So there will be no real gain even though you had to run this other tasks asynchronously.
And this is very common in computer vision.
And since we're dealing with computer vision, more specifically object detection, we have to understand
that even though our code is running asynchronously, if at the level of this detect or P, we have
this call on the emotions detector and we're still waiting for that to be completed no matter that we've
already completed this to task right here, we'll still have to wait for this to be complete.
So for such CPU bound tasks like.
Computer vision machine learning deep learning will instead take advantage of parallelism with parallelism.
Instead of having one worker, one CPU worker to run all these different tasks, what we could do is
we could allocate, say, for example, let's say three workers.
So we have now three workers where each worker can focus on a given task and now we can now take advantage
of the fact that our code runs asynchronously and takes or makes use of parallelism.
Now, so far we've been using this you've can HTTP server, which is an SGI web server implementation
for Python.
SGI actually means asynchronous server gateway interface, which now serves as a minimal low level server
interface for and async framework like fast API.
Now, although Yunicorn is coming with speed, it isn't mature enough to be used in a production setting.
Hence we have to.
Or we tend to use Gunny Conn, which is a mature, fully featured server and process manager for our
production settings.
So that's why you've gone includes a unicorn worker class allowing you to run SD as GUI applications
with all of you've ACORN's performance benefits while also giving you nikon's fully featured process
management.
So we are now going to go ahead and PIP install Nikon YUNICORN.
Once we have Nikon installed, we'll go ahead and run this command which we saw already Yunicorn Service
main app and then we'll specify a number of workers.
Let's change number of workers to three, for example.
So let's say we want to have three workers and then I'll walk.
Your class is you've gone, so let's run this.
And as you can see, we have this happening all occurring tries started several process with a specific
ID, then we have started several process with another ID, another study server process with this other
ID indicating our three different workers.
Now we could go ahead here, refresh this page, try this out, choose file, then execute and see.
There we go.
So we have our output exactly as we expect.
So that's it.
Now, you could obviously reduce a number of workers.
If you reduce this to two, oops, reduce that to two, you would find that we have only this process
and this other process.
So that is it.
In the section we've just seen how to build our own API and test it out locally.
In the next section we are going to deploy this on the cloud.