Spaces:
Running
Running
Upload app.py with huggingface_hub
Browse files
app.py
CHANGED
|
@@ -86,57 +86,152 @@ def do_everything(poem: str, greeting: str, style_id: str, song_style: str, dura
|
|
| 86 |
yield understanding, brief_en, card, painting, audio, video
|
| 87 |
|
| 88 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 89 |
CSS = """
|
| 90 |
-
|
| 91 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 92 |
background:
|
| 93 |
-
radial-gradient(
|
| 94 |
-
radial-gradient(
|
| 95 |
var(--paper) !important;
|
| 96 |
-
font-family: "Noto Serif SC", "Source Han Serif SC", "Songti SC", serif !important;
|
| 97 |
color: var(--ink);
|
| 98 |
}
|
| 99 |
-
#
|
| 100 |
-
|
| 101 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 102 |
}
|
| 103 |
-
|
| 104 |
-
|
| 105 |
-
|
| 106 |
-
font-size: 1.4rem; vertical-align: middle;
|
| 107 |
}
|
| 108 |
-
.
|
| 109 |
-
|
| 110 |
-
|
| 111 |
-
|
| 112 |
-
|
|
|
|
|
|
|
| 113 |
}
|
| 114 |
-
.step
|
| 115 |
-
|
| 116 |
-
background: var(--vermilion) !important; border: none !important;
|
| 117 |
-
font-size: 1.15rem !important; letter-spacing: 0.2rem;
|
| 118 |
}
|
| 119 |
-
|
| 120 |
-
|
| 121 |
-
|
| 122 |
-
|
|
|
|
|
|
|
| 123 |
}
|
| 124 |
-
|
| 125 |
"""
|
| 126 |
|
| 127 |
-
|
| 128 |
-
|
| 129 |
-
|
| 130 |
-
|
| 131 |
-
|
| 132 |
-
|
| 133 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 134 |
|
| 135 |
brief_state = gr.State("")
|
| 136 |
painting_state = gr.State(None)
|
| 137 |
|
| 138 |
-
with gr.Group(elem_classes="step
|
| 139 |
-
gr.
|
| 140 |
poem_box = gr.Textbox(
|
| 141 |
label="您的诗", lines=4, placeholder="把您想说的写成几句小诗,长短都可以。"
|
| 142 |
)
|
|
@@ -144,12 +239,16 @@ with gr.Blocks(title="诗成画 · Poem to Painting & Song") as demo:
|
|
| 144 |
label="想送的问候(可以不填)", placeholder="例如:早安,或一句祝福的话"
|
| 145 |
)
|
| 146 |
with gr.Row():
|
| 147 |
-
interpret_btn = gr.Button("读诗", variant="primary")
|
| 148 |
-
everything_btn = gr.Button(
|
|
|
|
|
|
|
| 149 |
|
| 150 |
-
with gr.Group(elem_classes="step
|
| 151 |
-
gr.
|
| 152 |
-
understanding_md = gr.Markdown(
|
|
|
|
|
|
|
| 153 |
correction_box = gr.Textbox(
|
| 154 |
label="如果我没读对,请告诉我", placeholder="例如:我想要更温暖的颜色"
|
| 155 |
)
|
|
@@ -157,16 +256,16 @@ with gr.Blocks(title="诗成画 · Poem to Painting & Song") as demo:
|
|
| 157 |
with gr.Accordion("给画师的英文说明(看看也无妨)", open=False):
|
| 158 |
brief_md = gr.Markdown("")
|
| 159 |
|
| 160 |
-
with gr.Group(elem_classes="step
|
| 161 |
-
gr.
|
| 162 |
style_radio = gr.Radio(
|
| 163 |
IMAGE_STYLE_CHOICES, value=DEFAULT_IMAGE_STYLE, label="选一种画风"
|
| 164 |
)
|
| 165 |
paint_btn = gr.Button("作画", variant="primary")
|
| 166 |
card_image = gr.Image(label="您的画卡", type="pil", interactive=False)
|
| 167 |
|
| 168 |
-
with gr.Group(elem_classes="step
|
| 169 |
-
gr.
|
| 170 |
with gr.Row():
|
| 171 |
song_radio = gr.Radio(
|
| 172 |
SONG_STYLE_CHOICES, value=DEFAULT_SONG_STYLE, label="选一种曲风"
|
|
@@ -175,9 +274,8 @@ with gr.Blocks(title="诗成画 · Poem to Painting & Song") as demo:
|
|
| 175 |
sing_btn = gr.Button("唱诗", variant="primary")
|
| 176 |
song_audio = gr.Audio(label="您的诗,唱出来了", type="filepath", interactive=False)
|
| 177 |
|
| 178 |
-
with gr.Group(elem_classes="step
|
| 179 |
-
gr.
|
| 180 |
-
gr.Markdown("让画轻轻动起来,配上您的歌,做成一段可以发给家人的小影片。")
|
| 181 |
animate_btn = gr.Button("让画活起来", variant="primary")
|
| 182 |
video_out = gr.Video(label="会唱歌的画", interactive=False)
|
| 183 |
|
|
@@ -220,4 +318,4 @@ with gr.Blocks(title="诗成画 · Poem to Painting & Song") as demo:
|
|
| 220 |
)
|
| 221 |
|
| 222 |
if __name__ == "__main__":
|
| 223 |
-
demo.launch(css=CSS)
|
|
|
|
| 86 |
yield understanding, brief_en, card, painting, audio, video
|
| 87 |
|
| 88 |
|
| 89 |
+
THEME = gr.themes.Base(
|
| 90 |
+
primary_hue=gr.themes.colors.red,
|
| 91 |
+
neutral_hue=gr.themes.colors.stone,
|
| 92 |
+
font=[gr.themes.GoogleFont("Noto Serif SC"), "Songti SC", "serif"],
|
| 93 |
+
).set(
|
| 94 |
+
body_background_fill="#FDFBF7",
|
| 95 |
+
body_text_color="#3e3a39",
|
| 96 |
+
block_background_fill="#FFFEFB",
|
| 97 |
+
block_border_color="#E7DCCC",
|
| 98 |
+
block_label_text_color="#6f655d",
|
| 99 |
+
input_background_fill="#FCFAF4",
|
| 100 |
+
input_border_color="#E7DCCC",
|
| 101 |
+
button_primary_background_fill="#8c3a38",
|
| 102 |
+
button_primary_background_fill_hover="#9c4240",
|
| 103 |
+
button_primary_text_color="#FDF6EF",
|
| 104 |
+
)
|
| 105 |
+
|
| 106 |
+
# Distinctive layer the theme tokens can't express: brush-calligraphy title,
|
| 107 |
+
# vermilion seal-stamp step markers, chip-style radios, rice-paper atmosphere.
|
| 108 |
CSS = """
|
| 109 |
+
@import url('https://fonts.googleapis.com/css2?family=Ma+Shan+Zheng&family=Noto+Serif+SC:wght@400;500;700;900&display=swap');
|
| 110 |
+
|
| 111 |
+
:root{
|
| 112 |
+
--paper:#FDFBF7; --paper-card:#FFFEFB; --paper-input:#FCFAF4;
|
| 113 |
+
--ink:#3e3a39; --ink-soft:#6f655d; --ink-faint:#9a8f83;
|
| 114 |
+
--seal:#8c3a38; --line:#E7DCCC;
|
| 115 |
+
--serif:"Noto Serif SC","Songti SC","STSong",serif;
|
| 116 |
+
--brush:"Ma Shan Zheng",var(--serif);
|
| 117 |
+
}
|
| 118 |
+
.gradio-container, .gradio-container *{ font-family: var(--serif); }
|
| 119 |
+
.gradio-container{
|
| 120 |
background:
|
| 121 |
+
radial-gradient(58rem 24rem at 90% -10%, rgba(140,58,56,.05), transparent 60%),
|
| 122 |
+
radial-gradient(46rem 22rem at -6% 110%, rgba(62,58,57,.045), transparent 55%),
|
| 123 |
var(--paper) !important;
|
|
|
|
| 124 |
color: var(--ink);
|
| 125 |
}
|
| 126 |
+
#app-root{ max-width: 860px; margin: 0 auto; }
|
| 127 |
+
footer{ display:none !important; }
|
| 128 |
+
|
| 129 |
+
/* hero */
|
| 130 |
+
#hero{ text-align:center; padding: 2.2rem 0 1rem; }
|
| 131 |
+
#hero .brush{
|
| 132 |
+
font-family:var(--brush); font-size: clamp(3.2rem,10vw,5rem);
|
| 133 |
+
color:var(--ink); letter-spacing:.3rem; line-height:1; margin:0;
|
| 134 |
+
}
|
| 135 |
+
#hero .stamp{
|
| 136 |
+
display:inline-grid; place-items:center; width:2.5rem; height:2.5rem;
|
| 137 |
+
margin-left:.55rem; vertical-align:.4rem; background:var(--seal); color:#fbf3ec;
|
| 138 |
+
border-radius:8px; font-size:1.15rem; font-weight:700; transform:rotate(-4deg);
|
| 139 |
+
box-shadow:0 4px 12px -2px rgba(140,58,56,.45);
|
| 140 |
+
}
|
| 141 |
+
#hero .sub{ margin:1.05rem auto 0; max-width:34rem; color:var(--ink-soft);
|
| 142 |
+
font-size:1.06rem; line-height:1.8; letter-spacing:.02rem; }
|
| 143 |
+
#hero .rule{ width:60px; height:3px; margin:1.1rem auto 0; background:var(--seal);
|
| 144 |
+
opacity:.85; border-radius:2px; }
|
| 145 |
+
|
| 146 |
+
/* step cards */
|
| 147 |
+
.step{
|
| 148 |
+
background:var(--paper-card) !important; border:1px solid var(--line) !important;
|
| 149 |
+
border-radius:16px !important; padding:1.5rem 1.4rem 1.3rem !important;
|
| 150 |
+
margin:0 0 1.35rem !important;
|
| 151 |
+
box-shadow:0 1px 0 #fff inset, 0 14px 32px -22px rgba(62,58,57,.5) !important;
|
| 152 |
+
}
|
| 153 |
+
/* let the step-head HTML sit directly on the paper card, no Gradio block chrome.
|
| 154 |
+
the .styler wrapper around the HTML block carries a tan fill — clear it. */
|
| 155 |
+
.step .styler:has(.step-head){ background:transparent !important; border:none !important;
|
| 156 |
+
box-shadow:none !important; padding:0 !important; }
|
| 157 |
+
.step-head{ display:flex; align-items:center; gap:.8rem; margin-bottom:1rem; }
|
| 158 |
+
.step-seal{
|
| 159 |
+
flex:0 0 auto; width:2.4rem; height:2.4rem; display:grid; place-items:center;
|
| 160 |
+
background:var(--seal); color:#fbf3ec; border-radius:9px; font-size:1.25rem;
|
| 161 |
+
font-weight:700; box-shadow:0 4px 10px -3px rgba(140,58,56,.5);
|
| 162 |
+
}
|
| 163 |
+
.step-title{ font-size:1.34rem; font-weight:700; color:var(--ink); line-height:1.2; }
|
| 164 |
+
.step-sub{ font-size:.94rem; color:var(--ink-faint); margin-top:.1rem; }
|
| 165 |
+
|
| 166 |
+
/* inputs */
|
| 167 |
+
textarea, input[type="text"]{
|
| 168 |
+
font-size:1.16rem !important; line-height:1.9 !important; color:var(--ink) !important;
|
| 169 |
+
border-radius:10px !important;
|
| 170 |
+
}
|
| 171 |
+
textarea:focus, input[type="text"]:focus{
|
| 172 |
+
border-color:var(--seal) !important; box-shadow:0 0 0 3px rgba(140,58,56,.12) !important;
|
| 173 |
+
}
|
| 174 |
+
|
| 175 |
+
/* buttons */
|
| 176 |
+
button.primary, button.secondary{
|
| 177 |
+
min-height:58px !important; font-size:1.14rem !important; font-weight:700 !important;
|
| 178 |
+
letter-spacing:.12rem !important; border-radius:12px !important;
|
| 179 |
+
}
|
| 180 |
+
button.primary{ box-shadow:0 9px 22px -12px rgba(140,58,56,.7) !important; }
|
| 181 |
+
button.primary:hover{ filter:brightness(1.05); transform:translateY(-1px); }
|
| 182 |
+
button.secondary{
|
| 183 |
+
background:var(--paper-card) !important; color:var(--ink) !important;
|
| 184 |
+
border:1px solid var(--line) !important;
|
| 185 |
}
|
| 186 |
+
.run-all button, .run-all.secondary{
|
| 187 |
+
background:linear-gradient(180deg,#4a4441,#322d2b) !important; color:#f3ece2 !important;
|
| 188 |
+
border:none !important; letter-spacing:.2rem !important;
|
|
|
|
| 189 |
}
|
| 190 |
+
.run-all button:hover{ filter:brightness(1.08); }
|
| 191 |
+
|
| 192 |
+
/* radios as paper chips */
|
| 193 |
+
.step fieldset label, .step .wrap label{
|
| 194 |
+
background:var(--paper-input) !important; border:1px solid var(--line) !important;
|
| 195 |
+
border-radius:999px !important; padding:.5rem 1.05rem !important; cursor:pointer;
|
| 196 |
+
font-size:1.05rem !important; color:var(--ink) !important; transition:all .15s ease;
|
| 197 |
}
|
| 198 |
+
.step fieldset label:has(input:checked), .step .wrap label:has(input:checked){
|
| 199 |
+
background:var(--seal) !important; border-color:var(--seal) !important; color:#fdf6ef !important;
|
|
|
|
|
|
|
| 200 |
}
|
| 201 |
+
|
| 202 |
+
/* understanding panel */
|
| 203 |
+
#understanding{
|
| 204 |
+
background:var(--paper-input); border:1px solid var(--line);
|
| 205 |
+
border-left:3px solid var(--seal); border-radius:10px;
|
| 206 |
+
padding:1rem 1.15rem; font-size:1.12rem; line-height:1.9; color:var(--ink);
|
| 207 |
}
|
| 208 |
+
#understanding h3{ color:var(--seal); margin-top:0; letter-spacing:.06rem; }
|
| 209 |
"""
|
| 210 |
|
| 211 |
+
|
| 212 |
+
def step_head(num: str, title: str, sub: str) -> str:
|
| 213 |
+
return (
|
| 214 |
+
f"<div class='step-head'><span class='step-seal'>{num}</span>"
|
| 215 |
+
f"<div><div class='step-title'>{title}</div>"
|
| 216 |
+
f"<div class='step-sub'>{sub}</div></div></div>"
|
| 217 |
+
)
|
| 218 |
+
|
| 219 |
+
|
| 220 |
+
with gr.Blocks(title="Poetic · 诗成画") as demo:
|
| 221 |
+
with gr.Column(elem_id="app-root"):
|
| 222 |
+
gr.HTML(
|
| 223 |
+
"<div id='hero'>"
|
| 224 |
+
"<h1 class='brush'>诗成画<span class='stamp'>印</span></h1>"
|
| 225 |
+
"<p class='sub'>写一首小诗,我替您读懂它、为它作画、把它唱出来,"
|
| 226 |
+
"再让画轻轻动起来——做成一张可以送给家人的画卡。<br>每一步都用开源小模型生成。</p>"
|
| 227 |
+
"<div class='rule'></div></div>"
|
| 228 |
+
)
|
| 229 |
|
| 230 |
brief_state = gr.State("")
|
| 231 |
painting_state = gr.State(None)
|
| 232 |
|
| 233 |
+
with gr.Group(elem_classes="step"):
|
| 234 |
+
gr.HTML(step_head("一", "写诗", "把心里的话写成几句,长短都可以"))
|
| 235 |
poem_box = gr.Textbox(
|
| 236 |
label="您的诗", lines=4, placeholder="把您想说的写成几句小诗,长短都可以。"
|
| 237 |
)
|
|
|
|
| 239 |
label="想送的问候(可以不填)", placeholder="例如:早安,或一句祝福的话"
|
| 240 |
)
|
| 241 |
with gr.Row():
|
| 242 |
+
interpret_btn = gr.Button("读诗", variant="primary", scale=1)
|
| 243 |
+
everything_btn = gr.Button(
|
| 244 |
+
"一气呵成 · 读诗 作画 唱诗 入画", scale=2, elem_classes="run-all"
|
| 245 |
+
)
|
| 246 |
|
| 247 |
+
with gr.Group(elem_classes="step"):
|
| 248 |
+
gr.HTML(step_head("二", "画中之意", "我把读到的画面说给您听,读错了可以纠正我"))
|
| 249 |
+
understanding_md = gr.Markdown(
|
| 250 |
+
"点「读诗」后,我会把读到的画面说给您听。", elem_id="understanding"
|
| 251 |
+
)
|
| 252 |
correction_box = gr.Textbox(
|
| 253 |
label="如果我没读对,请告诉我", placeholder="例如:我想要更温暖的颜色"
|
| 254 |
)
|
|
|
|
| 256 |
with gr.Accordion("给画师的英文说明(看看也无妨)", open=False):
|
| 257 |
brief_md = gr.Markdown("")
|
| 258 |
|
| 259 |
+
with gr.Group(elem_classes="step"):
|
| 260 |
+
gr.HTML(step_head("三", "作画", "选一种画风,为这首诗画一幅画卡"))
|
| 261 |
style_radio = gr.Radio(
|
| 262 |
IMAGE_STYLE_CHOICES, value=DEFAULT_IMAGE_STYLE, label="选一种画风"
|
| 263 |
)
|
| 264 |
paint_btn = gr.Button("作画", variant="primary")
|
| 265 |
card_image = gr.Image(label="您的画卡", type="pil", interactive=False)
|
| 266 |
|
| 267 |
+
with gr.Group(elem_classes="step"):
|
| 268 |
+
gr.HTML(step_head("四", "唱诗", "把这首诗唱成一首歌"))
|
| 269 |
with gr.Row():
|
| 270 |
song_radio = gr.Radio(
|
| 271 |
SONG_STYLE_CHOICES, value=DEFAULT_SONG_STYLE, label="选一种曲风"
|
|
|
|
| 274 |
sing_btn = gr.Button("唱诗", variant="primary")
|
| 275 |
song_audio = gr.Audio(label="您的诗,唱出来了", type="filepath", interactive=False)
|
| 276 |
|
| 277 |
+
with gr.Group(elem_classes="step"):
|
| 278 |
+
gr.HTML(step_head("五", "入画", "让画轻轻动起来,配上您的歌,做成一段小影片"))
|
|
|
|
| 279 |
animate_btn = gr.Button("让画活起来", variant="primary")
|
| 280 |
video_out = gr.Video(label="会唱歌的画", interactive=False)
|
| 281 |
|
|
|
|
| 318 |
)
|
| 319 |
|
| 320 |
if __name__ == "__main__":
|
| 321 |
+
demo.launch(theme=THEME, css=CSS)
|