AI ChatBot Mini App Overview (AI Chat Example)
This Mini-App is a simple GPT-4o-powered API wrapper that allows the user to interact with the AI chat-completions model (opens in a new tab) in a chat-like interface.
Features
- Chat Interface: A simple chat interface that allows the user to interact with the AI model.
- Chat History: The mini-app uses AuthKit and DBKit to allow the user to log in and automatically store the chat history in the cloud database, even if he quits the app and comes back. The user also has the ability to delete their chat history.
- AnalyticsKit Integration: If AnalyticsKit is selected during project generation, events and errors regarding user
interacting with the AI ChatBot mini-app will automatically be tracked with
aikit
as the source (both client-side and server-side).
Demo
Here's a demo of the AI ChatBot Mini-App in action:
Implementation
For this example, we have create multiple endpoints on our Backend for the client to interact with.
Fetching AI Chat history
When the user opens the AI Chat mini-app the client will first fetch the chat history from the backend.
// front-end
extension DB {
public func fetchAIChatHistory() async -> [AIChatMessage] { /* ... */ }
public struct AIChatMessage: Identifiable {
public let id: String // id in database
public let isFromUser: Bool // true if from user, false if from GPT
public let messageContent: String // the actual message
public let timestamp: Date // when the message was sent
// init using raw data from the endpoint
init(from rawData: [String: Any]) throws { /* ... */ }
}
}
The fetchAIChatHistory()
function call the backend enpoint retrieveCurrentUsersAIChatMessages()
and will
return an array of AIChatMessage
objects, which will be used to populate the chat interface.
This retrieveCurrentUsersAIChatMessages()
endpoint retrieves the currently logged in user's chat messages from the database (at path /users/USER_ID/AIChatMessages/
).
If the user is not logged in, it will throw an error.
// back-end
export const retrieveCurrentUsersAIChatMessages = onCall(async (request) => {});
On success, it will return an array of type AIChatMessage[]
which will then be converted to a client-side AIChatMessage
struct:
// back-end
type AIChatMessage = {
id: string; // id in database
isFromUser: boolean; // true if from user, false if from GPT
messageContent: string; // the actual message
timestamp: string; // when the message was sent (ISO STRING)
};
Sending a new message and receiving a response
When the user types a new message in the interface and sends it, the client will call the sendNewAIChatMessage()
function, which will send the message to the sendANewAIChatMessageForCurrentUser()
backend endpoint, which will
take the chat history, add the message, send it to the GPT Chat Completions model, and return the result.
The result will be an array of two AIChatMessage
's - the sent message and the response from the AI model. We will append both messages to the chat interface.
The resulting history is then also saved in the database. (Path is /users/USER_ID/AIChatMessages/
)
// front-end
// see AIChatMessage struct declaration above
public func sendNewAIChatMessage(text: String) async -> [AIChatMessage] { }
// back-end
import * as AI from "./AIKit/AI";
// ...
export const sendANewAIChatMessageForCurrentUser = onCall(async (request) => {
// ...
const response = await AI.accessGPTChat({
text,
previousChatMessages: chatHistoryInGPTFormat,
});
// ...
});
The endpoint calls a pre-made AIKit function accessGPTChat()
that sends the message to the GPT-4o model and returns the newest model response.
// back-end
import OpenAI from "openai";
import { openAIApiKey } from "../config";
const openai = new OpenAI({
apiKey: openAIApiKey,
});
export type GPTChatMessage = {
role: "user" | "assistant";
content: string;
};
export async function accessGPTChat({
text,
previousChatMessages = [],
}: {
text: string;
previousChatMessages?: GPTChatMessage[];
}): Promise<string | null> {
const response = await openai.chat.completions.create({
/* ... */
});
return response.choices[0].message.content;
}
Deleting the chat history
Users also have the ability to delete their chat history. This is done by calling the deleteAIChatHistory()
function on the
client side, which will call the clearAIChatHistoryForCurrentUser()
endpoint on the backend.
The client-side function and the backend endpoint both return a boolean value indicating if the deletion was successful.
// front-end
extension DB {
public func deleteAIChatHistory() async -> Bool { /* ... */ }
}
// back-end
export const clearAIChatHistoryForCurrentUser = onCall(async (request) => {});