Download app.py from Crocody/muse: direct link, hf CLI and curl.
- Browser
- Download file 7.49 kB
-
https://huggingface.co/spaces/Crocody/muse/resolve/main/app.py
- Command line
-
hf download hf://spaces/Crocody/muse/app.py
-
curl -L -o app.py https://huggingface.co/spaces/Crocody/muse/resolve/main/app.py
7.49 kB
| import os | |
| import re | |
| import gradio as ui | |
| import spaces # 1. ์ ๋กGPU ์ธ์์ ์ํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ถ๊ฐ | |
| from huggingface_hub import HfApi, hf_hub_url | |
| REPO_ID = "Crocody/mymuse" | |
| REPO_TYPE = "dataset" | |
| HF_TOKEN = os.getenv("HF_TOKEN") | |
| api = HfApi(token=HF_TOKEN) | |
| # 2. ์ ๋กGPU ์์ ์ค๋ฅ ๋ฐฉ์ง์ฉ ๋๋ฏธ ๋ฐ์ฝ๋ ์ดํฐ ํจ์ ์ถ๊ฐ | |
| def dummy_gpu_function(): | |
| pass | |
| def natural_sort_key(s): | |
| return [int(text) if text.isdigit() else text.lower() for text in re.split(r'(\d+)', s)] | |
| def get_lora_samples(sort_desc=False): | |
| try: | |
| files = api.list_repo_files(repo_id=REPO_ID, repo_type=REPO_TYPE) | |
| samples = [f for f in files if f.startswith("Muse/") and f.lower().endswith(('.png', '.jpg', '.jpeg'))] | |
| samples.sort(key=lambda x: natural_sort_key(os.path.basename(x)), reverse=sort_desc) | |
| return samples | |
| except Exception as e: | |
| print(f"ํ์ผ ๋ก๋ ์คํจ: {e}") | |
| return [] | |
| def update_gallery_data(sort_desc=False): | |
| paths = get_lora_samples(sort_desc=sort_desc) | |
| 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] | |
| return gallery_val, paths | |
| def generate_download_links(image_path): | |
| if not image_path: | |
| return "<div style='color: #94a3b8; text-align: center; margin-top: 140px; font-size: 15px;'>์ผ์ชฝ ๋ชฉ๋ก์์ ๋ก๋ผ ์นด๋๋ฅผ ํด๋ฆญํ๋ฉด<br>์ํ ์ ๋ณด ๋ฐ ๋ค์ด๋ก๋ ์ฐฝ์ด ํ์ฑํ๋ฉ๋๋ค.</div>" | |
| filename = os.path.splitext(os.path.basename(image_path))[0] | |
| img_url = hf_hub_url(repo_id=REPO_ID, repo_type=REPO_TYPE, filename=image_path) | |
| target_folders = ["Muse/Krea2"] | |
| # 1. ์๋จ ์ด๋ฏธ์ง ๋ฐฐ์น ๋ฐ 2. ํ๋จ ํ ์คํธ ๋ด์ฉ ์ ๊ธฐ์ ๊ฒฐํฉ (HTML ๋ ์ด์์) | |
| html_output = f""" | |
| <div style='display: flex; flex-direction: column; align-items: center; gap: 20px;'> | |
| <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);'> | |
| <img src='{img_url}' style='width: 100%; height: 100%; object-fit: cover;' alt='{filename} preview'/> | |
| </div> | |
| <div style='width: 100%;'> | |
| <h3 style='margin: 10px 0 5px 0; font-size: 18px; color: #1e293b; display: flex; align-items: center; gap: 6px;'>๐ฆ {filename} LoRA ๋ค์ด๋ก๋ ๋งํฌ</h3> | |
| <table class='download-table'> | |
| <thead> | |
| <tr><th>ํด๋ / ๋ชจ๋ธ</th><th>๋ค์ด๋ก๋ ๋งํฌ</th></tr> | |
| </thead> | |
| <tbody> | |
| """ | |
| all_files = api.list_repo_files(repo_id=REPO_ID, repo_type=REPO_TYPE) | |
| for folder in target_folders: | |
| target_file = f"{folder}/{filename}.safetensors" | |
| match = [f for f in all_files if f.lower() == target_file.lower()] | |
| if match: | |
| download_url = hf_hub_url(repo_id=REPO_ID, repo_type=REPO_TYPE, filename=match[0]) | |
| html_output += f"<tr><td><b>{folder}</b></td><td><a href='{download_url}' target='_blank' class='btn-download'>๋ค์ด๋ก๋ ({filename}.safetensors)</a></td></tr>" | |
| else: | |
| html_output += f"<tr><td><b>{folder}</b></td><td style='color: #ef4444;'>ํ์ผ ์์</td></tr>" | |
| html_output += """ | |
| </tbody> | |
| </table> | |
| </div> | |
| </div> | |
| """ | |
| return html_output | |
| # --- ์คํ์ผ์ํธ --- | |
| custom_css = """ | |
| body, .gradio-container { background-color: #f4f6f9 !important; font-family: sans-serif !important; } | |
| #lora-gallery { background: transparent !important; border: none !important; box-shadow: none !important; } | |
| #lora-gallery .gallery-item { background: #ffffff !important; border-radius: 12px !important; border: 1px solid #e2e8f0 !important; padding: 14px !important; } | |
| #info-panel { background: #ffffff !important; border-radius: 16px !important; border: 1px solid #e2e8f0 !important; padding: 24px !important; min-height: 500px; } | |
| .download-table { width: 100%; border-collapse: separate; border-spacing: 0; margin-top: 15px; border-radius: 8px; overflow: hidden; border: 1px solid #e2e8f0; } | |
| .download-table th { background-color: #f8fafc; color: #64748b; padding: 12px 16px; font-size: 14px; border-bottom: 1px solid #e2e8f0; } | |
| .download-table td { padding: 14px 16px; font-size: 14px; border-bottom: 1px solid #e2e8f0; color: #334155; } | |
| .btn-download { color: #2563eb !important; font-weight: 600; text-decoration: none; } | |
| .btn-download:hover { text-decoration: underline; } | |
| .nav-btn { font-weight: 600 !important; background: #ffffff !important; border: 1px solid #e2e8f0 !important; border-radius: 8px !important; } | |
| """ | |
| with ui.Blocks() as demo: | |
| with ui.Row(): | |
| ui.Markdown("# โจ muse LoRA Management Center") | |
| with ui.Row(elem_id="action-bar"): | |
| btn_asc = ui.Button("โฌ๏ธ ์ค๋ฆ์ฐจ์", elem_classes="nav-btn", scale=1) | |
| btn_desc = ui.Button("โฌ๏ธ ๋ด๋ฆผ์ฐจ์", elem_classes="nav-btn", scale=1) | |
| btn_refresh = ui.Button("๐ ์๋ก๊ณ ์นจ", elem_classes="nav-btn", scale=1) | |
| with ui.Row(): | |
| # ์ผ์ชฝ ๊ทธ๋ฆฌ๋ ์์ญ | |
| with ui.Column(scale=2): | |
| initial_paths = get_lora_samples(sort_desc=False) | |
| 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] | |
| gallery = ui.Gallery( | |
| value=initial_gallery, | |
| columns=4, | |
| object_fit="cover", | |
| height=750, | |
| allow_preview=False, | |
| show_label=False, | |
| elem_id="lora-gallery" | |
| ) | |
| paths_holder = ui.State(value=initial_paths) | |
| # ์ค๋ฅธ์ชฝ ์ ๋ณด ์ถ๋ ฅ ์์ญ (์๋จ ์ด๋ฏธ์ง + ํ๋จ ์ ๋ณด ๊ตฌ์กฐ ๋ฐ์) | |
| with ui.Column(scale=1): | |
| with ui.HTML(elem_id="info-panel") as output_area: | |
| output_area.value = "<div style='color: #94a3b8; text-align: center; margin-top: 180px; font-size: 15px;'>์ผ์ชฝ ๋ชฉ๋ก์์ ๋ก๋ผ ์นด๋๋ฅผ ํด๋ฆญํ๋ฉด<br>์ํ ์ ๋ณด ๋ฐ ๋ค์ด๋ก๋ ์ฐฝ์ด ํ์ฑํ๋ฉ๋๋ค.</div>" | |
| # --- ์ด๋ฒคํธ ํธ๋ค๋ง --- | |
| btn_asc.click( | |
| fn=lambda: update_gallery_data(sort_desc=False), | |
| inputs=[], | |
| outputs=[gallery, paths_holder] | |
| ) | |
| btn_desc.click( | |
| fn=lambda: update_gallery_data(sort_desc=True), | |
| inputs=[], | |
| outputs=[gallery, paths_holder] | |
| ) | |
| def refresh_all(): | |
| gallery_val, paths = update_gallery_data(sort_desc=False) | |
| reset_html = "<div style='color: #94a3b8; text-align: center; margin-top: 180px; font-size: 15px;'>์ผ์ชฝ ๋ชฉ๋ก์์ ๋ก๋ผ ์นด๋๋ฅผ ํด๋ฆญํ๋ฉด<br>์ํ ์ ๋ณด ๋ฐ ๋ค์ด๋ก๋ ์ฐฝ์ด ํ์ฑํ๋ฉ๋๋ค.</div>" | |
| return gallery_val, paths, reset_html | |
| btn_refresh.click( | |
| fn=refresh_all, | |
| inputs=[], | |
| outputs=[gallery, paths_holder, output_area] | |
| ) | |
| def on_select(evt: ui.SelectData, paths): | |
| return generate_download_links(paths[evt.index]) | |
| gallery.select(fn=on_select, inputs=[paths_holder], outputs=[output_area]) | |
| demo.launch( | |
| css=custom_css, | |
| show_error=True, | |
| server_name="0.0.0.0", | |
| server_port=7860, | |
| auth=None, | |
| root_path="" | |
| ) |