📦 SwiftyLaunch Modules
✨ AIKit
AI Chat Bot Mini-App

AI ChatBot Mini App Overview (AI Chat Example)

AIKit (SwiftyLaunch Module) - 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.

BackendFunctions.swift
// 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.

index.ts
// 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:

index.ts
// 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/)

BackendFunctions.swift
// front-end
// see AIChatMessage struct declaration above
public func sendNewAIChatMessage(text: String) async -> [AIChatMessage] { }
index.ts
// 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.

AI.ts
// 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.

BackendFunctions.swift
// front-end
extension DB {
    public func deleteAIChatHistory() async -> Bool { /* ... */ }
}
index.ts
// back-end
export const clearAIChatHistoryForCurrentUser = onCall(async (request) => {});