Spaces:
Running on Zero
Running on Zero
Update app.py
Browse files
app.py
CHANGED
|
@@ -343,28 +343,36 @@ def generate_reply(
|
|
| 343 |
# ══════════════════════════════════════════════════════════════════════════════
|
| 344 |
|
| 345 |
# ══════════════════════════════════════════════════════════════════════════════
|
| 346 |
-
# 6. GRADIO UI
|
| 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:
|
| 359 |
-
.orb2{width:
|
| 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 |
-
|
| 363 |
-
#
|
|
|
|
|
|
|
|
|
|
| 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}
|
|
@@ -372,6 +380,7 @@ footer,.svelte-1rjryqp{display:none!important}
|
|
| 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)}
|
|
@@ -384,40 +393,41 @@ footer,.svelte-1rjryqp{display:none!important}
|
|
| 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;
|
| 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 |
-
|
| 401 |
-
#main-col
|
| 402 |
-
#chat-header{padding:12px 20px;border-bottom:1px solid var(--line);background:rgba(255,255,255,.8);backdrop-filter:blur(20px);
|
|
|
|
| 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 |
-
|
|
|
|
|
|
|
| 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 |
-
|
|
|
|
|
|
|
| 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){
|
|
|
|
|
|
|
|
|
|
| 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>'
|
|
@@ -436,14 +446,7 @@ MODEL_CARDS_HTML = """<div class="sec-lbl">Select Model</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){
|
|
@@ -453,16 +456,16 @@ window._selectModel=function(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
|
| 457 |
};
|
| 458 |
window._sendEx=function(text){
|
| 459 |
var ta=document.querySelector('#chat-input textarea');
|
| 460 |
-
if(ta){var
|
| 461 |
};
|
| 462 |
window._setPreset=function(key){
|
| 463 |
-
var
|
| 464 |
var ta=document.querySelector('#sidebar-settings textarea');
|
| 465 |
-
if(ta){var
|
| 466 |
};
|
| 467 |
</script>"""
|
| 468 |
|
|
@@ -470,7 +473,9 @@ window._setPreset=function(key){
|
|
| 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)
|
|
@@ -484,11 +489,14 @@ with gr.Blocks(title="Gemma 4 Playground", fill_height=True) as demo:
|
|
| 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",
|
| 491 |
-
|
|
|
|
| 492 |
latex_delimiters=[
|
| 493 |
{"left": "$$", "right": "$$", "display": True},
|
| 494 |
{"left": "$", "right": "$", "display": False},
|
|
@@ -496,19 +504,27 @@ with gr.Blocks(title="Gemma 4 Playground", fill_height=True) as demo:
|
|
| 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(
|
|
|
|
|
|
|
|
|
|
| 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():
|
|
|
|
| 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":
|
|
|
|
| 512 |
user_text = history[-1]["content"]
|
| 513 |
past = history[:-1]
|
| 514 |
history = history + [{"role": "assistant", "content": ""}]
|
|
|
|
| 343 |
# ══════════════════════════════════════════════════════════════════════════════
|
| 344 |
|
| 345 |
# ══════════════════════════════════════════════════════════════════════════════
|
| 346 |
+
# 6. GRADIO UI
|
| 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 |
+
|
| 354 |
+
/* === FIX: lock viewport, kill all outer scrolling === */
|
| 355 |
+
html,body,.gradio-container,.main,.wrap,.contain{overflow:hidden!important;height:100vh!important;max-height:100vh!important}
|
| 356 |
.gradio-container{background:var(--cream)!important;font-family:'Cabinet Grotesk',sans-serif!important;max-width:100%!important;padding:0!important}
|
| 357 |
footer,.svelte-1rjryqp{display:none!important}
|
| 358 |
|
| 359 |
+
/* Background orbs */
|
| 360 |
#orbs{position:fixed;inset:0;z-index:0;pointer-events:none;overflow:hidden}
|
| 361 |
+
.orb{position:absolute;border-radius:50%;filter:blur(80px);opacity:.4;animation:drift 22s linear infinite}
|
| 362 |
+
.orb1{width:450px;height:450px;background:radial-gradient(circle,rgba(109,40,217,.3),transparent 70%);top:-80px;left:-80px}
|
| 363 |
+
.orb2{width:350px;height:350px;background:radial-gradient(circle,rgba(16,185,129,.25),transparent 70%);top:5%;right:-50px;animation-delay:-9s}
|
| 364 |
@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)}}
|
| 365 |
|
| 366 |
+
/* === Shell: sidebar + main === */
|
| 367 |
+
#shell-row{height:100vh!important;overflow:hidden!important;flex-wrap:nowrap!important;gap:0!important;padding:0!important;position:relative;z-index:1}
|
| 368 |
+
|
| 369 |
+
/* === Sidebar === */
|
| 370 |
+
#sidebar{background:rgba(255,255,255,.78)!important;backdrop-filter:blur(24px);border-right:1px solid var(--line)!important;overflow-y:auto!important;overflow-x:hidden!important;padding:0!important;border-radius:0!important;max-width:280px!important;min-width:280px!important;height:100vh!important}
|
| 371 |
#sidebar::-webkit-scrollbar{width:3px}
|
| 372 |
#sidebar::-webkit-scrollbar-thumb{background:var(--line);border-radius:10px}
|
| 373 |
+
#sidebar .gr-group{background:none!important;border:none!important;padding:0!important;box-shadow:none!important}
|
| 374 |
|
| 375 |
+
/* Logo */
|
| 376 |
#logo-area{padding:18px 16px 14px;border-bottom:1px solid var(--line)}
|
| 377 |
.logo-row{display:flex;align-items:center;gap:10px}
|
| 378 |
.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}
|
|
|
|
| 380 |
.logo-name em{color:var(--v);font-style:italic}
|
| 381 |
.logo-sub{font-size:9px;font-weight:700;letter-spacing:2px;text-transform:uppercase;color:var(--ink4)}
|
| 382 |
|
| 383 |
+
/* Model cards */
|
| 384 |
.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}
|
| 385 |
.mcard:hover{border-color:rgba(109,40,217,.3);box-shadow:0 2px 12px rgba(109,40,217,.08)}
|
| 386 |
.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)}
|
|
|
|
| 393 |
.mc-ok{background:rgba(22,163,74,.09);color:#16a34a}
|
| 394 |
.mc-desc{font-size:9px;color:var(--ink3);line-height:1.5}
|
| 395 |
.mc-check{display:none;font-size:14px}.mcard.active .mc-check{display:inline}
|
|
|
|
| 396 |
.sec-lbl{font-size:8px;font-weight:700;letter-spacing:2.5px;text-transform:uppercase;color:var(--ink4);padding:10px 14px 4px}
|
| 397 |
.preset-chips{display:flex;flex-wrap:wrap;gap:3px;padding:0 14px 6px}
|
| 398 |
.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}
|
| 399 |
.pchip:hover{background:rgba(109,40,217,.08);border-color:rgba(109,40,217,.25);color:var(--v)}
|
| 400 |
+
#sidebar-settings{padding:4px 12px 12px}
|
|
|
|
| 401 |
#sidebar-settings label span{font-size:11px!important;font-weight:600!important;color:var(--ink3)!important}
|
| 402 |
+
#sidebar-settings textarea{background:var(--fog)!important;border:1.5px solid var(--line)!important;border-radius:8px!important;font-size:11px!important;min-height:50px!important}
|
| 403 |
#sidebar-settings textarea:focus{border-color:rgba(109,40,217,.35)!important;box-shadow:0 0 0 3px rgba(109,40,217,.08)!important}
|
| 404 |
#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}
|
| 405 |
#clear-btn:hover{border-color:rgba(225,29,72,.3)!important;color:#e11d48!important}
|
| 406 |
|
| 407 |
+
/* === Main column === */
|
| 408 |
+
#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-radius:0!important;border:none!important}
|
| 409 |
+
#chat-header{padding:12px 20px;border-bottom:1px solid var(--line);background:rgba(255,255,255,.8);backdrop-filter:blur(20px);flex-shrink:0}
|
| 410 |
+
.hdr-row{display:flex;align-items:center;gap:10px}
|
| 411 |
.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}
|
| 412 |
@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)}}
|
| 413 |
.hdr-model-name{font-size:12px;font-weight:700;color:var(--v);font-family:'Geist Mono',monospace}
|
| 414 |
.hdr-model-meta{font-size:10px;color:var(--ink4);margin-left:auto;font-family:'Geist Mono',monospace}
|
| 415 |
|
| 416 |
+
/* === CHATBOT: fill remaining space, internal scroll === */
|
| 417 |
+
#chatbot{flex:1 1 0!important;min-height:0!important;max-height:none!important;height:auto!important;overflow-y:auto!important;border:none!important;border-radius:0!important;background:transparent!important}
|
| 418 |
+
#chatbot>.wrapper{height:100%!important;max-height:none!important}
|
| 419 |
#chatbot .bot{background:rgba(109,40,217,.03)!important;border-left:3px solid rgba(109,40,217,.15)!important;border-radius:12px!important}
|
| 420 |
+
|
| 421 |
+
/* === Input row: fixed at bottom === */
|
| 422 |
+
#input-row{padding:10px 16px!important;border-top:1px solid var(--line)!important;background:rgba(255,255,255,.85)!important;backdrop-filter:blur(20px);flex-shrink:0!important;flex-grow:0!important}
|
| 423 |
#chat-input textarea{border-radius:14px!important;border:1.5px solid var(--line)!important;background:white!important;font-size:13px!important}
|
| 424 |
#chat-input textarea:focus{border-color:rgba(109,40,217,.35)!important;box-shadow:0 0 0 3px rgba(109,40,217,.08)!important}
|
| 425 |
#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}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 426 |
|
| 427 |
+
@media(max-width:768px){
|
| 428 |
+
#shell-row{flex-direction:column!important}
|
| 429 |
+
#sidebar{display:none!important}
|
| 430 |
+
}
|
| 431 |
"""
|
| 432 |
|
| 433 |
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>'
|
|
|
|
| 446 |
|
| 447 |
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>'
|
| 448 |
|
| 449 |
+
CHAT_HEADER_HTML = '<div id="chat-header"><div class="hdr-row"><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></div>'
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 450 |
|
| 451 |
BRIDGE_JS = """<script>
|
| 452 |
window._selectModel=function(name){
|
|
|
|
| 456 |
var meta={'Gemma-4-26B-A4B-it':'MoE · 3.8B active · 256K ctx','Gemma-4-31B-it':'Dense · 30.7B · 256K ctx'};
|
| 457 |
var hm=document.getElementById('hdrModelMeta');if(hm)hm.textContent=meta[name]||'';
|
| 458 |
var dd=document.querySelector('#model-select input');
|
| 459 |
+
if(dd){var ns=Object.getOwnPropertyDescriptor(HTMLInputElement.prototype,'value').set;ns.call(dd,name);dd.dispatchEvent(new Event('input',{bubbles:true}));}
|
| 460 |
};
|
| 461 |
window._sendEx=function(text){
|
| 462 |
var ta=document.querySelector('#chat-input textarea');
|
| 463 |
+
if(ta){var ns=Object.getOwnPropertyDescriptor(HTMLTextAreaElement.prototype,'value').set;ns.call(ta,text);ta.dispatchEvent(new Event('input',{bubbles:true}));ta.focus();}
|
| 464 |
};
|
| 465 |
window._setPreset=function(key){
|
| 466 |
+
var p={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.',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.'};
|
| 467 |
var ta=document.querySelector('#sidebar-settings textarea');
|
| 468 |
+
if(ta){var ns=Object.getOwnPropertyDescriptor(HTMLTextAreaElement.prototype,'value').set;ns.call(ta,p[key]||p.general);ta.dispatchEvent(new Event('input',{bubbles:true}));}
|
| 469 |
};
|
| 470 |
</script>"""
|
| 471 |
|
|
|
|
| 473 |
with gr.Blocks(title="Gemma 4 Playground", fill_height=True) as demo:
|
| 474 |
gr.HTML('<div id="orbs"><div class="orb orb1"></div><div class="orb orb2"></div></div>')
|
| 475 |
|
| 476 |
+
with gr.Row(elem_id="shell-row", equal_height=True):
|
| 477 |
+
|
| 478 |
+
# ═══ SIDEBAR ═══
|
| 479 |
with gr.Column(scale=0, min_width=280, elem_id="sidebar"):
|
| 480 |
gr.HTML(SIDEBAR_LOGO)
|
| 481 |
gr.HTML(MODEL_CARDS_HTML)
|
|
|
|
| 489 |
topp_sl = gr.Slider(0.1, 1.0, value=0.9, step=0.05, label="Top-P")
|
| 490 |
clear_btn = gr.Button("🗑️ Clear conversation", elem_id="clear-btn")
|
| 491 |
|
| 492 |
+
# ═══ MAIN ═══
|
| 493 |
with gr.Column(scale=1, elem_id="main-col"):
|
| 494 |
gr.HTML(CHAT_HEADER_HTML)
|
| 495 |
+
|
| 496 |
chatbot = gr.Chatbot(
|
| 497 |
+
elem_id="chatbot",
|
| 498 |
+
show_label=False,
|
| 499 |
+
height="calc(100vh - 140px)",
|
| 500 |
latex_delimiters=[
|
| 501 |
{"left": "$$", "right": "$$", "display": True},
|
| 502 |
{"left": "$", "right": "$", "display": False},
|
|
|
|
| 504 |
{"left": "\\[", "right": "\\]", "display": True},
|
| 505 |
],
|
| 506 |
)
|
| 507 |
+
|
| 508 |
image_input = gr.Textbox(value="", visible=False)
|
| 509 |
+
|
| 510 |
with gr.Row(elem_id="input-row"):
|
| 511 |
+
chat_input = gr.Textbox(
|
| 512 |
+
placeholder="Message Gemma 4…", lines=1, max_lines=4,
|
| 513 |
+
scale=7, elem_id="chat-input", show_label=False, autofocus=True,
|
| 514 |
+
)
|
| 515 |
send_btn = gr.Button("↑", variant="primary", scale=0, min_width=48, elem_id="send-btn")
|
| 516 |
|
| 517 |
gr.HTML(BRIDGE_JS)
|
| 518 |
|
| 519 |
+
# ── Chat logic ──
|
| 520 |
def user_msg(message, history):
|
| 521 |
+
if not message.strip():
|
| 522 |
+
return "", history
|
| 523 |
return "", history + [{"role": "user", "content": message}]
|
| 524 |
|
| 525 |
def bot_reply(history, thinking_mode, image_data, system_prompt, max_new_tokens, temperature, top_p, model_choice):
|
| 526 |
+
if not history or history[-1]["role"] != "user":
|
| 527 |
+
return history
|
| 528 |
user_text = history[-1]["content"]
|
| 529 |
past = history[:-1]
|
| 530 |
history = history + [{"role": "assistant", "content": ""}]
|