Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować się zalogować lub zmienić katalog.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Z tego przewodnika dowiesz się, jak zintegrować API OpenAI z aplikacją desktopową WinUI 3 / Windows App SDK. Utworzymy interfejs przypominający czat, który umożliwia generowanie odpowiedzi na wiadomości przy użyciu API generowania tekstu i podpowiedzi OpenAI.
Prerequisites
- Konfigurowanie komputera programistycznego (zobacz Rozpoczynanie tworzenia aplikacji systemu Windows).
- Znajomość podstawowych pojęć dotyczących Jak utworzyć aplikację Hello World przy użyciu języka C# i WinUI/Windows App SDK — będziemy rozwijać ten temat w tym miejscu.
- Klucz API OpenAI z pulpitu nawigacyjnego dewelopera OpenAI.
- W projekcie zainstalowany zestaw SDK OpenAI. Zapoznaj się z dokumentacją OpenAI w celu uzyskania listy bibliotek społeczności. W tym przewodniku użyjemy oficjalnej biblioteki API OpenAI .NET.
Tworzenie projektu
W programie Visual Studio utworzysz nowy projekt WinUI, wykonując kroki opisane w sekcji Tworzenie i uruchamianie pierwszej aplikacji WinUI w artykule Rozpoczynanie opracowywania aplikacji systemu Windows . W tym przykładzie wprowadź ChatGPT_WinUI3 jako nazwę projektu i ChatGPT_WinUI3 nazwę rozwiązania podczas wprowadzania szczegółów projektu w oknie dialogowym.
Ustawianie zmiennej środowiskowej
Aby korzystać z zestawu OpenAI SDK, należy ustawić zmienną środowiskową przy użyciu klucza interfejsu API. W tym przykładzie użyjemy zmiennej środowiskowej OPENAI_API_KEY . Po uzyskaniu klucza interfejsu API z pulpitu nawigacyjnego dewelopera OpenAI, możesz ustawić zmienną środowiskową z poziomu wiersza polecenia w następujący sposób:
setx OPENAI_API_KEY <your-api-key>
Należy pamiętać, że ta metoda działa dobrze w przypadku programowania, ale chcesz użyć bezpieczniejszej metody dla aplikacji produkcyjnych (na przykład: klucz interfejsu API można przechowywać w bezpiecznym magazynie kluczy, do którego usługa zdalna może uzyskiwać dostęp w imieniu aplikacji). Zobacz Najlepsze rozwiązania dotyczące bezpieczeństwa kluczy OpenAI.
Instalowanie biblioteki OpenAI
Z menu programu Visual Studio View wybierz pozycję Terminal. Powinno zostać wyświetlone wystąpienie Developer Powershell . Uruchom następujące polecenie z katalogu głównego projektu, aby zainstalować pakiet OpenAI .NET:
dotnet add package OpenAI
Inicjowanie biblioteki
W MainWindow.xaml.cs zainicjuj bibliotekę OpenAI przy użyciu swojego klucza API:
//...
using OpenAI;
using OpenAI.Chat;
namespace ChatGPT_WinUI3
{
public sealed partial class MainWindow : Window
{
private OpenAIClient openAiService;
public MainWindow()
{
this.InitializeComponent();
var openAiKey = Environment.GetEnvironmentVariable("OPENAI_API_KEY");
openAiService = new(openAiKey);
}
}
}
Tworzenie interfejsu użytkownika czatu
Użyjemy elementu , StackPanel aby wyświetlić listę komunikatów i element , TextBox aby umożliwić użytkownikom wprowadzanie nowych wiadomości. Zaktualizuj MainWindow.xaml w następujący sposób:
<Window
x:Class="ChatGPT_WinUI3.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:ChatGPT_WinUI3"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid>
<StackPanel Orientation="Vertical" HorizontalAlignment="Stretch">
<ListView x:Name="ConversationList" />
<StackPanel Orientation="Horizontal">
<TextBox x:Name="InputTextBox" HorizontalAlignment="Stretch"/>
<Button x:Name="SendButton" Content="Send" Click="SendButton_Click"/>
</StackPanel>
</StackPanel>
</Grid>
</Window>
Implementowanie wysyłania, odbierania i wyświetlania komunikatów
Dodaj procedurę obsługi zdarzeń SendButton_Click do obsługi wysyłania, odbierania i wyświetlania komunikatów:
public sealed partial class MainWindow : Window
{
// ...
private async void SendButton_Click(object sender, RoutedEventArgs e)
{
try
{
string userInput = InputTextBox.Text;
if (!string.IsNullOrEmpty(userInput))
{
AddMessageToConversation($"User: {userInput}");
InputTextBox.Text = string.Empty;
var chatClient = openAiService.GetChatClient("gpt-4o"); // or another model
var chatOptions = new ChatCompletionOptions
{
MaxOutputTokenCount = 300
};
// Assemble the chat prompt with a system message and the user's input
var completionResult = await chatClient.CompleteChatAsync(
[
ChatMessage.CreateSystemMessage("You are a helpful assistant."),
ChatMessage.CreateUserMessage(userInput)
],
chatOptions);
if (completionResult != null && completionResult.Value.Content.Count > 0)
{
AddMessageToConversation($"GPT: {completionResult.Value.Content.First().Text}");
}
else
{
AddMessageToConversation($"GPT: Sorry, something bad happened: {completionResult?.Value.Refusal ?? "Unknown error."}");
}
}
}
catch (Exception ex)
{
AddMessageToConversation($"GPT: Sorry, something bad happened: {ex.Message}");
}
}
private void AddMessageToConversation(string message)
{
ConversationList.Items.Add(message);
ConversationList.ScrollIntoView(ConversationList.Items[ConversationList.Items.Last()]);
}
}
Uruchom aplikację
Uruchom aplikację i spróbuj porozmawiać! Powinna zostać wyświetlona zawartość podobna do następującej:
Ulepszanie interfejsu czatu
Wprowadźmy następujące ulepszenia interfejsu czatu:
- Dodaj element
ScrollViewerdo elementuStackPanel, aby włączyć przewijanie. - Dodaj element
TextBlock, aby wyświetlić odpowiedź GPT w sposób, który wizualnie odróżnia się od wejścia użytkownika. - Dodaj element ,
ProgressBaraby wskazać, kiedy aplikacja oczekuje na odpowiedź z interfejsu API GPT. - Wyśrodkuj
StackPanelw oknie, podobnie jak w przypadku interfejsu internetowego ChatGPT. - Upewnij się, że komunikaty przechodzą do następnego wiersza po osiągnięciu krawędzi okna.
- Zwiększ
TextBoxi spraw, aby reagował naEnterklucz.
Począwszy od góry:
Dodaj ScrollViewer
Zawiń ListView w ScrollViewer, aby umożliwić przewijanie w pionie przy długich konwersacjach.
<StackPanel Orientation="Vertical" HorizontalAlignment="Stretch">
<ScrollViewer x:Name="ConversationScrollViewer" VerticalScrollBarVisibility="Auto" MaxHeight="500">
<ListView x:Name="ConversationList" />
</ScrollViewer>
<!-- ... -->
</StackPanel>
Użyj TextBlock
Zmodyfikuj metodę AddMessageToConversation, aby zmienić styl danych wejściowych użytkownika oraz styl odpowiedzi GPT na różne sposoby.
// ...
private void AddMessageToConversation(string message)
{
var messageBlock = new TextBlock
{
Text = message,
Margin = new Thickness(5)
};
if (message.StartsWith("User:"))
{
messageBlock.Foreground = new SolidColorBrush(Colors.LightBlue);
}
else
{
messageBlock.Foreground = new SolidColorBrush(Colors.LightGreen);
}
ConversationList.Items.Add(messageBlock);
ConversationList.ScrollIntoView(ConversationList.Items.Last());
}
Dodaj ProgressBar
Aby wskazać, kiedy aplikacja czeka na odpowiedź, dodaj element ProgressBar do elementu StackPanel:
<StackPanel Orientation="Vertical" HorizontalAlignment="Stretch">
<ScrollViewer x:Name="ConversationScrollViewer" VerticalScrollBarVisibility="Auto" MaxHeight="500">
<ListView x:Name="ConversationList" />
</ScrollViewer>
<ProgressBar x:Name="ResponseProgressBar" Height="5" IsIndeterminate="True" Visibility="Collapsed"/> <!-- new! -->
</StackPanel>
Następnie zaktualizuj SendButton_Click program obsługi zdarzeń, aby wyświetlić ProgressBar podczas oczekiwania na odpowiedź.
private async void SendButton_Click(object sender, RoutedEventArgs e)
{
ResponseProgressBar.Visibility = Visibility.Visible; // new!
string userInput = InputTextBox.Text;
try
{
if (!string.IsNullOrEmpty(userInput))
{
AddMessageToConversation($"User: {userInput}");
InputTextBox.Text = string.Empty;
var chatClient = openAiService.GetChatClient("gpt-4o"); // or another model
var chatOptions = new ChatCompletionOptions
{
MaxOutputTokenCount = 300
};
// Assemble the chat prompt with a system message and the user's input
var completionResult = await chatClient.CompleteChatAsync(
[
ChatMessage.CreateSystemMessage("You are a helpful assistant."),
ChatMessage.CreateUserMessage(userInput)
],
chatOptions);
if (completionResult != null && completionResult.Value.Content.Count > 0)
{
AddMessageToConversation($"GPT: {completionResult.Value.Content.First().Text}");
}
else
{
AddMessageToConversation($"GPT: Sorry, something bad happened: {completionResult?.Value.Refusal ?? "Unknown error."}");
}
}
}
catch (Exception ex)
{
AddMessageToConversation($"GPT: Sorry, something bad happened: {ex.Message}");
}
finally // new!
{
ResponseProgressBar.Visibility = Visibility.Collapsed; // new!
}
}
Wyśrodkuj StackPanel
Aby wyśrodkować StackPanel i ściągnąć komunikaty w kierunku TextBox, dostosuj ustawienia w Grid w MainWindow.xaml.
<Grid VerticalAlignment="Bottom" HorizontalAlignment="Center">
<!-- ... -->
</Grid>
Zawijanie komunikatów
Aby zapewnić zawijanie komunikatów do następnego wiersza, gdy osiągną one krawędź okna, zaktualizuj MainWindow.xaml do korzystania z ItemsControl.
Zastąp następujące elementy:
<ScrollViewer x:Name="ConversationScrollViewer" VerticalScrollBarVisibility="Auto" MaxHeight="500">
<ListView x:Name="ConversationList" />
</ScrollViewer>
Na ten:
<ScrollViewer x:Name="ConversationScrollViewer" VerticalScrollBarVisibility="Auto" MaxHeight="500">
<ItemsControl x:Name="ConversationList" Width="300">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Text}" TextWrapping="Wrap" Margin="5" Foreground="{Binding Color}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
Następnie wprowadzimy klasę MessageItem ułatwiając powiązanie i kolorowanie:
// ...
public class MessageItem
{
public string Text { get; set; }
public SolidColorBrush Color { get; set; }
}
// ...
Na koniec zaktualizuj metodę AddMessageToConversation , aby użyć nowej MessageItem klasy:
// ...
private void AddMessageToConversation(string message)
{
var messageItem = new MessageItem
{
Text = message,
Color = message.StartsWith("User:") ? new SolidColorBrush(Colors.LightBlue)
: new SolidColorBrush(Colors.LightGreen)
};
ConversationList.Items.Add(messageItem);
// handle scrolling
ConversationScrollViewer.UpdateLayout();
ConversationScrollViewer.ChangeView(null, ConversationScrollViewer.ScrollableHeight, null);
}
// ...
Popraw TextBox
Aby powiększyć TextBox i sprawić, by reagował na klawisz Enter, zaktualizuj MainWindow.xaml w następujący sposób:
<!-- ... -->
<StackPanel Orientation="Vertical" Width="300">
<TextBox x:Name="InputTextBox" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" KeyDown="InputTextBox_KeyDown" TextWrapping="Wrap" MinHeight="100" MaxWidth="300"/>
<Button x:Name="SendButton" Content="Send" Click="SendButton_Click" HorizontalAlignment="Right"/>
</StackPanel>
<!-- ... -->
Następnie dodaj procedurę obsługi zdarzenia InputTextBox_KeyDown, aby obsłużyć klawisz Enter.
//...
private void InputTextBox_KeyDown(object sender, KeyRoutedEventArgs e)
{
if (e.Key == Windows.System.VirtualKey.Enter && !string.IsNullOrWhiteSpace(InputTextBox.Text))
{
SendButton_Click(this, new RoutedEventArgs());
}
}
//...
Uruchamianie ulepszonej aplikacji
Nowy i ulepszony interfejs czatu powinien wyglądać mniej więcej tak:
Recap
Oto, co udało Ci się osiągnąć w tym poradniku:
- Dodałeś funkcje API OpenAI do swojej aplikacji desktopowej WinUI 3 / Windows App SDK, instalując oficjalną bibliotekę OpenAI i inicjując ją za pomocą klucza API.
- Utworzono interfejs przypominający czat, który umożliwia generowanie odpowiedzi na komunikaty przy użyciu API OpenAI do generowania tekstu i tworzenia zapytań.
- Ulepszono interfejs czatu, wykonując następujące elementy:
- dodawanie elementu
ScrollViewer, - przy użyciu elementu
TextBlockaby wyświetlić odpowiedź GPT - dodanie elementu
ProgressBar, aby wskazać, kiedy aplikacja czeka na odpowiedź z interfejsu API GPT, - wyśrodkowanie
StackPanelw oknie, - zapewnienie, że komunikaty są zawijane do następnego wiersza, gdy dotrą do krawędzi okna i
- zwiększenie rozmiaru
TextBox, umożliwienie zmiany jego rozmiaru i reaktywność na klawiszEnter.
- dodawanie elementu
Pełne pliki kodu
Poniższy kod jest pełnym przykładem aplikacji czatu zintegrowanej z funkcją dokończeń czatów OpenAI:
<?xml version="1.0" encoding="utf-8"?>
<Window
x:Class="ChatGPT_WinUI3.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:ChatGPT_WinUI3"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid VerticalAlignment="Bottom" HorizontalAlignment="Center">
<StackPanel Orientation="Vertical" HorizontalAlignment="Center">
<ScrollViewer x:Name="ConversationScrollViewer" VerticalScrollBarVisibility="Auto" MaxHeight="500">
<ItemsControl x:Name="ConversationList" Width="300">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Text}" TextWrapping="Wrap" Margin="5" Foreground="{Binding Color}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
<ProgressBar x:Name="ResponseProgressBar" Height="5" IsIndeterminate="True" Visibility="Collapsed"/>
<StackPanel Orientation="Vertical" Width="300">
<TextBox x:Name="InputTextBox" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" KeyDown="InputTextBox_KeyDown" TextWrapping="Wrap" MinHeight="100" MaxWidth="300"/>
<Button x:Name="SendButton" Content="Send" Click="SendButton_Click" HorizontalAlignment="Right"/>
</StackPanel>
</StackPanel>
</Grid>
</Window>
using Microsoft.UI;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Input;
using Microsoft.UI.Xaml.Media;
using System;
using System.Collections.Generic;
using System.Linq;
using OpenAI;
using OpenAI.Chat;
namespace ChatGPT_WinUI3
{
public class MessageItem
{
public string Text { get; set; }
public SolidColorBrush Color { get; set; }
}
public sealed partial class MainWindow : Window
{
private OpenAIService openAiService;
public MainWindow()
{
this.InitializeComponent();
var openAiKey = Environment.GetEnvironmentVariable("OPENAI_API_KEY");
openAiService = new(openAiKey);
}
private async void SendButton_Click(object sender, RoutedEventArgs e)
{
ResponseProgressBar.Visibility = Visibility.Visible;
string userInput = InputTextBox.Text;
try
{
if (!string.IsNullOrEmpty(userInput))
{
AddMessageToConversation($"User: {userInput}");
InputTextBox.Text = string.Empty;
var chatClient = openAiService.GetChatClient("gpt-4o"); // or another model
var chatOptions = new ChatCompletionOptions
{
MaxOutputTokenCount = 300
};
// Assemble the chat prompt with a system message and the user's input
var completionResult = await chatClient.CompleteChatAsync(
[
ChatMessage.CreateSystemMessage("You are a helpful assistant."),
ChatMessage.CreateUserMessage(userInput)
],
chatOptions);
if (completionResult != null && completionResult.Value.Content.Count > 0)
{
AddMessageToConversation($"GPT: {completionResult.Value.Content.First().Text}");
}
else
{
AddMessageToConversation($"GPT: Sorry, something bad happened: {completionResult?.Value.Refusal ?? "Unknown error."}");
}
}
}
catch (Exception ex)
{
AddMessageToConversation($"GPT: Sorry, something bad happened: {ex.Message}");
}
finally
{
ResponseProgressBar.Visibility = Visibility.Collapsed;
}
}
private void AddMessageToConversation(string message)
{
var messageItem = new MessageItem
{
Text = message,
Color = message.StartsWith("User:") ? new SolidColorBrush(Colors.LightBlue)
: new SolidColorBrush(Colors.LightGreen)
};
ConversationList.Items.Add(messageItem);
// handle scrolling
ConversationScrollViewer.UpdateLayout();
ConversationScrollViewer.ChangeView(null, ConversationScrollViewer.ScrollableHeight, null);
}
private void InputTextBox_KeyDown(object sender, KeyRoutedEventArgs e)
{
if (e.Key == Windows.System.VirtualKey.Enter && !string.IsNullOrWhiteSpace(InputTextBox.Text))
{
SendButton_Click(this, new RoutedEventArgs());
}
}
}
}
Treści powiązane
Windows developer