Building a ChatGPT in .NET MAUI Part 1
In this first part of my post, I will focus on how to use the OpenAI APIs through HTTP POST requests, both to get text responses (completions) and to generate images with OpenAI technology.
INFO: It is important to me that you have full confidence in the authenticity of my posts. Therefore, I want to inform you that this publication had the help of GPT-3. However, I always use my criteria to make sure the post is clear and easy to understand. In case I use this tool or any other again in the future, I will let you know in advance to ensure transparency at all times.
WARNING: This post emphasizes the importance of using the application ethically and responsibly, which has been developed on the .NET MAUI platform and is based on OpenAI technology. While I do not consider myself a moral authority, I do recognize that I have made mistakes in the past and that I will continue to learn and evolve as a human being in the future. This same philosophy applies to the technological field, where both users and developers must be aware of the possible ethical and social implications of their actions. It is crucial to consider the impact of technology on society and work together to ensure its appropriate and responsible use. For this, it is necessary to adopt ethical and responsible standards, such as transparency, equity and responsibility. Transparency implies adequate and clear disclosure of the processes and results of the use of technology. Equity, for its part, requires that applications be accessible and fair to all people, regardless of their origin, gender, race or beliefs. And responsibility implies assuming the consequences of our actions and decisions, as well as the social responsibility of guaranteeing that technology does not cause harm to society. In summary, the ethical and responsible use of technology is essential to move towards a more just and equitable society. We need both users and developers to embrace ethical and responsible standards, and work together to ensure that technology is used for the common good.
I want to emphasize that all the information presented in this publication is due to the valuable talk given by Luis Beltran, PhD, who gave us taught how to build a ChatGPT in .NET MAUI with the OpenAI APIs. I appreciate his contribution and hope this post can help other developers implement this technology in their own .NET applications.
Essential parameters for business logic with OpenAI APIs
Before making HTTP POST requests, it is essential to establish an appropriate business logic. It is not necessary to use all the parameters provided by the OpenAI APIs, but rather those that are relevant to the logic of the application. Next I will show you some images that illustrate how to apply this idea in the generation of text (completions) and images (image generation).
Selection of parameters in completions
Selection of parameters in image generation
HTTP POST Request and Response in OpenAI API - Schema
The following images detail the process of generating text (completions) and images (image generation) through the OpenAI APIs.
TIP: For a better understanding, read each part and interact with the images.
To start the process, the user must make a query that triggers an HTTP POST request. It is important to note that such a request must include an authorization header and specify the content type, as well as serialize an object of the
CompletionRequest.cs
(text mode) orGenerationRequest.cs
(image mode) class. With the necessary parameters in a JSON format. Once the request has been prepared, it will be sent to the OpenAI API for processing.In case the API response is successful, a response body will be returned in the
choices
(text mode) ordata
(image mode) field. This response body is deserialized into an object of theCompletionResponse.cs
(text mode) orGenerationResponse.cs
(image mode) class, thus allowing the user to receive the response in the application.
OpenAI API request and response flow with parameters in text mode
OpenAI API request and response flow with parameters in image mode
HTTP POST Request and Response in OpenAI API - Service Layer
Now I will show you in a practical way how the HTTP POST request and response flows work with the OpenAI APIs to generate text and images in the service layer of the application. Join me as we explore the code needed to accomplish these requests:
TIP: For clearer understanding, I suggest you read a part and then check the code. Be sure to pause each process.
Constructor
In the constructor of the OpenAIService class, a connection to the OpenAI API is established by creating an HttpClient
object, which will be used to send HTTP requests to the API.
- The base address of the API is set in the
BaseAddress
property of the HttpClient object. - An authorization header is added to an HTTP request to the OpenAI API using the access token and the
"Bearer"
authorization scheme. This scheme is commonly used in API authorization to send the access token to the protected server, allowing to authenticate and authorize the request for access to the requested resource. - An
Accept
header is added indicating that the client expects to receive a response in JSON format.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class OpenAIService : IOpenAIService
{
HttpClient client;
public OpenAIService()
{
client = new HttpClient();
// Part 1
client.BaseAddress = new Uri(APIConstants.OpenAIUrl);
// Part 2
client.DefaultRequestHeaders.Authorization = new authorizationHeaderValue("Bearer", APIConstants.OpenAIToken);
// Part 3
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
}
}
AskQuestion and CreateImage methods
These methods use the OpenAI APIs to generate text and images from a query string provided as a parameter.
First, create an object of class
CompletionRequest
(for AskQuestion method) orGenerationRequest
(for CreateImage method) and set itsPrompt
property with the supplied query string as parameter.The
JsonSerializer
class is then used to serialize the instance ofCompletionRequest
(for the AskQuestion method) orGenerationRequest
(for the CreateImage method) to JSON format and is stored in the variablebody
.Next, a new instance of the
StringContent
class is created, which is used to send data in JSON format via an HTTP request, wherebody
is the text string containing the data in JSON format,Encoding.UTF8
specifies the character encoding used and"application/json"
specifies the type of content being sent.The
PostAsync
method of the HttpClient class is called with the OpenAI API endpoint URL for outputting text or images and thecontent
variable that contains the body of the POST request. This sends the HTTP POST request to the OpenAI API with the body in JSON format and returns a response.If the response is successful, the content of the response is read and deserialized using the
ReadFromJsonAsync
method and stored in thedata
variable.Next, access the
Choices
(for the AskQuestion method) orData
(for the CreateImage method) property of thedata
variable and use the FirstOrDefault() method to get the firstText
object (for the AskQuestion method) orUrl
(for the CreateImage method) available. This object is returned as a result in each method.If the response is not successful, the method returns a
default
value.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public class OpenAIService : IOpenAIService
{
HttpClient client;
JsonSerializerOptions options = new() { PropertyNameCaseInsensitive = true };
public async Task<string> AskQuestion(string query)
{
// Part 1
var completion = new CompletionRequest()
{
Prompt = query
};
// Part 2 - Serialize parameters for the response
var body = JsonSerializer.Serialize(completion);
// Part 3
var content = new StringContent(body, Encoding.UTF8, "application/json");
// Part 4 - HTTP POST request with headers and parameters
var response = await client.PostAsync(APIConstants.OpenAIEndpoint_Completions, content);
if (response.IsSuccessStatusCode)
{
// Part 5 - Deserialize the response to a object of class
var data = await response.Content.ReadFromJsonAsync<CompletionResponse>(options);
// Part 6
return data?.Choices?.FirstOrDefault().Text;
}
// Part 7
return default;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public class OpenAIService : IOpenAIService
{
HttpClient client;
JsonSerializerOptions options = new() { PropertyNameCaseInsensitive = true };
public async Task<string> CreateImage(string query)
{
// Part 1
var generation = new GenerationRequest()
{
Prompt = query
};
// Part 2 - Serialize parameters for the response
var body = JsonSerializer.Serialize(generation);
// Part 3
var content = new StringContent(body, Encoding.UTF8, "application/json");
// Part 4 - HTTP POST request with headers and parameters
var response = await client.PostAsync(APIConstants.OpenAIEndpoint_Generations, content);
if (response.IsSuccessStatusCode)
{
// Part 5 - Deserialize the response to a object of class
var data = await response.Content.ReadFromJsonAsync<GenerationResponse>(options);
// Part 6
return data.Data?.FirstOrDefault()?.Url;
}
// Part 7
return default;
}
}
Repository
The project is open source and you can see it by clicking on the following image. Don’t hesitate to take a look!
Resources
- Chatting with ChatGPT in .NET MAUI - Tutorial video made by Luis Beltran, PhD.
- Completions - OpenAI official documentation.
- Image generation - OpenAI official documentation.
Publication in Spanish
Conclusions
One of the main ways to interact with OpenAI APIs is through HTTP requests, which allows rich content to be generated from input data. To implement these requests, it is essential to understand the principles of serialization and deserialization to take full advantage of the capabilities of any type of APIs. By adopting appropriate practices and using effective tools, successful and efficient solutions can be generated.
Please feel free to give me your opinion and with the help of my repository, draw your own conclusions. If you have any constructive questions or suggestions, I would very much like to read them. Thanks for your time.