Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
In questa procedura si integreranno le funzionalità di generazione di immagini di DALL-E nell'app desktop WinUI 3/SDK per app di Windows.
Prerequisites
- Configurare il computer di sviluppo (vedere Avviare lo sviluppo di app di Windows).
- Interfaccia di chat funzionale in cui verrà integrata questa funzionalità. Vedere Come aggiungere completamenti della chat OpenAI all'app desktop WinUI/Windows App SDK . Verrà illustrato come integrare DALL-E nell'interfaccia della chat da questa procedura.
- Una chiave API OpenAI dal dashboard degli sviluppatori OpenAI assegnata alla variabile di ambiente
OPENAI_API_KEY. - Un SDK OpenAI installato nel progetto. Per un elenco delle raccolte della community, vedere la documentazione di OpenAI. In questa procedura si userà la libreria ufficiale dell'API .NET OpenAI.
Installare e inizializzare OpenAI SDK
Assicurarsi che la libreria .NET OpenAI sia installata nel progetto eseguendo dotnet add package OpenAI dalla finestra del terminale di Visual Studio. Inizializzare l'SDK con la chiave API OpenAI come indicato di seguito:
//...
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);
}
}
}
Modificare l'interfaccia utente dell'app
Modifica l'oggetto esistente DateTemplate in MainWindow.xaml per includere un Image controllo che visualizza le immagini all'interno della conversazione:
<!-- ... existing XAML ... -->
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<TextBlock Text="{Binding Text}" TextWrapping="Wrap" Margin="5" Foreground="{Binding Color}"/>
<Image Source="{Binding ImageUrl}" Margin="5" Stretch="UniformToFill"/>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
<!-- ... existing XAML ... -->
Si noti che questa procedura presuppone che si abbia un'interfaccia di chat con un oggetto TextBox e Button; vedere Come aggiungere completamenti di chat OpenAI all'app desktop WinUI 3/SDK per app di Windows.
Implementare la generazione di immagini DALL-E
In MainWindow.xaml.cs, aggiungere i metodi seguenti per gestire la generazione e la visualizzazione delle immagini:
// ... existing using statements ...
private async void SendButton_Click(object sender, RoutedEventArgs e)
{
ResponseProgressBar.Visibility = Visibility.Visible;
string userInput = InputTextBox.Text;
if (!string.IsNullOrEmpty(userInput))
{
InputTextBox.Text = string.Empty;
// Use the DALL-E 3 model for image generation.
ImageClient imageClient = openAiService.GetImageClient("dall-e-3");
ClientResult<GeneratedImage> imageResult = await imageClient.GenerateImageAsync(userInput,
new ImageGenerationOptions
{
Size = GeneratedImageSize.W1024xH1024,
ResponseFormat = GeneratedImageFormat.Uri,
EndUserId = "TestUser"
});
if (imageResult.Value != null)
{
AddImageMessageToConversation(imageResult.Value.ImageUri);
}
else
{
AddMessageToConversation("GPT: Sorry, something bad happened.");
}
}
ResponseProgressBar.Visibility = Visibility.Collapsed;
}
private void AddImageMessageToConversation(Uri imageUrl)
{
var imageMessage = new MessageItem
{
ImageUrl = imageUrl.ToString()
};
ConversationList.Items.Add(imageMessage);
// handle scrolling
ConversationScrollViewer.UpdateLayout();
ConversationScrollViewer.ChangeView(null, ConversationScrollViewer.ScrollableHeight, null);
}
Il metodo imageClient.GenerateImageAsync() è responsabile della chiamata dell'API DALL-E di OpenAI. Per altri esempi di utilizzo, vedere gli esempi openAI .NET in GitHub .
Tip
Provare a chiedere a Microsoft Copilot alcuni suggerimenti su diversi modi per usare le API di chat e DALL-E nell'app.
Si noti la presenza di ImageUrl nella classe MessageItem. Si tratta di una nuova proprietà:
public class MessageItem
{
public string Text { get; set; }
public SolidColorBrush Color { get; set; }
public string ImageUrl { get; set; } // new
}
Esecuzione e test
Eseguire l'app, immettere un prompt e fare clic sul pulsante "Invia". L'output dovrebbe essere simile al seguente:
Personalizzare l'interfaccia utente autonomamente
Prova ad aggiungere alcuni pulsanti di scelta all'interfaccia utente per selezionare se includere un'immagine nella conversazione. È quindi possibile modificare il metodo SendButton_Click per chiamare in modo condizionale il metodo di generazione dell'immagine in base alla selezione del pulsante radio.
Recap
In questa guida, si è appreso come:
- Accettare richieste di immagini dagli utenti all'interno di un oggetto
<TextBox>. - Generare immagini usando l'API DALL-E OpenAI.
- Visualizzare l'immagine in un oggetto
<Image>.
File di codice completi
Di seguito sono riportati i file di codice completi per l'interfaccia di chat con DALL-E generazione di immagini. Il codice è stato aggiornato per usare i pulsanti radio per chiamare in modo condizionale la generazione di chat o immagini come suggerito nella sezione Personalizzare da soli l'interfaccia utente.
<?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>
<StackPanel Orientation="Vertical">
<TextBlock Text="{Binding Text}" TextWrapping="Wrap" Margin="5" Foreground="{Binding Color}"/>
<Image Source="{Binding ImageUrl}" Margin="5" Stretch="UniformToFill"/>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
<ProgressBar x:Name="ResponseProgressBar" Height="5" IsIndeterminate="True" Visibility="Collapsed"/>
<StackPanel Orientation="Vertical" Width="300">
<RadioButtons Header="Query type:">
<RadioButton x:Name="chatRadioButton" Content="Chat" IsChecked="True"/>
<RadioButton x:Name="imageRadioButton" Content="Image"/>
</RadioButtons>
<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 System.Threading.Tasks;
using OpenAI;
using OpenAI.Chat;
using OpenAI.Images;
namespace ChatGPT_WinUI3
{
public class MessageItem
{
public string Text { get; set; }
public SolidColorBrush Color { get; set; }
public string ImageUrl { 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 (imageRadioButton.IsChecked == true)
{
await ProcessImageRequestAsync(userInput);
}
else
{
await ProcessChatRequestAsync(userInput);
}
}
catch (Exception ex)
{
AddMessageToConversation($"GPT: Sorry, something bad happened: {ex.Message}");
}
finally
{
ResponseProgressBar.Visibility = Visibility.Collapsed;
}
}
private async Task ProcessImageRequestAsync(string userInput)
{
if (!string.IsNullOrEmpty(userInput))
{
InputTextBox.Text = string.Empty;
// Use the DALL-E 3 model for image generation.
ImageClient imageClient = openAiService.GetImageClient("dall-e-3");
ClientResult<GeneratedImage> imageResult = await imageClient.GenerateImageAsync(userInput,
new ImageGenerationOptions
{
Size = GeneratedImageSize.W1024xH1024,
ResponseFormat = GeneratedImageFormat.Uri,
EndUserId = "TestUser"
});
if (imageResult.Value != null)
{
AddImageMessageToConversation(imageResult.Value.ImageUri);
}
else
{
AddMessageToConversation("GPT: Sorry, something bad happened.");
}
}
}
private async Task ProcessChatRequestAsync(string userInput)
{
if (!string.IsNullOrEmpty(userInput))
{
AddMessageToConversation($"User: {userInput}");
InputTextBox.Text = string.Empty;
var chatClient = openAiService.GetChatClient("gpt-4o");
var chatOptions = new ChatCompletionOptions
{
MaxOutputTokenCount = 300
};
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."}");
}
}
}
private void AddImageMessageToConversation(Uri imageUrl)
{
var imageMessage = new MessageItem
{
ImageUrl = imageUrl.ToString()
};
ConversationList.Items.Add(imageMessage);
// handle scrolling
ConversationScrollViewer.UpdateLayout();
ConversationScrollViewer.ChangeView(null, ConversationScrollViewer.ScrollableHeight, null);
}
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());
}
}
}
}