@page "/aiart" @using OpenAI_API @using OpenAI_API.Chat @using OpenAI_API.Models @using DataAccess.Data @using DataAccess.Models @using KIKunstKirstenKlöckner.Data @using KIKunstKirstenKlöckner.Extensions @using System.Diagnostics @inject IJSRuntime JSRuntime @inject IConfiguration Config @inject TooltipService TooltipService @inject NotificationService NotificationService @inject DialogService DialogService @inject ImageGenerator ImageGenerator; @inject BildInfoData BildInfoData; @inject WunschInfoData WunschInfoData; @implements IAsyncDisposable Wunschbild Generator

Hier werden
deine Wünsche
Wirklichkeit

Weiter unten findest du meinen Assistenten. Gebe ihm deinen Wunsch und er wird sich etwas tolles dazu überlegen. Es lohnt sich geduldig zu sein.
Scrolle einfach nach unten!

Previous Next

Wunschbilder von KI nur für dich

Nenne uns deinen Wunsch: @* Zusätzliche Optionen *@ Temperature: @_temperature Resolution: x @* *@ Generate
@if (_imageSectionVisible) {
Die Idee, die gemalt wird: @_imageIdea Verändere hier dein Bild durch Worte: await UpdateImagesAsync())>Generate @_imagePromts[0]
Model: @_bildInfos[0]?.ImageModel
@_imagePromts[1]
Model: @_bildInfos[1]?.ImageModel
@_imagePromts[2]
Model: @_bildInfos[2]?.ImageModel
@_imagePromts[3]
Model: @_bildInfos[3]?.ImageModel
} @if (!_imageSectionVisible) {
}
@code { // Animation stuff private int _indexForCarusell = 0; private ElementReference animatedEntrySection; private List animatedElements = new List(); private Func removeScrollListener; protected override async Task OnAfterRenderAsync(bool firstRender) { if (firstRender) { animatedElements.Add(animatedEntrySection); removeScrollListener = await JSRuntime.InvokeAsync>( "initHeroAreaScrollAnimation" ); await JSRuntime.InvokeVoidAsync("initScrollAnimations", animatedElements); } } private bool isDisposed = false; public async ValueTask DisposeAsync() { if (!isDisposed) { if (removeScrollListener != null) { await removeScrollListener.Invoke(); } isDisposed = true; } } private async Task OnGenerateButtonClickAsync() { _imageSectionVisible = true; StateHasChanged(); await Task.Delay(100); await JSRuntime.InvokeVoidAsync("scrollToElement", "imageSection"); await GenerateImagesAsync(); } IEnumerable? _allBildInfos; enum GptModel { Gpt3_5_turbo, Gpt4_turbo, Gpt4o } /// /// Das ChatGPT Model, das zur Erzeugung der Idee und Bild-Promts verwendet wird. /// private GptModel _usedGptModel = GptModel.Gpt3_5_turbo; private int maxAddons = 2; private int amountOfAddons = 0; // wird später geändert private bool _progressVisible = false; private bool _buttonVisible = true; private bool _addonsVisible = false; private bool _bothVisible = false; private bool _imageSectionVisible = false; public string BusyMessage { get; set; } = "Initial Message"; private string?[] _imageUrls = new string?[4]; private string?[] _imagePromts = new string?[4]; private BildInfoModel?[] _bildInfos = new BildInfoModel?[4]; private ImageState[] _imageStates = new ImageState[4]; enum ImageState { FadeOut, FadeIn } async Task ShowImageDialog(string imageUrl) { var result = await DialogService.OpenAsync("", ds => @
, new DialogOptions() { CloseDialogOnOverlayClick = true }); } void ShowTooltip(ElementReference elementReference, string text, TooltipOptions? options = null) => TooltipService.Open(elementReference, text, options); void ShowTemperatureTooltip(ElementReference elementReference) => TooltipService.Open(elementReference, ds => @
Gibt an, wie kreativ ChatGPT sein soll.
, new() { Position = TooltipPosition.Bottom, Duration = null}); void ShowTooltip(string text, ElementReference elementReference) => TooltipService.Open(elementReference, ds => @
@text
, new() { Position = TooltipPosition.Bottom, Duration = null}); private string _imageIdea = ""; private float _temperature = 0.9f; private int? _imageWidth = null; private int? _imageHeight = null; private string _userIdea = ""; private string _updateRequest = ""; private OpenAIAPI _openAiApi; private Conversation? _conversation; private string _basePrompt; private string _ideaPrompt; private string _imageUrl; private WunschInfoModel? _wunschInfo; async Task UpdateBusyMessage(string newMessage) { BusyMessage = newMessage; await InvokeAsync(StateHasChanged); } private string _openAiApiKey = ""; class ModelInfo { public string Name { get; set; } public string StableDiffusionModel { get; set; } public string PromptFormat { get; set; } } private List _imageModels; private ModelInfo? _selectedImageModel = null; protected override async Task OnInitializedAsync() { _allBildInfos = (await BildInfoData.GetAllBildInfosAsync()).ToList().PickRandom(10); //await InvokeAsync(StateHasChanged); _openAiApiKey = Config.GetValue("API:OpenAI"); _openAiApi = new OpenAIAPI(_openAiApiKey); _imageModels = Config.GetSection("ImageModels").Get>(); //_selectedImageModel = _imageModels[0]; await base.OnInitializedAsync(); } /// /// Setzt alle Felder zurück, die zu einem bestimmten Wunsch gehören. /// private void ClearOldGeneration() { // Bilder verbergen for (int i = 0; i < 4; i++) { _imageStates[i] = ImageState.FadeOut; _imagePromts[i] = null; } _imageIdea = ""; } /// /// Gibt ChatGPT den Wunsch und erlangt die Bild Idee. /// /// private async Task RequestImageIdeaAsync() { string ideaBasePrompt = await File.ReadAllTextAsync($"{Directory.GetCurrentDirectory()}{@"/wwwroot/idea_prompt.txt"}"); ChatRequest chatRequest = new ChatRequest { Temperature = _temperature, Model = _usedGptModel switch { GptModel.Gpt3_5_turbo => Model.ChatGPTTurbo, GptModel.Gpt4_turbo => ChatGPT.GPT4Turbo, GptModel.Gpt4o => ChatGPT.GPT4o, _ => throw new ArgumentOutOfRangeException() } }; _conversation = _openAiApi.Chat.CreateConversation(chatRequest); // Wunsch an GPT senden und Bild Idee anfordern _conversation.AppendUserInput(ideaBasePrompt + " " + _userIdea); _imageIdea = await _conversation.GetResponseFromChatbotAsync(); } /// /// Fordert für mehrere Bilder Bild-Prompts an und generiert die dazugehörigen Bilder. /// private async Task RequestImagesAsync(WunschInfoModel wunschInfo, string requestImagePrompt) { // Nachricht mit Bildpromt anfrage senden _conversation!.AppendUserInput(requestImagePrompt); // Task-Liste, damit wir parallel Prompts anfordern und Bilder generieren können. Task[] imagePromts = new Task[4]; for (int i = 0; i < 4; i++) { imagePromts[i] = RequestImagePromptAndGenerateImageAsync(i, wunschInfo); } await Task.WhenAll(imagePromts); } /// /// Fordert einen Bild Prompt an und generiert ein Bild für diesen. /// /// Der Index des Bildes (für UI zeug) /// Der Wunsch für den ein Bild erzeugt wird. private async Task RequestImagePromptAndGenerateImageAsync(int index, WunschInfoModel wunschInfo) { ModelInfo imageModel = _selectedImageModel ?? _imageModels[Random.Shared.Next(_imageModels.Count)]; // Bild Prompt von ChatGPT anfordern string imagePrompt = await _conversation!.GetResponseFromChatbotAsync(); // Keywords anhängen um Kirstens Stil zu aktivieren. // TODO: Gucken, ob wir dem Watercolor bums brauchen imagePrompt = string.Format(imageModel.PromptFormat, imagePrompt);//"kkkk " + imagePrompt;// + " kkkk Watercolor + ink on paper, Pen drawing, wet-on-wet technique, dry-on-dry technique, dabbing technique. "; // Debug only: Promt anzeigen _imagePromts[index] = imagePrompt; await InvokeAsync(StateHasChanged); BildInfoModel? bildInfo = await GenerateImageAsync(imagePrompt, imageModel.StableDiffusionModel, wunschInfo); // TODO: Fehler im UI anzeigen (zur Zeit bleibt einfach Ladebalken) _imageUrls[index] = bildInfo?.Dateiname; _bildInfos[index] = bildInfo; _imageStates[index] = ImageState.FadeIn; await InvokeAsync(StateHasChanged); } /// /// Erzeugt ein Bild für den gegebenen Prompt und Wunsch. /// /// Der Bild Prompt /// Der Wunsch. /// Die URL, falls das Bild generiert wurde; oder null, wenn kein Bild generiert werden konnte. private async Task GenerateImageAsync(string imagePrompt, string modelName, WunschInfoModel wunschInfo) { try { BildInfoModel? bildInfo = await ImageGenerator.GenerateImageAsync(imagePrompt, modelName, wunschInfo, _imageWidth, _imageHeight); // Kein Bild -> Fehler if (bildInfo == 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) { bildInfo = await ImageGenerator.GenerateImageAsync(imagePrompt, modelName, wunschInfo, _imageWidth, _imageHeight); } } return bildInfo; } catch (Exception e) { NotificationService.Notify(new NotificationMessage() { Summary = "Es ist ein Fehler beim Erzeugen der Bilder aufgetreten, bitte versuche es erneut." }); } return null; } /// /// Generiert Bilder oder aktualisiert sie mit dem neuen Prompt. /// private async Task GenerateImagesAsync() { _progressVisible = true; _buttonVisible = false; ClearOldGeneration(); amountOfAddons = maxAddons; _addonsVisible = false; _bothVisible = _buttonVisible && _addonsVisible; await UpdateBusyMessage("Kirstens Assistent zerbricht sich über deine Idee den Kopf..."); await RequestImageIdeaAsync(); await UpdateBusyMessage("Kirstens Assistent hat eine Idee! Er wird sie nun malen..."); _wunschInfo = new() { BildBeschreibung = _imageIdea, BildPrompt = "Individuelle Bild Prompts", Datum = DateTime.Now, GPTModel = _conversation!.Model, Wunsch = _userIdea, VorherigerWunsch = null }; try { await WunschInfoData.AddWunschInfoAsync(_wunschInfo); } catch (Exception e) { NotificationService.Notify(new NotificationMessage() { Summary = "Es ist ein Fehler aufgetreten, bitte versuche es erneut." }); return; } string requestImagePrompt = await File.ReadAllTextAsync($"{Directory.GetCurrentDirectory()}{@"/wwwroot/image_prompt.txt"}"); await RequestImagesAsync(_wunschInfo, requestImagePrompt); _progressVisible = false; _buttonVisible = true; if (amountOfAddons > 0) { _addonsVisible = true; _bothVisible = _buttonVisible && _addonsVisible; await InvokeAsync(StateHasChanged); } else { _addonsVisible = false; _bothVisible = false; } } private async Task UpdateImagesAsync() { Debug.Assert(_conversation != null); string updatePrompt = $"Gebe nun einen neuen Prompt unter berücksichtigung vorheriger Anweisungen und passe ihn folgender Maßen an: {_updateRequest}"; _wunschInfo = new() { BildBeschreibung = _updateRequest, BildPrompt = "Individuelle Bild Prompts", Datum = DateTime.Now, GPTModel = _conversation.Model, Wunsch = _userIdea, VorherigerWunsch = _wunschInfo!.Id }; try { await WunschInfoData.AddWunschInfoAsync(_wunschInfo); } catch (Exception e) { NotificationService.Notify(new NotificationMessage() { Summary = "Es ist ein Fehler aufgetreten, bitte versuche es erneut." }); return; } await RequestImagesAsync(_wunschInfo, updatePrompt); } }