Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / artificial-intelligence / ChatGPT

Chat GPT in VB.NET and C#

4.98/5 (30 votes)
22 Dec 2022CPOL 83.6K   5.4K  
Windows app to talk to Chat GPT
In this article, I have attempted to create windows to talk to Chat GPT using the least amount of code.

Introduction

This application is my attempt to create a smallest client app to talk to Chat GPT. Chat GPT is an AI your application can talk to.

Image 1

Using the Code

  1. Get OPENAI_API_KEY from https://beta.openai.com/account/api-keys.
  2. Open App.config (or bin\Debug\ChatGPT.exe.config) and add the API Key key to it.

Here is the code. Basically, it uses HttpWebRequest to post JSON to OpenAI. Endpoint: https://api.openai.com/v1/completions.

VB.NET Version

VB.NET
Imports System.Net
Imports System.IO
Imports System.Configuration
Imports System.Security.Cryptography
Imports System.Speech.Synthesis
Imports System.Speech.Recognition
Imports System.Numerics

Public Class frmGPTChat

    Dim OPENAI_API_KEY As String = "" 'https://beta.openai.com/account/api-keys
    Dim oSpeechRecognitionEngine As SpeechRecognitionEngine = Nothing
    Dim oSpeechSynthesizer As System.Speech.Synthesis.SpeechSynthesizer = Nothing

    Private Sub frmGPTChat_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Dim oAppSettingsReader As New AppSettingsReader()
        Dim sApiKey As String = oAppSettingsReader.GetValue("OPENAI_API_KEY", GetType(String)) & ""

        If sApiKey = "" Then
            MsgBox("Please enter your OpenAI API key in the App.config file.")
            End
        Else
            OPENAI_API_KEY = sApiKey
        End If

        'SetModels()
        cbModel.SelectedIndex = 0

        cbVoice.Items.Clear()
        Dim synth As New SpeechSynthesizer()
        For Each voice In synth.GetInstalledVoices()
            cbVoice.Items.Add(voice.VoiceInfo.Name)
        Next
        cbVoice.SelectedIndex = 0

    End Sub

    Private Sub chkListen_CheckedChanged(sender As Object, e As EventArgs) Handles chkListen.CheckedChanged
        If chkListen.Checked Then
            lblSpeech.Text = ""
            lblSpeech.Visible = True
            SpeechToText()
        Else
            oSpeechRecognitionEngine.RecognizeAsyncStop()
            lblSpeech.Visible = False
        End If
    End Sub
    Private Sub chkMute_CheckedChanged(sender As Object, e As EventArgs) Handles chkMute.CheckedChanged

        If chkMute.Checked Then
            lblVoice.Visible = False
            cbVoice.Visible = False
        Else
            lblVoice.Visible = True
            cbVoice.Visible = True
        End If

    End Sub

    Private Sub SpeechToText()

        If oSpeechRecognitionEngine IsNot Nothing Then
            oSpeechRecognitionEngine.RecognizeAsync(RecognizeMode.Multiple)
            Exit Sub
        End If

        oSpeechRecognitionEngine = New SpeechRecognitionEngine(New System.Globalization.CultureInfo("en-US"))
        oSpeechRecognitionEngine.LoadGrammar(New DictationGrammar())
        AddHandler oSpeechRecognitionEngine.SpeechRecognized, AddressOf OnSpeechRecognized
        AddHandler oSpeechRecognitionEngine.SpeechHypothesized, AddressOf OnSpeechHypothesized
        oSpeechRecognitionEngine.SetInputToDefaultAudioDevice()
        oSpeechRecognitionEngine.RecognizeAsync(RecognizeMode.Multiple)
    End Sub

    Private Sub OnSpeechRecognized(sender As Object, e As SpeechRecognizedEventArgs)
        lblSpeech.Text = "" 'Reset Hypothesized text

        If txtQuestion.Text <> "" Then
            txtQuestion.Text += vbCrLf
        End If

        Dim text As String = e.Result.Text
        txtQuestion.Text += text
    End Sub

    Private Sub OnSpeechHypothesized(sender As Object, e As SpeechHypothesizedEventArgs)
        Dim text As String = e.Result.Text
        lblSpeech.Text = text
    End Sub

    Private Sub btnSend_Click(sender As Object, e As EventArgs) Handles btnSend.Click

        Dim sQuestion As String = txtQuestion.Text
        If sQuestion = "" Then
            MsgBox("Type in your question!")
            txtQuestion.Focus()
            Exit Sub
        End If

        If txtAnswer.Text <> "" Then
            txtAnswer.AppendText(vbCrLf)
        End If

        txtAnswer.AppendText("Me: " & sQuestion & vbCrLf)
        txtQuestion.Text = ""

        Try
            Dim sAnswer As String = SendMsg(sQuestion)
            txtAnswer.AppendText("Chat GPT: " & Trim(Replace(sAnswer, vbLf, vbCrLf)))
            SpeechToText(sAnswer)
        Catch ex As Exception
            txtAnswer.AppendText("Error: " & ex.Message)
        End Try

    End Sub

    Sub SpeechToText(ByVal s As String)

        If chkMute.Checked Then
            Exit Sub
        End If

        If oSpeechSynthesizer Is Nothing Then
            oSpeechSynthesizer = New System.Speech.Synthesis.SpeechSynthesizer()
            oSpeechSynthesizer.SetOutputToDefaultAudioDevice()
        End If

        If cbVoice.Text <> "" Then
            oSpeechSynthesizer.SelectVoice(cbVoice.Text)
        End If

        oSpeechSynthesizer.Speak(s)

    End Sub

    Function SendMsg(ByVal sQuestion As String)

        System.Net.ServicePointManager.SecurityProtocol =
           System.Net.SecurityProtocolType.Ssl3 Or
           System.Net.SecurityProtocolType.Tls12 Or
           System.Net.SecurityProtocolType.Tls11 Or
           System.Net.SecurityProtocolType.Tls

        Dim sModel As String = cbModel.Text 'text-davinci-002, text-davinci-003
        Dim sUrl As String = "https://api.openai.com/v1/completions"

        If sModel.IndexOf("gpt-3.5-turbo") <> -1 Then
            'Chat GTP 4 https://openai.com/research/gpt-4
            sUrl = "https://api.openai.com/v1/chat/completions"
        End If

        Dim request As HttpWebRequest = WebRequest.Create(sUrl)
        request.Method = "POST"
        request.ContentType = "application/json"
        request.Headers.Add("Authorization", "Bearer " & OPENAI_API_KEY)

        Dim iMaxTokens As Integer = txtMaxTokens.Text '2048

        Dim dTemperature As Double = txtTemperature.Text '0.5
        If dTemperature < 0 Or dTemperature > 1 Then
            MsgBox("Randomness has to be between 0 and 1 with higher values resulting in more random text")
            Return ""
        End If

        Dim sUserId As String = txtUserID.Text '1

        'https://beta.openai.com/docs/api-reference/completions/create
        Dim data As String = ""

        If sModel.IndexOf("gpt-3.5-turbo") <> -1 Then
            'Chat GTP 4
            data = "{"
            data += " ""model"":""" & sModel & ""","
            data += " ""messages"": [{""role"":""user"", ""content"": """ & PadQuotes(sQuestion) & """}]"
            data += "}"
        Else
            data = "{"
            data += " ""model"":""" & sModel & ""","
            data += " ""prompt"": """ & PadQuotes(sQuestion) & ""","
            data += " ""max_tokens"": " & iMaxTokens & ","
            data += " ""user"": """ & sUserId & """, "
            data += " ""temperature"": " & dTemperature & ", "
            data += " ""frequency_penalty"": 0.0" & ", " 'Number between -2.0 and 2.0  Positive value decrease the model's likelihood to repeat the same line verbatim.
            data += " ""presence_penalty"": 0.0" & ", " ' Number between -2.0 and 2.0. Positive values increase the model's likelihood to talk about new topics.
            data += " ""stop"": [""#"", "";""]" 'Up to 4 sequences where the API will stop generating further tokens. The returned text will not contain the stop sequence.
            data += "}"
        End If

        Using streamWriter As New StreamWriter(request.GetRequestStream())
            streamWriter.Write(data)
            streamWriter.Flush()
            streamWriter.Close()
        End Using

        Dim response As HttpWebResponse = request.GetResponse()
        Dim streamReader As New StreamReader(response.GetResponseStream())
        Dim sJson As String = streamReader.ReadToEnd()
        'Return sJson

        Dim oJavaScriptSerializer As New System.Web.Script.Serialization.JavaScriptSerializer
        Dim oJson As Hashtable = oJavaScriptSerializer.Deserialize(Of Hashtable)(sJson)
        Dim sResponse As String = ""

        If sModel.IndexOf("gpt-3.5-turbo") <> -1 Then
            'Chat GTP 4
            sResponse = oJson("choices")(0)("message")("content")
        Else
            sResponse = oJson("choices")(0)("text")
        End If

        Return sResponse
    End Function

    Private Sub SetModels()
        'https://beta.openai.com/docs/models/gpt-3

        System.Net.ServicePointManager.SecurityProtocol =
           System.Net.SecurityProtocolType.Ssl3 Or
           System.Net.SecurityProtocolType.Tls12 Or
           System.Net.SecurityProtocolType.Tls11 Or
           System.Net.SecurityProtocolType.Tls

        Dim apiEndpoint As String = "https://api.openai.com/v1/models"
        Dim request As HttpWebRequest = WebRequest.Create(apiEndpoint)
        request.Method = "GET"
        request.ContentType = "application/json"
        request.Headers.Add("Authorization", "Bearer " & OPENAI_API_KEY)

        Dim response As HttpWebResponse = request.GetResponse()
        Dim streamReader As New StreamReader(response.GetResponseStream())
        Dim sJson As String = streamReader.ReadToEnd()
        'Return sJson

        cbModel.Items.Clear()

        'Dim sIds As String = ""
        Dim oSortedList As SortedList = New SortedList()
        Dim oJavaScriptSerializer As New System.Web.Script.Serialization.JavaScriptSerializer
        Dim oJson As Hashtable = oJavaScriptSerializer.Deserialize(Of Hashtable)(sJson)
        Dim oList As Object() = oJson("data")
        For i As Integer = 0 To oList.Length - 1
            Dim sId As String = oList(i)("id")
            'Dim sCreated As String = oList(i)("created")
            'Dim sObject As String = oList(i)("object")
            'Dim sOwned_by As String = oList(i)("owned_by")
            'Dim oPermission As Hashtable = oList(i)("permission")(0)
            'If sIds <> "" Then sIds += vbCrLf
            'sIds += sCreated & vbTab & sId
            oSortedList.Add(sId, sId)
        Next

        For Each oItem As DictionaryEntry In oSortedList
            cbModel.Items.Add(oItem.Key)
        Next


    End Sub

    Private Function PadQuotes(ByVal s As String) As String

        If s.IndexOf("\") <> -1 Then
            s = Replace(s, "\", "\\")
        End If

        If s.IndexOf(vbCrLf) <> -1 Then
            s = Replace(s, vbCrLf, "\n")
        End If

        If s.IndexOf(vbCr) <> -1 Then
            s = Replace(s, vbCr, "\r")
        End If

        If s.IndexOf(vbLf) <> -1 Then
            s = Replace(s, vbLf, "\f")
        End If

        If s.IndexOf(vbTab) <> -1 Then
            s = Replace(s, vbTab, "\t")
        End If

        If s.IndexOf("""") = -1 Then
            Return s
        Else
            Return Replace(s, """", "\""")
        End If
    End Function

End Class

C# Version

C#
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Speech.Synthesis;
using System.Speech.Recognition;
using static System.Net.WebRequestMethods;

namespace ChatGPTCS
{
    public partial class ChatGPT : Form
    {
        string OPENAI_API_KEY = "sfdsf"; // https://beta.openai.com/account/api-keys
        SpeechRecognitionEngine oSpeechRecognitionEngine = null;
        System.Speech.Synthesis.SpeechSynthesizer oSpeechSynthesizer = null;

        public ChatGPT()
        {
            InitializeComponent();
        }

        private void ChatGPT_Load(object sender, EventArgs e)
        {
            AppSettingsReader oAppSettingsReader = new AppSettingsReader();
            string sApiKey = oAppSettingsReader.GetValue("OPENAI_API_KEY", typeof(string)) + "";

            if (sApiKey == "")
            {
                MessageBox.Show("Please enter your OpenAI API key in the App.config file.");
                System.Windows.Forms.Application.Exit();
            }
            else
            {
                OPENAI_API_KEY = sApiKey;
            }
                        
            //SetModels();
            cbModel.SelectedIndex = 0;

            cbVoice.Items.Clear();
            SpeechSynthesizer synth = new SpeechSynthesizer();
            foreach (var voice in synth.GetInstalledVoices())
                cbVoice.Items.Add(voice.VoiceInfo.Name);
            cbVoice.SelectedIndex = 0;
        }

        private void chkListen_CheckedChanged(object sender, EventArgs e)
        {
            if (chkListen.Checked)
            {
                lblSpeech.Text = "";
                lblSpeech.Visible = true;
                SpeechToText();
            }
            else
            {
                oSpeechRecognitionEngine.RecognizeAsyncStop();
                lblSpeech.Visible = false;
            }
        }

        private void chkMute_CheckedChanged(object sender, EventArgs e)
        {
            if (chkMute.Checked)
            {
                lblVoice.Visible = false;
                cbVoice.Visible = false;
            }
            else
            {
                lblVoice.Visible = true;
                cbVoice.Visible = true;
            }
        }

        private void SpeechToText()
        {
            if (oSpeechRecognitionEngine != null)
            {
                oSpeechRecognitionEngine.RecognizeAsync(RecognizeMode.Multiple);
                return;
            }

            oSpeechRecognitionEngine = new SpeechRecognitionEngine(new System.Globalization.CultureInfo("en-US"));
            oSpeechRecognitionEngine.LoadGrammar(new DictationGrammar());
            oSpeechRecognitionEngine.SpeechRecognized += OnSpeechRecognized;
            oSpeechRecognitionEngine.SpeechHypothesized += OnSpeechHypothesized;
            oSpeechRecognitionEngine.SetInputToDefaultAudioDevice();
            oSpeechRecognitionEngine.RecognizeAsync(RecognizeMode.Multiple);
        }

        private void OnSpeechRecognized(object sender, SpeechRecognizedEventArgs e)
        {
            lblSpeech.Text = ""; // Reset Hypothesized text

            if (txtQuestion.Text != "")
                txtQuestion.Text += "\n";

            string text = e.Result.Text;
            txtQuestion.Text += text;
        }

        private void OnSpeechHypothesized(object sender, SpeechHypothesizedEventArgs e)
        {
            string text = e.Result.Text;
            lblSpeech.Text = text;
        }

        private void btnSend_Click(object sender, EventArgs e)
        {
            {

                string sQuestion = txtQuestion.Text;
                if (string.IsNullOrEmpty(sQuestion))
                {
                    MessageBox.Show("Type in your question!");
                    txtQuestion.Focus();
                    return;
                }

                if (txtAnswer.Text != "")
                {
                    txtAnswer.AppendText("\r\n");
                }

                txtAnswer.AppendText("Me: " + sQuestion + "\r\n");
                txtQuestion.Text = "";

                try
                {
                    string sAnswer = SendMsg(sQuestion) + "";
                    txtAnswer.AppendText("Chat GPT: " + sAnswer.Replace( "\n", "\r\n").Trim());
                    SpeechToText(sAnswer);
                }
                catch (Exception ex)
                {
                    txtAnswer.AppendText("Error: " + ex.Message);
                }
            }
            
        }

        public void SpeechToText(string s)
        {
            if (chkMute.Checked)
                return;

            if (oSpeechSynthesizer == null)
            {
                oSpeechSynthesizer = new System.Speech.Synthesis.SpeechSynthesizer();
                oSpeechSynthesizer.SetOutputToDefaultAudioDevice();
            }

            if (cbVoice.Text != "")
                oSpeechSynthesizer.SelectVoice(cbVoice.Text);

            oSpeechSynthesizer.Speak(s);
        }
        
        public string SendMsg(string sQuestion)
        {

            System.Net.ServicePointManager.SecurityProtocol = 
                System.Net.SecurityProtocolType.Ssl3 | 
                System.Net.SecurityProtocolType.Tls12 | 
                System.Net.SecurityProtocolType.Tls11 | 
                System.Net.SecurityProtocolType.Tls;

            string sModel = cbModel.Text; // text-davinci-002, text-davinci-003
            string sUrl = "https://api.openai.com/v1/completions";

            if (sModel.IndexOf("gpt-3.5-turbo") != -1)
            {
                //Chat GTP 4 https://openai.com/research/gpt-4
                sUrl = "https://api.openai.com/v1/chat/completions";
            }

            var request = WebRequest.Create(sUrl);
            request.Method = "POST";
            request.ContentType = "application/json";
            request.Headers.Add("Authorization", "Bearer " + OPENAI_API_KEY);

            int iMaxTokens = int.Parse( txtMaxTokens.Text); // 2048

            double dTemperature = double.Parse(txtTemperature.Text); // 0.5
            if (dTemperature < 0d | dTemperature > 1d)
            {
                MessageBox.Show("Randomness has to be between 0 and 1 with higher values resulting in more random text");
                return "";
            }

            string sUserId = txtUserID.Text; // 1        
            string data = "";

            if (sModel.IndexOf("gpt-3.5-turbo") != -1)
            {
                data = "{";
                data += " \"model\":\"" + sModel + "\",";
                data += " \"messages\": [{\"role\": \"user\", \"content\": \"" + PadQuotes(sQuestion) + "\"}]";
                data += "}";
            }
            else
            {
                data = "{";
                data += " \"model\":\"" + sModel + "\",";
                data += " \"prompt\": \"" + PadQuotes(sQuestion) + "\",";
                data += " \"max_tokens\": " + iMaxTokens + ",";
                data += " \"user\": \"" + sUserId + "\", ";
                data += " \"temperature\": " + dTemperature + ", ";
                data += " \"frequency_penalty\": 0.0" + ", "; // Number between -2.0 and 2.0  Positive value decrease the model's likelihood to repeat the same line verbatim.
                data += " \"presence_penalty\": 0.0" + ", "; // Number between -2.0 and 2.0. Positive values increase the model's likelihood to talk about new topics.
                data += " \"stop\": [\"#\", \";\"]"; // Up to 4 sequences where the API will stop generating further tokens. The returned text will not contain the stop sequence.
                data += "}";
            }

                using (var streamWriter = new StreamWriter(request.GetRequestStream()))
            {
                streamWriter.Write(data);
                streamWriter.Flush();
                streamWriter.Close();
            }
            
            var response = request.GetResponse();
            var streamReader = new StreamReader(response.GetResponseStream());
            string sJson = streamReader.ReadToEnd();
            // Return sJson

            var oJavaScriptSerializer = new System.Web.Script.Serialization.JavaScriptSerializer();
            Dictionary<string, object> oJson = (Dictionary<string, object>) oJavaScriptSerializer.DeserializeObject(sJson);
            Object[] oChoices = (Object[])oJson["choices"];
            Dictionary<string, object> oChoice = (Dictionary<string, object>)oChoices[0];
            string sResponse = "";

            if (sModel.IndexOf("gpt-3.5-turbo") != -1)
            {
                Dictionary<string, object> oMessage = (Dictionary<string, object>) oChoice["message"];
                sResponse = (string) oMessage["content"];
            }
            else
            {
                sResponse = (string) oChoice["text"];
            }

            return sResponse;
        }

        private string PadQuotes(string s)
        {
            if (s.IndexOf("\\") != -1)
                s = s.Replace("\\", @"\\");
                    
            if (s.IndexOf("\n\r") != -1)
                s = s.Replace("\n\r", @"\n");

            if (s.IndexOf("\r") != -1)
                s = s.Replace("\r", @"\r");

            if (s.IndexOf("\n") != -1)
                s = s.Replace("\n", @"\n");

            if (s.IndexOf("\t") != -1)
                s = s.Replace("\t", @"\t");
            
            if (s.IndexOf("\"") != -1)
                return s.Replace("\"", @"""");
            else
                return s;
        }
        
        private void SetModels()
        {
            // https://beta.openai.com/docs/models/gpt-3

            System.Net.ServicePointManager.SecurityProtocol = System.Net.SecurityProtocolType.Ssl3 | System.Net.SecurityProtocolType.Tls12 | System.Net.SecurityProtocolType.Tls11 | System.Net.SecurityProtocolType.Tls;

            string apiEndpoint = "https://api.openai.com/v1/models";
            var  request = WebRequest.Create(apiEndpoint);
            request.Method = "GET";
            request.ContentType = "application/json";
            request.Headers.Add("Authorization", "Bearer " + OPENAI_API_KEY);

            var response = request.GetResponse();
            StreamReader streamReader = new StreamReader(response.GetResponseStream());
            string sJson = streamReader.ReadToEnd();

            cbModel.Items.Clear();

            SortedList oSortedList = new SortedList();
            System.Web.Script.Serialization.JavaScriptSerializer oJavaScriptSerializer = new System.Web.Script.Serialization.JavaScriptSerializer();
            Dictionary<string, object> oJson = (Dictionary<string, object>)oJavaScriptSerializer.DeserializeObject(sJson);
            Object[] oList = (Object[])oJson["data"];
            for (int i = 0; i <= oList.Length - 1; i++)
            {
                Dictionary<string, object> oItem = (Dictionary<string, object>)oList[i];
                string sId = (String) oItem["id"];
                if (oSortedList.ContainsKey(sId) == false)
                {
                    oSortedList.Add(sId, sId);
                }                
            }

            foreach (DictionaryEntry oItem in oSortedList)
                cbModel.Items.Add(oItem.Key);
        }


    }
}

Points of Interest

The next step is to create an application that does something more useful... like read an Outlook email, text me its summary and file it into an appropriate Outlook folder.

History

  • 23rd December, 2022: Version 1 created
  • 24th December, 2022: Version 2 created (Added C#)
  • 27th December, 2022: Version 3 created (Added Model Selector)
  • 24th May         , 2023: Chat GPT4 support

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)