| """ |
| Gradio UI Components Module |
| Contains all Gradio interface component definitions and layouts |
| """ |
| import gradio as gr |
| from acestep.gradio_ui.i18n import get_i18n, t |
| from acestep.gradio_ui.interfaces.dataset import create_dataset_section |
| from acestep.gradio_ui.interfaces.generation import create_generation_section |
| from acestep.gradio_ui.interfaces.result import create_results_section |
| from acestep.gradio_ui.interfaces.training import create_training_section |
| from acestep.gradio_ui.events import setup_event_handlers, setup_training_event_handlers |
|
|
|
|
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| STUDIO_CSS = """ |
| @import url('https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;500;600;700&family=IBM+Plex+Mono:wght@400;500;600&family=Inter:wght@400;500;600&display=swap'); |
| |
| :root { |
| --studio-bg-0: #05060a; |
| --studio-bg-1: #0b0e17; |
| --studio-bg-2: #10141f; |
| --studio-panel: rgba(20, 24, 38, 0.62); |
| --studio-panel-border: rgba(148, 163, 255, 0.16); |
| --studio-line: rgba(255, 255, 255, 0.08); |
| --studio-text: #eef0ff; |
| --studio-text-dim: #9aa1c4; |
| --neon-a: #7c5cff; /* violet */ |
| --neon-b: #22d3ee; /* cyan */ |
| --neon-c: #ff5cb3; /* magenta */ |
| --neon-d: #34e89e; /* mint */ |
| --studio-radius: 16px; |
| --studio-shadow: 0 8px 32px rgba(0, 0, 0, 0.45); |
| } |
| |
| /* ---------- Base canvas ---------- */ |
| .gradio-container { |
| font-family: 'Inter', 'Space Grotesk', system-ui, sans-serif !important; |
| max-width: 1400px !important; |
| background: |
| radial-gradient(ellipse 60% 45% at 12% -10%, rgba(124, 92, 255, 0.28), transparent 60%), |
| radial-gradient(ellipse 55% 40% at 100% 0%, rgba(34, 211, 238, 0.20), transparent 60%), |
| radial-gradient(ellipse 70% 50% at 50% 110%, rgba(255, 92, 179, 0.14), transparent 60%), |
| linear-gradient(180deg, var(--studio-bg-0) 0%, var(--studio-bg-1) 45%, var(--studio-bg-2) 100%) !important; |
| background-attachment: fixed !important; |
| color: var(--studio-text) !important; |
| position: relative; |
| } |
| |
| /* faint animated scan-grid over everything, purely decorative */ |
| .gradio-container::before { |
| content: ""; |
| position: fixed; |
| inset: 0; |
| pointer-events: none; |
| z-index: 0; |
| background-image: |
| linear-gradient(rgba(148, 163, 255, 0.045) 1px, transparent 1px), |
| linear-gradient(90deg, rgba(148, 163, 255, 0.045) 1px, transparent 1px); |
| background-size: 42px 42px; |
| mask-image: radial-gradient(ellipse 80% 60% at 50% 0%, black 10%, transparent 75%); |
| animation: studio-grid-drift 26s linear infinite; |
| } |
| @keyframes studio-grid-drift { |
| 0% { background-position: 0 0, 0 0; } |
| 100% { background-position: 84px 84px, 84px 84px; } |
| } |
| |
| body, .gradio-container, .dark { color-scheme: dark !important; } |
| |
| /* ---------- Typography ---------- */ |
| .gradio-container h1, .gradio-container h2, .gradio-container h3, .gradio-container h4 { |
| font-family: 'Space Grotesk', sans-serif !important; |
| letter-spacing: 0.2px; |
| } |
| .gradio-container h3, .gradio-container h4 { |
| color: var(--studio-text) !important; |
| position: relative; |
| padding-left: 14px; |
| margin: 18px 0 10px 0 !important; |
| } |
| .gradio-container h3::before, .gradio-container h4::before { |
| content: ""; |
| position: absolute; |
| left: 0; top: 4px; bottom: 4px; |
| width: 4px; |
| border-radius: 3px; |
| background: linear-gradient(180deg, var(--neon-a), var(--neon-b)); |
| box-shadow: 0 0 10px rgba(124, 92, 255, 0.6); |
| } |
| .gradio-container hr { |
| border: none; |
| height: 1px; |
| margin: 22px 0; |
| background: linear-gradient(90deg, transparent, var(--neon-a) 20%, var(--neon-b) 50%, var(--neon-c) 80%, transparent); |
| opacity: 0.55; |
| } |
| |
| /* ---------- Hero ---------- */ |
| .studio-hero { |
| position: relative; |
| z-index: 1; |
| text-align: center; |
| padding: 40px 24px 28px 24px; |
| margin-bottom: 22px; |
| } |
| .studio-hero-badge { |
| display: inline-flex; |
| align-items: center; |
| gap: 8px; |
| padding: 6px 16px; |
| border-radius: 999px; |
| background: rgba(124, 92, 255, 0.12); |
| border: 1px solid rgba(124, 92, 255, 0.4); |
| color: #cfd3ff; |
| font-size: 12.5px; |
| font-weight: 600; |
| letter-spacing: 0.6px; |
| text-transform: uppercase; |
| margin-bottom: 18px; |
| } |
| .studio-hero-badge .dot { |
| width: 7px; height: 7px; border-radius: 50%; |
| background: var(--neon-d); |
| box-shadow: 0 0 8px var(--neon-d), 0 0 16px var(--neon-d); |
| animation: studio-pulse 1.6s ease-in-out infinite; |
| } |
| @keyframes studio-pulse { |
| 0%, 100% { opacity: 1; transform: scale(1); } |
| 50% { opacity: 0.4; transform: scale(0.75); } |
| } |
| .studio-hero h1.studio-title { |
| font-size: clamp(34px, 5.2vw, 58px) !important; |
| font-weight: 700 !important; |
| margin: 0 0 10px 0 !important; |
| line-height: 1.08; |
| background: linear-gradient(100deg, #ffffff 0%, var(--neon-b) 35%, var(--neon-a) 65%, var(--neon-c) 100%); |
| background-size: 200% auto; |
| -webkit-background-clip: text; |
| background-clip: text; |
| -webkit-text-fill-color: transparent; |
| animation: studio-shimmer 7s ease-in-out infinite; |
| } |
| @keyframes studio-shimmer { |
| 0%, 100% { background-position: 0% center; } |
| 50% { background-position: 100% center; } |
| } |
| .studio-hero p.studio-subtitle { |
| font-size: 16.5px; |
| color: var(--studio-text-dim); |
| max-width: 620px; |
| margin: 0 auto 22px auto; |
| font-weight: 500; |
| } |
| .studio-cta { |
| background: linear-gradient(120deg, rgba(124,92,255,0.22), rgba(34,211,238,0.18)); |
| border: 1px solid rgba(124, 92, 255, 0.45); |
| padding: 12px 22px; |
| border-radius: 14px; |
| display: inline-block; |
| margin: 4px auto 20px auto; |
| box-shadow: 0 0 24px rgba(124, 92, 255, 0.18); |
| } |
| .studio-cta span { color: #f1f2ff; font-size: 14.5px; } |
| .studio-cta a { |
| color: var(--neon-b) !important; |
| font-weight: 700; |
| text-decoration: none; |
| border-bottom: 1px dashed var(--neon-b); |
| } |
| |
| .studio-links { display: flex; flex-wrap: wrap; justify-content: center; gap: 10px; margin: 4px 0 26px 0; } |
| .studio-links a { |
| color: var(--studio-text) !important; |
| text-decoration: none !important; |
| font-size: 13px; |
| font-weight: 600; |
| padding: 8px 16px; |
| border-radius: 999px; |
| background: var(--studio-panel); |
| border: 1px solid var(--studio-panel-border); |
| transition: all 0.25s ease; |
| } |
| .studio-links a:hover { |
| border-color: var(--neon-b); |
| color: #fff !important; |
| box-shadow: 0 0 16px rgba(34, 211, 238, 0.35); |
| transform: translateY(-2px); |
| } |
| |
| .studio-feature-grid { |
| display: grid; |
| grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); |
| gap: 14px; |
| max-width: 1100px; |
| margin: 6px auto 0 auto; |
| } |
| .studio-feature-card { |
| background: var(--studio-panel); |
| border: 1px solid var(--studio-panel-border); |
| border-radius: var(--studio-radius); |
| padding: 18px 16px; |
| text-align: left; |
| backdrop-filter: blur(10px); |
| transition: transform 0.25s ease, border-color 0.25s ease, box-shadow 0.25s ease; |
| } |
| .studio-feature-card:hover { |
| transform: translateY(-4px); |
| border-color: rgba(124, 92, 255, 0.55); |
| box-shadow: var(--studio-shadow); |
| } |
| .studio-feature-icon { font-size: 22px; margin-bottom: 8px; display: block; } |
| .studio-feature-card b { color: #fff; font-size: 14.5px; display: block; margin-bottom: 4px; } |
| .studio-feature-card span { color: var(--studio-text-dim); font-size: 12.5px; line-height: 1.4; } |
| |
| /* ---------- Minimal in-app top bar ---------- */ |
| .studio-topbar { |
| display: flex; |
| align-items: center; |
| gap: 14px; |
| padding: 10px 4px 18px 4px; |
| margin-bottom: 6px; |
| border-bottom: 1px solid var(--studio-line); |
| } |
| .studio-back { |
| color: var(--studio-text-dim) !important; |
| text-decoration: none !important; |
| font-size: 13px; |
| font-weight: 600; |
| padding: 6px 14px; |
| border-radius: 999px; |
| border: 1px solid var(--studio-panel-border); |
| background: var(--studio-panel); |
| transition: all 0.2s ease; |
| } |
| .studio-back:hover { color: #fff !important; border-color: var(--neon-b); } |
| .studio-topbar-title { |
| font-family: 'Space Grotesk', sans-serif; |
| font-weight: 700; |
| font-size: 15px; |
| color: var(--studio-text); |
| opacity: 0.85; |
| } |
| |
| /* ===================================================================== |
| LANDING PAGE β a distinct "front door" screen shown before the studio. |
| Console / mixing-desk identity: warm near-black, amber + teal, an |
| animated EQ meter as the signature element, and channel-strip cards |
| that describe what the tool actually does. |
| ===================================================================== */ |
| #landing-page.block, #landing-page { |
| background: transparent !important; |
| border: none !important; |
| box-shadow: none !important; |
| backdrop-filter: none !important; |
| padding: 0 !important; |
| } |
| .landing-wrap { |
| position: relative; |
| background: |
| radial-gradient(ellipse 70% 45% at 50% -10%, rgba(255, 180, 84, 0.12), transparent 60%), |
| radial-gradient(ellipse 60% 40% at 90% 5%, rgba(43, 217, 185, 0.09), transparent 60%), |
| linear-gradient(180deg, #0c0a08 0%, #141110 100%); |
| border: 1px solid rgba(243, 237, 228, 0.08); |
| border-radius: 22px; |
| padding: 56px 32px 8px 32px; |
| text-align: center; |
| overflow: hidden; |
| } |
| .landing-eyebrow { |
| font-family: 'IBM Plex Mono', monospace; |
| font-size: 12.5px; letter-spacing: 1.6px; text-transform: uppercase; |
| color: #2bd9b9; display: inline-flex; align-items: center; gap: 10px; margin-bottom: 22px; |
| } |
| .landing-eyebrow::before, .landing-eyebrow::after { content: ""; width: 26px; height: 1px; background: #1c6d5e; } |
| .landing-title { |
| font-family: 'Space Grotesk', sans-serif; font-weight: 700; |
| font-size: clamp(32px, 5.4vw, 56px); line-height: 1.06; margin: 0 0 16px 0; |
| color: #f3ede4; letter-spacing: -0.5px; |
| } |
| .landing-title .accent { color: #ffb454; } |
| .landing-tagline { font-size: 16.5px; color: #a99f8e; max-width: 560px; margin: 0 auto 30px auto; line-height: 1.55; } |
| .landing-eq { display: flex; align-items: flex-end; justify-content: center; gap: 5px; height: 52px; margin: 0 auto 6px auto; } |
| .landing-eq span { |
| width: 5px; border-radius: 3px; |
| background: linear-gradient(180deg, #ffb454, #2bd9b9); |
| animation: landing-eqbounce 1.2s ease-in-out infinite; |
| opacity: 0.85; |
| } |
| @keyframes landing-eqbounce { 0%, 100% { height: 10%; } 50% { height: 100%; } } |
| |
| /* the "Enter Studio" call to action is a REAL Gradio button (so Python can react to it), |
| styled here to look like part of the console rather than a default Gradio button */ |
| #enter-studio-btn { max-width: 300px; margin: 8px auto 6px auto !important; } |
| #enter-studio-btn button { |
| background: linear-gradient(120deg, #ffb454, #ffcd82) !important; |
| color: #1a1208 !important; |
| font-family: 'Space Grotesk', sans-serif !important; |
| font-weight: 700 !important; |
| font-size: 16px !important; |
| border-radius: 11px !important; |
| padding: 14px 10px !important; |
| border: none !important; |
| box-shadow: 0 10px 30px rgba(255, 180, 84, 0.22) !important; |
| transition: transform 0.15s ease, box-shadow 0.15s ease; |
| } |
| #enter-studio-btn button:hover { transform: translateY(-2px); box-shadow: 0 14px 36px rgba(255, 180, 84, 0.32) !important; } |
| |
| .landing-note { margin: 10px 0 0 0; font-size: 12.5px; color: #6f6558; font-family: 'IBM Plex Mono', monospace; } |
| .landing-note a { color: #2bd9b9; text-decoration: none; border-bottom: 1px dashed #1c6d5e; } |
| |
| .landing-rack { |
| display: grid; grid-template-columns: repeat(4, 1fr); gap: 2px; |
| background: rgba(243, 237, 228, 0.08); border: 1px solid rgba(243, 237, 228, 0.08); |
| border-radius: 16px; overflow: hidden; margin: 34px 0 26px 0; |
| } |
| .landing-strip { background: #1b1714; padding: 24px 18px; display: flex; flex-direction: column; gap: 12px; min-height: 195px; text-align: left; transition: background 0.25s ease; } |
| .landing-strip:hover { background: #211c18; } |
| .landing-strip .ch-num { font-family: 'IBM Plex Mono', monospace; font-size: 11px; color: #6f6558; letter-spacing: 1px; } |
| .landing-strip .ch-icon { font-size: 20px; } |
| .landing-strip h4 { font-family: 'Space Grotesk', sans-serif; font-size: 14.5px; margin: 0; color: #f3ede4; font-weight: 600; padding-left: 0 !important; } |
| .landing-strip h4::before { display: none !important; } |
| .landing-strip p { font-size: 12.5px; color: #a99f8e; line-height: 1.5; margin: 0; } |
| .landing-fader { height: 3px; background: rgba(243, 237, 228, 0.16); border-radius: 2px; position: relative; margin-top: auto; } |
| .landing-fader i { position: absolute; top: 50%; width: 10px; height: 10px; border-radius: 50%; background: #ffb454; transform: translate(-50%, -50%); box-shadow: 0 0 10px rgba(255, 180, 84, 0.5); } |
| |
| .landing-footer { |
| display: flex; align-items: center; justify-content: center; gap: 18px; flex-wrap: wrap; |
| padding: 22px 0 30px 0; font-size: 12px; font-family: 'IBM Plex Mono', monospace; color: #6f6558; |
| } |
| .landing-footer a { text-decoration: none; color: #6f6558; transition: color 0.2s ease; } |
| .landing-footer a:hover { color: #ffb454; } |
| |
| #studio-back-btn button { |
| background: var(--studio-panel) !important; |
| border: 1px solid var(--studio-panel-border) !important; |
| color: var(--studio-text-dim) !important; |
| font-size: 13px !important; |
| font-weight: 600 !important; |
| border-radius: 999px !important; |
| box-shadow: none !important; |
| } |
| #studio-back-btn button:hover { color: #fff !important; border-color: var(--neon-b) !important; } |
| |
| @media (max-width: 860px) { .landing-rack { grid-template-columns: repeat(2, 1fr); } } |
| @media (max-width: 520px) { .landing-rack { grid-template-columns: 1fr; } .landing-wrap { padding: 40px 18px 4px 18px; } } |
| |
| /* legacy hooks kept so nothing that references them elsewhere breaks */ |
| .main-header { text-align: center; margin-bottom: 0.5rem; } |
| .section-header { |
| background: linear-gradient(90deg, var(--neon-a), var(--neon-b)); |
| color: #06070d; |
| font-weight: 700; |
| padding: 10px 14px; |
| border-radius: 10px; |
| margin: 10px 0; |
| box-shadow: 0 4px 18px rgba(124, 92, 255, 0.3); |
| } |
| |
| /* ---------- Panels / groups / accordions ---------- */ |
| .gradio-container .block, .gradio-container .form, .gradio-container .gr-group, .gradio-container fieldset { |
| background: var(--studio-panel) !important; |
| border: 1px solid var(--studio-panel-border) !important; |
| border-radius: var(--studio-radius) !important; |
| backdrop-filter: blur(10px); |
| } |
| .gradio-container .tabitem { border: none !important; background: transparent !important; } |
| .gradio-container .tab-nav { |
| border: none !important; |
| gap: 6px; |
| background: rgba(255,255,255,0.03); |
| padding: 6px; |
| border-radius: 14px; |
| } |
| .gradio-container .tab-nav button { |
| border-radius: 10px !important; |
| border: 1px solid transparent !important; |
| color: var(--studio-text-dim) !important; |
| font-weight: 600 !important; |
| transition: all 0.2s ease; |
| } |
| .gradio-container .tab-nav button.selected { |
| background: linear-gradient(120deg, rgba(124,92,255,0.28), rgba(34,211,238,0.2)) !important; |
| color: #fff !important; |
| border-color: rgba(124, 92, 255, 0.5) !important; |
| box-shadow: 0 0 14px rgba(124, 92, 255, 0.25); |
| } |
| |
| /* ---------- Buttons ---------- */ |
| .gradio-container button.primary, .gradio-container .primary { |
| background: linear-gradient(120deg, var(--neon-a), var(--neon-b)) !important; |
| border: none !important; |
| color: #06070d !important; |
| font-weight: 700 !important; |
| box-shadow: 0 4px 20px rgba(124, 92, 255, 0.35); |
| transition: transform 0.15s ease, box-shadow 0.15s ease; |
| } |
| .gradio-container button.primary:hover { transform: translateY(-1px); box-shadow: 0 6px 26px rgba(34, 211, 238, 0.45); } |
| .gradio-container button.secondary { |
| background: rgba(255,255,255,0.05) !important; |
| border: 1px solid var(--studio-panel-border) !important; |
| color: var(--studio-text) !important; |
| } |
| .gradio-container button.secondary:hover { border-color: var(--neon-b) !important; color: #fff !important; } |
| |
| /* ---------- Inputs / sliders / dataframe / audio ---------- */ |
| .gradio-container input, .gradio-container textarea, .gradio-container select { |
| background: rgba(0,0,0,0.28) !important; |
| border: 1px solid var(--studio-panel-border) !important; |
| color: var(--studio-text) !important; |
| border-radius: 10px !important; |
| } |
| .gradio-container input:focus, .gradio-container textarea:focus { |
| border-color: var(--neon-b) !important; |
| box-shadow: 0 0 0 3px rgba(34, 211, 238, 0.18) !important; |
| } |
| .gradio-container input[type=range] { accent-color: var(--neon-a); } |
| .gradio-container .wrap.svelte-1cl284s, .gradio-container table { |
| background: rgba(0,0,0,0.18) !important; |
| border-radius: 12px !important; |
| } |
| .gradio-container audio, .gradio-container video { |
| border-radius: 12px !important; |
| border: 1px solid var(--studio-panel-border) !important; |
| } |
| |
| /* scrollbars */ |
| .gradio-container ::-webkit-scrollbar { width: 9px; height: 9px; } |
| .gradio-container ::-webkit-scrollbar-thumb { |
| background: linear-gradient(180deg, var(--neon-a), var(--neon-b)); |
| border-radius: 6px; |
| } |
| .gradio-container ::-webkit-scrollbar-track { background: rgba(255,255,255,0.03); } |
| |
| .lm-hints-row { align-items: stretch; } |
| .lm-hints-col { display: flex; } |
| .lm-hints-col > div { flex: 1; display: flex; } |
| .lm-hints-btn button { height: 100%; width: 100%; } |
| |
| @media (max-width: 640px) { |
| .studio-feature-grid { grid-template-columns: 1fr; } |
| } |
| """ |
|
|
|
|
| def build_landing_hero_html(title: str) -> str: |
| """Top half of the landing screen: eyebrow, title, tagline, animated EQ meter.""" |
| delays = [0.0, 0.15, 0.3, 0.1, 0.45, 0.25, 0.55, 0.05, 0.35, 0.2, 0.5, 0.4] |
| bars = "".join(f'<span style="animation-delay:{d}s"></span>' for d in delays) |
| return f""" |
| <div class="landing-wrap"> |
| <div class="landing-eyebrow">ZeroGPU · Real-Time Inference</div> |
| <h1 class="landing-title">Compose music<br>at the speed of <span class="accent">thought</span>.</h1> |
| <p class="landing-tagline">{title} turns a short description, lyric or reference track into a finished, studio-quality song β open source, powered by ACE-Step v1.5.</p> |
| <div class="landing-eq" aria-hidden="true">{bars}</div> |
| </div> |
| """ |
|
|
|
|
| def build_landing_rack_html() -> str: |
| """Bottom half of the landing screen: channel-strip feature rack + footer links.""" |
| return """ |
| <div class="landing-wrap" style="padding-top:8px;"> |
| <p class="landing-note"> |
| Running on <a href="https://huggingface.co/collections/ACE-Step/ace-step-15" target="_blank">Hugging Face ZeroGPU</a> |
| β first generation may take a little longer while a GPU is allocated. |
| </p> |
| |
| <div class="landing-rack"> |
| <div class="landing-strip"> |
| <div class="ch-num">CH.01</div> |
| <div class="ch-icon">πΌ</div> |
| <h4>Text → Music</h4> |
| <p>Describe a genre, mood or write full lyrics β get back a complete, mixed track in seconds.</p> |
| <div class="landing-fader"><i style="left:78%"></i></div> |
| </div> |
| <div class="landing-strip"> |
| <div class="ch-num">CH.02</div> |
| <div class="ch-icon">ποΈ</div> |
| <h4>Reference-Guided</h4> |
| <p>Upload a reference recording to steer vocals, instrumentation and style with precision.</p> |
| <div class="landing-fader"><i style="left:55%"></i></div> |
| </div> |
| <div class="landing-strip"> |
| <div class="ch-num">CH.03</div> |
| <div class="ch-icon">π§ </div> |
| <h4>LoRA Fine-Tuning</h4> |
| <p>Build a custom dataset and train your own LoRA adapter directly inside the Space.</p> |
| <div class="landing-fader"><i style="left:40%"></i></div> |
| </div> |
| <div class="landing-strip"> |
| <div class="ch-num">CH.04</div> |
| <div class="ch-icon">β‘</div> |
| <h4>ZeroGPU Powered</h4> |
| <p>Serverless, on-demand GPU inference β fast, free and fully open source.</p> |
| <div class="landing-fader"><i style="left:92%"></i></div> |
| </div> |
| </div> |
| |
| <div class="landing-footer"> |
| <span>ACE-Step v1.5 · Open Source Music Generation</span> |
| <a href="https://huggingface.co/collections/ACE-Step/ace-step-15" target="_blank">Hugging Face</a> |
| <a href="https://modelscope.cn/models/ACE-Step/ACE-Step-v1-5" target="_blank">ModelScope</a> |
| <a href="https://github.com/ACE-Step/ACE-Step-1.5" target="_blank">GitHub</a> |
| <a href="https://discord.gg/PeWDxrkdj7" target="_blank">Discord</a> |
| <a href="https://arxiv.org/abs/2602.00744" target="_blank">Technical Report</a> |
| </div> |
| </div> |
| """ |
|
|
|
|
| def build_studio_header_html(title: str) -> str: |
| """Small in-app title shown next to the 'Home' button once inside the studio.""" |
| return f'<span class="studio-topbar-title">{title}</span>' |
|
|
|
|
| def create_gradio_interface(dit_handler, llm_handler, dataset_handler, init_params=None, language='en') -> gr.Blocks: |
| """ |
| Create Gradio interface |
| |
| Args: |
| dit_handler: DiT handler instance |
| llm_handler: LM handler instance |
| dataset_handler: Dataset handler instance |
| init_params: Dictionary containing initialization parameters and state. |
| If None, service will not be pre-initialized. |
| language: UI language code ('en', 'zh', 'ja', default: 'en') |
| |
| Returns: |
| Gradio Blocks instance |
| """ |
| |
| i18n = get_i18n(language) |
| |
| with gr.Blocks( |
| title=t("app.title"), |
| theme=gr.themes.Soft(), |
| css=STUDIO_CSS |
| ) as demo: |
|
|
| |
| |
| |
| |
| |
| |
| |
| with gr.Column(visible=True, elem_id="landing-page") as landing_page: |
| gr.HTML(build_landing_hero_html(t("app.title"))) |
| enter_btn = gr.Button("Enter the Studio β", elem_id="enter-studio-btn", variant="primary") |
| gr.HTML(build_landing_rack_html()) |
|
|
| |
| |
| |
| with gr.Column(visible=False, elem_id="studio-page") as studio_page: |
| with gr.Row(elem_classes=["studio-topbar"]): |
| back_btn = gr.Button("β Home", elem_id="studio-back-btn", size="sm", scale=0) |
| gr.HTML(build_studio_header_html(t("app.title"))) |
|
|
| |
| dataset_section = create_dataset_section(dataset_handler) |
|
|
| |
| generation_section = create_generation_section(dit_handler, llm_handler, init_params=init_params, language=language) |
|
|
| |
| results_section = create_results_section(dit_handler) |
|
|
| |
| |
| training_section = create_training_section(dit_handler, llm_handler, init_params=init_params) |
|
|
| |
| setup_event_handlers(demo, dit_handler, llm_handler, dataset_handler, dataset_section, generation_section, results_section, init_params=init_params) |
|
|
| |
| setup_training_event_handlers(demo, dit_handler, llm_handler, training_section) |
|
|
| |
| enter_btn.click( |
| fn=lambda: (gr.update(visible=False), gr.update(visible=True)), |
| inputs=None, |
| outputs=[landing_page, studio_page], |
| ) |
| back_btn.click( |
| fn=lambda: (gr.update(visible=True), gr.update(visible=False)), |
| inputs=None, |
| outputs=[landing_page, studio_page], |
| ) |
|
|
| return demo |
|
|