awacke1 commited on
Commit
1cd253f
·
verified ·
1 Parent(s): 637ba39

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +240 -282
app.py CHANGED
@@ -2,128 +2,54 @@ import os
2
  import random
3
  import uuid
4
  import base64
 
 
5
  import gradio as gr
6
  import numpy as np
7
- from PIL import Image
8
- import spaces
9
  import torch
10
- import glob
11
  from datetime import datetime
12
- import pandas as pd
13
- import json
14
- import re
15
-
16
  from diffusers import StableDiffusionXLPipeline, EulerAncestralDiscreteScheduler
 
17
 
18
- DESCRIPTION = """# 🎨 ArtForge: Community AI Gallery
19
-
20
- Create, curate, and compete with AI-generated art. Join our creative multiplayer experience! 🖼️🏆✨
21
- """
22
-
23
- # Global variables
24
- image_metadata = pd.DataFrame(columns=['Filename', 'Prompt', 'Likes', 'Dislikes', 'Hearts', 'Created'])
25
  LIKES_CACHE_FILE = "likes_cache.json"
 
 
 
 
26
 
27
- def load_likes_cache():
28
- if os.path.exists(LIKES_CACHE_FILE):
29
- with open(LIKES_CACHE_FILE, 'r') as f:
 
30
  return json.load(f)
31
  return {}
32
 
33
- def save_likes_cache(cache):
34
- with open(LIKES_CACHE_FILE, 'w') as f:
35
- json.dump(cache, f)
36
-
37
- likes_cache = load_likes_cache()
38
-
39
- def create_download_link(filename):
40
- with open(filename, "rb") as file:
41
- encoded_string = base64.b64encode(file.read()).decode('utf-8')
42
- download_link = f'<a href="data:image/png;base64,{encoded_string}" download="{filename}">Download Image</a>'
43
- return download_link
44
-
45
- def save_image(img, prompt):
46
- global image_metadata, likes_cache
47
- timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
48
- safe_prompt = re.sub(r'[^\w\s-]', '', prompt.lower())[:50] # Limit to 50 characters
49
- safe_prompt = re.sub(r'[-\s]+', '-', safe_prompt).strip('-')
50
- filename = f"{timestamp}_{safe_prompt}.png"
51
- img.save(filename)
52
- new_row = pd.DataFrame({
53
- 'Filename': [filename],
54
- 'Prompt': [prompt],
55
- 'Likes': [0],
56
- 'Dislikes': [0],
57
- 'Hearts': [0],
58
- 'Created': [datetime.now()]
59
- })
60
- image_metadata = pd.concat([image_metadata, new_row], ignore_index=True)
61
- likes_cache[filename] = {'likes': 0, 'dislikes': 0, 'hearts': 0}
62
- save_likes_cache(likes_cache)
63
- return filename
64
-
65
- def randomize_seed_fn(seed: int, randomize_seed: bool) -> int:
66
- if randomize_seed:
67
- seed = random.randint(0, MAX_SEED)
68
- return seed
69
-
70
- def get_image_gallery():
71
- global image_metadata
72
- image_files = image_metadata['Filename'].tolist()
73
- return [(file, get_image_caption(file)) for file in image_files if os.path.exists(file)]
74
-
75
- def get_image_caption(filename):
76
- global likes_cache, image_metadata
77
- if filename in likes_cache:
78
- likes = likes_cache[filename]['likes']
79
- dislikes = likes_cache[filename]['dislikes']
80
- hearts = likes_cache[filename]['hearts']
81
- prompt = image_metadata[image_metadata['Filename'] == filename]['Prompt'].values[0]
82
- return f"{filename}\nPrompt: {prompt}\n👍 {likes} 👎 {dislikes} ❤️ {hearts}"
83
- return filename
84
-
85
- def delete_all_images():
86
- global image_metadata, likes_cache
87
- for file in image_metadata['Filename']:
88
- if os.path.exists(file):
89
- os.remove(file)
90
- image_metadata = pd.DataFrame(columns=['Filename', 'Prompt', 'Likes', 'Dislikes', 'Hearts', 'Created'])
91
- likes_cache = {}
92
- save_likes_cache(likes_cache)
93
- return get_image_gallery(), image_metadata.values.tolist()
94
-
95
- def delete_image(filename):
96
- global image_metadata, likes_cache
97
- if filename and os.path.exists(filename):
98
- os.remove(filename)
99
- image_metadata = image_metadata[image_metadata['Filename'] != filename]
100
- if filename in likes_cache:
101
- del likes_cache[filename]
102
- save_likes_cache(likes_cache)
103
- return get_image_gallery(), image_metadata.values.tolist()
104
-
105
- def vote(filename, vote_type):
106
- global likes_cache
107
- if filename in likes_cache:
108
- likes_cache[filename][vote_type.lower()] += 1
109
- save_likes_cache(likes_cache)
110
- return get_image_gallery(), image_metadata.values.tolist()
111
 
