What is ChatGPT?

ChatGPT is an Artificial Intelligence(AI) chatbot launched by OpenAI. It is built on top of OpenAI’s GPT-3.

You can try ChatGPT on https://chat.openai.com/chat

Build a ChatGPT client & an Image Generator in Blazor using OpenAI API

When I asked "what is ChatGPT" on chat, I got the below answer

Hello! I am ChatGPT, a large language model developed by OpenAI based on the GPT (Generative Pre-trained Transformer) architecture. I am designed to generate human-like text based on the input I receive from users. I have been trained on a massive amount of text data from the internet and other sources, which enables me to understand and respond to a wide range of topics and questions. You can think of me as a conversational AI that is capable of engaging in natural language conversations with humans.

Build a ChatGPT client & an Image Generator in Blazor using OpenAI API

Create API token

Complete the sign-up at https://openai.com/product

After signing up, you will get a free trial for $18.

Build a ChatGPT client & an Image Generator in Blazor using OpenAI API

Under API key, click "Create new secret key". Copy the key and store it.

Build a ChatGPT client & an Image Generator in Blazor using OpenAI API

Tech Stack

Setup application

1. Under Visual Studio, "Create a new project". It will show the available project templates, and we can choose the "Blazor Server App" template.

Build a ChatGPT client & an Image Generator in Blazor using OpenAI API

2. Add a configuration section for OpenAI in the "appsettings.json" file. Replace the ApiKey value with your own created secret key.

{
    "OpenAISettings": {
        "ApiKey": "Your secret API key goes here"
    },
    "Logging": {
        "LogLevel": {
            "Default": "Information",
            "Microsoft.AspNetCore": "Warning"
        }
    },
    "AllowedHosts": "*"
}

3. Add OpenAI-DotNet NuGet package

Build a ChatGPT client & an Image Generator in Blazor using OpenAI API

Add usings for OpenAI-DotNet in the "_imports.razor" file.

@using OpenAI;
@using OpenAI.Chat;
@using OpenAI.Models;
@using OpenAI.Images;

@inject IConfiguration _configuration
@inject IJSRuntime _jsRuntime

3-a. Under the "Pages" folder, add a new Razor Component, "ChatGPT.razor"

Like the traditional razor views in classic MVC application, we can add client-side and server-side logic inside the razor component

@page "/chatgpt"
<PageTitle>ChatGPT</PageTitle>
<style>
 .assistant, .user {
  position: relative;
  font-family: arial;
  font-size: 1.1em;
  border-radius: 10px;
  padding: 20px;
  margin-bottom: 20px;
 }

  .assistant:after, .user:after {
   content: '';
   border: 20px solid transparent;
   position: absolute;
   margin-top: -30px;
  }

 .user {
  background: #0B93F6;
  color: white;
  margin-left: 20%;
  margin-right: 100px;
  top: 30%;
  text-align: right;
  font-weight: bold;
 }

 .assistant {
  background: #4CAF50;
  color: white;
  margin-left: 100px;
  margin-right: 20%;
  font-weight: bold;
 }

 .msg {
  font-size: small;
 }
</style>

<p style="font-size:small"><b>Total used tokens:</b> @TotalTokens</p>
<br />
<div id="chatcontainer" style="height:350px; width:100%; overflow: scroll;">
 @foreach (var item in messages)
 {
  <div>
   @if (item.Role == "user")
   {
    <div style="float: right; margin-right: 20px; margin-top: 10px">
     <b>User</b>
    </div>
    <div class="@item.Role">
     <div class="msg">
      @item.Prompt
     </div>
    </div>
   }
   else
   {
    <div style="float: left; margin-left: 20px; margin-top: 10px">
     <b>ChatGPT  </b>
    </div>
    <div class="@item.Role">
     <div class="msg">
      @if (item.Prompt != null)
      {
       @((MarkupString)item.Prompt)
      }
     </div>
    </div>
   }
  </div>
 }
 @if (_isLoading)
 {
  <div class="d-flex justify-content-center">
   <div class="spinner-border" role="status">
   </div>
  </div>
 }
</div>
<br />
<div class="row">
 <div class="col-sm-8">
  <input type="text"
      class="form-control"
      placeholder="Ask me Anything..."
      @bind="prompt" />
 </div>
 <div class="col-sm-4">
  <button class="btn btn-success"
    @onclick="StartChatGPTService">
   Ask Me !
  </button>
  <button class="btn btn-danger"
    @onclick="Clear">
   Clear
  </button>
 </div>
