Refactoring

This commit is contained in:
Simon Lübeß 2023-10-11 14:41:43 +02:00
parent 9c298c6e76
commit e4821d2d7e
6 changed files with 265 additions and 267 deletions

View File

@ -0,0 +1,16 @@
namespace KIKunstKirstenKlöckner.Data;
/// <summary>
/// Enthält Daten für die AiArt
/// </summary>
public class AiArtPageData
{
private readonly ImageGenerator _imageGenerator;
public ImageGenerator ImageGenerator => _imageGenerator;
public AiArtPageData(ImageGenerator imageGenerator)
{
_imageGenerator = imageGenerator;
}
}

View File

@ -0,0 +1,6 @@
namespace KIKunstKirstenKlöckner.Data;
public class ChatGPT
{
}

View File

@ -0,0 +1,105 @@
using DataAccess.Data;
using DataAccess.Models;
using Radzen;
using System.Diagnostics;
namespace KIKunstKirstenKlöckner.Data;
public class ImageGenerator
{
private readonly HttpClient _client = new();
private readonly BildInfoData _bildInfoData;
public ImageGenerator(IConfiguration config, BildInfoData bildInfoData)
{
_bildInfoData = bildInfoData;
string? inferenceApiKey = config.GetValue<string>("API:HF_Inference");
_client.DefaultRequestHeaders.Clear();
_client.DefaultRequestHeaders.Add("Authorization", $"Bearer {inferenceApiKey}");
}
/// <summary>
/// Geneiert das Bild für den aktuellen <see cref="_imagePrompt"/>
/// </summary>
public async Task<string?> GenerateImageAsync(string prompt, string negativePromt, int? width, int? height, WunschInfoModel wunschInfo, bool isRetry = false)
{
var postData = new
{
inputs = prompt,
parameters = new
{
negative_prompt = negativePromt, //"photorealistic, highly detailed, 8K, portrait",
width = width,
height = height
},
options = new
{
// Cache deaktivieren, damit Huggingface für den selben Prompt unterschiedliche Ergebnisse liefert
use_cache = false,
// Erst wenn wir bereits in einem retry sind warten wir implizit auf das Model. (ignoriert quasi 503-Fehler)
wait_for_model = true
}
};
JsonContent content = JsonContent.Create(postData);
try
{
//const string modelName = "Nacken/kkkk-sdxl-5000";
const string modelName = "Nacken/kkk-sdxl-18000";
var inferenceModelUrl = $"https://api-inference.huggingface.co/models/{modelName}";
var response = await _client.PostAsync(inferenceModelUrl, content);
if (response?.IsSuccessStatusCode == true)
{
await using Stream imageStream = await response.Content.ReadAsStreamAsync();
using Image image = await Image.LoadAsync(imageStream);
DateTime imageDate = DateTime.Now;
BildInfoModel bildInfo = new()
{
Dateiname = "PlaceHolder",
Datum = imageDate,
ImageModel = modelName,
WunschId = wunschInfo.Id
};
await _bildInfoData.AddBildInfoAsync(bildInfo);
string imgUrl = $"generated_images/Image_{bildInfo.Id}.jpg";
string mapPath = $"./wwwroot/{imgUrl}";
await image.SaveAsJpegAsync(mapPath);
bildInfo.Dateiname = imgUrl;
await _bildInfoData.UpdateBildInfoDateinameAsync(bildInfo);
return imgUrl;
}
else
{
Console.WriteLine($"Image conversion failed: {response}");
if (Debugger.IsAttached)
Debugger.Break();
return null;
}
}
catch (Exception exception)
{
Console.WriteLine($"Image request failed: {exception}");
if (Debugger.IsAttached)
Debugger.Break();
return null;
}
}
}

View File

