Wednesday, June 28, 2023

Integrating ChatGPT Bot into Your Angular Application: A Step-by-Step Guide

In today's digital landscape, interactive and engaging user experiences are crucial for the success of web applications. As the demand for intelligent and interactive chatbots continues to grow, developers are constantly exploring innovative ways to enhance user experiences within their applications. One powerful tool that has gained significant popularity is ChatGPT, an advanced language model developed by OpenAI. With its ability to generate human-like responses and understand natural language, integrating ChatGPT into your Angular application can elevate your user engagement to new heights.

In this article, we will walk you through the process of adding a ChatGPT bot to your Angular application. We'll explore the necessary steps, from setting up an OpenAI API account to creating a seamless user experience within your application. Whether you're building a customer support chatbot, an interactive virtual assistant, or any other conversational interface, this guide will equip you with the knowledge and tools to get started.

Prerequisites:

Before diving into the integration process, ensure that you have the following prerequisites in place:

ChatGPT API access: To interact with the ChatGPT model, you'll need an API key or credentials. If you don't have one, you can obtain it from OpenAI's platform or consult the relevant documentation. Here's a step-by-step guide on how to gain access to the ChatGPT API:

  1. Visit the OpenAI website:
    • Go to the OpenAI website by typing "openai.com" in your web browser's address bar and pressing Enter.
  1. Explore the OpenAI API section:
    • Navigate to the OpenAI API section of the website. You can usually find it in the top navigation menu or by searching for "OpenAI API" in the website's search bar.
  2. Understand the API access requirements:
    • Get familiar with the details and requirements for accessing the OpenAI API. Take note of any pricing, usage limits, or terms of service that may apply.
  3. Sign in to your OpenAI account or create a new one:
    • If you already have an OpenAI account, sign in using your credentials.
    • If you don't have an account, create a new one by following the registration process provided on the OpenAI website.
  4. Navigate to the API documentation:
    • Once you're logged in, navigate to the API documentation section. Look for documentation related to the ChatGPT API or any specific information related to integrating ChatGPT into your application.
  5. Review the API documentation:
    • Take the time to carefully read and understand the API documentation. It should provide information on endpoints, request and response formats, authentication, and any additional details necessary for making API calls.
  6. Familiarize yourself with the pricing and billing:
    • Understand the pricing structure for using the ChatGPT API. OpenAI may charge for API usage based on factors such as the number of requests made or the amount of data processed. Ensure that you are aware of the associated costs.
  7. Apply for API access or join the waitlist:
    • Depending on the availability of the ChatGPT API, you may need to apply for access or join a waitlist. Follow the instructions provided in the API documentation to request access. OpenAI may require additional information or have specific criteria for granting access.
  8. Await confirmation and receive API access:
    • Once you have applied for access, await confirmation from OpenAI. They will typically send an email notification with instructions on how to access the ChatGPT API.
  9. Retrieve your API key:
    • Upon receiving access to the ChatGPT API, you should be provided with an API key. This key is a crucial piece of information required to authenticate and make requests to the API.

Choose the model for communication with Open AI API

The OpenAI API is powered by a diverse set of models with different capabilities and price points. You can also make limited customizations to our original base models for your specific use case with fine-tuning.

MODELS

DESCRIPTION

GPT-4 

Limited beta

A set of models that improve on GPT-3.5 and can understand as well as generate natural language or code

GPT-3.5

A set of models that improve on GPT-3 and can understand as well as generate natural language or code

Model endpoint compatibility

ENDPOINT

MODEL NAME

/v1/chat/completions

gpt-4, gpt-4-0314, gpt-4-32k, gpt-4-32k-0314, gpt-3.5-turbo, gpt-3.5-turbo-0301

/v1/completions

text-davinci-003, text-davinci-002, text-curie-001, text-babbage-001, text-ada-001

For our implementation you can use any of the proposed models, however, it is important to compare prices before choosing one or another model. When you sign up for Open AI, they give you $18 for free for several months. For our chatbot, we are going to use gpt-3.5-turbo. The main reason is speed and price ($0.002/1K tokens). For example, the new models such as gpt-4, gpt-4-0314 ($0.03/1K tokens), and gpt-4-32k costs $0.06 / 1K tokens. Besides that, it is required to register on the waitlist. Based on my personal experience, choosing gpt-3.5-turbo will be the best option for your commercial chatbot, so we will choose this model for communication with Open AI API and will continue to use it in the next slides. 

