Utilizando o ChatGpt com uma aplicação .NET

Marcio Nizzola
7 min readFeb 10, 2023

--

integrando ChatGpt com .NET

O assunto da moda agora é o ChatGpt, para quem não sabe, é uma inteligência artificial com capacidade de comunicação e que está chocando a todos com a sua capacidade de responder perguntas complexas, entender contextos e até escrever e refatorar códigos de programação.

Para quem não conhece, você pode fazer seu cadastro no site e testá-la, através de uma interface gráfica, mas também, ela possui uma API, a qual podemos acessar e assim utilizar suas funcionalidades (por enquanto é gratis).

A Microsoft já está trabalhando para disponibilizar ao público a ferramenta dentro do Azure, já existe até uma versão que foi apresentada nesta semana e estará em breve liberada ao público geral.

Primeiramente, para poder acessar a API e consumir seus serviços, você precisa acessar o site da OpenAI e fazer seu cadastro (link aqui).

Depois é só chegar lá e fazer perguntas, você pode perguntar em qualquer linguagem, pois ele é capaz de entender e responder, veja o exemplo abaixo:

E onde o .NET entra nessa? Bom, podemos através da API do OpenAI fazer uso deste serviço enviando mensagens e recebendo as respostas imediatamente.

Para fazer isso, vamos criar um projeto, optei pelo MVC para que eu crie um site e vocês possam até acessá-lo e brincar com ele.

A Api oferece integração simples, sem necessidade de bibliotecas específicas, tanto que para isto vamos realizar uma implementação bem básica com uma chamada HttpClient comum.

UPDATE: Tenho uma nova postagem com uma abordagem muito mais simples e atualizada utilizando uma biblioteca Azure.Openai (link).

Projeto Oráculo

Criei um projeto do tipo Asp Net Core MVO, onde para integração, vamos precisar de algumas classes específicas conforme verá abaixo:

Para requisição foi criada esta classe, com os parâmetros básicos para a comunicação, caso queira mais detalhes na documentação da api tem todas as informações:

using System.Text.Json.Serialization;

namespace OraculoApi.Model.OpenAI;

public class OpenAIRequest
{
public OpenAIRequest(string question)
{
this.Model = "text-davinci-003";
this.Prompt = question;
this.Temperature = 0f;
this.MaxTokens = 500;
}

[JsonPropertyName("model")]
public string Model { get; set; }

[JsonPropertyName("prompt")]
public string Prompt { get; set; }

[JsonPropertyName("temperature")]
public float Temperature { get; set; }

[JsonPropertyName("max_tokens")]
public int MaxTokens { get; set; }
}

Os parâmetros “model”, “temperature” e “maxtokens” são usados na requisição ao OpenAI para personalizar a saída gerada pelo modelo. Aqui está uma explicação detalhada de cada parâmetro:

  1. Model: Este parâmetro especifica qual modelo de linguagem OpenAI deve ser usado para gerar a saída. O OpenAI mantém vários modelos de linguagem, cada um com suas próprias especializações e capacidades. Ao especificar o modelo, você pode escolher o modelo que mais se adequa aos seus requisitos de saída.
  2. Temperature: Este parâmetro controla a “temperatura” da saída gerada pelo modelo. A temperatura é uma medida da aleatoriedade na saída do modelo. Quanto maior a temperatura, mais aleatória será a saída, enquanto uma temperatura mais baixa resultará em saídas mais previsíveis.
  3. Maxtokens: Este parâmetro controla o comprimento máximo da saída gerada pelo modelo. Ao especificar o número máximo de tokens, você pode limitar o tamanho da saída gerada pelo modelo, o que é útil para garantir que a saída não seja muito longa ou para controlar o tempo de resposta da requisição.

Para tratar a resposta:

Criamos a classe OpenAIResponse

using OraculoMVC.Models.OpenAI;
using static System.Runtime.InteropServices.JavaScript.JSType;

namespace OraculoApi.Model.OpenAI;

