KI-Kunst-Kirsten-Kloeckner/KIKunstKirstenKlöckner/Pages/AiArt.razor

266 lines
11 KiB
Plaintext

@page "/aiart"
@using OpenAI_API
@using Microsoft.AspNetCore.Components.Web
@using OpenAI_API.Chat
@using OpenAI_API.Models
@using System.Diagnostics
@inject TooltipService TooltipService
@inject DialogService DialogService
@inject IJSRuntime JSRuntime;
<PageTitle>AiArt</PageTitle>
<h1>Wunschbilder von KI nur für dich</h1>
@*<EditForm Model="@exampleModel" OnSubmit="@DoStuff">
<InputText @bind-Value="exampleModel.Name" />
<button type="submit">Submit</button>
</EditForm>*@
<!-- Dies ist das Textfeld -->
@*<input type="text" @bind="request" placeholder="Text eingeben..." />
*@
<!-- Dies ist der Button -->
@*<button @onclick="DoStuff">Klick mich</button>*@
<RadzenStack Orientation="Orientation.Vertical" AlignItems="AlignItems.Center">
<RadzenText TextStyle="TextStyle.H2">Nenne uns deinen Wunsch:</RadzenText>
<RadzenTextBox @bind-Value=@request Placeholder="Dein Wunsch"/>
<RadzenPanel AllowCollapse="true" Style="width: 500px;" Text="Mehr Optionen">
<ChildContent>
<RadzenCard class="rz-mt-4">
<RadzenStack Orientation="Orientation.Horizontal"
MouseEnter="@(args => ShowTemperatureTooltip(args))"
MouseLeave="TooltipService.Close"
AlignItems="AlignItems.Center" Wrap="FlexWrap.Wrap">
<RadzenText>Temperature:</RadzenText>
<RadzenSlider @bind-Value=@temperature TValue="float"
Step="0.0001" Min="0.0m" Max="2.0m">
</RadzenSlider>
<RadzenText>@temperature</RadzenText>
</RadzenStack>
</RadzenCard>
</ChildContent>
</RadzenPanel>
<RadzenButton Visible=@_buttonVisible Click=@(async ()=> await DoStuff(true))>Generate</RadzenButton>
<RadzenPanel AllowCollapse="true" Style="width: 500px;" Text="Zeige Prompt">
<ChildContent>
<RadzenCard class="rz-mt-4">
<RadzenStack Orientation="Orientation.Horizontal"
MouseEnter="@(args => ShowTemperatureTooltip(args))"
MouseLeave="TooltipService.Close"
AlignItems="AlignItems.Center" Wrap="FlexWrap.Wrap">
<RadzenText>@_imagePrompt</RadzenText>
</RadzenStack>
</RadzenCard>
</ChildContent>
</RadzenPanel>
<RadzenText TextStyle="TextStyle.H4">Die Idee, die gemalt wird:</RadzenText>
<RadzenText>@_imageDescription</RadzenText>
<RadzenProgressBarCircular Visible=@_progressVisible ProgressBarStyle="ProgressBarStyle.Secondary" Value="100" ShowValue="false" Mode="ProgressBarMode.Indeterminate" />
<RadzenText Visible=@_progressVisible TextStyle="TextStyle.H6" Text=@BusyMessage></RadzenText>
<RadzenImage Path=@_imageUrl></RadzenImage>
<RadzenText Visible=@_addonsVisible TextStyle="TextStyle.H4">Verändere hier dein Bild durch Worte:</RadzenText>
<RadzenTextBox Visible=@_addonsVisible @bind-Value=@addons Placeholder="Mehr Farben" />
<RadzenButton Visible=@_bothVisible Click=@(async ()=> await DoStuff(false))>Generate</RadzenButton>
</RadzenStack>
@code {
private int maxAddons = 2;
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 _buttonVisible = true;
private bool _addonsVisible = false;
private bool _bothVisible = false;
public string BusyMessage { get; set; } = "Initial Message";
// 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 });
}
// 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 ShowTemperatureTooltip(ElementReference elementReference) => TooltipService.Open(elementReference, ds =>
@<div>
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>
,
new() { Position = TooltipPosition.Bottom, Duration = null});
private string _imagePrompt = "\"Painting of a soccer match with the Hamburger SV team scoring multiple goals, vibrant colors and dynamic brushstrokes.\" Watercolor + ink on paper, Pen drawing, wet-on-wet technique, dry-on-dry technique, dabbing technique.";
private string _imageDescription = "Ich habe mich für diese Interpretation des Titels entschieden, um die Dynamik und den Erfolg des Hamburger SV Fußballvereins darzustellen. Durch die Darstellung eines Spiels, in dem der HSV viele Tore schießt, wird die Leidenschaft und das Streben nach Erfolg hervorgehoben. Die lebendigen Farben und die dynamischen Pinselstriche sollen die Energie und Aufregung des Spiels wiedergeben.";
private float temperature = 0.9f;
private string request = "";
private string addons = "";
private OpenAIAPI api = new OpenAIAPI("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");
private Conversation converse;
private string _basePrompt;
private string _imageUrl;
//protected override async Task OnInitializedAsync()
//{
// _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)
{
BusyMessage = newMessage;
await InvokeAsync(StateHasChanged);
}
public async Task GenerateImage()
{
//await JSRuntime.InvokeVoidAsync("DoSexyStuffBridge", _imagePrompt);
_imageUrl = await JSRuntime.InvokeAsync<string>("DoSexyStuffBridge", _imagePrompt);
}
private async Task DoStuff(bool newPic)
{
// 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();
_progressVisible = true;
_buttonVisible = false;
if (converse == null || newPic)
{
amountOfAddons = maxAddons;
_addonsVisible = false;
_bothVisible = _buttonVisible && _addonsVisible;
await UpdateBusyMessage("Kirstens Assistent zerbricht sich über deine Idee den Kopf...");
_basePrompt = await File.ReadAllTextAsync($"{Directory.GetCurrentDirectory()}{@"/wwwroot/test_prompt.txt"}");
ChatRequest chatRequest = new ChatRequest
{
Temperature = temperature,
Model = Model.ChatGPTTurbo,
};
converse = api.Chat.CreateConversation(chatRequest);
converse.AppendUserInput(_basePrompt + " " + request);
}
else
{
if (amountOfAddons > 0)
{
amountOfAddons--;
_bothVisible = _buttonVisible && _addonsVisible;
await UpdateBusyMessage("Kirstens Assistent passt das Bild an deine Wünsche an...");
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);
}
}
_imagePrompt = await converse.GetResponseFromChatbotAsync();
_imagePrompt += " 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...");
Task makeImagesTask = GenerateImage();
//CancellationTokenSource cancelFunnyMessages = new CancellationTokenSource();
//Task funnyMessagesTask = FunnyMessageSwitcher_ImageGen(cancelFunnyMessages.Token);
// Wichtig, erst Bilder awaiten, dann die lustingen Sprüche, sonst warten wir ewig...
await makeImagesTask;
//cancelFunnyMessages.Cancel();
//await funnyMessagesTask;
_progressVisible = false;
_buttonVisible = true;
if (amountOfAddons > 0)
{
_addonsVisible = true;
_bothVisible = _buttonVisible && _addonsVisible;
await InvokeAsync(StateHasChanged);
}
else
{
_addonsVisible = false;
_bothVisible = false;
}
}
}