Integrating OpenAI's ChatGPT into cross-platform .NET applications (2024)

Integrating OpenAI’s ChatGPT into cross-platform .NET applications

From simplified UI design with C# markup to dynamic AI integration
  • April 12, 2024

In this article, we’ll explore Uno Platform implementations using a ChatGPT-enabled chat application. We’ll look at using C# markup, which offers a XAML-like structure to efficiently manage the user interface and functionality. Additionally, we will discuss the Uno.Extensions.Configuration package, which provides robust configuration management, ensuring the secure handling of settings, such as API keys.

Furthermore, we’ll demonstrate the straightforward process of integrating OpenAI services into our .NET projects using NuGet packages and dependency injection. We’ll also introduce MVUX—a method for effective state management that supports data binding and promotes immutability.

By the end of this article, you’ll better understand how to use C# markup, MVUX, and Uno Extensions and apply these techniques in your own Uno Platform projects. You

C# Markup: Simplifying UI Design and Functionality

C# Markup allows developers to use a consistent language for both design and functionality. Structured similarly to XAML, C# Markup simplifies the integration of elements, controls, and bindings, making it more accessible to handle UI tasks. Developers can leverage constructors and extension methods to add controls, set properties, and manage resources effortlessly. Additionally, breaking down code into helper methods improves both the readability and maintainability of the code.

For instance, consider our implementation of a `Prompt` method, designed to render the input textbox and send button section:

