JS6969 commited on
Commit
89ff26c
·
verified ·
1 Parent(s): c5bf419

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +66 -73
app.py CHANGED
@@ -119,7 +119,6 @@ EXTRA_CHOICES = [
119
  "Include information on composition (rule of thirds, symmetry, leading lines, etc).",
120
  "Specify the depth of field and whether the background is in focus or blurred.",
121
  "If applicable, mention the likely use of artificial or natural lighting sources.",
122
- "If it is a work of art, do not include the artist's name or the title of the work.",
123
  "Identify the image orientation (portrait, landscape, or square) if obvious.",
124
  ]
125
  NAME_OPTION = "If there is a person/character in the image you must refer to them as {name}."
@@ -281,11 +280,36 @@ def load_journal() -> dict:
281
  # ────────────────────────────────────────────────────────
282
  # Shape Aliases (compile/cache/apply)
283
  # ────────────────────────────────────────────────────────
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
284
  def get_shape_alias_rows_ui_defaults():
285
  s = load_settings()
286
  rows = [[it.get("shape",""), it.get("name","")] for it in s.get("shape_aliases", [])]
287
  enabled = bool(s.get("shape_aliases_enabled", True))
288
- # Always show at least one empty row
289
  if not rows:
290
  rows = [["", ""]]
291
  return rows, enabled
@@ -307,14 +331,12 @@ def save_shape_alias_rows(enabled, df_rows):
307
  save_settings(cfg)
308
  _refresh_shape_aliases_cache()
309
 
310
- # Normalize table after save (keep one empty row at the end)
311
  normalized = [[it["shape"], it["name"]] for it in cleaned] + [["", ""]]
312
  return (
313
  "✅ Saved shape alias options.",
314
  gr.update(value=normalized, row_count=(max(1, len(normalized)), "dynamic"))
315
  )
316
 
317
-
318
  # ────────────────────────────────────────────────────────
319
  # Logo loader
320
  # ────────────────────────────────────────────────────────
@@ -614,84 +636,55 @@ with gr.Blocks(css=BASE_CSS, title="CaptionForge") as demo:
614
  chunk_size = gr.Slider(1, 50, settings.get("chunk_size", 10), step=1, label="Chunk size")
615
  max_side = gr.Slider(256, MAX_SIDE_CAP, settings.get("max_side", min(896, MAX_SIDE_CAP)), step=32, label="Max side (resize)")
616
 
617
- # Shape Aliases UI (Accordion)
618
- with gr.Tab("Shape Aliases"):
619
  gr.Markdown(
620
  "### 🔷 Shape Aliases\n"
621
- "Tell CaptionForge to replace literal **shape tokens** it sees in captions with your preferred **name**.\n\n"
622
  "**How to use:**\n"
623
- "1) In the left column, type the exact shape token (e.g., `diamond`, `heart`, `oval`).\n"
624
- "2) In the right column, type the replacement name you want inserted (e.g., `starkey-emblem`).\n"
625
  "3) Click **Save**.\n\n"
626
- "Tips: rows with either side blank are ignored; you can add as many rows as you like."
627
- )
628
-
629
- init_rows, init_enabled = get_shape_alias_rows_ui_defaults()
630
 
631
- enable_aliases = gr.Checkbox(
632
- label="Enable shape alias replacements",
633
- value=init_enabled,
634
- info="Turn all replacements on/off without deleting your list."
635
- )
636
 
637
- alias_table = gr.Dataframe(
638
- headers=["shape (literal token)", "name to insert"],
639
- value=init_rows, # <-- set value at creation time
640
- col_count=(2, "fixed"), # <-- lock to 2 columns
641
- row_count=(max(1, len(init_rows)), "dynamic"), # user can add rows
642
- datatype=["str", "str"],
643
- type="array", # <-- treat rows as lists (most reliable for editing)
644
- interactive=True
645
- )
646
 
