Discover how to integrate OpenAI's API into a JavaScript and Python chat application, building a real-time conversational experience. Learn to seamlessly pass chat data between Flask, JavaScript, and OpenAI to maintain context-rich interactions.
Key Insights
- Implement JavaScript fetch to send user messages along with the conversation history as JSON data to a Flask server, which then communicates with OpenAI's API to return AI-generated responses.
- Maintain synchronized conversation storage using parallel data structures: JavaScript arrays and Python lists, ensuring both client and server maintain accurate and complete conversation context.
- Create a robust Flask route named "chat with AI" to handle incoming JSON requests from JavaScript, process and append these messages to the conversation, interact with the OpenAI API, and return AI responses back to the JavaScript frontend.
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.
Hi, welcome back to this Python for AI apps course. My name is Brian McLean. We're onto Lesson 10, where we're going to be chatting with the OpenAI API for real from that Greenleaf Tree Nursery website.
So let's get going. We're at the beginning of Lesson 10. We're gonna use JavaScript fetch, which will send chat data as JSON to the Flask server.
That chat data will be the user chat data, chat message. Flask will append the new user message to the conversation list. We're gonna have this array in JavaScript corresponding to a list.
We're going to have an array in JavaScript and a corresponding list by the same name in Python, where we're going to be storing the entire conversation. So every time the user says something to the AI or the AI answers, we have to add that, append that, push that into the conversation list or array. In JavaScript, we call it an array; in Python, it's a list.
Flask will then send the entire conversation list to the OpenAI API. The API needs context. You can't just give it the last question.
You need all the questions and all the answers. The OpenAI API will return the AI's answer. We're gonna append the AI's answer to the conversation and return that answer with the full conversation in JavaScript.
The JavaScript array over there will update itself to match, so the conversations have the latest content on both sides—in JS and in Flask. We're gonna update the chat window with the AI's latest answer in a chat bubble. We're gonna do a save as of the last file, which is the Greenleaf Tree Nursery AI chat assistant.
So index nine is to be saved as index 10, and then in the bottom, the script will become 10 as well. They're gonna have a matching JS file. Change the scripting import to 10 and do a save as of script nine and call the new file 10.
Script nine, save as 10. 10. Now in 10, make a JS array for storing the entire chat conversation.
Yup, and more and more. We're gonna change the name of the function that the button is calling to Chat with AI. It's not just chat—Chat with AI.
So the button's calling function, you have to do it twice, right? The button listener and the actual function. In script 10, above the Chat with AI function, declare a new empty array called conversation. This is for storing all user and AI chat messages.
Array for storing entire convo. We'll say let conversation equal a new empty array. And again, in JS, an array is what you'd call a list over in Python.
Remove the—rename the chat function. I already did that. Request—we're gonna change the request to Chat with AI. Inside the Chat with AI function, rename the fetch route to Chat with AI.
So I'll be down here, right? Chat with AI—that's the name of the Python route we have to write later that we're sending our user chat message to. Add the request array to the object. The first time fetch runs, it will be an empty array, but it will get longer with each round of conversation.
So you're sending over, as a request body to Flask, the latest user message, as well as the entire conversation. And it's going to be over in Flask where the new user message is added to the conversation. That won't be happening here in JS.
Just get the conversation with the user message over to Flask, and Flask will add the user message to the conversation and then send that to the OpenAI API. Handle the response.
So imagine it did all that stuff over in Flask. It got the incoming and it sent it to the OpenAI API, got the AI's response, fed it back to us. That's where we're gonna be at, right? Because we're not gonna just bounce over to the Flask file right now.
And stay here—finish out the JS. You're gonna get this classic line every time. It's your JSON coming in with your parse.
And we can just change the name. We'll call it AI JSON instead. We'll leave it the same exact name.
It's response JSON, but we'll call it AI. Then we're going to take the parsed object and send it to the next callback. And that object is gonna have two accessible properties: AI message and conversation.
So the next then is gonna be the AI object, which we need to do the same stuff from before. We need to make the chat bubble. Make a chat bubble to hold the AI's answer text.
Assign the chat bubble's class and background color, which will be this pale green. It puts the message in the bubble or else it gets in trouble. Output the AI chat bubble to the chat window.
This is what we did before as well, in the last previous lesson. Update the conversation array now, which, coming in from Flask, has a new AI message and the most recent user and AI messages. It actually has this conversation update right here where we take the incoming conversation and set it equal to the incoming conversation from Flask and set it equal to the JS version to make them the same.
It's two things coming over that are being added new—the user and the AI's answer. Update the conversation. We're gonna say conversation equals AIMSG.conversation. Run your standard error catch thing, which we have.
Clear the input, auto-scroll to the bottom, which we've done. We don't have to mention those because there are no changes. We're gonna now make a new route for the AI chat.
We will base our server code on Server 4 because that's where we actually had a chat going in the terminal with the AI. Remember we were asking questions, and it was coming out in the terminal. The fetch will be hitting the Chat with AI route, which we're specifying in fetch, and Flask will then have to have that route.
Flask will be sending the user's message to the OpenAI API, and then will return the AI's response back to JavaScript, thus completing the round-trip chat. So from Server 4 now, file save as, Server 10, boom, boom, boom. We need to import Flask, render_template, request, and jsonify.
We need Flask, render_template, request—that's for handling the incoming JSON from fetch—and jsonify for JSONifying what we're gonna send back to the fetch route, the fetch request in JavaScript. So this is a bit—you'll see this requesting is a little bit new. We have to make a route that returns index 10.
We already have an index route. No, we don't. Oh, no—no, we do not from 4, right? We're going to say route, home route index return, render_template index 10.
Okay. Make a route called Chat with AI. The fetch method will request this route, whose Chat with AI function communicates with the OpenAI API.
We will assign the route a Chat with AI function for interfacing with the OpenAI API. So Chat with AI method is POST. Route: Chat with AI. Chat with AI method is POST, because it's gonna be getting stuff coming in.
It's receiving incoming from fetch. In the Chat with AI route, extract the incoming JSON. Extract the user message and conversation from the incoming JSON. The syntax request.get_json parses the incoming JSON, one property at a time, as the request body.
Each incoming property value is saved by setting the key to a variable. Def chat_with_ai, request_json = request.get_json().
User_message = request_json.get("user_message"), conversation = request_json.get("conversation"). Oh, it's request_json.get, yeah. Doesn't say body.
It is a request body though, okay. Add the new user chat message to the conversation. If the conversation is new—has a length of zero—start with a system prompt, however.
So, we're gonna run this little script. If the—I'm just gonna copy it, 'cause it's a little—well, I'll write this part. If len(conversation) == 0, so if the conversation has no length, the conversation is new—start with a system prompt.
If len(conversation) == 0, conversation.append. We're gonna append the role: system, and the content—it's a little bit longer. We'll grab these instructions. This prompt: You are a Customer Service Assistant for Greenleaf Tree Nursery, a tree nursery website that sells saplings, seeds, and gardening accessories.
That's being appended or added to the end of the conversation. The conversation is new, but only if it's a new conversation, right? With a length of zero. Append the user's chat message to the conversation using the same dictionary format with role and content properties.
So, now we're gonna unconditionally append, right? Whether it's a new or ongoing conversation. We're gonna say role: system—role: user, rather—content: user chat message. That's the incoming message.
It's called the user message. We call it the chat message—user chat message. We call that user chat message.
No, just user message. I'm calling it AI message. Don't go changing these, yo.
Why would you do that? You wouldn't. User message. User message.
Leave it alone. All the code's written that way, in the book, everywhere. Append the user's chat message—done.
Okay. Call the function that connects to the AI API. We're gonna call our sendConvoToAI function.
It's actually called Chat with AI function. But we need to change it. We already have a Chat with AI function.
We're gonna change it. Change. Dude, I shouldn't have called it that. I should've just called it chat.
I know—we could leave this with Chat with AI. Eh. All right, I'm gonna put it back.
Chat. I don't wanna change the name of this thing. It's perfect.
Okay. So, yeah. That's a conversation.
Let's not change that either. Okay, here we go. AI message.
I'm gonna get to the—all right. I'm getting ahead of ourselves a little bit. Okay.
So, here. We've got this Chat with AI function. It's all set up, ready to go.
I don't wanna change the name, and I've already used the name here in the route. So what we're gonna do is just go back to chat for the name of that function. I think that's reasonable.
It's not too hard to do that. You just go back, call this chat like it was. Keep it simple.
We already—you know. Chat with AI is gonna be the one that actually goes to the AI, which this doesn't. Okay.
Chat. Chat. Chat function.
This does not interface with the AI—with OpenAI, actually. No, it doesn't. It calls something that does.
This just handles routing back and forth between the webpage and the server. It's not the direct call.