Update app.py
Browse files
app.py
CHANGED
|
@@ -9,18 +9,13 @@ HF_TOKEN = os.getenv("HF_TOKEN")
|
|
| 9 |
|
| 10 |
api = HfApi(token=HF_TOKEN)
|
| 11 |
|
| 12 |
-
# --- ์์ฐ์ด ์ ๋ ฌ ํจ์ (mymuse2๊ฐ mymuse10๋ณด๋ค ์์ ์ค๋๋ก ์ค์ ) ---
|
| 13 |
def natural_sort_key(s):
|
| 14 |
return [int(text) if text.isdigit() else text.lower() for text in re.split(r'(\d+)', s)]
|
| 15 |
|
| 16 |
def get_lora_samples(sort_desc=False):
|
| 17 |
-
"""๋ฐ์ดํฐ์
์์ ์ด๋ฏธ์ง๋ฅผ ๊ฐ์ ธ์ ์์ฐ์ด ๊ธฐ์ค์ผ๋ก ์ ๋ ฌํฉ๋๋ค."""
|
| 18 |
try:
|
| 19 |
-
# ์บ์๋ฅผ ๋ฐฉ์งํ๊ณ ์ต์ ๋ชฉ๋ก์ ๊ฐ์ ธ์ค๊ธฐ ์ํด list_repo_files ํธ์ถ
|
| 20 |
files = api.list_repo_files(repo_id=REPO_ID, repo_type=REPO_TYPE)
|
| 21 |
samples = [f for f in files if f.startswith("LoRA_Samples/") and f.lower().endswith(('.png', '.jpg', '.jpeg'))]
|
| 22 |
-
|
| 23 |
-
# ํ์ผ๋ช
๊ธฐ์ค ์ ๋ ฌ ์คํ
|
| 24 |
samples.sort(key=lambda x: natural_sort_key(os.path.basename(x)), reverse=sort_desc)
|
| 25 |
return samples
|
| 26 |
except Exception as e:
|
|
@@ -28,20 +23,33 @@ def get_lora_samples(sort_desc=False):
|
|
| 28 |
return []
|
| 29 |
|
| 30 |
def update_gallery_data(sort_desc=False):
|
| 31 |
-
"""๋ฒํผ ํด๋ฆญ ์ ๊ฐค๋ฌ๋ฆฌ ๋ฐ์ดํฐ์ ์ํ ๊ฐ์ ๋์ ์ผ๋ก ๊ฐฑ์ ํ๊ธฐ ์ํ ๋ํผ ํจ์"""
|
| 32 |
paths = get_lora_samples(sort_desc=sort_desc)
|
| 33 |
gallery_val = [(hf_hub_url(repo_id=REPO_ID, repo_type=REPO_TYPE, filename=p), os.path.splitext(os.path.basename(p))[0]) for p in paths]
|
| 34 |
return gallery_val, paths
|
| 35 |
|
| 36 |
def generate_download_links(image_path):
|
| 37 |
if not image_path:
|
| 38 |
-
return "<div style='color: #94a3b8; text-align: center; margin-top:
|
| 39 |
|
| 40 |
filename = os.path.splitext(os.path.basename(image_path))[0]
|
|
|
|
| 41 |
target_folders = ["Qwen2509", "Qwen2512", "Zit"]
|
| 42 |
|
| 43 |
-
|
| 44 |
-
html_output
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 45 |
|
| 46 |
all_files = api.list_repo_files(repo_id=REPO_ID, repo_type=REPO_TYPE)
|
| 47 |
|
|
@@ -55,7 +63,12 @@ def generate_download_links(image_path):
|
|
| 55 |
else:
|
| 56 |
html_output += f"<tr><td><b>{folder}</b></td><td style='color: #ef4444;'>ํ์ผ ์์</td></tr>"
|
| 57 |
|
| 58 |
-
html_output += "
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 59 |
return html_output
|
| 60 |
|
| 61 |
# --- ์คํ์ผ์ํธ ---
|
|
@@ -63,18 +76,16 @@ custom_css = """
|
|
| 63 |
body, .gradio-container { background-color: #f4f6f9 !important; font-family: sans-serif !important; }
|
| 64 |
#lora-gallery { background: transparent !important; border: none !important; box-shadow: none !important; }
|
| 65 |
#lora-gallery .gallery-item { background: #ffffff !important; border-radius: 12px !important; border: 1px solid #e2e8f0 !important; padding: 14px !important; }
|
| 66 |
-
#info-panel { background: #ffffff !important; border-radius: 16px !important; border: 1px solid #e2e8f0 !important; padding: 24px !important; min-height:
|
| 67 |
.download-table { width: 100%; border-collapse: separate; border-spacing: 0; margin-top: 15px; border-radius: 8px; overflow: hidden; border: 1px solid #e2e8f0; }
|
| 68 |
.download-table th { background-color: #f8fafc; color: #64748b; padding: 12px 16px; font-size: 14px; border-bottom: 1px solid #e2e8f0; }
|
| 69 |
.download-table td { padding: 14px 16px; font-size: 14px; border-bottom: 1px solid #e2e8f0; color: #334155; }
|
| 70 |
.btn-download { color: #2563eb !important; font-weight: 600; text-decoration: none; }
|
| 71 |
.btn-download:hover { text-decoration: underline; }
|
| 72 |
-
/* ๋ฒํผ ์คํ์ผ ์ปค์คํ
*/
|
| 73 |
.nav-btn { font-weight: 600 !important; background: #ffffff !important; border: 1px solid #e2e8f0 !important; border-radius: 8px !important; }
|
| 74 |
"""
|
| 75 |
|
| 76 |
with ui.Blocks(css=custom_css) as demo:
|
| 77 |
-
# ํ์ดํ ์์ญ๊ณผ ์ฐ์ธก ๋ฒํผ ๋จ์ถ ๋ผ์ธ์ ์ผ๋ ฌ ๋ฐฐ์นํ๊ธฐ ์ํ ์๋จ ํด๋ฐ ๊ตฌ์ฑ
|
| 78 |
with ui.Row():
|
| 79 |
ui.Markdown("# โจ mymuse LoRA Management Center")
|
| 80 |
with ui.Row(elem_id="action-bar"):
|
|
@@ -85,7 +96,6 @@ with ui.Blocks(css=custom_css) as demo:
|
|
| 85 |
with ui.Row():
|
| 86 |
# ์ผ์ชฝ ๊ทธ๋ฆฌ๋ ์์ญ
|
| 87 |
with ui.Column(scale=2):
|
| 88 |
-
# ์ด๊ธฐ ๋ฐ์ดํฐ ๋ก๋ (์ค๋ฆ์ฐจ์)
|
| 89 |
initial_paths = get_lora_samples(sort_desc=False)
|
| 90 |
initial_gallery = [(hf_hub_url(repo_id=REPO_ID, repo_type=REPO_TYPE, filename=p), os.path.splitext(os.path.basename(p))[0]) for p in initial_paths]
|
| 91 |
|
|
@@ -98,34 +108,29 @@ with ui.Blocks(css=custom_css) as demo:
|
|
| 98 |
show_label=False,
|
| 99 |
elem_id="lora-gallery"
|
| 100 |
)
|
| 101 |
-
# ํ์ฌ ์ ๋ ฌ๋ ํ์ผ ๊ฒฝ๋ก๋ค์ ๋ค๊ณ ์๋ ์ํ ๋ณ์
|
| 102 |
paths_holder = ui.State(value=initial_paths)
|
| 103 |
|
| 104 |
-
# ์ค๋ฅธ์ชฝ ์ ๋ณด ์ถ๋ ฅ ์์ญ
|
| 105 |
with ui.Column(scale=1):
|
| 106 |
with ui.HTML(elem_id="info-panel") as output_area:
|
| 107 |
-
output_area.value = "<div style='color: #94a3b8; text-align: center; margin-top:
|
| 108 |
|
| 109 |
-
# --- ์ด๋ฒคํธ
|
| 110 |
-
|
| 111 |
-
# 1. ์ค๋ฆ์ฐจ์ ๋ฒํผ ํด๋ฆญ ์
|
| 112 |
btn_asc.click(
|
| 113 |
fn=lambda: update_gallery_data(sort_desc=False),
|
| 114 |
inputs=[],
|
| 115 |
outputs=[gallery, paths_holder]
|
| 116 |
)
|
| 117 |
|
| 118 |
-
# 2. ๋ด๋ฆผ์ฐจ์ ๋ฒํผ ํด๋ฆญ ์
|
| 119 |
btn_desc.click(
|
| 120 |
fn=lambda: update_gallery_data(sort_desc=True),
|
| 121 |
inputs=[],
|
| 122 |
outputs=[gallery, paths_holder]
|
| 123 |
)
|
| 124 |
|
| 125 |
-
# 3. ์๋ก๊ณ ์นจ ๋ฒํผ ํด๋ฆญ ์ (๊ธฐ๋ณธ ์ค๋ฆ์ฐจ์ ๊ฐฑ์ ๋ฐ ์ฐ์ธก ํจ๋ ์ด๊ธฐํ)
|
| 126 |
def refresh_all():
|
| 127 |
gallery_val, paths = update_gallery_data(sort_desc=False)
|
| 128 |
-
reset_html = "<div style='color: #94a3b8; text-align: center; margin-top:
|
| 129 |
return gallery_val, paths, reset_html
|
| 130 |
|
| 131 |
btn_refresh.click(
|
|
@@ -134,7 +139,6 @@ with ui.Blocks(css=custom_css) as demo:
|
|
| 134 |
outputs=[gallery, paths_holder, output_area]
|
| 135 |
)
|
| 136 |
|
| 137 |
-
# 4. ์นด๋ ์ ํ ์ด๋ฒคํธ
|
| 138 |
def on_select(evt: ui.SelectData, paths):
|
| 139 |
return generate_download_links(paths[evt.index])
|
| 140 |
|
|
|
|
| 9 |
|
| 10 |
api = HfApi(token=HF_TOKEN)
|
| 11 |
|
|
|
|
| 12 |
def natural_sort_key(s):
|
| 13 |
return [int(text) if text.isdigit() else text.lower() for text in re.split(r'(\d+)', s)]
|
| 14 |
|
| 15 |
def get_lora_samples(sort_desc=False):
|
|
|
|
| 16 |
try:
|
|
|
|
| 17 |
files = api.list_repo_files(repo_id=REPO_ID, repo_type=REPO_TYPE)
|
| 18 |
samples = [f for f in files if f.startswith("LoRA_Samples/") and f.lower().endswith(('.png', '.jpg', '.jpeg'))]
|
|
|
|
|
|
|
| 19 |
samples.sort(key=lambda x: natural_sort_key(os.path.basename(x)), reverse=sort_desc)
|
| 20 |
return samples
|
| 21 |
except Exception as e:
|
|
|
|
| 23 |
return []
|
| 24 |
|
| 25 |
def update_gallery_data(sort_desc=False):
|
|
|
|
| 26 |
paths = get_lora_samples(sort_desc=sort_desc)
|
| 27 |
gallery_val = [(hf_hub_url(repo_id=REPO_ID, repo_type=REPO_TYPE, filename=p), os.path.splitext(os.path.basename(p))[0]) for p in paths]
|
| 28 |
return gallery_val, paths
|
| 29 |
|
| 30 |
def generate_download_links(image_path):
|
| 31 |
if not image_path:
|
| 32 |
+
return "<div style='color: #94a3b8; text-align: center; margin-top: 140px; font-size: 15px;'>์ผ์ชฝ ๋ชฉ๋ก์์ ๋ก๋ผ ์นด๋๋ฅผ ํด๋ฆญํ๋ฉด<br>๋ฒ์ ๋ณ ์ํ ์ ๋ณด ๋ฐ ๋ค์ด๋ก๋ ์ฐฝ์ด ํ์ฑํ๋ฉ๋๋ค.</div>"
|
| 33 |
|
| 34 |
filename = os.path.splitext(os.path.basename(image_path))[0]
|
| 35 |
+
img_url = hf_hub_url(repo_id=REPO_ID, repo_type=REPO_TYPE, filename=image_path)
|
| 36 |
target_folders = ["Qwen2509", "Qwen2512", "Zit"]
|
| 37 |
|
| 38 |
+
# 1. ์๋จ ์ด๋ฏธ์ง ๋ฐฐ์น ๋ฐ 2. ํ๋จ ํ
์คํธ ๋ด์ฉ ์ ๊ธฐ์ ๊ฒฐํฉ (HTML ๋ ์ด์์)
|
| 39 |
+
html_output = f"""
|
| 40 |
+
<div style='display: flex; flex-direction: column; align-items: center; gap: 20px;'>
|
| 41 |
+
<div style='width: 100%; max-width: 280px; aspect-ratio: 3/4; overflow: hidden; border-radius: 8px; box-shadow: 0 2px 8px rgba(0,0,0,0.1);'>
|
| 42 |
+
<img src='{img_url}' style='width: 100%; height: 100%; object-fit: cover;' alt='{filename} preview'/>
|
| 43 |
+
</div>
|
| 44 |
+
|
| 45 |
+
<div style='width: 100%;'>
|
| 46 |
+
<h3 style='margin: 10px 0 5px 0; font-size: 18px; color: #1e293b; display: flex; align-items: center; gap: 6px;'>๐ฆ {filename} LoRA ๋ค์ด๋ก๋ ๋งํฌ</h3>
|
| 47 |
+
<table class='download-table'>
|
| 48 |
+
<thead>
|
| 49 |
+
<tr><th>๋ฒ์ / ํด๋</th><th>๋ค์ด๋ก๋ ๋งํฌ</th></tr>
|
| 50 |
+
</thead>
|
| 51 |
+
<tbody>
|
| 52 |
+
"""
|
| 53 |
|
| 54 |
all_files = api.list_repo_files(repo_id=REPO_ID, repo_type=REPO_TYPE)
|
| 55 |
|
|
|
|
| 63 |
else:
|
| 64 |
html_output += f"<tr><td><b>{folder}</b></td><td style='color: #ef4444;'>ํ์ผ ์์</td></tr>"
|
| 65 |
|
| 66 |
+
html_output += """
|
| 67 |
+
</tbody>
|
| 68 |
+
</table>
|
| 69 |
+
</div>
|
| 70 |
+
</div>
|
| 71 |
+
"""
|
| 72 |
return html_output
|
| 73 |
|
| 74 |
# --- ์คํ์ผ์ํธ ---
|
|
|
|
| 76 |
body, .gradio-container { background-color: #f4f6f9 !important; font-family: sans-serif !important; }
|
| 77 |
#lora-gallery { background: transparent !important; border: none !important; box-shadow: none !important; }
|
| 78 |
#lora-gallery .gallery-item { background: #ffffff !important; border-radius: 12px !important; border: 1px solid #e2e8f0 !important; padding: 14px !important; }
|
| 79 |
+
#info-panel { background: #ffffff !important; border-radius: 16px !important; border: 1px solid #e2e8f0 !important; padding: 24px !important; min-height: 500px; }
|
| 80 |
.download-table { width: 100%; border-collapse: separate; border-spacing: 0; margin-top: 15px; border-radius: 8px; overflow: hidden; border: 1px solid #e2e8f0; }
|
| 81 |
.download-table th { background-color: #f8fafc; color: #64748b; padding: 12px 16px; font-size: 14px; border-bottom: 1px solid #e2e8f0; }
|
| 82 |
.download-table td { padding: 14px 16px; font-size: 14px; border-bottom: 1px solid #e2e8f0; color: #334155; }
|
| 83 |
.btn-download { color: #2563eb !important; font-weight: 600; text-decoration: none; }
|
| 84 |
.btn-download:hover { text-decoration: underline; }
|
|
|
|
| 85 |
.nav-btn { font-weight: 600 !important; background: #ffffff !important; border: 1px solid #e2e8f0 !important; border-radius: 8px !important; }
|
| 86 |
"""
|
| 87 |
|
| 88 |
with ui.Blocks(css=custom_css) as demo:
|
|
|
|
| 89 |
with ui.Row():
|
| 90 |
ui.Markdown("# โจ mymuse LoRA Management Center")
|
| 91 |
with ui.Row(elem_id="action-bar"):
|
|
|
|
| 96 |
with ui.Row():
|
| 97 |
# ์ผ์ชฝ ๊ทธ๋ฆฌ๋ ์์ญ
|
| 98 |
with ui.Column(scale=2):
|
|
|
|
| 99 |
initial_paths = get_lora_samples(sort_desc=False)
|
| 100 |
initial_gallery = [(hf_hub_url(repo_id=REPO_ID, repo_type=REPO_TYPE, filename=p), os.path.splitext(os.path.basename(p))[0]) for p in initial_paths]
|
| 101 |
|
|
|
|
| 108 |
show_label=False,
|
| 109 |
elem_id="lora-gallery"
|
| 110 |
)
|
|
|
|
| 111 |
paths_holder = ui.State(value=initial_paths)
|
| 112 |
|
| 113 |
+
# ์ค๋ฅธ์ชฝ ์ ๋ณด ์ถ๋ ฅ ์์ญ (์๋จ ์ด๋ฏธ์ง + ํ๋จ ์ ๋ณด ๊ตฌ์กฐ ๋ฐ์)
|
| 114 |
with ui.Column(scale=1):
|
| 115 |
with ui.HTML(elem_id="info-panel") as output_area:
|
| 116 |
+
output_area.value = "<div style='color: #94a3b8; text-align: center; margin-top: 180px; font-size: 15px;'>์ผ์ชฝ ๋ชฉ๋ก์์ ๋ก๋ผ ์นด๋๋ฅผ ํด๋ฆญํ๋ฉด<br>๋ฒ์ ๋ณ ์ํ ์ ๋ณด ๋ฐ ๋ค์ด๋ก๋ ์ฐฝ์ด ํ์ฑํ๋ฉ๋๋ค.</div>"
|
| 117 |
|
| 118 |
+
# --- ์ด๋ฒคํธ ํธ๋ค๋ง ---
|
|
|
|
|
|
|
| 119 |
btn_asc.click(
|
| 120 |
fn=lambda: update_gallery_data(sort_desc=False),
|
| 121 |
inputs=[],
|
| 122 |
outputs=[gallery, paths_holder]
|
| 123 |
)
|
| 124 |
|
|
|
|
| 125 |
btn_desc.click(
|
| 126 |
fn=lambda: update_gallery_data(sort_desc=True),
|
| 127 |
inputs=[],
|
| 128 |
outputs=[gallery, paths_holder]
|
| 129 |
)
|
| 130 |
|
|
|
|
| 131 |
def refresh_all():
|
| 132 |
gallery_val, paths = update_gallery_data(sort_desc=False)
|
| 133 |
+
reset_html = "<div style='color: #94a3b8; text-align: center; margin-top: 180px; font-size: 15px;'>์ผ์ชฝ ๋ชฉ๋ก์์ ๋ก๋ผ ์นด๋๋ฅผ ํด๋ฆญํ๋ฉด<br>๋ฒ์ ๋ณ ์ํ ์ ๋ณด ๋ฐ ๋ค์ด๋ก๋ ์ฐฝ์ด ํ์ฑํ๋ฉ๋๋ค.</div>"
|
| 134 |
return gallery_val, paths, reset_html
|
| 135 |
|
| 136 |
btn_refresh.click(
|
|
|
|
| 139 |
outputs=[gallery, paths_holder, output_area]
|
| 140 |
)
|
| 141 |
|
|
|
|
| 142 |
def on_select(evt: ui.SelectData, paths):
|
| 143 |
return generate_download_links(paths[evt.index])
|
| 144 |
|