Create your first app using ChatGPT

In this tutorial, I will show you how to create an app called the Rephrasing App. The app that you are going to build has a simple UI written in React, uses the ChatGPT API and is deployed on genezio.

It will have two main components: the frontend which will consist of a simple chat-like interface, and the backend which exposes a function meant to rephrase your input text. Once implemented, the Rephrasing App can be used to rephrase text, write better articles or even upgrade your CV.

Prerequisites:

Introduction

ChatGPT and genezio

Since you are reading this, I assume you already know what ChatGPT is and how it works at its core. But how do you actually use it to build a working and useful app? Is it enough to call the API directly, or do you need to write other functions as well? How and where do you host it? I will work alongside you towards finding out the answers to most of these questions until the end of this article.

When deciding where to do the calls from, you have to keep in mind how secure you want this to be. So, as it is smart not to do them from the frontend, you are going to use genezio to host the backend and to call the OpenAPI from the genezio functions. For you to create a clearer idea about how this works, take a look at this illustration:

Street Art Image

Now, let’s dive in! You can find the complete project here .

Configuration

Get the API Key from OpenAI

  1. Go to the OpenAI website and create an account.

Street Art Image

  1. Go to platform.openai.com/account/api-keys

  2. Click on the “Create new secret key” button.

Street Art Image

Note: Remember to keep your API key secure and do not share it with anyone.

Set Up genezio

First, install genezio using npm:

npm install genezio -g

Then, use this command to log in:

genezio login

Create a new project folder:

mkdir chatgpt-project && cd chatgpt-project

In this folder you will add 2 more folders: client_chatgpt and server_chatgpt. The second one will be added with genezio init and the first one will be added using this command:

mkdir client_chatgpt

The Server-side Project

Set up a new genezio project:

genezio init

After you complete the wizard, your terminal should look like this:

What is the name of the project: server_chatgpt
What region do you want to deploy your project to? [default value: us-east-1]: 

Your genezio project was successfully initialized!

The genezio.yaml configuration file was generated.
You can now add the classes that you want to deploy using the'genezio addClass <className> <classType>' command.

Change into the newly created server_chatgpt folder:

cd server_chatgpt

Create a package.json file:

npm init -y

Now, you’re ready to install openai:

npm install openai

Note: This npm package provides a convenient way to access OpenAI API from any JavaScript application.

Implement the Backend Class

You will implement a class containing a function that you will deploy and then call it from the frontend application.

You will need to install dotenv and create a .env file to securely store your secret key:

npm install dotenv
touch .env

Open the .env file and add the following variable that will store your OpenAI secret key from your OpenAI account:

OPENAI_SECRET_KEY=<your_secret_key>

Now, create a new class using genezio:

genezio addClass gptCaller.js

Open the newly created gptCaller.js class and start by adding the dependencies:

import OpenAI from 'openai';
import dotenv from "dotenv";
dotenv.config();

In the constructor of the class, instantiate the openai object:

export class GptCaller {
  openai = null;

  constructor() {
    this.openai = new OpenAI({
      apiKey: process.env.OPENAI_SECRET_KEY
    });
  }
}

Now you can create the class and the async method that will receive the input text from the frontend app. It will call ChatGPT, and then send the response back to the frontend.

Take a look at the complete file code:

import OpenAI from 'openai';
import dotenv from "dotenv";
dotenv.config();


export class GptCaller {
  openai = null;

  constructor() {
    this.openai = new OpenAI({
      apiKey: process.env.OPENAI_SECRET_KEY
    });
  }
// send a request to the ChatGPT API to get the requestText
  async askChatGPT(requestText) {
    const completion = await this.openai.chat.completions.create({
      // the used model at the moment of writing this article
      model: "gpt-3.5-turbo",
      // tells ChatGPT to rephrase the requestText
      messages: [{"role": "user", "content": "rephrase this:" + requestText}],
    });

    console.log(
      `DEBUG: request: ${requestText}, response: ${completion.choices[0].message}`
    );
    return completion.choices[0].message.content;
  }
}

Note: Please make sure to check out the OpenAI API Official Documentation for more information.

The Client-side React Project

Go to the client_chatgpt folder:

cd ./../client_chatgpt

Create a new React app:

npx create-react-app .

Now, you can deploy your backend project from the server_chatgpt folder to the genezio infrastructure (this might take up to 3 minutes, so be patient):

cd ./../server_chatgpt && genezio deploy --env .env

After the deployment is done, you can go to the genezio web app to see more information and logs of your project:

https://app.genez.io/project/<your_project_id>

Now that the backend is deployed, you can start the React app:

cd ./../client_chatgpt && npm start

Implement the User Interface

In this part of the article you will create the UI for chatting with the backend. This in the src/App.js file.