647
- with gr.Row():
648
- add_row_btn = gr.Button("+ Add row", variant="secondary")
649
- clear_btn = gr.Button("Clear", variant="secondary")
650
- save_btn = gr.Button("💾 Save", variant="primary")
651
-
652
- save_status = gr.Markdown("")
653
-
654
- # Button logic
655
- def _add_row(cur):
656
- cur = (cur or []) + [["", ""]]
657
- # keep dynamic rows in sync
658
- return gr.update(value=cur, row_count=(max(1, len(cur)), "dynamic"))
659
-
660
- def _clear_rows():
661
- return gr.update(value=[["", ""]], row_count=(1, "dynamic"))
662
-
663
- add_row_btn.click(_add_row, inputs=[alias_table], outputs=[alias_table])
664
- clear_btn.click(_clear_rows, inputs=None, outputs=[alias_table])
665
- save_btn.click(save_shape_alias_rows, inputs=[enable_aliases, alias_table], outputs=[save_status, alias_table])
666
-
667
-
668
- save_aliases_btn = gr.Button("Save aliases")
669
- save_status = gr.Markdown()
670
-
671
- # init values
672
- init_rows = [[it.get("shape",""), it.get("name","")] for it in settings.get("shape_aliases", [])]
673
- if not init_rows:
674
- init_rows = [["diamond", "starkey-emblem"]]
675
- enable_aliases.value = bool(settings.get("shape_aliases_enabled", True))
676
- alias_table.value = init_rows
677
-
678
- def set_shape_alias_rows(enabled, rows):
679
- cfg = load_settings()
680
- cfg["shape_aliases_enabled"] = bool(enabled)
681
- cfg["shape_aliases"] = [
682
- {"shape": (r[0] or "").strip(), "name": (r[1] or "").strip()}
683
- for r in (rows or []) if r and (r[0] or "").strip() and (r[1] or "").strip()
684
- ]
685
- save_settings(cfg)
686
- _refresh_shape_aliases_cache()
687
- return "Saved shape alias options."
688
-
689
- save_aliases_btn.click(
690
- set_shape_alias_rows,
691
- inputs=[enable_aliases, alias_table],
692
- outputs=[save_status]
693
  )
694
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
695
  # Auto-refresh instruction & persist key controls
696
  def _refresh_instruction(styles, extra, name_value, trigv, begv, endv):
697
  instr = final_instruction(styles or ["Character training (short)"], extra or [], name_value)
 
119
  "Include information on composition (rule of thirds, symmetry, leading lines, etc).",
120
  "Specify the depth of field and whether the background is in focus or blurred.",
121
  "If applicable, mention the likely use of artificial or natural lighting sources.",
 
122
  "Identify the image orientation (portrait, landscape, or square) if obvious.",
123
  ]
124
  NAME_OPTION = "If there is a person/character in the image you must refer to them as {name}."
 
280
  # ────────────────────────────────────────────────────────
281
  # Shape Aliases (compile/cache/apply)
282
  # ────────────────────────────────────────────────────────
283
+ def _compile_shape_aliases_from_file():
284
+ s = load_settings()
285
+ if not s.get("shape_aliases_enabled", True):
286
+ return []
287
+ compiled = []
288
+ for item in s.get("shape_aliases", []):
289
+ shape = (item.get("shape") or "").strip()
290
+ name = (item.get("name") or "").strip()
291
+ if not shape or not name:
292
+ continue
293
+ pat = rf"\b{re.escape(shape)}(?:-?shaped)?\b"
294
+ compiled.append((re.compile(pat, flags=re.I), name))
295
+ return compiled
296
+
297
+ _SHAPE_ALIASES = _compile_shape_aliases_from_file()
298
+
299
+ def _refresh_shape_aliases_cache():
300
+ global _SHAPE_ALIASES
301
+ _SHAPE_ALIASES = _compile_shape_aliases_from_file()
302
+
303
+ def apply_shape_aliases(caption: str) -> str:
304
+ for pat, name in _SHAPE_ALIASES:
305
+ caption = pat.sub(f"({name})", caption)
306
+ return caption
307
+
308
+ # Helpers for Shape Aliases UI
309
  def get_shape_alias_rows_ui_defaults():
