Great work so far! In this video, we'll begin to unleash the full potential of chat models by creating multi-turn conversations. Recall that messages are sent to the Chat Completions endpoint as a list of dictionaries, where each dictionary provides content to a specific role from either system, user, or assistant. For single turn tasks, no content is sent to the assistant role - the model relies only on its existing knowledge, the behaviors sent to the system role, and the instruction from the user. Providing assistant messages can be a simple way for developers to steer the model in the right direction without having to surface anything to end-users. If we created a data science tutor application, we could provide a few examples of data science questions and answers that would be sent to the API along with the user's question. Let's improve our data science tutor by providing an example. Between the system message outlining the assistant's behavior and the user's question to answer, we'll add a user and assistant message to serve as an ideal example for the model. We add a user message containing a question on a similar topic and a response that we consider ideally written for our use case. The model now not only has its pre-existing understanding, but also a working example to guide its response. With an example to work with, the assistant provides a succinct and accurate response that's more in-line with our expectations. Another common use for providing assistant messages is to store responses. Storing responses means that we can create a conversation history, which we can feed into the model to have back-and-forth conversations. This is exactly what goes on underneath AI chatbots like ChatGPT! To code a conversation, we'll need to create a system so that when a user message is sent, and an assistant response is generated, they are fed back into the messages and stored to be sent with the next user message. Then, when a new user message is provided, the model has the context from the conversation history to draw from. This means that if we introduce ourselves in the first user message, then ask the model what our name is in the second, it should return the correct answer, as it has access to the conversation history. Let's start to code this in Python. We start by defining some base messages, which can include the system message and any other developer-written examples. Then we can define a list of questions. Here we ask why Python is popular and then ask it to summarize the response provided in one sentence, which requires context on the previous response. Because we want a response for each question, we start by looping over the user_qs list. Next, to prepare the user message string for the API, we need to create a dictionary and add it to the list of messages using the list append method. We can now send the messages to the Chat Completion endpoint and store the response. We extract the assistant's message by subsetting from the API response, converting to a dictionary so it's in the correct format, then adding it to the messages list for the next iteration. Finally, we'll add two print statements so the output is a conversation between the user and assistant written as a script. We can see that we were successfully able to provide a follow-up correction to the model's response without having to repeat our question or the model's response. You've learned about the key functionality underpinning many AI-powered chatbots and assistants - time to begin creating your own!