First, import the dependencies from react, SDK, and CSS:

import { useState } from "react";
import { GptCaller } from "./sdk/gptCaller.sdk.js";
import "./App.css";

In the App component you will need 3 useState objects for the messages, requestText, and a boolean variable for the request - isRequesting:

// each mesage format: {text: "message", isUser: true/false}
const [messages, setMessages] = useState([]);
const [requestText, setRequestText] = useState("");
const [isRequesting, setIsRequesting] = useState(false);

You will also need to write a method for sending the request:

function sendRequest(e) {
  e.preventDefault();
  setIsRequesting(true);
  GptCaller.askChatGPT(requestText)
    .then(response => {
      setMessages([
        {
          text: requestText,
          isUser: true
        },
        {
          text: response,
          isUser: false
        }
      ]);
      setRequestText("");
      setIsRequesting(false);
    })
    .catch(err => {
      console.log(err);
      setIsRequesting(false);
    });
}

For displaying the user’s input text and the response generated by ChatGPT, you need 2 elements. On the left side of the screen text generated by ChatGPT will be displayed, and on the right there will be the user text.

This will be done in a map of the messages:

{messages.map((message, index) => {
  if (message.isUser) {
    return (
      <div className="msg right-msg" key={index}>
        <div className="msg-bubble">
          <div className="msg-info">
            <div className="msg-info-name">You</div>
          </div>

          <div className="msg-text">
            {message.text}
          </div>
        </div>
      </div>
    );
  } else {
    return (
      <div className="msg left-msg" key={index}>
        <div className="msg-bubble">
          <div className="msg-info">
            <div className="msg-info-name">ChatGPT</div>
          </div>

          <div className="msg-text">
            {message.text}
          </div>
        </div>
      </div>
    );
  }
})}

To finish, you need a form with an input text box where the user can enter the text:

<form className="msger-inputarea" onSubmit={e => sendRequest(e)}>
  <input
    type="text"
    className="msger-input"
    placeholder="Enter your message..."
    value={requestText}
    onChange={e => setRequestText(e.target.value)}
  />
  <button
    type="submit"
    className="msger-send-btn"
    onClick={e => sendRequest(e)}
  >
    {isRequesting ? "Sending..." : "Send"}
  </button>
</form>

Complete code file:

import { useState } from "react";
import { GptCaller } from "./sdk/gptCaller.sdk.js";
import "./App.css";

function App() {
  // each mesage format: {text: "message", isUser: true/false}
  const [messages, setMessages] = useState([]);
  const [requestText, setRequestText] = useState("");
  const [isRequesting, setIsRequesting] = useState(false);

  function sendRequest(e) {
    e.preventDefault();
    setIsRequesting(true);
    GptCaller.askChatGPT(requestText)
      .then(response => {
        setMessages([
          {
            text: requestText,
            isUser: true
          },
          {
            text: response,
            isUser: false
          }
        ]);
        setRequestText("");
        setIsRequesting(false);
      })
      .catch(err => {
        console.log(err);
        setIsRequesting(false);
      });
  }

  return (
    <div className="App">
      <section className="msger">
        <header className="msger-header">
          <h4>Rephrasing app using ChatGPT, genezio and React</h4>
        </header>

        <main className="msger-chat">
          {messages.map((message, index) => {
            if (message.isUser) {
              return (
                <div className="msg right-msg" key={index}>
                  <div className="msg-bubble">
                    <div className="msg-info">
                      <div className="msg-info-name">You</div>
                    </div>

                    <div className="msg-text">
                      {message.text}
                    </div>
                  </div>
                </div>
              );
            } else {
              return (
                <div className="msg left-msg" key={index}>
                  <div className="msg-bubble">
                    <div className="msg-info">
                      <div className="msg-info-name">ChatGPT</div>
                    </div>

                    <div className="msg-text">
                      {message.text}
                    </div>
                  </div>
                </div>
              );
            }
          })}
        </main>

        <form className="msger-inputarea" onSubmit={e => sendRequest(e)}>
          <input
            type="text"
            className="msger-input"
            placeholder="Enter your message..."
            value={requestText}
            onChange={e => setRequestText(e.target.value)}
          />
          <button
            type="submit"
            className="msger-send-btn"
            onClick={e => sendRequest(e)}
          >
            {isRequesting ? "Sending..." : "Send"}
          </button>
        </form>
      </section>
    </div>
  );
}

export default App;

Note: We provide you with the complete CSS for this project in src/App.css.

This is it!

You can find the complete project on our Github

I hope that you found this tutorial informative and helpful, and I encourage you to check out our other articles for more tips and tricks on mastering your craft.

Let me know if you need help by contacting me on Discord or write me an email at contact@genez.io.