Generate a custom C# ChatGPT API client in minutes with Kiota
Tags: dotnet, chatgpt, csharp, ai
Published: 2023-04-27 19:00:37

During my recent visit to the Microsoft offices in Montréal for a meetup organized by the [MSDEVMTL Meetup group](https://www.meetup.com/msdevmtl/), I had the opportunity to learn more about [Kiota](https://learn.microsoft.com/openapi/kiota/), an incredible tool developed by Microsoft. The Kiota development team showcased its capabilities and demonstrated how it streamlines the process of generating client SDKs for various APIs.

Kiota is an [OpenAPI](https://oai.github.io/Documentation/)-driven code generation tool that enables developers to create SDKs in different programming languages. By using Kiota, you can generate a custom C# client for a given API, tailored to your specific needs. This is an alternative to using third-party packages, as it allows for greater flexibility and control over your implementation.

In this blog post, we will dive into the process of generating a C# client for the [ChatGPT API](https://platform.openai.com/docs/guides/chat) using Kiota, and explore the benefits of having a custom SDK at your disposal instead of [third-party NuGet packages developed by the community](https://platform.openai.com/docs/libraries/community-libraries).

## Why generate your own C# client with Kiota?

Using Kiota to generate your own C# client for any OpenAPI-based API offers several advantages over using a prebuilt, third-party client library.

1. **Customization and extensibility**: Kiota gives you full control over the codebase, and it can be customized according to your needs and requirements.
2. **Up-to-date API coverage**: You can generate an up-to-date C# client anytime the API specification changes.
3. **Reduced dependency on external packages**: Kiota helps avoid potential issues related to version compatibility or package deprecation.
4. **Increased security**: Avoiding the use of third-party client libraries reduces the attack surface.
5. **Batteries included**: Kiota’s default HTTP client includes built-in OpenTelemetry support, a retry helper, a compression handler [and more](https://github.com/microsoft/kiota-http-dotnet/tree/main/src/Middleware).

The best example of Kiota’s capabilities is its use in generating [Microsoft Graph SDKs](https://learn.microsoft.com/graph/sdks/sdk-installation). For the past few months, these SDKs have been generated from the [~25MB Microsoft Graph OpenAPI specification](https://github.com/microsoftgraph/msgraph-metadata/tree/master/openapi). Microsoft utilizes Kiota with this specification to generate SDKs for multiple languages, not just C#, in a matter of seconds.


## Installing Kiota

The easiest way to [install Kiota is as a .NET tool](https://learn.microsoft.com/openapi/kiota/install). Make sure you have [.NET SDK 7](https://dotnet.microsoft.com/download) installed on your system. Simply open a terminal or command prompt and execute the following command:

```bash
dotnet tool install --global Microsoft.OpenApi.Kiota
```

Once the installation is complete, you’ll have access to the `kiota` command line tool, which we’ll use in a next section to generate the C# client for the ChatGPT API.


## Preparing OpenAI’s OpenAPI specification for Kiota

> **TL;DR**: [OpenAI’s OpenAPI specification](https://github.com/openai/openai-openapi/blob/master/openapi.yaml) contains an **invalid number** value `default: inf` for the `CreateChatCompletionRequest.max_tokens` property. Fortunately, we can fix the specification by replacing the line with `nullable: true`.

To generate a C# SDK client with Kiota, we need OpenAI’s OpenAPI specification. It’s hosted on this [GitHub repository](https://github.com/openai/openai-openapi/), and you can [download the current specification directly](https://github.com/openai/openai-openapi/blob/master/openapi.yaml).

However, OpenAI’s API specification includes an invalid number value that makes Kiota generate invalid C#, so we’ll need to modify it manually:

![Replace default: inf with nullable: true for the CreateChatCompletionRequest.max_tokens property](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bfn18wv6fgehzq3fwmie.png)

The modified compatible OpenAI OpenAPI specification can be found [here](https://github.com/asimmon/openai-csharp-client-kiota-demo/blob/main/src/MyApp/openai.yaml).


## Generating OpenAI C# client with Kiota

> The final code sample can be found on [my GitHub repository](https://github.com/asimmon/openai-csharp-client-kiota-demo).

Given an existing C# project named *MyApp* and OpenAI’s OpenAPI specification in a `./openai.yaml` file, execute the following command:

```bash
kiota generate --language csharp --openapi ./openai.yaml --class-name OpenAiClient --namespace-name MyApp.OpenAi --output ./OpenAi
```

Next, copy the output directory `./OpenAi` to the *MyApp* project and add the [required Kiota dependencies](https://learn.microsoft.com/en-us/openapi/kiota/quickstarts/dotnet#add-dependencies):

```bash
dotnet add package Microsoft.Kiota.Abstractions
dotnet add package Microsoft.Kiota.Http.HttpClientLibrary
dotnet add package Microsoft.Kiota.Serialization.Form
dotnet add package Microsoft.Kiota.Serialization.Json
dotnet add package Microsoft.Kiota.Serialization.Text
```

Now we’re almost done. The generated `OpenAiClient` requires an implementation of `IRequestAdapter`, which is a way for Kiota to understand how to make HTTP requests. Fortunately, the package `Microsoft.Kiota.Http.HttpClientLibrary` comes with a defaut implementation: `HttpClientRequestAdapter`.

As Kiota does not know the specific API authentication mechanism, the `HttpClientRequestAdapter` needs an implementation of the `IAuthenticationProvider` interface. By default, the package `Microsoft.Kiota.Abstractions` includes the following implementations:

- `AnonymousAuthenticationProvider`: for APIs that do not require authentication.
- `ApiKeyAuthenticationProvider`: adds an HTTP request header or query parameter for authenticating HTTP requests.
- `BaseBearerTokenAuthenticationProvider`: for more complex scenarios when the API requires a bearer token.

The OpenAI API uses API keys for authentication, in the form of a HTTP header `Authorization: Bearer OPENAI_API_KEY`. This makes it a perfect candidate for `ApiKeyAuthenticationProvider`. We can extend this class to create our own `OpenAiAuthenticationProvider`:

```csharp
public sealed class OpenAiAuthenticationProvider : ApiKeyAuthenticationProvider
{
    public OpenAiAuthenticationProvider(string apiKey)
        : base("Bearer " + apiKey, "Authorization", KeyLocation.Header)
    {
    }
}
```


## Using the generated OpenAI C# client to consume ChatGPT completion API

It is time to consume OpenAI API using our generated C# client! Get your [OpenAI API key](https://platform.openai.com/account/api-keys), then let’s call the [chat completion API](https://platform.openai.com/docs/api-reference/chat):

```csharp
using Microsoft.Kiota.Http.HttpClientLibrary;
using MyApp.OpenAi;
using MyApp.OpenAi.Models;

var authProvider = new OpenAiAuthenticationProvider("<OPENAI_API_KEY>");
var requestAdapter = new HttpClientRequestAdapter(authProvider);
var client = new OpenAiClient(requestAdapter);

var response = await client.Chat.Completions.PostAsync(new CreateChatCompletionRequest
{
    Model = "gpt-3.5-turbo",
    Messages = new List<ChatCompletionRequestMessage>
    {
        new ChatCompletionRequestMessage
        {
            Role = ChatCompletionRequestMessage_role.System,
            Content = "You are a helpful assistant."
        },
        new ChatCompletionRequestMessage
        {
            Role = ChatCompletionRequestMessage_role.User,
            Content = "Who won the world series in 2020?"
        },
        new ChatCompletionRequestMessage
        {
            Role = ChatCompletionRequestMessage_role.Assistant,
            Content = "The Los Angeles Dodgers won the World Series in 2020."
        },
        new ChatCompletionRequestMessage
        {
            Role = ChatCompletionRequestMessage_role.User,
            Content = "Where was it played?"
        }
    }
});

// Prints "The 2020 World Series was played at Globe Life Field in Arlington, Texas."
Console.WriteLine(response.Choices[0].Message.Content);
```


## Conclusion

In this blog post, we’ve demonstrated how to use Kiota to generate a custom C# client for the ChatGPT API. By creating your own client, you gain full control over the codebase, allowing for better customization, extensibility, and security. Additionally, you can easily keep your client up-to-date with any API changes and minimize dependencies on external packages. This opens up new possibilities and flexibility in how you interact with the ChatGPT API and other OpenAPI-based APIs, making it easier to integrate them into your projects.

Now that you’re equipped with the knowledge of how to generate and use a custom C# client with Kiota, you can explore other OpenAPI specifications and generate clients for different APIs, tailoring them to your specific needs.