public class OpenAIResponse
{
public string Id { get; set; }
public string Object { get; set; }
public int Created { get; set; }
public string Model { get; set; }
public Choice[] Choices { get; set; }
public Usage Usage { get; set; }
public OpenAIError? Error { get; set; }
}

a classe Choice foi criada por fazer parte da resposta, e é nela que a resposta esperada vem no campo de nome “Text”

using System.Text.Json.Serialization;

namespace OraculoApi.Model.OpenAI;

public class Choice
{
public string Text { get; set; }
public int Index { get; set; }
public object Logprobs { get; set; }
public string FinishReason { get; set; }
}

a classe Usage foi criada por fazer parte da resposta

using System.Text.Json.Serialization;

namespace OraculoApi.Model.OpenAI;

public class Usage
{
public int PromptTokens { get; set; }
public int CompletionTokens { get; set; }
public int TotalTokens { get; set; }
}

Além disso foi criada uma classe para receber os erros chamada OpenAIError

namespace OraculoMVC.Models.OpenAI;

public class OpenAIError
{
public string Message { get; set; }
public string Type { get; set; }
public object Param { get; set; }
public object code { get; set; }
}

Para armazenar o config da aplicação foi criada a classe “OpenAIConfig” que armazenará o endpoint da API e a chave privada criada lá no site exclusiva do seu usuário, que será inserida no arquivo appsettings.json

namespace OraculoApi;

public class OpenAIConfig
{
public string AuthSecret { get; set; }
public string BaseAddress { get; set; }
}

Foram criadas classes de serviço, onde utilizamos os códigos abaixo para fazer a comunicação.

foi criada a interface, chamada: IOpenAITextService que será a base da implementação do serviço

using OraculoApi.Model.OpenAI;

namespace OraculoApi.Interfaces;

public interface IOpenAITextService
{
Task<OpenAIResponse> CompletePrompt(CompletionRequest request);
}

Foi criada a BaseOpenAIService como base para os métodos da chamada à API utilizando HttpCClient e recebendo como parâmetro a chave da API e o URL através do padrão “IOptions”.

using Microsoft.Extensions.Options;
using System.Net.Http.Headers;

namespace OraculoApi.Services;

public class BaseOpenAIService
{
protected readonly HttpClient _httpClient;
private readonly OpenAIConfig _config;

public BaseOpenAIService(HttpClient httpClient, IOptions<OpenAIConfig> options)
{
_config = options.Value;

_httpClient = httpClient;
_httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", _config.AuthSecret);
_httpClient.BaseAddress = new System.Uri(_config.BaseAddress);
}
}

e aí sim, criada a classe de Serviço OpenAITextService responsável por realizar a chamada do serviço, sendo ela filha da classe anterior “BaseOpenAIService”, nela é recebido o resultado e transformado para o objeto de resposta.

using Microsoft.Extensions.Options;
using System.Text;
using System.Text.Json;
using OraculoApi.Interfaces;
using OraculoApi.Model.OpenAI;

namespace OraculoApi.Services;

public class OpenAITextService : BaseOpenAIService, IOpenAITextService
{
public OpenAITextService(HttpClient httpClient, IOptions<OpenAIConfig> options) : base(httpClient, options)
{
}

public async Task<OpenAIResponse> CompletePrompt(OpenAIRequest request)
{
var options = new JsonSerializerOptions() { PropertyNameCaseInsensitive = true };

string json = JsonSerializer.Serialize(request,options);
StringContent content = new StringContent(json, Encoding.UTF8, "application/json");
HttpResponseMessage response = await _httpClient.PostAsync("completions", content);
string responseContent = await response.Content.ReadAsStringAsync();

return JsonSerializer.Deserialize<OpenAIResponse>(responseContent, options);
}
}

Foi criada uma tela básica para receber uma pergunta, em Html onde é postado o resultado e também no retorno tratadas as respostas, no arquivo \Views\Home\Index.cshtml

@{
ViewData["Title"] = "Home Page";
}

