OpenAI API Chatbot for ChatGPT
Go on an adventure into AI! In this tutorial, you’ll use the OpenAI ChatGPT API to create a chatbot in Android and create your own experience with this user-friendly machine learning technology. By arjuna sky kok.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
OpenAI API Chatbot for ChatGPT
30 mins
- Getting Started
- Opening the Starter Project
- Creating a Chat Messages List
- Displaying the Chat Response
- Talk to Me: Mimic the Back-and-Forth
- Artificial, for Real
- Creating Typing Animation
- Animate Text Output
- Creating OpenAI API Calls
- Messages Overview
- Engage the Bot! (You Won’t Be Assimilated)
- Puttin’ on the Persona
- Chat Completion Mode
- Limits to Your Adventure
- Adding Another Parameter
- Where to Go From Here?
Talk to Me: Mimic the Back-and-Forth
To display the message from ChatGPT, remove the code you added in the ChattingScreen.kt file below the line // TODO: Create dialog boxes
, then add the following code:
val dummyMessages = listOf("Hello, AI!", "Hi, Human!")
LazyColumn(
modifier = Modifier
.fillMaxHeight(),
verticalArrangement = Arrangement.Bottom
) {
itemsIndexed(dummyMessages) { index, messageBox ->
if (index==0) {
UserMessage(messageBox)
} else {
AIMessage(messageBox)
}
}
}
Build and run the project, and you see the following screen:
This looks good. The AI message box is aligned to the left, and the user message box is aligned to the right. They have different colors for the box and message. Both chat message boxes are bottom aligned. This is because of the Arrangement.Bottom
value for the verticalArrangement
property of the LazyColumn
function. Currently, these are merely dummy chat messages that you printed. But you want the user message to pop up after the user types a message, followed by the AI message.
Artificial, for Real
It’s time to add a callback to the chat window button to display the user message.
Remove the code you added below the line // TODO: Create dialog boxes
. Then, replace it with the following code:
LazyColumn(
modifier = Modifier
.fillMaxHeight(),
verticalArrangement = Arrangement.Bottom
) {
itemsIndexed(historicalMessages) { index, messageBox ->
if (messageBox.role == MessageType.USER.type) {
UserMessage(messageBox.content)
} else if (messageBox.role == MessageType.ASSISTANT.type) {
AIMessage(messageBox.content)
}
}
}
You don’t need to use dummy messages anymore. You used historicalMessages
, which is a mutableListOf
. The Message
class itself was defined in ChatModel.kt like this:
data class Message(
val role: String,
val content: String
)
This is part of the payload data you’ll send to the OpenAI API server. If the role
attribute of the Message
data is user
, then it’s the message that the user types. If the role
attribute of the Message
data is assistant
, then it’s the message that comes from the server. The content
attribute refers to the message itself.
So in the button’s callback, you merely need to add messages to the historicalMessages
variable. Add the following code below the line // TODO: Add dialog boxes to the chatting window
in the ChattingScreen.kt:
historicalMessages.add(Message("user", message))
val aiMessage = "Hello! This is an automated message generated by an AI assistant. I'm here to assist you with any tasks or inquiries you may have. Please let me know how I can be of assistance!"
historicalMessages.add(Message("assistant", aiMessage))
You added the message to historicalMessages
and then added an AI dummy message to historicalMessages
to simulate the reply from ChatGPT.
Build and run the project, then type something in the TextField
before clicking the button. When “Hello, AI!” is entered into the TextField
and sent, Chatty Bot sends the dummy message in response, and you see a screen that looks something like this:
Creating Typing Animation
Before creating calls to the OpenAI API server, you’ll enhance the appearance of the ChatGPT response. If you’ve used ChatGPT, you’ve noticed that the reply doesn’t show up instantly; it’s presented as if ChatGPT is typing the text to you.
You’ll use LaunchedEffect
to achieve this same type of animation on the Compose function. To create the animation, you need to think of two texts. The first one is the complete reply text from ChatGPT. The second one is the partial text. At the beginning, the partial text is empty. Then, after a delay, the partial text is the first character of the full text. Then, after another delay, the partial text is the first two characters of the full text. This process continues until the partial text becomes the full text.
Put this process inside the LaunchedEffect
. The partial text and the full text have been set up for you. They’re the partText
variable as the partial text and the addedString
variable as the full text.
Delete the lines of code you added in the ChattingScreen.kt file below the line // TODO: Create dialog boxes
and replace it with the following code:
LazyColumn(
modifier = Modifier
.fillMaxHeight(),
verticalArrangement = Arrangement.Bottom
) {
itemsIndexed(historicalMessages) { index, messageBox ->
if (messageBox.role == MessageType.ASSISTANT.type && index == historicalMessages.size - 1) {
AIMessage(partText)
} else if (messageBox.role == MessageType.USER.type) {
UserMessage(messageBox.content)
} else if (messageBox.role == MessageType.ASSISTANT.type) {
AIMessage(messageBox.content)
}
}
}
Animate Text Output
It’s the same response as before, except for the last message. If the message comes from ChatGPT, you want to set the content with the partText
variable. To update the partial text so it becomes the full text, add the following code below the line // TODO: Add the animation of typing text to the dialog box
:
addedString.forEachIndexed { charIndex, _ ->
partText = addedString.substring(startIndex = 0, endIndex = charIndex + 1)
delay(50)
}
Here, you update the partText
variable by getting a substring of the full text, addedString
. You add some delay to create the typing simulation.
Last, you need to set the addedString
variable with the dummy reply message from ChatGPT. Go to the line // TODO: Add dialog boxes to the chat window
and add the following code below the declaration of the aiMessage
variable:
addedString = aiMessage
Build and run the project, then type a message before clicking the button. You see the typing animation:
If you look at the LaunchedEffect
code, you notice there’s the key argument key1
:
LaunchedEffect(key1 = addedString) {
addedString.forEachIndexed { charIndex, _ ->
partText = addedString.substring(startIndex = 0, endIndex = charIndex + 1)
delay(50)
}
}
LaunchedEffect
is a one-time event executed after the Compose UI is ready and the key arguments change. In the code above, the key argument is key1
. If the key1
argument that tracks addedString
changes because the OpenAI server sends a reply message, the animation is triggered. So if another reply message changes the key1
argument, it will trigger the animation again.
Creating OpenAI API Calls
Until now, you created dummy messages because your focus was on the UI. It’s time to display reply messages from ChatGPT. But first, you need to get the API key from OpenAI. Go to here to grab your OpenAI API key. Then, put it on the Settings screen and click Save:
To create an API call to the OpenAI API server, the URL is https://api.openai.com/v1/chat/completions
and the content type is JSON. Next, put the API key in the authorization header.
No coding is required regarding this. You can find the URL in the BASE_URL
variable that has the value https://api.openai.com/v1/
in the ChatRetriever.kt file. The baseURL
method of Retrofit.Builder
uses the variable’s value.
You’ll find the rest of the API URL, chat/completions
, in the annotation of the getChatCompletions
method in OpenAIService
. The JSON content type is also set here.
But what JSON payload do you need to send to the OpenAI API server? You’ll send a JSON object that has several keys, like model
and prompt
. An example would be:
{
"model": "gpt-3.5-turbo",
"messages": [
{"role": "user", "content": "Hello AI!"}
]
}
That’s the basic message you need to send to the server. You’ll use the GPT-3.5 model because that’s the most popular one available to the general public, though as of this tutorial’s completion, OpenAI is releasing the GPT-4 model. However, due to high demand, OpenAI is granting access to the GPT-4 API model at a measured pace. The GPT-4 model has a more extensive knowledge base and an enhanced ability to reason, but it’s more expensive.
If you want to use the GPT-4 model, change the "gpt-3.5-turbo"
string to the "gpt-4"
string in ChatRetriever.kt
.