Transcript for:
Building Web Apps with FastAPI

learn modern web development with python and fast API by building five projects Zach is an experienced software engineer and in this course he'll teach you how to build apps using an event driven architecture that manages different tasks all implemented using fast API welcome to this modern python course we will be building web applications that utilize fast API and some other modern libraries that will help you build full stack development projects my name is Zach and I am a software engineer based in London I wanted to design a course that will demonstrate some of the modern usage of Python's web development Frameworks and I believe that with this type of project building you can really practice relevant portfolio skills that can help you progress your career in this particular industry before we dive in let's talk about what you need to know to get the most out of this course course you should have a basic understanding of Python Programming as well as some familiarity with some front-end Technologies like HTML CSS and basic JavaScript additionally a fundamental knowledge of HTTP networking is a requirement here as we don't really go into the details of how these certain protocols work we will review some of the key Concepts as they needed throughout the course since I wanted for this project to be useful for developers trying to learn their first job as a python backend engineer I implemented some of the more advanced topics like example of using multi-threading for dealing with asynchronous tasks when doing API Integrations if I could summarize the importance of this entire course in one sentence I would say that in a way you are building some kind of a event driven architecture and managing different tasks with in the implementation of fast API framework I did my best to to implement without too much redundancy things like database Integrations so that the coders here can get some hands-on experience with various apis and databases first we'll build a real-time translation service using fast API and gp4 this project will show you how to harness the power of language models to create an application that can translate text in real time for our second project you will learn how to create a tool that not only generates content but it also analyzes the sentiment the third project we use fast API and open AI where you will learn how to interact with external apis and process data to create a functional and useful web application in the fourth project we'll switch Gaz a bit and create an image to text web app with P Tesseract and flask you'll see how to integrate OCR technology into a web app to extract text from images and finally we'll wrap up with the KV app for downloading videos this project will introduce you to KV for building multitouch applications and you'll learn how to integrate it with virus apis to download video content I feel like these five projects will definitely help you use Python for some Modern application so let's get started and bring these projects to life we will build a translation service application it will be a web based tool designed to translate text into multiple languages for our backend we'll use fast API we'll have a database in postgress and for the translation we'll communicate with open AI CH GPT 4 model this is what the end result will be the user can input a desired text for the translation here and also in any number of languages that they want their text translated to they can hit translate and this will execute a post request to our API service and fast API will then try to communicate with ch GPT to provide a translation whilst this is happening we want to inform the user that we have received their request so it will return a 200 whilst is asynchronously processing the translation and waiting for that to come back so once the results have landed back onto our fast API app we want to display them dynamically without the user having to click anything so we will be building this event driven architecture and this is in my opinion the most important aspect of the video we also added a search functionality here which will allow the user to query the database and check the status of any particular translation order also by querying the ID they'll be able to check the content so they can historically browse through any of the previous translations so this is what the project structure will look like and it's pretty straightforward so this is our web app so it's our fast API fast API izing conventional file structure this will be our front end and almic will handle all the database migrations this will be our configuration files and because we in the end we will also create a Docker image for easy deployment so we are moving to our vs code now and we will start coding the project so you want to create your main folder and inside you want to create another sub folder we'll call it app inside of that folder you want to create your main py and this will be our fast API client now we will make sure that we have our virtual environment running let me zoom in a bit here you want to make sure that you're in your main folder and we will create a new environment once this is completed you want to activate this environment so we can install our dependencies so I'm going to use Powershell for that so you want to navigate into your requirement scripts and I believe here should be your activate. PS1 and once you see this prefix it means you have activated your virtual environment so now we can install our dependencies that we'll be using for this project so for that we'll create a requirements text file and I'm just going to copy everything that I know we need here keep in mind very important we have to use a specific version of open AI for this to to work so it has to be open AI 028.0 we also need a limic and now we can install all of the dependencies so you want to navigate back to your main working directory and you can type in P install our requirements.txt once this is completed I came back too quick oh it wasn't saved so you want to type in PIP install all requirements and once this is completed we can start writing the code so it might take a minute we can start writing something in our main py file from Fast API import fast API this is something we will use later on but you might as well do it now background tasks HTTP exception request and Depends we'll also import HTML responses we will import cost middle bear and to be able to render an HTML page we will import Ginger to templates with that being said we'll say that fast API is in our app variable and we can create a templates folder inside of this app folder so you want to make sure that you're in the right place go see the app make sure that you're type in PWD which stands for print workking directory you want to see that you're in app and then type in make directory templates inside of the templates we'll create our index.html file and for now we can just put in an exclamation mark to generate an automatic HTML file and we'll just say hello so we can test that our app is running and rendering a page so we want to Define our first endpoint to do that we'll start the with The Decorator and we will call our first path index and the response class will be HTML response called the function index and you can take in a request which is going for the request fast API library and it will return the rended version of the index HTML file so we'll say return templates template response so template response and we want to name our file that we want rendered and we'll give it the request to be the request that was passed on to our main function here so you can see that it's showing me the S template template is not defined so we need to make sure our fast API app knows where to find this file so we will have to set this up set up for new templates so we will say that our templates is and then we will give it the directory file path and that will be templates so this now is looking for the template folder which we have just created so typ of there we need a colum so if we run this now we should be able to see our index.html file on a local host so if you go to your terminal and you make sure that you're in your app folder and you type in uvicorn main colon app reload it didn't save restarting and we can see that it's running if we go to the browser and we type in Local Host give it Port 8,000 and index we can see this is what our index.html file has so if I was to save this put all these exclamation marks refresh this you can see that it gets updated so this means our fast API web server is running so we will go back to our index.html file and start writing some front end code to create the basic structure of this web app so this is our translation service that will be the title we can delete this and I'm going to add a bootstrap Link in the head segment so you want to do the same just have this copy pasted other than looking at the video and having to type all of this in the link just go to my GitHub the link will be in description and on index HTML file you can just find this link this particular link and copy paste it and you should do the same for the style as well so we're not going to do to explain the basics of CSS in this video this video is more about API integration especially with the new services like the J gpts AP and uh and it's pretty self-explanatory if you just read through it you will immediately know what everything does here so we're just defining some of these aesthetic properties for our HTML elements that we will build right now so we will create some kind of a nav bar at the top these will be the properties and we can add some kind of a text we say with the class bar and the top of of it will be translation service this can be anything you want really so next we'll open a new container and inside of this div will open a form so this is where the important part in regards to the front end comes starting our form that we will submit to our fast API for translation so we'll give label here to be for text to translate so this later on we will write our JavaScript functions within this one index.html file file that will do all the front end processing towards the back end the fast API so that's in my opinion another positive aspect of this project that you will actually write some backend with python and still touch upon the front end aspects written in Java Script as well there's no need for D and we type in that this is the text to translate when this and will close the label this will be the text area and we will give it a class form control I will give it the ID that to translate you can have four rows and we'll give it this placeholder and close the so just make sure you close this text area tag after giving it the placeholder to be end the text here close the tag we move on we want to close this div or not the form yet just a div we can copy paste this and just slightly modify it to now include the input for the languages that the user wants the translation for so it's again form group oh I forgot to put that on the top top as well just a second we don't want to move on without including that so you want to go back Above This translation form and in here we will give the form ID that's a double one so just this line was missing we are opening a form group here so we're doing that again now to include the languages input and after you finish with the placeholder you can close the tag and close the div and underneath of this there will be a submit button so it's just a button type button but the important aspect now is to just identify this point that the on click for this button will be a JavaScript function that we will write pretty soon so that'll be at the bottom of our file here and this is our form so we can close the form here just make that consistent there so now we want to write the HTML element for displaying the translation results so we'll create some space here for readability so this particular div will be the HTML element that displays the result make sure that you have the ID in this particular syntax here so pre ID translation results this will be important for the event architecture make sure that div is closed and we're starting a new div so this will be the progress container so as we said earlier we want to make sure that the process of translation and display for the user is being transparent towards the user so in case they have a very long file that they want to translate they'll have to wait for it we want to make sure that the user is aware that that request has been accepted it's in progress so this particular div will be a display function for that and it will include some kind of a visual representation of the progress bar and now we want to include our search functionality but before that let's see how this or HTML file looks so if we go back to our browser and refresh this it looks a bit messy at the moment this will all fall into place as we build rest of the HTML elements but we can see that this is a part of the N Navar bar at the moment we didn't close the main div that we open so everything is being chucked into the single at the moment that will that'll be sorted in a minute but we can see that everything else is in place so we'll just continue with our work so now we want the search functionality so we will open a new div here and add the text of check translation by ID so we want to be able to query the database and then return the state so keep in mind in my opinion the only important thing to really take away from this is that inside of this particular input or the form will be interacting with our JavaScript so the onclick functions for our buttons are very important and this is why we write here on click equals and then these two particular functions that we'll write at the bottom of the page right now so make sure that div is closed and we'll open a new div and this will be the translation status so we want to display the actual text from the database that the translation is still in progress or if it's completed and then finally we want to display if user clicks this button so the second button which will call the function that queries the database for the content of the translation this will be the div that will display it so when it comes to our HTML elements that's it we just now need to write the functions the JavaScript functions and we have pretty much completed our front end so we will open a script tag here and this is where our JavaScript will go before that make sure you get the links for the bootstrap that we're using for this front end so once again it's important that you don't just try to type what you're about to see by looking this video rather go to my GitHub the first link you'll see in the description and locate this file you will see then at this particular line that will be this we can align that back so make sure that you copy paste this from the actual file right other than trying to write it but by all means if you feel like it you can just retype it from the video so now we want to start writing our JavaScript before we type some JavaScript let's see how does the updated front end look now so if we go back to our browser and we refresh this still looks like a mess so we want to go back and make sure we find where I made a mistake and fix it so going back to our code this was our CSS move on so as I said we haven't closed one of the elements so everything got bundled I briefly talked about it but forgot to type the text so we'll close the nav bar here and go back to our browser and see yep there we go so this is our front end finished now and as you can see inputs for the users are here the translate button is here and everything then will be displayed underneath the translate button so now we can write the logic in JavaScript that will take this data so if I want to translate this is what I want to translate and in here I type in engl so it's already in English German and French if I click the button I want the translation to appear here once it's done but keep in mind in case the text is long and we will test that version as well where we are trying to translate a huge amount of text and it will take time I don't want to just have nothing happening what I'm waiting we don't want the user having to click anything or refresh the page manually themselves so just to make sure if if you do search for axio JavaScript you'll be able to get more information about this and what it does but as you can see it's a promise based HTTP client so by using it we'll be able to do requests so we didn't have to install it in npm because we are we put this link in our script so we are able to use it through that through the link of the script so we'll go back to our codes and we'll finish off the front end officially with the JavaScript functions that we need so we will do a async function we'll call it submit translation and we'll give it text variable that will extract the user's text by using get element by ID and we will give it the ID text to translate. Value so this will grab this text so from this HTML element and it will store it in our text variable so we can copy paste this and we'll do the same to have our languages stored uh as an array in this variable called languages so the different ID will be languages like so and we want to format this to be an array of strings so in here you want to do do split and a map that will trim it so just have a look at this text and rewrite it yourself because this is just a simple logic to do some formatting to have a comma separated array of strings for our languages choice of the user I want to write some logic that will prevent the user from submitting an empty input we don't want to query the database or just to create this unnecessary Network traffic to chat GPT if the user is submitting an empty text empty array basically so we'll say if not text languages length be zero and languages to have to be empty and then we'll write just to return an alert in the browser that will say please provide both text and target language and we can just return so I want to implement the progress bar if the user has to wait for a significant amount of time it's just nice to have this more interactive experience in terms of the interface the user is working with so we will create this progress bar and keep in mind this is not just about the visual about implementing something new and nice to see visually we also need to write our own logic that will synchronize the progress bar with the actual backend process so this is where axios comes in so handy and we'll make sure that these events happen happen in the same time in real time for the user we'll create some space here and we'll will Define our progress bar and we will say that this is document can get it by ID the ID will be progress bar and we'll do the text on the progress bar be the same but here with the ID change it to progress text and we want to make sure that the progress bar can get restarted if the user gives a new request so we'll say progress bar plus list and remove if it was successful like so and we want to add this primary and this will be style would give it the style width style. width to be for the style of 0% and then we'll also have progress. text that we want displayed and it will be text cont content soorry this doesn't have a DOT so delete that so progress progress text content and this will say that the translation is in progress so now we'll write the xos function that will execute the post request with the payload so we will say try this will be con response and it will await post and here will be the link of our endpoint which we will we still haven't built that so this will be what we'll do on our fast API file so we will call this Endo uh translate so after giving the endpoint open the C braces so we can give it the payload and we will say that the text is the variable text and the languages are the variable languages so oh this is not capital I don't know why I did that and we will close this so I made a typo here you need to go back to where I provided the endpoint link and delete these parentheses here so that we can close them here hope you can see my cursor make sure you close them here all right moving on now we'll Define the task ID to be to go into the response object and get the parameter of task ID and we'll give it the alert that will say that the task ID is and give it dollar sizing it's the task ID so the reason why we have this here keep in mind we said it'll be important for the user to receive a confirmation that the request that they've sent we have received it and we are processing it this is to cover the case where the input is large and it will take time to translate all of this and return it back to the user so we want to instantiate some objects here so we'll change the display so this will be the part that dynamically changes the display so initially in this process at this stage we want to set all of this to none so feel free to either pause and rewrite this from the video or go to my GitHub and copy paste this particular bit and then from here we'll say that translation result is null and the progress is zero and we will say whil progress is zero is less than 100 sorry and we'll write some logic saying await a new promise which will resolve through the timeout and we'll set time out at a th000 so by the way these are millisecond so this is 1 second so 1,000 milliseconds so with this polling technology we want to make sure that this is constantly awaiting the the response from the back end and it will check for that every second and then we will say that constant result response will be the get request and again we'll give it the Local Host the end point of translate and use this syntax to make sure that it gets the exact ID of the entry oh May the typo here so this needs access so we want to declare that our translation result then is the result response of data and writing translation result status then being changed to completed this will also mean that our progress has reached 100 AKA 100% or else we'll give this the interval of 50% so our Progress power will do increments or either zero meaning nothing has started yet if something is in progress it'll be at 50% and then the third state will be a complete state which is 100% so we say that the width of the progress bar in this case would be 50% so now I just wanted to add some extra visual components to it so we want to change the color to green and text according to the events that happen so we'll Target progress bar and once it's successful we can dynamically update the text by saying translation complete oh you want to write another document get element by ID this one will Target translation results and we want to stringify the the the data there and we will do another document get element by ID this one will Target the results and we want to make sure that this display now is set at block and we can close the curly braces and write hatch error statement and we can display this in our console so this is just for debugging in case something goes wrong error submitting translation and we want to see that error so we can display it there and we'll also give an alert in the actual browser and we'll say an error but while translating let's try again C braces are closed and now we'll we'll use another two functions so we want to add search functionality component and with this we can do this later so we don't want to forget that but we will have two functions so I'm just going to open the structure for it and we'll return to this so this will be our check translation Styles and for now we'll give it is there a pass just something that won't cause an error and there will be another one that checks for Content so it'll be check translation content so we will return to this data so I believe that should be it so all of our front end is completed other than the last two functions where we want to add the search functionality and we can deal with that practically at the end so once we actually have everything up and running we'll add this ability to go through our database and historically retrieve any of the completed or not completed translations so with that being said we'll move on to our back end so this is where we left off we defined the endpoint that through a get request renders an index.html page so the first thing that we will do is set up our database so you want to create these files now you want to do database. py you want to do models py create crud py and create schemas py now a good point to discuss how does this process actually work with the front end communicating with backend and what are the roles of these individual files here so if we go back to to do some drawing we'll go down here so I'm going to create some some boxes here and we're going to say this is our front end this will be our our database and this will be our fast API service so this is our back end so as you saw there is a particular input that the user will give us in the front end so this is the input just for the sake of this wonderful diagram I'm going to call I'm going to refer to this as a payload so instead of I is going to be P which stands for payload we already know that this payload will be text and language so text that they wish to be translated into these languages so this will be our payload we'll send this as a Json we have this HTML that allows the user to input this text to create this payload and then with the axio code that we written to execute a post request this post request will go to our fast API endpoint so more specifically that's the translate endpoint then we want our fast API service to First make sure that it knows what to do with this data and that it also can receive this data so this is why we created this schemas py so what we're going to do in the schemas py is to make sure that the data is validated so that it lands on our fast API service in a format that we can work with it as you saw we want to implement this search functionality by using idid so we will then write some logic that will take the payload from this point and store it into our database so I'm just going to mark that this payload has initially been given to the front end with a post request this payload now has reached the back end and then the back end gives it to a database so it can receive a unique ID so now this payload here will have some kind of an ID so let's just give it a random numeric value let's say this is now number four P4 so payload with an ID 4 we will have some further logic that will send the payload to chat GPT so this will be our external API here so we will say open API for translation so our fast API service will will need some logic that does that once that is returned we will have our fast API stored in a database so this flow now has another line we can say that once it reaches that place it needs to go into the database so initially this part was just storing the payload and giving it so it was ID and payload which was text and languages but on the second entry as you can see this blue line this becomes the translated payload and it will just be the text and then once this event has been confirmed there has to be some logic that will inform the front end of data that you originally sent to me as a payload well I've done what you asked of me and it's ready for you to use and then in that case the back end will deliver the payload payload with the ID and with the translation of the text so I'm just going to put TT translated text so then all of this can be displayed on our front end so this ugly looking diagram is an explanation of this event architecture so first things first something that I like to get out of the way and it's pretty much the standard for me in the development process keep in mind for deployment this requires a little bit more talk based on specific circumstances of how you want to deploy your project but for now for this project we want to make sure that once we do run it locally if we want to thinker around with certain things I don't want errors to come up so I'm going to make course not a problem immediately by adding this middleware so we imported that in the beginning of the tutorial and we're going to use it like this not the most important aspect of this video so we will move on so remember I want to have my endpoints for handling data so we'll say app. post and this is our main translate end point and we'll give it a response class oh sorry response model and we will have a schema for this so this will be the moment where we write our validations with pantic so stop this for a second and open your schemas piy file and in here you want to import pantic space model and you want to get from typing list and dictionary and we will have three classes one will be translation request test and it will inherit from base model and this will be the string of the text that the user has given us for translation and then the list of languages this will be a list of strings next is the task response this will also inherit from no base base model not base exception and this will be the ID that we are returning to the front end as soon as the request has been made lastly we have translation Styles and this will also get base model I'll have task ID integer status string and translations should be dictionary of strings so these are our schemas and the purpose of them will be to valid the data to make sure that the data before getting processed before we assign it all sorts of work to do is in the format of how we want it to be so you can close your schemas pii that's all we're going to do with that I'm we think before we deal with the rest of the schema implementation you also want to create a file here called init oh in case then you want to have a different way of importing for example instead of saying here import schemas we'll be able to import from schemas and then give it the exact names of the requests so in order for that to work you would need this init file but even if you leave it just with import schemas all of the schemas would work that's up to you now for your preference so we want to make sure that the incoming data which is a part of our request variable here so that's our p Lo is validated by by our translation request schema and then what we returning is Task response schemas so if I open a second tab here just for you to have a quick look the incoming payload is going according to the request so the input from the user which is text and the languages they want translation in and the task response will just be the ID so all that will send back to the user is the ID keep keep in mind this goes along with what we decided to do that once the user has clicked translate this for me what they will receive immediately is a 20000 or this is your process it has an ID and once it's actually processed and the bar reaches 100% you will get a translation so that's the reason why we have this schema order so after we have defined the schemas we can move this we want to start modifying how the database will be set up and how this CR system operations will be done so the pseudo code for it would look like something like defining that within our task we will have a crud file that will hold all of our operations all of our methods for doing create read update delete operations and we will call this function we can call it create translation task so we don't have this yet but we will create it in a second and this function will have certain parameters so we can have two parameters three parameters because it will also have the languages XY z p then we will add it to the background tasks and this is something that I believe is fundamentally important to understand in order to proceed so we will go to the browser and read something about the documentation so I just want to make sure that you know where to look for to understand this particular technology so if you go on Google and type in fast API documentation and in the search bar you want to look for background tasks so this is where you'll be able to find all the documentation related to this particular concept can use it to schedule the execution of background tasks after the response is sent and you can pretty much see where where I'm going with this so I want to be able to have my web app process these asynchronous tasks so by all means if you need any further familiarization open this particular document and you can find all the details you need there in the meantime now we'll go back to our code so we want to now add once we are creating the translation so this is our create translation function which we still have not created will create it now we are going to add to the background tasks task we'll do perform translation askask ID and the request variables so request text and request languages and we'll pass the B again and we will return as we said the return schema as we said for what we decided to return to the user would just be the ID so now to create we don't need this so so now to create these methods so we want to go in our Crow file and create this method for creating translation task and then we're going to deal with our perform translation method for our background tasks so we can copy this and we'll go into our crowd file and from here you want to import Q Alchemy M at the session and we will import models because this is how we will fill out our tables but we'll build the database after this first let's define this method so you can copy paste the name and this will be this will have a connection to our database and it will take as we said it it three parameters database and then the payloads components so this will be languages which is a list and we want to say the task is a models translation task and languages are languages so after that we want to go into our DB session and use it to this to the base every time you do that you need to do commit and refresh so this is how SQL Alchemy this particular RM handles this this will be always a part of any CR operation but I'm going to pass the task here and say return task then the second method we want is the method that will fetch the translation task it will also able to go into the database and work with the ID that's an integer and it will just return the qu according to the ID that we pass it so it will go translation task and you want to pass this so models translation task ID so find the models that has the ID same as the ID that we passed in this parameter and return the first TCH and then the last thing we want in our croud operations methods will be to update the translation task so once again this part will be the same so I can copy paste this from above but this now Returns the translations as well so if you remember when we actually had our diagram I'm going to pull it up so you can see exactly where and this method where they appear on our diagram so take it in mental memory for now this is Method number one and this is Method number two so if you remember our not so good-looking diagram here we were talking about the backend processing this particular payload so the method number one is the payload that has the text and the languages as a parameter so they will still share the same ID the red text here and the blue text here representing two different aspects that work within the same table so this is all one table but on two different instances we are doing a either create or update request to it so in the red one which corresponds to our when I said red I'm referring to this line here it corresponds with our first method here create translation task and this line and so this particular secets of event here is just updating the translation so adding the translation so that's the update and it needs the ID parameter to know where to add that translation to because it's returning after so these are two separate events that are operating in the same table so as you can see we need to pass task ID so that it knows how to find the table where it will check in is the translation of this text here from the first function and in the Lang ages of the first function so I hope that's clear and that's quite important to understand for this particular type of system so we'll say that the task it can go and find according to the ID so it will filter models and it will be the same way of quering like the one above and then we want to say to translations and the status now changes to complet it and again after every CR operation you want to do commit and refresh and return task that's that's it for our crowd operations we won't have to open this anymore I believe now we want to create our database so we're going to talk about how to set up this database and create our table so first you want to go into your database. py then here you want to import OS you want to import create engine from SQL Alchemy session maker and in order to keep our varibles safe the ones that contain sensitive data that's important here you want to import EnV load. EnV so we will load this. EnV and what this means so what that means you want to go in the main directory so if you go print working directory inside here so you want to make sure you are in your main working directory so outside of the main app folder and we will do touch. EnV and in this file we will have our database URL and we will have our open AI key so for now you can leave this empty but this will this will be the file that we hold your sensitive information and then we're going to load this file with our dependency here EnV so that will allow us to say OS using the input OS Library get EnV and then particular variable called database URL which is which you can see corresponds with this here so this is the way you keep it safe then below that you want to say that the engine is create engine and we will pass the parameter of the previously defined connection string sensitive information that we stored in ourv file so it travel all the way through this in such Manner and lastly we want to add the session maker I'm not sure does this have to be here but for now let it remain I doubt that it can hurt so that's all we need for our database. py we'll move on to our models.py where we will be defining our table so you want to import these from SQL Alchemy so column integer string text and Json those will help us create different types of data types in our database and then after that you want to get Clarity base from this particular dependency also SQL Alchemy so here we will call Base Clarity base and now we will create our table so we'll say that the translation task creates a table called translation tasks and now we will actually Define all the the rows so we'll say that the ID is a column which will be an integer and a primary key true and we'll have text which is type text nullable false so it can't be empty and we'll do that for languages but languages will are a list so that will be adjacent here and there will be status which is a column string and the default is in progress so if you remember we only had to in our CR file we only had to have an alternative of can be change to completed now because here we can set the default to be in progress and then we are adding the translations finally that's a Json and the default is just an empty Json and that's our models py I don't think we will need to go back to this but I'll still leave this open because I might have to talk about it a bit later so now we can go to our main.py and write a cleaner version of this so you want to go to the top and import the CR file and now this function actually exists we just created it so we can pass the genuine parameters so this will be the database this will be the the text parameter of the request and this will be the languages parameter of the request so the only thing missing Within These parameters is our DB so you will go here above the course and we will Define this function actually we can Define this in our database file so we can say ITB I'm sure you can copy paste this just from the fast API documentation but I have it here in front of me as well and we can say try yield this DB so this now turns into a generator TB close and then we will import this so if we go back to main py we can say from database import now we should be able to use this if we say DB so now moving on to our background tasks so for this we'll have to write some utility functions so these are the functions that we want to give to our background tasks process to handle asynchronously oh we want to make sure that this is called the same is get DB so we want to create a new file here we'll call it utils.py and what we're going to do now is create this function that will perform the translation but before that there is one thing that I forgot we want to make sure that a database is created so if you go here above app you want to paste this part so you want to say models. base metadata create all and then bind the engine and we will import models and also from database we want to import the engine so now once we start the main file each time my fast API loads up the server it will make sure that a certain B database exists and that a table that's defined in our models exists if it doesn't it's going to create it so next thing we'll do is create our database in PG admin 4 I'm not going to insult your intelligence by showing you how to download PG and admin 4 from internet just Google it download it configure it you will get a username and a password once you configure it and then you will see in your server cluster you can create a database by clicking right click on databases create database and give it a name so I'm going to give it the name translation service you'll just click save and that's it you have your database if you go under schemas and tables if you click refresh here you'll see that there are no tables which is good we will create that from Python and this is the beauty of using an orm which is SQL Alchemy in this case so so what we have to do is Define it here and uh this particular table name with this name will be created once we load our server so in order now to connect your database to this particular project you want to go in your EnV and your username and password will go here this is the address and this is the name of the database so once again here you're defining what SQL here you are giving the username this is the password this is the address and obviously we're working locally so this is Local Host if you're deploying this project these are be these will be credentials of your actual provider and then the translation service is the database so this is the database name over there so this is pretty self-explanatory I have no doubts that you can configure this successfully once you have done that you will go back to your vs code we can delete this and now we are ready to launch our server and this should automatically create our table as well so if you go in the main folder and run this line one think before I move on we need to also make sure that we installed this so I've added I've added it in our requirements.txt but if you need to individually install it do pip install this particular Library the last one here so after You' done that you go your terminal working directory and you run your recall main app reload so everything is running and now if you go back to your PG admin 4 and refresh the tables you will see that the translation tasks table has appeared so now we know that our database is connected our server is running and we can finish the back end by writing the utility functions so just to remind you of where we are if you go into your main.py you'll remember that when we were writing our endpoint we Define this background tasks process and the task that we added was supposed to be a function called perform translation so now we're going to actually write that function that method in our utility. py so here you want to import open AI from SQL Alchemy RM you want to import session to be able to connect to the database from our croud file you want to import the updat ration task and from our environment you want to import load function and also OS here we will pass the API key for open AI we'll use OS to fetch the environment and we will say that this variable is called open AI API key to make sure this is connected you have to go in your EnV file and you have to put in a API key in a variable called open API key like such I'm going to do that off screen so you just copy paste your open API key here or any other llm you want to use but I'll be using open API so once you do that you click save and we move on so when you finish setting up your environment for sensitive data we can write our function so we'll say that perform translation exp parameter of task ID so the integer and the text is string and languages will be a list and we also want to get DB session we will say that translations are an empty dictionary and write a for Loops saying for each element in the languages list by giving in the response open AI chat completion and create model will be gp4 and the messages will be a list an F string that says this or a helpful assistant that translates text into and then the language of each language that'll work and underneath that we'll do roll user content and then the text we give a coma here and we'll say that the max tokens are a th000 but you can adjust this based on your own needs so then we will get the translated text and we will give it in the respond so that's a zero and here we'll write some formatting because we're dealing with a list and we'll give our translations then of each language to be translated text and we're going to we want to do some debugging as well oh in the meantime I forgot you want to go above and load the environment variable and here I made a typo so this is Max tokens like such and now we will write this exception so our exception will print that if there was an error we will get the error back so we can see and we can play around with this if we end up actually having some errors but for now just leave it as such and now we want to call this function the update translation task so if you click on the update translation task and click F12 it will take you back to your Crow file so you can remind yourself of what this actually does so we have already written this function we are just invoking it here now to perform that task so we will say update translation task it will have a parameter of DB to connect to the database and then update the database by finding the particular ID and inserting the translations into the table so we save this and we just now need to finish our end points and that'll be the end of our back end so I'm just going to clean this up a little bit we'll take the core stuff and just put it above our end points so I forgot to pass the background tasks as a parameter so in our translate function here we want to add the background tasks so I've inserted here between the schemas and the DB session so add the to be background tasks with the capital B and then we want to add the connection to the database so we will say that variable DB is session depends get DB and then we don't need this get DB variable so in this line 43 delete get DB and do the same for this line 42 in task first thing after parenthesis delete this as well and now we need to import session so if you go on top and we do from SQL Alchemy import session and that's sqlalchemy.orm import session so we will now write the utility functions for our search functionality and this will be fairly similar so it will be a get request so I copied the previous endpoint I'm just going to modify it so this one will go this get request will have a task I the parameter and the schema is not going to be task response delete that and put translation status delete all of these parameters other than DB and here we will pass in task ID to be an integer and then just have the connection with the database here in the task we'll go into our Crow file and we will get I feel like there's a typo here but we can still get the exact text so get the Translating task DB task ID this line of code we can delete and underneath the task we'll say if nothing returns in task or or better said if task returns empty so if task is null we want to raise an exception so we'll put in HTTP exception and we'll give it the status code of 404 with the detail of task not found but if task is not null then we want to return task ID and the status which is the task. status so it will access that parameter and return entry from the database and the translation will be the variable translation so again we'll access the task translations and then we want to do practically the same thing but for Content so this particular endpoint will correspond to let me show you exactly what so it will correspond exactly to check status button and then now we're going to write a function that will be an endpoint that gets executed once we click check content so we can copy this and we'll slightly modify we can change the endpoint address so we'll say that this is Content slask ID and I forgot one thing we want to change the name so it go back to the previous function for me that's line 60 and here we will just say get translate because they have to be called differently the first one is called translate the second one then should be called get translate and the third one can be called get translate content something like that as long as they have unique names it's fine and this will remain all the same the task line will also remain the same and this will remain same as well but when we return we do not need to return the ID we just want to return the task Al together and that should be it so I believe this is all we need for our back end to work but now we can go and try running this so if we save and give it the first test so we put some text here we will say hello there how are you and we will say that we want to translate this to to French German and Italian and we will click translate and we get error please provide both text and target language so this means there is some kind of a problem with the logic that's supposed to confirm that there actually is content here so to troubleshoot this I'm going to start from the beginning I need to check what's wrong with this button is this button actually picking up extracting the data from here so let's try opening the developer resources we'll go into console in the console I want to be able to see so if I do a console log of something I want to be able to see a particular result let me see can I zoom in on this make it a bit larger that should work for now at least hello pasting that's too much of text so we want to we'll say that constant text and we want to get element by D this particular text so now if I do console log text and I can see that it does extract the text from here so that's not an issue and if I do constant languages and the ID for this are languages and I do value and we put in languages here I get this so that's not an issue next I want to make sure that this button actually does what it's supposed to so what I'm going to try to do is go to my HTML file and find the code for the button so if we go into our app and we'll open templates HTML and we want to find a line that is the button for submit so in our line 46 on click is submit translation if I do an F12 on this it takes me to my function this is the code that we tested so we know that code worked so the console loging that we just did in the console and I think I can see a typo here so after this we need these two so I believe I just om missed these particular bit of characters so I've saved that we are rerunning our server and let's try it again and then I realized I made a silly typo with response. openai it should be response equals I'll go to network and I want to see what happens when I try to make this request and I can see nothing happens so the get requests here are fine but if I do hello to German and I want to do this nothing happens so my first idea how to troubleshoot this I just want to make sure that all of the back end now works properly so so I'm going to use Postman to just quickly test the back end so if you go into Postman and you provide the endpoint address so that's our 8,000 ports SL translate and we give it this particular payload and we click Send we get 422 unprocessable entity so there is an error with our back end so we just catching some errors I realized that I forgot to pass the variable for the API key so if you go into your U tools. py underneath this we want to make sure that that we have given the API key properly so make sure this particular line the line number 10 is present also I made an error here so indentation error this function should be outside of this particular except so it is outside of this for Loop so make sure you align it with the for Loop all right we'll continue troubleshooting we'll make sure that languages is written properly so I misspelled it here it's written atrociously so make sure you fix that too if you go back to the models.py and instead of the forw written languages here make sure that this is written correctly so now in order to update this unfortunately uh this orm SQL Alchemy cannot do migrations dynamically like this so we will have to go to our postest database in PG admin 4 and manually delete the tables and restart everything so we will go to translation tasks delete click okay now when we go back to to our server and click save it should create a new one so if we refresh we see translation tasks and I want to open it to make sure that in my columns the languages is written correctly now and as you can see it is so to double check triple check actually from schemas to the main py we want to make sure that every time we have languages it's written correctly there are no typos or nothing like that and after that I need to check how did I write the names of the methods in case I'm misspelled when re-referencing them in other places so I'm going to open main.py and utils and crud next to each other and then we'll make sure that all of them are named the way they should be so in our utils this is perform translation that's fine but then in our main.py we want to make sure that in our first function that we are calling create translation task and if we click on it and press F12 it will lead us to a crow operation so that's fine in our Second Use method this is supposed to lead to the second quad operation and that's fine as well so you want to make sure that these are aligned and the third one should lead to again the second Crow operation as well so if that's all correct let's try running the server and see are there any further vxs that we need to fix so we are running the fast API server again so it looks like it is online let's check what happens when we try to send a request so I've tried sending this and we got an error which says that there was an error translating to French and German so this means that we did get payload delivered to our fast API web service but the followup with our background tasks did not manage to get a return from our translation service so now now we know where to go and troubleshoot how silly of me I forgot that we left two functions untouched and we need to finish that my plan was to do it at the end but I did end up forgetting to do them all together so let's go back to our front end and make sure that we have those functions written so if we open our index.html so in our first function that will check for the translation status so that will be our first button in our search functionality we want to add constant ID which will be document get element by ID and this will be the ID of search ID and we want to get the value of that stored inable ID so we'll do try we'll have constant response which will be our axios function that will execute a get to our Local Host let me just copy paste this particular link so you want to do the same brackets so this is your link this is our endpoint on our fast API after this we going to say that our translation result is uh data from response so whatever is received from this endpoint will be stored in response and we are access accessing that data after that we'll be using El ID for translation results so we want to get the text content of that are we going to stringify that then we want to also get element by ID of with ID results and the style display for that will be block after we want to display translation status and we'll do that again by using get element by ID and we'll Target the status result and with this the text content will change to status give it a dollar sign translation result status and we'll close this and again we want to change this one to block else we want to catch an error so we know that if we need to do debugging we can actually see what's going on what's going wrong so we'll do console error fetching translation status and we'll print the error so log the error and we can give an alert and says there was an error while fetching the translation status and try again so that's our first function and then we want to have the function for the second button so this will be the on click for the second button on our page when we actually want to display the entire content of a particular historic entry in our database so a translation we did before and again just like in the above function you can copy paste the host ID which will be get element by ID search ID so exact same line like in the F function above and we're going to use the same structure of saying uh try and defining the response to execute a get request but with the previous one endpoint was SL translate ID this one is Content ID so it corresponds exactly to this endpoint so the first function calls a get request to this endpoint this one will be called by our second function that we are writing right now so again we want to stringify this and with the second element we want to change the style to blocks I'm going to copy paste the code for that and if you need to you can pause and rewrite the code yourself or play around a bit to understand how we are accessing these elements with get element by ID typing in the actual ID of the HTML element dot text content and stringifying the Json just realized I don't need the return for this so if you go above to the first function you can delete the return same for the second function and we will just finish off writing the statement for our try and we can just add catch error just as we did uh in the previous function so you can copy paste this entire bit and if we save this we can check do we have any bugs after this so if you need to feel free to pause look at the code for these two functions this is the final version of them and this is all the are index HTML file needs in terms of JavaScript so feel free to pause and make sure your code is updated with all of this so another silly typo in our models. P you want to add the S so it's not translation its translations we'll save that and try running everything again and now we have the issue that comes with uh SQL Alchemy just working with an RM like SQL Alchemy so we not able to modify these tables dynamically we have to delete everything effectively and then restart recreate a new table again and then it will be updated to this new name for the column so if you open your PG Adin and you go into your tables translation task and if you delete this table and now if you rerun the whole thing you can go back into your tables and refresh this and there will be a brand new translation tasks table so if you query for the last all rows you can see that the table is empty so a brand new table has been created we'll go to crow. py and make sure that all of our methods here are named grammatically correct so you want to change the middle one I believe it had the missing which one was it so it was get translating so we can change all of that and just put get translation task for the middle one so feel free to pause and compare this CR py file to the current one you have make sure it's written exactly like you see here and we can move on so we need to go to our main py and make sure that just how we have everything written in cr. py the functions are written the exact same way in our main py so we can open them one next to another so if we open CR on the right hand side and we have main py on the left hand side so let's see now in our post request we are using Create translation task and that's correct here in our get endpoint for our task ID we are using get translating task so this is the one that we just changed so we will copy this name and here we will change into get translation task and the same thing goes for our third method here we want to put get translation task we'll save that I believe we also need to go to our inputs and make sure that from database we import session local next to engine we also want to import list from typing and we will import uu ID so just to make sure we don't get any errors in regards to that we'll move on now and in our F method we deleted so there's no need for this response model that's not going to give translation status so you want to do s so after we deleted that we also want to make sure that we return the task not as an object but as a variable here and that was the last of our errors I believe there was a good five to 10 errors that we had to fix at the end some of them just being typos some of them being logical errors and we will go and test our app now so we want to go to our browser we will access our endpoint for rendering the main page and we will put some text here hello how are you today and let's say we want this in French German and Italian and if we click translate we are given an ID so it's an id6 we can see the translation is in progress we got the results so we see now progress bar in action transation is complete so now we want to maybe check let's first check did this land in our database so if we go into our PG admin and we refresh this by going into show me all rows you can see here at the bottom that we do have the the recent request the languages the status being complete and we have the translations here so what was the IDE for that it was number six so if we put enter translation ID 6 and check status we see that status is complete if we do check content we that we get the entire content of the translation request let's try doing something much bigger so I'm going to just try going to a random Wikipedia page or something like that so let's say I type in I don't know raldi and we'll try to take let's try to take a big chunk of ral's Page from Wikipedia and if we put weol this Wikipedia and request the translation into to French German Italian and Portuguese so this should take considerably longer so now we want to see this asynchronous nature of our web app in action so this is Task id7 so we got our confirmation that the progress has been received and as we as we wanted now we can see that asynchronously the background tasks from Fast API is running the second process of translating the task and we already have our 200 so even if we go back in our vs code we can see that we have our translate every one second going as a okay which is what we wanted so we are still waiting for this we are waiting for the open AI API to return the translation for us so let's see how long it takes so it's been two or 3 minutes and as you can see see we still didn't get our request back and if I go back to my vs code you can see that the polling that we defined to be 1,000 milliseconds it's doing its job every 1 second it's constantly refreshing and wanting to get that payload back so that it can display it to the user like we said we don't want the user to have to do anything on the page the page should dynamically update so the translation finally came back it took a good couple of minutes and we can see that everything is updated on our page if we want to check now the status of it and we put number seven check status we did see that the status is complete and same thing for Content we can retri it on our page and that's it that's our project I hope you enjoyed it you learned something and I'll see you next time so the next project we will do will be this AI powered content generator and analyzer and the idea behind this project is more to explain how the infrastructure of a similar project can be produced this particular content generator is not exactly what I consider to be some kind of high quality product output but it's there to teach you how to actually implement this type of a system and then you can easily create or modify a custom version of it for yourself if you're actually trying to build something like this is or if not this project itself will be sufficient to Just Master these Concepts so like before we will do an explanation of the project that we will build I'll use a diagram and also show you the project itself how it works so the important aspects that I wanted to include in this project was how to approach this situation where you have multiple tasks that you want your service to run and then utilizing Python's multi threading built-in Library liary and this is very very important where you actually want to build something more sophisticated so the first thing we will touch upon is Python's multi threading and semop fores which will help optimize the performance especially when dealing with this input output bound tasks like making API calls or database operations so by incorporating multi trending as semop you can optimize the performance of your application important to note this bit here this approach helps manage concurrent requests efficiently so you can imagine as you build a system system like this if you're dealing with what you will see here you're not really increasing the overall performance of it but as your system scales this becomes so so so efficient so you are improving the overall responsiveness of the system as it scales so there is much on multi- threading that can be discussed about and this video will be more about the implementation of it rather than just Theory but in a natural multi threading will allow multiple threads to run concurrently so lastly with semapo is a synchronization primitive that controls access to a common resource by multiple threats and in this project semop for is used to limit the number of concurrent API requests to the open API preventing overload and managing rate limits effectively so we will implement it in our. py file you saw at this point we kind of approach this file structure in a similar way for each project and we always have this U.P file where we include additional function aspect that is running our main.py file so this is where we will do our semop for initialization so for now we will do just five concurrent threads so what is it used for the sem for usage it block it shows that each thread acquires the semaphor before making an API call and this is the important part after a certain threshold additional threads will wait until one of the current threads releases the semaphor so we'll have these two functions that will use semop for in our made. py file we will have a threadpool executor and this manages the thread pool and executes the utility functions in separate threads I'm going to leave this explanation here pause it there's no need for me just to read it out loud just by all means pause the video and read this explanation for it moving on so before we analyze the diagram that will explain our project I'm going to go back to the actual project itself and show you how it works so the idea is that you can enter any topic so for example if I to enter right now Super Bowl and click generate content this is now making a request call to open Ai and we receive some generic text that explains Super Bowl and the idea is that by modifying this Additionally you can have this very quick one button generated content on a topic of your request so furthermore uh project here will have an ability to analyze the text and we have two parameters readability and sentiment as you can see since this is I generated the text coming back has quite a good reability score but what's more important here is that it can actually comment on the sentiment of the text so here I'm providing you the template of how you can utilize sentiment analysis for any particular purpose let's say you wanted to do Twitter post analysis if you were to query each individual feed post however you call it it will give you the sentiment analysis of that and you get like positive neutral negative so you can see this objective commentary on what Super Bowl is so it correctly states that the sentiment of the text is neutral if I was to go in a different direction let's say we go through for historic event W to casualties click generate content so now we have this text that speaks about the casualties in World War I and if I go now and copy paste this into the box for Content analysis and click analyze content now the sentiment of the text is negative so clearly because it is the casualties in in a war let's say I try to do something like successful operation so this is just some kind of like to create a successful operation and then some key factors and then because this is kind of positive uh advice on how to approach whatever long story short we can see that the sentiment of the text is positive so our app works like intended and we'll just break it down through this diagram of how things actually occur so as you saw we have this user interface which is our web app so this is our first SP here I will segment it like so and say this is number one and this is just our HTML elements as you see it's a simple HTML page there's just a little bit of bootstrap here to make the buttons look slightly more modern but nothing special I think I generated it with Char GPT so this triggers out JavaScript so if you go back to this page and we look into the source so if you look into the source and look at the JavaScript you'll see there's a little bit of JavaScript here which is basically just a couple of functions that will extract this text and forward it to our fast API app so that's the JavaScript that we use here so let's say this JavaScript kind of flower number two stage so now our data will land with our fast API back end so with our fast API back end we will include a schema validation so that's not written anywhere here but this definitely will start off stage three starts with schema validation that make sure the data that JavaScript fored with with f fetch method reaches our end points and we will have two end points so as you can see uh we have endpoint and analyze endpoint respectively representing two of the each input boxes one ging an option for Content generation and the otherwise the sentiment analysis so the important part which I segment maybe as number four is the calls to the threadpool executor So This Is Us controlling the processes and making sure that they run sequentially in a specific order and that the sixth one would not start before the semor actually allows it too so after that I would say that what we do have then is communicating with open ey open AI API to retrieve the sentiment analysis and then we can store it in a database this is just the addition to consistently practice incorporating this postest database aspect of uh all of these projects so we can store our content or sentiment analysis into a database this will be our postgress and then it return Returns the data data retrial for displays and then as you saw we get it back in our HTML page so just to briefly comment on when and where multi friending for are used because I believe this is effectively the reason why this project should be studied so the trigger user submits the form to generate content and where so this is the Endo so when we submit the payload to this particular endpoint the thread pool handles the request concurrently and use a semop for to limit the number of concurrent AP calls and so like I said this is our first part uh generate content and then put like one and then two here so the second one is when we do sentiment analysis and what four is submitting the analyze content function to the thread pool to handle the request concurrently just like with the previous one so we use it for the same purpose in these two end points by all means also read this summary it's just F information and like I've said it's very important that you are quite comfortable with dealing with multi API requests currently and making order with a very unorganized situation which could be a system that scales upwards so semaphor so that all being said we went through our diagrams some Theory and we can go and start writing some code so you want to go to this particular GitHub repo it will be the link the first link you see under the project and you want to go and clone the repo so you're going to copy URL and just go into your working directory and get clone this link so we start together with the same file structure that you can see on the left hand side in in this video so yeah after you have done the git clone you will have the app folder templates folder and env. G no. requirements.txt so first thing you want to do is create a virtual environment and activate the virtual environment pip install all of this so I already have the running in a different window but I'm just going to give you a quick introduction of how to do that in I believe in the previous two videos we have done that so you want to make sure that you're in the right folder so the working directory you will do Python and M VNV and then the name so once you have this you want to activate this particular enironment so in Pell I like to do it in Pell so that will be scripts PS1 like so and you can see the prefix VNV meaning that we have activated our virtual environment we want to install all of these libraries so what I'm going to do is PIP install our requirements. dxt so you just leave this to run and within a couple of minutes you will have all of the dependencies ready to be used so in your EnV you want to make sure that you have your sensitive data so we will not hard code any of the sensitive data in our app code rather we will use a particular dependency that allows us to use them in a safe way so you want to make sure that your open AI API key is copy pasted here and also with this project we will be doing a database implementation so you want to create a database with Fest and for that I use PG admin 4 so if you open PG admin 4 in databases here you want to create the database and as you can see I already created this AI gen database so you do the same and make sure that's then your EnV you write this particular variable database U database URL so we will say that we are using postgress and then you want to put username password the address which will be Local Host Port 5432 which is the B one and then the last slash is the name of the database you do the exact same format and like I've set above you just copy paste your API key from open AI dashboard so that's all you need for your EnV file right we're moving on so we can see that all of our dependencies have been successfully installed so we can start coding our app so the first thing we'll do is create our files so we will create a main.py we will have a cr. py database. py ility schemas and models so these are all the files that we'll need in our app folder and just before we start writing the back end logic I will quickly schim over the front end stuff front end stuff is not relevant for this project so you should just use it from the git clone provided with the description but just to briefly schem over what's going on here so the boost stop we're using we are using it through the link there is some CSS styling just to make this project work in the way we want it to work you have your standard HTML which gives us forms so we can take the input from the user and the submit form will then execute some Java script the JavaScript itself is nothing more than a fetch function that will take the payload to do a post request send it to a specific endpoint which in this case will be our fast API endpoint I believe that's sufficient in terms of how much we need to talk about the front end back to us coding our backend now so first things first I like to kind of get the generic stuff that we always do in the same way out of the way so what we'll do we'll go into database. py so we we will import what we need here so we are using SQL Alchemy so the dependency injections will be done with these particular variables and write these also use OS because we'll be working with files and what we said earlier we are using dnv to store our sensitive data so the dependency that will enable us to use that is EnV so make sure you import that we want to load this environment so we'll say load. TV and then we want to import our variables that store our sensitive data so we'll say that the database URL is and then we use the OS framework to actually access that file so get environment and the name of it is database URL so now we want to create the SQL Alchemy engine and we will say that the engine is just create engine and we are passing the database URL so creating a configured session class session local so we have session maker and we'll pass these three parameters and then at the end we'll say that the base equals declarative base so this is our database. py and we can close it we're not going to need to open this anymore so for our main.py now we'll go there and we'll first deal with the inputs so we want to use these three from Fast API to be able to render our HTML page we want to import this particular templates and we importing the our RM which is SQL Alchemy session and we we want to make sure that we can work with all of the files from our app folder so we are importing models CR database utility and schemas so these are the files in the folder respectively and we want to make sure that from database we import engine and session local and uh lastly from stet concurrency we import run in thread pool we'll write models. space. metadata create all to bind the engine and call our app which is the fast API so store it in app variable we want to make sure that this app knows where to look for our template files so to be able to render the HTML file the front end we want to say that go and look into the template folder so that's the directory where we will store our front end stuff which is if you look at the left hand side where the file structures are you can see where our HTML file is right there so to do dependency injection next we can use the same thing so I always copy paste this from the actual website to get our dependency injections we'll be using we'll just be passing this get DB parameter with our endpoint methods so lastly now we can actually write our endpoints so the main endpoint will just read our HTML page and render it so that's what what it does we'll name it accordingly read root it has a request and the return is just U template response giving the template that we have there now we want to so we said we we said we will have two end points that will effectively do all the work so that will be our post endpoint on/ generate so this is for generating content and we want to asynchronously Define this method we calling it generate content and we are making sure that the data that travels from the front end is validated by by our schemas so we still have not written this so now we will go into schemas and make sure that the quest body that comes gets validated by this particular parameter from schemas and stores in payload variable here so this is how we will access the data that goes onto this particular endpoint and then the second parameter is our dependency injection and as you saw we defined that here so this is what allows us to actually have the connection to the database but like we said we have our payload here and we need to make sure that it gets validated and I always like to just use pantic schemas for that so going into our schemas py we will import base model from pantic and we will have a bunch of classes now to validate our data so we have this one that takes the first input which will just be a string so it gives the topic that we want to generate content about and then the second one for sentiment analysis it's also a string so we're just making sure that whatever comes it's a particular one variable and uh type the data type is a string and if you think about it do we really need schemas at this point uh no not really but uh as this tutorial kind of aims to teach the basic architecture structure of uh web up the functions like this we try to establish it as a practice as a habit as a good practice of creating high standard of uh API systems so after we have our schemas we'll go back to our main.py and under generated text we will stall what this particular method returns so as we mentioned earlier we have importing This runin Thread pool from stall. concurrency and the parameters we're passing is a particular function from utility our dependency injection and the topic from the payload so this third parameter is what comes from the front end the input from the user the dependency injection is our connection to the database and the one that we still have not written is the generate content function from utility so that's what we'll do next so if we go into utility. py we want to make sure we import everything that we need so you want to import open AI OS just like with the other files we importing session and loading our sensitive data in load. tnv we're using crowed models files from our app file from our app folder we are importing threading and thread pool execut once again we want to establish the connection to our sensitive data we will be using the open AI key so this is how you're going to do that just like with the database URL we are establishing that here and what I consider to be the pivotal moment of this particular project is to explain that here is the moment we Define semor to limit the number of concurrent threads so just for this example we are doing a particular number five so we'll be running five threads and then if there is a sixth one it actually waits for one of these to finish so now we want to write out generate content function so what we'll do is have it with our dependency injection and the the topic the string that gets passed from the front end and the return will be a string as well so with semaphore we'll say that the search term is cr. get search term and this will have the two parameters of the dependency injection and the topic and as you can see we still have not touched our cr. py file so we need to make sure now we have this particular method written in our cr. py going to our cr. py we will just import these two particular lines and then we'll write our create search them method so it will have the same parameters and we're going to say that the TB search term is models search term term which is the term so as you can see now as we are creating this flow we are kind of jumping from a file to file but I believe it's important that you have an idea of how the thought process usually is when you are creating these end points and modifying specific utility adding functionality to it so now we'll go into our models and write our tables so going into models.py we want to import a couple of things so from SQL Alchemy we'll import this particular column integer string forign key and text we'll import relationship because we'll be using a relational concept when it comes to creating these tables and our first table will be our Search terms so we want to store that so we will say that the table name is Search terms and this is how I've generated this so it will have an ID the ID is the primary key the term which is what gets passed from the user and then we have the generated content that returns to be displayed in the front end aspect for the for the user and also we have sentiment analysis so this is what we're storing in our database called Search terms then our second table is called generated content and this takes from a particular line from the table we just created previously our Search terms table and it also has its own ID this the content and then we have the search term ID and the search term which has the relationship with the search ter table and our third table for sentiment analysis it also has ID ability sentiment so these are the outputs that you saw in our front end up our return to the user when they do sentiment analysis and we are also storing the ID and the search term in this table so that's our models.py if you need to again just pause and make sure that you have written this in the same way I'm going to make sure that everything is visible in a way that you can just pause and go over it so I believe now in the video If you pause everything is visible so going back to where we were so as you can see if you look at the files that open here main Crow utility schemas and models this was the workflow as we were trying to write this endpoint so we can effectively close them one by one and go where we were so the last one that we were working was utility. py and we will finish off writing our generate content function so if this is null we'll say that the search term sorry if this is not null CR create search term and this has the same two parameters so now we want to make sure that we can actually access the open AI Pi so in our response variable we will store open. chat completion and we will write these particular parameters so what's getting passed to open AI is your be my assistant and write a detail article about and we are passing the topic that the user has chosen we will store that in generated text and we will say is that generated test text text equals respond choices with index zero and the message content we'll use strip to do some formatting of the string and we want to access now in our CR create generated content and pass the dependency ejection generated text and search term. ID so this is now a method that we still have not created so we'll go to our cr. py and create this method so going back there we see that we still have not finished our create search method so what we just need to add here is this real lines which is the way how this particular orm SQL Alchemy will actually insert this data into the database it always needs a commit and refresh after that and we can just say return DB search term so that's our first method defined and very similarly now we are doing the create generated content method and with this one we will say that the DB generated content is models and from models we get generated content and we say that content is content we will also add that search them ID we will add the same three lines from above here which allows us to actually do the insertion of data into our database sorry wrong copy paste so the one with DB generated content and at this point we'll just return DB generated content so now we can go to our utility. py and as you can see we are accessing this method that we have just written create generated content lastly this will return generated text so we go back to our main.py and finish off defining our endpoint so after generated text we just want to return that our generated text is the variable of generated text so I believe we have everything we need to actually test this so this particular endpoint so if we go and run our fast API app so we'll go into folder app and we will write uicorn main app reload so our app is running so if we we go and open our end point for rendering our HTML and we enter some kind of a topic here so we'll just I'll just do something very random I'll say New York and click generate content and after approximately like 5 10 seconds we can see that we have our results returned so we have this information about New York so we still now have to do the second part which is make sure that this particular input will reach our second end point so we have to create that second end point all right then so quite similar to what we have already done so we'll just copy paste the previous post and modify what we need to modify so instead of endpoint generate it will be endpoint SL analyze instead of the function called generate content it'll be called analyze content the schemas you'll be using will be analyze payload and the dependency injection can remain exactly the same then instead of just creating generated text we are creating two variables and again we are using running thread pool but when we reach into utility file we'll be using analyze content variable so as you can see we do not have this method written yet so that's what we'll do next we'll go into utility. piy and now we'll create a function that can do content analysis so call it like that call it analyze content because that's what we written in our main pii endpoint and again we will be using semaphor so with semore we'll say that our search term is C.G search term so as you can see we do not have this method so we shall go in CR py and write it now so going there we will say that the method get search them takes two parameters and they are a database session and a string called term and it will just return from our database so we'll use SQL Alchemy here and we will query through our models a datab uh table called search term and we want to filter model search term do ter and it will be the exact term and we will return the first so we will save that and go back into our utility and see that this thing went green now from white to Green meaning that this method it can now be used next we will say if this is not null then we actually want to do a crow operation and create the search term so we entering that into our table and we want to say that readability is the output of the get readability score method which takes the content parameter so we do not have this function yet so we're going to Define it here so we're going to say that this takes content which is the string and it returns a string reability score which is good so this can be something you modify and play with yourself so you can see that within utility you can add any additional functionality so you would actually have to find a way to connect an API that can do a relability score so this will be your place for it so if available replace with Act ual readability I call the one that we will use with our open open a is the sentiment and we will do get sentiment analysis so just like we did with readability score we will create that here and we'll say that the get sentiment analysis takes content as a string and gives us a string put and in this response we will again use open ai ai so we using chat GPT 3.5 turbo and this is the message just saying be my assistant and analyze the sentiment of the following text and we are passing the content that we have just generated previously and you want to make sure you actually know how much tokens you're using with this you don't want to just burn through it so I'm limiting it to 10 after that we will return the response of choices and again with some formatting using strip oh this indentation is not right so you want to make sure the indentation is right so just have a quick check over you don't do the same mistake I just did a second ago so now we have a get sentiment analysis function so just to recap this is an actual function that works properly we the readability score you are free to improvise with this and play around implement the readability API here you will do it in the exact way how this is done with the sentiment analysis So within the response variable you will make an API call pass it certain parameters you can read API documentation of your readability and then return the response that it gives so going back to our analyze content function after we have done readability and sentiment analysis we will do some crowd operations so we want to store all of that and we are just saying create sentiment analysis this is the method that we will create right now and the parameters we're passing is our dependency injection and the readability sentiment files but also the ID because if you remember we are using a relational concept here when it comes to our tables so now we want to create the sentiment analysis method so going into crud we will do create sentiment analysis the parameters are the dependency injection readability string string and the ID which is an integer and here we want to say that our variable called sentiment analysis analysis basically just like the line from our create generated content functions this one here so it'll be very similar so I'm just going to do that it goes into models of sentiment analysis table and readability through ability and you can see where this is going just like with the previous one ending with adding the search term ID then we want to do our croud operation uh specifically create so we are going into the database we are adding this particular ular payload and you always have to do commit and refresh and then it's just returning the VAR variable that we created here so it will return DB sentiment analysis so we have everything we need in our Crow I believe now and we can close it to finish off our utility. piy we want to go back to where we were which is this line so we have just created this particular function and as you can see it went green so it means it's connected and we just want to return these two variables so if you remember we we have this readability and sentiment and we want to return those two so we'll say readability and sentiment so I believe with these four functions we have finished our utility. py file as well so 1 2 3 4 that's correct so we can close utility. py as well going back to our main py to finish off defining the second end point the post one we want to now return the data that we have produced with readability and sentiment so we will just say that readability is readability sentiment sentiment and this will be in for of a Json it's an object like so so what remains now is to test the second end point and if everything works then we will also just check does the crud operations do they operate properly and insert the data into our database and if all of that works that's our project finished so we are saving this our app is running so we will open our app and test it we will do for example London click generate content and wait so we have some information about and now we want to do sentiment analysis we expect it to be positive because this is all like superlative Des of London so if we copy paste that into our analyze content and click analyze content we see that it says that the sentiment of the text is positive so everything works here as we want it to now all we want to see is if we open our PG admin 4 and check into our database did this London information get accordingly stored in our database so doing that I'm going to refresh my database and going into my tables first I'll do Search terms so if I return all rows and I've been testing a lot of things as you can see but at the bottom you can see that there is London so everything works right here doing the same for our generated content and I do return all rows and we see that the content text expl in the vi city of London and now we want to make sure that the third analysis table also works properly and we can see that it gives us yet the last sentiment of the text dispositive which is consistent with what we just saw so everything in this project works as we intended I hope you enjoyed it and learned something and we'll see you in the next one we will create a web app that will combine the functional web application using audio processing and AI models and it'll create something kind of unique and this is the end result what we'll end up with so as you can see this is a Content aspect of it and it gives the user an option to upload any audio file they want for all intents and purposes I'm just going to choose a random song from my computer so I've chosen this song you can see what is here for this app I've included also Russian and Spanish so if you want to try doing songs that are in Russian or Spanish and you and Spanish and you want the lyrics this is the way to do it so after choosing all of that we click extract lyrics so after clicking extract lyrics We will have to wait for a minute or two because now in the background we will have the following processing happen with this song which is an MP3 file we'll get converted into a VA w a file then we'll have the lyrics extracted as you can see they just popped up here then we will communicate to open ai's API to have a summary of the transcribed text so it will Express the general meaning the sentiment of it and then the idea is that that this particular summary will be forwarded as a prompt to open ai's API to produce an image inspired by this particular summary so that is what the end product will look like and now we can explain high level what is going on in the background and how this project works so just initially I want to show that with the file structure what we'll be working with here is just the main py so we are doing the back end here everything else you will just get from my git repo I'll show you in a minute how to do that so the front end the index. HTML the static files these will all come from the git repo and then these two folders will just be there to manage all the files that we'll be working with so irrelevant to talk about now and you will also have to create your EnV to provide the open AI API key of yours and the conventional requirements.txt is just a file that I will will include in the git repo to make sure you have all the dependencies required for your project so like I said everything here is pretty much a relevant other than our main.py so all of this will come from the git repo and we will just call the main P py so on a high level what will happen is you saw with the front end the user has the option to use a file so this file user uploads an MP3 file once this particular event have happens so this is matched with this we initiate the conversion of an MP3 file into wav so this particular line here so that we will call let's say event number two so once that is completed we initiate our audio transcription So This Is Us extracting the lyrics and providing them back to the user so let's say this is our step number three here with number four you saw that in the summary of the transcribe text we will extract General meaning the sentiment and then provide that to the front end as well so our back end event number four is the text summarization and it provides this summarized text so as you can see that goes within our before here text summarization showing the summarization of the transcribe text into a concise sentence and then lastly the idea at least is that we will create some kind of an image that is inspired by the lyrics of the text so just for the sake of the project this tutorial is supposed to teach you about this backend architecture that's kind of event driven and it combines usage of different API so API integration for a specific purpose but you can modify this however you would like based on what you would like as an outcome here I just wanted to show you the way to do it so I thought all right the best way maybe would be to rather than just take the whole lyrics and try to create an image I'll create some kind of a text summary which we saw here with the step number four and then that will be the prompt to create image out of it once we prompt open AI with this summarized text that image will be generated and the result displayed back to the client so to reiterate the events we want to implement in our architecture is the following sequence so the user uploading the MP3 file through a web interface so in the back end then conversion to a different file type will happen so after this processing is complete we we will actually extract the text from the file that text through open AI API will be summarized in one concise sentence then we will use that to prompt open AI API to generate an image and that image will be displayed to the user and that's the end of the sequence of events for our back end so this is the high level overview of our project here with all of that that being said now we can go into implementation so the first thing you want to do is go to the GitHub link the following link that will be provided in the description and it will land you in this lyrics start repo and you want to copy this and go into your vs code so once you've done your git clone and you land with this exact file structure we'll be working with this main.py and build the rest of the app but first before we do that we'll go through what you get here so you're just familiar with what's happening with the front end and the remaining of the files and folders here so I'll go from like to bottom so this is for now an empt folder where we will store the converted files meaning that we will take a MP3 file convert it into a WAV file and story there with the media this is the place where the pictures like the images that are generated with our AI will be stored before they are displayed on the front end client uh static will just hold our CSS and maybe if we want to include logo for our front end in the templates we'll have a front end like the HTML uh file written and we'll go through each of the elements just to make sure even though this is this project is not meant to teach front end in any way shape or form but we will still go through it so that we can reference what goes where as we C the back end we want to understand why a particular function or logic from the back endend is influencing something in in the front end and then with the uploads I believe this will be the place where we store the initial chosen files so the MP3 files so git ignore it's just here once I push this to get I don't want to push some of the stuff that's sensitive or that I just don't need in a repo and if you want to read more about the actual project the read me file here is exactly for that it actually explains all the features of the project and the specifications like the text stack used and it just gives um overall how it works so without further Ado we will actually get the link go back to our vs code you can create a new folder it doesn't matter but we will git clone this into your working directory so doing git clone and giving the link of the repo we have this folder now so we'll CD into it so the first thing you want to do is install everything from your requirements.txt so just like with the other projects we'll create a virtual environment so this is your command for it let me see maybe you can't see it over there so python mvnv VNV once you do that you will see a new folder in your working directory VNV so you want to go and activate that I prefer opening Powershell but it's really up to you which terminal you use to do that so you want to make sure that you're in the folder and you want to access it all the way into scripts and then activate PS1 and this is fine so now we have everything activated and we want to install all of our dependencies so you have the requirements.txt file here you just want to type in PIP install our requirements like this and just let this run so this will now install all the dependencies and whil this is happening we'll we can just start writing our back and code here so the first thing we will do is import everything that we need so I'm going to copy paste all of the stuff and just break it down quickly so this is everything from Fast API that we'll be using we'll be using pantic we are implementing this particular software templating this allows us to render the HTML page you don't want any issues with cost so we'll import cost middleware OS is to be able to manipulate files to work with files because as you saw we have to upload uh an audio file from our device then the remainder here will just help us work with the image that's displayed and the audio processing do EnV is important because we don't want to include any sensitive information by hard ining it in our code in something that you might push to repo or share with other people so this is dependency that will allow us to store it securely logging not the most important thing but I like to have it as I build this project if I encounter situations where I'm building something new and I want a troubleshoot logging helps a lot speech recognition will help us with audio processing and then finally we are using open Ai and requests to make this sub requests for HTML protocol requests and open AI to communicate with our open AI API so that's all of our dependencies at Imports if you want you can pause the video and just make sure you write this exact same thing so we move on we will create a EnV file so you want to make sure that it's in your working directory so you want to write this open API _ key equals and then you want to include your API so your API your API key from open AI so I'm going to do this offscreen and you can do exactly the same once you have done that now we can actually import that variable so we will write load. EnV we will say that our open API key is OS meaning the input that deals with files as you saw earlier in the line seven here this import OS so we accessing that and saying get environment variable and then we're giving the name of the variable so now we can use that securely we want to initialize our first API app so we will say fast API if need be here we will use loging so we can configure that later if we have to back and stay as it to do so we want to mount our static files so our fast API app needs to know where to look for our static files if you look on the left hand side we have our folder static and that's the place where we will direct our fast API to look so at the moment over there you have the CSS and I've just included this logo from my YouTube channel so all we have to do is say look for it in this particular f a folder and we will say that those are the static files called Static with name static now we want to be able to render our HTML page so we will do templates and say the directory of it is templates just as we have the directory static underneath we have templates and that's where our HTML file is so now is a good moment for us to open that front end and see what we have there as we said we will not be doing a tutorial on anything front end related but we want to make sure that you understand once you're writing the backend code what does it pertain in terms of the front end so in your templates index.html open that and we'll just quickly do a breakdown so that's not really relevant so this is just using the text of it it's a lyrics extractor so in our main we have a form which will allow a user to upload an MP3 file so we are saying choose an MP3 file and then in the input type we specify that it is like the ID file so the type is file and it accepts MP3 then we allow these three so you have these three options if you remember it's a drop down between three languages English Russian and Spanish so then we have a button that submits this form once that button is submitted we have some JavaScript here in this script tag that does that work for us so once the submit button is clicked the extract lyrics this is the event that's triggered and we execute a post request to our endpoint that we will Define in our main.py file so that's something that we will do now that's not something that exists here but ahead we are referencing that in our JavaScript logic here so the Ajax code it is pretty much similar I believe in the previous tutorial we used Fetch and it's different but it works on the same principle where we are defining the endpoint address we are defining the type of the HTML request that we are doing then we doing this Json stringify to make sure that it's in adequate data form where we are expecting a response as well so that's the JavaScript there and as you can see there is not much to the front end other than just these couple of elements that will accordingly display the different content as it's generated so that's why we have these respective ml elements they're pretty self-explanatory I don't think we need to discuss this further more and we should focus on what matters more which is the front end so oh by the way I don't want to forget also in our static we have some CSS just to make this up a little bit more aesthetically pleasing but once again not the front end tutorial so if you feel like exploring it a bit studying it by all means do that and we will now Focus again on our back end so this is where we left off and this is something that I just copy paste from the documentation of fast API there's always always the same thing used for me just to make sure that there is no cause issues so for data validation I might use just a particular schema so I'm going to say that the lyrics payload inherit base model and it's just one variable which will be a string so to keep things a bit more organized we might as well create a file and we can call this schemas py and we will check this there so we want to make sure we import pantic for this then going back to our main we can go on the bottom here of the Imports and just say import now I can say from scheme as import payload though one thing when it comes to managing these different directories here where we will be storing content that's dynamically generated I like to include some code that helps the logic of it by making sure that certain directories exist before it executes logic where it's supposed to save something in that folder so just in case things get scrumbled later on if you're playing around thinking around with this project or any other project I like to include something like this so I say if this is null and I will give the name of our converted files folder we'll do OS make this so it will create a directory called this so now if I just run this python main.py you can see that it has created converted files folder so if it doesn't exist it creates it if it exists this becomes obsolete I like to have it so we can Define our endpoints now so we will have a get endpoint that will first render the HTML page so this will be the response class of HTML response and you can asynchronously call this method read root which will just render the HTML page from our templates so it will give return templates template response index.html and also request so leave that empty for now so with this we can already test this fronts as we needed to so if we go into our terminal and type in uicorn main reload we can see that it's running so if you open your browser uncheck Local Host a000 we can see that we have the front end rendered so nothing here will work because there is no back end that this can communicate with yet but we know that so far so good everything is working as intended so going back to our back end we can continue with our other endpoints so we just create something like we'll call it Roots so now what we want to do is create the endpoint where the button will go so so once the user clicks submit we want to upload that file so we can initiate the processing of the audio file so we'll say endpoint upload file and asynchronously called create upload file so this will Tak in file as a part of the request and also the language that we want the text to extract to into and this is a string so we want to make sure just like we previously made sure that we created a directory called ined files now we want to create a directory uploads where we will store all the files that the user chooses to upload so let me just copy paste this bit actually and this can be indented but there'll be a difference in the name of the actual file so it'll be called uploads well so as soon as the first time we actually try to communicate with this endpoint then this logic will be executed and it will create our uploads F uploads folder so next we want to store the file location so the actual actual path so as you can see in our file location variable here we are storing this as an F string and we will say with open and then give it the file location as file object and we want to write file file read like so so now we're going to be doing our audio processing so for this we'll say thatav location of the file is and then we'll do an F string and we'll basically give it the same half as the MP3 but with just replaced extension so it's not going to be MP3 it's going to be VAV remember this is not modifying a file this is just giving the location of where we want to save the processed file the converted file hence we are just effectively changing the name just changing the string and then now we want to call a function that will convert mp3 to wav so to do that we will create a new file we'll call it utility byy and in here now we'll write some logic that will actually do the conversion of that so we will call this convert mp3 to wav so this will take a parameter of a path of MP3 and wav so I will say that audio is audio segment from MP3 and then the MP3 path audio export now we give the wav path and format wav and at this point I want to make sure this actually happened so successfully so I will go back and implement the logging that I was talking about so earlier remember I said if need be we can use logging here and I think it need be not just that it's necessary but I believe it's good practice and it will help me stay ahead of any potential problems that might might occur by telling me exactly where my problem is rather than me having to spend time on troubleshooting so we'll configure that by saying logging basic config level logging info so we'll create a similar put in our utility file so what we'll need is logging we will need this for audio processing I'll copy these as well so space recognition open AI requests OS and I believe that's all we need for now these two actually let me do all of these so if you want to pause and have a look at everything the output here so to make sure that you are on the same page at the moment it might be a bit redundant but I'm trying to be time efficient as well and just making sure that I get everything if there is an extra line here it's not really a major problem for me now as long as as long as I get everything working so back to our function after this has happened I want to get some kind of a message that will confirm this so for that I'm going to say login the info and then just inform converted MP3 to wav and give it a path of where it has happened this will also let me know of the location of my file if for whatever reason I need to see it at that moment we'll whilst we're here we'll do another function and this will be to segment the file so the reason why is only later I realized that open AI has a limit on the size of the file that you can give it to transcribe so the go around method for this the first thing I thought of and by the way there might be me better ways but I don't think it's necessary for the scope of this project so what I do I just split the audio in segmented Parts in small chunks and then transcri transcribe them one by one in smaller parts and once it finishes it comes up as text anyway it's very easy just to join display to the user so it works quite fine so you want to write function split audio and it will again take the path of our converted file and then we'll say the chunk chunk length can be this particular length of milliseconds so we are splitting the entire file divided by so if it's 5 minutes it's going to be however many milliseconds in 5 minutes divided by 60,000 and we will say that the chunk path is ch index a no this is the wrong line going back on this we don't need the path we need to actually Define what our chunks are so quick re-edit and we say the chunks is audio and we want to Define that audio above actually so going one line above that we'll say that our audio is audio segment and then from wav and giving it the path of our WAV file now we're going to take this audio variable and do some slicing here so we will take the index plus chunk length for I in range of zero and give it the length of the audio and then pass chunk length Mill seconds and this will return so this will then play the audio physically into smaller segments and then we want to transcribe each individual audio segment so we will create a new function so this will be transcribe audio chunk and then this will take individual chunk and the chunk index and we will give it the path of each individual chunk so we will say that this is chunk and then the chunk index so finally exporting these individual chunks so and giving it the format UAV so with this we will say try open chunk path as audio file so now this needs to travel to our open AI API to get transcribed and we will be using the model called whisper one so I already prepared some code for this and we can just copy paste it if you need to ask after you see the copy paste you can pause the video and make sure you have the same thing so we'll write an exception store it as e and then we will again utilize logging to say that some kind of an error has occurred and then we can actually inform what particular chunk cause the problem by passing the chunk index as the error so we can give it the finally and we can remove all the chunk files so it's just a cleanup of after the processing has finished and we will return the text so we are still working on our transcribing methods so we have written the first two we can minimize them to make this a bit more readable and write our third one so this one will transcribe the wav to text so I can take the path and the chunks here will be the audio of the path of the file full text here it's just an empty variable an empty string as a placeholder and we will write a for Loop saying for I and Chunk in EN numerate so going through all the chunks we'll say that the chunk text and then we will call the previous function of transcribing audio chunk we'll pass chunk file and the chunk index so now we want to make sure that we join in our full text transcription from each individual chunk of the video so we will give chunk TT plus an empty space just a placeholder so after this we can do logging info and just inform what the outcome is so we'll actually see it for example in the terminal here and finally we just want to return the full text and we will use some string manipulation to strip so these are the three methods that we will need to successfully do transcribing of the audio files now we can move on to the last method that we will include in our utility. piy and this will be the one that will provide with the summary of the lyrics so if you remember in our front end we have the extracted lyrics that will display the entire transcription of the audio file and then below it's the summary of the transcribed text so what will provide that summary is what we will do right now so it will be another asynchronous method we'll give it an appropriate name this will take in the parameter of text which will be the entire lyrics or transcription of the audio file and we will take the similar approach like before we will have try and accept and the accept will perform the similar logic as before so you will just perform some error logging and this can just be text that says that some kind of an error has occurred just keeping us know that if there is a particular problem we don't need to do any troubleshooting it will tell us that it was during the text summarization and then this will return something just put summary generation failed that will suffice so in our try we will use something similar for from what we have done before and I'm just going to copy paste this particular response variable so we are communicating with open AI API so the model is chat GPT 3.5 turbo and the prompt is just asking the B API to do an assistant Return of summarizing the following text in one sentence and we are passing the variable of text which if you remember in the parameter of this function is our audio transcription after that in our summary we want to store the response and then just particularly Define choices with index of zero and with the message content and just we want to trip this to make sure that it formats it for us and then we can say loging for and then this can be the generated summary displayed here for us just another way of keeping this good practice and this returns summary so that's all that we need in our. py so with this we can now return to the main py and make sure that all this is imported so the first thing we'll do is write import utility do py sorry not py import utility so now we should be able to use all of the functions that we have defined oh no let me particularly name them so from utility we will import and then we can do all of these functions so it was summarize text transcribe another transcribe split audio and our last one convert mp3 so now we know that we'll have access to all of them and we can now focus on finishing all of our endpoints so if you remember where we left off with the post endpoint for uploading the file so what the user will do from the front end so we gave the location for the WAV file remember this is not some kind of logic that will do a conversion or processing it's just naming the new file and making sure that the extension is no longer MP3 so now we will actually use one of the functions from utility. py that will do the transcription sorry not Transcription conversion so now we can call this function convert mp3 to wav and we will give it the file location and we will now also give it the AV file location then after it's been successfully converted and stored in our converted files folder we want to extract the lyrics so we will use our transcribe function for that and give it the location of our newly converted file and there is no need for us to keep the MP3 file that user has uploaded so we can use OS to actually delete that file so for that we'll give it the file location to our o. remove command now we want to create our summary and for that we can use a weit and do summarize text so this doesn't run in a way that can break the logic so this will await for the previous functions to finish this might take a certain amount of time and there are factors different factors that can differentiate what takes longer or shorter time so for example obviously strer files will not take the same amount of time to create transcriptions so await will make sure that this these tasks are run in a sequential Manner and then lastly we can just return that our lyrics uh lyrics and the summary is variable summary so now we can go to our front end and test some of this functionality so I've just uploaded a random song and clicked the extract lyrics button to see what the output will be and if I go back to my vs code we can see that we successfully delivered this payload to our endpoint and our logging initiated all this information to be shown to us so the backend has successfully done the conversion from MP3 to wav and then you can also see that the backend has successfully executed the. py methods communicated with open ai's API to provide this transcribed text so these are the lyrics from the song that I've uploaded and then there was another call that done has done a prompt to open as API again to create a summary from the previous text and you can see that it's successfully done exact exactly that so now what we trying to do is make sure that we create an image that's inspired by this one sentence and just to make sure I can see that the back end has successfully done everything that I wanted but I want to see has it all been displayed accordingly to my front end and uh as you can see it has exactly how we expected it in the extracted lyrics box we see the lyrics from the song that I uploaded and then in the summary we see our sentence again so the final missing bit now is to create an image that's inspired by the summary of the transcribed text so for that we will create a new endpoint and this one will be generate image again it's a asynchronous method and we'll call it generate image and it will take the lyrics payload so again we will use the try and accept exception struct so first for how we will actually try to generate this image we need to use our API key so just just like previous we are using OS and getting the environment variable and this is called open I API and then just to make sure that we have some troubleshooting logic if something goes wrong as this is common and good practice we will write that in case our program is not able to access our API key or if the API key variable is null then we will say logging error Pi key not access able found not found and we can raise an HTTP exception with a status code 500 and give it the same um same detail so we can say just copy paste this wasn't found so now we can do the URL for the open AI image generation and uh I'm just going to copy paste this online you can Google this so once we have that link I want to take this approach in my headers I'm going to pass the API key and uh again I have this documentation written in front of me so I'm going to copy paste this part too so what's going on here is that we are passing the API key as a part of our header and that's the way open will verify that we have access to the API features so for the prompt we can do an F string and say that we want so keep in mind as well you can modify this you can write this the best way you think will fit your project or to be honest most likely you can Tinker around with this and create a better prompt than what I'm about to do because I've already tested this and the outputs are just very not artistic to say the least so I'm just going to WR create an image based on this summary of a song maybe something like that I don't know you try playing around with it a little bit more if you want a more quality product but we are here to demonstrate how an architecture like this is implemented so we want to make sure that we don't get any errors in terms of either are limits for open ai's API how they can process a certain amount of text so we will try to say that if the length of this prompt is greater than 1,000 characters then we will just truncate it and we will do prompt and then slice everything above above 1,000 so just to make sure that the image that arrives is within some acceptable menion parameter we'll say that is prompt the size of the image and this is relatively arbitrary but feel free to play around with these Dimensions If this means anything to you but I'm quite happy with these dimensions and we won't just one picture that suffice so again trying to keep up with the good practice of logging the information we can do an FST string and communicate to our server saying that we are sending the request to open AI my API with the following data we can include the data so we can see actually what we sent the prompt with and then we will store the response and say that it's the request post and then we'll pass the URL headers will be headers and the Json will be data so this is what we are creating our quest with these parameters and then storing the response that comes in the response variable again we want to do some logging and we will say that open AI API response status is and then we can pass the response. status code and we can also do logging info so more loging for response content so we will actually show all of that in the terminal here as the server is running and we'll do raise for status so the image we want to store it and say that it's response. Json so in our data list zero and we extract the URL so the Inon is URL here so we'll do a get request for that and again we'll do image response rates for status so then we want to now show that image as in l in our front end so we will say that image open and then we'll use bytes iio which response content and we want to use a similar approach before we did with creating that directories in case they're not there so we'll say that if this particular folder does not exist then we will use OS to actually make create that folder here and our image path being os. path join and we will use media and generated image PNG so this will be the name for our image you can if for whatever reason want this to be different change that and have it called whatever you want it really so we want to save the image as the image path and just to know that everything went fine here we can do some logging and say we do an F string that image was saved at and give it the file path and lastly we return an object that will say that the image path is and then the variable of image path I believe that's pretty self-explanatory then so we want to write some smart code so we'll do accept requests start exceptions Quest exception as error and then in our loging we can pass that and say that request exception was the variable e which will be which will call the error that has happened and we want to raise an HTTP exception and we'll give it the status code 500 the detail of error and we just want to make sure that it's a string so I had some issues before with this data being not the appropriate data type so just want to preemptively put that there and the last thing that we need to display our image I'm going to show you in our front end so as you can see the here this code with Ajax is going to do a post request to generate an image with the summary so as a prompt and then upon success what we want to do is then actually get fetch that image so in order to show it we need to communicate with our endpoint media generated image.png and that's something that does not exist yet so that'll be the last thing that we need to do is to create a new get end point and we'll call it generated. PNG and this will be another asynchronous method we'll call it give it an appropriate name and all that this will do is return the file which will be the image that we have just generated so this will go into the media folder and fetch the image and that should be all for our project so now we can do some unit testing so going to our front end I'm going to choose a completely random song from my computer I know it's in English language so we will do extract lyrics looking in my vs code we can see that our logging utility is working fine and giving us information that the conversion from MP3 to wav has started and when I look into my converted files I can see that song is actually there so as you can see the back end has successfully transcribed the text and it looks exactly like the lyrics of this particular song and also then the second aspect of our back end has requested this summary this text describes a sense of determination resilience and strength in the face of challenges with a focus on survival and perseverance through difficult times I'm happy with that so now we want to create an image and we see that we got an error so so something is wrong with this particular aspect we do not have our image yet so we will do some troubleshooting and try to find why has this happened so I can see a typo if we go to our endpoint here it's not supposed to be generate image but rather generate underscore image so we'll save and try doing it again so I have the same song there I'm I'm just going to click extract lyrics so the same lyrics will show up here but what I'm expecting now is that with the generated image there will be some kind of an image produced by open AI charp that will be based on this particular summary and looking at the vs codes terminal I can see now that it actually has executed the post request successfully so as you can see here the logging command has given us this information that the prompt has included the summary and the other parameters that we defined so everything went fine here we have to status 200 and the content then being the link of the image so everything here looks fine so now when I go back to my front end I should be able to see this uh piece of artwork and U this is what he gave us I don't know how is this inspired by this particular summary that you see here this is bloody awful but hey it's not me it's the the current state of the art isn't it let's try and see maybe if we modify the prompt can we get something more consistent with the actual summary so previously The Prompt was generate an image based on the summary of a song and then we passed actual lyrics maybe we shouldn't do lyrics we should do the actual summary so let me try maybe writing a better prompt here so I'm going to write something like I have a song and I will summarize the lyrics from this song I want you to generate a beautiful art based on this summary here is my summary of the text so let's see does this change anything I'm not really an expert for this type of prompt engineering especially for creating something artistic that's probably the exact opposite of what I feel I have some kind of a talent for but nevertheless we shall try so I will try and use the exact same song just to be able to compare so this is our previous one and um let's see has our new prompt made any type of an improvement so once again just going back to our back end so you can see that all of the logging is doing its thing there so we can follow along how this process is sequentially happening wow this is even worse so my prompt has made it uh considerably worse so when it comes to Art this is definitely not producing the best results and just for fun I want to try and see how this same prompt will perform in ch gpt's new model so as a tangent to this project we will actually take the exact same prompt copy it and check it in that GPT so I think it'll be quite funny to see the massive difference between the model that we are using here so this definitely needs a much better model rather than this particular one that my API is communicating with here I leave that part up to you and just to demonstrate what kind of a difference it can make please have a look at the image that CH GP 40 has created from the exact same prompt I think this is actually hilarious so the difference is substantial from this I don't even know what to call this previous one but as you can see I did a direct copy paste of the exact same prompt and please read the summary and then look at the picture I feel like wow this actually did create a very fitting for the song So as you can see if you think around and Implement a better model for this particular part of this project you can get considerably better results I'll leave that autistic aspect up to you this particular tutorial you've seen how to implement this architecture and there is plenty of room for improvement upon your own personal preferences today we will build this particular web app you'll be able to upload any image that has text on it and have the text extracted from the image directly onto the page so it will be displayed here so we'll test the app right now I'm going to upload a picture we click extract so this was the picture that I uploaded this was just randomly Googled and as you can see the text is extracted and it appears for the user right above so without further Ado let's start building this app the first thing you want to do is navigate to my GitHub I'll leave the link in the description and you can find find this particular repo we will get the link for it and we can move on into our vs so we will open just open a brand new folder do kit clone paste that link and we can start building together from this exact file system so you can see a couple of files already there and we have to discuss a couple of things that you need before you can run this project so the first things first let's install everything that python needs to run this good practice is to create your own virtual environment so none of your dependencies Clash and we will do that so in this particular folder can navigate in our working folder we can create a new environment so we can say Python and this should create a new environment for us I'll navigate to power shell but you can activate this any way you really want the inash or power sh so going into to activate it we want to go a second to see we want to go into the script folder now we want to go into VNV first and then scripts so here if we type in activate. PS1 we can activate our environment and as you can see now there's this prefix with the exact name of my environment meaning that now we have activated our environment so just to reiterate for those of you that haven't done this before you type in this particular command to create a virtual environment so this is the command after you run this you navigate into the scripts folder and there you activate by typing in this do/ activate. PS1 so now we will install the pendencies that we need for our project and you can see in this requirements.txt you have everything listed here so you can just type in want to make sure that we are in the main folder again so we will go back and now we can type in PIP install our requirements.txt and this will install all the dependencies that we need for this project lastly we need to discuss how we will be implementing the AI aspect of this web app so we're going to be using p SCT and now we have installed the python wrapper for it but we also need to install the proprietary software and run it on on our machine and the way to do that if you're go into read me I've written some basic explanation on how to do that so we need to install this python rapper we have just done that so that was us installing with Pip but we also need to install this so navigate to this link and install Tesseract for Windows without this you won't be able to run the program I will include the link for this as well in the description but anyone can just Google Tesseract for Windows installation and it will give you the download option and as soon as it's installed that's it you're ready to go with all the requirements met you can start building this project next thing we want to do is to make sure that we can run our flask app so we will just prepare the layout for our web app and we can discuss then one by one what goes in which file you will see that as soon as you did git clone you already got this config.py I don't think there is much necessary to discuss here this is just the configuration file for our flask app and you can basically just use it the same way how you see it here here only thing you want want to do different is Define the upload folder the uploads file path for yourself so if you remember our app had an option to upload image that will then be giving the text extracted to the display so this will be the folder where those images get uploaded to so you can choose any folder in your documents it's entirely up to you other than that I don't think there's anything necessary to discuss in regards to the config.py page moving on we want to create a app.py and this will be the main file that actually runs our app and all it is all it's going to say from App import app so this will go into the app folder this one here where we will have all the files for our web app and it will just import that into our file here the one that runs back end and we'll say that if name isore main then we just want to run our app that's all we are going to do with this and we will create another file here where we will write the logic for the AI processing but we're going to leave this empty for now and then if you navigate into your app folder you'll see that you have another two you have two subfolders static and templates in the templates you will see index.html if you open that you will see that there is already pretty much everything done here the reason why most of this is already completed is that I didn't want to focus this particular tutorial on building front end even though we will discuss this front end so that you understand every L of code here so I will guide you through it but I didn't think it would be necessary uh it will be kind of waste of time time to discuss every single aspect of this especially talking about CSS and stuff it's not the purpose of this video and then in the static you will see that you have two subfolders images and uploads and this will just manage when we want to upload a picture one of them will go into this particular folder called uploads so as you saw earlier this was the picture that I use for test so it naturally end up being uploaded into this folder and in the images here I'm just using the logo from my channel this is something you can for the sake of just practicing and building the same app you can use this you don't have to can put anything you want here or you can ignore it entirely you can delete this one that's entirely up to you but that's the brief explanation of our folder structure and with that being said we can start building our app so what we're going to do first is we're going to do the backend logic of our AI processing of the image so we just installed the tesser ACT and we can start writing the code for that so this will be our AI model that will take an image as an input and give text as output this is just a brief explanation for it so we'll get an image as an input and the output coming out will be a string derived directly from the actual image so we want to start by importing our libraries but n as NP and to manage images we will import this and just change this back to import so we want to specify the path to the Tesseract executable so earlier I mentioned to you that you have to download the Tesseract software their proprietary software and the way to do that is by going onto the GitHub link when you find the installer the windows installer and once the installation is finished you want to get the path and copy it into this particular variable so most likely it'll be the same as you see it here if it's not you might have to do some tinkering and find this exact file so this is needed for the program to run you want to save this file path into this variable so we'll write a function that will extract the text parameter for it will be the file path of the image file and it will return a string so like we said the a model will take an image as an input so that's the image path and the output being a string type that's this bit here so we want to say that image will use the image library from p and it will open the image path so the variable p in our method and then TCT will do its magic and do image to string from image we want to remove symbols and split by lines for better display so this is just for read readability and I've actually produced this just by wearing chat GP what characters could kind of be problematic in that sense so to manage then this particular idea we want to write this line here moving on we're going to create some distance once again we are with these last last three lines of code we are just working on creating readability in our output and this will just split the lines with a break so if you remember from like python Basics this n character here will create it's like a space line to create some Division and then finally we want to just return text lines so this will be the string output so that's all this Library pretty much does everything for you and that's how simple the AI aspect of it is and we want to try and test this now and see if this runs properly so we're going to say test and run by saying image PA and we want to give the path of the image so I might just use the one that I had here again so I will go and copy let's try copying relative path so we will give it the path I believe I need to change these to forward sls2 just want to test this and make sure that I'm actually printing this so if we do python ml. Prime yes it gives me the correct path to the the image as we can see so it's always good to test these things before you actually run your program or something like that uh you catch errors before they become too much to handle so we will then that the extracted text is and then we want to run our function that we just defined here so we can just call the function and give it the parameter of our image path which was this so if we give it that and then we want to just show our extracted text so we can print this particular variable so the instructed text is and then we can just give it a variable so if we try running this now Arrow so I've just changed the way how the path is given so we want to delete this bit and we'll just give it a DOT to say from the current file from the current directory go into app and and I believe this is all we need to do so if we run now we see that we get the extracted text in this particular string so this works now and that's all we needed for our back we can comment this out and move on next thing we want to do is go into our app folder and we will open templates just to discuss the front end aspect so like we said we will not write this code from scratch I don't think it's necessary for this particular project we can just discuss that it's it's just a HTML page with some CSS and bootstrap that's all it is using this particular boost trrap there is some CSS that will just give some aesthetic aspects but nothing too complicated you can examine this on your own and play around with it if you choose though so closing the CSS aspect we can just talk about what's in the body of the HTML so we have our upload image button and upon submission there is some logic some templating templating that handles how once the image has been processed and we have our text in the form of a string this is just some templating that will handle how it's being displayed and that's pretty much all that it is so without talk if we open this by itself so if you open this by itself just as a file you can see how it looks like I said the upload image element with the browse option for selecting the image the button to extract and then once we receive the output when now backend processes the AI code we have just written it will be formatted here and we want to also display the image that we got the text from so with the front and being sorted like that we can now move on to building our flask app which I believe is the most important part of this video so as you saw the actual AI itself we have tesser doing all the work for us it's a very simple function it just does all the work we don't really have to do more than that so we want to now build our flask app so the first thing we do is we'll create two new files I'll call it views. pi and the other one called init with two underscores like such so in this init file we want to import flask and we want to say that our app is flask and then for the configure file we will use the file that you got just from the git repo so we'll say from object and then we will name this file config development config like such and we will also import views and that's it that's all you need so the last thing that we need to do to finish off our web app is is to write the backend logic in our view section so again we want to import plk an app and we want to request render template and URL 4 we also want to import OS to handle files I have this recommendation from chat GPT to use this particular Library as a method of dealing with files when changing or modifying file names so we will move on with that we also want to include your typical numpy SNP we again need p and image random string and we want to import our function that we built we want to add the path to config so we'll say that app config is initial file uploads and we will give it a path so for us that's in our static and we'll write our rout to the homepage the only page that we will be using for our web app and it will include methods both get and post so I am assuming that at this stage you are familiar to at least the basics of HTTP protocol and specifically the four requests that you can make get post delete so kind basics of your crowd systems we stand for create read update delete if this line here means absolutely nothing to you I would suggest finding a dedicated video for this particular reason if you want a good understanding of what we are doing here you would necessarily need to completely understand this just to finish off this web app finish off this project but I do highly recommend so that being said we're going to move on and write our index function and this this will now handle the flow of data so we'll say that the full file name is URL for static and the file name is in the images so that's where we'll be storing and then we want to say if image upload is not empty so we will say if request. method is post that's what we want to handle first then we want to define the image upload to be the request files of image upload so what we're doing here is saying that if there is a post request it expects a file in the payload of that post request and that file will then be stored in the variable image upload so if you go back to what our web app looked once the user clicks browse once they choose the image they want the text extracted from that image will go here into this image upload variable so we want to save the file now we're going to to use the secure file name and say that image upload. file name and then we want to define the file path using the OS join with app config initial file initial file uploads comma file name we'll say that image upload save in the file path so now we want to use the Tesseract app and we'll just use the method we created in our MLP so we want to call call this particular method now and pass it image that got uploaded so we will say that the extracted text is the function so we are calling this function right now if you remember earlier we wrote this line here and this line invokes the usage of this particular function from our ml. P file so we will pass the file path for the image and we want to have the image URL four static we'll give it the file name uploads plus file name and in our return we want to render the template that will be displayed so we want to render the template of our HTML file that earlier we were looking at so it's this particular HTML file and we'll say that the URL is image URL and the full file name is file path and the text is extracted extracted text so we need to pass this back onto our front end and this covers any post request coming towards this endpoint so we have defined this endpoint we mentioned that it will handle get and post requests and the first thing find in our conditional statement here is what happens if there is a post request coming this is the logic for the Post request and our return statement will finish uh processing of our post request but else we want to handle a get request and we will again give the HTML template we want to give file name is full file name and lastly this is just the standard for flask apps just going to copy paste this bit main function for our flask app and you want to write this if double uncore name double uncore is main app. run debug equals true and that's all we need to do so let's try running our app now so I'm going to type in me open this a bit more so we want to write Python app.py and we can see that our app is running live on our Local Host Port 5,000 so we will open our browser and we will type in Local Host give it a 5,000 port and you can see that we have our front end but let's see does it work with the back end so I'm choosing again that image I'm clicking extract and the image is displayed with the text above so everything works as intended and this is our app I hope you enjoyed it and and that's all the first thing you want to do is navigate to my GitHub I'll leave the link in the description and you can find this particular repo we will get the link for it and we can move on into our vs so we will open just open a brand new folder do kit clone paste that link and we can start building together from this exact file system so you can see a couple of files already there and we have to discuss a couple of things that you need before you can run this project so the first things first let's install everything that python needs to run this good practice is to create your own virtual environment so none of your dependencies Clash and we will do that so in this particular folder we can navigate now working folder we can create a new environment so we can save Python and this should create a new environment for us I'll navigate to Powershell but you can activate this any way you really want the inash or Powers shell so going in to to activate it we want to go a second to see we want to go into the script folder now we want to go into VNV first and then scripts so here if we type in activate. PS1 we can activate our environment and as you can see now there's this prefix with the exact name of my environment meaning that now we have activated our environment so just to reiterate for those of you that haven't done this before you type in this particular command to create a virtual environment so this is the command after you run this you navigate into the scripts folder and there you activate by typing in this do/ activate. PS1 so now we will install the pendencies that we need for our project and you can see in this requirements. dxt you have everything listed here so you can just type in want to make sure that we are in the main folder again so we will go back and now we can type in pin our requirements.txt this will install all the dependencies that we need for this project lastly we need to discuss how we will be implementing the AI aspect of this web app so we're going to be using py SCT and now we have install the python wrapper for it but we also need to install the proprietary software and run it on on our machine and the way to do that if you're going to read me I've written some basic explanation on how to do that so we need to install this python wrapper we have just done that so that was us installing with Pip but we also need to install this so navigate to this link and install Tesseract for Windows without this you won't be able to run the program I will include the link for this as well in the description but anyone can just Google testera for Windows installation and it will give you the download option and as soon as it's installed that's it you're ready to go with all the requirements met you can start building this project the next thing we want to do is to make sure that we can run our flask app so we will just prepare the layout for our web app and we can discuss then one by one what goes in which file you will see that as soon as you did git clone you already got this config.py I don't think there is much necessary to discuss here this is just the configuration file for our flask app and you can basically just use it the same way how you see it here here only thing you might want to do different is Define the upload folder the upload file path for yourself so if you remember our app had an option to upload image that will then be giving the text extracted to the display so this will be the folder where those images get uploaded to so you can choose any folder in your documents it's entirely up to you other than that I don't think there's anything necessary to discuss in regards to the config.py page moving on we want to create a app.py and this will be the main file that actually runs our app and all it is all it's going to say from App import app so this will go into the app folder this one here where we will have all the files for our web app and it will just import that into our file here the one that runs backend and we'll say that if name is double uncore main then we just want to run our app that's all we are going to do with this and we will create another file here where we will write the logic for the AI processing but we're going to leave this empty for now and then if you navigate into your app folder you will see that you have another two you have two subfolders static and templates in the templates you'll see in index.html if you open that you will see that there is already pretty much everything done here the reason why most of this is already completed is that I didn't want to focus this particular tutorial on building front end even though we will discuss this front end so that you understand every line of code here so I will guide you through it but I didn't think it would be necessary uh it will be kind of waste of time to discuss every single aspect of this especially talking about CSS and stuff it's not the purpose of this video and then in the static you will see that you have two subfolders images and uploads and this will just manage when we want to upload a picture one of them will go into this particular folder called uploads so as you saw earlier this was the picture that I used for test so it naturally ended up being uploaded into this folder and in the images here I'm just using the logo from my channel this is some you can for the sake of just practicing and building the same app you can use this you don't have to can put anything you want here or you can ignore it entirely you can delete this one that's entirely up to you but that's the brief explanation of our folder structure and with that being said we can start building our app so what we're going to do first is we're going to do the backend logic of our AI processing of the image so we just installed the tesser act and we can start writing the code for for that so this will be our AI model that will take an image as an input and give text as output this is just a brief explanation for it so we'll get an image as an input and the output coming out will be a string derived directly from the actual image so we want to start by pting our libraries for n as NP and to manage images we will import this and just change this back to import so we want to specify the path to the Tesseract executable so earlier I mentioned to you that you have to download the Tesseract software their proprietary software and the way to do that is by going onto the GitHub link when you find the installer the windows installer and once the installation is finished you want to get the path and copy it into this particular variable so most likely it'll be the same as you see it here here if it's not you might have to do some tinkering and find this exact file so this is needed for the program to run you want to save this file path into this variable so we'll write a function that will extract the text parameter for it will be the file path of the image file and it will return a string so like we said the a model will take an image as an input so that's the image path and the output being a string type that's this bit here so we want to say that image we'll use the image library from p and it will open the image path so the variable past in our method and then TCT will do its magic and do image to string from image we want to remove symbols and split by lines for better display so this is just for readability and I've actually produced this just by wearing chat GPT what characters could kind of be problematic in that sense so to manage then this particular idea we want to write this line here moving on we're going to create some distance once again we are with these last last three lines of code we are just working on creating readability in our output and this will just split the lines with a break so if you remember from lithan Basics this character here will create it's like a space line to create some Division and then finally we want to just return text lines so this will be the string output so that's all this this Library pretty much does everything for you and that's how simple the AI aspect of it is and we want to try and test this now and see if this runs properly so we're going to say test and run by saying image path and we want to give the path of the image image so I might just use the one that I had here again so I will go and copy let's try copying relative path so we will give it the path I believe I need to change this to forward sles two just want to test this and make sure that I'm actually printing this so if we do python ml. Prime yes it gives me the correct path to the image as we can see so it's always good to test these things before you actually on your program or something like that uh you catch errors before they become too much to handle so we will then that the extracted text is and then we want to run our function that we just defined here so we can just call the function and give it the parameter of our image path which was this so if we give it that and then we want to just show our extracted text so we can print this particular variable so the extracted text is and then we can just give it a variable so if we try running this now go Arrow so I've just changed the way how the path is given so we want to delete this bit and we'll just give it a DOT to say from the current file from the current directory go into app and I believe this is all we need to do so if we run now we see that we get the extracted text in this particular string so this works now and that's all we needed for our back end we can comment this out and move on next thing we want to do is go into our app folder and we will open templates just to discuss the front end aspect so like we said we will not write this code from scratch I don't think it's necessary for this particular project we can just discuss that it's just a HTML page with some CSS and bootstrap that's all it is using this particular bootstrap there is some CSS that will just give some aesthetic aspects but nothing too complicated you can examine this on your own and play around with it if you choose so closing the CSS aspect we can just talk about what's in the body of the HTML so we have our upload image button and upon submission there is some logic some templating templating that handles how once the image has been processed and we have our text in the form of a string this is just some templating that will handle how it's being displayed and that's pretty much all that it is so without talk if we open this by itself so if you open this by itself just as a file you can see how it looks like I said the upload image element with the browse option for selecting the image the button to extract and then once we receive the output when our backend processes the AI code we have just written it will be formatted here and we want to also display the image that we got the text from so with the front and being sorted like that we can now move on to building our flask app which I believe is the most important part of this video so as you saw the actual AI itself we have tesak doing all the work for us it's a very simple function it just does all the work we don't really have to do more than that so we want to now build our flask app so the first thing we do is we'll create two new files I'll call it views.py and the other one called init with two underscores like such so in this init file you want to import flask and we want to say that our app is flask and then for the configure file we will use the file that you got just from the git repo so we'll say from object and then we will name this file config development like such and we will also import views and that's it that's all you need so the last thing that we need to do to finish off our web app is to write the backend logic in our view section so again we want to import flask an app and we want to request render template and URL 4 and we also want to import OS to handle files I have this recommendation from CH GPT to use this particular Library as a method of dealing with files when changing or modifying file names so we will move on with that we also want to include your typical numpy SNP we again need p and image random string and we want to import our function that we built we want to add the path to config so we say that app config is initial file uploads and we will give it a path so for us that's in our static and we'll write our rout to the homepage the only page that we will be using for our web app and it will include methods both get and post so I am assuming that at this stage you are familiar to at least the basics of HTTP protocol and specifically the four requests that you can make get post delete so the basics of your crowd systems we stand for create read update delete if this line here means absolutely nothing to you I would suggest finding a dedicated video for this particular reason if you want a good understanding of what we are doing here you would necessarily need to completely understand this just to finish off this web app finish off this project but I do highly recommend so that being said we're going to move on and write our index function and this will now handle the flow of data so we'll say that the full file name is URL for static and the file name is in the images so that's where we'll be storing and then we want to say if image upload is not empty so we will say if request. method is post that's what we want to handle first then we want to define the image upload to be the request files of image upload so what we're doing here is saying that if there is a post request it expects a file in the payload of that post request and that file will then be stored in the variable image upload so if you go back to what our web app looked once the user clicks browse once they choose the image they want the text extracted from that image will go here into this image upload variable so we want to save the file and now we're going to use the secur file name and say that image upload the file name and then we want to define the file path using the OS join with app config initial file initial file uploads coma file name we'll say the image upload do save in the file path so now we want to use the Tesseract app and we'll just use the method we created in our dopy so we want to call this particular method now and pass it the image that c uploaded so we will say that the extracted text is the function so we are calling this function right now if you remember earlier we wrote this line here and this line invokes the usage of this particular function from our ml. P file so we will pass the file path for the image and we want to have the image URL for for static we'll give it the uploads plus file name and in our return we want to render the template that will be displayed so we want to render the template of our HTML file that earlier we were looking at so it's this particular HTML file and we'll say that the URL is image URL and the full file name is file path and the text is extracted extracted text so we need to pass this back onto our front end and this covers any post request coming towards this endpoint so we have defined this endpoint we mentioned that it will handle get and post requests and the first thing find in our conditional statement here is what happens if there is a post request coming this is the logic for the Post request and our return statement will finish the processing of our post request but else we want to handle a get request and we will again give the HTML template and we want to give file name is full file name and lastly this is just the standard for flask apps just going to copy paste this bit our main function for our flask app and you want to write this if double uncore name double uncore is main app. run debug equals true and and that's all we need to do so let's try running our app now so I'm going to type in me open this a bit more so we want to write Python app.py and we can see that our app is running live on our local host for 5,000 so we will open our browser and we will type in Local Host give it a 5,000 port and you can see that we have our front end but let's see those it work with the back end so I'm choosing again that image I'm clicking extract and the image is displayed with the text above so everything works as intended and this is our app I hope you enjoyed it and that's all so we will be building this app as you can see it's offering you to download videos and we'll be able to put a link from YouTube and and choosing whether you want a individual video individual audio and you can also download playlists so you can copy paste the link choose your path and you can just click download and it will work so without further Ado let's write some code and see how we build this exact app so let's try to describe how we are going to approach this app so this is some doodling app I've already done here and you can clearly see we have the distinction between back end and front end so we are doing a YouTube video downloader app and we want the app to download YouTube videos songs and playlist We want to have a simple but nice looking GUI that's user friendly so that will be the GUI that we will build with kiwi when I thought about what kind of design to use I'm just going to include some kind of a logo this will be like a Dropbox that will feature four options so to give the user the option to do one video playlist of videos one song or playlist of songs so clearly we want then to correspond each of these four options with these four functions in the back end I just do four of these so this particular Dropbox will include four options and then each of these options will correspond with downloading these one of these four and then we want a file path so it'll be some kind of a browse option will then give file path to where to back end so with this we only now need the link so we can say then that if we have another box here we can say that this will be the link input link for download so with this I know that I can have two inputs from the user one being where the user wants to store the file and the second one being the link of the YouTube video that they want to download or link of the playlist so then we can take this and give it this will go into one of our four functions as a parameter is this drawing yes it is so if you have b in a draw so we will have two parameters on all of the four functions where X will be in this case it's going to get a bit messy but you get the idea the X will correspond with the link and the Y will correspond with the file path so we will pass that on onto our backend functions and uh then we just want to click download and the download should execute the rest of the function so this will be our approach onto our design it's quite simplistic the front end is just a GUI that will give the user the option to choose where to store the file and which file to download and the back end will just have four functions that correspond with the option of the user of what they want out of the download link so with that being said we can move on and create this app in code so first things first we'll import the libraries that we'll be using so we'll use PBE to download YouTube videos I we say from PBE in port list and YouTube When We want to download audio songs we will actually have to convert them so part tube can only download videos from YouTube so if you want to end up with a song out of that video you have to convert it here in Python yourself and we will be using mov pie for that so we'll just import everything from there and we'll import OS to manage the file paths one thing that I like to do for every project is to install the dependencies into a virtual environment just to make sure that you have this project isolated from the rest of your dependencies so we will do that we'll open the terminal I prefer to use Powershell but it's entirely up to you how you do this part so all we want to do is create a virtual environment so we'll do python we do this command so then we will navigate into I believe it's the scripts so we want to navigate into this folder now and activate this environment so we'll do that and will'll do activate I believe yes so you can see we have activated our environment it tells tells us in this prefix that we are in this environment now so we want to start in we want to install the dependencies that we'll be using so the quickest way to do it is to use this requirements.txt and all that we will need is we don't need this for now all that we will need is these two libraries for the back end and we will build our front end with KV so just these three libraries so we'll say pep install this and now when we run this we should be able to see that the libraries are being installed all right until this finishes we can start writing our backend code so continuing this part we will start by defining our class call it YouTube downloader and this will include our four functions so I can just do a layout of our functions so we'll have four of these so we have four functions and will'll pass the self parameter as well as such I want to name these properly so they should be called something that makes sense and then we can just copy paste this we want to name these functions in a way that will make sense to us as well so this one will download a single video the meantime we can see that all of our libraries were installed so I can minimize this for now and continue naming our functions so then we can do one that downloads a playlist of videos we can do one that downloads video as audio so when you want to download a song in MP3 format so we can call this one download video as audio and then in case you want to download a playlist of videos but save them in MP3 format this one can take a link of a playlist and download all of them that's brilliant I think this will be the structure that we use to build our four functions if you remember this is what we had as a plan to have four functions that we will then connect to our front end later moving on we want to start writing our code for our functions so the track for this can be that we try to execute the logic of downloading and if it doesn't work we can pass an error so give it an exception and then print out that error so that we know what went wrong and then we can do this so this is just good practice to make sure that we attempt certain logic and if it doesn't work we get an explanation of what went wrong that being said let's write the download logic so the way this Library work works is that we need to instantiate this YouTube objects and we pass it the parameter of the url url the link of a YouTube video we want to download then we want to select the highest possible resolution if you want to play around with this you can examine the documentation just do some research but that there's no reason for me to go that deep into it at the point at this point I just wanted to download the best quality of Video available so we will Define the file tension here as well and then we can say to this get highest resolution so we want to make sure that we got the link that the link of the YouTube video we want has been passed on through our function so we can print that we can say that the video title is and then here do yt. tile and this will give us the full name then we want to set the save path and the file name so we'll say that in our file name variable we sto the name of the video but we want to make sure that no illegal characters pass on and cause a potential error so I've played around with this earlier and sometimes if you have a particular character written in the name of the YouTube video this program will know how to handle it and it throws an error so I went to chat GPT and I've asked it to think of any possible character that could throw an error and just replace it with an underscore so let me show you what that looks like when I copy paste this part so we are saying that we want to replace this character with that one and this goes on for all these examples you can see pretty much what the point of this is uh you can get this exact line of code or you can skip this part enti high but for me this has ended up working fine so for example there was a video with this character in in the name of it and it gave me an error so this L code will make sure that this character gets replaced with an underscore so you can get this line if you open my GitHub you can take the exact one I did or you can do your own it's completely up to you so now we want to write the logic for the download with this specified file name so we will say stream download and then we'll pass on the save path that we initially gave as a parameter in our function so we'll do output path and we'll say that this is the save path and the will be file name we want to print some context just saved as and we can just say something like save as then the file name and we can also say in the location save path so this is our first function and we can test it now so let's see how this works so I'll minimize this for now to try this function so I'm going to open here on the side just any video a first video that comes out and see if I copy paste the link you will see it in a second so if I if I say that XY Z is this particular link so this is just the YouTube video and I say that XY Z2 this will be my file path so I can try getting this from let's try doing it here so we will create a for here say create this folder test 313 and then we can get this path I believe I need to change this and we will give the name of our folder so now we can try to execute the logic of the first function so we will say download it's within our class so we need to access the class I will choose to download a single video and we'll pass these two parameters the link and the file path so let's see if this works now so if we try running oh so was a an eror so this should be Capital like such say that it's not defin mind oh there as well we should be good now so we run the script and there's another eror let's see why is that the case so this might be because we specified self let me try putting none here and running it now again let's try removing this for now which object has no attribute stream oh this should be streams plural and we can see now that it says it was completed successfully and if I check here we can see that we have this file so something that you can notice is that this file's extension is not defined so at the moment the type of this file is file and I don't want that I want this to be MP4 so we will write some logic now that will take care of that so let's redo this so as as I said we want to add the MP4 extension to the downloaded video the shortest way I thought about doing that is to just use some pure python string manipulation so I will say that the new tension is MP4 so I just want to add this to the end of my file and I already have the save path and the name was file name what was this so I already have the file name and the actual path of the file so I'm just going to say that my separator is the backs slash because I want to construct the file so I want to identify the file and save it in a variable so I'm going to say that the full path is the save path plus the separator plus the file name so this will just identify the downloaded file this particular file and take its path as a string and store it inside of this inside of the full path so we can then check we can write some logic to make sure that this works properly so and say if not o. path exists and then we give the string path of our downloaded file we W know that so we will say the file of file name does not exist simple as that so that's just to catch a potential error and then now we want the new name which will be the old name plus this new extension so we adding this MP4 so we will just write that the new Full path is the old path plus the new extension like this um this might not be the best way way to do it but it works so now we want to actually rename the file and then we can pass the old and the new name that we want which we defined in these two variables and then I like to see that this work so we'll write our file was renamed to and then we can just pass the new Full path so now I'll rerun the exact same test code that we've written and I expect now this same file to be downloaded but this time to be in a MP4 format so we'll rerun the code and there we go it's been downloaded and now it's MP4 so that's really I'm happy with that this works and we can use practically the exact same approach to write the rest of our functions so now we want to do the same but we just want to download no we want to download the whole playlist so that's what we'll do now we'll write the logic for that so it's slightly different in a sense that we will just modify certain bit like here instead of starting with instantiating the YouTube object we need to let it know that we want to download a playlist so we will say download playlist and give it the URL the link that will be passed will be the link of the entire playlist and uh then we want to iterate through the YouTube playlist and just approach downloading each video individually so let me try doing that let me try writing a for Loop that will say for each video URL in the URL no in the playlist object cuz we store that in bable P Brant so in here we'll say let us what video is being downloaded at that moment so we can say just write the name of this and then we will just repeat the same process from earlier technically we could just pass this function now because in this for Loop we'll be doing the exact logic of this first function but for the sake of the video we might just write a l again but everything should be exactly the same let's try doing it that way first actually so we can say YouTube downloader then download single video and then we are passing the video URL and the save path so let's see if this will work once this for Loop iterates through the entire YouTube list we want want to know that it has finished all videos have been downloaded in mp format so let's try this now so as you can see our list downloading is working and we don't need to write the manual code for going through through for iterating through this list we can just use recursion here and we are just reusing this function of downloading a single video that worked fine and now with this we can very quickly write the logic for for the remaining two functions where we want to download a single video a single audio song let's say or a playlist of audios The Only Exception will be now that after downloading a video we will have to convert it ourselves to an audio file say that we want to instantiate this object give it a URL file sorry URL link and print that we are downloading that that particular from and we can say again it's just a title we want to select the best quality available so we can say that YouTube streams only audio is true and we want to pick the first in case that's not available we can print some some logic just to let us know and sorry this goes here so we want to define the output file and say that that's the audio stream which we want to download and we will pass the parameters to let it know where we want to save it which is our save path and we can do a print statement so that we know where the file went now we have to manually convert our file to an MP3 so first we can find the actual file and add it the MP3 tension so this is similar to what we did earlier where we added the MP4 because the p tube will just download type file so now we are manually adding the MP3 extension and after that we can say that converting file to MP3 and our audio clip will be audio file clip of the output file and need to write some more Logic for it is the new file with a codec being MP3 and then we want to close this file C close and then we just want to remove the original that was not. MP3 so we can say OS remove the original file and print conversion complete and just some additional logic this this is our new file and then if something went wrong we have our error so we can try and test that again just creating a folder that can test this going back to YouTube just to copy paste a link for the first video that I see because this is just testing so I'm giving it some random song from YouTube and now we want to download a video as audio we passed the link we gave it the file path of test 313 this folder here so now when we run this we expect to see this downloaded in MP3 we get an error so there's a syntax error at line 51 believe this was or not audio stream yep I put that in the wrong place so that should work now again this being the problem testing now so eror has a so this is the error this should be only no sorry output putut path and it equals save path so now if we rerun This brilliant we see that this function works great so same logic now we will write the function to download a playlist and we can reuse a lot of the same logic from a function that download the playlist of videos so we will go into to that function and in the try again we're doing the same thing we saying to instantiate our playlist object passing the URL of the playlist and then we want to iterate through the YouTube list and the only difference will be that we are not going to run the function to download a single video we'll download the function to download video as audio so let's try doing that and then we can try passing YouTube download downloads video as audio and we will give it the video URL and save path parameters and then if everything goes well we want to say all files convert to MP3 so now we want to test this so you can go on YouTube and find any public playlist to try and test this so I want to run the function for it here so we want to download playlist as MP3 and we can see so far that this is working so everything is being downloaded here and I'm going to stop the code from running further because I can see that everything works as intended and this means that we have just successfully completed our backend so we can delete this one thing going further that I want to add is is the self parameter in all of our functions I deleted it whilst we were doing testing but when integrating with kiwi this might be necessary for me so return the self parameter first and we can close this and continue building our front end so let's do that now so we will be using K to build the guey for this so I'm going to copy paste all the inputs and uh I advise you to do the same if you open my GitHub you can see the full file for front end and just copy paste all the libraries and then we'll we'll continue manually building the code for the rest oh there is another thing that I want to copy paste and I got this directly from the documentation for kiwi so the custom styles using K's builder for around the corners of background Styles like some sort of equivalent of CSS for or kiwi just to give a bit more of a aesthetically pleasing look to the elements that we going to build so by all means please copy paste this yourself so we can start first by importing the backend file that we built so we can save from backend one port and then we can import our class want to import T in D from T we want to report file dialogue now we can choose the primary color for our window we'll just say to get color and this will be white we want to define the class for the styled button and this will inherit from button and now we will start building our G we give it this name it will inherit the from box layout will Define our init method you can take all the parameters and vered the init to all key arguments and we will choose the orientation to be vertical padding L and spacing 10 I've chosen to include a logo from my channel in this GOI it will just be this picture you don't have to do this you can skip this part for the logo but if you want to do something similar just include the name include the picture in your main folder and then we'll just use this name here so we'll say that self logo is the uh image we'll give it the source which is in our folder in our working folder and we'll just Define the dimensions and we'll keep the ratio true and allow stretch true now we will add this as a widget add self logo so we will continue building and we will do a self. spinner and call onto the spinner object and will say that the text is download type so I want to show you exactly what this part is now what we are building so if you remember if we go back to this drawing that I made we made the decision that this button here will be a Dropbox that will give four options each representing one of these functions respectively so we are building this Dropbox here right now and that's the spinner widget in KV so now when you know what it does logically I find it a bit easier to understand the code for it so the multi line will be false now we don't need the multi line we'll give it the values so our fun our four functions for to download a video to download a playlist of videos to download audio or download list of audios call it audios like this we'll give it the size H to be one and 01 and the backround color we can use so for got to add the coma and here and then the last bit will say that the back background normal is an empty string so now we want to add this widget just like we did with the logo so we're doing this but we are adding the URL input so now we want to do the path input with rounded Corners so this will be the box that allows the user to add the path where the file will be downloaded so we'll say that sub. input is text input and this object will have loads of parameters as well so the size hint being one and 05 multiline is false read only is true and the text for it will be enter where you want to download your files file for files doesn't matter and we'll say the background normal is again an empty string and the background color and uh we'll choose be six of these and foreground color will be all ones and lastly we want to add this widget again so we adding the silver path input so I forgot one thing here so this actually is adding the widget for our spinner and then to have our link input we'll do something similar to this we'll Define this to be a URL input this can be smaller this can be 02 and this can be enter the link of the file you want to download and then all of this will be the same and we just want to add this add widget self. URL input just there's no confusion I'm going to zoom out and talk about this for a second so in our class where we are building our gy The Constructor function The Constructor method in it is where you can build widgets and then add them so we start off by creating the putting the logo on top so that's a vidget this is the code for it and then this is the line of code that adds that fidget that we built we build it here we add it here so now that's how you approach it we are building the drop- down box with these options this is where we build it this is how we add it with the add widget line so then when we want to build the box to add the the ability for the user to choose to to put the link of the file they want to download this is how we built it again we are adding it with the add widget option so then we have choosing where the file will be downloaded same thing happens again so we want to add some styling for the for the path button and we'll do that here so zooming in a little bit again so you can see and we can write self PA button is the style button so this object will have the name for the button which is browse size hint will be101 the background color that's color from hex and Del button will bind this that when this button is pressed it opens the self. open file dialogue so this will be outside of this actually and then we are just going to add this fidget so PA button that's great now we want so we added the button that will allow the user to click this option adding the path input and then the button will open the typical a window where you can manually navigate and find the folder where you want to download your file so now we'll add the button for download and we can pretty much use we can reuse this code and we will just say that this is a download button now and instead of browse you'll say download and it will have the same size but we can choose a different color like green color or something like that so we'll remove this I think this is the hex code for for that and the difference now will be that when this is run we want to start download so instead of this we will say self. download button and then oness it will start the download and then we just want to add this widget so say download button like so brilliant so now we want to write the logic for displaying the messages so we'll say that the message is label object we'll give it the size staying consistent with what already we declared we give it color and it can be the same color and just like before We'll add the vidget that WID this built and say self message label now we want to write the function for opening the file and this is the way we choose we give the user the option to choose where to download the file but we want them to navigate through it like the same way how every single file opener works and this is just the code for that that's brilliant so we have this now we will want to write the function that will be attached to our download button the one we mentioned here have self and instance and we can give it some text here I will say that the download type is self spinner text so if you remember the drop down box that we built this is the download type for us and we are giving the the URL of strip and say path path input. text STP and we want to catch an error in case we don't have a URL similarly if we don't have a save file we want to couch that aror too so we don't want the user to be pressing this button the download button if they haven't successfully given a valid link and a valid file path because if you remember a backend featured those four functions of each having two parameters the URL and uh the path where the f will be downloaded so we want to see that downloader is the YouTube downloader and now the final logic is to try if the download type so if that drop down box the choice was to download video let me just see the text for the drop down box so download video playlist of videos so let me have these values handy here so I can just build this quickly like so so we'll do some copy pasting here to save time download audio download playlist of videos and we want to run our downloader object here so we can say and here as usual we want to catch an error and we want to push that error into our messaging and then we can print it here too so in here we can actually write the logic now for download single video with the parameters of URL and save path and we'll do some copy pasting again saving time but we'll choose different functions that correspond with what's chosen here so this will be downloading list of videos so download playlist this will be downloading a single audio and this will be downloading the whole playlist of audio that should be it and lastly we want to do we want to build self return downloader the class that we just defined and we're just adding the last line if this is main then we want to run our app so that should be it so let's try and give this a run so let's see how how our go looks front and py we get an error so troubleshooting another error is the iPhone got to give the correct method here so with the audio type we want to make sure that we choose video as audio the rest should be fine let's try running this error again I think I've identified some of the typos that I've done so the first one being when adding the widget for the path input so the first iPod I found was these two selves here so the delete I found the typo this is a dot it shouldn't be it's an underscore so now we have an error again another typo this is allow stretch but clearly I didn't type it correctly here we are now it actually runs properly so this is our app so let's test it now we can choose the download video we'll give it a link of first link that I found on YouTube we will choose to download it in my test folder so I am choosing that right now you can't see it but when you click browse it will just prompt you with a regular window that allows you to navigate exactly where you want this thing to be downloaded so now going here we press download and we can see that it has successfully downloaded that is wonderful so the app works and that's it I hope you enjoyed it and make sure to have a look at the new videos that will be coming after this one