fh46jderf / app.py
ssboost's picture
Update app.py
5b349d3 verified
raw
history blame
17.1 kB
import os
import sys
import logging
import tempfile
import traceback
from typing import List, Tuple, Optional, Any
import gradio as gr
from gradio_client import Client, handle_file
from dotenv import load_dotenv
# .env ํŒŒ์ผ ๋กœ๋“œ
load_dotenv()
# ๋กœ๊น… ์„ค์ • (API ์—”๋“œํฌ์ธํŠธ ์ •๋ณด๋Š” ๋กœ๊ทธ์— ๋‚จ๊ธฐ์ง€ ์•Š์Œ)
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
handlers=[
logging.FileHandler("app.log"),
logging.StreamHandler(sys.stdout)
]
)
logger = logging.getLogger("image-enhancer-control-tower")
class GradioClientController:
"""ํ—ˆ๊น…ํŽ˜์ด์Šค ๊ทธ๋ผ๋””์˜ค API ํด๋ผ์ด์–ธํŠธ ์ปจํŠธ๋กค๋Ÿฌ"""
def __init__(self):
self.client = None
self._initialize_client()
def _initialize_client(self):
"""ํด๋ผ์ด์–ธํŠธ ์ดˆ๊ธฐํ™” (์—”๋“œํฌ์ธํŠธ ์ •๋ณด๋Š” ๋กœ๊ทธ์— ๋‚จ๊ธฐ์ง€ ์•Š์Œ)"""
try:
api_endpoint = os.environ.get("API_ENDPOINT")
if not api_endpoint:
logger.error("API_ENDPOINT ํ™˜๊ฒฝ ๋ณ€์ˆ˜๊ฐ€ ์„ค์ •๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.")
raise ValueError("API_ENDPOINT ํ™˜๊ฒฝ ๋ณ€์ˆ˜๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.")
self.client = Client(api_endpoint)
logger.info("API ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์„ฑ๊ณต์ ์œผ๋กœ ์ดˆ๊ธฐํ™”๋˜์—ˆ์Šต๋‹ˆ๋‹ค.")
except Exception as e:
logger.error(f"ํด๋ผ์ด์–ธํŠธ ์ดˆ๊ธฐํ™” ์‹คํŒจ: {e}")
self.client = None
def update_dropdowns(self, bg_type: str) -> Tuple:
"""๋ฐฐ๊ฒฝ ์œ ํ˜•์— ๋”ฐ๋ฅธ ๋“œ๋กญ๋‹ค์šด ์—…๋ฐ์ดํŠธ"""
try:
if not self.client:
logger.error("ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์ดˆ๊ธฐํ™”๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.")
return tuple([gr.update() for _ in range(7)])
result = self.client.predict(
bg_type=bg_type,
api_name="/update_dropdowns"
)
logger.info(f"๋“œ๋กญ๋‹ค์šด ์—…๋ฐ์ดํŠธ ์™„๋ฃŒ: {bg_type}")
# ๊ฒฐ๊ณผ๋ฅผ Gradio ์—…๋ฐ์ดํŠธ ํ˜•์‹์œผ๋กœ ๋ณ€ํ™˜
updates = []
for i, choices in enumerate(result):
if i == 0: # ์‹ฌํ”Œ ๋ฐฐ๊ฒฝ
updates.append(gr.update(visible=(bg_type == "์‹ฌํ”Œ ๋ฐฐ๊ฒฝ"), choices=choices, value=choices[0] if choices else None))
elif i == 1: # ์ŠคํŠœ๋””์˜ค ๋ฐฐ๊ฒฝ
updates.append(gr.update(visible=(bg_type == "์ŠคํŠœ๋””์˜ค ๋ฐฐ๊ฒฝ"), choices=choices, value=choices[0] if choices else None))
elif i == 2: # ์ž์—ฐ ํ™˜๊ฒฝ
updates.append(gr.update(visible=(bg_type == "์ž์—ฐ ํ™˜๊ฒฝ"), choices=choices, value=choices[0] if choices else None))
elif i == 3: # ์‹ค๋‚ด ํ™˜๊ฒฝ
updates.append(gr.update(visible=(bg_type == "์‹ค๋‚ด ํ™˜๊ฒฝ"), choices=choices, value=choices[0] if choices else None))
elif i == 4: # ํŠน์ˆ˜๋ฐฐ๊ฒฝ
updates.append(gr.update(visible=(bg_type == "ํŠน์ˆ˜๋ฐฐ๊ฒฝ"), choices=choices, value=choices[0] if choices else None))
elif i == 5: # ์ฃผ์–ผ๋ฆฌ
updates.append(gr.update(visible=(bg_type == "์ฃผ์–ผ๋ฆฌ"), choices=choices, value=choices[0] if choices else None))
elif i == 6: # ํŠน์ˆ˜ํšจ๊ณผ
updates.append(gr.update(visible=(bg_type == "ํŠน์ˆ˜ํšจ๊ณผ"), choices=choices, value=choices[0] if choices else None))
return tuple(updates)
except Exception as e:
logger.error(f"๋“œ๋กญ๋‹ค์šด ์—…๋ฐ์ดํŠธ ์˜ค๋ฅ˜: {e}")
return tuple([gr.update() for _ in range(7)])
def generate_prompt_only(self, password: str, bg_type: str, simple: str, studio: str,
nature: str, indoor: str, special: str, jewelry: str,
special_effects: str, request_text: str, aspect_ratio: str) -> str:
"""ํ”„๋กฌํ”„ํŠธ๋งŒ ์ƒ์„ฑ"""
try:
if not self.client:
logger.error("ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์ดˆ๊ธฐํ™”๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.")
return "ํด๋ผ์ด์–ธํŠธ ์—ฐ๊ฒฐ ์˜ค๋ฅ˜"
result = self.client.predict(
password=password,
bg_type=bg_type,
simple=simple,
studio=studio,
nature=nature,
indoor=indoor,
special=special,
jewelry=jewelry,
special_effects=special_effects,
request_text=request_text,
aspect_ratio=aspect_ratio,
api_name="/generate_prompt_with_password_check"
)
logger.info("ํ”„๋กฌํ”„ํŠธ ์ƒ์„ฑ ์™„๋ฃŒ")
return result
except Exception as e:
logger.error(f"ํ”„๋กฌํ”„ํŠธ ์ƒ์„ฑ ์˜ค๋ฅ˜: {e}")
return f"ํ”„๋กฌํ”„ํŠธ ์ƒ์„ฑ ์˜ค๋ฅ˜: {str(e)}"
def process_image(self, password: str, image, bg_type: str, simple: str, studio: str,
nature: str, indoor: str, special: str, jewelry: str, special_effects: str,
request_text: str, quality_level: str, aspect_ratio: str,
output_format: str, enable_enhancement: bool) -> Tuple:
"""์ด๋ฏธ์ง€ ์ฒ˜๋ฆฌ (ํŽธ์ง‘ ๋ฐ ํ™”์งˆ ๊ฐœ์„ )"""
try:
if not self.client:
logger.error("ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์ดˆ๊ธฐํ™”๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.")
return ([], None, [], None, "", "", "ํด๋ผ์ด์–ธํŠธ ์—ฐ๊ฒฐ ์˜ค๋ฅ˜")
# ์ด๋ฏธ์ง€๋ฅผ ์ž„์‹œ ํŒŒ์ผ๋กœ ์ €์žฅ
temp_path = None
if image is not None:
temp_path = tempfile.mktemp(suffix='.png')
image.save(temp_path)
# API ํ˜ธ์ถœ
result = self.client.predict(
password=password,
param_1=handle_file(temp_path) if temp_path else None,
param_2=bg_type,
param_3=simple,
param_4=studio,
param_5=nature,
param_6=indoor,
param_7=special,
param_8=jewelry,
param_9=special_effects,
param_10=request_text,
param_11=quality_level,
param_12=aspect_ratio,
param_13=output_format,
param_14=enable_enhancement,
api_name="/check_password"
)
# ์ž„์‹œ ํŒŒ์ผ ์ •๋ฆฌ
if temp_path and os.path.exists(temp_path):
try:
os.remove(temp_path)
except:
pass
logger.info("์ด๋ฏธ์ง€ ์ฒ˜๋ฆฌ ์™„๋ฃŒ")
# ๊ฒฐ๊ณผ ๋ฐ˜ํ™˜: (original_output, original_download, enhanced_output, enhanced_download, prompt_output, info, error)
return result
except Exception as e:
logger.error(f"์ด๋ฏธ์ง€ ์ฒ˜๋ฆฌ ์˜ค๋ฅ˜: {e}")
# ์ž„์‹œ ํŒŒ์ผ ์ •๋ฆฌ
if 'temp_path' in locals() and temp_path and os.path.exists(temp_path):
try:
os.remove(temp_path)
except:
pass
return ([], None, [], None, "", "", f"์ด๋ฏธ์ง€ ์ฒ˜๋ฆฌ ์˜ค๋ฅ˜: {str(e)}")
# ์ „์—ญ ํด๋ผ์ด์–ธํŠธ ์ปจํŠธ๋กค๋Ÿฌ ์ธ์Šคํ„ด์Šค
controller = GradioClientController()
def create_gradio_interface():
"""Gradio ์ธํ„ฐํŽ˜์ด์Šค ์ƒ์„ฑ"""
try:
logger.info("Gradio ์ธํ„ฐํŽ˜์ด์Šค ์ƒ์„ฑ ์‹œ์ž‘")
# ๋ฐฐ๊ฒฝ ์œ ํ˜• ์„ ํƒ์ง€ (ํ•˜๋“œ์ฝ”๋”ฉ)
background_types = ["์‹ฌํ”Œ ๋ฐฐ๊ฒฝ", "์ŠคํŠœ๋””์˜ค ๋ฐฐ๊ฒฝ", "์ž์—ฐ ํ™˜๊ฒฝ", "์‹ค๋‚ด ํ™˜๊ฒฝ", "ํŠน์ˆ˜๋ฐฐ๊ฒฝ", "์ฃผ์–ผ๋ฆฌ", "ํŠน์ˆ˜ํšจ๊ณผ"]
with gr.Blocks(title="AI ์ด๋ฏธ์ง€ ํŽธ์ง‘ ๋ฐ ํ™”์งˆ ๊ฐœ์„ ") as app:
gr.Markdown("# AI ์ด๋ฏธ์ง€ ํŽธ์ง‘ ๋ฐ ํ™”์งˆ ๊ฐœ์„  ๋„๊ตฌ")
# ๋น„๋ฐ€๋ฒˆํ˜ธ ์ž…๋ ฅ ํ•„๋“œ
password_box = gr.Textbox(
label="๋น„๋ฐ€๋ฒˆํ˜ธ",
type="password",
placeholder="์‚ฌ์šฉํ•˜๋ ค๋ฉด ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ์ž…๋ ฅํ•˜์„ธ์š”",
interactive=True
)
# ์ด๋ฏธ์ง€ ํŽธ์ง‘ ๋ฐ ํ™”์งˆ ๊ฐœ์„  ์ธํ„ฐํŽ˜์ด์Šค
with gr.Row():
with gr.Column():
# ์ƒํ’ˆ ์ด๋ฏธ์ง€ ์—…๋กœ๋“œ
image = gr.Image(label="์ƒํ’ˆ ์ด๋ฏธ์ง€ ์—…๋กœ๋“œ", type="pil")
with gr.Row():
with gr.Column():
background_type = gr.Radio(
choices=background_types,
label="๋ฐฐ๊ฒฝ ์œ ํ˜•",
value="์‹ฌํ”Œ ๋ฐฐ๊ฒฝ"
)
# ๋“œ๋กญ๋‹ค์šด ์ปดํฌ๋„ŒํŠธ๋“ค (์ดˆ๊ธฐ์—๋Š” ๋นˆ ์ƒํƒœ)
simple_dropdown = gr.Dropdown(
choices=[],
label="์‹ฌํ”Œ ๋ฐฐ๊ฒฝ ์„ ํƒ",
visible=True,
interactive=True
)
studio_dropdown = gr.Dropdown(
choices=[],
label="์ŠคํŠœ๋””์˜ค ๋ฐฐ๊ฒฝ ์„ ํƒ",
visible=False,
interactive=True
)
nature_dropdown = gr.Dropdown(
choices=[],
label="์ž์—ฐ ํ™˜๊ฒฝ ์„ ํƒ",
visible=False,
interactive=True
)
indoor_dropdown = gr.Dropdown(
choices=[],
label="์‹ค๋‚ด ํ™˜๊ฒฝ ์„ ํƒ",
visible=False,
interactive=True
)
special_dropdown = gr.Dropdown(
choices=[],
label="ํŠน์ˆ˜๋ฐฐ๊ฒฝ ์„ ํƒ",
visible=False,
interactive=True
)
jewelry_dropdown = gr.Dropdown(
choices=[],
label="์ฃผ์–ผ๋ฆฌ ๋ฐฐ๊ฒฝ ์„ ํƒ",
visible=False,
interactive=True
)
special_effects_dropdown = gr.Dropdown(
choices=[],
label="ํŠน์ˆ˜ํšจ๊ณผ ๋ฐฐ๊ฒฝ ์„ ํƒ",
visible=False,
interactive=True
)
# ๋“œ๋กญ๋‹ค์šด ๋ณ€๊ฒฝ ์ด๋ฒคํŠธ
background_type.change(
fn=controller.update_dropdowns,
inputs=[background_type],
outputs=[simple_dropdown, studio_dropdown, nature_dropdown,
indoor_dropdown, special_dropdown, jewelry_dropdown, special_effects_dropdown]
)
# ์š”์ฒญ์‚ฌํ•ญ ์ž…๋ ฅ
request_text = gr.Textbox(
label="์š”์ฒญ์‚ฌํ•ญ",
placeholder="์ƒํ’ˆ ์ด๋ฏธ์ง€์— ์ ์šฉํ•  ์Šคํƒ€์ผ, ๋ถ„์œ„๊ธฐ, ํŠน๋ณ„ ์š”์ฒญ์‚ฌํ•ญ ๋“ฑ์„ ์ž…๋ ฅํ•˜์„ธ์š”.",
lines=3
)
# ์ƒˆ๋กœ์šด ์˜ต์…˜๋“ค
quality_level = gr.Radio(
label="ํ’ˆ์งˆ ๋ ˆ๋ฒจ",
choices=["gpt", "flux"],
value="flux",
info="GPT: GPT ๋ชจ๋ธ (๊ณ ํ’ˆ์งˆ), ์ผ๋ฐ˜: Flux ๋ชจ๋ธ (๋น ๋ฅธ ์ฒ˜๋ฆฌ + ๊ธฐ๋ณธ ํ™”์งˆ๊ฐœ์„ )"
)
aspect_ratio = gr.Dropdown(
label="์ข…ํšก๋น„",
choices=["1:1", "3:2", "2:3"],
value="1:1"
)
output_format = gr.Dropdown(
label="์ด๋ฏธ์ง€ ํ˜•์‹",
choices=["jpg", "png"],
value="jpg"
)
# ํ™”์งˆ ๊ฐœ์„  ์˜ต์…˜
enable_enhancement = gr.Checkbox(
label="์ถ”๊ฐ€ ํ™”์งˆ ๊ฐœ์„ ",
value=False,
info="GPT: 1ํšŒ ํ™”์งˆ๊ฐœ์„ , Flux: 2์ฐจ ํ™”์งˆ๊ฐœ์„  (๊ธฐ๋ณธ 1ํšŒ + ์ถ”๊ฐ€ 1ํšŒ)"
)
# ํ”„๋กฌํ”„ํŠธ ์ƒ์„ฑ ๋ฒ„ํŠผ
generate_prompt_btn = gr.Button("ํ”„๋กฌํ”„ํŠธ๋งŒ ์ƒ์„ฑ")
# ํŽธ์ง‘ ๋ฒ„ํŠผ
edit_btn = gr.Button("์ด๋ฏธ์ง€ ํŽธ์ง‘ ๋ฐ ํ™”์งˆ ๊ฐœ์„ ")
with gr.Column():
with gr.Row():
with gr.Column():
gr.Markdown("## ํŽธ์ง‘๋œ ์ด๋ฏธ์ง€")
original_output = gr.Gallery(label="ํŽธ์ง‘ ๊ฒฐ๊ณผ", preview=True)
original_download = gr.File(label="ํŽธ์ง‘ ์ด๋ฏธ์ง€ ๋‹ค์šด๋กœ๋“œ", interactive=False)
with gr.Column():
gr.Markdown("## ํ™”์งˆ ๊ฐœ์„ ๋œ ์ด๋ฏธ์ง€")
enhanced_output = gr.Gallery(label="ํ™”์งˆ ๊ฐœ์„  ๊ฒฐ๊ณผ", preview=True)
enhanced_download = gr.File(label="๊ฐœ์„  ์ด๋ฏธ์ง€ ๋‹ค์šด๋กœ๋“œ", interactive=False)
# ํ”„๋กฌํ”„ํŠธ ์ถœ๋ ฅ
prompt_output = gr.Textbox(label="์ƒ์„ฑ๋œ ํ”„๋กฌํ”„ํŠธ", lines=10, interactive=False)
info = gr.Textbox(label="์ฒ˜๋ฆฌ ์ •๋ณด", interactive=False)
error = gr.Textbox(label="์˜ค๋ฅ˜ ๋ฉ”์‹œ์ง€", interactive=False, visible=True)
# ํ”„๋กฌํ”„ํŠธ ์ƒ์„ฑ ๋ฒ„ํŠผ ํด๋ฆญ ์ด๋ฒคํŠธ
generate_prompt_btn.click(
fn=controller.generate_prompt_only,
inputs=[
password_box,
background_type,
simple_dropdown, studio_dropdown, nature_dropdown, indoor_dropdown, special_dropdown,
jewelry_dropdown, special_effects_dropdown,
request_text, aspect_ratio
],
outputs=[prompt_output]
)
# ํŽธ์ง‘ ๋ฒ„ํŠผ ํด๋ฆญ ์ด๋ฒคํŠธ
edit_btn.click(
fn=controller.process_image,
inputs=[
password_box,
image, background_type,
simple_dropdown, studio_dropdown, nature_dropdown, indoor_dropdown, special_dropdown,
jewelry_dropdown, special_effects_dropdown,
request_text, quality_level, aspect_ratio, output_format, enable_enhancement
],
outputs=[
original_output, original_download,
enhanced_output, enhanced_download,
prompt_output, info, error
]
)
# ์ดˆ๊ธฐ ๋“œ๋กญ๋‹ค์šด ๋กœ๋“œ
app.load(
fn=controller.update_dropdowns,
inputs=[background_type],
outputs=[simple_dropdown, studio_dropdown, nature_dropdown,
indoor_dropdown, special_dropdown, jewelry_dropdown, special_effects_dropdown]
)
logger.info("Gradio ์ธํ„ฐํŽ˜์ด์Šค ์ƒ์„ฑ ์™„๋ฃŒ")
return app
except Exception as e:
logger.error(f"Gradio ์ธํ„ฐํŽ˜์ด์Šค ์ƒ์„ฑ ์˜ค๋ฅ˜: {e}")
logger.error(traceback.format_exc())
raise
# ์•ฑ ์‹คํ–‰
if __name__ == "__main__":
try:
logger.info("์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์‹œ์ž‘")
# imgs ๋””๋ ‰ํ† ๋ฆฌ ํ™•์ธ/์ƒ์„ฑ
os.makedirs("imgs", exist_ok=True)
logger.info("์ด๋ฏธ์ง€ ๋””๋ ‰ํ† ๋ฆฌ ์ค€๋น„ ์™„๋ฃŒ")
app = create_gradio_interface()
logger.info("Gradio ์•ฑ ์‹œ์ž‘")
app.launch(share=True)
except Exception as e:
logger.error(f"์•ฑ ์‹คํ–‰ ์˜ค๋ฅ˜: {e}")
logger.error(traceback.format_exc())