<div class="text-center">
<h1 class="display-4">Bem vindo ao Oráculo</h1>
<form method="post">
<input type="text" name="pergunta" placeholder="digite aqui sua pergunta"/>
<input type="submit" value="Enviar" />
</form>

@if (ViewBag.Resposta != null)
{
<br />
<h1>Você perguntou: @ViewBag.Pergunta</h1>
<br />
<br />
<h2>@ViewBag.Resposta</h2>
}
@if(ViewBag.Error != null)
{
<br />
<h1>Você perguntou: @ViewBag.Pergunta</h1>
<br />
<br />
<h2 style="color:red">Houve um erro na comunicação</h2>
<h2 style="color:red">@ViewBag.Error</h2>
}

</div>

Que aciona a HomeController no método “Post” onde acontecerá o acionamento do serviço de comunicação que buscará a resposta e tratará para exibição em tela.

using Microsoft.AspNetCore.Mvc;
using OraculoApi.Interfaces;
using OraculoApi.Model.OpenAI;
using OraculoMVC.Models;
using System.Diagnostics;

namespace OraculoMVC.Controllers
{
public class HomeController : Controller
{
private readonly ILogger<HomeController> _logger;
private readonly IOpenAITextService _openAIService;

public HomeController(ILogger<HomeController> logger, IOpenAITextService openAIService)
{
_logger = logger;
_openAIService = openAIService;
}

public IActionResult Index()
{
return View();
}

[HttpPost]
public async Task<IActionResult> Index(string pergunta)
{
var request = new OpenAIRequest(pergunta);
var response = await _openAIService.CompletePrompt(request);

if (response != null )
{
if (response.Error != null)
{
ViewBag.Pergunta = pergunta;
ViewBag.Error = response.Error.Message.ToString();
}
else if (response.Choices != null)
{
ViewBag.Pergunta = pergunta;
ViewBag.Resposta = response.Choices.Select(a => a.Text).FirstOrDefault();
}
}

return View();
}

public IActionResult About()
{
return View();
}

[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
public IActionResult Error()
{
return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
}
}
}

Na inicialização da aplicação no Program.cs teremos que incluir os elementos conforme a imagem onde temos:

  • leitura do config onde tem as chaves da api e o endpoint, associando à classe “OpenAIConfig”.
  • injeção de dependência da classe de serviço (OpenAITextService).

Além disso, o nosso AppSettings.Json deverá receber a configuração de segurança para acesso à api.

{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"OpenAIConfig": {
"BaseAddress": "https://api.openai.com/v1/",
"AuthSecret": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}
}

Então vamos executar a aplicação, conforme a tela abaixo você vê que há apenas um textbox para digitação.

Feita a pesquisa, é acionada a api, que trará a resposta gerada pela inteligência artificial.

Resumindo, tudo depende de como você pede, há inúmeras possibilidades e uma delas é pedir para que as respostas sejam geradas num formato que torne possível a transformação em objetos e utilização para outros propósitos, como por exemplo, pedir para que a IA gere um JSON.

As possibilidades são inúmeras, dado que você estabeleça a conexão, podemos pedir dados em JSON e fazer as conversões para utilizarmos de acordo com as necessidades dos nossos projetos, veja este exemplo:

Então vem vindo à era da Inteligência artificial, com certeza ela mudará tudo aquilo que fizemos até agora, eliminando muito trabalho manual e criando novas possibilidades para quem souber utilizá-la da melhor forma.

Se quiser utilizar o código, postei no meu Github, fique à vontade e nos conte depois o que mais conseguiu fazer utilizando a API !

Link do Repositório

Gostou do artigo? clique no ícone👏e também me siga para ver as próximas publicações !!

Se quiser ver mais também, recomendo o link deste vídeo Henrique que é MVP também e fala mais um pouco sobre o ChatGpt https://www.youtube.com/live/uozy8wr8h4A?feature=share

--

--

Marcio Nizzola

Microsoft MVP | Software Architect na CI&T | Prof. da Etec Itu | Membro Fundador da Comunidade Itu Developers.