@ -3,16 +3,18 @@
@using OpenAI_API @using OpenAI_API
@using OpenAI_API.Chat @using OpenAI_API.Chat
@using OpenAI_API.Models @using OpenAI_API.Models
@using System.Diagnostics
@using DataAccess.Data @using DataAccess.Data
@using DataAccess.Models @using DataAccess.Models
@using KIKunstKirstenKlöckner.Data
@inject IConfiguration Config @inject IConfiguration Config
@inject TooltipService TooltipService @inject TooltipService TooltipService
@inject NotificationService NotificationService
@inject DialogService DialogService @inject DialogService DialogService
@inject BildInfoData BildInfoData; @* @inject AiArtPageData AiArtData; *@
@inject WunschInfoData WunschInfoData; @inject WunschInfoData WunschInfoData;
@inject ImageGenerator ImageGenerator;
<PageTitle>AiArt</PageTitle> <PageTitle>AiArt</PageTitle>
@ -32,10 +34,10 @@
MouseLeave="TooltipService.Close" MouseLeave="TooltipService.Close"
AlignItems="AlignItems.Center" Wrap="FlexWrap.Wrap"> AlignItems="AlignItems.Center" Wrap="FlexWrap.Wrap">
<RadzenText>Temperature:</RadzenText> <RadzenText>Temperature:</RadzenText>
<RadzenSlider @bind-Value=@temperature TValue="float" <RadzenSlider @bind-Value=@_temperature TValue="float"
Step="0.1" Min="0.0m" Max="2.0m"> Step="0.1" Min="0.0m" Max="2.0m">
</RadzenSlider> </RadzenSlider>
<RadzenText>@temperature</RadzenText> <RadzenText>@_temperature</RadzenText>
</RadzenStack> </RadzenStack>
<RadzenStack Orientation="Orientation.Horizontal" <RadzenStack Orientation="Orientation.Horizontal"
AlignItems="AlignItems.Center" Wrap="FlexWrap.Wrap"> AlignItems="AlignItems.Center" Wrap="FlexWrap.Wrap">
@ -46,11 +48,17 @@
<RadzenNumeric ShowUpDown = "false" TValue = "int?" @bind-Value=@height /> <RadzenNumeric ShowUpDown = "false" TValue = "int?" @bind-Value=@height />
</RadzenStack> </RadzenStack>
</RadzenStack> </RadzenStack>
<RadzenStack Orientation="Orientation.Horizontal"
AlignItems="AlignItems.Center" Wrap="FlexWrap.Wrap">
<RadzenCheckBox @bind-Value=@_useGpt4>
Verwende Gibbidy 4
</RadzenCheckBox>
</RadzenStack>
</RadzenCard> </RadzenCard>
</ChildContent> </ChildContent>
</RadzenPanel> </RadzenPanel>
<RadzenButton Visible=@_buttonVisible Click=@(async ()=> await DoStuff(true))>Generate</RadzenButton> <RadzenButton Visible=@_buttonVisible Click=@(async ()=> await GenerateImages(true))>Generate</RadzenButton>
<RadzenPanel AllowCollapse="true" Style="width: 500px;" Text="Zeige Prompt"> <RadzenPanel AllowCollapse="true" Style="width: 500px;" Text="Zeige Prompt">
<ChildContent> <ChildContent>
@ -59,7 +67,7 @@
MouseEnter="@(args => ShowTemperatureTooltip(args))" MouseEnter="@(args => ShowTemperatureTooltip(args))"
MouseLeave="TooltipService.Close" MouseLeave="TooltipService.Close"
AlignItems="AlignItems.Center" Wrap="FlexWrap.Wrap"> AlignItems="AlignItems.Center" Wrap="FlexWrap.Wrap">
<RadzenText>@_imagePromptEnglish</RadzenText> <RadzenText>@_imagePrompt</RadzenText>
</RadzenStack> </RadzenStack>
</RadzenCard> </RadzenCard>
</ChildContent> </ChildContent>
@ -70,7 +78,7 @@
<RadzenCard class="rz-mt-4" Style="width: 800px;"> <RadzenCard class="rz-mt-4" Style="width: 800px;">
<RadzenText>@_imageDescription</RadzenText> <RadzenText>@_imageIdea</RadzenText>
</RadzenCard> </RadzenCard>
@ -83,7 +91,7 @@
<RadzenText Visible=@_addonsVisible TextStyle="TextStyle.H2">Verändere hier dein Bild durch Worte:</RadzenText> <RadzenText Visible=@_addonsVisible TextStyle="TextStyle.H2">Verändere hier dein Bild durch Worte:</RadzenText>
<RadzenTextBox Visible=@_addonsVisible @bind-Value=@addons Placeholder="z.B. Mehr Farben" /> <RadzenTextBox Visible=@_addonsVisible @bind-Value=@addons Placeholder="z.B. Mehr Farben" />
<RadzenButton Visible=@_bothVisible Click=@(async ()=> await DoStuff(false))>Generate</RadzenButton> <RadzenButton Visible=@_bothVisible Click=@(async ()=> await GenerateImages(false))>Generate</RadzenButton>
<RadzenCard> <RadzenCard>
<RadzenRow Style="width:24.5em" Gap="0.5rem" RowGap="0.5rem"> <RadzenRow Style="width:24.5em" Gap="0.5rem" RowGap="0.5rem">
@ -115,9 +123,13 @@
</section> </section>
@code { @code {
/// <summary>
/// Wenn <see langword="true"/> wird GPT4 verwendet um die Idee zu interpretieren.
/// </summary>
private bool _useGpt4;
private int maxAddons = 2; private int maxAddons = 2;
private int amountOfAddons = 0; // wird später geändert private int amountOfAddons = 0; // wird später geändert
private string _imageDescriptionPrompt = "Zusätzlich zu dem Promt erkläre kurz auf deutsch, warum du dich für diese Umsetzung des Titels entschieden hast und gib zusätzlich eine Interpretation des Bildes an. Beginne diesen Teil immer mit \"Beschreibung: \". Zuletzt Beschreibe das Bild und die verbundenen Emotionen mit drei Worten und beginne den Teil mit \"Keywords: \".";
private bool _progressVisible = false; private bool _progressVisible = false;
private bool _buttonVisible = true; private bool _buttonVisible = true;
private bool _addonsVisible = false; private bool _addonsVisible = false;
@ -130,20 +142,8 @@
enum ImageState enum ImageState
{ {
//Hide = 0,
FadeOut, FadeOut,
FadeIn, FadeIn
//Show,
}
// Busy dialog from markup
async Task ShowBusyDialog()
{
await DialogService.OpenAsync("", ds =>
@<RadzenStack AlignItems="AlignItems.Center" Gap="2rem" Class="rz-p-12">
<RadzenProgressBarCircular ProgressBarStyle="ProgressBarStyle.Secondary" Value="100" ShowValue="false" Mode="ProgressBarMode.Indeterminate"/>
<RadzenText TextStyle="TextStyle.H6" Text=@BusyMessage></RadzenText>
</RadzenStack>, new DialogOptions() { ShowTitle = false, Style = "min-height:auto;min-width:auto;width:auto", CloseDialogOnEsc = false });
} }
async Task ShowImageDialog(string imageUrl) async Task ShowImageDialog(string imageUrl)
@ -154,51 +154,25 @@
</div>, new DialogOptions() { CloseDialogOnOverlayClick = true }); </div>, new DialogOptions() { CloseDialogOnOverlayClick = true });
} }
// Busy dialog from string
async Task BusyDialog(string message)
{
await DialogService.OpenAsync("", ds =>
{
RenderFragment content = b =>
{
b.OpenElement(0, "RadzenRow");
b.OpenElement(1, "RadzenColumn");
b.AddAttribute(2, "Size", "12");
b.AddContent(3, message);
b.CloseElement();
b.CloseElement();
};
return content;
}, new DialogOptions() { ShowTitle = false, Style = "min-height:auto;min-width:auto;width:auto", CloseDialogOnEsc = false });
}
void ShowTooltip(ElementReference elementReference, string text, TooltipOptions? options = null) => TooltipService.Open(elementReference, text, options); void ShowTooltip(ElementReference elementReference, string text, TooltipOptions? options = null) => TooltipService.Open(elementReference, text, options);
void ShowTemperatureTooltip(ElementReference elementReference) => TooltipService.Open(elementReference, ds => void ShowTemperatureTooltip(ElementReference elementReference) => TooltipService.Open(elementReference, ds =>
@<div> @<div>
Gibt an, wie <em>kreativ</em> ChatGPT sein soll.<br /> Gibt an, wie <em>kreativ</em> ChatGPT sein soll.<br/>
Ich glaube, eigentlich bedeutet es eher, wie <em>deterministisch</em> die Ausgabe ist.<br />
Bei 0.0 kommt immer fast die selbe Antwort. Bei zu hohen Werten kommt nur noch Schwachsinn.<br />
OpenAI empfielt einen Wert von ca. 0.9 für kreative Anwendungen.
</div> </div>
, ,
new() { Position = TooltipPosition.Bottom, Duration = null}); new() { Position = TooltipPosition.Bottom, Duration = null});
private string _imagePromptEnglish = "";
private string _imageIdea = ""; private string _imageIdea = "";
private string _imageDescription = "";
private string _imagePrompt = ""; private string _imagePrompt = "";
private float temperature = 0.9f; private float _temperature = 0.9f;
private int? width = 1024; private int? width = 1024;
private int? height = 1024; private int? height = 1024;
private string request = ""; private string request = "";
private string addons = ""; private string addons = "";
private OpenAIAPI _openAiApi; private OpenAIAPI _openAiApi;
private Conversation converse; private Conversation? _conversation;
private string _basePrompt; private string _basePrompt;
private string _ideaPrompt; private string _ideaPrompt;
@ -210,258 +184,161 @@
// _basePrompt = await File.ReadAllTextAsync($"{Directory.GetCurrentDirectory()}{@"\wwwroot\prompt.txt"}"); // _basePrompt = await File.ReadAllTextAsync($"{Directory.GetCurrentDirectory()}{@"\wwwroot\prompt.txt"}");
//} //}
private async Task FunnyMessageSwitcher_ImageGen(CancellationToken cancellationToken)
{
Stopwatch sw = Stopwatch.StartNew();
await Task.Delay(1000, cancellationToken);
await UpdateBusyMessage("Dauert noch eine Weile...");
await Task.Delay(1000, cancellationToken);
await UpdateBusyMessage("Gut Ding hat Weil...");
await Task.Delay(1000, cancellationToken);
await UpdateBusyMessage("Sach ma, was issn da l... achso, er ist auf Klo gegangen... Er ist bestimmt gleich wieder da...");
await Task.Delay(1000, cancellationToken);
await UpdateBusyMessage("Na, also langsam verlier ich hier die Geduld, ich dachte KI soll alles schneller machen...");
while (!cancellationToken.IsCancellationRequested)
{
await Task.Delay(1000, cancellationToken);
await UpdateBusyMessage($"Keine Sorge, er arbeitet noch. Die Bilder werden gemalt... ({sw.Elapsed.Seconds}s)");
}
}
async Task UpdateBusyMessage(string newMessage) async Task UpdateBusyMessage(string newMessage)
{ {
BusyMessage = newMessage; BusyMessage = newMessage;
await InvokeAsync(StateHasChanged); await InvokeAsync(StateHasChanged);
} }
private readonly HttpClient _client = new();
private string _inferenceApiKey = "";
private string _openAiApiKey = ""; private string _openAiApiKey = "";
protected override async Task OnInitializedAsync() protected override async Task OnInitializedAsync()
{ {
_inferenceApiKey = Config.GetValue<string>("API:HF_Inference");
_openAiApiKey = Config.GetValue<string>("API:OpenAI"); _openAiApiKey = Config.GetValue<string>("API:OpenAI");
_openAiApi = new OpenAIAPI(_openAiApiKey); _openAiApi = new OpenAIAPI(_openAiApiKey);
var inferenceModelUrl = "https://api-inference.huggingface.co/models/Nacken/kkkk-sdxl-5000";
//_client.BaseAddress = new Uri(inferenceModelUrl);
_client.DefaultRequestHeaders.Clear();
_client.DefaultRequestHeaders.Add("Authorization", $"Bearer {_inferenceApiKey}");
// BildInfoModel bildInfo = new()
// {
// BildBeschreibung = "Test",
// BildPrompt = "Tost",
// Dateiname = "Task",
// Datum = DateTime.Now,
// GPTModel = "Geht dich nichts an",
// ImageModel = "Jup",
// Wunsch = request
// };
// try
// {
// //await BildInfoData.AddBildInfo(bildInfo);
// }
// catch (Exception e)
// {
// Console.WriteLine(e);
// throw;
// }
await base.OnInitializedAsync(); await base.OnInitializedAsync();
} }
/// <summary> private void ClearOldGeneration()
/// Geneiert das Bild für den aktuellen <see cref="_imagePrompt"/>
/// </summary>
public async Task<string?> GenerateImageAsync(string prompt, WunschInfoModel wunschInfo, bool isRetry = false)
{
var postData = new
{
inputs = prompt,
parameters = new
{
negative_prompt = "photorealistic, highly detailed, 8K, portrait",
width = width,
height = height
},
options = new
{
// Cache deaktivieren, damit Huggingface für den selben Prompt unterschiedliche Ergebnisse liefert
use_cache = false,
// Erst wenn wir bereits in einem retry sind warten wir implizit auf das Model. (ignoriert quasi 503-Fehler)
wait_for_model = true
}
};
JsonContent content = JsonContent.Create(postData);
async Task<string?> FailedToDrawImage()
{
bool? retry = await DialogService.Confirm("Leider konnte das Bild nicht gemalt werden. Möchtest du es noch eimal versuchen?", "Ups, ein Fehler ist aufgetreten...",
new ConfirmOptions { OkButtonText = "Ja", CancelButtonText = "Nein" });
if (retry == true)
{
return await GenerateImageAsync(prompt, wunschInfo, true);
}
return null;
}
try
{
const string modelName = "Nacken/kkkk-sdxl-5000";
var inferenceModelUrl = $"https://api-inference.huggingface.co/models/{modelName}";
var response = await _client.PostAsync(inferenceModelUrl, content);
if (response?.IsSuccessStatusCode == true)
{
await using Stream imageStream = await response.Content.ReadAsStreamAsync();
using Image image = await Image.LoadAsync(imageStream);
DateTime imageDate = DateTime.Now;
BildInfoModel bildInfo = new()
{
Dateiname = "PlaceHolder",
Datum = imageDate,
ImageModel = modelName,
WunschId = wunschInfo.Id
};
await BildInfoData.AddBildInfoAsync(bildInfo);
string imgUrl = $"generated_images/Image_{bildInfo.Id}.jpg";
string mapPath = $"./wwwroot/{imgUrl}";
await image.SaveAsJpegAsync(mapPath);
bildInfo.Dateiname = imgUrl;
await BildInfoData.UpdateBildInfoDateinameAsync(bildInfo);
return imgUrl;
}
else
{
Console.WriteLine($"Image conversion failed: {response}");
if (Debugger.IsAttached)
Debugger.Break();
return await FailedToDrawImage();
}
}
catch (Exception exception)
{
Console.WriteLine($"Image request failed: {exception}");
if (Debugger.IsAttached)
Debugger.Break();
return await FailedToDrawImage();
}
return null;
}
private async Task DoStuff(bool newPic)
{ {
// Bilder verbergen
for (int i = 0; i < 4; i++) for (int i = 0; i < 4; i++)
_imageStates[i] = ImageState.FadeOut; _imageStates[i] = ImageState.FadeOut;
_imageIdea = "";
_imagePrompt = "";
}
private async Task RequestImageIdeaAsync()
{
string ideaBasePrompt = await File.ReadAllTextAsync($"{Directory.GetCurrentDirectory()}{@"/wwwroot/idea_prompt.txt"}");
string requestImagePrompt = await File.ReadAllTextAsync($"{Directory.GetCurrentDirectory()}{@"/wwwroot/test_prompt2.txt"}");
ChatRequest chatRequest = new ChatRequest
{
Temperature = _temperature,
Model = _useGpt4 ? Model.GPT4 : Model.ChatGPTTurbo
};
_conversation = _openAiApi.Chat.CreateConversation(chatRequest);
// Wunsch an GPT senden und Bild Idee anfordern
_conversation.AppendUserInput(ideaBasePrompt + " " + request);
_imageIdea = await _conversation.GetResponseFromChatbotAsync();
// Bild Promt anfordern
_conversation.AppendUserInput(requestImagePrompt);
_imagePrompt = await _conversation.GetResponseFromChatbotAsync();
}
/// <summary>
/// Generiert Bilder oder aktualisiert sie mit dem neuen Prompt.
/// </summary>
/// <param name="generateNewImage">Wenn <see langword="true"/>, werden neue Bilder generiert; sonst wird die vorhandene Idee bearbeitet.</param>
private async Task GenerateImages(bool generateNewImage)
{
// Der Dialog blokiert so lange, wie der er offen ist, deshalb dürfen wir hier nicht warten, da wir sonst nie mit der Arbeit anfangen... // Der Dialog blokiert so lange, wie der er offen ist, deshalb dürfen wir hier nicht warten, da wir sonst nie mit der Arbeit anfangen...
//Task busyDialog = ShowBusyDialog(); //Task busyDialog = ShowBusyDialog();
_progressVisible = true; _progressVisible = true;
_buttonVisible = false; _buttonVisible = false;
if (converse == null || newPic) if (_conversation == null || generateNewImage)
{ {
ClearOldGeneration();
amountOfAddons = maxAddons; amountOfAddons = maxAddons;
_addonsVisible = false; _addonsVisible = false;
_bothVisible = _buttonVisible && _addonsVisible; _bothVisible = _buttonVisible && _addonsVisible;
await UpdateBusyMessage("Kirstens Assistent zerbricht sich über deine Idee den Kopf..."); await UpdateBusyMessage("Kirstens Assistent zerbricht sich über deine Idee den Kopf...");
_ideaPrompt = await File.ReadAllTextAsync($"{Directory.GetCurrentDirectory()}{@"/wwwroot/idea_prompt.txt"}");
ChatRequest chatRequest = new ChatRequest
{
Temperature = temperature,
Model = Model.ChatGPTTurbo,
};
converse = _openAiApi.Chat.CreateConversation(chatRequest);
converse.AppendUserInput(_ideaPrompt + " " + request);
_imageIdea = await converse.GetResponseFromChatbotAsync();
_basePrompt = await File.ReadAllTextAsync($"{Directory.GetCurrentDirectory()}{@"/wwwroot/test_prompt2.txt"}");
converse.AppendUserInput(_basePrompt);
await RequestImageIdeaAsync();
} }
else else
{ {
if (amountOfAddons > 0) throw new NotImplementedException("Verändern von Idees ist nicht implementiert");
{ // if (amountOfAddons > 0)
amountOfAddons--; // {
_bothVisible = _buttonVisible && _addonsVisible; // amountOfAddons--;
await UpdateBusyMessage("Kirstens Assistent passt das Bild an deine Wünsche an..."); // _bothVisible = _buttonVisible && _addonsVisible;
string addonsPrompt1 = "Erstelle einen neuen Prompt auf englisch mit den gleichen Restriktionen auf Basis des Alten mit folgender Anpassung: "; // await UpdateBusyMessage("Kirstens Assistent passt das Bild an deine Wünsche an...");
string addonsPrompt2 = ". Denke daran nur den Prompt zu generieren und noch keine Beschreibung oder ähnliches."; // string addonsPrompt1 = "Erstelle einen neuen Prompt auf englisch mit den gleichen Restriktionen auf Basis des Alten mit folgender Anpassung: ";
// string addonsPrompt2 = ". Denke daran nur den Prompt zu generieren und noch keine Beschreibung oder ähnliches.";
converse.AppendUserInput(addonsPrompt1 + addons + addonsPrompt2); // _conversation.AppendUserInput(addonsPrompt1 + addons + addonsPrompt2);
} // }
} }
_imagePromptEnglish = await converse.GetResponseFromChatbotAsync(); _imagePrompt = "kkkk " + _imagePrompt + " kkkk Watercolor + ink on paper, Pen drawing, wet-on-wet technique, dry-on-dry technique, dabbing technique. ";
_imagePrompt = _imagePromptEnglish;
_imagePrompt += "kkkk Watercolor + ink on paper, Pen drawing, wet-on-wet technique, dry-on-dry technique, dabbing technique. ";
converse.AppendUserInput(_imageDescriptionPrompt);
_imageDescription = await converse.GetResponseFromChatbotAsync();
await UpdateBusyMessage("Kirstens Assistent hat eine Idee! Er wird sie nun malen..."); await UpdateBusyMessage("Kirstens Assistent hat eine Idee! Er wird sie nun malen...");
WunschInfoModel wunschInfo = new() WunschInfoModel wunschInfo = new()
{ {
BildBeschreibung = _imageDescription, BildBeschreibung = _imageIdea,
BildPrompt = _imagePrompt, BildPrompt = _imagePrompt,
Datum = DateTime.Now, Datum = DateTime.Now,
GPTModel = converse.Model, GPTModel = _conversation.Model,
Wunsch = request Wunsch = request
}; };
// TODO: Try try
{
await WunschInfoData.AddWunschInfoAsync(wunschInfo); await WunschInfoData.AddWunschInfoAsync(wunschInfo);
}
catch (Exception e)
{
NotificationService.Notify(new NotificationMessage()
{
Summary = "Es ist ein Fehler aufgetreten, bitte versuche es erneut."
});
return;
}
int generatedImages = 0;
try
{
// Vier Bilder generieren // Vier Bilder generieren
for (int i = 0; i < 4; i++) for (int i = 0; i < 4; i++)
{ {
_imageUrls[i] = await GenerateImageAsync(_imagePrompt, wunschInfo); _imageUrls[i] = await ImageGenerator.GenerateImageAsync(_imagePrompt, "", width, height, wunschInfo);
// Kein Bild -> Fehler
if (_imageUrls[i] == null)
{
bool? retry = await DialogService.Confirm(
"Leider konnte das Bild nicht gemalt werden. Möchtest du es noch eimal versuchen?",
"Ups, ein Fehler ist aufgetreten...",
new ConfirmOptions { OkButtonText = "Ja", CancelButtonText = "Nein" });
if (retry == true)
{
await ImageGenerator.GenerateImageAsync(_imagePrompt, "", width, height, wunschInfo);
}
}
generatedImages++;
_imageStates[i] = ImageState.FadeIn; _imageStates[i] = ImageState.FadeIn;
await InvokeAsync(StateHasChanged); await InvokeAsync(StateHasChanged);
} }
}
catch (Exception e)
{
NotificationService.Notify(new NotificationMessage()
{
Summary = "Es ist ein Fehler beim Erzeugen der Bilder aufgetreten, bitte versuche es erneut."
});
if (generatedImages == 0)
{
// TODO: Delete WunschInfo
}
}
_progressVisible = false; _progressVisible = false;
_buttonVisible = true; _buttonVisible = true;
@ -477,17 +354,5 @@
_bothVisible = false; _bothVisible = false;
} }
} }
private void NavigateToGallery()
{
NavigationManager.NavigateTo("/gallery");
}
[Inject]
private NavigationManager NavigationManager { get; set; }
[Inject]
private IWebHostEnvironment _environment { get; set; }
} }