Creating ChatGPT Bot in Angular:

  • Set up the Angular Development Environment:
    • Make sure you have Node.js installed on your machine.

    • Install the Angular CLI globally by running the following command in your terminal or command prompt: npm install -g @angular/cli

  • Create a new Angular project:

    • Open your terminal or command prompt and navigate to the directory where you want to create your project.
    • Run the following command to generate a new Angular project: ng new chatgpt-bot --skip-tests --style=scss
    • For the question “Would you like to add Angular routing?” please choose N because we do not need any routing for this app.  
  • Install Angular Material and the Angular CDK:

    • Navigate to your project's root directory: cd chatgpt-bot

    • Install Angular Material and the Angular CDK by running the following command:

      ng add @angular/material

    • Select a custom theme when prompted. Choose the "Indigo/Pink" theme, or select any other options you prefer.

    • This command will install Angular Material and its dependencies and add the necessary styles and configurations to your project.

  • Customize your application with Angular Material components:

    • Open the src/app/app.component.html file and modify it according to your requirements. You can use Angular Material components in your templates. For example:

<button mat-raised-button color="primary">Primary</button>

    • Open the src/app/ app.module.ts file and add MatButtonModule to import.

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';

import { AppComponent } from './app.component';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { MatButtonModule } from '@angular/material/button';

@NgModule({
  declarations: [AppComponent],
  imports: [BrowserModule, BrowserAnimationsModule, MatButtonModule],
  providers: [],
  bootstrap: [AppComponent],
})
export class AppModule {}
  • Run the Angular application:

    • In your terminal or command prompt, make sure you are in your project's root directory.

    • Run the following command to start the development server and launch your application: ng serve 

    • Open your web browser and navigate to http://localhost:4200 to see your Angular application in action.

    • The result should be identical to the screen below.

Open AI API key

Create in the main folder a new folder called environments. Inside this folder, please create a file called environment.ts. This environment.ts file has the next structure:

export const environment = {
  openAIKey: 'OPENTAI_KEY',
};

Go to the Open AI and open the API keys page. Click on the "+ Create new secret key" button. Let's get a string like "sk-xxxxx..." and copy it to our environment.ts file as the value of the openAIKey variable.

Added customer-support-button and customer-support components:

Step 1: Create the Components

Open your terminal and navigate to your Angular project's root directory. Then, run the following command to generate the components:

ng generate component customer-support-button

ng generate component customer-support

It will create two new directories: customer-support-button and customer-support. Inside each directory, you'll find the necessary files for the components.

Step 2: Add Required Material UI modules to app.module.ts

Open your app.module.ts and update it similar to the screen below:

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';

import { AppComponent } from './app.component';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { CustomerSupportButtonComponent } from '../components/customer-support-button
/customer-support-button.component';
import { MatIconModule } from '@angular/material/icon';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { CustomerSupportComponent } from '../components/customer-support
/customer-support.component';
import { MatDialogModule } from '@angular/material/dialog';
import { MatButtonModule } from '@angular/material/button';
import { HttpClientModule } from '@angular/common/http';

@NgModule({
  declarations: [
    AppComponent,
    CustomerSupportButtonComponent,
    CustomerSupportComponent,
  ],
  imports: [
    BrowserModule,
    BrowserAnimationsModule,
    HttpClientModule,
    MatButtonModule,
    MatDialogModule,
    MatIconModule,
    MatFormFieldModule,
    MatInputModule,
    FormsModule,
    ReactiveFormsModule,
  ],
  providers: [],
  bootstrap: [AppComponent],
})
export class AppModule {}

Step 3: Create a service for Chat GPT communication

Open the terminal once again and run the following command to generate the service:

ng generate service chat-service

Verify that our service was added to app.module.ts. If not, please update your app.module.ts

@NgModule({
  declarations: [
    AppComponent,
    CustomerSupportButtonComponent,
    CustomerSupportComponent,
  ],
  imports: [
    BrowserModule,
    BrowserAnimationsModule,
    HttpClientModule,
    MatButtonModule,
    MatDialogModule,
    MatIconModule,
    MatFormFieldModule,
    MatInputModule,
    FormsModule,
    ReactiveFormsModule,
  ],
  providers: [ChatService],
  bootstrap: [AppComponent],
})
export class AppModule {}

Open chat-service.service.ts for editing and pass the next logic:

import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable, of, switchMap } from 'rxjs';
import { environment } from '../environments/environment';

@Injectable({
  providedIn: 'root',
})
export class ChatService {
  constructor(private http: HttpClient) {}

  // Define a method to send a message and receive a response from ChatGPT
  chat(message: string): Observable<string> {
    const headers = new HttpHeaders({
      'Content-Type': 'application/json',
      Authorization: `Bearer ${environment.openAIKey}`,
    });

    const body = {
      model: 'gpt-3.5-turbo',
      messages: [{ role: 'user', content: message }],
      temperature: 0.95,
      max_tokens: 250,
      top_p: 1.0,
      frequency_penalty: 0.0,
      presence_penalty: 0.0,
    };
    return this.http
      .post<unknown>('https://api.openai.com/v1/chat/completions', body, {
        headers,
      })
      .pipe(
        switchMap((apiResponse: any) => {
          return of(apiResponse.choices[0].message.content as string);
        })
      );
  }
}

Here you will find detailed information about the parameters of creating completion such as temperature, max_tokens etc.

NB! You will probably hear about nuget package called openai. The reason why we do not use it here is that this library is meant for server-side usage only, as using it in client-side browser code will expose your secret API key. So, if you want to use this library, you must use node.js or some backend server such as express or some others. This logic is out of scope for us because we are not going to share our secret key somewhere if it is crucial to you – move your communication logic to the backend. 

Step 4: Add Component Logic and Template

Open the customer-support-button.component.ts file located in the customer-support-button directory. This file contains the component's TypeScript logic.

 import { Component } from '@angular/core';

import { MatDialog } from '@angular/material/dialog';
import { CustomerSupportComponent } from
    '../customer-support/customer-support.component';

@Component({
  selector: 'app-customer-support-button',
  templateUrl: './customer-support-button.component.html',
  styleUrls: ['./customer-support-button.component.scss'],
})
export class CustomerSupportButtonComponent {
  customerSupportDialogOpened: boolean = false;
  constructor(private readonly dialog: MatDialog) {}

  onCustomerSupportOpen(): void {
    if (this.customerSupportDialogOpened) {
      return;
    }

    this.customerSupportDialogOpened = true;

    this.dialog
      .open(CustomerSupportComponent, {
        width: '400px',
        disableClose: false,
        panelClass: 'mat-dialog-customer-support-modal',
        autoFocus: false,
        hasBackdrop: false,
      })
      .afterClosed()
      .subscribe(() => {
        this.customerSupportDialogOpened = false;
      });
  }
}

Open the customer-support-button.component.html file located in the customer-support-button directory. This file contains the component's markup logic.

<button
  mat-flat-button
  color="primary"
  data-testid="btn"
  class="customer-support-button"
  (click)="onCustomerSupportOpen()"
>
  <mat-icon>chat</mat-icon>eSupport
</button>

For the customer-support component, we need to add a few models first. In your Angular project's root directory please create folder models and add the next file gpt-response.model.ts.

export type PersonType = 'Customer Support' | 'You';

export interface ChatWithBot {
  person: PersonType;
  response: string;
  fromUser: boolean;
}

This PersonType will help us to identify our response (the question from us or response from ChatGPT).

Repeat the same process for the customer-support component as we have already done for customer-support-button components. Add logic and template in the corresponding .ts and .html files in the customer-support directory.

Open the customer-support.component.html file located in the customer-support directory and update it in the following way:

<div class="chat-container">
  <div
    cdkDrag
    cdkDragHandle
    cdkDragRootElement=".cdk-overlay-pane"
    cdkDragBoundary=".cdk-global-overlay-wrapper"
    class="dialog-header chat-header"
  >
    <h1 mat-dialog-title>Chat with us</h1>

    <button mat-icon-button class="close-button" mat-dialog-close>
      <mat-icon class="close-icon">close</mat-icon>
    </button>
  </div>

  <div #chatRef class="chat-body">
    <ng-container *ngIf="chatConversation?.length; else noMessages">
      <div
        *ngFor="let message of chatConversation"
        class="message"
        [class.from-user]="message.fromUser"
      >
        <span class="user-name">{{ message.person }}:</span>
        {{ message.response }}
      </div>

      <div *ngIf="responseLoading" class="message">
        <span class="user-name">{{ botName }}:</span>
        <div class="chat-loading-wrapper">
          <div class="dot-typing"></div>
        </div>
      </div>
    </ng-container>
    <ng-template #noMessages>
      <div class="no-messages" translate>
        Glory to Ukraine! Glory to the heroes!
      </div>
    </ng-template>
  </div>

  <div class="chat-footer">
    <ng-container [formGroup]="customerSupportForm">
      <mat-form-field>
        <mat-label translate>Ask us a question</mat-label>
        <input
          #inpRef
          type="text"
          matInput
          formControlName="promptText"
          (keydown.enter)="sendChatGptRequest()"
        />
      </mat-form-field>
      <button
        mat-icon-button
        type="button"
        color="primary"
        aria-label="Send message"
        [disabled]="!inpRef.value.length"
        (click)="sendChatGptRequest()"
      >
        <mat-icon>send</mat-icon>
      </button>
    </ng-container>
  </div>
</div>

Open the customer-support.component.ts file located in the customer-support directory and update it as follows:

import { Component, ElementRef, ViewChild } from '@angular/core';
import { FormBuilder, FormGroup } from '@angular/forms';
import { ChatService } from '../../services/chat-service.service';
import { ChatWithBot, PersonType } from '../../models/gpt-response.model';

@Component({
  selector: 'app-customer-support',
  templateUrl: './customer-support.component.html',
  styleUrls: ['./customer-support.component.scss'],
})
export class CustomerSupportComponent {
  customerSupportForm!: FormGroup;
  chatConversation: ChatWithBot[] = [];
  responseLoading = false;
  botName: PersonType = 'Customer Support';

  @ViewChild('chatRef', { read: ElementRef }) chatRef!: ElementRef;

  constructor(
    private chatService: ChatService,
    private formBuilder: FormBuilder
  ) {
    this.createForm();
  }

  sendChatGptRequest(): void {
    const promptText = this.customerSupportForm.get('promptText')!.value;
    if (!promptText) {
      return;
    }

    this.responseLoading = true;
    this.chatConversation.push({
      person: 'You',
      response: promptText,
      fromUser: true,
    });
    this.customerSupportForm
      .get('promptText')
      ?.setValue('', { emitEvent: false });
    this.scrollChat();

    this.chatService.chat(promptText).subscribe((response) => {
      this.responseLoading = false;
      this.chatConversation.push({
        person: this.botName,
        response: response,
        fromUser: false,
      });
      this.scrollChat();
    });
  }

  private scrollChat(): void {
    requestAnimationFrame(() => {
      const chatBody = this.chatRef.nativeElement as HTMLElement;
      chatBody.scrollTo({ top: chatBody.scrollHeight, behavior: 'smooth' });
    });
  }

  private createForm(): void {
    this.customerSupportForm = this.formBuilder.group({
      promptText: [''],
    });
  }
}

When we run our component right now, it will look ugly, however, it should work. So, it’s high time to add nice styling to our application. 

Step 5: Add Component Styling

Setup global styling

Inside the folder assets create new folder styles. Create four SCSS files in our newly created folder: _mixins.scss, _base.scss, _dialog.scss and _variables.scss. Besides the files above, we need to create one index.scss file with the next setup:

@import "variables";
@import "mixins";

@import "base";

@import "dialog";

Open angular.json file and find "styles": [] for build section and update as follows:

"styles": [
              "@angular/material/prebuilt-themes/indigo-pink.css",
              "src/styles.scss",
              "src/assets/styles/index.scss"
            ],

Open _variables.scss and provide the next variables:

:root {
  --base-font-size: 10px;
}

$screen-sm: 600px;
$screen-md: 960px;
$screen-lg: 1280px;
$screen-vertical-max: 460px;

$button-height: 50px !default;
$button-simple-height: 40px !default;

$default-space-size: 15px !default;

/* Page container */
$page-space: $default-space-size;
$page-space-mobile: 10px;

/* Colors */
$color-base: #212529;
$color-blue-primary: #004bc1;
$color-yellow-primary: #ffe358;

$color-dark-gray: #6d727c;
$color-gray: #c2c5cb;
$color-light-gray: #f5f7fa;

$color-black: #000;
$color-white: #fff;

// Font
$font-family: "Proba Pro", "Roboto", Arial, sans-serif;
$font-family-semibold: "Proba Pro Semibold", "Roboto", Arial, sans-serif;

// Set of common variables
$default-font-size: 1.8rem;
$default-transition: 200ms linear;

$content-width-limit: 720px;

Open _base.scss and provide the next changes:

