ollamadiffuser 1.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,496 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>OllamaDiffuser Web UI</title>
7
+ <style>
8
+ * {
9
+ margin: 0;
10
+ padding: 0;
11
+ box-sizing: border-box;
12
+ }
13
+
14
+ body {
15
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
16
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
17
+ min-height: 100vh;
18
+ padding: 20px;
19
+ }
20
+
21
+ .container {
22
+ max-width: 1200px;
23
+ margin: 0 auto;
24
+ background: white;
25
+ border-radius: 16px;
26
+ box-shadow: 0 20px 40px rgba(0,0,0,0.1);
27
+ overflow: hidden;
28
+ }
29
+
30
+ .header {
31
+ background: linear-gradient(135deg, #4f46e5 0%, #7c3aed 100%);
32
+ color: white;
33
+ padding: 30px;
34
+ text-align: center;
35
+ }
36
+
37
+ .header h1 {
38
+ font-size: 2.5em;
39
+ margin-bottom: 10px;
40
+ }
41
+
42
+ .header p {
43
+ opacity: 0.9;
44
+ font-size: 1.1em;
45
+ }
46
+
47
+ .status-bar {
48
+ background: #f8fafc;
49
+ padding: 20px 30px;
50
+ border-bottom: 1px solid #e2e8f0;
51
+ display: flex;
52
+ justify-content: space-between;
53
+ align-items: center;
54
+ flex-wrap: wrap;
55
+ gap: 15px;
56
+ }
57
+
58
+ .status-item {
59
+ display: flex;
60
+ align-items: center;
61
+ gap: 8px;
62
+ }
63
+
64
+ .status-indicator {
65
+ width: 12px;
66
+ height: 12px;
67
+ border-radius: 50%;
68
+ }
69
+
70
+ .status-loaded {
71
+ background: #10b981;
72
+ }
73
+
74
+ .status-unloaded {
75
+ background: #ef4444;
76
+ }
77
+
78
+ .main-content {
79
+ display: grid;
80
+ grid-template-columns: 1fr 1fr;
81
+ gap: 30px;
82
+ padding: 30px;
83
+ }
84
+
85
+ @media (max-width: 768px) {
86
+ .main-content {
87
+ grid-template-columns: 1fr;
88
+ }
89
+ }
90
+
91
+ .form-section {
92
+ background: #f8fafc;
93
+ padding: 25px;
94
+ border-radius: 12px;
95
+ border: 1px solid #e2e8f0;
96
+ }
97
+
98
+ .form-section h2 {
99
+ color: #1e293b;
100
+ margin-bottom: 20px;
101
+ font-size: 1.5em;
102
+ }
103
+
104
+ .form-group {
105
+ margin-bottom: 20px;
106
+ }
107
+
108
+ .form-group label {
109
+ display: block;
110
+ margin-bottom: 8px;
111
+ color: #374151;
112
+ font-weight: 500;
113
+ }
114
+
115
+ .form-group input,
116
+ .form-group textarea {
117
+ width: 100%;
118
+ padding: 12px;
119
+ border: 1px solid #d1d5db;
120
+ border-radius: 8px;
121
+ font-size: 14px;
122
+ transition: border-color 0.2s;
123
+ }
124
+
125
+ .form-group input:focus,
126
+ .form-group textarea:focus {
127
+ outline: none;
128
+ border-color: #4f46e5;
129
+ box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.1);
130
+ }
131
+
132
+ .form-row {
133
+ display: grid;
134
+ grid-template-columns: 1fr 1fr;
135
+ gap: 15px;
136
+ }
137
+
138
+ .btn {
139
+ background: linear-gradient(135deg, #4f46e5 0%, #7c3aed 100%);
140
+ color: white;
141
+ padding: 12px 24px;
142
+ border: none;
143
+ border-radius: 8px;
144
+ font-size: 16px;
145
+ font-weight: 500;
146
+ cursor: pointer;
147
+ transition: transform 0.2s, box-shadow 0.2s;
148
+ width: 100%;
149
+ }
150
+
151
+ .btn:hover {
152
+ transform: translateY(-2px);
153
+ box-shadow: 0 10px 20px rgba(79, 70, 229, 0.3);
154
+ }
155
+
156
+ .btn:disabled {
157
+ background: #9ca3af;
158
+ cursor: not-allowed;
159
+ transform: none;
160
+ box-shadow: none;
161
+ }
162
+
163
+ .result-section {
164
+ text-align: center;
165
+ }
166
+
167
+ .result-image {
168
+ max-width: 100%;
169
+ border-radius: 12px;
170
+ box-shadow: 0 10px 25px rgba(0,0,0,0.1);
171
+ margin-bottom: 20px;
172
+ }
173
+
174
+ .error-message {
175
+ background: #fee2e2;
176
+ color: #dc2626;
177
+ padding: 15px;
178
+ border-radius: 8px;
179
+ margin-bottom: 20px;
180
+ border: 1px solid #fecaca;
181
+ }
182
+
183
+ .success-message {
184
+ background: #d1fae5;
185
+ color: #065f46;
186
+ padding: 15px;
187
+ border-radius: 8px;
188
+ margin-bottom: 20px;
189
+ border: 1px solid #a7f3d0;
190
+ }
191
+
192
+ .loading {
193
+ display: none;
194
+ text-align: center;
195
+ padding: 40px;
196
+ color: #6b7280;
197
+ }
198
+
199
+ .loading.show {
200
+ display: block;
201
+ }
202
+
203
+ .spinner {
204
+ border: 3px solid #f3f4f6;
205
+ border-top: 3px solid #4f46e5;
206
+ border-radius: 50%;
207
+ width: 40px;
208
+ height: 40px;
209
+ animation: spin 1s linear infinite;
210
+ margin: 0 auto 15px;
211
+ }
212
+
213
+ @keyframes spin {
214
+ 0% { transform: rotate(0deg); }
215
+ 100% { transform: rotate(360deg); }
216
+ }
217
+
218
+ .model-info {
219
+ background: #e0f2fe;
220
+ padding: 15px;
221
+ border-radius: 8px;
222
+ margin-bottom: 20px;
223
+ border: 1px solid #b3e5fc;
224
+ }
225
+
226
+ .model-management {
227
+ background: #f8fafc;
228
+ border: 1px solid #e2e8f0;
229
+ border-radius: 12px;
230
+ padding: 20px;
231
+ margin-bottom: 30px;
232
+ }
233
+
234
+ .model-controls {
235
+ display: flex;
236
+ gap: 10px;
237
+ align-items: center;
238
+ flex-wrap: wrap;
239
+ }
240
+
241
+ .model-controls select {
242
+ flex: 1;
243
+ min-width: 200px;
244
+ padding: 8px 12px;
245
+ border: 1px solid #d1d5db;
246
+ border-radius: 6px;
247
+ background: white;
248
+ }
249
+
250
+ .btn-small {
251
+ background: linear-gradient(135deg, #4f46e5 0%, #7c3aed 100%);
252
+ color: white;
253
+ padding: 8px 16px;
254
+ border: none;
255
+ border-radius: 6px;
256
+ font-size: 14px;
257
+ font-weight: 500;
258
+ cursor: pointer;
259
+ transition: transform 0.2s, box-shadow 0.2s;
260
+ white-space: nowrap;
261
+ }
262
+
263
+ .btn-small:hover {
264
+ transform: translateY(-1px);
265
+ box-shadow: 0 5px 15px rgba(79, 70, 229, 0.3);
266
+ }
267
+
268
+ .btn-small.btn-danger {
269
+ background: linear-gradient(135deg, #dc2626 0%, #b91c1c 100%);
270
+ }
271
+
272
+ .btn-small.btn-danger:hover {
273
+ box-shadow: 0 5px 15px rgba(220, 38, 38, 0.3);
274
+ }
275
+ </style>
276
+ </head>
277
+ <body>
278
+ <div class="container">
279
+ <div class="header">
280
+ <h1>🎨 OllamaDiffuser</h1>
281
+ <p>Image Generation Model Management Tool</p>
282
+ </div>
283
+
284
+ <div class="status-bar">
285
+ <div class="status-item">
286
+ <div class="status-indicator {{ 'status-loaded' if model_loaded else 'status-unloaded' }}"></div>
287
+ <span>Model Status: {{ 'Loaded' if model_loaded else 'Not Loaded' }}</span>
288
+ </div>
289
+ {% if current_model %}
290
+ <div class="status-item">
291
+ <span>Current Model: <strong>{{ current_model }}</strong></span>
292
+ </div>
293
+ {% endif %}
294
+ <div class="status-item">
295
+ <span>Installed Models: {{ installed_models|length }}</span>
296
+ </div>
297
+ <div class="status-item">
298
+ <div class="status-indicator {{ 'status-loaded' if current_lora else 'status-unloaded' }}"></div>
299
+ <span>LoRA Status: {{ 'Loaded' if current_lora else 'Not Loaded' }}</span>
300
+ </div>
301
+ {% if current_lora %}
302
+ <div class="status-item">
303
+ <span>Current LoRA: <strong>{{ current_lora }}</strong></span>
304
+ </div>
305
+ {% endif %}
306
+ <div class="status-item">
307
+ <span>Installed LoRAs: {{ installed_loras|length }}</span>
308
+ </div>
309
+ </div>
310
+
311
+ <div class="model-management">
312
+ <h3>🔧 Model Management</h3>
313
+ {% if installed_models %}
314
+ <form method="post" action="/load_model" style="margin-bottom: 15px;">
315
+ <div class="model-controls">
316
+ <select name="model_name" required>
317
+ <option value="">Select model to load...</option>
318
+ {% for model in installed_models %}
319
+ <option value="{{ model }}" {{ 'selected' if model == current_model else '' }}>{{ model }}</option>
320
+ {% endfor %}
321
+ </select>
322
+ <button type="submit" class="btn-small">🚀 Load Model</button>
323
+ </div>
324
+ </form>
325
+ {% endif %}
326
+
327
+ {% if model_loaded %}
328
+ <form method="post" action="/unload_model">
329
+ <button type="submit" class="btn-small btn-danger">🔄 Unload Current Model</button>
330
+ </form>
331
+ {% endif %}
332
+
333
+ {% if not installed_models %}
334
+ <div class="model-info">
335
+ <strong>📥 No installed models</strong><br>
336
+ Please install models using CLI: <code>ollamadiffuser pull model-name</code>
337
+ </div>
338
+ {% endif %}
339
+ </div>
340
+
341
+ <div class="model-management">
342
+ <h3>🔄 LoRA Management</h3>
343
+
344
+ <!-- Download LoRA Section -->
345
+ <form method="post" action="/pull_lora" style="margin-bottom: 15px;">
346
+ <div style="display: grid; grid-template-columns: 2fr 1fr 1fr auto; gap: 10px; align-items: end;">
347
+ <div>
348
+ <label for="repo_id" style="display: block; margin-bottom: 5px; font-size: 12px; color: #6b7280;">Hugging Face Repository ID</label>
349
+ <input type="text" name="repo_id" id="repo_id" placeholder="e.g.: openfree/flux-chatgpt-ghibli-lora" required style="width: 100%; padding: 8px 12px; border: 1px solid #d1d5db; border-radius: 6px; background: white; font-size: 14px;">
350
+ </div>
351
+ <div>
352
+ <label for="weight_name" style="display: block; margin-bottom: 5px; font-size: 12px; color: #6b7280;">Weight File Name (Optional)</label>
353
+ <input type="text" name="weight_name" id="weight_name" placeholder="e.g.: lora.safetensors" style="width: 100%; padding: 8px 12px; border: 1px solid #d1d5db; border-radius: 6px; background: white; font-size: 14px;">
354
+ </div>
355
+ <div>
356
+ <label for="alias" style="display: block; margin-bottom: 5px; font-size: 12px; color: #6b7280;">Alias (Optional)</label>
357
+ <input type="text" name="alias" id="alias" placeholder="e.g.: ghibli" style="width: 100%; padding: 8px 12px; border: 1px solid #d1d5db; border-radius: 6px; background: white; font-size: 14px;">
358
+ </div>
359
+ <button type="submit" class="btn-small">📥 Download LoRA</button>
360
+ </div>
361
+ </form>
362
+
363
+ <!-- Load LoRA Section -->
364
+ {% if installed_loras %}
365
+ <form method="post" action="/load_lora" style="margin-bottom: 15px;">
366
+ <div class="model-controls">
367
+ <select name="lora_name" required style="flex: 2;">
368
+ <option value="">Select LoRA to load...</option>
369
+ {% for lora_name, lora_info in installed_loras.items() %}
370
+ <option value="{{ lora_name }}" {{ 'selected' if lora_name == current_lora else '' }}>
371
+ {{ lora_name }} ({{ lora_info.get('repo_id', 'Unknown') }})
372
+ </option>
373
+ {% endfor %}
374
+ </select>
375
+ <div style="display: flex; flex-direction: column; min-width: 100px;">
376
+ <label for="scale" style="font-size: 12px; color: #6b7280; margin-bottom: 2px;">Strength</label>
377
+ <input type="number" name="scale" id="scale" value="1.0" min="0.1" max="2.0" step="0.1" style="padding: 8px 12px; border: 1px solid #d1d5db; border-radius: 6px; background: white; font-size: 14px;">
378
+ </div>
379
+ <button type="submit" class="btn-small" {{ 'disabled' if not model_loaded }}>🚀 Load LoRA</button>
380
+ </div>
381
+ </form>
382
+ {% endif %}
383
+
384
+ <!-- Unload LoRA Section -->
385
+ {% if current_lora %}
386
+ <form method="post" action="/unload_lora">
387
+ <button type="submit" class="btn-small btn-danger">🔄 Unload Current LoRA</button>
388
+ </form>
389
+ {% endif %}
390
+
391
+ <!-- LoRA Status -->
392
+ {% if not installed_loras %}
393
+ <div class="model-info">
394
+ <strong>📥 No installed LoRAs</strong><br>
395
+ Please enter a Hugging Face repository ID above to download LoRA, or use CLI: <code>ollamadiffuser lora pull repo-id</code>
396
+ </div>
397
+ {% endif %}
398
+
399
+ {% if installed_loras and not model_loaded %}
400
+ <div class="model-info">
401
+ <strong>⚠️ Note:</strong> You need to load a model first before using LoRA
402
+ </div>
403
+ {% endif %}
404
+ </div>
405
+
406
+ <div class="main-content">
407
+ <div class="form-section">
408
+ <h2>Image Generation</h2>
409
+
410
+ {% if not model_loaded %}
411
+ <div class="model-info">
412
+ <strong>⚠️ Note:</strong> Please first load a model in the model management area above, or use CLI: <code>ollamadiffuser load model-name</code>
413
+ </div>
414
+ {% endif %}
415
+
416
+ {% if success_message %}
417
+ <div class="success-message">
418
+ {{ success_message }}
419
+ </div>
420
+ {% endif %}
421
+
422
+ {% if error_message %}
423
+ <div class="error-message">
424
+ {{ error_message }}
425
+ </div>
426
+ {% endif %}
427
+
428
+ <form method="post" action="/generate" id="generateForm">
429
+ <div class="form-group">
430
+ <label for="prompt">Prompt</label>
431
+ <textarea name="prompt" id="prompt" rows="3" placeholder="Describe the image you want to generate..." required>{{ prompt or '' }}</textarea>
432
+ </div>
433
+
434
+ <div class="form-group">
435
+ <label for="negative_prompt">Negative Prompt</label>
436
+ <textarea name="negative_prompt" id="negative_prompt" rows="2" placeholder="Describe what you don't want in the image...">{{ negative_prompt or 'low quality, bad anatomy, worst quality, low resolution' }}</textarea>
437
+ </div>
438
+
439
+ <div class="form-row">
440
+ <div class="form-group">
441
+ <label for="width">Width</label>
442
+ <input type="number" name="width" id="width" value="{{ width or 1024 }}" min="512" max="2048" step="64">
443
+ </div>
444
+ <div class="form-group">
445
+ <label for="height">Height</label>
446
+ <input type="number" name="height" id="height" value="{{ height or 1024 }}" min="512" max="2048" step="64">
447
+ </div>
448
+ </div>
449
+
450
+ <div class="form-row">
451
+ <div class="form-group">
452
+ <label for="num_inference_steps">Inference Steps</label>
453
+ <input type="number" name="num_inference_steps" id="num_inference_steps" value="{{ num_inference_steps or 28 }}" min="1" max="100">
454
+ </div>
455
+ <div class="form-group">
456
+ <label for="guidance_scale">Guidance Scale</label>
457
+ <input type="number" name="guidance_scale" id="guidance_scale" value="{{ guidance_scale or 3.5 }}" min="0" max="20" step="0.1">
458
+ </div>
459
+ </div>
460
+
461
+ <button type="submit" class="btn" {{ 'disabled' if not model_loaded }}>
462
+ 🎨 Generate Image
463
+ </button>
464
+ </form>
465
+ </div>
466
+
467
+ <div class="result-section">
468
+ <h2>Generation Result</h2>
469
+
470
+ <div class="loading" id="loading">
471
+ <div class="spinner"></div>
472
+ <p>Generating image, please wait...</p>
473
+ </div>
474
+
475
+ {% if image_b64 %}
476
+ <img src="data:image/png;base64,{{ image_b64 }}" alt="Generated Image" class="result-image">
477
+ <p style="color: #6b7280; margin-top: 15px;">
478
+ <strong>Prompt:</strong> {{ prompt }}
479
+ </p>
480
+ {% else %}
481
+ <div style="background: #f9fafb; border: 2px dashed #d1d5db; border-radius: 12px; padding: 60px 20px; color: #6b7280;">
482
+ <div style="font-size: 3em; margin-bottom: 15px;">🖼️</div>
483
+ <p>Generated image will be displayed here</p>
484
+ </div>
485
+ {% endif %}
486
+ </div>
487
+ </div>
488
+ </div>
489
+
490
+ <script>
491
+ document.getElementById('generateForm').addEventListener('submit', function() {
492
+ document.getElementById('loading').classList.add('show');
493
+ });
494
+ </script>
495
+ </body>
496
+ </html>