112
- def get_random_style():
113
- styles = [
114
- "Impressionist", "Cubist", "Surrealist", "Abstract Expressionist",
115
- "Pop Art", "Minimalist", "Baroque", "Art Nouveau", "Pointillist", "Fauvism"
116
- ]
117
- return random.choice(styles)
118
 
119
- MAX_SEED = np.iinfo(np.int32).max
 
120
 
121
- if not torch.cuda.is_available():
122
- DESCRIPTION += "\n<p>Running on CPU 🥶 This demo may not work on CPU.</p>"
123
-
124
- USE_TORCH_COMPILE = 0
125
- ENABLE_CPU_OFFLOAD = 0
126
 
 
 
 
 
127
  if torch.cuda.is_available():
128
  pipe = StableDiffusionXLPipeline.from_pretrained(
129
  "fluently/Fluently-XL-v4",
@@ -131,26 +57,60 @@ if torch.cuda.is_available():
131
  use_safetensors=True,
132
  )
133
  pipe.scheduler = EulerAncestralDiscreteScheduler.from_config(pipe.scheduler.config)
134
-
135
  pipe.load_lora_weights("ehristoforu/dalle-3-xl-v2", weight_name="dalle-3-xl-lora-v2.safetensors", adapter_name="dalle")
136
  pipe.set_adapters("dalle")
137
-
138
  pipe.to("cuda")
139
 
140
- @spaces.GPU(enable_queue=True)
141
- def generate(
142
- prompt: str,
143
- negative_prompt: str = "",
144
- use_negative_prompt: bool = False,
145
- seed: int = 0,
146
- width: int = 1024,
147
- height: int = 1024,
148
- guidance_scale: float = 3,
149
- randomize_seed: bool = False,
150
- progress=gr.Progress(track_tqdm=True),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
151
  ):
152
- seed = int(randomize_seed_fn(seed, randomize_seed))
 
153
 
 
154
  if not use_negative_prompt:
155
  negative_prompt = ""
156
 
@@ -165,185 +125,183 @@ def generate(
165
  cross_attention_kwargs={"scale": 0.65},
166
  output_type="pil",
167
  ).images
168
- image_paths = [save_image(img, prompt) for img in images]
169
- download_links = [create_download_link(path) for path in image_paths]
170
 
171
- return image_paths, seed, download_links, get_image_gallery(), image_metadata.values.tolist()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
172
 
173
  examples = [
174
- f"{get_random_style()} painting of a majestic lighthouse on a rocky coast. Use bold brushstrokes and a vibrant color palette to capture the interplay of light and shadow as the lighthouse beam cuts through a stormy night sky.",
175
- f"{get_random_style()} still life featuring a pair of vintage eyeglasses. Focus on the intricate details of the frames and lenses, using a warm color scheme to evoke a sense of nostalgia and wisdom.",
176
- f"{get_random_style()} depiction of a rustic wooden stool in a sunlit artist's studio. Emphasize the texture of the wood and the interplay of light and shadow, using a mix of earthy tones and highlights.",
177
- f"{get_random_style()} scene viewed through an ornate window frame. Contrast the intricate details of the window with a dreamy, soft-focus landscape beyond, using a palette that transitions from cool interior tones to warm exterior hues.",
178
- f"{get_random_style()} close-up study of interlaced fingers. Use a monochromatic color scheme to emphasize the form and texture of the hands, with dramatic lighting to create depth and emotion.",
179
- f"{get_random_style()} composition featuring a set of dice in motion. Capture the energy and randomness of the throw, using a dynamic color palette and blurred lines to convey movement.",
180
- f"{get_random_style()} interpretation of heaven. Create an ethereal atmosphere with soft, billowing clouds and radiant light, using a palette of celestial blues, golds, and whites.",
181
- f"{get_random_style()} portrayal of an ancient, mystical gate. Combine architectural details with elements of fantasy, using a rich, jewel-toned palette to create an air of mystery and magic.",
182
- f"{get_random_style()} portrait of a curious cat. Focus on capturing the feline's expressive eyes and sleek form, using a mix of bold and subtle colors to bring out the cat's personality.",
183
- f"{get_random_style()} abstract representation of toes in sand. Use textured brushstrokes to convey the feeling of warm sand, with a palette inspired by a sun-drenched beach."
184
  ]