html {
  font-size: var(--base-font-size);
  height: 100%;
  -webkit-text-size-adjust: 100%;
  -webkit-tap-highlight-color: rgba($color-base, 0.25);

  @include respond(phone) {
    font-size: calc(var(--base-font-size) + 3 * ((100vw - 320px) / 680));
  }
}

body {
  font-family: $font-family;
  font-size: $default-font-size;
  font-weight: 400;
  min-height: 100vh;
  line-height: 1.5;
  overflow: hidden;
}

Open _mixins.scss and provide the next changes:

//MEDIA QUERY MANAGER
/*
0 - 599.9px:      Phone
600 - 959.9px:    Tablet portrait
960 - 1279.9px    Tablet landscape
1280px < ~        Desktop

$breakpoint argument choices:
- phone
- tab-port
- tab-land
- desktop

*/
@mixin respond($breakpoint) {
  @if $breakpoint == phone {
    @media only screen and (max-width: #{$screen-sm - 0.1px}) {
      @content;
    } // > 600px
  }
  @if $breakpoint == phone-landscape {
    @media (max-device-height: #{$screen-vertical-max}) and (orientation: landscape) {
      @content;
    } // orientation: landscape
  }
  @if $breakpoint == tab-port {
    @media only screen and (max-width: #{$screen-md - 0.1px}) {
      @content;
    } // > 960px
  }
  @if $breakpoint == tab-land {
    @media only screen and (max-width: #{$screen-lg - 0.1px}) {
      @content;
    } // > 1280px
  }
  @if $breakpoint == desktop {
    @media only screen and (min-width: $screen-lg) {
      @content;
    } // < 1280px
  }
}

// Set mat-icon icon size (with points)
@mixin icon-size($size) {
  font-size: $size;
  line-height: $size;
  height: $size;
  width: $size;
}

// Default outline
@mixin default-outline() {
  outline: 2px dotted rgba($color-dark-gray, 0.75);
  outline-offset: 2px;
}

Open _dialog.scss and provide the next changes:

/* Material dialog overwrites */
$dialog-inner-space: 32px;
$dialog-inner-space-mobile: 16px;

.cdk-overlay-pane {
  max-width: calc(100vw - $dialog-inner-space-mobile * 2) !important;

  &.mat-dialog-customer-support-modal {
    margin-right: 4rem;
    margin-left: auto;

    @include respond(tab-port) {
      margin-right: 1.5rem;
      margin-left: 1.5rem;
    }
  }
}

.mat-mdc-dialog-container {
  div.mdc-dialog__surface {
    --mdc-dialog-container-shape: #{0};
  }

  .dialog-header {
    box-sizing: border-box;
    display: flex;
    align-items: center;
    gap: 10px;
    padding: $dialog-inner-space $dialog-inner-space 10px;
    white-space: pre-wrap;

    .mdc-dialog__title {
      --mdc-dialog-subhead-font: #{$font-family-semibold};
      --mdc-dialog-subhead-line-height: #{1.2};
      --mdc-dialog-subhead-size: #{134%};
      --mdc-dialog-subhead-weight: #{600};
      --mdc-dialog-subhead-tracking: #{0};
      flex: 1 1 auto;
      margin: 0;
      color: $color-base;
      margin: 0;
      padding: 0;

      &::before {
        display: none;
      }

      @include respond(phone) {
        --mdc-dialog-subhead-size: #{123%};
      }
    }

    .close-button {
      margin-right: -15px;
    }
  }

  div.mdc-dialog__content {
    --mdc-dialog-supporting-text-font: #{$font-family};
    --mdc-dialog-supporting-text-line-height: #{1.2};
    --mdc-dialog-supporting-text-size: #{2rem};
    --mdc-dialog-supporting-text-weight: #{400};
    --mdc-dialog-supporting-tracking: #{0};
    color: $color-base;
    padding: 10px $dialog-inner-space;
    word-break: break-word;
  }

  .mdc-dialog__actions {
    gap: 8px;
    padding: 10px $dialog-inner-space $dialog-inner-space;
  }

  @include respond(phone) {
    .dialog-header {
      padding: $dialog-inner-space-mobile $dialog-inner-space-mobile 10px;
    }

    div.mdc-dialog__content {
      padding: 8px $dialog-inner-space-mobile;
    }

    .mdc-dialog__actions {
      padding: 10px $dialog-inner-space-mobile $dialog-inner-space-mobile;
    }
  }
}

Setup local styling

