Build A ChatGPT Client And An Image Generator In Blazor Using OpenAI API

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 

  • Visual Studio 2022
  • .NET 7
  • Blazor Server

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" fileReplace 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&nbsp;&nbsp;</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}'/>&nbsp;&nbsp;&nbsp;";
            }
        } 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!