Scalino84 commited on
Commit
3fb9e5f
·
verified ·
1 Parent(s): dfca2cb

Upload /home/user/app/bck/templates/index.html with huggingface_hub

Browse files
home/user/app/bck/templates/index.html ADDED
@@ -0,0 +1,371 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {% extends "base.html" %}
2
+
3
+ {% block title %}Flux Image Generator - Home{% endblock %}
4
+
5
+ {% block content %}
6
+ <h1>Flux Image Generator</h1>
7
+ <form id="generateForm" class="needs-validation custom-bg p-3 rounded" novalidate>
8
+ <!-- Prompt-Eingabe -->
9
+ <div class="mb-3">
10
+ <label for="prompt" class="form-label">Prompt:</label>
11
+ <textarea class="form-control" id="prompt" name="prompt" rows="4" required></textarea>
12
+ <div class="invalid-feedback">Bitte geben Sie einen Prompt ein.</div>
13
+ </div>
14
+ <!-- Album-Auswahl -->
15
+ <div class="mb-3">
16
+ <label for="album_id" class="form-label">Album:</label>
17
+ <input class="form-control" id="album_id" name="album_id" list="albums" placeholder="Wählen oder neues Album eingeben">
18
+ <datalist id="albums">
19
+ {% for album in albums %}
20
+ <option value="{{ album[1] }}">{{ album[0] }}</option>
21
+ {% endfor %}
22
+ </datalist>
23
+ </div>
24
+ <!-- Kategorie-Auswahl -->
25
+ <div class="mb-3">
26
+ <label for="category_id" class="form-label">Kategorie:</label>
27
+ <input class="form-control" id="category_id" name="category_id" list="categories" placeholder="Wählen oder neue Kategorie eingeben">
28
+ <datalist id="categories">
29
+ {% for category in categories %}
30
+ <option value="{{ category[1] }}">{{ category[0] }}</option>
31
+ {% endfor %}
32
+ </datalist>
33
+ </div>
34
+ <!-- Buttons zur Generierung und Optimierung -->
35
+ <button type="button" class="btn btn-primary mb-3" onclick="startGeneration()">Bild Generieren</button>
36
+ <button type="button" class="btn btn-secondary mb-3" onclick="optimizeOnly()">Nur Optimieren</button>
37
+ <button type="button" class="btn btn-secondary mb-3" onclick="copyPrompt()">Prompt Kopieren</button>
38
+
39
+ <!-- Fortschrittsanzeige -->
40
+ <div class="progress mb-3" id="progressContainer" style="display: none;">
41
+ <div id="progressBar" class="progress-bar progress-bar-striped progress-bar-animated" role="progressbar" style="width: 0%;" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100"></div>
42
+ </div>
43
+
44
+ <!-- Fortschrittsnachricht -->
45
+ <div id="progressMessage" class="mb-3" style="display: none;">
46
+ <p>Generiere Bilder, bitte warten...</p>
47
+ </div>
48
+
49
+ <!-- Erweiterte Einstellungen -->
50
+ <div class="accordion" id="advancedSettingsAccordion">
51
+ <div class="accordion-item custom-bg">
52
+ <h2 class="accordion-header" id="headingOne">
53
+ <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapseOne" aria-expanded="false" aria-controls="collapseOne">
54
+ Erweiterte Einstellungen
55
+ </button>
56
+ </h2>
57
+ <div id="collapseOne" class="accordion-collapse collapse" aria-labelledby="headingOne" data-bs-parent="#advancedSettingsAccordion">
58
+ <div class="accordion-body">
59
+ <div class="row g-3">
60
+ <div class="col-12 col-md-6">
61
+ <label for="num_outputs" class="form-label">Anzahl der Ausgaben:</label>
62
+ <select class="form-control" id="num_outputs" name="num_outputs">
63
+ <option value="1">1</option>
64
+ <option value="2">2</option>
65
+ <option value="3">3</option>
66
+ <option value="4">4</option>
67
+ </select>
68
+ </div>
69
+ <div class="col-12 col-md-6">
70
+ <label for="aspect_ratio" class="form-label">Seitenverhältnis:</label>
71
+ <select class="form-control" id="aspect_ratio" name="aspect_ratio">
72
+ <option value="1:1">1:1</option>
73
+ <option value="16:9">16:9</option>
74
+ <option value="21:9">21:9</option>
75
+ <option value="3:2">3:2</option>
76
+ <option value="2:3">2:3</option>
77
+ <option value="4:5">4:5</option>
78
+ <option value="5:4">5:4</option>
79
+ <option value="3:4">3:4</option>
80
+ <option value="4:3">4:3</option>
81
+ <option value="9:16">9:16</option>
82
+ <option value="9:21">9:21</option>
83
+ </select>
84
+ </div>
85
+ <div class="col-12 col-md-6">
86
+ <label for="output_format" class="form-label">Ausgabeformat:</label>
87
+ <select class="form-control" id="output_format" name="output_format">
88
+ <option value="png">PNG</option>
89
+ <option value="jpg">JPG</option>
90
+ <option value="webp">WEBP</option>
91
+ </select>
92
+ </div>
93
+ <div class="col-12 col-md-6">
94
+ <label for="guidance_scale" class="form-label">Guidance Scale:</label>
95
+ <input type="number" step="0.1" class="form-control" id="guidance_scale" name="guidance_scale" value="3.5">
96
+ </div>
97
+ <div class="col-12 col-md-6">
98
+ <label for="output_quality" class="form-label">Ausgabequalität:</label>
99
+ <input type="number" class="form-control" id="output_quality" name="output_quality" value="80">
100
+ </div>
101
+ <div class="col-12 col-md-6">
102
+ <label for="prompt_strength" class="form-label">Prompt Strength:</label>
103
+ <input type="number" step="0.1" class="form-control" id="prompt_strength" name="prompt_strength" value="0.8">
104
+ </div>
105
+ <div class="col-12 col-md-6">
106
+ <label for="num_inference_steps" class="form-label">Anzahl der Inference Steps:</label>
107
+ <input type="number" class="form-control" id="num_inference_steps" name="num_inference_steps" value="28">
108
+ </div>
109
+ <div class="col-12 col-md-6">
110
+ <label for="lora_scale" class="form-label">LoRA Scale:</label>
111
+ <input type="number" step="0.1" class="form-control" id="lora_scale" name="lora_scale" value="0.8">
112
+ </div>
113
+ <div class="col-12 col-md-6 d-flex align-items-center">
114
+ <div class="form-switch mb-3">
115
+ <input class="form-check-input" type="checkbox" id="hf_lora_toggle" name="hf_lora_toggle" checked>
116
+ <label class="form-check-label" for="hf_lora_toggle">HF LoRA verwenden</label>
117
+ </div>
118
+ <div class="form-switch mb-3 ms-3">
119
+ <input class="form-check-input" type="checkbox" id="agent" name="agent" checked>
120
+ <label class="form-check-label" for="agent">Mistral Agent verwenden</label>
121
+ </div>
122
+ </div>
123
+ </div>
124
+ </div>
125
+ </div>
126
+ </div>
127
+ </div>
128
+
129
+ <!-- Batch-Optimierung -->
130
+ <div class="accordion mt-3" id="batchOptimizationAccordion">
131
+ <div class="accordion-item custom-bg">
132
+ <h2 class="accordion-header" id="headingTwo">
133
+ <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapseTwo" aria-expanded="false" aria-controls="collapseTwo">
134
+ Batch-Optimierung
135
+ </button>
136
+ </h2>
137
+ <div id="collapseTwo" class="accordion-collapse collapse" aria-labelledby="headingTwo" data-bs-parent="#batchOptimizationAccordion">
138
+ <div class="accordion-body">
139
+ <textarea id="batchPrompts" class="form-control" rows="10" placeholder="Mehrere Prompts eingeben, einer pro Zeile"></textarea>
140
+ <button type="button" class="btn btn-primary mt-2" onclick="batchOptimize()">Batch Optimieren</button>
141
+ </div>
142
+ </div>
143
+ </div>
144
+ </div>
145
+ </form>
146
+
147
+ <!-- Ausgabebereich -->
148
+ <div id="output" class="mt-3"></div>
149
+ {% endblock %}
150
+
151
+ {% block scripts %}
152
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/cropperjs/1.5.12/cropper.min.js"></script>
153
+ <script>
154
+ // Initialisierung des Croppers
155
+ let cropper;
156
+ function startCropper(imageElement) {
157
+ if (cropper) {
158
+ cropper.destroy();
159
+ }
160
+ cropper = new Cropper(imageElement, {
161
+ aspectRatio: 1,
162
+ viewMode: 1,
163
+ autoCropArea: 1,
164
+ responsive: true,
165
+ });
166
+ }
167
+
168
+ // Funktion zur Bildgenerierung
169
+ function startGeneration() {
170
+ const form = document.getElementById('generateForm');
171
+ if (!form.checkValidity()) {
172
+ form.classList.add('was-validated');
173
+ return;
174
+ }
175
+
176
+ // Fortschrittsanzeige einblenden
177
+ const progressContainer = document.getElementById('progressContainer');
178
+ progressContainer.style.display = 'block';
179
+ const progressBarInner = document.getElementById('progressBar');
180
+ progressBarInner.style.width = '0%';
181
+ progressBarInner.setAttribute('aria-valuenow', 0);
182
+
183
+ const progressMessage = document.getElementById('progressMessage');
184
+ progressMessage.style.display = 'block';
185
+
186
+ const outputDiv = document.getElementById('output');
187
+ outputDiv.innerHTML = '';
188
+
189
+ const formData = new FormData(form);
190
+
191
+ // HF LoRA-Einstellung hinzufügen
192
+ if (document.getElementById('hf_lora_toggle').checked) {
193
+ formData.append('hf_lora', 'Scalino84/my-flux-face');
194
+ } else {
195
+ formData.delete('hf_lora');
196
+ }
197
+
198
+ // Formulardaten in ein Objekt umwandeln
199
+ const formObject = Object.fromEntries(formData.entries());
200
+
201
+ // WebSocket-Verbindung öffnen
202
+ const socket = new WebSocket('ws://localhost:8000/ws');
203
+
204
+ socket.onopen = function (event) {
205
+ socket.send(JSON.stringify(formObject));
206
+ };
207
+
208
+ socket.onmessage = function (event) {
209
+ const data = JSON.parse(event.data);
210
+ if (data.optimized_prompt) {
211
+ document.getElementById('prompt').value = data.optimized_prompt;
212
+ }
213
+ if (data.progress !== undefined) {
214
+ progressBarInner.style.width = `${data.progress}%`;
215
+ progressBarInner.setAttribute('aria-valuenow', data.progress);
216
+ }
217
+ if (data.message) {
218
+ const message = document.createElement('div');
219
+ message.textContent = data.message;
220
+ outputDiv.appendChild(message);
221
+ }
222
+ if (data.generated_files) {
223
+ data.generated_files.forEach(file => {
224
+ const img = document.createElement('img');
225
+ img.src = file;
226
+ img.style.maxWidth = '100%';
227
+ outputDiv.appendChild(img);
228
+ const promptText = document.createElement('p');
229
+ promptText.textContent = `Prompt: ${formData.get('prompt')}`;
230
+ outputDiv.appendChild(promptText);
231
+ const copyButton = document.createElement('button');
232
+ copyButton.textContent = 'Prompt Kopieren';
233
+ copyButton.className = 'btn btn-secondary mt-2';
234
+ copyButton.onclick = function() { copyPrompt(formData.get('prompt')) };
235
+ outputDiv.appendChild(copyButton);
236
+ outputDiv.appendChild(document.createElement('br'));
237
+ });
238
+ // Fortschrittsanzeige ausblenden
239
+ progressContainer.style.display = 'none';
240
+ progressMessage.style.display = 'none';
241
+ }
242
+ };
243
+
244
+ socket.onerror = function (event) {
245
+ console.error('WebSocket error:', event);
246
+ // Fortschrittsanzeige ausblenden im Fehlerfall
247
+ progressContainer.style.display = 'none';
248
+ progressMessage.style.display = 'none';
249
+ };
250
+
251
+ socket.onclose = function (event) {
252
+ console.log('WebSocket connection closed:', event);
253
+ };
254
+ }
255
+
256
+ // Funktion zur Optimierung des Prompts
257
+ function optimizeOnly() {
258
+ const form = document.getElementById('generateForm');
259
+ if (!form.checkValidity()) {
260
+ form.classList.add('was-validated');
261
+ return;
262
+ }
263
+
264
+ const formData = new FormData(form);
265
+
266
+ // HF LoRA-Einstellung hinzufügen
267
+ if (document.getElementById('hf_lora_toggle').checked) {
268
+ formData.append('hf_lora', 'Scalino84/my-flux-face');
269
+ } else {
270
+ formData.delete('hf_lora');
271
+ }
272
+
273
+ // Formulardaten in ein Objekt umwandeln
274
+ const formObject = Object.fromEntries(formData.entries());
275
+ formObject.optimize_only = true;
276
+
277
+ // WebSocket-Verbindung öffnen
278
+ const socket = new WebSocket('ws://localhost:8000/ws');
279
+
280
+ socket.onopen = function (event) {
281
+ socket.send(JSON.stringify(formObject));
282
+ };
283
+
284
+ socket.onmessage = function (event) {
285
+ const data = JSON.parse(event.data);
286
+ if (data.optimized_prompt) {
287
+ document.getElementById('prompt').value = data.optimized_prompt;
288
+ }
289
+ };
290
+
291
+ socket.onerror = function (event) {
292
+ console.error('WebSocket error:', event);
293
+ };
294
+
295
+ socket.onclose = function (event) {
296
+ console.log('WebSocket connection closed:', event);
297
+ };
298
+ }
299
+
300
+ function batchOptimize() {
301
+ // Prompts aus dem Textbereich sammeln
302
+ const batchPrompts = document.getElementById('batchPrompts').value.split('\n').filter(prompt => prompt.trim() !== '');
303
+ if (batchPrompts.length === 0) {
304
+ alert("Bitte geben Sie mindestens einen Prompt ein.");
305
+ return;
306
+ }
307
+
308
+ // Formulardaten sammeln
309
+ const formData = new FormData(document.getElementById('generateForm'));
310
+ const prompts = batchPrompts.map(prompt => {
311
+ const data = Object.fromEntries(formData);
312
+ data.prompt = prompt;
313
+ return data;
314
+ });
315
+
316
+ // Add HF LoRA toggle value to each prompt
317
+ if (hf_lora_toggle.checked) {
318
+ formData.append('hf_lora', 'Scalino84/my-flux-face');
319
+ } else {
320
+ formData.delete('hf_lora');
321
+ }
322
+
323
+ // WebSocket-Verbindung öffnen
324
+ const socket = new WebSocket('ws://localhost:8000/ws');
325
+
326
+ socket.onopen = function () {
327
+ // Prompts an den Server senden
328
+ socket.send(JSON.stringify({ prompts }));
329
+ };
330
+
331
+ socket.onmessage = function (event) {
332
+ const data = JSON.parse(event.data);
333
+ if (data.optimized_prompt) {
334
+ document.getElementById('prompt').value = data.optimized_prompt;
335
+ }
336
+ if (data.generated_files) {
337
+ data.generated_files.forEach(file => {
338
+ const livePreviewImage = document.getElementById('livePreviewImage');
339
+ if (livePreviewImage) {
340
+ livePreviewImage.src = file;
341
+ } else {
342
+ const img = document.createElement('img');
343
+ img.id = 'livePreviewImage';
344
+ img.src = file;
345
+ img.style.maxWidth = '100%';
346
+ document.getElementById('output').appendChild(img);
347
+ }
348
+ });
349
+ }
350
+ };
351
+
352
+ socket.onerror = function (event) {
353
+ console.error('WebSocket error:', event);
354
+ alert('Ein Fehler ist aufgetreten. Bitte versuchen Sie es erneut.');
355
+ };
356
+
357
+ socket.onclose = function (event) {
358
+ console.log('WebSocket connection closed:', event);
359
+ };
360
+ }
361
+
362
+ function copyPrompt() {
363
+ const promptText = document.getElementById('prompt').value;
364
+ navigator.clipboard.writeText(promptText).then(() => {
365
+ alert('Prompt in die Zwischenablage kopiert!');
366
+ }).catch(err => {
367
+ console.error('Fehler beim Kopieren des Prompts:', err);
368
+ });
369
+ }
370
+ </script>
371
+ {% endblock %}