throaway2854 commited on
Commit
93a76ad
1 Parent(s): 9eec9d3

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +67 -303
app.py CHANGED
@@ -5,7 +5,6 @@ import random
5
  from PIL import Image
6
  import base64
7
  import io
8
- from functools import partial
9
 
10
  # Define categories at the top so they are accessible throughout the code
11
  categories = [
@@ -21,7 +20,7 @@ categories = [
21
  ]
22
 
23
  class DataManager:
24
- def __init__(self, base_dir='data'):
25
  self.base_dir = base_dir
26
  # Ensure the base directory exists
27
  if not os.path.exists(self.base_dir):
@@ -58,11 +57,11 @@ class DataManager:
58
 
59
  def save_characters(self):
60
  with open(self.characters_file, 'w') as f:
61
- json.dump(self.characters, f, indent=4)
62
 
63
  def save_persistent_tags(self):
64
  with open(self.persistent_tags_file, 'w') as f:
65
- json.dump(self.persistent_tags, f, indent=4)
66
 
67
  def load_category_tags(self):
68
  if os.path.exists(self.category_tags_file):
@@ -73,7 +72,7 @@ class DataManager:
73
 
74
  def save_category_tags(self):
75
  with open(self.category_tags_file, 'w') as f:
76
- json.dump(self.category_tags, f, indent=4)
77
 
78
  def get_category_tags(self, category_var_name):
79
  # Return the tags list for the given category variable name
@@ -84,7 +83,7 @@ class DataManager:
84
  self.save_category_tags()
85
 
86
  def get_characters(self):
87
- # Ensure images paths are up-to-date
88
  for char in self.characters:
89
  image_path = char.get('image_path')
90
  if image_path and os.path.exists(image_path):
@@ -102,21 +101,16 @@ class DataManager:
102
 
103
  def add_character(self, character):
104
  # Save image to disk and store the filename
105
- image_data = character['image'] # This is the file path
106
  safe_name = "".join(c for c in character['name'] if c.isalnum() or c in (' ', '_', '-')).rstrip()
107
  image_filename = f"{safe_name}.png"
108
  image_path = os.path.join(self.images_folder, image_filename)
109
 
110
- # Save the image if provided
111
- if image_data and os.path.exists(image_data):
112
- try:
113
- # Open and save the uploaded image to the images folder
114
- image = Image.open(image_data)
115
- image.save(image_path)
116
- character['image_path'] = image_path
117
- except Exception as e:
118
- print(f"Error saving image: {e}")
119
- character['image_path'] = None
120
  else:
121
  character['image_path'] = None
122
 
@@ -130,56 +124,34 @@ class DataManager:
130
  self.characters.append(character)
131
  self.save_characters()
132
 
133
- def update_character(self, original_name, updated_character):
134
- # Find the character by original_name
135
- for idx, char in enumerate(self.characters):
136
- if char['name'] == original_name:
137
- # Handle image update
138
- if updated_character['image'] and os.path.exists(updated_character['image']):
139
- image_data = updated_character['image'] # File path
140
- safe_name = "".join(c for c in updated_character['name'] if c.isalnum() or c in (' ', '_', '-')).rstrip()
141
- image_filename = f"{safe_name}.png"
142
- new_image_path = os.path.join(self.images_folder, image_filename)
143
-
144
- try:
145
- image = Image.open(image_data)
146
- image.save(new_image_path)
147
- updated_character['image_path'] = new_image_path
148
- # Remove old image if name has changed
149
- if original_name != updated_character['name']:
150
- old_image_path = char.get('image_path')
151
- if old_image_path and os.path.exists(old_image_path):
152
- os.remove(old_image_path)
153
- except Exception as e:
154
- print(f"Error updating image: {e}")
155
- updated_character['image_path'] = char.get('image_path')
156
- else:
157
- # If no new image provided, retain the old image_path
158
- updated_character['image_path'] = char.get('image_path')
159
-
160
- updated_character.pop('image', None)
161
-
162
- # Process traits
163
- if isinstance(updated_character['traits'], str):
164
- updated_character['traits'] = updated_character['traits'].split(',')
165
- updated_character['traits'] = [t.strip() for t in updated_character['traits']]
166
-
167
- self.characters[idx] = updated_character
168
- self.save_characters()
169
- return True
170
- return False
171
-
172
- def delete_character(self, name):
173
- # Find and remove the character
174
- for idx, char in enumerate(self.characters):
175
- if char['name'] == name:
176
- image_path = char.get('image_path')
177
- if image_path and os.path.exists(image_path):
178
- os.remove(image_path)
179
- del self.characters[idx]
180
- self.save_characters()
181
- return True
182
- return False
183
 
184
  def prompt_generator_app(data_manager):
185
  with gr.Tab("Prompt Generator"):
@@ -188,7 +160,7 @@ def prompt_generator_app(data_manager):
188
  # Add a refresh tags button
189
  refresh_tags_button = gr.Button("Refresh Tags")
190
 
191
- inputs_sliders = {}
192
  tag_displays = {}
193
  for category_name, var_name in categories:
194
  tags_list = data_manager.get_category_tags(var_name)
@@ -201,14 +173,8 @@ def prompt_generator_app(data_manager):
201
  with gr.Group():
202
  gr.Markdown(f"### {category_name}")
203
  tag_display = gr.Markdown(f"**Tags:** {tags_string}")
204
- tag_num = gr.Slider(
205
- minimum=0,
206
- maximum=max_tags,
207
- step=1,
208
- value=default_value,
209
- label=f"Number of {category_name} Tags to Select"
210
- )
211
- inputs_sliders[var_name + '_num'] = tag_num
212
  tag_displays[var_name] = (tag_display, tag_num)
213
 
214
  # For Character Selection
@@ -225,31 +191,18 @@ def prompt_generator_app(data_manager):
225
  return character_options
226
 
227
  character_options = get_character_options()
228
- character_select = gr.CheckboxGroup(
229
- choices=character_options,
230
- label="Select Characters",
231
- interactive=True
232
- )
233
 
234
  refresh_characters_button = gr.Button("Refresh Character List")
235
 
236
- def refresh_character_selection():
237
  new_options = get_character_options()
238
- return [gr.CheckboxGroup.update(choices=new_options)]
239
 
240
- refresh_characters_button.click(
241
- refresh_character_selection,
242
- outputs=[character_select]
243
- )
244
 
245
  random_characters = gr.Checkbox(label="Select Random Characters")
246
- num_characters = gr.Slider(
247
- minimum=1,
248
- maximum=10,
249
- step=1,
250
- value=1,
251
- label="Number of Characters (if random)"
252
- )
253
 
254
  generate_button = gr.Button("Generate Prompt")
255
  prompt_output = gr.Textbox(label="Generated Prompt", lines=5)
@@ -343,18 +296,15 @@ def prompt_generator_app(data_manager):
343
  # Prepare the list of inputs for the generate_prompt function
344
  inputs_list = []
345
  for category_name, var_name in categories:
346
- inputs_list.append(inputs_sliders[f"{var_name}_num"])
347
  # Add character_select directly to inputs
348
  inputs_list.extend([character_select, random_characters, num_characters])
349
 
350
- generate_button.click(
351
- generate_prompt,
352
- inputs=inputs_list,
353
- outputs=prompt_output
354
- )
355
 
356
  # Function to refresh tags display and sliders
357
  def refresh_tags():
 
358
  for category_name, var_name in categories:
359
  # Reload tags from data_manager
360
  tags_list = data_manager.get_category_tags(var_name)
@@ -366,192 +316,15 @@ def prompt_generator_app(data_manager):
366
  slider_value = min(1, max_tags)
367
  # Update the tag display and slider
368
  tag_display, tag_num = tag_displays[var_name]
369
- tag_display.update(value=f"**Tags:** {tags_string}")
370
- tag_num.update(maximum=max_tags, value=slider_value)
371
- return None # No outputs to return
372
 
373
- # Connect the refresh_tags function to the refresh_tags_button
374
- refresh_tags_button.click(
375
- refresh_tags,
376
- inputs=None,
377
- outputs=None
378
- )
379
 
380
- def character_creation_app(data_manager):
381
- with gr.Tab("Character Creation"):
382
- gr.Markdown("## Create and Manage Characters")
383
-
384
- # **Section 1: Create a New Character**
385
- with gr.Row():
386
- name_input = gr.Textbox(
387
- label="Character Name",
388
- placeholder="Enter unique character name"
389
- )
390
- traits_input = gr.Textbox(
391
- label="Traits/Appearance Tags (comma separated)",
392
- placeholder="e.g., blue hair, green eyes, tall"
393
- )
394
- image_input = gr.Image(label="Upload Character Image", type="filepath")
395
- gender_input = gr.Radio(choices=["Boy", "Girl"], label="Gender")
396
- save_button = gr.Button("Save Character")
397
- save_output = gr.Textbox(label="Status", interactive=False)
398
-
399
- # **Section 2: Existing Characters**
400
- gr.Markdown("---")
401
- gr.Markdown("## Existing Characters")
402
-
403
- # Dropdown to select a character for editing or deleting
404
- def get_character_names():
405
- characters = data_manager.get_characters()
406
- return [char['name'] for char in characters]
407
-
408
- selected_character = gr.Dropdown(
409
- choices=get_character_names(),
410
- label="Select a Character to Edit/Delete",
411
- interactive=True
412
- )
413
-
414
- # Buttons for Edit and Delete
415
- edit_button = gr.Button("Edit Selected Character")
416
- delete_button = gr.Button("Delete Selected Character")
417
- action_output = gr.Textbox(label="Action Status", interactive=False)
418
-
419
- # **Section 3: Edit Character**
420
- edit_section = gr.Row(visible=False)
421
- with edit_section:
422
- with gr.Row():
423
- edit_name = gr.Textbox(
424
- label="New Character Name",
425
- placeholder="Enter new character name"
426
- )
427
- edit_traits = gr.Textbox(
428
- label="New Traits/Appearance Tags (comma separated)",
429
- placeholder="e.g., red hair, blue eyes"
430
- )
431
- edit_image = gr.Image(label="Upload New Character Image", type="filepath")
432
- edit_gender = gr.Radio(
433
- choices=["Boy", "Girl"],
434
- label="Gender"
435
- )
436
- update_button = gr.Button("Update Character")
437
- update_output = gr.Textbox(label="Update Status", interactive=False)
438
-
439
- # **Section 4: Delete Confirmation**
440
- delete_confirmation = gr.Textbox(
441
- label="Are you sure you want to delete this character? Type 'YES' to confirm.",
442
- interactive=True,
443
- visible=False
444
- )
445
- confirm_delete_button = gr.Button("Confirm Delete", visible=False)
446
- cancel_delete_button = gr.Button("Cancel Delete", visible=False)
447
-
448
- # **Function to Save New Character**
449
- def save_character(name, traits, image_path, gender):
450
- if not name.strip() or not traits.strip() or not gender:
451
- return "Please enter all fields."
452
- # Check for duplicate names
453
- existing_names = [char['name'] for char in data_manager.get_characters()]
454
- if name in existing_names:
455
- return f"Character with name '{name}' already exists. Please choose a different name."
456
-
457
- character = {'name': name, 'traits': traits, 'gender': gender, 'image': image_path}
458
- data_manager.add_character(character)
459
- return f"Character '{name}' saved successfully."
460
-
461
- save_button.click(
462
- save_character,
463
- inputs=[name_input, traits_input, image_input, gender_input],
464
- outputs=save_output
465
- )
466
-
467
- # **Function to Show Edit Section**
468
- def show_edit(selected_name):
469
- if not selected_name:
470
- return "Please select a character to edit.", gr.update(visible=False)
471
- # Fetch character details
472
- character = next((char for char in data_manager.get_characters() if char['name'] == selected_name), None)
473
- if character:
474
- # Pre-fill the edit fields
475
- edit_name.value = character['name']
476
- edit_traits.value = ', '.join(character['traits'])
477
- edit_gender.value = character['gender']
478
- edit_image.value = None # Reset image
479
- return "", gr.update(visible=True)
480
- else:
481
- return f"Character '{selected_name}' not found.", gr.update(visible=False)
482
-
483
- edit_button.click(
484
- show_edit,
485
- inputs=selected_character,
486
- outputs=[action_output, edit_section]
487
- )
488
-
489
- # **Function to Update Character**
490
- def update_character(original_name, new_name, new_traits, new_image_path, new_gender):
491
- if not new_name.strip() or not new_traits.strip() or not new_gender:
492
- return "Please enter all fields.", gr.update(visible=False)
493
- # If the name has changed, check for duplicates
494
- if new_name != original_name:
495
- existing_names = [char['name'] for char in data_manager.get_characters()]
496
- if new_name in existing_names:
497
- return f"Character with name '{new_name}' already exists. Please choose a different name.", gr.update(visible=True)
498
- updated_char = {
499
- 'name': new_name,
500
- 'traits': new_traits,
501
- 'gender': new_gender,
502
- 'image': new_image_path if new_image_path else \
503
- next((char for char in data_manager.get_characters() if char['name'] == original_name), {}).get('image')
504
- }
505
- success = data_manager.update_character(original_name, updated_char)
506
- if success:
507
- # Update the dropdown choices
508
- return f"Character '{new_name}' updated successfully.", gr.update(visible=False)
509
- else:
510
- return "Failed to update character.", gr.update(visible=True)
511
-
512
- update_button.click(
513
- update_character,
514
- inputs=[selected_character, edit_name, edit_traits, edit_image, edit_gender],
515
- outputs=[update_output, edit_section]
516
- )
517
-
518
- # **Function to Show Delete Confirmation**
519
- def show_delete_confirmation(selected_name):
520
- if not selected_name:
521
- return "Please select a character to delete.", gr.update(visible=False), gr.update(visible=False)
522
- return f"Are you sure you want to delete '{selected_name}'? Type 'YES' to confirm.", gr.update(visible=True), gr.update(visible=True)
523
-
524
- delete_button.click(
525
- show_delete_confirmation,
526
- inputs=selected_character,
527
- outputs=[action_output, delete_confirmation, confirm_delete_button]
528
- )
529
-
530
- # **Function to Perform Deletion**
531
- def perform_deletion(selected_name, confirmation):
532
- if confirmation.strip().upper() != "YES":
533
- return "Deletion cancelled.", gr.update(visible=False), gr.update(visible=False)
534
- success = data_manager.delete_character(selected_name)
535
- if success:
536
- return f"Character '{selected_name}' deleted successfully.", gr.update(visible=False), gr.update(visible=False)
537
- else:
538
- return f"Failed to delete character '{selected_name}'.", gr.update(visible=False), gr.update(visible=False)
539
-
540
- confirm_delete_button.click(
541
- perform_deletion,
542
- inputs=[selected_character, delete_confirmation],
543
- outputs=[action_output, delete_confirmation, confirm_delete_button]
544
- )
545
-
546
- # **Function to Cancel Deletion**
547
- def cancel_deletion():
548
- return "Deletion cancelled.", gr.update(visible=False), gr.update(visible=False)
549
-
550
- cancel_delete_button.click(
551
- cancel_deletion,
552
- inputs=None,
553
- outputs=[action_output, delete_confirmation, confirm_delete_button]
554
- )
555
 
556
  def tags_app(data_manager):
557
  with gr.Tab("Tags"):
@@ -561,13 +334,11 @@ def tags_app(data_manager):
561
  gr.Markdown(f"### {category_name} Tags")
562
  tags_list = data_manager.get_category_tags(var_name)
563
  tags_string = ', '.join(tags_list)
564
- tag_input = gr.Textbox(
565
- label=f"{category_name} Tags (comma separated)",
566
- value=tags_string
567
- )
568
  save_button = gr.Button(f"Save {category_name} Tags")
569
  status_output = gr.Textbox(label="", interactive=False)
570
 
 
571
  def make_save_category_tags_fn(var_name, category_name):
572
  def fn(tags_string):
573
  tags_list = [t.strip() for t in tags_string.split(',') if t.strip()]
@@ -581,31 +352,24 @@ def tags_app(data_manager):
581
  # Persistent Tags
582
  gr.Markdown(f"### Persistent Tags")
583
  persistent_tags_string = ', '.join(data_manager.get_persistent_tags())
584
- persistent_tags_input = gr.Textbox(
585
- label="Persistent Tags (comma separated)",
586
- value=persistent_tags_string
587
- )
588
  save_persistent_tags_button = gr.Button("Save Persistent Tags")
589
  persistent_status_output = gr.Textbox(label="", interactive=False)
590
 
591
- def save_persistent_tags_fn(tags_string):
592
  tags_list = [t.strip() for t in tags_string.split(',') if t.strip()]
593
  data_manager.set_persistent_tags(tags_list)
594
  return "Persistent tags saved successfully."
595
 
596
- save_persistent_tags_button.click(
597
- save_persistent_tags_fn,
598
- inputs=persistent_tags_input,
599
- outputs=persistent_status_output
600
- )
601
 
602
  def main():
603
- data_manager = DataManager(base_dir='data')
604
  with gr.Blocks() as demo:
605
- with gr.Tabs():
606
- prompt_generator_app(data_manager)
607
- character_creation_app(data_manager)
608
- tags_app(data_manager)
609
  demo.launch()
610
 
611
  if __name__ == "__main__":
 
5
  from PIL import Image
6
  import base64
7
  import io
 
8
 
9
  # Define categories at the top so they are accessible throughout the code
10
  categories = [
 
20
  ]
21
 
22
  class DataManager:
23
+ def __init__(self, base_dir='/data'):
24
  self.base_dir = base_dir
25
  # Ensure the base directory exists
26
  if not os.path.exists(self.base_dir):
 
57
 
58
  def save_characters(self):
59
  with open(self.characters_file, 'w') as f:
60
+ json.dump(self.characters, f)
61
 
62
  def save_persistent_tags(self):
63
  with open(self.persistent_tags_file, 'w') as f:
64
+ json.dump(self.persistent_tags, f)
65
 
66
  def load_category_tags(self):
67
  if os.path.exists(self.category_tags_file):
 
72
 
73
  def save_category_tags(self):
74
  with open(self.category_tags_file, 'w') as f:
75
+ json.dump(self.category_tags, f)
76
 
77
  def get_category_tags(self, category_var_name):
78
  # Return the tags list for the given category variable name
 
83
  self.save_category_tags()
84
 
85
  def get_characters(self):
86
+ # Load character images
87
  for char in self.characters:
88
  image_path = char.get('image_path')
89
  if image_path and os.path.exists(image_path):
 
101
 
102
  def add_character(self, character):
103
  # Save image to disk and store the filename
104
+ image_data = character['image'] # This is base64 encoded string
105
  safe_name = "".join(c for c in character['name'] if c.isalnum() or c in (' ', '_', '-')).rstrip()
106
  image_filename = f"{safe_name}.png"
107
  image_path = os.path.join(self.images_folder, image_filename)
108
 
109
+ # Decode the base64 image data and save it
110
+ if image_data:
111
+ image = Image.open(io.BytesIO(base64.b64decode(image_data.split(",")[1])))
112
+ image.save(image_path)
113
+ character['image_path'] = image_path
 
 
 
 
 
114
  else:
115
  character['image_path'] = None
116
 
 
124
  self.characters.append(character)
125
  self.save_characters()
126
 
127
+ def character_creation_app(data_manager):
128
+ with gr.Tab("Character Creation"):
129
+ with gr.Row():
130
+ name_input = gr.Textbox(label="Character Name")
131
+ traits_input = gr.Textbox(label="Traits/Appearance Tags (comma separated)")
132
+ image_input = gr.Image(label="Upload Character Image", type="filepath")
133
+ # New gender selection input
134
+ gender_input = gr.Radio(choices=["Boy", "Girl"], label="Gender")
135
+ save_button = gr.Button("Save Character")
136
+ output = gr.Textbox(label="Status", interactive=False)
137
+
138
+ def save_character(name, traits, image_path, gender):
139
+ if not name or not traits or not gender:
140
+ return "Please enter all fields."
141
+ character = {'name': name, 'traits': traits, 'gender': gender, 'image': None}
142
+
143
+ # Read and encode image if provided
144
+ if image_path:
145
+ with open(image_path, "rb") as img_file:
146
+ image_data = base64.b64encode(img_file.read()).decode('utf-8')
147
+ character['image'] = f"data:image/png;base64,{image_data}"
148
+ else:
149
+ character['image'] = None
150
+
151
+ data_manager.add_character(character)
152
+ return f"Character '{name}' saved successfully."
153
+
154
+ save_button.click(save_character, inputs=[name_input, traits_input, image_input, gender_input], outputs=output)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
155
 
156
  def prompt_generator_app(data_manager):
157
  with gr.Tab("Prompt Generator"):
 
160
  # Add a refresh tags button
161
  refresh_tags_button = gr.Button("Refresh Tags")
162
 
163
+ inputs = {}
164
  tag_displays = {}
165
  for category_name, var_name in categories:
166
  tags_list = data_manager.get_category_tags(var_name)
 
173
  with gr.Group():
174
  gr.Markdown(f"### {category_name}")
175
  tag_display = gr.Markdown(f"**Tags:** {tags_string}")
176
+ tag_num = gr.Slider(minimum=0, maximum=max_tags, step=1, value=default_value, label=f"Number of {category_name} Tags to Select")
177
+ inputs[f"{var_name}_num"] = tag_num
 
 
 
 
 
 
178
  tag_displays[var_name] = (tag_display, tag_num)
179
 
180
  # For Character Selection
 
191
  return character_options
192
 
193
  character_options = get_character_options()
194
+ character_select = gr.CheckboxGroup(choices=character_options, label="Select Characters", interactive=True)
 
 
 
 
195
 
196
  refresh_characters_button = gr.Button("Refresh Character List")
197
 
198
+ def refresh_characters():
199
  new_options = get_character_options()
200
+ return gr.update(choices=new_options)
201
 
202
+ refresh_characters_button.click(refresh_characters, outputs=character_select)
 
 
 
203
 
204
  random_characters = gr.Checkbox(label="Select Random Characters")
205
+ num_characters = gr.Slider(minimum=1, maximum=10, step=1, value=1, label="Number of Characters (if random)")
 
 
 
 
 
 
206
 
207
  generate_button = gr.Button("Generate Prompt")
208
  prompt_output = gr.Textbox(label="Generated Prompt", lines=5)
 
296
  # Prepare the list of inputs for the generate_prompt function
297
  inputs_list = []
298
  for category_name, var_name in categories:
299
+ inputs_list.append(inputs[f"{var_name}_num"])
300
  # Add character_select directly to inputs
301
  inputs_list.extend([character_select, random_characters, num_characters])
302
 
303
+ generate_button.click(generate_prompt, inputs=inputs_list, outputs=prompt_output)
 
 
 
 
304
 
305
  # Function to refresh tags display and sliders
306
  def refresh_tags():
307
+ updates = []
308
  for category_name, var_name in categories:
309
  # Reload tags from data_manager
310
  tags_list = data_manager.get_category_tags(var_name)
 
316
  slider_value = min(1, max_tags)
317
  # Update the tag display and slider
318
  tag_display, tag_num = tag_displays[var_name]
319
+ updates.append(gr.update(value=f"**Tags:** {tags_string}"))
320
+ updates.append(gr.update(maximum=max_tags, value=slider_value))
321
+ return updates
322
 
323
+ # Prepare the outputs list
324
+ outputs = [component for pair in tag_displays.values() for component in pair]
 
 
 
 
325
 
326
+ # Connect the refresh_tags function to the refresh_tags_button
327
+ refresh_tags_button.click(refresh_tags, outputs=outputs)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
328
 
329
  def tags_app(data_manager):
330
  with gr.Tab("Tags"):
 
334
  gr.Markdown(f"### {category_name} Tags")
335
  tags_list = data_manager.get_category_tags(var_name)
336
  tags_string = ', '.join(tags_list)
337
+ tag_input = gr.Textbox(label=f"{category_name} Tags (comma separated)", value=tags_string)
 
 
 
338
  save_button = gr.Button(f"Save {category_name} Tags")
339
  status_output = gr.Textbox(label="", interactive=False)
340
 
341
+ # Function to save tags
342
  def make_save_category_tags_fn(var_name, category_name):
343
  def fn(tags_string):
344
  tags_list = [t.strip() for t in tags_string.split(',') if t.strip()]
 
352
  # Persistent Tags
353
  gr.Markdown(f"### Persistent Tags")
354
  persistent_tags_string = ', '.join(data_manager.get_persistent_tags())
355
+ persistent_tags_input = gr.Textbox(label="Persistent Tags (comma separated)", value=persistent_tags_string)
 
 
 
356
  save_persistent_tags_button = gr.Button("Save Persistent Tags")
357
  persistent_status_output = gr.Textbox(label="", interactive=False)
358
 
359
+ def save_persistent_tags(tags_string):
360
  tags_list = [t.strip() for t in tags_string.split(',') if t.strip()]
361
  data_manager.set_persistent_tags(tags_list)
362
  return "Persistent tags saved successfully."
363
 
364
+ save_persistent_tags_button.click(save_persistent_tags, inputs=persistent_tags_input, outputs=persistent_status_output)
 
 
 
 
365
 
366
  def main():
367
+ data_manager = DataManager(base_dir='/data')
368
  with gr.Blocks() as demo:
369
+ prompt_generator_app(data_manager)
370
+ character_creation_app(data_manager)
371
+ tags_app(data_manager)
372
+
373
  demo.launch()
374
 
375
  if __name__ == "__main__":