</div>
<p style="color:red">@ErrorMessage</p>
@code {
    string ApiKey = string.Empty;
    string ErrorMessage = string.Empty;
    string prompt = string.Empty;
    bool _isLoading = false;
    int TotalTokens = 0;
    List < Message > messages = new List < Message > ();
    protected override void OnInitialized() {
        ApiKey = _configuration["OpenAISettings:ApiKey"] ?? "";
    }
    protected override async Task OnAfterRenderAsync(bool firstRender) {
        await _jsRuntime.InvokeAsync < string > ("ScrollToBottom", "chatcontainer");
    }
    public async Task StartChatGPTService() {
        try {
            StateHasChanged();
            ErrorMessage = string.Empty;
            _isLoading = true;
            var _openAIClient = new OpenAIClient(new OpenAIAuthentication(ApiKey));
            var chatPromptList = new List < ChatPrompt > ();
            foreach(var item in messages) {
                chatPromptList.Add(new ChatPrompt(item.Role, item.Prompt));
            }
            chatPromptList.Add(new ChatPrompt("user", prompt));
            var chatRequest = new ChatRequest(chatPromptList);
            var result = await _openAIClient.ChatEndpoint.GetCompletionAsync(chatRequest);
            messages.Add(new Message {
                Prompt = prompt,
                    Role = "user",
                    Tokens = result.Usage.PromptTokens
            });
            messages.Add(new Message {
                Prompt = result.FirstChoice.Message,
                    Role = "assistant",
                    Tokens = result.Usage.CompletionTokens
            });
            TotalTokens = TotalTokens + result.Usage.TotalTokens;
        } catch (Exception ex) {
            ErrorMessage = ex.Message;
        } finally {
            prompt = string.Empty;
            _isLoading = false;
            StateHasChanged();
        }
    }
    void Clear() {
        messages = new List < Message > ();
        TotalTokens = 0;
        ErrorMessage = string.Empty;
        StateHasChanged();
    }
    public class Message {
        public string ? Prompt {
            get;
            set;
        }
        public string ? Role {
            get;
            set;
        }
        public int Tokens {
            get;
            set;
        }
    }
}

Run the application and click the menu ChatGPT.

Build a ChatGPT client & an Image Generator in Blazor using OpenAI API

3-b. Under the "Pages" folder, add a new Razor Component, "ImageGenerator.razor"

@page "/imagegenerator" <PageTitle>Image Generator</PageTitle>
<h2 style="text-align:center">
  <b>Model - DALL-E</b>
</h2>
<br />
<h5>
  <b>Given a prompt, the model will return a generated image or images.</b>
</h5>
<div class="row">
  <div class="col-sm-10">
    <input type="text" class="form-control" placeholder="Give me a clue..." @bind="prompt" />
  </div>
  <div class="col-sm-2">
    <button class="btn btn-success" @onclick="StartImageGeneratorService"> Generate </button>
  </div>
</div>
<br />
@if (_isLoading)
{
 <div class="d-flex justify-content-center">
  <div class="spinner-border" role="status">
  </div>
 </div>
}
else
{
 <p>@((MarkupString)GeneratedImage)</p>
}
<p style="color:red">@ErrorMessage</p>

@code {
    string ApiKey = string.Empty;
    string ErrorMessage = string.Empty;
    string prompt = string.Empty;
    string GeneratedImage = string.Empty;
    bool _isLoading = false;
    protected override void OnInitialized() {
        ApiKey = _configuration["OpenAISettings:ApiKey"] ?? "";
    }
    public async Task StartImageGeneratorService() {
        try {
            StateHasChanged();
            ErrorMessage = string.Empty;
            GeneratedImage = string.Empty;
            _isLoading = true;
            var _openAIClient = new OpenAIClient(new OpenAIAuthentication(ApiKey));
            var imageResult = await _openAIClient.ImagesEndPoint.GenerateImageAsync(prompt, 3, ImageSize.Small);
            foreach(var image in imageResult) {
                GeneratedImage += $ @ "<img src='{image}'/>   ";
            }
        } catch (Exception ex) {
            ErrorMessage = ex.Message;
        } finally {
            _isLoading = false;
            StateHasChanged();
        }
    }
}

Run the application and click the menu Image Generator.

Build a ChatGPT client & an Image Generator in Blazor using OpenAI API

We successfully created a Blazor Server OpenAi demo application.

Live preview : https://openai-chatgpt-blazor.herokuapp.com/

The source code for this tutorial is available on GitHub.

Some piece of code was inspired from https://blazorhelpwebsite.com/ by Michael Washington.

Did you catch something I did wrong, or can you improve my implementation? Let me know in the comments!

Happy Documenting!