En este tutorial intentaremos mostrar escribiendo un ejemplo de cómo integrar la api de chatgpt en un programa escrito en VB.Net
Primero comenzamos creando un proyecto VB ChatGPT
Una vez creado, ya tendremos el primer formulario insertado en nuestro proyecto.
Necesitaremos la biblioteca de voz, vaya al paquete nuget para instalar la biblioteca
Una vez hecho esto, comenzamos a insertar todos nuestros objetos necesarios para construir nuestro chatgpt, el primer objeto es textEdit multiline donde tendremos la respuesta del servidor, le damos el nombre txtAnswer
Luego insertamos el objeto txtQuestion donde escribimos nuestras preguntas, insertamos el botón de enviar para enviar nuestra solicitud intento darle el nombre btnSend
Insertamos la etiqueta lblSpeech que se utiliza para recibir parte del texto cada vez que recibimos la respuesta.
Ahora insertamos el objeto de aleatoriedad asociado con la variable temperatura. La temperatura es un hiperparámetro utilizado en algunos modelos de procesamiento de lenguaje natural, incluido ChatGPT, para controlar el nivel de randomnes
Después insertamos el objeto MaxTokens (TextEdit)
Los modelos entienden y procesan el texto dividiéndolo en fichas.
Los tokens pueden ser palabras o simplemente fragmentos de caracteres. Por ejemplo, la palabra "hamburguesa" se divide en las fichas "jamón", "bur" y "ger", mientras que una palabra corta y común como "pera" es una sola ficha. Muchos tokens comienzan con un espacio en blanco, por ejemplo, "hola" y "adiós".
La cantidad de tokens procesados en una solicitud de API determinada depende de la longitud de sus entradas y salidas. Como regla general, 1 token tiene aproximadamente 4 caracteres o 0,75 palabras para texto en inglés.
Una limitación a tener en cuenta es que la solicitud de texto y la finalización generada combinadas no deben superar la longitud máxima de contexto del modelo (para la mayoría de los modelos, esto es 2048 tokens, o alrededor de 1500 palabras).
Consulte la herramienta tokenizer para obtener más información sobre cómo se traduce el texto en tokens.
Luego insertamos una casilla para poner en pausa la escucha y otra para silenciar. También usamos un cuadro combinado para los modelos.
La API está impulsada por un conjunto de modelos con diferentes capacidades y puntos de precio. los modelos GPT-3 de base openai se llaman Davinci, Curie, Babbage y Ada. La serie Codex es un descendiente de GPT-3 que ha sido entrenado tanto en lenguaje natural como en código. Para obtener más información, visite la documentación de modelos del sitio web de openai.
Y otra para las voces existentes, que deberemos cargar enviando una petición al servidor
Ahora comenzamos a escribir código VB .Net
Empezamos importando todos los módulos necesarios:
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
Necesitamos las variables oSpeechRecognitonEngine y oSpeechSynthesizer en el procedimiento de carga del formulario. Leemos el valor del archivo de configuración openai_api_key xml appi.config.
Ahora intentamos cargar el combo que contiene las diferentes voces que podemos usar.
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() We can load all the models or load only the three models that I've noticed working
cbModel.Items.Clear()
cbModel.Items.Add("text-davinci-003")
cbModel.Items.Add("text-davinci-002")
cbModel.Items.Add("code-davinci-002")
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
Cuando hace clic en cklisten si está seleccionado, ve la etiqueta lblSpeech y llamamos a la función speechtoText
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
Si el objeto oSpeechRecognitionEngine no está inicializado, lo inicializamos
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
También asociamos el evento OnSpeechRecognized que nos permite preparar nuestra pregunta antes de enviarla, asociamos el evento OnSpeechHypoSynthesized que nos permite visualizar el texto en la etiqueta lblSpeech.
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
Ahora vamos al botón enviar el cual nos permite enviar la solicitud gracias a la función sendMsg usando el protocolo http invocando la API openai
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: " & Replace(sAnswer, vbLf, vbCrLf))
SpeechToText(sAnswer)
Catch ex As Exception
txtAnswer.AppendText("Error: " & ex.Message)
End Try
End Sub
Tenemos el punto final api.openai.com/v1/completion y la solicitud se realiza con el método de publicación con contenido json
Nuestra solicitud consta de maxtokens con valor 2048, aleatoriedad 0.5, la identificación de usuario para este ejemplo es 1 pero podemos asociar las solicitudes a diferentes usuarios
Preparamos la variable de datos con todos los parámetros necesarios al final leemos nuestra respuesta en formato json.
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 apiEndpoint As String = "https://api.openai.com/v1/completions"
Dim request As HttpWebRequest = WebRequest.Create(apiEndpoint)
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 = "1"
Dim sModel As String = cbModel.Text 'text-davinci-002, text-davinci-003
'https://beta.openai.com/docs/api-reference/completions/create
Dim data As String = "{"
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 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 = oJson("choices")(0)("text")
Return sResponse
End Function
La función setmodels permite inicializar el combo con los modelos posibles, por el momento noté que solo 3 modelos que puedo usar los demás no funcionan, quizás porque mi registro en el sitio openai es gratis
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 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")
oSortedList.Add(sId, sId)
Next
'Text-davinci - 3
'Text-davinci - 2
'code-davinci - 2
For Each oItem As DictionaryEntry In oSortedList
cbModel.Items.Add(oItem.Key)
Next
End Sub
No olvidemos reemplazar los diferentes caracteres no permitidos usando una función separada llamada PdQuotes antes de enviar el mensaje.
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
Una vez finalizada la parte del código buscaremos la clave, debemos realizar un registro en la web openai.com, es gratuita y pegamos la clave en nuestro archivo xml api.config