2023-08-02 21:33:09 +02:00
|
|
|
@page "/aiart"
|
2023-08-04 15:45:38 +02:00
|
|
|
|
2023-08-02 18:33:28 +02:00
|
|
|
@using OpenAI_API
|
|
|
|
@using OpenAI_API.Chat
|
|
|
|
@using OpenAI_API.Models
|
2023-10-10 16:21:00 +02:00
|
|
|
@using DataAccess.Data
|
|
|
|
@using DataAccess.Models
|
2023-10-11 14:41:43 +02:00
|
|
|
@using KIKunstKirstenKlöckner.Data
|
2023-11-17 13:33:05 +01:00
|
|
|
@using KIKunstKirstenKlöckner.Extensions
|
2023-10-22 12:39:11 +02:00
|
|
|
@using System.Diagnostics
|
2023-08-02 21:33:09 +02:00
|
|
|
|
2023-11-16 22:47:03 +01:00
|
|
|
@inject IJSRuntime JSRuntime
|
2023-08-05 01:40:55 +02:00
|
|
|
@inject IConfiguration Config
|
2023-08-02 21:33:09 +02:00
|
|
|
@inject TooltipService TooltipService
|
2023-10-11 14:41:43 +02:00
|
|
|
@inject NotificationService NotificationService
|
2023-08-02 21:33:09 +02:00
|
|
|
@inject DialogService DialogService
|
2023-08-02 18:33:28 +02:00
|
|
|
|
2023-10-11 14:41:43 +02:00
|
|
|
@inject ImageGenerator ImageGenerator;
|
2023-11-17 01:35:14 +01:00
|
|
|
@inject BildInfoData BildInfoData;
|
|
|
|
@inject WunschInfoData WunschInfoData;
|
2023-10-10 16:21:00 +02:00
|
|
|
|
2023-11-17 01:35:14 +01:00
|
|
|
@implements IAsyncDisposable
|
2023-08-02 18:33:28 +02:00
|
|
|
|
2023-11-17 01:35:14 +01:00
|
|
|
<style>
|
|
|
|
.invisible-rectangle {
|
|
|
|
width: 100%;
|
|
|
|
height: 600px;
|
|
|
|
opacity: 0;
|
|
|
|
background-color: transparent;
|
|
|
|
pointer-events: none;
|
|
|
|
}
|
2023-09-20 12:20:26 +02:00
|
|
|
|
2023-11-17 01:35:14 +01:00
|
|
|
.invisible-rectangle-small {
|
|
|
|
width: 100%;
|
|
|
|
height: 100px;
|
|
|
|
opacity: 0;
|
|
|
|
background-color: transparent;
|
|
|
|
pointer-events: none;
|
|
|
|
}
|
|
|
|
</style>
|
|
|
|
|
2024-06-30 13:38:37 +02:00
|
|
|
<PageTitle>Wunschbild Generator</PageTitle>
|
2023-11-17 01:35:14 +01:00
|
|
|
|
|
|
|
<section class="about_section" style="background-image: url('images/5KeineAngstvorFehlern2014.jpeg'); background-size: cover; background-repeat: no-repeat; background-blend-mode:lighten">
|
|
|
|
|
|
|
|
<div class="hero_area hero-area-visible">
|
|
|
|
|
|
|
|
<!-- slider section -->
|
|
|
|
<section class="slider_section" style="background-image: url('images/3730Kilo2015.jpeg'); background-size: cover; background-repeat: no-repeat; background-blend-mode:lighten">
|
|
|
|
<div class="container">
|
|
|
|
<div class="row">
|
|
|
|
<div class="col-md-6 ">
|
|
|
|
<div class="detail_box">
|
|
|
|
<h1>
|
|
|
|
Hier werden <br>
|
|
|
|
deine Wünsche <br>
|
|
|
|
Wirklichkeit
|
|
|
|
</h1>
|
|
|
|
<p>
|
|
|
|
Weiter unten findest du meinen Assistenten. Gebe ihm deinen Wunsch und er wird sich etwas tolles dazu überlegen. Es lohnt sich geduldig zu sein. <br>
|
|
|
|
Scrolle einfach nach unten!
|
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div class="col-lg-5 col-md-6 offset-lg-1">
|
|
|
|
<div class="img_content">
|
|
|
|
<div class="img_container">
|
|
|
|
<div id="carouselExampleControls" class="carousel slide" data-ride="carousel">
|
|
|
|
<div class="carousel-inner">
|
|
|
|
@if (_allBildInfos != null)
|
|
|
|
{
|
|
|
|
@foreach (var bildInfo in _allBildInfos)
|
|
|
|
{
|
|
|
|
if (_indexForCarusell == 0)
|
|
|
|
{
|
|
|
|
<div class="carousel-item active">
|
|
|
|
<div class="img-box">
|
2023-11-17 13:33:05 +01:00
|
|
|
<img src="@bildInfo.Dateiname"/>
|
2023-11-17 01:35:14 +01:00
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
}
|
2023-11-17 13:33:05 +01:00
|
|
|
else
|
|
|
|
{
|
|
|
|
<div class="carousel-item">
|
|
|
|
<div class="img-box">
|
|
|
|
<img src="@bildInfo.Dateiname"/>
|
|
|
|
</div>
|
2023-11-17 01:35:14 +01:00
|
|
|
</div>
|
2023-11-17 13:33:05 +01:00
|
|
|
}
|
2023-11-17 01:35:14 +01:00
|
|
|
_indexForCarusell++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<a class="carousel-control-prev" href="#carouselExampleControls" role="button" data-slide="prev">
|
|
|
|
<span class="sr-only">Previous</span>
|
|
|
|
</a>
|
|
|
|
<a class="carousel-control-next" href="#carouselExampleControls" role="button" data-slide="next">
|
|
|
|
<span class="sr-only">Next</span>
|
|
|
|
</a>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</section>
|
|
|
|
<!-- end slider section -->
|
|
|
|
</div>
|
|
|
|
<div class="invisible-rectangle-small"></div>
|
|
|
|
|
|
|
|
<!-- start entry section -->
|
|
|
|
<section id="entrySection" class="section-animate-left" @ref="animatedEntrySection">
|
|
|
|
<div class="container">
|
|
|
|
|
|
|
|
<RadzenStack Orientation="Orientation.Vertical" AlignItems="AlignItems.Center">
|
2023-08-18 14:57:12 +02:00
|
|
|
<h1>Wunschbilder von KI nur für dich</h1>
|
2023-09-20 12:20:26 +02:00
|
|
|
<RadzenText TextStyle="TextStyle.H2">Nenne uns deinen Wunsch:</RadzenText>
|
2023-10-22 12:39:11 +02:00
|
|
|
<RadzenTextBox @bind-Value=@_userIdea Placeholder="Dein Wunsch"/>
|
|
|
|
|
|
|
|
@* Zusätzliche Optionen *@
|
2023-09-20 12:20:26 +02:00
|
|
|
<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>
|
2023-10-11 14:41:43 +02:00
|
|
|
<RadzenSlider @bind-Value=@_temperature TValue="float"
|
2023-09-20 12:20:26 +02:00
|
|
|
Step="0.1" Min="0.0m" Max="2.0m">
|
|
|
|
</RadzenSlider>
|
2023-10-11 14:41:43 +02:00
|
|
|
<RadzenText>@_temperature</RadzenText>
|
2023-09-20 12:20:26 +02:00
|
|
|
</RadzenStack>
|
2023-09-21 12:25:11 +02:00
|
|
|
<RadzenStack Orientation="Orientation.Horizontal"
|
|
|
|
AlignItems="AlignItems.Center" Wrap="FlexWrap.Wrap">
|
|
|
|
<RadzenText>Resolution:</RadzenText>
|
|
|
|
<RadzenStack Orientation="Orientation.Horizontal">
|
2023-10-22 15:16:05 +02:00
|
|
|
<RadzenNumeric ShowUpDown = "false" TValue = "int?" @bind-Value=@_imageWidth />
|
2023-09-21 12:25:11 +02:00
|
|
|
x
|
2023-10-22 15:16:05 +02:00
|
|
|
<RadzenNumeric ShowUpDown = "false" TValue = "int?" @bind-Value=@_imageHeight />
|
2023-09-21 12:25:11 +02:00
|
|
|
</RadzenStack>
|
|
|
|
</RadzenStack>
|
2024-06-30 14:16:16 +02:00
|
|
|
<RadzenRadioButtonList @bind-Value=@_usedGptModel TValue="GptModel" class="mb-5">
|
|
|
|
<Items>
|
|
|
|
<RadzenRadioButtonListItem Text="GPT-3.5 Turbo" Value="GptModel.Gpt3_5_turbo"
|
|
|
|
MouseEnter="@(args => ShowTooltip("Schnell aber nicht sonderlich clever.", args))"
|
|
|
|
MouseLeave="TooltipService.Close">
|
|
|
|
</RadzenRadioButtonListItem>
|
|
|
|
<RadzenRadioButtonListItem Text="GPT-4 Turbo" Value="GptModel.Gpt4_turbo"
|
|
|
|
MouseEnter="@(args => ShowTooltip("Etwas langsamer, aber recht klug.", args))"
|
|
|
|
MouseLeave="TooltipService.Close">
|
|
|
|
</RadzenRadioButtonListItem>
|
|
|
|
<RadzenRadioButtonListItem Text="GPT-4o" Value="GptModel.Gpt4o"
|
|
|
|
MouseEnter="@(args => ShowTooltip("Schnell, gut und günstig. Warum gibt es überhaupt eine Auswahlmöglichkeit?", args))"
|
|
|
|
MouseLeave="TooltipService.Close">
|
|
|
|
</RadzenRadioButtonListItem>
|
|
|
|
</Items>
|
|
|
|
</RadzenRadioButtonList>
|
2023-10-22 15:16:05 +02:00
|
|
|
@* <RadzenRadioButtonList Data="@_imageModels" @bind-Value=@_selectedImageModel TValue="ModelInfo" TextProperty="Name" class="mb-5"> *@
|
|
|
|
<RadzenRadioButtonList Data="@_imageModels" @bind-Value=@_selectedImageModel TValue="ModelInfo" TextProperty="Name" ValueProperty="" class="mb-5">
|
|
|
|
<Items>
|
2024-06-30 14:16:16 +02:00
|
|
|
<RadzenRadioButtonListItem Text="Zufällig" Value="@null" TValue="ModelInfo"
|
|
|
|
MouseEnter="@(args => ShowTooltip("Für jedes Bild wird zufällig ein Generator ausgewählt.", args))"
|
|
|
|
MouseLeave="TooltipService.Close"/>
|
2023-10-22 15:16:05 +02:00
|
|
|
</Items>
|
|
|
|
</RadzenRadioButtonList>
|
2023-09-20 12:20:26 +02:00
|
|
|
</RadzenCard>
|
|
|
|
</ChildContent>
|
2023-11-17 01:35:14 +01:00
|
|
|
</RadzenPanel>
|
2023-08-02 21:33:09 +02:00
|
|
|
|
2023-11-16 22:47:03 +01:00
|
|
|
<RadzenButton Visible=@_buttonVisible Click="@OnGenerateButtonClickAsync">Generate</RadzenButton>
|
2023-11-17 01:35:14 +01:00
|
|
|
</RadzenStack>
|
|
|
|
</div>
|
|
|
|
</section>
|
|
|
|
<!-- end entry section -->
|
2023-11-16 22:47:03 +01:00
|
|
|
|
2023-11-17 01:35:14 +01:00
|
|
|
<!-- start image section -->
|
|
|
|
<section id="imageSection">
|
|
|
|
<div class="container">
|
2023-11-16 22:47:03 +01:00
|
|
|
@if (_imageSectionVisible)
|
|
|
|
{
|
|
|
|
<section id="imageSection">
|
|
|
|
<RadzenStack Orientation="Orientation.Vertical" AlignItems="AlignItems.Center">
|
|
|
|
<RadzenText TextStyle="TextStyle.H4">Die Idee, die gemalt wird:</RadzenText>
|
|
|
|
|
|
|
|
<RadzenCard class="rz-mt-4" Style="width: 800px;">
|
|
|
|
<RadzenText>@_imageIdea</RadzenText>
|
|
|
|
</RadzenCard>
|
|
|
|
|
|
|
|
<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.H2">Verändere hier dein Bild durch Worte:</RadzenText>
|
|
|
|
<RadzenTextBox Visible=@_addonsVisible @bind-Value=@_updateRequest Placeholder="z.B. Mehr Farben" />
|
|
|
|
<RadzenButton Visible=@_bothVisible Click=@(async ()=> await UpdateImagesAsync())>Generate</RadzenButton>
|
|
|
|
|
|
|
|
<RadzenCard>
|
|
|
|
<RadzenRow Style="width:24.5em" Gap="0.5rem" RowGap="0.5rem">
|
|
|
|
<RadzenColumn Size="6">
|
|
|
|
<FlippingImage ImageUrl="@_imageUrls[0]" HideImage="false"
|
|
|
|
Show="@(_imageStates[0] == ImageState.FadeIn)" FlipTo="FlippingImage.FlipDirection.Up"
|
|
|
|
Click="() => ShowImageDialog(_imageUrls[0])" />
|
|
|
|
<RadzenPanel AllowCollapse="true" Collapsed="true" Text="Info">
|
|
|
|
@_imagePromts[0]
|
|
|
|
<br />
|
|
|
|
Model: @_bildInfos[0]?.ImageModel
|
|
|
|
</RadzenPanel>
|
|
|
|
</RadzenColumn>
|
|
|
|
<RadzenColumn Size="6">
|
|
|
|
<FlippingImage ImageUrl="@_imageUrls[1]" HideImage="false"
|
|
|
|
Show="@(_imageStates[1] == ImageState.FadeIn)" FlipTo="FlippingImage.FlipDirection.Right" FlipDelay="200"
|
|
|
|
Click="() => ShowImageDialog(_imageUrls[1])" />
|
|
|
|
<RadzenPanel AllowCollapse="true" Collapsed="true" Text="Info">
|
|
|
|
@_imagePromts[1]
|
|
|
|
<br />
|
|
|
|
Model: @_bildInfos[1]?.ImageModel
|
|
|
|
</RadzenPanel>
|
|
|
|
</RadzenColumn>
|
|
|
|
<RadzenColumn Size="6">
|
|
|
|
<FlippingImage ImageUrl="@_imageUrls[2]" HideImage="false"
|
|
|
|
Show="@(_imageStates[2] == ImageState.FadeIn)" FlipTo="FlippingImage.FlipDirection.Left" FlipDelay="600"
|
|
|
|
Click="() => ShowImageDialog(_imageUrls[2])" />
|
|
|
|
<RadzenPanel AllowCollapse="true" Collapsed="true" Text="Info">
|
|
|
|
@_imagePromts[2]
|
|
|
|
<br />
|
|
|
|
Model: @_bildInfos[2]?.ImageModel
|
|
|
|
</RadzenPanel>
|
|
|
|
</RadzenColumn>
|
|
|
|
<RadzenColumn Size="6">
|
|
|
|
<FlippingImage ImageUrl="@_imageUrls[3]" HideImage="false"
|
|
|
|
Show="@(_imageStates[3] == ImageState.FadeIn)" FlipTo="FlippingImage.FlipDirection.Down" FlipDelay="400"
|
|
|
|
Click="() => ShowImageDialog(_imageUrls[3])" />
|
|
|
|
<RadzenPanel AllowCollapse="true" Collapsed="true" Text="Info">
|
|
|
|
@_imagePromts[3]
|
|
|
|
<br />
|
|
|
|
Model: @_bildInfos[3]?.ImageModel
|
|
|
|
</RadzenPanel>
|
|
|
|
</RadzenColumn>
|
|
|
|
</RadzenRow>
|
|
|
|
</RadzenCard>
|
|
|
|
</RadzenStack>
|
|
|
|
</section>
|
|
|
|
}
|
2023-11-17 01:35:14 +01:00
|
|
|
@if (!_imageSectionVisible)
|
|
|
|
{
|
|
|
|
<div class="invisible-rectangle"></div>
|
|
|
|
}
|
|
|
|
</div>
|
|
|
|
</section>
|
|
|
|
<!-- end image section -->
|
2023-08-05 00:43:11 +02:00
|
|
|
|
2023-09-20 12:20:26 +02:00
|
|
|
</section>
|
2023-08-02 18:33:28 +02:00
|
|
|
|
|
|
|
@code {
|
2023-11-17 01:35:14 +01:00
|
|
|
// Animation stuff
|
|
|
|
private int _indexForCarusell = 0;
|
|
|
|
private ElementReference animatedEntrySection;
|
|
|
|
private List<ElementReference> animatedElements = new List<ElementReference>();
|
|
|
|
|
|
|
|
private Func<Task> removeScrollListener;
|
|
|
|
|
|
|
|
protected override async Task OnAfterRenderAsync(bool firstRender)
|
|
|
|
{
|
|
|
|
if (firstRender)
|
|
|
|
{
|
|
|
|
animatedElements.Add(animatedEntrySection);
|
|
|
|
|
|
|
|
removeScrollListener = await JSRuntime.InvokeAsync<Func<Task>>(
|
|
|
|
"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();
|
|
|
|
}
|
|
|
|
|
2023-11-17 13:33:05 +01:00
|
|
|
IEnumerable<BildInfoModel>? _allBildInfos;
|
2023-11-17 01:35:14 +01:00
|
|
|
|
2024-06-30 14:16:16 +02:00
|
|
|
enum GptModel
|
|
|
|
{
|
|
|
|
Gpt3_5_turbo,
|
|
|
|
Gpt4_turbo,
|
|
|
|
Gpt4o
|
|
|
|
}
|
|
|
|
|
2023-10-11 14:41:43 +02:00
|
|
|
/// <summary>
|
2024-06-30 14:16:16 +02:00
|
|
|
/// Das ChatGPT Model, das zur Erzeugung der Idee und Bild-Promts verwendet wird.
|
2023-10-11 14:41:43 +02:00
|
|
|
/// </summary>
|
2024-06-30 14:16:16 +02:00
|
|
|
private GptModel _usedGptModel = GptModel.Gpt3_5_turbo;
|
2023-10-11 14:41:43 +02:00
|
|
|
|
2023-08-04 14:42:03 +02:00
|
|
|
private int maxAddons = 2;
|
|
|
|
private int amountOfAddons = 0; // wird später geändert
|
2023-08-02 21:33:09 +02:00
|
|
|
private bool _progressVisible = false;
|
2023-08-03 23:24:10 +02:00
|
|
|
private bool _buttonVisible = true;
|
2023-08-04 14:42:03 +02:00
|
|
|
private bool _addonsVisible = false;
|
|
|
|
private bool _bothVisible = false;
|
2023-11-16 22:47:03 +01:00
|
|
|
private bool _imageSectionVisible = false;
|
2023-08-02 21:33:09 +02:00
|
|
|
|
|
|
|
public string BusyMessage { get; set; } = "Initial Message";
|
|
|
|
|
2023-08-05 00:43:11 +02:00
|
|
|
private string?[] _imageUrls = new string?[4];
|
2023-10-14 14:33:35 +02:00
|
|
|
private string?[] _imagePromts = new string?[4];
|
2023-10-22 15:16:05 +02:00
|
|
|
private BildInfoModel?[] _bildInfos = new BildInfoModel?[4];
|
2023-08-05 00:43:11 +02:00
|
|
|
private ImageState[] _imageStates = new ImageState[4];
|
|
|
|
|
|
|
|
enum ImageState
|
|
|
|
{
|
|
|
|
FadeOut,
|
2023-10-11 14:41:43 +02:00
|
|
|
FadeIn
|
2023-08-02 21:33:09 +02:00
|
|
|
}
|
|
|
|
|
2023-08-05 00:43:11 +02:00
|
|
|
async Task ShowImageDialog(string imageUrl)
|
|
|
|
{
|
|
|
|
var result = await DialogService.OpenAsync("", ds =>
|
2023-09-20 15:43:10 +02:00
|
|
|
@<div>
|
|
|
|
<RadzenImage Style="object-fit: contain; width: 100%; height:100%;" Path="@imageUrl"/>
|
2023-08-05 00:43:11 +02:00
|
|
|
</div>, new DialogOptions() { CloseDialogOnOverlayClick = true });
|
|
|
|
}
|
|
|
|
|
2023-08-02 21:33:09 +02:00
|
|
|
void ShowTooltip(ElementReference elementReference, string text, TooltipOptions? options = null) => TooltipService.Open(elementReference, text, options);
|
|
|
|
|
|
|
|
void ShowTemperatureTooltip(ElementReference elementReference) => TooltipService.Open(elementReference, ds =>
|
|
|
|
@<div>
|
2023-10-11 14:41:43 +02:00
|
|
|
Gibt an, wie <em>kreativ</em> ChatGPT sein soll.<br/>
|
2023-08-04 14:42:03 +02:00
|
|
|
</div>
|
|
|
|
,
|
2023-08-02 21:33:09 +02:00
|
|
|
new() { Position = TooltipPosition.Bottom, Duration = null});
|
|
|
|
|
2024-06-30 14:16:16 +02:00
|
|
|
void ShowTooltip(string text, ElementReference elementReference) => TooltipService.Open(elementReference, ds =>
|
|
|
|
@<div>@text</div>
|
|
|
|
,
|
|
|
|
new() { Position = TooltipPosition.Bottom, Duration = null});
|
|
|
|
|
2023-09-20 12:22:52 +02:00
|
|
|
private string _imageIdea = "";
|
2023-08-02 21:33:09 +02:00
|
|
|
|
2023-10-11 14:41:43 +02:00
|
|
|
private float _temperature = 0.9f;
|
2023-10-22 15:16:05 +02:00
|
|
|
private int? _imageWidth = null;
|
|
|
|
private int? _imageHeight = null;
|
2023-10-22 12:39:11 +02:00
|
|
|
private string _userIdea = "";
|
|
|
|
private string _updateRequest = "";
|
2023-08-05 01:40:55 +02:00
|
|
|
private OpenAIAPI _openAiApi;
|
2023-10-11 14:41:43 +02:00
|
|
|
private Conversation? _conversation;
|
2023-08-02 18:33:28 +02:00
|
|
|
|
2023-08-02 21:33:09 +02:00
|
|
|
private string _basePrompt;
|
2023-09-20 12:22:52 +02:00
|
|
|
private string _ideaPrompt;
|
2023-08-02 21:33:09 +02:00
|
|
|
|
2023-08-03 23:24:10 +02:00
|
|
|
private string _imageUrl;
|
|
|
|
|
2023-10-22 12:39:11 +02:00
|
|
|
private WunschInfoModel? _wunschInfo;
|
|
|
|
|
2023-08-02 21:33:09 +02:00
|
|
|
async Task UpdateBusyMessage(string newMessage)
|
|
|
|
{
|
|
|
|
BusyMessage = newMessage;
|
|
|
|
await InvokeAsync(StateHasChanged);
|
|
|
|
}
|
2023-08-04 15:37:07 +02:00
|
|
|
|
2023-08-05 01:40:55 +02:00
|
|
|
private string _openAiApiKey = "";
|
|
|
|
|
2023-10-22 15:16:05 +02:00
|
|
|
class ModelInfo
|
|
|
|
{
|
|
|
|
public string Name { get; set; }
|
|
|
|
public string StableDiffusionModel { get; set; }
|
|
|
|
public string PromptFormat { get; set; }
|
|
|
|
}
|
|
|
|
|
|
|
|
private List<ModelInfo> _imageModels;
|
|
|
|
|
|
|
|
private ModelInfo? _selectedImageModel = null;
|
|
|
|
|
2023-10-10 16:21:00 +02:00
|
|
|
protected override async Task OnInitializedAsync()
|
2023-08-03 23:24:10 +02:00
|
|
|
{
|
2023-11-17 13:33:05 +01:00
|
|
|
_allBildInfos = (await BildInfoData.GetAllBildInfosAsync()).ToList().PickRandom(10);
|
|
|
|
//await InvokeAsync(StateHasChanged);
|
2023-11-17 01:35:14 +01:00
|
|
|
|
2023-08-05 01:40:55 +02:00
|
|
|
_openAiApiKey = Config.GetValue<string>("API:OpenAI");
|
2023-08-04 15:37:07 +02:00
|
|
|
|
2023-08-05 01:40:55 +02:00
|
|
|
_openAiApi = new OpenAIAPI(_openAiApiKey);
|
2023-08-04 15:37:07 +02:00
|
|
|
|
2023-10-22 15:16:05 +02:00
|
|
|
_imageModels = Config.GetSection("ImageModels").Get<List<ModelInfo>>();
|
|
|
|
//_selectedImageModel = _imageModels[0];
|
|
|
|
|
2023-10-10 16:21:00 +02:00
|
|
|
await base.OnInitializedAsync();
|
2023-08-03 23:24:10 +02:00
|
|
|
}
|
2023-08-02 21:33:09 +02:00
|
|
|
|
2023-10-14 14:33:35 +02:00
|
|
|
/// <summary>
|
|
|
|
/// Setzt alle Felder zurück, die zu einem bestimmten Wunsch gehören.
|
|
|
|
/// </summary>
|
2023-10-11 14:41:43 +02:00
|
|
|
private void ClearOldGeneration()
|
2023-08-05 00:43:11 +02:00
|
|
|
{
|
2023-10-11 14:41:43 +02:00
|
|
|
// Bilder verbergen
|
|
|
|
for (int i = 0; i < 4; i++)
|
2023-10-14 14:33:35 +02:00
|
|
|
{
|
2023-10-11 14:41:43 +02:00
|
|
|
_imageStates[i] = ImageState.FadeOut;
|
2023-10-14 14:33:35 +02:00
|
|
|
_imagePromts[i] = null;
|
|
|
|
}
|
2023-08-05 00:43:11 +02:00
|
|
|
|
2023-10-11 14:41:43 +02:00
|
|
|
_imageIdea = "";
|
|
|
|
}
|
2023-08-18 11:52:58 +02:00
|
|
|
|
2023-10-14 14:33:35 +02:00
|
|
|
/// <summary>
|
|
|
|
/// Gibt ChatGPT den Wunsch und erlangt die Bild Idee.
|
|
|
|
/// </summary>
|
|
|
|
/// <returns></returns>
|
2023-10-11 14:41:43 +02:00
|
|
|
private async Task RequestImageIdeaAsync()
|
|
|
|
{
|
|
|
|
string ideaBasePrompt = await File.ReadAllTextAsync($"{Directory.GetCurrentDirectory()}{@"/wwwroot/idea_prompt.txt"}");
|
2023-08-05 00:43:11 +02:00
|
|
|
|
2023-10-11 14:41:43 +02:00
|
|
|
ChatRequest chatRequest = new ChatRequest
|
2023-08-05 00:43:11 +02:00
|
|
|
{
|
2023-10-11 14:41:43 +02:00
|
|
|
Temperature = _temperature,
|
2024-06-30 14:16:16 +02:00
|
|
|
Model = _usedGptModel switch
|
|
|
|
{
|
|
|
|
GptModel.Gpt3_5_turbo => Model.ChatGPTTurbo,
|
|
|
|
GptModel.Gpt4_turbo => ChatGPT.GPT4Turbo,
|
|
|
|
GptModel.Gpt4o => ChatGPT.GPT4o,
|
|
|
|
_ => throw new ArgumentOutOfRangeException()
|
|
|
|
}
|
2023-10-11 14:41:43 +02:00
|
|
|
};
|
2023-08-05 00:43:11 +02:00
|
|
|
|
2023-10-11 14:41:43 +02:00
|
|
|
_conversation = _openAiApi.Chat.CreateConversation(chatRequest);
|
2023-08-05 00:43:11 +02:00
|
|
|
|
2023-10-11 14:41:43 +02:00
|
|
|
// Wunsch an GPT senden und Bild Idee anfordern
|
2023-10-22 12:39:11 +02:00
|
|
|
_conversation.AppendUserInput(ideaBasePrompt + " " + _userIdea);
|
2023-10-11 14:41:43 +02:00
|
|
|
_imageIdea = await _conversation.GetResponseFromChatbotAsync();
|
2023-10-14 14:33:35 +02:00
|
|
|
}
|
|
|
|
/// <summary>
|
|
|
|
/// Fordert für mehrere Bilder Bild-Prompts an und generiert die dazugehörigen Bilder.
|
|
|
|
/// </summary>
|
2023-10-22 12:39:11 +02:00
|
|
|
private async Task RequestImagesAsync(WunschInfoModel wunschInfo, string requestImagePrompt)
|
2023-10-14 14:33:35 +02:00
|
|
|
{
|
|
|
|
// 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++)
|
|
|
|
{
|
2023-10-22 12:39:11 +02:00
|
|
|
imagePromts[i] = RequestImagePromptAndGenerateImageAsync(i, wunschInfo);
|
2023-10-14 14:33:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
await Task.WhenAll(imagePromts);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Fordert einen Bild Prompt an und generiert ein Bild für diesen.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="index">Der Index des Bildes (für UI zeug)</param>
|
|
|
|
/// <param name="wunschInfo">Der Wunsch für den ein Bild erzeugt wird.</param>
|
2023-10-22 12:39:11 +02:00
|
|
|
private async Task RequestImagePromptAndGenerateImageAsync(int index, WunschInfoModel wunschInfo)
|
2023-10-14 14:33:35 +02:00
|
|
|
{
|
2023-10-22 15:16:05 +02:00
|
|
|
ModelInfo imageModel = _selectedImageModel ?? _imageModels[Random.Shared.Next(_imageModels.Count)];
|
|
|
|
|
2023-10-14 14:33:35 +02:00
|
|
|
// 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
|
2023-10-22 15:16:05 +02:00
|
|
|
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. ";
|
2023-10-14 14:33:35 +02:00
|
|
|
|
|
|
|
// Debug only: Promt anzeigen
|
|
|
|
_imagePromts[index] = imagePrompt;
|
|
|
|
await InvokeAsync(StateHasChanged);
|
|
|
|
|
2023-10-22 15:16:05 +02:00
|
|
|
BildInfoModel? bildInfo = await GenerateImageAsync(imagePrompt, imageModel.StableDiffusionModel, wunschInfo);
|
2023-10-14 14:33:35 +02:00
|
|
|
|
|
|
|
// TODO: Fehler im UI anzeigen (zur Zeit bleibt einfach Ladebalken)
|
2023-10-22 15:16:05 +02:00
|
|
|
_imageUrls[index] = bildInfo?.Dateiname;
|
|
|
|
_bildInfos[index] = bildInfo;
|
2023-10-14 14:33:35 +02:00
|
|
|
_imageStates[index] = ImageState.FadeIn;
|
|
|
|
await InvokeAsync(StateHasChanged);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Erzeugt ein Bild für den gegebenen Prompt und Wunsch.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="imagePrompt">Der Bild Prompt</param>
|
|
|
|
/// <param name="wunschInfo">Der Wunsch.</param>
|
|
|
|
/// <returns>Die URL, falls das Bild generiert wurde; oder null, wenn kein Bild generiert werden konnte.</returns>
|
2023-10-22 15:16:05 +02:00
|
|
|
private async Task<BildInfoModel?> GenerateImageAsync(string imagePrompt, string modelName, WunschInfoModel wunschInfo)
|
2023-10-14 14:33:35 +02:00
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
2023-10-22 15:16:05 +02:00
|
|
|
BildInfoModel? bildInfo = await ImageGenerator.GenerateImageAsync(imagePrompt, modelName, wunschInfo, _imageWidth, _imageHeight);
|
2023-10-14 14:33:35 +02:00
|
|
|
|
|
|
|
// Kein Bild -> Fehler
|
2023-10-22 15:16:05 +02:00
|
|
|
if (bildInfo == null)
|
2023-10-14 14:33:35 +02:00
|
|
|
{
|
|
|
|
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)
|
|
|
|
{
|
2023-10-22 15:16:05 +02:00
|
|
|
bildInfo = await ImageGenerator.GenerateImageAsync(imagePrompt, modelName, wunschInfo, _imageWidth, _imageHeight);
|
2023-10-14 14:33:35 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-10-22 15:16:05 +02:00
|
|
|
return bildInfo;
|
2023-10-14 14:33:35 +02:00
|
|
|
}
|
|
|
|
catch (Exception e)
|
|
|
|
{
|
|
|
|
NotificationService.Notify(new NotificationMessage()
|
|
|
|
{
|
|
|
|
Summary = "Es ist ein Fehler beim Erzeugen der Bilder aufgetreten, bitte versuche es erneut."
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
return null;
|
2023-08-05 00:43:11 +02:00
|
|
|
}
|
2023-08-04 14:42:03 +02:00
|
|
|
|
2023-10-11 14:41:43 +02:00
|
|
|
/// <summary>
|
|
|
|
/// Generiert Bilder oder aktualisiert sie mit dem neuen Prompt.
|
|
|
|
/// </summary>
|
2023-10-22 12:39:11 +02:00
|
|
|
private async Task GenerateImagesAsync()
|
2023-08-02 21:33:09 +02:00
|
|
|
{
|
|
|
|
_progressVisible = true;
|
2023-08-03 23:24:10 +02:00
|
|
|
_buttonVisible = false;
|
2023-08-02 21:33:09 +02:00
|
|
|
|
2023-10-22 12:39:11 +02:00
|
|
|
ClearOldGeneration();
|
2023-10-11 14:41:43 +02:00
|
|
|
|
2023-10-22 12:39:11 +02:00
|
|
|
amountOfAddons = maxAddons;
|
|
|
|
_addonsVisible = false;
|
|
|
|
_bothVisible = _buttonVisible && _addonsVisible;
|
|
|
|
await UpdateBusyMessage("Kirstens Assistent zerbricht sich über deine Idee den Kopf...");
|
2023-09-20 12:22:52 +02:00
|
|
|
|
2023-10-22 12:39:11 +02:00
|
|
|
await RequestImageIdeaAsync();
|
2023-08-02 21:33:09 +02:00
|
|
|
|
|
|
|
await UpdateBusyMessage("Kirstens Assistent hat eine Idee! Er wird sie nun malen...");
|
2023-10-10 18:18:17 +02:00
|
|
|
|
2023-10-22 12:39:11 +02:00
|
|
|
_wunschInfo = new()
|
2023-10-10 18:18:17 +02:00
|
|
|
{
|
2023-10-11 14:41:43 +02:00
|
|
|
BildBeschreibung = _imageIdea,
|
2023-10-14 14:33:35 +02:00
|
|
|
BildPrompt = "Individuelle Bild Prompts",
|
2023-10-10 18:18:17 +02:00
|
|
|
Datum = DateTime.Now,
|
2023-10-22 12:39:11 +02:00
|
|
|
GPTModel = _conversation!.Model,
|
|
|
|
Wunsch = _userIdea,
|
2023-10-14 14:33:35 +02:00
|
|
|
VorherigerWunsch = null
|
2023-10-10 18:18:17 +02:00
|
|
|
};
|
2023-10-22 12:39:11 +02:00
|
|
|
|
2023-10-11 14:41:43 +02:00
|
|
|
try
|
2023-08-05 00:43:11 +02:00
|
|
|
{
|
2023-10-22 12:39:11 +02:00
|
|
|
await WunschInfoData.AddWunschInfoAsync(_wunschInfo);
|
2023-08-05 00:43:11 +02:00
|
|
|
}
|
2023-10-11 14:41:43 +02:00
|
|
|
catch (Exception e)
|
|
|
|
{
|
|
|
|
NotificationService.Notify(new NotificationMessage()
|
|
|
|
{
|
|
|
|
Summary = "Es ist ein Fehler aufgetreten, bitte versuche es erneut."
|
|
|
|
});
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-10-22 12:39:11 +02:00
|
|
|
string requestImagePrompt = await File.ReadAllTextAsync($"{Directory.GetCurrentDirectory()}{@"/wwwroot/image_prompt.txt"}");
|
|
|
|
|
|
|
|
await RequestImagesAsync(_wunschInfo, requestImagePrompt);
|
2023-10-11 14:41:43 +02:00
|
|
|
|
2023-08-02 21:33:09 +02:00
|
|
|
_progressVisible = false;
|
2023-08-03 23:24:10 +02:00
|
|
|
_buttonVisible = true;
|
2023-08-04 14:42:03 +02:00
|
|
|
if (amountOfAddons > 0)
|
|
|
|
{
|
|
|
|
_addonsVisible = true;
|
|
|
|
_bothVisible = _buttonVisible && _addonsVisible;
|
|
|
|
await InvokeAsync(StateHasChanged);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
_addonsVisible = false;
|
|
|
|
_bothVisible = false;
|
|
|
|
}
|
2023-08-02 18:33:28 +02:00
|
|
|
}
|
2023-10-22 12:39:11 +02:00
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
2023-08-02 18:33:28 +02:00
|
|
|
}
|