We are almost at the finish line. Only styling for our created components is left, and we are going to start with the smallest one.

Open customer-support-button.component.scss and update it in the following way:

@use "@angular/material" as mat;
@import "variables";
@import "mixins";

.customer-support-button {
  @include mat.elevation(2);
  position: fixed;
  right: 4rem;
  bottom: 4rem;
  z-index: 10;

  @include respond(tab-port) {
    right: 1.5rem;
    bottom: 8rem;
  }

  @include respond(phone) {
    bottom: 6.2rem;

    ::ng-deep {
      min-width: 40px;
      padding: 0;

      .mdc-button__label {
        display: none;
      }

      .mat-icon {
        margin-right: -4px;
      }
    }
  }

  @media print {
    display: none;
  }
}

Open customer-support.component.scss and update this file as well:

@use "@angular/material" as mat;
@import "variables";
@import "mixins";

.chat-container {
  background-color: $color-white;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.chat-header {
  cursor: all-scroll;
  padding-bottom: 16px;
  padding-top: 16px;
}

.chat-body {
  background-color: $color-light-gray;
  display: flex;
  flex-direction: column;
  flex-grow: 1;
  padding: 8px 16px;
  height: calc(86vh - 160px);
  max-height: 400px;
  overflow-y: auto;
  overflow-x: hidden;
  word-break: break-word;
  -webkit-overflow-scrolling: touch;

  .no-messages {
    font-size: 14px;
    padding-top: 10px;
    text-align: center;
  }
}

.message {
  background-color: $color-yellow-primary;
  color: $color-base;
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: 10px;
  margin-bottom: 12px;
  margin-top: 12px;
  margin-right: 3.5rem;

  .user-name {
    font-family: $font-family-semibold;
    font-size: 14px;
    line-height: 1.5;
  }

  &.from-user {
    background-color: $color-blue-primary;
    color: $color-white;
    margin-right: 0;
    margin-left: 3.5rem;
  }
}

.chat-footer {
  background-color: $color-white;
  display: flex;
  align-items: center;
  padding: 12px;
  gap: 10px;

  .mat-mdc-form-field {
    flex-grow: 1;

    ::ng-deep .mat-mdc-form-field-subscript-wrapper {
      display: none;
    }
  }
}

// Chat response loading
.chat-loading-wrapper {
  margin: 4px 0;
  padding: 8px 16px 5px;
}

.dot-typing {
  border-radius: 50%;
  position: relative;
  left: -9999px;
  height: 6px;
  width: 6px;
  animation: dot-typing 1s infinite ease-out;
  opacity: 0.75;
}

@keyframes dot-typing {
  0% {
    box-shadow: 9984px 0 0 0 $color-base, 9999px 0 0 0 $color-base,
      10014px 0 0 0 $color-base;
  }
  16.667% {
    box-shadow: 9984px -10px 0 0 $color-base, 9999px 0 0 0 $color-base,
      10014px 0 0 0 $color-base;
  }
  33.333% {
    box-shadow: 9984px 0 0 0 $color-base, 9999px 0 0 0 $color-base,
      10014px 0 0 0 $color-base;
  }
  50% {
    box-shadow: 9984px 0 0 0 $color-base, 9999px -10px 0 0 $color-base,
      10014px 0 0 0 $color-base;
  }
  66.667% {
    box-shadow: 9984px 0 0 0 $color-base, 9999px 0 0 0 $color-base,
      10014px 0 0 0 $color-base;
  }
  83.333% {
    box-shadow: 9984px 0 0 0 $color-base, 9999px 0 0 0 $color-base,
      10014px -10px 0 0 $color-base;
  }
  100% {
    box-shadow: 9984px 0 0 0 $color-base, 9999px 0 0 0 $color-base,
      10014px 0 0 0 $color-base;
  }
}

Let's run our application and verify that we have our awesome blue and yellow styles applied.

Open the terminal once again and run the following command: 

ng serve

And we have to see the nice styled button at the bottom right side of our application. 


Click on this eSupport button and check what we will have next

Let’s ask our Chat GPT bot how to learn angular

Areas for improvement:

In the current implementation, we do not have any error handling. So, for your production code, you have to handle status codes from open ai gracefully. 

I would like to say a personal thank you to Mykola Pavelchuk for assisting with the design of this chat gpt bot.

The source code for our chatbot can be found here.

I hope this small example will help you to understand how to use Open AI API with chatbots.