Spaces:
Running on Zero
Running on Zero
Update app.py
Browse files
app.py
CHANGED
|
@@ -341,289 +341,189 @@ def generate_reply(
|
|
| 341 |
|
| 342 |
|
| 343 |
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 344 |
-
|
| 345 |
-
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 346 |
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 347 |
-
# 6. GRADIO UI โ
|
| 348 |
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 349 |
|
| 350 |
CSS = """
|
| 351 |
@import url('https://fonts.googleapis.com/css2?family=Instrument+Serif:ital@0;1&display=swap');
|
| 352 |
@import url('https://api.fontshare.com/v2/css?f[]=cabinet-grotesk@400;500;700;800&display=swap');
|
| 353 |
-
|
| 354 |
-
:
|
| 355 |
-
|
| 356 |
-
|
| 357 |
-
|
| 358 |
-
}
|
| 359 |
-
|
| 360 |
-
|
| 361 |
-
|
| 362 |
-
|
| 363 |
-
|
| 364 |
-
|
| 365 |
-
#
|
| 366 |
-
|
| 367 |
-
|
| 368 |
-
|
| 369 |
-
|
| 370 |
-
|
| 371 |
-
.
|
| 372 |
-
|
| 373 |
-
|
| 374 |
-
|
| 375 |
-
|
| 376 |
-
|
| 377 |
-
|
| 378 |
-
|
| 379 |
-
|
| 380 |
-
|
| 381 |
-
|
| 382 |
-
.
|
| 383 |
-
.
|
| 384 |
-
.
|
| 385 |
-
.
|
| 386 |
-
|
| 387 |
-
|
| 388 |
-
|
| 389 |
-
|
| 390 |
-
|
| 391 |
-
|
| 392 |
-
|
| 393 |
-
|
| 394 |
-
|
| 395 |
-
|
| 396 |
-
#
|
| 397 |
-
#
|
| 398 |
-
#
|
| 399 |
-
|
| 400 |
-
|
| 401 |
-
#
|
| 402 |
-
|
| 403 |
-
|
| 404 |
-
.
|
| 405 |
-
|
| 406 |
-
.
|
| 407 |
-
|
| 408 |
-
|
| 409 |
-
#chatbot
|
| 410 |
-
#chatbot .
|
| 411 |
-
#
|
| 412 |
-
|
| 413 |
-
|
| 414 |
-
#
|
| 415 |
-
|
| 416 |
-
|
| 417 |
-
|
| 418 |
-
|
| 419 |
-
|
| 420 |
-
|
| 421 |
-
|
| 422 |
-
.primary { background: linear-gradient(135deg, var(--v), var(--v2)) !important; border: none !important; border-radius: 12px !important; }
|
| 423 |
-
|
| 424 |
-
/* Model dropdown */
|
| 425 |
-
#model-select .wrap { border-color: rgba(109,40,217,.2) !important; }
|
| 426 |
-
#model-select .wrap:focus-within { border-color: var(--v) !important; box-shadow: 0 0 0 3px rgba(109,40,217,.08) !important; }
|
| 427 |
-
|
| 428 |
-
@media(max-width:768px) {
|
| 429 |
-
#examples-area { grid-template-columns: 1fr; }
|
| 430 |
-
#header-banner h1 { font-size: 24px !important; }
|
| 431 |
-
}
|
| 432 |
-
"""
|
| 433 |
-
|
| 434 |
-
HEADER_HTML = """
|
| 435 |
-
<div id="orbs"><div class="orb orb1"></div><div class="orb orb2"></div><div class="orb orb3"></div><div class="bg-grid"></div></div>
|
| 436 |
-
<div id="header-banner">
|
| 437 |
-
<div class="logo-icon">๐</div>
|
| 438 |
-
<h1>Hello, I'm <em>Gemma 4</em></h1>
|
| 439 |
-
<div class="sub">Google DeepMind's most intelligent open model โ Dense 31B or MoE 26B-A4B ยท Vision ยท Thinking ยท Apache 2.0</div>
|
| 440 |
-
<div class="badges">
|
| 441 |
-
<span class="badge wb-purple">AIME 89.2%</span>
|
| 442 |
-
<span class="badge wb-green">GPQA 84.3%</span>
|
| 443 |
-
<span class="badge wb-amber">Codeforces 2150</span>
|
| 444 |
-
<span class="badge wb-teal">256K context</span>
|
| 445 |
-
<a href="https://huggingface.co/collections/google/gemma-4" target="_blank" class="badge wb-purple" style="text-decoration:none;">๐ค Gemma 4 โ</a>
|
| 446 |
-
</div>
|
| 447 |
-
</div>
|
| 448 |
"""
|
| 449 |
|
| 450 |
-
|
| 451 |
-
<div id="model-card">
|
| 452 |
-
<div class="mc-top">
|
| 453 |
-
<span class="mc-name" id="mcName">Gemma-4-26B-A4B-it</span>
|
| 454 |
-
<span class="mc-arch" id="mcArch">MoE 3.8B / 26B</span>
|
| 455 |
-
</div>
|
| 456 |
-
<div class="mc-stats" id="mcStats">
|
| 457 |
-
<span class="mc-stat mc-hl">GPQA 82.3%</span>
|
| 458 |
-
<span class="mc-stat mc-ok">AIME 88.3%</span>
|
| 459 |
-
<span class="mc-stat mc-ok">๐๏ธ Vision</span>
|
| 460 |
-
<span class="mc-stat mc-ok">256K ctx</span>
|
| 461 |
-
</div>
|
| 462 |
-
<div class="mc-desc" id="mcDesc">MoE 128 experts ยท 3.8B active params ยท 31B์ 95% ์ฑ๋ฅ, ์ถ๋ก ~8๋ฐฐ ๋น ๋ฆ ยท 140+ languages</div>
|
| 463 |
-
<div class="mc-links">
|
| 464 |
-
<a id="mcHfLink" href="https://huggingface.co/google/gemma-4-26B-A4B-it" target="_blank" style="background:rgba(109,40,217,.08);color:#6d28d9;border:1px solid rgba(109,40,217,.15);">๐ค Model Card โ</a>
|
| 465 |
-
<a href="https://deepmind.google/models/gemma/gemma-4/" target="_blank" style="background:rgba(16,185,129,.08);color:#059669;border:1px solid rgba(16,185,129,.15);">๐ฌ DeepMind โ</a>
|
| 466 |
-
</div>
|
| 467 |
-
</div>
|
| 468 |
-
"""
|
| 469 |
|
| 470 |
-
|
| 471 |
-
<div id="
|
| 472 |
-
<div class="
|
| 473 |
-
|
| 474 |
-
</div>
|
| 475 |
-
<div class="ex-card" onclick="document.querySelector('#chat-input textarea').value='Write a Python async web scraper with retry logic, rate limiting, and type hints.';document.querySelector('#chat-input textarea').dispatchEvent(new Event('input',{bubbles:true}));">
|
| 476 |
-
<span class="ex-icon">๐ป</span><div class="ex-title">Code Generation</div><div class="ex-desc">Production-quality Python</div>
|
| 477 |
-
</div>
|
| 478 |
-
<div class="ex-card" onclick="document.querySelector('#chat-input textarea').value='ํ๊ตญ์ K-pop์ด ์ธ๊ณ์ ์ผ๋ก ์ฑ๊ณตํ ์ด์ ๋ฅผ ๋ฌธํ์ , ๊ฒฝ์ ์ ๊ด์ ์์ ๋ถ์ํด์ฃผ์ธ์.';document.querySelector('#chat-input textarea').dispatchEvent(new Event('input',{bubbles:true}));">
|
| 479 |
-
<span class="ex-icon">๐</span><div class="ex-title">140+ Languages</div><div class="ex-desc">Korean, Japanese, Arabicโฆ</div>
|
| 480 |
-
</div>
|
| 481 |
-
<div class="ex-card" onclick="document.querySelector('#chat-input textarea').value='Solve: Find all real solutions to xยณ - 6xยฒ + 11x - 6 = 0. Show step-by-step reasoning.';document.querySelector('#chat-input textarea').dispatchEvent(new Event('input',{bubbles:true}));">
|
| 482 |
-
<span class="ex-icon">๐งฎ</span><div class="ex-title">Math Reasoning</div><div class="ex-desc">Step-by-step problem solving</div>
|
| 483 |
-
</div>
|
| 484 |
</div>
|
| 485 |
-
"""
|
| 486 |
-
|
| 487 |
-
|
| 488 |
-
|
| 489 |
-
<
|
| 490 |
-
|
| 491 |
-
|
| 492 |
-
|
| 493 |
-
|
| 494 |
-
|
| 495 |
-
|
| 496 |
-
|
| 497 |
-
|
| 498 |
-
|
| 499 |
-
|
| 500 |
-
|
| 501 |
-
|
| 502 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 503 |
};
|
| 504 |
-
|
| 505 |
-
|
| 506 |
-
|
| 507 |
-
|
| 508 |
-
|
| 509 |
-
|
| 510 |
-
|
| 511 |
-
|
| 512 |
-
|
| 513 |
-
|
| 514 |
-
document.getElementById('mcArch').textContent = m.arch;
|
| 515 |
-
document.getElementById('mcStats').innerHTML = m.stats;
|
| 516 |
-
document.getElementById('mcDesc').textContent = m.desc;
|
| 517 |
-
document.getElementById('mcHfLink').href = m.hf;
|
| 518 |
-
}
|
| 519 |
-
}).observe(document.body, {subtree: true, childList: true, characterData: true});
|
| 520 |
-
</script>
|
| 521 |
-
"""
|
| 522 |
-
|
| 523 |
|
| 524 |
-
with gr.Blocks(title="๐ Gemma 4 Playground", fill_height=True) as demo:
|
| 525 |
|
| 526 |
-
|
| 527 |
-
gr.HTML(
|
| 528 |
|
| 529 |
-
with gr.
|
| 530 |
-
with gr.
|
| 531 |
-
|
| 532 |
-
|
| 533 |
-
|
| 534 |
-
|
| 535 |
-
)
|
| 536 |
-
|
| 537 |
-
choices=["โก Fast", "๐ง Thinking"],
|
| 538 |
-
value="โก Fast", label="Mode", scale=1,
|
| 539 |
-
)
|
| 540 |
-
with gr.Row():
|
| 541 |
-
sys_prompt = gr.Textbox(
|
| 542 |
-
value=PRESETS["general"], label="System Prompt", lines=2, scale=3,
|
| 543 |
-
)
|
| 544 |
-
with gr.Row():
|
| 545 |
-
with gr.Column(scale=1):
|
| 546 |
-
preset_dd = gr.Dropdown(
|
| 547 |
-
choices=list(PRESETS.keys()), value="general",
|
| 548 |
-
label="Preset", info="Quick system prompt selection",
|
| 549 |
-
)
|
| 550 |
-
with gr.Column(scale=1):
|
| 551 |
max_tok_sl = gr.Slider(64, 8192, value=4096, step=64, label="Max Tokens")
|
| 552 |
-
with gr.Column(scale=1):
|
| 553 |
temp_sl = gr.Slider(0.0, 1.5, value=0.6, step=0.05, label="Temperature")
|
| 554 |
-
with gr.Column(scale=1):
|
| 555 |
topp_sl = gr.Slider(0.1, 1.0, value=0.9, step=0.05, label="Top-P")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 556 |
|
| 557 |
-
|
| 558 |
-
preset_dd.change(
|
| 559 |
-
fn=lambda k: PRESETS.get(k, PRESETS["general"]),
|
| 560 |
-
inputs=[preset_dd], outputs=[sys_prompt],
|
| 561 |
-
)
|
| 562 |
-
|
| 563 |
-
gr.HTML(EXAMPLES_HTML)
|
| 564 |
-
|
| 565 |
-
image_input = gr.Textbox(value="", visible=False)
|
| 566 |
-
|
| 567 |
-
chatbot = gr.Chatbot(
|
| 568 |
-
elem_id="chatbot", scale=1,
|
| 569 |
-
latex_delimiters=[
|
| 570 |
-
{"left": "$$", "right": "$$", "display": True},
|
| 571 |
-
{"left": "$", "right": "$", "display": False},
|
| 572 |
-
{"left": "\\(", "right": "\\)", "display": False},
|
| 573 |
-
{"left": "\\[", "right": "\\]", "display": True},
|
| 574 |
-
],
|
| 575 |
-
)
|
| 576 |
|
| 577 |
-
with gr.Row():
|
| 578 |
-
chat_input = gr.Textbox(
|
| 579 |
-
placeholder="Message Gemma 4โฆ", lines=1, scale=7,
|
| 580 |
-
elem_id="chat-input", show_label=False, autofocus=True,
|
| 581 |
-
)
|
| 582 |
-
send_btn = gr.Button("Send", variant="primary", scale=1, min_width=80)
|
| 583 |
-
|
| 584 |
-
# โโ Chat logic โโ
|
| 585 |
def user_msg(message, history):
|
| 586 |
-
if not message.strip():
|
| 587 |
-
|
| 588 |
-
history = history + [{"role": "user", "content": message}]
|
| 589 |
-
return "", history
|
| 590 |
-
|
| 591 |
-
def bot_reply(history, thinking_mode, image_data, system_prompt,
|
| 592 |
-
max_new_tokens, temperature, top_p, model_choice):
|
| 593 |
-
if not history or history[-1]["role"] != "user":
|
| 594 |
-
return history
|
| 595 |
|
|
|
|
|
|
|
| 596 |
user_text = history[-1]["content"]
|
| 597 |
past = history[:-1]
|
| 598 |
-
|
| 599 |
history = history + [{"role": "assistant", "content": ""}]
|
| 600 |
-
|
| 601 |
-
for chunk in generate_reply(
|
| 602 |
-
user_text, past, thinking_mode, image_data,
|
| 603 |
-
system_prompt, max_new_tokens, temperature, top_p, model_choice,
|
| 604 |
-
):
|
| 605 |
history[-1]["content"] = chunk
|
| 606 |
yield history
|
| 607 |
|
| 608 |
-
common_inputs = [
|
| 609 |
-
|
| 610 |
-
|
| 611 |
-
]
|
| 612 |
-
|
| 613 |
-
# Send on button click
|
| 614 |
-
send_btn.click(user_msg, [chat_input, chatbot], [chat_input, chatbot], queue=False).then(
|
| 615 |
-
bot_reply, common_inputs, chatbot,
|
| 616 |
-
)
|
| 617 |
-
# Send on Enter
|
| 618 |
-
chat_input.submit(user_msg, [chat_input, chatbot], [chat_input, chatbot], queue=False).then(
|
| 619 |
-
bot_reply, common_inputs, chatbot,
|
| 620 |
-
)
|
| 621 |
-
|
| 622 |
-
gr.HTML(MODEL_SWITCH_JS)
|
| 623 |
|
| 624 |
|
| 625 |
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 626 |
-
# 7. LAUNCH
|
| 627 |
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 628 |
if __name__ == "__main__":
|
| 629 |
print(f"[BOOT] Gemma 4 Playground ยท Default: {DEFAULT_MODEL}", flush=True)
|
|
|
|
| 341 |
|
| 342 |
|
| 343 |
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 344 |
+
|
|
|
|
| 345 |
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 346 |
+
# 6. GRADIO UI โ Sidebar + Chat layout
|
| 347 |
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 348 |
|
| 349 |
CSS = """
|
| 350 |
@import url('https://fonts.googleapis.com/css2?family=Instrument+Serif:ital@0;1&display=swap');
|
| 351 |
@import url('https://api.fontshare.com/v2/css?f[]=cabinet-grotesk@400;500;700;800&display=swap');
|
| 352 |
+
:root{--v:#6d28d9;--v2:#7c3aed;--teal:#0d9488;--cream:#faf8f5;--ink:#1c1917;--ink3:#78716c;--ink4:#a8a29e;--line:#e4dfd8;--fog:#ede9e3}
|
| 353 |
+
.gradio-container{background:var(--cream)!important;font-family:'Cabinet Grotesk',sans-serif!important;max-width:100%!important;padding:0!important}
|
| 354 |
+
footer,.svelte-1rjryqp{display:none!important}
|
| 355 |
+
|
| 356 |
+
#orbs{position:fixed;inset:0;z-index:0;pointer-events:none;overflow:hidden}
|
| 357 |
+
.orb{position:absolute;border-radius:50%;filter:blur(80px);opacity:.4;animation:drift linear infinite}
|
| 358 |
+
.orb1{width:500px;height:500px;background:radial-gradient(circle,rgba(109,40,217,.3),transparent 70%);top:-100px;left:-100px;animation-duration:22s}
|
| 359 |
+
.orb2{width:380px;height:380px;background:radial-gradient(circle,rgba(16,185,129,.25),transparent 70%);top:5%;right:-60px;animation-duration:28s;animation-delay:-9s}
|
| 360 |
+
@keyframes drift{0%{transform:translate(0,0) scale(1)}33%{transform:translate(40px,-30px) scale(1.05)}66%{transform:translate(-20px,20px) scale(.97)}100%{transform:translate(0,0) scale(1)}}
|
| 361 |
+
|
| 362 |
+
#shell{display:grid!important;grid-template-columns:280px 1fr!important;height:100vh!important;overflow:hidden!important;position:relative;z-index:1;gap:0!important;padding:0!important}
|
| 363 |
+
#sidebar{background:rgba(255,255,255,.78)!important;backdrop-filter:blur(24px);border-right:1px solid var(--line)!important;overflow-y:auto!important;padding:0!important;border:none!important;border-radius:0!important;display:flex!important;flex-direction:column!important;gap:0!important}
|
| 364 |
+
#sidebar::-webkit-scrollbar{width:3px}
|
| 365 |
+
#sidebar::-webkit-scrollbar-thumb{background:var(--line);border-radius:10px}
|
| 366 |
+
#sidebar .gr-group{background:none!important;border:none!important;padding:0!important}
|
| 367 |
+
|
| 368 |
+
#logo-area{padding:18px 16px 14px;border-bottom:1px solid var(--line)}
|
| 369 |
+
.logo-row{display:flex;align-items:center;gap:10px}
|
| 370 |
+
.logo-icon{width:42px;height:42px;border-radius:13px;background:linear-gradient(135deg,#6d28d9,#a78bfa,#10b981);display:flex;align-items:center;justify-content:center;font-size:20px;box-shadow:0 4px 14px rgba(109,40,217,.3);flex-shrink:0}
|
| 371 |
+
.logo-name{font-family:'Instrument Serif',serif;font-size:20px;color:var(--ink)}
|
| 372 |
+
.logo-name em{color:var(--v);font-style:italic}
|
| 373 |
+
.logo-sub{font-size:9px;font-weight:700;letter-spacing:2px;text-transform:uppercase;color:var(--ink4)}
|
| 374 |
+
|
| 375 |
+
.mcard{margin:6px 12px;padding:12px 14px;border-radius:12px;border:2px solid var(--line);background:rgba(255,255,255,.6);cursor:pointer;transition:all .25s}
|
| 376 |
+
.mcard:hover{border-color:rgba(109,40,217,.3);box-shadow:0 2px 12px rgba(109,40,217,.08)}
|
| 377 |
+
.mcard.active{border-color:var(--v)!important;background:linear-gradient(135deg,rgba(109,40,217,.06),rgba(16,185,129,.04))!important;box-shadow:0 4px 20px rgba(109,40,217,.12)}
|
| 378 |
+
.mc-top{display:flex;align-items:center;justify-content:space-between;margin-bottom:5px}
|
| 379 |
+
.mc-name{font-size:12px;font-weight:700;color:var(--ink)}
|
| 380 |
+
.mc-arch{font-size:8px;font-weight:700;padding:2px 7px;border-radius:8px;background:rgba(109,40,217,.08);color:var(--v);font-family:'Geist Mono',monospace}
|
| 381 |
+
.mc-stats{display:flex;flex-wrap:wrap;gap:3px;margin-bottom:5px}
|
| 382 |
+
.mc-stat{font-size:8px;font-weight:600;padding:1px 6px;border-radius:5px;font-family:'Geist Mono',monospace}
|
| 383 |
+
.mc-hl{background:rgba(109,40,217,.08);color:var(--v)}
|
| 384 |
+
.mc-ok{background:rgba(22,163,74,.09);color:#16a34a}
|
| 385 |
+
.mc-desc{font-size:9px;color:var(--ink3);line-height:1.5}
|
| 386 |
+
.mc-check{display:none;font-size:14px}.mcard.active .mc-check{display:inline}
|
| 387 |
+
|
| 388 |
+
.sec-lbl{font-size:8px;font-weight:700;letter-spacing:2.5px;text-transform:uppercase;color:var(--ink4);padding:10px 14px 4px}
|
| 389 |
+
.preset-chips{display:flex;flex-wrap:wrap;gap:3px;padding:0 14px 6px}
|
| 390 |
+
.pchip{font-size:9px;font-weight:600;padding:3px 9px;border-radius:16px;background:var(--fog);border:1px solid var(--line);color:var(--ink3);cursor:pointer;transition:all .2s}
|
| 391 |
+
.pchip:hover{background:rgba(109,40,217,.08);border-color:rgba(109,40,217,.25);color:var(--v)}
|
| 392 |
+
|
| 393 |
+
#sidebar-settings{padding:4px 12px 12px;flex:1}
|
| 394 |
+
#sidebar-settings label span{font-size:11px!important;font-weight:600!important;color:var(--ink3)!important}
|
| 395 |
+
#sidebar-settings textarea{background:var(--fog)!important;border:1.5px solid var(--line)!important;border-radius:8px!important;font-size:11px!important;padding:6px 8px!important;min-height:50px!important}
|
| 396 |
+
#sidebar-settings textarea:focus{border-color:rgba(109,40,217,.35)!important;box-shadow:0 0 0 3px rgba(109,40,217,.08)!important}
|
| 397 |
+
#clear-btn{margin:8px 12px 12px!important;border-radius:8px!important;border:1.5px solid var(--line)!important;background:var(--fog)!important;color:var(--ink3)!important;font-size:11px!important}
|
| 398 |
+
#clear-btn:hover{border-color:rgba(225,29,72,.3)!important;color:#e11d48!important}
|
| 399 |
+
|
| 400 |
+
#main-col{display:flex!important;flex-direction:column!important;height:100vh!important;overflow:hidden!important;padding:0!important;background:rgba(250,248,245,.4)!important;border:none!important;border-radius:0!important}
|
| 401 |
+
#main-col .gr-group{background:none!important;border:none!important}
|
| 402 |
+
#chat-header{padding:12px 20px;border-bottom:1px solid var(--line);background:rgba(255,255,255,.8);backdrop-filter:blur(20px);display:flex;align-items:center;gap:10px}
|
| 403 |
+
.dot{width:7px;height:7px;border-radius:50%;background:linear-gradient(135deg,var(--v),#10b981);animation:pulse 2s ease-in-out infinite;flex-shrink:0}
|
| 404 |
+
@keyframes pulse{0%,100%{box-shadow:0 0 0 0 rgba(109,40,217,.4)}50%{box-shadow:0 0 0 4px rgba(109,40,217,0)}}
|
| 405 |
+
.hdr-model-name{font-size:12px;font-weight:700;color:var(--v);font-family:'Geist Mono',monospace}
|
| 406 |
+
.hdr-model-meta{font-size:10px;color:var(--ink4);margin-left:auto;font-family:'Geist Mono',monospace}
|
| 407 |
+
|
| 408 |
+
#chatbot{flex:1!important;min-height:0!important;overflow-y:auto!important;border:none!important;border-radius:0!important;background:transparent!important}
|
| 409 |
+
#chatbot .bot{background:rgba(109,40,217,.03)!important;border-left:3px solid rgba(109,40,217,.15)!important;border-radius:12px!important}
|
| 410 |
+
#input-row{padding:12px 20px!important;border-top:1px solid var(--line)!important;background:rgba(255,255,255,.8)!important;backdrop-filter:blur(20px);flex-shrink:0!important}
|
| 411 |
+
#chat-input textarea{border-radius:14px!important;border:1.5px solid var(--line)!important;background:white!important;font-size:13px!important}
|
| 412 |
+
#chat-input textarea:focus{border-color:rgba(109,40,217,.35)!important;box-shadow:0 0 0 3px rgba(109,40,217,.08)!important}
|
| 413 |
+
#send-btn{background:linear-gradient(135deg,var(--v),var(--v2))!important;border:none!important;border-radius:12px!important;color:white!important;font-weight:700!important;min-width:48px!important;font-size:18px!important}
|
| 414 |
+
.ex-card{background:white;border:1.5px solid var(--line);border-radius:12px;padding:11px 13px;cursor:pointer;transition:all .22s}
|
| 415 |
+
.ex-card:hover{border-color:rgba(109,40,217,.3);box-shadow:0 2px 12px rgba(28,25,23,.06);transform:translateY(-2px)}
|
| 416 |
+
.ex-icon{font-size:16px;display:block;margin-bottom:3px}
|
| 417 |
+
.ex-title{font-size:11px;font-weight:700;color:var(--ink);margin-bottom:1px}
|
| 418 |
+
.ex-desc{font-size:9px;color:var(--ink4)}
|
| 419 |
+
|
| 420 |
+
@media(max-width:768px){#shell{grid-template-columns:1fr!important}#sidebar{display:none!important}}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 421 |
"""
|
| 422 |
|
| 423 |
+
SIDEBAR_LOGO = '<div id="logo-area"><div class="logo-row"><div class="logo-icon">๐</div><div><div class="logo-name"><em>Gemma</em> 4</div><div class="logo-sub">Google DeepMind</div></div></div></div>'
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 424 |
|
| 425 |
+
MODEL_CARDS_HTML = """<div class="sec-lbl">Select Model</div>
|
| 426 |
+
<div class="mcard active" id="card-moe" onclick="window._selectModel('Gemma-4-26B-A4B-it')">
|
| 427 |
+
<div class="mc-top"><span class="mc-name">โก Gemma 4 ยท 26B-A4B</span><span class="mc-arch">MoE</span><span class="mc-check">โ</span></div>
|
| 428 |
+
<div class="mc-stats"><span class="mc-stat mc-hl">GPQA 82.3%</span><span class="mc-stat mc-ok">AIME 88.3%</span><span class="mc-stat mc-ok">๐๏ธ Vision</span></div>
|
| 429 |
+
<div class="mc-desc">3.8B active / 26B total ยท 128 experts ยท ์ถ๋ก ๋น ๋ฆ</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 430 |
</div>
|
| 431 |
+
<div class="mcard" id="card-dense" onclick="window._selectModel('Gemma-4-31B-it')">
|
| 432 |
+
<div class="mc-top"><span class="mc-name">๐ Gemma 4 ยท 31B</span><span class="mc-arch">Dense</span><span class="mc-check">โ</span></div>
|
| 433 |
+
<div class="mc-stats"><span class="mc-stat mc-hl">AIME 89.2%</span><span class="mc-stat mc-ok">GPQA 84.3%</span><span class="mc-stat mc-ok">๐๏ธ Vision</span></div>
|
| 434 |
+
<div class="mc-desc">30.7B Dense ยท Codeforces 2150 ยท ์ต๊ณ ํ์ง</div>
|
| 435 |
+
</div>"""
|
| 436 |
+
|
| 437 |
+
PRESETS_HTML = '<div class="sec-lbl">Preset</div><div class="preset-chips"><span class="pchip" onclick="window._setPreset(\'general\')">General</span><span class="pchip" onclick="window._setPreset(\'code\')">Code</span><span class="pchip" onclick="window._setPreset(\'math\')">Math</span><span class="pchip" onclick="window._setPreset(\'creative\')">Creative</span><span class="pchip" onclick="window._setPreset(\'translate\')">Translate</span><span class="pchip" onclick="window._setPreset(\'research\')">Research</span></div>'
|
| 438 |
+
|
| 439 |
+
CHAT_HEADER_HTML = '<div id="chat-header"><div class="dot"></div><span class="hdr-model-name" id="hdrModelName">Gemma-4-26B-A4B-it</span><span class="hdr-model-meta" id="hdrModelMeta">MoE ยท 3.8B active ยท 256K ctx</span></div>'
|
| 440 |
+
|
| 441 |
+
EXAMPLES_HTML = """<div style="display:grid;grid-template-columns:repeat(2,1fr);gap:8px;max-width:460px;margin:40px auto">
|
| 442 |
+
<div class="ex-card" onclick="window._sendEx('Explain how Gemma 4 MoE architecture works with 128 experts and hybrid attention.')"><span class="ex-icon">๐</span><div class="ex-title">Architecture</div><div class="ex-desc">MoE + hybrid attention</div></div>
|
| 443 |
+
<div class="ex-card" onclick="window._sendEx('Write a Python async web scraper with retry logic, rate limiting, and type hints.')"><span class="ex-icon">๐ป</span><div class="ex-title">Code</div><div class="ex-desc">Production-quality Python</div></div>
|
| 444 |
+
<div class="ex-card" onclick="window._sendEx('ํ๊ตญ์ K-pop์ด ์ธ๊ณ์ ์ผ๋ก ์ฑ๊ณตํ ์ด์ ๋ฅผ ๋ฌธํ์ , ๊ฒฝ์ ์ ๊ด์ ์์ ๋ถ์ํด์ฃผ์ธ์.')"><span class="ex-icon">๐</span><div class="ex-title">๋ค๊ตญ์ด</div><div class="ex-desc">Korean, Japanese, Arabicโฆ</div></div>
|
| 445 |
+
<div class="ex-card" onclick="window._sendEx('Solve: Find all real solutions to xยณ - 6xยฒ + 11x - 6 = 0')"><span class="ex-icon">๐งฎ</span><div class="ex-title">Math</div><div class="ex-desc">Step-by-step reasoning</div></div>
|
| 446 |
+
</div>"""
|
| 447 |
+
|
| 448 |
+
BRIDGE_JS = """<script>
|
| 449 |
+
window._selectModel=function(name){
|
| 450 |
+
document.querySelectorAll('.mcard').forEach(function(c){c.classList.remove('active')});
|
| 451 |
+
document.getElementById(name==='Gemma-4-26B-A4B-it'?'card-moe':'card-dense').classList.add('active');
|
| 452 |
+
var h=document.getElementById('hdrModelName');if(h)h.textContent=name;
|
| 453 |
+
var meta={'Gemma-4-26B-A4B-it':'MoE ยท 3.8B active ยท 256K ctx','Gemma-4-31B-it':'Dense ยท 30.7B ยท 256K ctx'};
|
| 454 |
+
var hm=document.getElementById('hdrModelMeta');if(hm)hm.textContent=meta[name]||'';
|
| 455 |
+
var dd=document.querySelector('#model-select input');
|
| 456 |
+
if(dd){var nativeSet=Object.getOwnPropertyDescriptor(HTMLInputElement.prototype,'value').set;nativeSet.call(dd,name);dd.dispatchEvent(new Event('input',{bubbles:true}));}
|
| 457 |
};
|
| 458 |
+
window._sendEx=function(text){
|
| 459 |
+
var ta=document.querySelector('#chat-input textarea');
|
| 460 |
+
if(ta){var nativeSet=Object.getOwnPropertyDescriptor(HTMLTextAreaElement.prototype,'value').set;nativeSet.call(ta,text);ta.dispatchEvent(new Event('input',{bubbles:true}));ta.focus();}
|
| 461 |
+
};
|
| 462 |
+
window._setPreset=function(key){
|
| 463 |
+
var presets={general:'You are Gemma 4, a highly capable multimodal AI assistant by Google DeepMind. Think step by step for complex questions.',code:'You are an expert software engineer. Write clean, efficient, well-commented code.',math:'You are a world-class mathematician. Break problems step-by-step. Show full working.',creative:'You are a brilliant creative writer. Be imaginative, vivid, and engaging.',translate:'You are a professional translator fluent in 140+ languages.',research:'You are a rigorous research analyst. Provide structured, well-reasoned analysis.'};
|
| 464 |
+
var ta=document.querySelector('#sidebar-settings textarea');
|
| 465 |
+
if(ta){var nativeSet=Object.getOwnPropertyDescriptor(HTMLTextAreaElement.prototype,'value').set;nativeSet.call(ta,presets[key]||presets.general);ta.dispatchEvent(new Event('input',{bubbles:true}));}
|
| 466 |
+
};
|
| 467 |
+
</script>"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 468 |
|
|
|
|
| 469 |
|
| 470 |
+
with gr.Blocks(title="Gemma 4 Playground", fill_height=True) as demo:
|
| 471 |
+
gr.HTML('<div id="orbs"><div class="orb orb1"></div><div class="orb orb2"></div></div>')
|
| 472 |
|
| 473 |
+
with gr.Row(elem_id="shell"):
|
| 474 |
+
with gr.Column(scale=0, min_width=280, elem_id="sidebar"):
|
| 475 |
+
gr.HTML(SIDEBAR_LOGO)
|
| 476 |
+
gr.HTML(MODEL_CARDS_HTML)
|
| 477 |
+
model_dd = gr.Dropdown(choices=list(MODELS.keys()), value=DEFAULT_MODEL, elem_id="model-select", visible=False)
|
| 478 |
+
gr.HTML(PRESETS_HTML)
|
| 479 |
+
with gr.Group(elem_id="sidebar-settings"):
|
| 480 |
+
sys_prompt = gr.Textbox(value=PRESETS["general"], label="System Prompt", lines=2)
|
| 481 |
+
thinking_radio = gr.Radio(choices=["โก Fast", "๐ง Thinking"], value="โก Fast", label="Mode")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 482 |
max_tok_sl = gr.Slider(64, 8192, value=4096, step=64, label="Max Tokens")
|
|
|
|
| 483 |
temp_sl = gr.Slider(0.0, 1.5, value=0.6, step=0.05, label="Temperature")
|
|
|
|
| 484 |
topp_sl = gr.Slider(0.1, 1.0, value=0.9, step=0.05, label="Top-P")
|
| 485 |
+
clear_btn = gr.Button("๐๏ธ Clear conversation", elem_id="clear-btn")
|
| 486 |
+
|
| 487 |
+
with gr.Column(scale=1, elem_id="main-col"):
|
| 488 |
+
gr.HTML(CHAT_HEADER_HTML)
|
| 489 |
+
chatbot = gr.Chatbot(
|
| 490 |
+
elem_id="chatbot", show_label=False,
|
| 491 |
+
placeholder=EXAMPLES_HTML,
|
| 492 |
+
latex_delimiters=[
|
| 493 |
+
{"left": "$$", "right": "$$", "display": True},
|
| 494 |
+
{"left": "$", "right": "$", "display": False},
|
| 495 |
+
{"left": "\\(", "right": "\\)", "display": False},
|
| 496 |
+
{"left": "\\[", "right": "\\]", "display": True},
|
| 497 |
+
],
|
| 498 |
+
)
|
| 499 |
+
image_input = gr.Textbox(value="", visible=False)
|
| 500 |
+
with gr.Row(elem_id="input-row"):
|
| 501 |
+
chat_input = gr.Textbox(placeholder="Message Gemma 4โฆ", lines=1, max_lines=5, scale=7, elem_id="chat-input", show_label=False, autofocus=True)
|
| 502 |
+
send_btn = gr.Button("โ", variant="primary", scale=0, min_width=48, elem_id="send-btn")
|
| 503 |
|
| 504 |
+
gr.HTML(BRIDGE_JS)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 505 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 506 |
def user_msg(message, history):
|
| 507 |
+
if not message.strip(): return "", history
|
| 508 |
+
return "", history + [{"role": "user", "content": message}]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 509 |
|
| 510 |
+
def bot_reply(history, thinking_mode, image_data, system_prompt, max_new_tokens, temperature, top_p, model_choice):
|
| 511 |
+
if not history or history[-1]["role"] != "user": return history
|
| 512 |
user_text = history[-1]["content"]
|
| 513 |
past = history[:-1]
|
|
|
|
| 514 |
history = history + [{"role": "assistant", "content": ""}]
|
| 515 |
+
for chunk in generate_reply(user_text, past, thinking_mode, image_data, system_prompt, max_new_tokens, temperature, top_p, model_choice):
|
|
|
|
|
|
|
|
|
|
|
|
|
| 516 |
history[-1]["content"] = chunk
|
| 517 |
yield history
|
| 518 |
|
| 519 |
+
common_inputs = [chatbot, thinking_radio, image_input, sys_prompt, max_tok_sl, temp_sl, topp_sl, model_dd]
|
| 520 |
+
send_btn.click(user_msg, [chat_input, chatbot], [chat_input, chatbot], queue=False).then(bot_reply, common_inputs, chatbot)
|
| 521 |
+
chat_input.submit(user_msg, [chat_input, chatbot], [chat_input, chatbot], queue=False).then(bot_reply, common_inputs, chatbot)
|
| 522 |
+
clear_btn.click(lambda: [], None, chatbot, queue=False)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 523 |
|
| 524 |
|
| 525 |
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 526 |
+
# 7. LAUNCH
|
| 527 |
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 528 |
if __name__ == "__main__":
|
| 529 |
print(f"[BOOT] Gemma 4 Playground ยท Default: {DEFAULT_MODEL}", flush=True)
|