185
 
186
- css = '''
187
- .gradio-container{max-width: 1024px !important}
188
- h1{text-align:center}
189
- footer {
190
- visibility: hidden
191
- }
192
- '''
193
-
194
- with gr.Blocks(theme=gr.themes.Soft(), css=css) as demo:
195
  gr.Markdown(DESCRIPTION)
196
 
197
  with gr.Tab("Generate Images"):
198
- with gr.Group():
199
- with gr.Row():
200
- prompt = gr.Text(
201
- label="Prompt",
202
- show_label=False,
203
- max_lines=1,
204
- placeholder="Enter your prompt",
205
- container=False,
206
- )
207
- run_button = gr.Button("Run", scale=0)
208
- result = gr.Gallery(label="Result", columns=1, preview=True, show_label=False)
209
- with gr.Accordion("Advanced options", open=False):
210
- use_negative_prompt = gr.Checkbox(label="Use negative prompt", value=True)
211
- negative_prompt = gr.Text(
212
- label="Negative prompt",
213
- lines=4,
214
- max_lines=6,
215
- value="""(deformed, distorted, disfigured:1.3), poorly drawn, bad anatomy, wrong anatomy, extra limb, missing limb, floating limbs, (mutated hands and fingers:1.4), disconnected limbs, mutation, mutated, ugly, disgusting, blurry, amputation, (NSFW:1.25)""",
216
- placeholder="Enter a negative prompt",
217
- visible=True,
218
- )
219
- seed = gr.Slider(
220
- label="Seed",
221
- minimum=0,
222
- maximum=MAX_SEED,
223
- step=1,
224
- value=0,
225
- visible=True
226
- )
227
- randomize_seed = gr.Checkbox(label="Randomize seed", value=True)
228
- with gr.Row(visible=True):
229
- width = gr.Slider(
230
- label="Width",
231
- minimum=512,
232
- maximum=2048,
233
- step=8,
234
- value=1920,
235
- )
236
- height = gr.Slider(
237
- label="Height",
238
- minimum=512,
239
- maximum=2048,
240
- step=8,
241
- value=1080,
242
- )
243
- with gr.Row():
244
- guidance_scale = gr.Slider(
245
- label="Guidance Scale",
246
- minimum=0.1,
247
- maximum=20.0,
248
- step=0.1,
249
- value=20.0,
250
- )
251
-
252
- gr.Examples(
253
- examples=examples,
254
- inputs=prompt,
255
- outputs=[result, seed],
256
- fn=generate,
257
- cache_examples=False,
258
- )
259
-
260
- with gr.Tab("Gallery and Voting"):
261
- image_gallery = gr.Gallery(label="Generated Images", show_label=True, columns=4, height="auto")
262
-
263
  with gr.Row():
264
- like_button = gr.Button("👍 Like")
265
- dislike_button = gr.Button("👎 Dislike")
266
- heart_button = gr.Button("❤️ Heart")
267
- delete_image_button = gr.Button("🗑️ Delete Selected Image")
268
-
269
- selected_image = gr.State(None)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
270
 
271
- with gr.Tab("Metadata and Management"):
 
272
  metadata_df = gr.Dataframe(
273
  label="Image Metadata",
274
  headers=["Filename", "Prompt", "Likes", "Dislikes", "Hearts", "Created"],
275
  interactive=False
276
  )