310
  s = load_settings()
311
  rows = [[it.get("shape",""), it.get("name","")] for it in s.get("shape_aliases", [])]
312
  enabled = bool(s.get("shape_aliases_enabled", True))
 
313
  if not rows:
314
  rows = [["", ""]]
315
  return rows, enabled
 
331
  save_settings(cfg)
332
  _refresh_shape_aliases_cache()
333
 
 
334
  normalized = [[it["shape"], it["name"]] for it in cleaned] + [["", ""]]
335
  return (
336
  "✅ Saved shape alias options.",
337
  gr.update(value=normalized, row_count=(max(1, len(normalized)), "dynamic"))
338
  )
339
 
 
340
  # ────────────────────────────────────────────────────────
341
  # Logo loader
342
  # ────────────────────────────────────────────────────────
 
636
  chunk_size = gr.Slider(1, 50, settings.get("chunk_size", 10), step=1, label="Chunk size")
637
  max_side = gr.Slider(256, MAX_SIDE_CAP, settings.get("max_side", min(896, MAX_SIDE_CAP)), step=32, label="Max side (resize)")
638
 
639
+ # === Shape Aliases UI (Accordion) ===
640
+ with gr.Accordion("Shape Aliases", open=False):
641
  gr.Markdown(
642
  "### 🔷 Shape Aliases\n"
643
+ "Replace literal **shape tokens** in captions with a preferred **name**.\n\n"
644
  "**How to use:**\n"
645
+ "1) Left column: exact shape token (e.g., `diamond`, `heart`).\n"
646
+ "2) Right column: replacement name (e.g., `starkey-emblem`).\n"
647
  "3) Click **Save**.\n\n"
648
+ "_Rows with blanks are ignored; add as many rows as you like._"
649
+ )
 
 
650
 
651
+ init_rows, init_enabled = get_shape_alias_rows_ui_defaults()
 
 
 
 
652
 
653
+ enable_aliases = gr.Checkbox(
654
+ label="Enable shape alias replacements",
655
+ value=init_enabled,
656
+ )
 
 
 
 
 
657
 
658
+ alias_table = gr.Dataframe(
659
+ headers=["shape (literal token)", "name to insert"],
660
+ value=init_rows, # set value at creation time
661
+ col_count=(2, "fixed"), # exactly two columns
662
+ row_count=(max(1, len(init_rows)), "dynamic"), # user can add/remove rows
663
+ datatype=["str", "str"],
664
+ type="array", # treat rows as simple lists
665
+ interactive=True
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
666
  )
667
 
668
+ with gr.Row():
669
+ add_row_btn = gr.Button("+ Add row", variant="secondary")
670
+ clear_btn = gr.Button("Clear", variant="secondary")
671
+ save_btn = gr.Button("💾 Save", variant="primary")
672
+
673
+ save_status = gr.Markdown("")
674
+
675
+ # Button handlers
676
+ def _add_row(cur):
677
+ cur = (cur or []) + [["", ""]]
678
+ return gr.update(value=cur, row_count=(max(1, len(cur)), "dynamic"))
679
+
680
+ def _clear_rows():
681
+ return gr.update(value=[["", ""]], row_count=(1, "dynamic"))
682
+
683
+ add_row_btn.click(_add_row, inputs=[alias_table], outputs=[alias_table])
684
+ clear_btn.click(_clear_rows, outputs=[alias_table])
685
+ save_btn.click(save_shape_alias_rows, inputs=[enable_aliases, alias_table],
686
+ outputs=[save_status, alias_table])
687
+
688
  # Auto-refresh instruction & persist key controls
689
  def _refresh_instruction(styles, extra, name_value, trigv, begv, endv):
690
  instr = final_instruction(styles or ["Character training (short)"], extra or [], name_value)