Enhance your Flask applications by integrating Jinja templating to dynamically display AI-generated content. Learn how to effectively parse and render JSON responses from OpenAI's GPT-4 model directly onto your HTML pages.
Key Insights
- Implement Jinja templating within Flask to dynamically insert AI-generated responses into HTML pages using double curly braces syntax (
{{ AI answer }}
). - Request and process JSON-formatted responses from OpenAI's GPT-4 API, parsing the JSON string into a Python dictionary for streamlined data handling.
- Utilize Flask's
render_template
method to pass server-side variables, such as the AI-generated response, directly into HTML templates, facilitating automated and dynamic web content updates.
Note: These materials offer prospective students a preview of how our classes are structured. Students enrolled in this course will receive access to the full set of materials, including video lectures, project-based assignments, and instructor feedback.
This is a lesson preview only. For the full lesson, purchase the course here.
Next up, the Jinja templating engine for dynamic HTML. We're going to use a Jinja templating engine to add dynamic content to the HTML page. And we're going to request our JSON, we're going to request that our AI answer us in JSON format.
We're going to add a Jinja variable in the HTML using this syntax with the double curly braces. We'll explain exactly what that all is. And then when we render template, we're not only going to render the HTML page we want, but we're going to also pass in a variable from Flask to the HTML where the value of it will render.
And that will be the AI's answer. So Jinja is a so-called templating engine, which means it's used to populate HTML pages with dynamic content that's generated server-side, namely in our case, our AI's answer to our questions. So let's display the AI's response text in an HTML page.
Remember last time, we got our Grand Slam question answered, but we just outputted raw text to the browser. And we know how to render an HTML page anyway with render template. So that part should be pretty smooth.
We're going to up it a notch this time. We're not going to just render the template like I just was saying. So it's going to be HTML page and then variable.
That's the syntax. You're passing in not just the HTML page to render. So let's say index HTML.
But it's also going to be your variable like AI answer, which would be equal to your AI answer. I don't usually put a lot of code in the little summary here, but this is important. We know we've got, we've seen this, right? We've done this render template where you render, you pass the name of the HTML page that you want to render.
But this time we've got a second argument that we're passing in, an optional argument. Do you have any variables that you would like to send to that HTML page? And if you do, you know, you set, you declare the variable, set the value to be the variable on your server-side. They don't have to be the same name, but we want to, basically what it means is we want to have in our HTML this variable.
And the way you render it on the HTML is you wrap it in double curly braces. Okay. We're going to see all, we're going to do every bit of it.
You can read more about Jinja here at this link, the Jinja templating engine. Again, it's a way to dynamically populate web pages with HTML. We're going to make the next server file, server 03, keeping the numbering, matching the lessons.
So from server 02, do a save as and call the new file server 03. Let's go ahead and do that. Let's close this stuff that we have open.
We don't need all those files open. Server 02, file save as, server 03. And now from index one, because lesson two, where we did our grand slam question to the API, we didn't have an HTML page for lesson two.
We just had raw text in the browser because our primary focus, of course, was establishing that connection and getting the response from the OpenAI API. We didn't even want to have a webpage to, you know, almost as a distraction in that sense, right? It was just all about, can we get the AI to answer our question? And then we'll be perfectly happy to just dump that text response in the browser. But now we want to get back to taking the open, rendering a webpage in the browser.
And this time, including the AI's response as a dynamic variable into that webpage. So because we didn't have a webpage for the last lesson, when we save as index one, we're going to skip right to three. There is no index two, therefore.
In case you're wondering, where's index two? It doesn't exist because we didn't have one in lesson two. We want to keep the numbering in sync with the lesson numbers. Now we're going to change the h1 and drop in a p tag in our HTML page.
So welcome to Python. We'll just say AI. What do we want to, what did I say to call it? OpenAI response text.
Great. Open, OpenAI GPT4 little o model. Here we'll write more.
OpenAI API GPT4 little o model response text. There you go. And take that out.
We'll dump the h, we'll just put it in a p tag, right? We don't want to have, we don't need this, you know, we don't need the AI's answer to be this huge thing of text. The Jinja templating engine syntax, as I was describing a moment ago, involves adding dynamic variables to HTML. The vars go inside double curly braces.
So double curly, whatever the var name is. We want to output the AI's answer to our question inside the paragraph tag. We're going to call the variable AI answer.
So this is what we want. We're going to come, staying in our HTML, we're going to say double curly braces AI answer. So this means that in the Python file, the Flask server file, we're going to have a variable called AI answer that we pass to the render template method.
So it'll come in to the HTML page that's also being passed into that render template method. Like so. Render template, right? We'll take the file you're rendering as the first argument, and I'll take as the second argument the variable that you're passing in and the value of it, which may or may not be the same thing.
Style the p tag. I guess. Sure.
Let's style the p tag. Oh, we already have. No, we don't already have it.
Okay. I'm not going to make you write all that. You can just copy paste that stuff.
If you would like to write all that, by all means, go ahead. Maybe later or pause the video now or something, and then just hand type all that if you want the practice with CSS. Not for part of the text, though.
And it even says here, like, there's almost no parts of the whole book that say to copy paste anything. I think that this might be the only time. All right.
Anyway, we're going to render the HTML page and pass in the dynamic data. So in server 03, we're going to import JSON. We already have open AI, and now we need JSON.
Import JSON. And we don't have it in here because this is a this is a save as off of server 2. It was the server 2 lab that had the JSON last time. We're going to specify JSON as the response format inside our create method, which is also what we did in the lab last time.
Response format equals an object. Key is type. Value is response format.
Response object, rather. No, excuse me, excuse me, excuse me. Okay.
Right? JSON. Yep. JSON object.
Underscore, right? Everywhere. That's what Python does. No camel casing in sight.
So rather than return the response directly, right, just dumping text out, we're going to save it to a variable called AI JSON. We don't want to save the response as response when the response is this big, long thing, and all we're doing is grabbing the content, which is actually the AI's answer, JSON. Okay.
AI JSON. Yeah. We don't want this.
You can leave it as a reference. We're going to say AI JSON equals response choices, et cetera, like that. So whatever we get back from the AI, we're going to unpack it, and it's going to be a JSON string.
And again, we can print that to the terminal like we did in the lab if we want. So sure, why don't we do that? It would be a string. Because JSON is a stringy object, stringy dictionary.
Next, we're going to modify the content prompt to request the AI answer as JSON. Right? We have that in our lab, too. We're going to take that and copy it.
We're kind of double specifying JSON, right? We've got it here telling it we want JSON, and we're telling it the names of the keys that we want, describing how the keys are to be populated. But then we're also specifying, setting this response format as JSON, too. We're going to pass the response JSON loads.
We're going to save so this is going to come in as AI JSON. We're going to take the AI JSON, pass it to loads, and we're going to get AI dictionary. And the AI answer, now we're going to extract just the AI answer.
Right? We're going to look up in the dictionary, it's got two keys, we're going to square bracket long answer is the dictionary key, which returns the value, which will be the answer, the text. Now we're going to render the template, which is index 3. We're going to say this is what we're returning, by the way. We have to have a return value.
Return render template. We'll say return index return a call to render template with index as its argument. Right? That's basically what we're doing here.
Index 3. Let me fix these little curly quotes. There we go. Pass the AI answer variable, set equal to itself to render template as its second argument.
In index 3 HTML, the AI answer variable will be available. We already have it there, ready to render as double square bracket, double curly's AI answer. So there's the AI answer variable we're passing in, the value of which is the AI answer, which is the value of the long answer from the AI dictionary, which we parse from the AI JSON, which is the response exactly as we asked for it.
So, game on here. Okay. Return, that comment would be good for that.
I'll put a little comment for that here. Okay. Return render template index 03.html, comma, AI answer equals AI answer.
Oh, skipped a step. Oops. Oh, yeah.
Nope. Here. Save the text, the JSON portion of the response as AI JSON, and then pass that through the JSON loads method, saving the parse JSON as JSON dictionary.
Okay. Yep. Better get it right.
Okay. So, that's the JSON answer unpacked, drilled into an unpacked. But it's still a string, right? Here.
Log the data types of AI JSON string and AI dictionary. So, for that, that's a long, that could be two steps, but oh well. Okay.
All right. Oh, okay. Print.
Whoa, why did it, why is it all messed up now? So, print data type of AI JSON. And that is a string because JSON is a string type AI JSON. And the dictionary that we parse out of that is a dictionary.
That will be a string. That will be a dictionary. Bloody, that's a really long number.
But it's okay. We've already done one of these in the lab, so I'm combining it. Save the long answer to a variable called AI answer.
There you go. Return a call to render template with index 03 as its argument, as its first argument. Pass the AI answer variable set equal to itself to render template as its second argument.
In index 03 HTML, the AI answer variable will be available, and we already have it in there ready to render as AI answer double curlies. So, we have that. Let the code breathe a little bit.
That's fine. Run the app. Let's make sure we have all these steps.
Okay. So, now, parse the JSON string into a dictionary. So, this is mostly the same.
We're going to say AI dictionary equals JSON.loads, AI JSON, AI dictionary, AI dictionary, dictionary. And now, next, save just the long answer to a text to a long answer, which is a string to a variable. That will be AI answer is going to equal your dictionary long answer.
And then we can pass that with index 03. And return a call to render template with index 03 and AI answer as the two arguments. That ought to do it.
Quit the server by typing boom and start a new server. Control C, new server. I don't even think we have a server running.
So, oh, we do. Okay. Control C. Python server 3.py. All right.
Now, when we go to the browser and look, it should hit the route, the home route, right? Still the same home route. It should send the request, the question, the query, the prompt to the OpenAI API, more specifically to the GPT-4.0 model and store the response in this object here. We're going to then drill into that object until we get all the way down to the actual content, which is a JSON string.
I'm going to save that. Log its type. Make sure it's a string.
We're going to see the prints, rather. The print statements are going to appear in the terminal. Then we're going to parse that JSON string into a usable dictionary.
Print that data type. And we know that the dictionary has two keys, two key value pairs, a short answer and a long answer. Because we asked for that.
So, just the long answer as text. And then we're going to return render template, which allows us to publish a whole webpage to the browser as opposed to just blobs of text. So, in that whole webpage, we have a tag set up in index 03.html. The AI answer text will appear in DoubleCurly's AI answer.
There you go. And if it all fails, you get an error. Okay.
Let's see. Run that again. What's going on? Control C. Keyboard interrupt.
Save. Control C again. Okay.
I'm going to trash this instance. Control C. There we go. Run it again.
Okay. So, now when we go to the browser and refresh, we should see the long answer to the Grand Slam question, but inside a webpage, inside a P tag, as opposed to just dumped loose. Here we are.
Sending. Spinning its wheels. It's sending it.
Spinning its wheels. Oh, there you go. There it is.
It's in the P tag. Not too shabby. Refresh the browser and this hits the home route where our chat prompt with Grand Slam questions sent to the AI.
After a brief pause, the AI answer, after a brief wait, the AI answer should appear inside the paragraph tag. And you could have a nicer screenshot, really. Let's have a nice screenshot there.
I don't like the word text dangling like that. I'm going to take it out. AI model response.
Question. Okay. Basically, that's our question.
May as well show the question, right? You might want to add that little context, right? Send it again. Let's even make it look a little more AI-ish-y. We'll say AI answer.
There you go. We can make this an H3. Nah, we'll leave it as a P tag.
That's cool. Okay. Maybe a strong tag.
Why don't we do that? Just bold the text, the question. It's just cosmetic. I want to make a nice screenshot, though, so go forth and answer my question.
AI answer. Sure. Maybe bold.
So you can just sit here and edit your text. Resubmit. Save.
Refresh. Screenshot. All right.
We've got all this room. At the end of the lesson, let's drop in a screenshot. Absolutely.
Okay. Finito. Final code for the lesson.
We're not calling the response that. We're calling it AI JSON. Then we also have AI dictionary equals AI JSON.load AI.
Excuse me. JSON.loads. That loads AI JSON. Then we have AI answer equals AI dictionary long answer.
Then we're going to return render template the AI answer. We need to import JSON, which we're doing. Try.
Roll. System. Content.
You are a helpful assistant. User. What is a grand slam? I left out the print statements here.
Oh, let's make sure the prints are working. Are we getting the print statements? Sure, we are. AI JSON data type, AI JSON string.
Not just put the front-end, right? Let's put this, too. Final code. Yep.
Yep, yep, yep. That's good stuff. All right, guys and gals, we're on to the next thing.
Have a go at it. Should be good.