277
- delete_all_button = gr.Button("🗑️ Delete All Images")
278
-
279
- use_negative_prompt.change(
280
- fn=lambda x: gr.update(visible=x),
281
- inputs=use_negative_prompt,
282
- outputs=negative_prompt,
283
- api_name=False,
284
- )
285
-
286
- delete_all_button.click(
287
- fn=delete_all_images,
288
- inputs=[],
289
- outputs=[image_gallery, metadata_df],
290
- )
291
-
292
- image_gallery.select(
293
- fn=lambda evt: evt,
294
- inputs=[],
295
- outputs=[selected_image],
296
- )
297
-
298
- like_button.click(
299
- fn=lambda x: vote(x, 'likes'),
300
- inputs=[selected_image],
301
- outputs=[image_gallery, metadata_df],
302
- )
303
 
304
- dislike_button.click(
305
- fn=lambda x: vote(x, 'dislikes'),
306
- inputs=[selected_image],
307
- outputs=[image_gallery, metadata_df],
308
- )
309
 
310
- heart_button.click(
311
- fn=lambda x: vote(x, 'hearts'),
312
- inputs=[selected_image],
313
- outputs=[image_gallery, metadata_df],
314
- )
315
 
316
- delete_image_button.click(
317
- fn=delete_image,
318
- inputs=[selected_image],
319
- outputs=[image_gallery, metadata_df],
320
- )
321
 
322
- def update_gallery_and_metadata():
323
- return gr.update(value=get_image_gallery()), gr.update(value=image_metadata.values.tolist())
324
-
325
- gr.on(
326
- triggers=[
327
- prompt.submit,
328
- negative_prompt.submit,
329
- run_button.click,
330
- ],
331
- fn=generate,
332
- inputs=[
333
- prompt,
334
- negative_prompt,
335
- use_negative_prompt,
336
- seed,
337
- width,
338
- height,
339
- guidance_scale,
340
- randomize_seed,
341
- ],
342
- outputs=[result, seed, gr.HTML(visible=False), image_gallery, metadata_df],
343
- api_name="run",
344
- )
345
 
346
- demo.load(fn=update_gallery_and_metadata, outputs=[image_gallery, metadata_df])
347
 
348
- if __name__ == "__main__":
349
- demo.queue(max_size=20).launch(share=True, debug=False)
 
2
  import random
3
  import uuid
4
  import base64
5
+ import json
6
+ import re
7
  import gradio as gr
8
  import numpy as np
9
+ import pandas as pd
 
10
  import torch
11
+ from PIL import Image
12
  from datetime import datetime
 
 
 
 
13
  from diffusers import StableDiffusionXLPipeline, EulerAncestralDiscreteScheduler
14
+ import anthropic
15
 
16
+ # ============================================================
17
+ # === GLOBALS & DATA STORAGE FILES
18
+ # ============================================================
 
 
 
 
19
  LIKES_CACHE_FILE = "likes_cache.json"
20
+ LOG_CACHE_FILE = "log_cache.json"
21
+ QUOTE_CACHE_FILE = "quotes_cache.json"
22
+
23
+ STATIC_URL_PREFIX = "https://huggingface.co/spaces/awacke1/dalle-3-xl-lora-v2/file="
24
 
25
+ # Initialize caches / load from JSON
26
+ def load_json(file):
27
+ if os.path.exists(file):
28
+ with open(file, 'r', encoding='utf-8') as f:
29
  return json.load(f)
30
  return {}
31
 
32
+ def save_json(file, data):
33
+ with open(file, 'w', encoding='utf-8') as f:
34
+ json.dump(data, f, indent=4)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35
 
36
+ likes_cache = load_json(LIKES_CACHE_FILE) or {}
37
+ chat_logs = load_json(LOG_CACHE_FILE) if os.path.exists(LOG_CACHE_FILE) else []
38
+ quotes = load_json(QUOTE_CACHE_FILE) if os.path.exists(QUOTE_CACHE_FILE) else []
 
 
 
39
 
40
+ # DataFrame for images
41
+ image_metadata = pd.DataFrame(columns=['Filename','Prompt','Likes','Dislikes','Hearts','Created'])
42
 
43
+ # ============================================================
44
+ # === ANTHROPIC CLIENT (Claude)
45
+ # ============================================================
46
+ anthropic_api_key = os.environ.get("ANTHROPIC_API_KEY", None)
47
+ claude_client = anthropic.Anthropic(api_key=anthropic_api_key) if anthropic_api_key else None
48
 