View File

@ -1,5 +1,6 @@
using DataAccess.Data; using DataAccess.Data;
using DataAccess.DbAccess; using DataAccess.DbAccess;
using KIKunstKirstenKlöckner.Data;
using Radzen; using Radzen;
var builder = WebApplication.CreateBuilder(args); var builder = WebApplication.CreateBuilder(args);
@ -7,9 +8,14 @@ var builder = WebApplication.CreateBuilder(args);
// Add services to the container. // Add services to the container.
builder.Services.AddRazorPages(); builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor(); builder.Services.AddServerSideBlazor();
builder.Services.AddScoped<TooltipService>(); builder.Services.AddScoped<TooltipService>();
builder.Services.AddScoped<DialogService>(); builder.Services.AddScoped<DialogService>();
builder.Services.AddScoped<NotificationService>(); builder.Services.AddScoped<NotificationService>();
builder.Services.AddScoped<ImageGenerator>();
builder.Services.AddScoped<AiArtPageData>();
builder.Services.AddSingleton<ISqlDataAccess, SqlDataAccess>(); builder.Services.AddSingleton<ISqlDataAccess, SqlDataAccess>();
builder.Services.AddSingleton<BildInfoData>(); builder.Services.AddSingleton<BildInfoData>();
builder.Services.AddSingleton<WunschInfoData>(); builder.Services.AddSingleton<WunschInfoData>();

View File

@ -1,2 +1,2 @@
Gib mir eine kreative und wenn möglich tiefsinnige Idee für ein Kunstwerk. Gib mir eine kreative und wenn möglich tiefsinnige Idee, die nicht unbedingt mit Städten zu tun hat, für ein Kunstwerk.
Der Titel ist: Der Titel ist: