SeaWolf-AI commited on
Commit
b8875ff
Β·
verified Β·
1 Parent(s): e3bb4f6

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +81 -70
app.py CHANGED
@@ -347,97 +347,95 @@ def generate_reply(
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
-
353
  footer { display: none !important; }
354
  .gradio-container { background: #faf8f5 !important; }
355
-
356
- .mcard { padding: 10px 12px; border-radius: 10px; border: 2px solid #e4dfd8; background: rgba(255,255,255,.6); cursor: pointer; transition: all .2s; margin-bottom: 6px; }
357
- .mcard:hover { border-color: rgba(109,40,217,.3); box-shadow: 0 2px 10px rgba(109,40,217,.08); }
358
- .mcard.active { border-color: #6d28d9 !important; background: linear-gradient(135deg, rgba(109,40,217,.06), rgba(16,185,129,.04)) !important; }
359
- .mc-row { display: flex; align-items: center; justify-content: space-between; margin-bottom: 4px; }
360
- .mc-name { font-size: 13px; font-weight: 700; }
361
- .mc-badge { font-size: 9px; font-weight: 700; padding: 2px 7px; border-radius: 8px; background: rgba(109,40,217,.08); color: #6d28d9; }
362
- .mc-stats { display: flex; gap: 4px; flex-wrap: wrap; margin-bottom: 4px; }
363
- .mc-stat { font-size: 9px; font-weight: 600; padding: 1px 6px; border-radius: 5px; }
364
- .mc-hl { background: rgba(109,40,217,.08); color: #6d28d9; }
365
- .mc-ok { background: rgba(22,163,74,.09); color: #16a34a; }
366
- .mc-desc { font-size: 10px; color: #78716c; }
367
- .mc-check { display: none; } .mcard.active .mc-check { display: inline; }
368
-
369
- .pchip { display: inline-block; font-size: 10px; font-weight: 600; padding: 3px 10px; border-radius: 16px; background: #ede9e3; border: 1px solid #e4dfd8; color: #78716c; cursor: pointer; transition: all .2s; margin: 2px; }
370
- .pchip:hover { background: rgba(109,40,217,.08); border-color: rgba(109,40,217,.25); color: #6d28d9; }
371
-
372
  #send-btn { background: linear-gradient(135deg, #6d28d9, #7c3aed) !important; border: none !important; border-radius: 12px !important; color: white !important; font-size: 18px !important; min-width: 48px !important; }
 
 
 
 
373
  """
374
 
375
- MODEL_CARDS = """
376
- <div class="mcard active" id="card-moe" onclick="window._sel('Gemma-4-26B-A4B-it')">
377
- <div class="mc-row"><span class="mc-name">⚑ Gemma 4 Β· 26B-A4B</span> <span class="mc-badge">MoE</span> <span class="mc-check">βœ“</span></div>
378
- <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>
379
- <div class="mc-desc">3.8B active / 26B total Β· 128 experts Β· Fast inference</div>
380
- </div>
381
- <div class="mcard" id="card-dense" onclick="window._sel('Gemma-4-31B-it')">
382
- <div class="mc-row"><span class="mc-name">πŸ† Gemma 4 Β· 31B</span> <span class="mc-badge">Dense</span> <span class="mc-check">βœ“</span></div>
383
- <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>
384
- <div class="mc-desc">30.7B Dense Β· Codeforces 2150 Β· Best quality</div>
385
- </div>
386
- """
387
-
388
- PRESETS_CHIPS = '<div style="margin-bottom:8px">' + ''.join(
389
- f'<span class="pchip" onclick="window._pre(\'{k}\')">{k.title()}</span>' for k in PRESETS
390
- ) + '</div>'
391
-
392
- JS = """<script>
393
- window._sel=function(n){
394
- document.querySelectorAll('.mcard').forEach(function(c){c.classList.remove('active')});
395
- document.getElementById(n==='Gemma-4-26B-A4B-it'?'card-moe':'card-dense').classList.add('active');
396
- var d=document.querySelector('#model-dd input');
397
- if(d){var s=Object.getOwnPropertyDescriptor(HTMLInputElement.prototype,'value').set;s.call(d,n);d.dispatchEvent(new Event('input',{bubbles:true}));}
398
- };
399
- window._pre=function(k){
400
- var p=""" + json.dumps(PRESETS) + """;
401
- var t=document.querySelector('#sys-prompt textarea');
402
- if(t){var s=Object.getOwnPropertyDescriptor(HTMLTextAreaElement.prototype,'value').set;s.call(t,p[k]||p.general);t.dispatchEvent(new Event('input',{bubbles:true}));}
403
- };
404
- </script>"""
405
 
406
  with gr.Blocks(title="Gemma 4 Playground") as demo:
407
 
408
- gr.Markdown("## πŸ’Ž Gemma 4 Playground\nGoogle DeepMind Β· Dense 31B / MoE 26B-A4B Β· Vision Β· Thinking Β· Apache 2.0")
409
 
410
  with gr.Row():
411
- # ── Sidebar ──
412
- with gr.Column(scale=0, min_width=280):
413
- gr.HTML(MODEL_CARDS)
414
- model_dd = gr.Dropdown(choices=list(MODELS.keys()), value=DEFAULT_MODEL, elem_id="model-dd", visible=False)
415
-
416
- gr.HTML(PRESETS_CHIPS)
417
- sys_prompt = gr.Textbox(value=PRESETS["general"], label="System Prompt", lines=2, elem_id="sys-prompt")
418
- thinking_radio = gr.Radio(["⚑ Fast", "🧠 Thinking"], value="⚑ Fast", label="Mode")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
419
  max_tok = gr.Slider(64, 8192, value=4096, step=64, label="Max Tokens")
420
  temp = gr.Slider(0.0, 1.5, value=0.6, step=0.05, label="Temperature")
421
  topp = gr.Slider(0.1, 1.0, value=0.9, step=0.05, label="Top-P")
422
- clear_btn = gr.Button("πŸ—‘οΈ Clear", size="sm")
423
 
424
- # ── Chat ──
425
  with gr.Column(scale=3):
426
- chatbot = gr.Chatbot(elem_id="chatbot", show_label=False, height=550)
427
- image_input = gr.Textbox(value="", visible=False)
428
  with gr.Row():
429
- chat_input = gr.Textbox(placeholder="Message Gemma 4…", show_label=False, scale=7, autofocus=True, lines=1, max_lines=4, elem_id="chat-input")
 
 
 
430
  send_btn = gr.Button("↑", variant="primary", scale=0, min_width=48, elem_id="send-btn")
431
 
432
- gr.HTML(JS)
 
 
 
 
 
433
 
434
- # ── Logic ──
 
 
 
 
 
 
 
435
  def user_msg(msg, hist):
436
- if not msg.strip(): return "", hist
 
437
  return "", hist + [{"role": "user", "content": msg}]
438
 
439
  def bot_reply(hist, think, img, sysp, maxt, tmp, tp, model):
440
- if not hist or hist[-1]["role"] != "user": return hist
 
441
  txt, past = hist[-1]["content"], hist[:-1]
442
  hist = hist + [{"role": "assistant", "content": ""}]
443
  for chunk in generate_reply(txt, past, think, img, sysp, maxt, tmp, tp, model):
@@ -445,10 +443,23 @@ with gr.Blocks(title="Gemma 4 Playground") as demo:
445
  yield hist
446
 
447
  ins = [chatbot, thinking_radio, image_input, sys_prompt, max_tok, temp, topp, model_dd]
448
- send_btn.click(user_msg, [chat_input, chatbot], [chat_input, chatbot], queue=False).then(bot_reply, ins, chatbot)
449
- chat_input.submit(user_msg, [chat_input, chatbot], [chat_input, chatbot], queue=False).then(bot_reply, ins, chatbot)
 
 
 
 
 
 
 
 
 
450
  clear_btn.click(lambda: [], None, chatbot, queue=False)
451
 
 
 
 
 
452
  if __name__ == "__main__":
453
  print(f"[BOOT] Gemma 4 Playground Β· Default: {DEFAULT_MODEL}", flush=True)
454
  demo.launch(server_name="0.0.0.0", server_port=7860, css=CSS)
 
347
  # ══════════════════════════════════════════════════════════════════════════════
348
 
349
  CSS = """
 
 
 
350
  footer { display: none !important; }
351
  .gradio-container { background: #faf8f5 !important; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
352
  #send-btn { background: linear-gradient(135deg, #6d28d9, #7c3aed) !important; border: none !important; border-radius: 12px !important; color: white !important; font-size: 18px !important; min-width: 48px !important; }
353
+ #chatbot { border: 1.5px solid #e4dfd8 !important; border-radius: 14px !important; background: rgba(255,255,255,.65) !important; }
354
+ .model-info-box { padding: 10px 14px; border-radius: 10px; border: 1.5px solid rgba(109,40,217,.2); background: linear-gradient(135deg, rgba(109,40,217,.04), rgba(16,185,129,.03)); font-size: 12px; line-height: 1.6; }
355
+ .model-info-box b { color: #6d28d9; }
356
+ .model-info-box .stats { font-size: 10px; color: #78716c; margin-top: 4px; }
357
  """
358
 
359
+ # Model info display (updates when dropdown changes)
360
+ def _model_info_html(name):
361
+ m = MODELS.get(name, MODELS[DEFAULT_MODEL])
362
+ return (
363
+ f'<div class="model-info-box">'
364
+ f'<b>{"⚑" if m["arch"]=="MoE" else "πŸ†"} {name}</b> '
365
+ f'<span style="font-size:9px;padding:2px 6px;border-radius:6px;background:rgba(109,40,217,.08);color:#6d28d9;font-weight:700">{m["arch"]}</span><br>'
366
+ f'<div class="stats">{m["active"]} active / {m["total"]} total Β· πŸ‘οΈ Vision Β· {m["ctx"]} context<br>{m["desc"]}</div>'
367
+ f'</div>'
368
+ )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
369
 
370
  with gr.Blocks(title="Gemma 4 Playground") as demo:
371
 
372
+ gr.Markdown("## πŸ’Ž Gemma 4 Playground\nGoogle DeepMind Β· Dense 31B or MoE 26B-A4B Β· Vision Β· Thinking Β· Apache 2.0")
373
 
374
  with gr.Row():
375
+ # ══ Sidebar ══
376
+ with gr.Column(scale=0, min_width=300):
377
+
378
+ gr.Markdown("#### Select Model")
379
+ model_dd = gr.Dropdown(
380
+ choices=list(MODELS.keys()), value=DEFAULT_MODEL,
381
+ label="Model", elem_id="model-dd",
382
+ info="MoE=Fast inference | Dense=Best quality",
383
+ )
384
+ model_info = gr.HTML(value=_model_info_html(DEFAULT_MODEL))
385
+
386
+ gr.Markdown("---")
387
+ gr.Markdown("#### πŸ‘οΈ Vision")
388
+ image_input = gr.Image(label="Upload image", type="filepath", height=150)
389
+
390
+ gr.Markdown("---")
391
+ gr.Markdown("#### Settings")
392
+ thinking_radio = gr.Radio(
393
+ ["⚑ Fast", "🧠 Thinking"], value="⚑ Fast", label="Mode",
394
+ )
395
+ sys_prompt = gr.Textbox(
396
+ value=PRESETS["general"], label="System Prompt", lines=2,
397
+ )
398
+ preset_dd = gr.Dropdown(
399
+ choices=list(PRESETS.keys()), value="general", label="Preset",
400
+ )
401
  max_tok = gr.Slider(64, 8192, value=4096, step=64, label="Max Tokens")
402
  temp = gr.Slider(0.0, 1.5, value=0.6, step=0.05, label="Temperature")
403
  topp = gr.Slider(0.1, 1.0, value=0.9, step=0.05, label="Top-P")
404
+ clear_btn = gr.Button("πŸ—‘οΈ Clear conversation", size="sm")
405
 
406
+ # ══ Chat ══
407
  with gr.Column(scale=3):
408
+ chatbot = gr.Chatbot(elem_id="chatbot", show_label=False, height=600)
 
409
  with gr.Row():
410
+ chat_input = gr.Textbox(
411
+ placeholder="Message Gemma 4…", show_label=False,
412
+ scale=7, autofocus=True, lines=1, max_lines=4,
413
+ )
414
  send_btn = gr.Button("↑", variant="primary", scale=0, min_width=48, elem_id="send-btn")
415
 
416
+ # ── Events: model info update ──
417
+ model_dd.change(
418
+ fn=_model_info_html,
419
+ inputs=[model_dd],
420
+ outputs=[model_info],
421
+ )
422
 
423
+ # ── Events: preset β†’ system prompt ──
424
+ preset_dd.change(
425
+ fn=lambda k: PRESETS.get(k, PRESETS["general"]),
426
+ inputs=[preset_dd],
427
+ outputs=[sys_prompt],
428
+ )
429
+
430
+ # ── Chat logic ──
431
  def user_msg(msg, hist):
432
+ if not msg.strip():
433
+ return "", hist
434
  return "", hist + [{"role": "user", "content": msg}]
435
 
436
  def bot_reply(hist, think, img, sysp, maxt, tmp, tp, model):
437
+ if not hist or hist[-1]["role"] != "user":
438
+ return hist
439
  txt, past = hist[-1]["content"], hist[:-1]
440
  hist = hist + [{"role": "assistant", "content": ""}]
441
  for chunk in generate_reply(txt, past, think, img, sysp, maxt, tmp, tp, model):
 
443
  yield hist
444
 
445
  ins = [chatbot, thinking_radio, image_input, sys_prompt, max_tok, temp, topp, model_dd]
446
+
447
+ send_btn.click(
448
+ user_msg, [chat_input, chatbot], [chat_input, chatbot], queue=False
449
+ ).then(
450
+ bot_reply, ins, chatbot
451
+ )
452
+ chat_input.submit(
453
+ user_msg, [chat_input, chatbot], [chat_input, chatbot], queue=False
454
+ ).then(
455
+ bot_reply, ins, chatbot
456
+ )
457
  clear_btn.click(lambda: [], None, chatbot, queue=False)
458
 
459
+
460
+ # ════════��═════════════════════════════════════════════════════════════════════
461
+ # 7. LAUNCH
462
+ # ══════════════════════════════════════════════════════════════════════════════
463
  if __name__ == "__main__":
464
  print(f"[BOOT] Gemma 4 Playground Β· Default: {DEFAULT_MODEL}", flush=True)
465
  demo.launch(server_name="0.0.0.0", server_port=7860, css=CSS)