49
+ # ============================================================
50
+ # === IMAGE PIPELINE
51
+ # ============================================================
52
+ pipe = None
53
  if torch.cuda.is_available():
54
  pipe = StableDiffusionXLPipeline.from_pretrained(
55
  "fluently/Fluently-XL-v4",
 
57
  use_safetensors=True,
58
  )
59
  pipe.scheduler = EulerAncestralDiscreteScheduler.from_config(pipe.scheduler.config)
 
60
  pipe.load_lora_weights("ehristoforu/dalle-3-xl-v2", weight_name="dalle-3-xl-lora-v2.safetensors", adapter_name="dalle")
61
  pipe.set_adapters("dalle")
 
62
  pipe.to("cuda")
63
 
64
+ MAX_SEED = np.iinfo(np.int32).max
65
+
66
+ # ============================================================
67
+ # === HELPER FUNCTIONS
68
+ # ============================================================
69
+ def randomize_seed_fn(seed: int, randomize_seed: bool):
70
+ if randomize_seed:
71
+ seed = random.randint(0, MAX_SEED)
72
+ return int(seed)
73
+
74
+ def sanitize_prompt(prompt):
75
+ return re.sub(r'[^\w\s-]', '', prompt.lower())[:50]
76
+
77
+ def save_image_locally(img, prompt):
78
+ timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
79
+ safe_prompt = sanitize_prompt(prompt)
80
+ filename = f"{timestamp}_{safe_prompt}.png"
81
+ img.save(filename)
82
+ if filename not in likes_cache:
83
+ likes_cache[filename] = {'likes': 0, 'dislikes': 0, 'hearts': 0}
84
+ save_json(LIKES_CACHE_FILE, likes_cache)
85
+ global image_metadata
86
+ new_row = {
87
+ 'Filename': filename,
88
+ 'Prompt': prompt,
89
+ 'Likes': 0,
90
+ 'Dislikes': 0,
91
+ 'Hearts': 0,
92
+ 'Created': str(datetime.now())
93
+ }
94
+ image_metadata = pd.concat([image_metadata, pd.DataFrame([new_row])], ignore_index=True)
95
+ return filename
96
+
97
+ def log_input_output(user_input, model_output, link=""):
98
+ global chat_logs
99
+ chat_logs.append({
100
+ "timestamp": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
101
+ "input": user_input,
102
+ "output": model_output,
103
+ "file_link": link
104
+ })
105
+ save_json(LOG_CACHE_FILE, chat_logs)
106
+
107
+ def generate_image(
108
+ prompt, negative_prompt, use_negative_prompt, seed, width, height, guidance_scale, randomize_seed
109
  ):
110
+ if pipe is None:
111
+ return ["No GPU available, cannot generate images."], 0, [], [], []
112
 
113
+ seed = randomize_seed_fn(seed, randomize_seed)
114
  if not use_negative_prompt:
115
  negative_prompt = ""
116
 
 
125
  cross_attention_kwargs={"scale": 0.65},
126
  output_type="pil",
127
  ).images
 
 
128
 
