Примечание
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
В этом руководстве вы узнаете, как интегрировать API OpenAI в классическое приложение WinUI 3 / Windows App SDK. Мы создадим интерфейс чата, который позволяет создавать ответы на сообщения с помощью API завершения чата OpenAI:
Необходимые компоненты
- Настройте компьютер разработки (см. статью "Начало работы с WinUI").
- Знакомство с основными понятиями, описанными в руководстве по созданию приложения Hello World с помощью C# и WinUI 3 / Пакета SDK для приложений Windows, мы рассмотрим это руководство.
- Ключ API OpenAI на панели мониторинга разработчика OpenAI.
- Пакет SDK OpenAI, установленный в проекте. Ознакомьтесь с документацией По OpenAI для списка библиотек сообщества. В этом руководстве мы будем использовать betalgo/openai.
Создание проекта
- Откройте Visual Studio и создайте проект с помощью
File
>>New
Project
. WinUI
Найдите и выберитеBlank App, Packaged (WinUI 3 in Desktop)
шаблон проекта C#.- Укажите имя проекта, имя решения и каталог. В этом примере наш
ChatGPT_WinUI3
проект принадлежитChatGPT_WinUI3
решению, в котором будет созданоC:\Projects\
.
После создания проекта в Обозреватель решений должна появиться следующая структура файлов по умолчанию:
Настройка переменной среды
Чтобы использовать пакет SDK OpenAI, необходимо задать переменную среды с помощью ключа API. В этом примере мы будем использовать OPENAI_API_KEY
переменную среды. После получения ключа API на панели мониторинга разработчика OpenAI можно задать переменную среды из командной строки следующим образом:
setx OPENAI_API_KEY <your-api-key>
Обратите внимание, что этот метод хорошо подходит для разработки, но вы хотите использовать более безопасный метод для рабочих приложений (например, вы можете сохранить ключ API в безопасном хранилище ключей, к которому удаленная служба может обращаться от имени приложения). Ознакомьтесь с рекомендациями по безопасности ключей OpenAI.
Установка пакета SDK OpenAI
В меню Visual Studio View
выберите Terminal
. Должен появиться экземпляр Developer Powershell
. Выполните следующую команду из корневого каталога проекта, чтобы установить пакет SDK:
dotnet add package Betalgo.OpenAI
Инициализация пакета SDK
Инициализировать MainWindow.xaml.cs
пакет SDK с помощью ключа API:
//...
using OpenAI;
using OpenAI.Managers;
using OpenAI.ObjectModels.RequestModels;
using OpenAI.ObjectModels;
namespace ChatGPT_WinUI3
{
public sealed partial class MainWindow : Window
{
private OpenAIService openAiService;
public MainWindow()
{
this.InitializeComponent();
var openAiKey = Environment.GetEnvironmentVariable("OPENAI_API_KEY");
openAiService = new OpenAIService(new OpenAiOptions(){
ApiKey = openAiKey
});
}
}
}
Создание пользовательского интерфейса чата
Мы будем использовать StackPanel
для отображения списка сообщений и TextBox
разрешения пользователям вводить новые сообщения. Обновите файл MainWindow.xaml
следующим образом:
<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>
Реализация отправки, получения и отображения сообщений
SendButton_Click
Добавьте обработчик событий для обработки отправки, получения и отображения сообщений:
public sealed partial class MainWindow : Window
{
// ...
private async void SendButton_Click(object sender, RoutedEventArgs e)
{
string userInput = InputTextBox.Text;
if (!string.IsNullOrEmpty(userInput))
{
AddMessageToConversation($"User: {userInput}");
InputTextBox.Text = string.Empty;
var completionResult = await openAiService.ChatCompletion.CreateCompletion(new ChatCompletionCreateRequest()
{
Messages = new List<ChatMessage>
{
ChatMessage.FromSystem("You are a helpful assistant."),
ChatMessage.FromUser(userInput)
},
Model = Models.Gpt_4_1106_preview,
MaxTokens = 300
});
if (completionResult != null && completionResult.Successful) {
AddMessageToConversation("GPT: " + completionResult.Choices.First().Message.Content);
} else {
AddMessageToConversation("GPT: Sorry, something bad happened: " + completionResult.Error?.Message);
}
}
}
private void AddMessageToConversation(string message)
{
ConversationList.Items.Add(message);
ConversationList.ScrollIntoView(ConversationList.Items[ConversationList.Items.Last()]);
}
}
Выполнить приложение
Запустите приложение и попробуйте чаты! Отобразятся примерно следующие сведения:
Улучшение интерфейса чата
Давайте внося следующие улучшения в интерфейс чата:
- Добавьте в
ScrollViewer
приложениеStackPanel
для включения прокрутки. - Добавьте ответ
TextBlock
GPT таким образом, чтобы визуально отличаться от входных данных пользователя. - Добавьте значение
ProgressBar
, указывающее, когда приложение ожидает ответа от API GPT. StackPanel
Центр в окне, аналогично веб-интерфейсу ChatGPT.- Убедитесь, что сообщения упаковываются в следующую строку, когда они достигают края окна.
TextBox
Сделайте его более крупным и адаптивным к ключуEnter
.
Начиная с верхней части:
Добавить ScrollViewer
ListView
Обертывание в окне для включения вертикальной ScrollViewer
прокрутки в длинных беседах:
<StackPanel Orientation="Vertical" HorizontalAlignment="Stretch">
<ScrollViewer x:Name="ConversationScrollViewer" VerticalScrollBarVisibility="Auto" MaxHeight="500">
<ListView x:Name="ConversationList" />
</ScrollViewer>
<!-- ... -->
</StackPanel>
Использование TextBlock
Измените AddMessageToConversation
метод, чтобы изменить стиль входных данных пользователя и ответ GPT по-другому:
// ...
private void AddMessageToConversation(string message)
{
var messageBlock = new TextBlock();
messageBlock.Text = message;
messageBlock.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());
}
Добавить ProgressBar
Чтобы указать, когда приложение ожидает ответа, добавьте в ProgressBar
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>
Затем обновите SendButton_Click
обработчик событий, чтобы отобразить ProgressBar
время ожидания ответа:
private async void SendButton_Click(object sender, RoutedEventArgs e)
{
ResponseProgressBar.Visibility = Visibility.Visible; // new!
string userInput = InputTextBox.Text;
if (!string.IsNullOrEmpty(userInput))
{
AddMessageToConversation("User: " + userInput);
InputTextBox.Text = string.Empty;
var completionResult = await openAiService.Completions.CreateCompletion(new CompletionCreateRequest()
{
Prompt = userInput,
Model = Models.TextDavinciV3
});
if (completionResult != null && completionResult.Successful) {
AddMessageToConversation("GPT: " + completionResult.Choices.First().Text);
} else {
AddMessageToConversation("GPT: Sorry, something bad happened: " + completionResult.Error?.Message);
}
}
ResponseProgressBar.Visibility = Visibility.Collapsed; // new!
}
Центр StackPanel
Чтобы вывести сообщения в центр StackPanel
и вытащить сообщения в сторону TextBox
, настройте Grid
параметры в MainWindow.xaml
:
<Grid VerticalAlignment="Bottom" HorizontalAlignment="Center">
<!-- ... -->
</Grid>
Оболочка сообщений
Чтобы убедиться, что сообщения упаковываются в следующую строку при достижении края окна, обновите MainWindow.xaml
его для использования ItemsControl
.
Замените это:
<ScrollViewer x:Name="ConversationScrollViewer" VerticalScrollBarVisibility="Auto" MaxHeight="500">
<ListView x:Name="ConversationList" />
</ScrollViewer>
На следующий код:
<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>
Затем мы введем MessageItem
класс для упрощения привязки и цвета:
// ...
public class MessageItem
{
public string Text { get; set; }
public SolidColorBrush Color { get; set; }
}
// ...
Наконец, обновите AddMessageToConversation
метод, чтобы использовать новый MessageItem
класс:
// ...
private void AddMessageToConversation(string message)
{
var messageItem = new MessageItem();
messageItem.Text = message;
messageItem.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);
}
// ...
Улучшение TextBox
Чтобы сделать TextBox
ключ более большим и адаптивным Enter
, обновите MainWindow.xaml
следующее:
<!-- ... -->
<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>
<!-- ... -->
Затем добавьте InputTextBox_KeyDown
обработчик событий для обработки 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());
}
}
//...
Запуск улучшенного приложения
Новый и улучшенный интерфейс чата должен выглядеть примерно так:
Кратко
Вот что вы выполнили в этом руководстве:
- Вы добавили возможности API OpenAI в классическое приложение WinUI 3 / Windows App SDK, установив пакет SDK сообщества и инициализировав его с помощью ключа API.
- Вы создали интерфейс чата, который позволяет создавать ответы на сообщения с помощью API завершения чата OpenAI.
- Вы улучшили интерфейс чата, выполнив следующие действия.
- добавление ,
ScrollViewer
TextBlock
с помощью ответа GPT,- добавлено значение
ProgressBar
, указывающее, когда приложение ожидает ответа из API GPT, - центрирование
StackPanel
в окне, - обеспечение упаковки сообщений в следующую строку, когда они достигают края окна, и
TextBox
делает более крупным, изменяемым и адаптивным к ключуEnter
.
- добавление ,
Полные файлы кода
<?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.Managers;
using OpenAI.ObjectModels.RequestModels;
using OpenAI.ObjectModels;
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 OpenAIService(new OpenAiOptions(){
ApiKey = openAiKey
});
}
private async void SendButton_Click(object sender, RoutedEventArgs e)
{
ResponseProgressBar.Visibility = Visibility.Visible;
string userInput = InputTextBox.Text;
if (!string.IsNullOrEmpty(userInput))
{
AddMessageToConversation("User: " + userInput);
InputTextBox.Text = string.Empty;
var completionResult = await openAiService.ChatCompletion.CreateCompletion(new ChatCompletionCreateRequest()
{
Messages = new List<ChatMessage>
{
ChatMessage.FromSystem("You are a helpful assistant."),
ChatMessage.FromUser(userInput)
},
Model = Models.Gpt_4_1106_preview,
MaxTokens = 300
});
Console.WriteLine(completionResult.ToString());
if (completionResult != null && completionResult.Successful)
{
AddMessageToConversation("GPT: " + completionResult.Choices.First().Message.Content);
}
else
{
AddMessageToConversation("GPT: Sorry, something bad happened: " + completionResult.Error?.Message);
}
}
ResponseProgressBar.Visibility = Visibility.Collapsed;
}
private void AddMessageToConversation(string message)
{
var messageItem = new MessageItem();
messageItem.Text = message;
messageItem.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());
}
}
}
}
Связанные
Windows developer