public MainPage(){this.Background(ThemeResource.Get<brush>("ApplicationPageBackgroundThemeBrush")).DataContext<bindablemainmodel>((page, vm) =&gt; page.Content(new Grid()//Properties left out for brevity.Children(Header(vm),Messages(vm),Prompt(vm))));}private Grid Prompt(BindableMainModel vm) =&gt; new Grid() .Grid(row: 2) .ColumnDefinitions("*, Auto") .VerticalAlignment(VerticalAlignment.Bottom) .HorizontalAlignment(HorizontalAlignment.Stretch) .Children( new TextBox() .PlaceholderText("Message ChatGPT") .CommandExtensions(x =&gt; x.Command(() =&gt; vm.AskMessage)) .Text(x =&gt; x.Bind(() =&gt; vm.Prompt) .TwoWay() .UpdateSourceTrigger(UpdateSourceTrigger.PropertyChanged)), new Button() .Grid(column: 1) .Style(Theme.Button.Styles.Icon) .Command(() =&gt; vm.AskMessage) .Content( new PathIcon() .Data("M2.01 21L23 12L2.01 3L2 10L17 12L2 14L2.01 21Z") ) );</bindablemainmodel></brush>

To learn more about using C# Markup, please take a look at our C# Markup docs

Configuration Management

Uno Platform provides strong configuration management capabilities, simplifying how developers handle and retrieve application settings. Through the Uno.Extensions.Configuration package, you can effortlessly read and write settings across multiple sources. This is particularly useful for accessing essential parameters like API keys.

For instance, in our ChatGPT example, we use this feature by adding an “ApiKey” attribute in the “AppConfig” section of the appsettings.json file.

{ "AppConfig": { "Environment": "Production", "ApiKey": "<insert access="" api="" generate="" here.="" https:="" key="" key.="" openai="" to="" your="">" }, "ApiClient": { "UseNativeHandler": true }}</insert>

Then we change the existingAppConfigrecord to have anApiKeyproperty that reflects the json structure:

public record AppConfig{ public string? Environment { get; init; }+ public string? ApiKey { get; init; }}

Afterward, we can access theAppConfigclass across our project. This is possible because we can obtain anIOptions<AppConfig> appConfigparameter through Dependency Injection.

By adding configurations to the appsettings.json file and accessing them through theAppConfigclass, developers can simplify the integration of external services like OpenAI. This method improves security and flexibility by keeping sensitive information separate from the main code.

For more information, please see ourConfiguration docs.

Integration with OpenAI Services

Integrating OpenAI services into Uno Platform applications opens up a world of possibilities for creating intelligent and interactive experiences. With the Betalgo.OpenAI NuGet package, developers can access OpenAI services such as ChatGPT and DALL-E with ease.

The integration begins with setting up theOpenAiOptionsclass from OpenAI, this class is responsible for receiving our API Key. So we define aChatAiOptionsthat derives fromOpenAiOptionsand in its constructor we obtain aIOptions<AppConfig>as parameter, where we can access ourAppConfig.ApiKey.

Once that is done, we can start working on ourChatServiceimplementation. This class receive aIChatCompletionServiceas parameter, that was registered in the Dependency Injection container. We are particularly interrested on two methods of the implementation of thar interface,CreateCompletion(takes a request as parameter and returns an object with the AI response) andCreateCompletionAsStream(takes a request as parameter and asyncronously returns the AI response as it gets generated).

Users have the option to input a message to provide context for ChatGPT, guiding its conversation or behavior. For instance, they can provide background information or specific topics of interest. For our sample we use this in “You are Uno ChatGPT Sample, a helpful assistant helping users to learn more about how to develop using Uno Platform.”, ChatGPT can adopt a particular persona or focus its responses accordingly. For example, users could input lines like “You are Borat, a clueless journalist from Kazakhstan” or “You are Buzz Lightyear, a space ranger on a mission to infinity and beyond” allowing ChatGPT to respond in character or tailor its answers to match the chosen persona.

ChatGPT as Borat and Buzz Lightyear:

Integrating OpenAI's ChatGPT into cross-platform .NET applications (1)

To ensure that this setup functions correctly, it’s essential to remember to register the necessary classes in the Dependency Injection container.

.ConfigureServices( (context, services) =&gt; { services .AddSingleton<openaioptions chataioptions="">() .AddSingleton<ichatcompletionservice openaiservice="">() .AddSingleton<ichatservice chatservice="">(); })</ichatservice></ichatcompletionservice></openaioptions>

With the ChatService acting as a bridge between the model and OpenAI services, developers can incorporate AI-driven functionalities into their applications.

For more information, please see ourDependency Injection docs.

MVUX: State Management Made Simple

MVUX, a pattern for state management, offers an alternative to traditional MVVM architectures. Built on the Model-View-Update paradigm, MVUX simplifies state management and the pain of dealing with MVVMwhile encouraging immutability. By defining models, views, and update actions, developers can create robust and responsive applications.

MVUX extends the concept of immutability through the use of records, ensuring that states remain consistent throughout the application lifecycle. This approach enhances reliability and predictability, crucial for building complex applications.

Within our app we have aMainModelpartialrecordwhere we defined the properties that will be bound to our view.

public IState<string> Prompt =&gt; State.Value(this, () =&gt; string.Empty);public IState<bool> UseStream =&gt; State.Value(this, () =&gt; CanStream);public IListState<message> Messages =&gt; ListState<message>.Empty(this);</message></message></bool></string>

Also we have the command methods that will be triggered when the Send button is pressed and will connect with the OpenAI services, sending our request and getting a response. We defined two methods, the first oneAskthat uses theChatService.CreateCompletion(...)method that returns the complete AI response and theAskAsStreamthat uses theChatService.CreateCompletionAsStream(...)method that asyncronously returns the AI response as it gets generated. Take a look at how theAskAsStreamwas implemented:

private async ValueTask AskAsStream(string prompt, CancellationToken ct){ if (prompt is null or { Length: 0 }) { return; } //Add the User prompt message to the conversation await Messages.AddAsync(new Message(prompt), ct); await Prompt.Set(string.Empty, ct); //Add a Plaecholder loading message while awaiting the AI response var message = Message.CreateLoading(); await Messages.AddAsync(message, ct); //Create the request with the conversation history var request = await CreateRequest(); //Send the request to AI Services await foreach (var response in _chatService.AskAsStream(request).WithCancellation(ct)) { //Finds the message with same id and updates the instance with new part of response await Messages.UpdateAsync(message.With(response), ct); }}

For more information about how to use MVUX, please see our MVUX docs. Also see our guidance of How to Write Proper Records with MVUX.

Next Steps

To get started with Uno Platform, install the Visual Studio extension and follow the beginner-oriented Counter App or Simple Calc workshop. Both are doable during a coffee break. Or, for more advanced topics, use our Tube Player workshop.

Install Uno Platform Extension

Integrating OpenAI's ChatGPT into cross-platform .NET applications (2)

Uno Platform Team

Tags:

Related Posts

Cross-Platform Mobile Social Networking App

Cross-Platform Mobile Social Networking App

🕓 5 MIN Hug App by Some …

Toyota migrates mobile app to Uno Platform

Toyota migrates mobile app to Uno Platform

🕓 5 MIN A car giant’s strategic …

Why choose Uno Platform for your next .NET Project?

Why choose Uno Platform for your next .NET Project?

🕓 13 MIN Building a cross-platform application …

We use cookies on our website to give you the most relevant experience by remembering your preferences and repeat visits. By clicking “Accept”, you consent to the use of ALL the cookies.

Integrating OpenAI's ChatGPT into cross-platform .NET applications (2024)
Top Articles
Latest Posts
Article information

Author: Ray Christiansen

Last Updated:

Views: 5648

Rating: 4.9 / 5 (49 voted)

Reviews: 88% of readers found this page helpful

Author information

Name: Ray Christiansen

Birthday: 1998-05-04

Address: Apt. 814 34339 Sauer Islands, Hirtheville, GA 02446-8771

Phone: +337636892828

Job: Lead Hospitality Designer

Hobby: Urban exploration, Tai chi, Lockpicking, Fashion, Gunsmithing, Pottery, Geocaching

Introduction: My name is Ray Christiansen, I am a fair, good, cute, gentle, vast, glamorous, excited person who loves writing and wants to share my knowledge and understanding with you.