129
+ filenames = []
130
+ for img in images:
131
+ fname = save_image_locally(img, prompt)
132
+ filenames.append(fname)
133
+
134
+ links = [f"{STATIC_URL_PREFIX}{f}" for f in filenames]
135
+ # Log the generation
136
+ log_input_output(user_input=prompt, model_output="(image generated)", link=", ".join(links))
137
+
138
+ # Return Gradio objects
139
+ return filenames, seed, links, get_image_gallery(), image_metadata.values.tolist()
140
+
141
+ def get_image_gallery():
142
+ return [
143
+ (row["Filename"], f"{row['Filename']}\nPrompt: {row['Prompt']}\n👍 {row['Likes']} 👎 {row['Dislikes']} ❤️ {row['Hearts']}")
144
+ for _, row in image_metadata.iterrows()
145
+ if os.path.exists(row["Filename"])
146
+ ]
147
+
148
+ def vote_image(filename, vote_type):
149
+ if filename and filename in likes_cache:
150
+ likes_cache[filename][vote_type] += 1
151
+ save_json(LIKES_CACHE_FILE, likes_cache)
152
+ idx = image_metadata.index[image_metadata['Filename'] == filename]
153
+ if not idx.empty:
154
+ image_metadata.at[idx, vote_type.capitalize()] = image_metadata.at[idx, vote_type.capitalize()] + 1
155
+ return get_image_gallery(), image_metadata.values.tolist()
156
+
157
+ def delete_image(filename):
158
+ if filename and os.path.exists(filename):
159
+ os.remove(filename)
160
+ if filename in likes_cache:
161
+ del likes_cache[filename]
162
+ save_json(LIKES_CACHE_FILE, likes_cache)
163
+ global image_metadata
164
+ image_metadata = image_metadata[image_metadata['Filename'] != filename]
165
+ return get_image_gallery(), image_metadata.values.tolist()
166
+
167
+ def delete_all_images():
168
+ global image_metadata, likes_cache
169
+ for f in image_metadata["Filename"].tolist():
170
+ if os.path.exists(f):
171
+ os.remove(f)
172
+ image_metadata = pd.DataFrame(columns=['Filename','Prompt','Likes','Dislikes','Hearts','Created'])
173
+ likes_cache.clear()
174
+ save_json(LIKES_CACHE_FILE, likes_cache)
175
+ return get_image_gallery(), image_metadata.values.tolist()
176
+
177
+ # === QUOTES Demo (Optional) ===
178
+ def add_quote(q):
179
+ if q.strip():
180
+ quotes.append({
181
+ "text": q,
182
+ "likes": 0,
183
+ "created": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
184
+ })
185
+ save_json(QUOTE_CACHE_FILE, quotes)
186
+ return [[idx, itm["text"], itm["likes"], itm["created"]] for idx, itm in enumerate(quotes)]
187
+
188
+ def like_quote(idx):
189
+ if 0 <= idx < len(quotes):
190
+ quotes[idx]["likes"] += 1
191
+ save_json(QUOTE_CACHE_FILE, quotes)
192
+ return [[i, itm["text"], itm["likes"], itm["created"]] for i, itm in enumerate(quotes)]
193
+
194
+ # === CLAUDE Chat ===
195
+ def chat_claude(user_message):
196
+ if not claude_client:
197
+ return "No Anthropic API key configured."
198
+ if not user_message.strip():
199
+ return "Empty message."
200
+ resp = claude_client.messages.create(
201
+ model="claude-3-sonnet-20240229",
202
+ max_tokens=1000,
203
+ messages=[{"role": "user", "content": user_message}],
204
+ )
205
+ text = resp.content[0].text
206
+ log_input_output(user_input=user_message, model_output=text, link="")
207
+ return text
208
+
209
+ # === Refresh gallery + DF
210
+ def refresh_gallery_and_df():
211
+ return gr.update(value=get_image_gallery()), gr.update(value=image_metadata.values.tolist())
212
+
213
+ # ============================================================
214
+ # === BUILD GRADIO UI
215
+ # ============================================================
216
+ DESCRIPTION = """# 🎨 ArtForge & Claude Chat
217
+ Generate AI art, chat with Claude, log everything, and vote on images.
218
+ """
219
 
220
  examples = [
221
+ "Futuristic cityscape in neon lighting",
222
+ "Cute cat wearing a wizard hat",
223
+ "Surreal landscape with floating islands",
 
 
 
 
 
 
 
224
  ]
225
 
226
+ with gr.Blocks(css=".gradio-container {max-width: 1024px !important}") as demo:
 
 
 
 
 
 
 
 
227
  gr.Markdown(DESCRIPTION)
228
 
229
  with gr.Tab("Generate Images"):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
230
  with gr.Row():
