Spaces:
Running
Running
Update app-backup.py
Browse files- app-backup.py +175 -74
app-backup.py
CHANGED
@@ -537,67 +537,93 @@ class ImageGenerator:
|
|
537 |
enhanced_prompt = core_elements
|
538 |
|
539 |
return enhanced_prompt # ์ฌ๋ฐ๋ฅธ ์ธ๋ดํ
์ด์
|
540 |
-
|
|
|
541 |
def generate_image(self, prompt: str, panel_id: str, session_id: str,
|
542 |
scene_type: str = "medium", genre: str = "๋ก๋งจ์ค",
|
|
|
543 |
progress_callback=None) -> Dict[str, Any]:
|
544 |
-
"""Generate image using qwen/qwen-image with
|
545 |
try:
|
546 |
if not REPLICATE_API_TOKEN:
|
547 |
logger.warning("No Replicate API token")
|
548 |
return {"panel_id": panel_id, "status": "error", "message": "No API token"}
|
549 |
|
550 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
551 |
panel_number = int(re.findall(r'\d+', panel_id)[-1]) if re.findall(r'\d+', panel_id) else 1
|
552 |
|
553 |
# ์นํฐ ์คํ์ผ ํ๋กฌํํธ ๊ฐํ
|
554 |
enhanced_prompt = self.enhance_prompt_for_webtoon(prompt, panel_number, scene_type, genre)
|
555 |
|
556 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
557 |
input_params = {
|
558 |
"prompt": enhanced_prompt,
|
559 |
-
"aspect_ratio": "9:16",
|
560 |
-
"num_outputs": 1,
|
561 |
-
"guidance_scale": 4.5
|
562 |
-
"num_inference_steps": 50,
|
563 |
-
"output_format": "jpg",
|
564 |
-
"output_quality": 95,
|
565 |
-
"disable_safety_checker": False,
|
566 |
"negative_prompt": "comic strip, multiple panels, divided frames, split screen, grid layout, manga panels",
|
567 |
-
"seed":
|
568 |
}
|
569 |
|
570 |
-
logger.info(f"Generating image for panel {panel_id}
|
571 |
-
logger.info(f"
|
572 |
|
573 |
try:
|
574 |
-
# Replicate API ํธ์ถ
|
575 |
output = replicate.run(
|
576 |
"qwen/qwen-image",
|
577 |
input=input_params
|
578 |
)
|
579 |
|
580 |
if output:
|
581 |
-
#
|
582 |
-
# ์์ ์ฒ๋ผ .url() ๋ฉ์๋๋ฅผ ์ฌ์ฉ
|
583 |
if isinstance(output, list) and len(output) > 0:
|
584 |
-
# ์ฒซ ๋ฒ์งธ ์ด๋ฏธ์ง ๊ฐ์ ธ์ค๊ธฐ
|
585 |
image_item = output[0]
|
586 |
-
|
587 |
-
# FileObject์ url() ๋ฉ์๋ ํธ์ถ
|
588 |
if hasattr(image_item, 'url'):
|
589 |
if callable(image_item.url):
|
590 |
image_url = image_item.url()
|
591 |
else:
|
592 |
image_url = image_item.url
|
593 |
else:
|
594 |
-
# ๋ฌธ์์ด๋ก ๋ณํ ์๋
|
595 |
image_url = str(image_item)
|
596 |
elif isinstance(output, str):
|
597 |
-
# ์ง์ URL ๋ฌธ์์ด์ธ ๊ฒฝ์ฐ
|
598 |
image_url = output
|
599 |
else:
|
600 |
-
# ๊ธฐํ ํ์ ์ฒ๋ฆฌ
|
601 |
image_url = str(output)
|
602 |
|
603 |
# URL ์ ํจ์ฑ ํ์ธ
|
@@ -605,7 +631,7 @@ class ImageGenerator:
|
|
605 |
logger.error(f"Invalid image URL: {image_url}")
|
606 |
return {"panel_id": panel_id, "status": "error", "message": "Invalid image URL format"}
|
607 |
|
608 |
-
#
|
609 |
logger.info(f"Resizing image to {WEBTOON_IMAGE_WIDTH}x{WEBTOON_IMAGE_HEIGHT}px")
|
610 |
resized_image_url = self.resize_image_from_url(
|
611 |
image_url,
|
@@ -613,18 +639,19 @@ class ImageGenerator:
|
|
613 |
WEBTOON_IMAGE_HEIGHT
|
614 |
)
|
615 |
|
616 |
-
# ์บ์
|
617 |
-
cache_key = f"{session_id}_{panel_id}"
|
618 |
generated_images_cache[cache_key] = resized_image_url
|
619 |
|
620 |
-
logger.info(f"Successfully generated
|
621 |
return {
|
622 |
"panel_id": panel_id,
|
623 |
"status": "success",
|
624 |
-
"image_url": resized_image_url,
|
625 |
-
"original_url": image_url,
|
626 |
"prompt": enhanced_prompt,
|
627 |
-
"size": f"{WEBTOON_IMAGE_WIDTH}x{WEBTOON_IMAGE_HEIGHT}"
|
|
|
|
|
628 |
}
|
629 |
else:
|
630 |
logger.error(f"No output from qwen/qwen-image for panel {panel_id}")
|
@@ -641,6 +668,8 @@ class ImageGenerator:
|
|
641 |
logger.error(f"Image generation error: {e}", exc_info=True)
|
642 |
return {"panel_id": panel_id, "status": "error", "message": str(e)}
|
643 |
|
|
|
|
|
644 |
# --- LLM Integration ---
|
645 |
class WebtoonSystem:
|
646 |
"""Webtoon planning and storyboard generation system"""
|
@@ -1959,68 +1988,133 @@ def create_interface():
|
|
1959 |
|
1960 |
# ์ฃผ์ ์์ ๋ถ๋ถ๋ง ํฌํจํ ํจ์น ์ฝ๋
|
1961 |
# generate_selected_panel_images ํจ์ ์์
|
1962 |
-
def
|
1963 |
-
|
|
|
|
|
1964 |
if not REPLICATE_API_TOKEN:
|
1965 |
-
|
1966 |
-
|
1967 |
-
|
|
|
|
|
1968 |
if not panel_data:
|
1969 |
-
|
1970 |
-
|
1971 |
-
|
|
|
|
|
1972 |
if not selected_panels:
|
1973 |
-
|
1974 |
-
|
1975 |
-
|
|
|
|
|
1976 |
if not webtoon_system:
|
1977 |
-
|
1978 |
-
|
1979 |
-
|
1980 |
selected_numbers = [int(p.split()[1]) for p in selected_panels]
|
1981 |
total = len(selected_numbers)
|
1982 |
successful = 0
|
1983 |
-
|
1984 |
-
|
|
|
1985 |
updated_panel_data = panel_data.copy()
|
1986 |
-
|
1987 |
for i, panel in enumerate(updated_panel_data):
|
1988 |
if panel['number'] in selected_numbers:
|
1989 |
idx = selected_numbers.index(panel['number'])
|
1990 |
progress((idx / total), desc=f"ํจ๋ {panel['number']} ์์ฑ ์ค...")
|
1991 |
-
|
1992 |
panel_id = f"panel_{panel['number']}"
|
1993 |
prompt = panel_prompts.get(panel_id, panel.get('prompt', ''))
|
1994 |
-
|
|
|
|
|
|
|
1995 |
if prompt:
|
1996 |
try:
|
1997 |
panel['prompt'] = prompt
|
1998 |
-
|
1999 |
-
|
2000 |
-
|
2001 |
-
|
2002 |
-
|
2003 |
-
|
|
|
|
|
|
|
2004 |
result = webtoon_system.image_generator.generate_image(
|
2005 |
-
|
2006 |
-
|
2007 |
-
|
2008 |
-
|
2009 |
-
|
|
|
2010 |
)
|
2011 |
-
|
2012 |
if result['status'] == 'success':
|
2013 |
panel['image_url'] = result['image_url']
|
2014 |
successful += 1
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2015 |
except Exception as e:
|
2016 |
logger.error(f"Error generating panel {panel['number']}: {e}")
|
2017 |
-
|
|
|
2018 |
time.sleep(0.5)
|
2019 |
-
|
2020 |
-
|
2021 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
2022 |
return updated_panel_data, html, gr.update(visible=False)
|
2023 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2024 |
# generate_all_panel_images ํจ์ ์์
|
2025 |
def generate_all_panel_images(panel_data, session_id, character_profiles, webtoon_system, panel_prompts, genre, progress=gr.Progress()):
|
2026 |
"""Generate images for all panels - ์์ ๋ ๋ฒ์ """
|
@@ -2288,11 +2382,23 @@ def create_interface():
|
|
2288 |
inputs=[panel_data_state],
|
2289 |
outputs=[panel_data_state, generation_progress]
|
2290 |
).then(
|
2291 |
-
fn=
|
2292 |
-
inputs=[panel_data_state, panel_selector, current_session_id,
|
2293 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2294 |
)
|
2295 |
|
|
|
|
|
|
|
2296 |
# ๋ชจ๋ ํจ๋ ์ด๋ฏธ์ง ์์ฑ - panel_data_state ์
๋ฐ์ดํธ ์ถ๊ฐ
|
2297 |
generate_all_images_btn.click(
|
2298 |
fn=lambda pd: (pd, gr.update(visible=True, value="๋ชจ๋ ํจ๋ ์ด๋ฏธ์ง ์์ฑ ์์...")),
|
@@ -2304,12 +2410,7 @@ def create_interface():
|
|
2304 |
outputs=[panel_data_state, panels_display, generation_progress] # panel_data_state ์ถ๋ ฅ ์ถ๊ฐ
|
2305 |
)
|
2306 |
|
2307 |
-
|
2308 |
-
clear_images_btn.click(
|
2309 |
-
fn=clear_all_images,
|
2310 |
-
inputs=[panel_data_state, panel_prompts_state, current_session_id, character_profiles_state, webtoon_system, current_genre],
|
2311 |
-
outputs=[panel_data_state, panels_display] # panel_data_state ์ถ๋ ฅ ์ถ๊ฐ
|
2312 |
-
)
|
2313 |
|
2314 |
# ์ ์ฒด ์ด๋ฏธ์ง ๋ค์ด๋ก๋ - ์์ ๋ ๋ฉ์์ง
|
2315 |
download_all_images_btn.click(
|
|
|
537 |
enhanced_prompt = core_elements
|
538 |
|
539 |
return enhanced_prompt # ์ฌ๋ฐ๋ฅธ ์ธ๋ดํ
์ด์
|
540 |
+
|
541 |
+
|
542 |
def generate_image(self, prompt: str, panel_id: str, session_id: str,
|
543 |
scene_type: str = "medium", genre: str = "๋ก๋งจ์ค",
|
544 |
+
force_regenerate: bool = False, # ์ฌ์์ฑ ๊ฐ์ ํ๋๊ทธ ์ถ๊ฐ
|
545 |
progress_callback=None) -> Dict[str, Any]:
|
546 |
+
"""Generate image using qwen/qwen-image with regeneration support"""
|
547 |
try:
|
548 |
if not REPLICATE_API_TOKEN:
|
549 |
logger.warning("No Replicate API token")
|
550 |
return {"panel_id": panel_id, "status": "error", "message": "No API token"}
|
551 |
|
552 |
+
# ์บ์ ํค ์์ฑ
|
553 |
+
cache_key = f"{session_id}_{panel_id}"
|
554 |
+
|
555 |
+
# force_regenerate๊ฐ True์ด๋ฉด ์บ์ ๋ฌด์ํ๊ณ ์๋ก ์์ฑ
|
556 |
+
if not force_regenerate and cache_key in generated_images_cache:
|
557 |
+
logger.info(f"Using cached image for {panel_id}")
|
558 |
+
# ์บ์๋ ์ด๋ฏธ์ง ๋ฐํํ์ง ์๊ณ ์๋ก ์์ฑํ๋๋ก ์์
|
559 |
+
# return {"panel_id": panel_id, "status": "success", "image_url": generated_images_cache[cache_key]}
|
560 |
+
pass # ์บ์ ๋ฌด์ํ๊ณ ๊ณ์ ์งํ
|
561 |
+
|
562 |
+
# Panel number ์ถ์ถ
|
563 |
panel_number = int(re.findall(r'\d+', panel_id)[-1]) if re.findall(r'\d+', panel_id) else 1
|
564 |
|
565 |
# ์นํฐ ์คํ์ผ ํ๋กฌํํธ ๊ฐํ
|
566 |
enhanced_prompt = self.enhance_prompt_for_webtoon(prompt, panel_number, scene_type, genre)
|
567 |
|
568 |
+
# ์ฌ์์ฑ ์ ํ๋กฌํํธ์ ๋ณํ ์ถ๊ฐ (๋ ๋ค์ํ ๊ฒฐ๊ณผ๋ฅผ ์ํด)
|
569 |
+
if force_regenerate or cache_key in generated_images_cache:
|
570 |
+
# ํ๋กฌํํธ์ ์ฝ๊ฐ์ ๋ณํ ์ถ๊ฐ
|
571 |
+
variation_keywords = [
|
572 |
+
"different angle", "alternative view", "varied perspective",
|
573 |
+
"new composition", "fresh approach", "revised scene",
|
574 |
+
"different lighting", "alternative mood", "varied atmosphere"
|
575 |
+
]
|
576 |
+
variation = random.choice(variation_keywords)
|
577 |
+
enhanced_prompt = f"{enhanced_prompt}, {variation}"
|
578 |
+
logger.info(f"Regenerating with variation: {variation}")
|
579 |
+
|
580 |
+
# ์ฌ์์ฑ ์ ๋ค๋ฅธ seed ์ฌ์ฉํ์ฌ ๋ค๋ฅธ ์ด๋ฏธ์ง ์์ฑ ๋ณด์ฅ
|
581 |
+
if force_regenerate or cache_key in generated_images_cache:
|
582 |
+
# ๋๋ค seed ์์ฑ (1-1000000 ๋ฒ์)
|
583 |
+
random_seed = random.randint(1, 1000000)
|
584 |
+
logger.info(f"Using random seed for regeneration: {random_seed}")
|
585 |
+
else:
|
586 |
+
# ์ฒซ ์์ฑ ์์๋ ๋๋ค seed ์ฌ์ฉ
|
587 |
+
random_seed = random.randint(1, 1000000)
|
588 |
+
|
589 |
+
# qwen/qwen-image ํ๋ผ๋ฏธํฐ ์ค์
|
590 |
input_params = {
|
591 |
"prompt": enhanced_prompt,
|
592 |
+
"aspect_ratio": "9:16",
|
593 |
+
"num_outputs": 1,
|
594 |
+
"guidance_scale": 4.5 + random.uniform(-0.5, 0.5), # ์ฝ๊ฐ์ ๋๋ค์ฑ ์ถ๊ฐ
|
595 |
+
"num_inference_steps": 50,
|
596 |
+
"output_format": "jpg",
|
597 |
+
"output_quality": 95,
|
598 |
+
"disable_safety_checker": False,
|
599 |
"negative_prompt": "comic strip, multiple panels, divided frames, split screen, grid layout, manga panels",
|
600 |
+
"seed": random_seed # ๋ช
์์ ์ผ๋ก ๋๋ค seed ์ค์
|
601 |
}
|
602 |
|
603 |
+
logger.info(f"Generating {'new variant' if force_regenerate else 'image'} for panel {panel_id}")
|
604 |
+
logger.info(f"Seed: {random_seed}, Guidance: {input_params['guidance_scale']:.2f}")
|
605 |
|
606 |
try:
|
607 |
+
# Replicate API ํธ์ถ
|
608 |
output = replicate.run(
|
609 |
"qwen/qwen-image",
|
610 |
input=input_params
|
611 |
)
|
612 |
|
613 |
if output:
|
614 |
+
# ์ด๋ฏธ์ง URL ์ถ์ถ
|
|
|
615 |
if isinstance(output, list) and len(output) > 0:
|
|
|
616 |
image_item = output[0]
|
|
|
|
|
617 |
if hasattr(image_item, 'url'):
|
618 |
if callable(image_item.url):
|
619 |
image_url = image_item.url()
|
620 |
else:
|
621 |
image_url = image_item.url
|
622 |
else:
|
|
|
623 |
image_url = str(image_item)
|
624 |
elif isinstance(output, str):
|
|
|
625 |
image_url = output
|
626 |
else:
|
|
|
627 |
image_url = str(output)
|
628 |
|
629 |
# URL ์ ํจ์ฑ ํ์ธ
|
|
|
631 |
logger.error(f"Invalid image URL: {image_url}")
|
632 |
return {"panel_id": panel_id, "status": "error", "message": "Invalid image URL format"}
|
633 |
|
634 |
+
# ์ด๋ฏธ์ง ๋ฆฌ์ฌ์ด์ฆ
|
635 |
logger.info(f"Resizing image to {WEBTOON_IMAGE_WIDTH}x{WEBTOON_IMAGE_HEIGHT}px")
|
636 |
resized_image_url = self.resize_image_from_url(
|
637 |
image_url,
|
|
|
639 |
WEBTOON_IMAGE_HEIGHT
|
640 |
)
|
641 |
|
642 |
+
# ์บ์ ์
๋ฐ์ดํธ (์ฌ์์ฑ ์์๋ ์ ์ด๋ฏธ์ง๋ก ๋ฎ์ด์ฐ๊ธฐ)
|
|
|
643 |
generated_images_cache[cache_key] = resized_image_url
|
644 |
|
645 |
+
logger.info(f"Successfully generated {'variant' if force_regenerate else 'image'} for panel {panel_id}")
|
646 |
return {
|
647 |
"panel_id": panel_id,
|
648 |
"status": "success",
|
649 |
+
"image_url": resized_image_url,
|
650 |
+
"original_url": image_url,
|
651 |
"prompt": enhanced_prompt,
|
652 |
+
"size": f"{WEBTOON_IMAGE_WIDTH}x{WEBTOON_IMAGE_HEIGHT}",
|
653 |
+
"seed": random_seed, # seed ์ ๋ณด ๋ฐํ
|
654 |
+
"regenerated": force_regenerate # ์ฌ์์ฑ ์ฌ๋ถ ํ์
|
655 |
}
|
656 |
else:
|
657 |
logger.error(f"No output from qwen/qwen-image for panel {panel_id}")
|
|
|
668 |
logger.error(f"Image generation error: {e}", exc_info=True)
|
669 |
return {"panel_id": panel_id, "status": "error", "message": str(e)}
|
670 |
|
671 |
+
|
672 |
+
|
673 |
# --- LLM Integration ---
|
674 |
class WebtoonSystem:
|
675 |
"""Webtoon planning and storyboard generation system"""
|
|
|
1988 |
|
1989 |
# ์ฃผ์ ์์ ๋ถ๋ถ๋ง ํฌํจํ ํจ์น ์ฝ๋
|
1990 |
# generate_selected_panel_images ํจ์ ์์
|
1991 |
+
def generate_selected_panel_images_fixed(panel_data, selected_panels, session_id,
|
1992 |
+
character_profiles, webtoon_system,
|
1993 |
+
panel_prompts, genre, progress=gr.Progress()):
|
1994 |
+
"""Generate images for selected panels with regeneration support"""
|
1995 |
if not REPLICATE_API_TOKEN:
|
1996 |
+
html, _ = display_panels_with_editable_prompts(panel_data, panel_prompts,
|
1997 |
+
session_id, character_profiles,
|
1998 |
+
webtoon_system, genre)
|
1999 |
+
return panel_data, html, gr.update(visible=True, value="โ ๏ธ Replicate API ํ ํฐ์ด ์ค์ ๋์ง ์์์ต๋๋ค.")
|
2000 |
+
|
2001 |
if not panel_data:
|
2002 |
+
html, _ = display_panels_with_editable_prompts(panel_data, panel_prompts,
|
2003 |
+
session_id, character_profiles,
|
2004 |
+
webtoon_system, genre)
|
2005 |
+
return panel_data, html, gr.update(visible=True, value="โ ๏ธ ํจ๋ ๋ฐ์ดํฐ๊ฐ ์์ต๋๋ค.")
|
2006 |
+
|
2007 |
if not selected_panels:
|
2008 |
+
html, _ = display_panels_with_editable_prompts(panel_data, panel_prompts,
|
2009 |
+
session_id, character_profiles,
|
2010 |
+
webtoon_system, genre)
|
2011 |
+
return panel_data, html, gr.update(visible=True, value="โ ๏ธ ์์ฑํ ํจ๋์ ์ ํํ์ธ์.")
|
2012 |
+
|
2013 |
if not webtoon_system:
|
2014 |
+
webtoon_system = WebtoonSystem()
|
2015 |
+
webtoon_system.current_genre = genre
|
2016 |
+
|
2017 |
selected_numbers = [int(p.split()[1]) for p in selected_panels]
|
2018 |
total = len(selected_numbers)
|
2019 |
successful = 0
|
2020 |
+
regenerated = 0
|
2021 |
+
|
2022 |
+
# panel_data๋ฅผ ๋ณต์ฌํ์ฌ ์์
|
2023 |
updated_panel_data = panel_data.copy()
|
2024 |
+
|
2025 |
for i, panel in enumerate(updated_panel_data):
|
2026 |
if panel['number'] in selected_numbers:
|
2027 |
idx = selected_numbers.index(panel['number'])
|
2028 |
progress((idx / total), desc=f"ํจ๋ {panel['number']} ์์ฑ ์ค...")
|
2029 |
+
|
2030 |
panel_id = f"panel_{panel['number']}"
|
2031 |
prompt = panel_prompts.get(panel_id, panel.get('prompt', ''))
|
2032 |
+
|
2033 |
+
# ์ด๋ฏธ ์ด๋ฏธ์ง๊ฐ ์๋์ง ํ์ธ
|
2034 |
+
has_existing_image = bool(panel.get('image_url'))
|
2035 |
+
|
2036 |
if prompt:
|
2037 |
try:
|
2038 |
panel['prompt'] = prompt
|
2039 |
+
|
2040 |
+
# ์์ด ํ๋กฌํํธ ๋ฒ์ญ
|
2041 |
+
if not panel.get('prompt_en') or has_existing_image:
|
2042 |
+
# ์ฌ์์ฑ ์ ํ๋กฌํํธ ๋ค์ ๋ฒ์ญ
|
2043 |
+
panel['prompt_en'] = webtoon_system.translate_prompt_to_english(
|
2044 |
+
prompt, character_profiles
|
2045 |
+
)
|
2046 |
+
|
2047 |
+
# ์ด๋ฏธ์ง ์์ฑ (์ฌ์์ฑ ํ๋๊ทธ ํฌํจ)
|
2048 |
result = webtoon_system.image_generator.generate_image(
|
2049 |
+
panel['prompt_en'],
|
2050 |
+
f"ep1_panel{panel['number']}",
|
2051 |
+
session_id,
|
2052 |
+
scene_type=panel.get('scene_type', 'medium'),
|
2053 |
+
genre=genre,
|
2054 |
+
force_regenerate=has_existing_image # ๊ธฐ์กด ์ด๋ฏธ์ง๊ฐ ์์ผ๋ฉด ์ฌ์์ฑ
|
2055 |
)
|
2056 |
+
|
2057 |
if result['status'] == 'success':
|
2058 |
panel['image_url'] = result['image_url']
|
2059 |
successful += 1
|
2060 |
+
if result.get('regenerated'):
|
2061 |
+
regenerated += 1
|
2062 |
+
|
2063 |
+
# seed ์ ๋ณด ์ ์ฅ (๋๋ฒ๊น
์ฉ)
|
2064 |
+
if 'seed' in result:
|
2065 |
+
panel['last_seed'] = result['seed']
|
2066 |
+
|
2067 |
except Exception as e:
|
2068 |
logger.error(f"Error generating panel {panel['number']}: {e}")
|
2069 |
+
|
2070 |
+
# API ๋ถํ ๋ฐฉ์ง๋ฅผ ์ํ ๋๋ ์ด
|
2071 |
time.sleep(0.5)
|
2072 |
+
|
2073 |
+
status_msg = f"์๋ฃ! {successful}/{total} ํจ๋ ์์ฑ ์ฑ๊ณต"
|
2074 |
+
if regenerated > 0:
|
2075 |
+
status_msg += f" (์ฌ์์ฑ: {regenerated}๊ฐ)"
|
2076 |
+
|
2077 |
+
progress(1.0, desc=status_msg)
|
2078 |
+
html, _ = display_panels_with_editable_prompts(updated_panel_data, panel_prompts,
|
2079 |
+
session_id, character_profiles,
|
2080 |
+
webtoon_system, genre)
|
2081 |
return updated_panel_data, html, gr.update(visible=False)
|
2082 |
|
2083 |
+
def clear_image_cache(session_id=None):
|
2084 |
+
"""์ด๋ฏธ์ง ์บ์ ํด๋ฆฌ์ด"""
|
2085 |
+
global generated_images_cache
|
2086 |
+
|
2087 |
+
if session_id:
|
2088 |
+
# ํน์ ์ธ์
์ ์บ์๋ง ํด๋ฆฌ์ด
|
2089 |
+
keys_to_remove = [k for k in generated_images_cache.keys() if k.startswith(f"{session_id}_")]
|
2090 |
+
for key in keys_to_remove:
|
2091 |
+
del generated_images_cache[key]
|
2092 |
+
logger.info(f"Cleared {len(keys_to_remove)} cached images for session {session_id}")
|
2093 |
+
else:
|
2094 |
+
# ์ ์ฒด ์บ์ ํด๋ฆฌ์ด
|
2095 |
+
cache_size = len(generated_images_cache)
|
2096 |
+
generated_images_cache.clear()
|
2097 |
+
logger.info(f"Cleared all {cache_size} cached images")
|
2098 |
+
|
2099 |
+
|
2100 |
+
def clear_all_images_with_cache(panel_data, panel_prompts, session_id,
|
2101 |
+
character_profiles, webtoon_system, genre):
|
2102 |
+
"""Clear all images and cache"""
|
2103 |
+
# ์บ์ ํด๋ฆฌ์ด
|
2104 |
+
clear_image_cache(session_id)
|
2105 |
+
|
2106 |
+
# panel_data๋ฅผ ๋ณต์ฌํ์ฌ ์์
|
2107 |
+
updated_panel_data = panel_data.copy()
|
2108 |
+
for panel in updated_panel_data:
|
2109 |
+
panel['image_url'] = None
|
2110 |
+
panel.pop('last_seed', None) # seed ์ ๋ณด๋ ์ ๊ฑฐ
|
2111 |
+
|
2112 |
+
html, _ = display_panels_with_editable_prompts(updated_panel_data, panel_prompts,
|
2113 |
+
session_id, character_profiles,
|
2114 |
+
webtoon_system, genre)
|
2115 |
+
return updated_panel_data, html
|
2116 |
+
|
2117 |
+
|
2118 |
# generate_all_panel_images ํจ์ ์์
|
2119 |
def generate_all_panel_images(panel_data, session_id, character_profiles, webtoon_system, panel_prompts, genre, progress=gr.Progress()):
|
2120 |
"""Generate images for all panels - ์์ ๋ ๋ฒ์ """
|
|
|
2382 |
inputs=[panel_data_state],
|
2383 |
outputs=[panel_data_state, generation_progress]
|
2384 |
).then(
|
2385 |
+
fn=generate_selected_panel_images_fixed, # ์์ ๋ ํจ์ ์ด๋ฆ ์ฌ์ฉ
|
2386 |
+
inputs=[panel_data_state, panel_selector, current_session_id,
|
2387 |
+
character_profiles_state, webtoon_system, panel_prompts_state, current_genre],
|
2388 |
+
outputs=[panel_data_state, panels_display, generation_progress]
|
2389 |
+
)
|
2390 |
+
|
2391 |
+
# clear_all_images_with_cache ํจ์๋ ์ด๋ฒคํธ ํธ๋ค๋ฌ์์ ์ฌ์ฉ
|
2392 |
+
clear_images_btn.click(
|
2393 |
+
fn=clear_all_images_with_cache, # ์บ์ ํด๋ฆฌ์ด ๊ธฐ๋ฅ์ด ํฌํจ๋ ๋ฒ์ ์ฌ์ฉ
|
2394 |
+
inputs=[panel_data_state, panel_prompts_state, current_session_id,
|
2395 |
+
character_profiles_state, webtoon_system, current_genre],
|
2396 |
+
outputs=[panel_data_state, panels_display]
|
2397 |
)
|
2398 |
|
2399 |
+
|
2400 |
+
|
2401 |
+
|
2402 |
# ๋ชจ๋ ํจ๋ ์ด๋ฏธ์ง ์์ฑ - panel_data_state ์
๋ฐ์ดํธ ์ถ๊ฐ
|
2403 |
generate_all_images_btn.click(
|
2404 |
fn=lambda pd: (pd, gr.update(visible=True, value="๋ชจ๋ ํจ๋ ์ด๋ฏธ์ง ์์ฑ ์์...")),
|
|
|
2410 |
outputs=[panel_data_state, panels_display, generation_progress] # panel_data_state ์ถ๋ ฅ ์ถ๊ฐ
|
2411 |
)
|
2412 |
|
2413 |
+
|
|
|
|
|
|
|
|
|
|
|
2414 |
|
2415 |
# ์ ์ฒด ์ด๋ฏธ์ง ๋ค์ด๋ก๋ - ์์ ๋ ๋ฉ์์ง
|
2416 |
download_all_images_btn.click(
|