231
+ prompt = gr.Text(label="Prompt", max_lines=1)
232
+ run_button = gr.Button("Run")
233
+ result = gr.Gallery(label="Result", columns=1, preview=True)
234
+ use_negative_prompt = gr.Checkbox(label="Use negative prompt", value=True)
235
+ negative_prompt = gr.Text(
236
+ label="Negative prompt",
237
+ lines=3,
238
+ value="(deformed, distorted:1.3), poorly drawn, bad anatomy",
239
+ )
240
+ seed = gr.Slider(label="Seed", minimum=0, maximum=MAX_SEED, step=1, value=0)
241
+ randomize_seed = gr.Checkbox(label="Randomize seed", value=True)
242
+ width = gr.Slider(label="Width", minimum=512, maximum=2048, step=64, value=1024)
243
+ height = gr.Slider(label="Height", minimum=512, maximum=2048, step=64, value=1024)
244
+ guidance_scale = gr.Slider(label="Guidance Scale", minimum=1, maximum=20, step=0.5, value=7)
245
+ run_button.click(
246
+ fn=generate_image,
247
+ inputs=[prompt, negative_prompt, use_negative_prompt, seed, width, height, guidance_scale, randomize_seed],
248
+ outputs=[result, seed, gr.HTML(visible=False), gr.Gallery(), gr.Dataframe()],
249
+ api_name="run"
250
+ )
251
+ gr.Examples(examples=examples, inputs=prompt)
252
+
253
+ with gr.Tab("Chat with Claude"):
254
+ claude_input = gr.Textbox(label="Your Message")
255
+ claude_output = gr.Textbox(label="Claude's Reply", lines=4)
256
+ send_claude = gr.Button("Send to Claude")
257
+ send_claude.click(chat_claude, inputs=claude_input, outputs=claude_output)
258
+
259
+ with gr.Tab("Logs & Management"):
260
+ with gr.Accordion("All Logs", open=False):
261
+ logs_data = gr.Dataframe(
262
+ value=pd.DataFrame(chat_logs),
263
+ label="Input/Output Logs",
264
+ interactive=False,
265
+ wrap=True
266
+ )
267
 
268
+ with gr.Tab("Gallery & Voting"):
269
+ image_gallery = gr.Gallery(label="Generated Images", columns=4)
270
  metadata_df = gr.Dataframe(
271
  label="Image Metadata",
272
  headers=["Filename", "Prompt", "Likes", "Dislikes", "Hearts", "Created"],
273
  interactive=False
274
  )
275
+ selected_image = gr.State()
276
+ with gr.Row():
277
+ like_button = gr.Button("👍 Like")
278
+ dislike_button = gr.Button("👎 Dislike")
279
+ heart_button = gr.Button("❤️ Heart")
280
+ delete_image_button = gr.Button("🗑️ Delete Image")
281
+ delete_all_button = gr.Button("🗑️ Delete All")
282
+ image_gallery.select(fn=lambda evt: evt, inputs=[], outputs=[selected_image])
283
+ like_button.click(fn=lambda x: vote_image(x, 'likes'), inputs=selected_image, outputs=[image_gallery, metadata_df])
284
+ dislike_button.click(fn=lambda x: vote_image(x, 'dislikes'), inputs=selected_image, outputs=[image_gallery, metadata_df])
285
+ heart_button.click(fn=lambda x: vote_image(x, 'hearts'), inputs=selected_image, outputs=[image_gallery, metadata_df])
286
+ delete_image_button.click(fn=delete_image, inputs=selected_image, outputs=[image_gallery, metadata_df])
287
+ delete_all_button.click(fn=delete_all_images, outputs=[image_gallery, metadata_df])
288
+
289
+ with gr.Tab("Quotes (Optional)"):
290
+ quote_input = gr.Textbox(label="Enter a quote")
291
+ add_q_button = gr.Button("Add Quote")
292
+ quote_df = gr.Dataframe(value=[(idx, q['text'], q['likes'], q['created']) for idx,q in enumerate(quotes)],
293
+ headers=["Index","Text","Likes","Created"], interactive=False)
294
+ selected_quote = gr.Number(label="Index to Like")
295
+ like_q_button = gr.Button("Like Quote")
296
+ add_q_button.click(fn=add_quote, inputs=quote_input, outputs=quote_df)
297
+ like_q_button.click(fn=like_quote, inputs=selected_quote, outputs=quote_df)
298
+
299
+ demo.load(fn=refresh_gallery_and_df, outputs=[image_gallery, metadata_df])
 
300
 
301
+ if __name__ == "__main__":
302
+ demo.queue(max_size=20).launch()
 
 
 
303
 
 
 
 
 
 
304
 
 
 
 
 
 
305
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
306
 
 
307