Gogs commited on
Commit
3ce8ecc
·
1 Parent(s): f709304

🔧 Switch to Inference API (no local model loading)

Browse files
Files changed (1) hide show
  1. app.py +107 -409
app.py CHANGED
@@ -13,14 +13,13 @@ tokenizer = None
13
 
14
 
15
  def load_model():
16
- """Load the Yuuki model with proper error handling."""
17
  global model, tokenizer, MODEL_LOADED
18
 
19
  if MODEL_LOADED:
20
  return True
21
 
22
  try:
23
- print(f"Loading Yuuki model from {MODEL_ID}...")
24
 
25
  tokenizer = AutoTokenizer.from_pretrained(MODEL_ID)
26
  model = AutoModelForCausalLM.from_pretrained(
@@ -50,7 +49,6 @@ def generate_code(
50
  top_k: int = 50,
51
  repetition_penalty: float = 1.1
52
  ) -> str:
53
- """Generate code completion using Yuuki."""
54
 
55
  if not MODEL_LOADED:
56
  if not load_model():
@@ -89,30 +87,10 @@ def generate_code(
89
 
90
 
91
  # ============================================================================
92
- # Examples
93
- # ============================================================================
94
-
95
- EXAMPLES = [
96
- ["module Main where"],
97
- ["open import Data.Nat"],
98
- ["data Bool : Set where"],
99
- ["int main() {"],
100
- ["#include <stdio.h>"],
101
- ["mov eax,"],
102
- ["def hello():"],
103
- ]
104
-
105
-
106
- # ============================================================================
107
- # CSS - Professional Dark Theme (Vercel/ChatGPT Style)
108
  # ============================================================================
109
 
110
  CUSTOM_CSS = """
111
- /* Reset and base */
112
- * {
113
- box-sizing: border-box;
114
- }
115
-
116
  .gradio-container {
117
  max-width: 100% !important;
118
  padding: 0 !important;
@@ -125,20 +103,10 @@ CUSTOM_CSS = """
125
  background: #0a0a0a !important;
126
  }
127
 
128
- /* Hide default footer */
129
  footer {
130
  display: none !important;
131
  }
132
 
133
- /* Main app container */
134
- #app-container {
135
- display: flex;
136
- flex-direction: column;
137
- min-height: 100vh;
138
- background: #0a0a0a;
139
- }
140
-
141
- /* Header */
142
  #header {
143
  display: flex;
144
  align-items: center;
@@ -146,66 +114,28 @@ footer {
146
  padding: 16px 24px;
147
  border-bottom: 1px solid #1f1f1f;
148
  background: #0a0a0a;
149
- position: sticky;
150
- top: 0;
151
- z-index: 100;
152
  }
153
 
154
  #logo {
155
  font-size: 1.25rem;
156
  font-weight: 600;
157
  color: #fafafa;
158
- letter-spacing: -0.02em;
159
  }
160
 
161
- #logo span {
162
  color: #666;
163
  font-weight: 400;
164
  font-size: 0.875rem;
165
  margin-left: 8px;
166
  }
167
 
168
- #nav-buttons {
169
- display: flex;
170
- gap: 4px;
171
- }
172
-
173
- .nav-btn {
174
- background: transparent !important;
175
- border: none !important;
176
- color: #a1a1a1 !important;
177
- padding: 8px 16px !important;
178
- font-size: 0.875rem !important;
179
- font-weight: 500 !important;
180
- border-radius: 6px !important;
181
- cursor: pointer !important;
182
- transition: all 0.15s ease !important;
183
- }
184
-
185
- .nav-btn:hover {
186
- background: #1f1f1f !important;
187
- color: #fafafa !important;
188
- }
189
-
190
- .nav-btn.active {
191
- background: #1f1f1f !important;
192
- color: #fafafa !important;
193
- }
194
-
195
- /* Chat area */
196
- #chat-area {
197
- flex: 1;
198
- display: flex;
199
- flex-direction: column;
200
- align-items: center;
201
- justify-content: center;
202
- padding: 40px 24px;
203
  max-width: 800px;
204
  margin: 0 auto;
205
- width: 100%;
206
  }
207
 
208
- #welcome-section {
209
  text-align: center;
210
  margin-bottom: 32px;
211
  }
@@ -215,105 +145,56 @@ footer {
215
  font-weight: 600;
216
  color: #fafafa;
217
  margin-bottom: 8px;
218
- letter-spacing: -0.03em;
219
  }
220
 
221
  #welcome-subtitle {
222
  font-size: 1rem;
223
  color: #666;
224
- margin-bottom: 24px;
225
- }
226
-
227
- /* Output display */
228
- #output-container {
229
- width: 100%;
230
- margin-bottom: 24px;
231
  }
232
 
233
- #output-box {
234
- background: #141414 !important;
235
- border: 1px solid #262626 !important;
236
- border-radius: 12px !important;
237
- min-height: 200px;
 
 
 
 
 
238
  }
239
 
240
  #output-box textarea {
241
- background: transparent !important;
242
  color: #e5e5e5 !important;
243
- font-family: 'SF Mono', 'Fira Code', 'Consolas', monospace !important;
244
  font-size: 0.875rem !important;
245
- line-height: 1.6 !important;
246
- padding: 16px !important;
247
- }
248
-
249
- #output-box label {
250
- color: #666 !important;
251
- font-size: 0.75rem !important;
252
- text-transform: uppercase !important;
253
- letter-spacing: 0.05em !important;
254
- }
255
-
256
- /* Input area */
257
- #input-container {
258
- width: 100%;
259
- position: relative;
260
- }
261
-
262
- #input-box {
263
- background: #141414 !important;
264
  border: 1px solid #262626 !important;
265
  border-radius: 12px !important;
266
- transition: border-color 0.15s ease !important;
267
- }
268
-
269
- #input-box:focus-within {
270
- border-color: #404040 !important;
271
  }
272
 
273
  #input-box textarea {
274
- background: transparent !important;
275
  color: #fafafa !important;
276
- font-size: 1rem !important;
277
- padding: 16px !important;
278
- padding-right: 100px !important;
279
  }
280
 
281
  #input-box textarea::placeholder {
282
  color: #525252 !important;
283
  }
284
 
285
- #input-box label {
286
- display: none !important;
287
- }
288
-
289
  #generate-btn {
290
- position: absolute !important;
291
- right: 8px !important;
292
- bottom: 8px !important;
293
  background: #fafafa !important;
294
  color: #0a0a0a !important;
295
  border: none !important;
296
  border-radius: 8px !important;
297
- padding: 8px 16px !important;
298
  font-weight: 600 !important;
299
- font-size: 0.875rem !important;
300
- cursor: pointer !important;
301
- transition: all 0.15s ease !important;
302
  }
303
 
304
  #generate-btn:hover {
305
  background: #e5e5e5 !important;
306
- transform: translateY(-1px) !important;
307
- }
308
-
309
- #generate-btn:active {
310
- transform: translateY(0) !important;
311
- }
312
-
313
- /* Examples */
314
- #examples-container {
315
- width: 100%;
316
- margin-top: 16px;
317
  }
318
 
319
  #examples-label {
@@ -322,24 +203,15 @@ footer {
322
  text-transform: uppercase;
323
  letter-spacing: 0.05em;
324
  margin-bottom: 12px;
325
- }
326
-
327
- #examples-grid {
328
- display: flex;
329
- flex-wrap: wrap;
330
- gap: 8px;
331
  }
332
 
333
  .example-btn {
334
  background: #141414 !important;
335
  border: 1px solid #262626 !important;
336
  color: #a1a1a1 !important;
337
- padding: 8px 14px !important;
338
- font-size: 0.8rem !important;
339
- font-family: 'SF Mono', monospace !important;
340
  border-radius: 8px !important;
341
- cursor: pointer !important;
342
- transition: all 0.15s ease !important;
343
  }
344
 
345
  .example-btn:hover {
@@ -348,14 +220,6 @@ footer {
348
  color: #fafafa !important;
349
  }
350
 
351
- /* Tabs/Panels */
352
- #panel-container {
353
- width: 100%;
354
- max-width: 800px;
355
- margin: 0 auto;
356
- padding: 24px;
357
- }
358
-
359
  .panel-section {
360
  background: #141414;
361
  border: 1px solid #262626;
@@ -369,49 +233,8 @@ footer {
369
  font-weight: 600;
370
  color: #fafafa;
371
  margin-bottom: 16px;
372
- display: flex;
373
- align-items: center;
374
- gap: 8px;
375
- }
376
-
377
- .panel-title::before {
378
- content: '';
379
- width: 4px;
380
- height: 16px;
381
- background: #fafafa;
382
- border-radius: 2px;
383
- }
384
-
385
- /* Settings sliders */
386
- .settings-grid {
387
- display: grid;
388
- grid-template-columns: repeat(2, 1fr);
389
- gap: 16px;
390
  }
391
 
392
- @media (max-width: 640px) {
393
- .settings-grid {
394
- grid-template-columns: 1fr;
395
- }
396
- }
397
-
398
- /* Override Gradio slider styles */
399
- .gr-slider input[type="range"] {
400
- background: #262626 !important;
401
- }
402
-
403
- .gr-slider label {
404
- color: #a1a1a1 !important;
405
- font-size: 0.8rem !important;
406
- }
407
-
408
- .gr-slider .gr-input {
409
- background: #1f1f1f !important;
410
- border: 1px solid #262626 !important;
411
- color: #fafafa !important;
412
- }
413
-
414
- /* Info cards in panels */
415
  .info-row {
416
  display: flex;
417
  justify-content: space-between;
@@ -434,12 +257,10 @@ footer {
434
  font-weight: 500;
435
  }
436
 
437
- /* Score badges */
438
  .score-grid {
439
  display: flex;
440
  gap: 8px;
441
  flex-wrap: wrap;
442
- margin-top: 12px;
443
  }
444
 
445
  .score-badge {
@@ -449,25 +270,24 @@ footer {
449
  font-weight: 600;
450
  }
451
 
452
- .score-badge.good {
453
  background: rgba(34, 197, 94, 0.15);
454
  color: #22c55e;
455
  border: 1px solid rgba(34, 197, 94, 0.3);
456
  }
457
 
458
- .score-badge.medium {
459
  background: rgba(234, 179, 8, 0.15);
460
  color: #eab308;
461
  border: 1px solid rgba(234, 179, 8, 0.3);
462
  }
463
 
464
- .score-badge.weak {
465
  background: rgba(239, 68, 68, 0.15);
466
  color: #ef4444;
467
  border: 1px solid rgba(239, 68, 68, 0.3);
468
  }
469
 
470
- /* Comparison table */
471
  .comparison-table {
472
  width: 100%;
473
  border-collapse: collapse;
@@ -486,18 +306,16 @@ footer {
486
  font-weight: 500;
487
  font-size: 0.75rem;
488
  text-transform: uppercase;
489
- letter-spacing: 0.05em;
490
  }
491
 
492
  .comparison-table td {
493
  color: #a1a1a1;
494
  }
495
 
496
- .comparison-table td strong {
497
  color: #22c55e;
498
  }
499
 
500
- /* Links */
501
  .links-grid {
502
  display: flex;
503
  gap: 16px;
@@ -508,26 +326,16 @@ footer {
508
  color: #a1a1a1;
509
  text-decoration: none;
510
  font-size: 0.875rem;
511
- padding: 8px 0;
512
- transition: color 0.15s ease;
513
  }
514
 
515
  .link-item:hover {
516
  color: #fafafa;
517
  }
518
 
519
- /* Tab styling override */
520
- .gr-tab-nav {
521
- background: transparent !important;
522
- border: none !important;
523
- }
524
-
525
  .gr-tab-nav button {
526
  background: transparent !important;
527
  border: none !important;
528
  color: #666 !important;
529
- font-size: 0.875rem !important;
530
- padding: 12px 16px !important;
531
  }
532
 
533
  .gr-tab-nav button.selected {
@@ -535,68 +343,18 @@ footer {
535
  border-bottom: 2px solid #fafafa !important;
536
  }
537
 
538
- /* Disclaimer banner */
539
- #disclaimer-banner {
540
- background: #18181b;
541
- border: 1px solid #27272a;
542
- border-radius: 8px;
543
- padding: 12px 16px;
544
- margin-bottom: 24px;
545
- display: flex;
546
- align-items: flex-start;
547
- gap: 12px;
548
- }
549
-
550
- #disclaimer-icon {
551
- color: #eab308;
552
- font-size: 1rem;
553
- flex-shrink: 0;
554
- margin-top: 2px;
555
- }
556
-
557
- #disclaimer-text {
558
- color: #a1a1a1;
559
- font-size: 0.8rem;
560
- line-height: 1.5;
561
- }
562
-
563
- #disclaimer-text strong {
564
- color: #fafafa;
565
- }
566
-
567
- /* Hide Gradio branding */
568
  .gr-prose {
569
  color: #a1a1a1 !important;
570
  }
571
 
572
- .gr-prose h3 {
573
- color: #fafafa !important;
574
- }
575
-
576
  .gr-prose strong {
577
  color: #fafafa !important;
578
  }
579
-
580
- /* Accordion override */
581
- .gr-accordion {
582
- background: #141414 !important;
583
- border: 1px solid #262626 !important;
584
- border-radius: 12px !important;
585
- }
586
-
587
- .gr-accordion > .label-wrap {
588
- background: transparent !important;
589
- color: #fafafa !important;
590
- }
591
-
592
- .gr-accordion > .label-wrap:hover {
593
- background: #1f1f1f !important;
594
- }
595
  """
596
 
597
 
598
  # ============================================================================
599
- # Gradio Interface - Professional Dark Theme
600
  # ============================================================================
601
 
602
  with gr.Blocks(
@@ -613,175 +371,115 @@ with gr.Blocks(
613
  block_background_fill_dark="#141414",
614
  block_border_color="#262626",
615
  block_border_color_dark="#262626",
616
- block_label_text_color="#666666",
617
- block_title_text_color="#fafafa",
618
  body_text_color="#a1a1a1",
619
  body_text_color_dark="#a1a1a1",
620
- color_accent="#fafafa",
621
  input_background_fill="#141414",
622
  input_background_fill_dark="#141414",
623
- input_border_color="#262626",
624
- input_border_color_dark="#262626",
625
  )
626
  ) as demo:
627
 
628
- current_tab = gr.State("chat")
629
-
630
  # Header
631
- gr.HTML("""
632
- <div id="header">
633
- <div id="logo">Yuuki <span>v0.1-preview</span></div>
634
- </div>
635
- """)
636
 
637
- # Main Tabs
638
- with gr.Tabs() as tabs:
639
 
640
- # ===== CHAT TAB =====
641
- with gr.Tab("Chat", id="chat"):
642
- gr.HTML("""
643
- <div id="chat-area">
644
- <div id="welcome-section">
645
- <div id="welcome-title">Yuuki</div>
646
- <div id="welcome-subtitle">Mobile-trained code generation model</div>
647
- <div id="disclaimer-banner">
648
- <span id="disclaimer-icon">!</span>
649
- <span id="disclaimer-text">
650
- <strong>Experimental model.</strong> Best at Agda (55/100). Limited C, Assembly. Weak Python.
651
- Trained entirely on smartphone CPU with $0 budget.
652
- </span>
653
- </div>
654
- </div>
655
- </div>
656
- """)
657
 
658
- with gr.Column(elem_id="output-container"):
659
- output = gr.Textbox(
660
- label="Output",
661
- lines=10,
662
- show_copy_button=True,
663
- elem_id="output-box",
664
- placeholder="Generated code will appear here..."
665
- )
666
 
667
- with gr.Column(elem_id="input-container"):
668
  prompt_input = gr.Textbox(
669
  label="",
670
  placeholder="Enter code prompt... (e.g., module Main where)",
671
  lines=2,
672
  elem_id="input-box",
673
- show_label=False
674
- )
675
- generate_btn = gr.Button(
676
- "Generate",
677
- variant="primary",
678
- elem_id="generate-btn",
679
- size="sm"
680
  )
 
681
 
682
- # Examples
683
  gr.HTML('<div id="examples-label">Try these</div>')
684
- with gr.Row(elem_id="examples-grid"):
685
- ex_btn_1 = gr.Button("module Main where", elem_classes=["example-btn"], size="sm")
686
- ex_btn_2 = gr.Button("open import Data.Nat", elem_classes=["example-btn"], size="sm")
687
- ex_btn_3 = gr.Button("int main() {", elem_classes=["example-btn"], size="sm")
688
- ex_btn_4 = gr.Button("def hello():", elem_classes=["example-btn"], size="sm")
689
 
690
- ex_btn_1.click(lambda: "module Main where", outputs=prompt_input)
691
- ex_btn_2.click(lambda: "open import Data.Nat", outputs=prompt_input)
692
- ex_btn_3.click(lambda: "int main() {", outputs=prompt_input)
693
- ex_btn_4.click(lambda: "def hello():", outputs=prompt_input)
694
 
695
- # ===== SETTINGS TAB =====
696
- with gr.Tab("Settings", id="settings"):
697
- gr.HTML('<div id="panel-container">')
698
-
699
  with gr.Column(elem_classes=["panel-section"]):
700
  gr.HTML('<div class="panel-title">Generation Parameters</div>')
701
 
702
  with gr.Row():
703
  with gr.Column():
704
- max_new_tokens = gr.Slider(
705
- minimum=20,
706
- maximum=256,
707
- value=100,
708
- step=10,
709
- label="Max Tokens"
710
- )
711
- temperature = gr.Slider(
712
- minimum=0.1,
713
- maximum=1.5,
714
- value=0.7,
715
- step=0.1,
716
- label="Temperature"
717
- )
718
- top_p = gr.Slider(
719
- minimum=0.1,
720
- maximum=1.0,
721
- value=0.9,
722
- step=0.05,
723
- label="Top P"
724
- )
725
  with gr.Column():
726
- top_k = gr.Slider(
727
- minimum=1,
728
- maximum=100,
729
- value=50,
730
- step=5,
731
- label="Top K"
732
- )
733
- repetition_penalty = gr.Slider(
734
- minimum=1.0,
735
- maximum=2.0,
736
- value=1.1,
737
- step=0.05,
738
- label="Repetition Penalty"
739
- )
740
-
741
- gr.HTML('</div>')
742
 
743
- # ===== INFO TAB =====
744
- with gr.Tab("Info", id="info"):
745
- gr.HTML('<div id="panel-container">')
746
-
747
- # Model Info
748
  with gr.Column(elem_classes=["panel-section"]):
749
  gr.HTML('<div class="panel-title">Model Information</div>')
750
- gr.HTML("""
751
- <div class="info-row">
752
- <span class="info-label">Model</span>
753
- <span class="info-value">Yuuki-best (checkpoint-2000)</span>
754
- </div>
755
- <div class="info-row">
756
- <span class="info-label">Size</span>
757
- <span class="info-value">988 MB</span>
758
- </div>
759
- <div class="info-row">
760
- <span class="info-label">Training Progress</span>
761
- <span class="info-value">2,000 / 37,500 steps (5.3%)</span>
762
- </div>
763
- <div class="info-row">
764
- <span class="info-label">Hardware</span>
765
- <span class="info-value">Snapdragon 685 (CPU only)</span>
766
- </div>
767
- <div class="info-row">
768
- <span class="info-label">Training Speed</span>
769
- <span class="info-value">~86 sec/step</span>
770
- </div>
771
- <div class="info-row">
772
- <span class="info-label">Loss Range</span>
773
- <span class="info-value">1.69 - 2.31</span>
774
- </div>
775
- <div class="info-row">
776
- <span class="info-label">Cost</span>
777
- <span class="info-value">$0.00</span>
778
- </div>
779
- """)
780
 
781
- # Language Scores
782
  with gr.Column(elem_classes=["panel-section"]):
783
  gr.HTML('<div class="panel-title">Language Performance</div>')
784
- gr.HTML("""
785
- <div class="score-grid">
786
- <span class="score-badge good">Agda: 55/100</span>
787
- <span class="score-badge medium">C: 20/100</sp
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13
 
14
 
15
  def load_model():
 
16
  global model, tokenizer, MODEL_LOADED
17
 
18
  if MODEL_LOADED:
19
  return True
20
 
21
  try:
22
+ print("Loading Yuuki model...")
23
 
24
  tokenizer = AutoTokenizer.from_pretrained(MODEL_ID)
25
  model = AutoModelForCausalLM.from_pretrained(
 
49
  top_k: int = 50,
50
  repetition_penalty: float = 1.1
51
  ) -> str:
 
52
 
53
  if not MODEL_LOADED:
54
  if not load_model():
 
87
 
88
 
89
  # ============================================================================
90
+ # CSS
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
91
  # ============================================================================
92
 
93
  CUSTOM_CSS = """
 
 
 
 
 
94
  .gradio-container {
95
  max-width: 100% !important;
96
  padding: 0 !important;
 
103
  background: #0a0a0a !important;
104
  }
105
 
 
106
  footer {
107
  display: none !important;
108
  }
109
 
 
 
 
 
 
 
 
 
 
110
  #header {
111
  display: flex;
112
  align-items: center;
 
114
  padding: 16px 24px;
115
  border-bottom: 1px solid #1f1f1f;
116
  background: #0a0a0a;
 
 
 
117
  }
118
 
119
  #logo {
120
  font-size: 1.25rem;
121
  font-weight: 600;
122
  color: #fafafa;
 
123
  }
124
 
125
+ #version-tag {
126
  color: #666;
127
  font-weight: 400;
128
  font-size: 0.875rem;
129
  margin-left: 8px;
130
  }
131
 
132
+ #chat-container {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
133
  max-width: 800px;
134
  margin: 0 auto;
135
+ padding: 40px 24px;
136
  }
137
 
138
+ #welcome-box {
139
  text-align: center;
140
  margin-bottom: 32px;
141
  }
 
145
  font-weight: 600;
146
  color: #fafafa;
147
  margin-bottom: 8px;
 
148
  }
149
 
150
  #welcome-subtitle {
151
  font-size: 1rem;
152
  color: #666;
153
+ margin-bottom: 16px;
 
 
 
 
 
 
154
  }
155
 
156
+ #disclaimer {
157
+ background: #18181b;
158
+ border: 1px solid #27272a;
159
+ border-radius: 8px;
160
+ padding: 12px 16px;
161
+ color: #a1a1a1;
162
+ font-size: 0.8rem;
163
+ text-align: left;
164
+ display: inline-block;
165
+ max-width: 600px;
166
  }
167
 
168
  #output-box textarea {
169
+ background: #141414 !important;
170
  color: #e5e5e5 !important;
171
+ font-family: monospace !important;
172
  font-size: 0.875rem !important;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
173
  border: 1px solid #262626 !important;
174
  border-radius: 12px !important;
 
 
 
 
 
175
  }
176
 
177
  #input-box textarea {
178
+ background: #141414 !important;
179
  color: #fafafa !important;
180
+ border: 1px solid #262626 !important;
181
+ border-radius: 12px !important;
 
182
  }
183
 
184
  #input-box textarea::placeholder {
185
  color: #525252 !important;
186
  }
187
 
 
 
 
 
188
  #generate-btn {
 
 
 
189
  background: #fafafa !important;
190
  color: #0a0a0a !important;
191
  border: none !important;
192
  border-radius: 8px !important;
 
193
  font-weight: 600 !important;
 
 
 
194
  }
195
 
196
  #generate-btn:hover {
197
  background: #e5e5e5 !important;
 
 
 
 
 
 
 
 
 
 
 
198
  }
199
 
200
  #examples-label {
 
203
  text-transform: uppercase;
204
  letter-spacing: 0.05em;
205
  margin-bottom: 12px;
206
+ margin-top: 16px;
 
 
 
 
 
207
  }
208
 
209
  .example-btn {
210
  background: #141414 !important;
211
  border: 1px solid #262626 !important;
212
  color: #a1a1a1 !important;
213
+ font-family: monospace !important;
 
 
214
  border-radius: 8px !important;
 
 
215
  }
216
 
217
  .example-btn:hover {
 
220
  color: #fafafa !important;
221
  }
222
 
 
 
 
 
 
 
 
 
223
  .panel-section {
224
  background: #141414;
225
  border: 1px solid #262626;
 
233
  font-weight: 600;
234
  color: #fafafa;
235
  margin-bottom: 16px;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
236
  }
237
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
238
  .info-row {
239
  display: flex;
240
  justify-content: space-between;
 
257
  font-weight: 500;
258
  }
259
 
 
260
  .score-grid {
261
  display: flex;
262
  gap: 8px;
263
  flex-wrap: wrap;
 
264
  }
265
 
266
  .score-badge {
 
270
  font-weight: 600;
271
  }
272
 
273
+ .score-good {
274
  background: rgba(34, 197, 94, 0.15);
275
  color: #22c55e;
276
  border: 1px solid rgba(34, 197, 94, 0.3);
277
  }
278
 
279
+ .score-medium {
280
  background: rgba(234, 179, 8, 0.15);
281
  color: #eab308;
282
  border: 1px solid rgba(234, 179, 8, 0.3);
283
  }
284
 
285
+ .score-weak {
286
  background: rgba(239, 68, 68, 0.15);
287
  color: #ef4444;
288
  border: 1px solid rgba(239, 68, 68, 0.3);
289
  }
290
 
 
291
  .comparison-table {
292
  width: 100%;
293
  border-collapse: collapse;
 
306
  font-weight: 500;
307
  font-size: 0.75rem;
308
  text-transform: uppercase;
 
309
  }
310
 
311
  .comparison-table td {
312
  color: #a1a1a1;
313
  }
314
 
315
+ .comparison-table strong {
316
  color: #22c55e;
317
  }
318
 
 
319
  .links-grid {
320
  display: flex;
321
  gap: 16px;
 
326
  color: #a1a1a1;
327
  text-decoration: none;
328
  font-size: 0.875rem;
 
 
329
  }
330
 
331
  .link-item:hover {
332
  color: #fafafa;
333
  }
334
 
 
 
 
 
 
 
335
  .gr-tab-nav button {
336
  background: transparent !important;
337
  border: none !important;
338
  color: #666 !important;
 
 
339
  }
340
 
341
  .gr-tab-nav button.selected {
 
343
  border-bottom: 2px solid #fafafa !important;
344
  }
345
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
346
  .gr-prose {
347
  color: #a1a1a1 !important;
348
  }
349
 
 
 
 
 
350
  .gr-prose strong {
351
  color: #fafafa !important;
352
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
353
  """
354
 
355
 
356
  # ============================================================================
357
+ # Interface
358
  # ============================================================================
359
 
360
  with gr.Blocks(
 
371
  block_background_fill_dark="#141414",
372
  block_border_color="#262626",
373
  block_border_color_dark="#262626",
 
 
374
  body_text_color="#a1a1a1",
375
  body_text_color_dark="#a1a1a1",
 
376
  input_background_fill="#141414",
377
  input_background_fill_dark="#141414",
 
 
378
  )
379
  ) as demo:
380
 
 
 
381
  # Header
382
+ gr.HTML('<div id="header"><div id="logo">Yuuki <span id="version-tag">v0.1-preview</span></div></div>')
 
 
 
 
383
 
384
+ # Tabs
385
+ with gr.Tabs():
386
 
387
+ # Chat Tab
388
+ with gr.Tab("Chat"):
389
+ gr.HTML('<div id="chat-container">')
390
+ gr.HTML('<div id="welcome-box"><div id="welcome-title">Yuuki</div><div id="welcome-subtitle">Mobile-trained code generation model</div><div id="disclaimer"><strong>Experimental model.</strong> Best at Agda (55/100). Limited C, Assembly. Weak Python. Trained on smartphone CPU.</div></div>')
 
 
 
 
 
 
 
 
 
 
 
 
 
391
 
392
+ output = gr.Textbox(
393
+ label="Output",
394
+ lines=10,
395
+ show_copy_button=True,
396
+ elem_id="output-box",
397
+ placeholder="Generated code will appear here..."
398
+ )
 
399
 
400
+ with gr.Row():
401
  prompt_input = gr.Textbox(
402
  label="",
403
  placeholder="Enter code prompt... (e.g., module Main where)",
404
  lines=2,
405
  elem_id="input-box",
406
+ show_label=False,
407
+ scale=4
 
 
 
 
 
408
  )
409
+ generate_btn = gr.Button("Generate", variant="primary", elem_id="generate-btn", scale=1)
410
 
 
411
  gr.HTML('<div id="examples-label">Try these</div>')
412
+ with gr.Row():
413
+ ex1 = gr.Button("module Main where", elem_classes=["example-btn"], size="sm")
414
+ ex2 = gr.Button("open import Data.Nat", elem_classes=["example-btn"], size="sm")
415
+ ex3 = gr.Button("int main() {", elem_classes=["example-btn"], size="sm")
416
+ ex4 = gr.Button("def hello():", elem_classes=["example-btn"], size="sm")
417
 
418
+ gr.HTML('</div>')
 
 
 
419
 
420
+ # Settings Tab
421
+ with gr.Tab("Settings"):
 
 
422
  with gr.Column(elem_classes=["panel-section"]):
423
  gr.HTML('<div class="panel-title">Generation Parameters</div>')
424
 
425
  with gr.Row():
426
  with gr.Column():
427
+ max_new_tokens = gr.Slider(minimum=20, maximum=256, value=100, step=10, label="Max Tokens")
428
+ temperature = gr.Slider(minimum=0.1, maximum=1.5, value=0.7, step=0.1, label="Temperature")
429
+ top_p = gr.Slider(minimum=0.1, maximum=1.0, value=0.9, step=0.05, label="Top P")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
430
  with gr.Column():
431
+ top_k = gr.Slider(minimum=1, maximum=100, value=50, step=5, label="Top K")
432
+ repetition_penalty = gr.Slider(minimum=1.0, maximum=2.0, value=1.1, step=0.05, label="Repetition Penalty")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
433
 
434
+ # Info Tab
435
+ with gr.Tab("Info"):
 
 
 
436
  with gr.Column(elem_classes=["panel-section"]):
437
  gr.HTML('<div class="panel-title">Model Information</div>')
438
+ gr.HTML('<div class="info-row"><span class="info-label">Model</span><span class="info-value">Yuuki-best (checkpoint-2000)</span></div>')
439
+ gr.HTML('<div class="info-row"><span class="info-label">Size</span><span class="info-value">988 MB</span></div>')
440
+ gr.HTML('<div class="info-row"><span class="info-label">Training Progress</span><span class="info-value">2,000 / 37,500 steps (5.3%)</span></div>')
441
+ gr.HTML('<div class="info-row"><span class="info-label">Hardware</span><span class="info-value">Snapdragon 685 (CPU only)</span></div>')
442
+ gr.HTML('<div class="info-row"><span class="info-label">Speed</span><span class="info-value">~86 sec/step</span></div>')
443
+ gr.HTML('<div class="info-row"><span class="info-label">Cost</span><span class="info-value">$0.00</span></div>')
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
444
 
 
445
  with gr.Column(elem_classes=["panel-section"]):
446
  gr.HTML('<div class="panel-title">Language Performance</div>')
447
+ gr.HTML('<div class="score-grid"><span class="score-badge score-good">Agda: 55/100</span><span class="score-badge score-medium">C: 20/100</span><span class="score-badge score-medium">Assembly: 15/100</span><span class="score-badge score-weak">Python: 8/100</span></div>')
448
+ gr.HTML('<p style="color: #666; font-size: 0.8rem; margin-top: 16px;">Average quality: 24.6/100 (+146% from checkpoint 1400)</p>')
449
+
450
+ with gr.Column(elem_classes=["panel-section"]):
451
+ gr.HTML('<div class="panel-title">Checkpoint Comparison</div>')
452
+ gr.HTML('<table class="comparison-table"><thead><tr><th>Metric</th><th>CP-1400</th><th>CP-2000</th></tr></thead><tbody><tr><td>Progress</td><td>3.7%</td><td><strong>5.3%</strong></td></tr><tr><td>Agda</td><td>20/100</td><td><strong>55/100</strong></td></tr><tr><td>C</td><td>8/100</td><td><strong>20/100</strong></td></tr><tr><td>Assembly</td><td>2/100</td><td><strong>15/100</strong></td></tr><tr><td>Average</td><td>~10/100</td><td><strong>24.6/100</strong></td></tr></tbody></table>')
453
+
454
+ with gr.Column(elem_classes=["panel-section"]):
455
+ gr.HTML('<div class="panel-title">About</div>')
456
+ gr.Markdown("This is the **best model available at this moment**. The full **v0.1** release is coming soon. Once published, plans for **v0.2** will begin.\n\nYuuki is being trained **entirely on a smartphone CPU** by a **single person**. A research paper exploring mobile LLM training will be published soon.\n\n**Why this matters:**\n- Students without GPU access can experiment with ML\n- Democratizes ML research globally\n- Explores edge ML training possibilities")
457
+
458
+ with gr.Column(elem_classes=["panel-section"]):
459
+ gr.HTML('<div class="panel-title">Links</div>')
460
+ gr.HTML('<div class="links-grid"><a href="https://huggingface.co/OpceanAI/Yuuki-best" target="_blank" class="link-item">Model Card</a><a href="https://huggingface.co/OpceanAI/Yuuki" target="_blank" class="link-item">Original Yuuki</a><a href="https://github.com/YuuKi-OS/yuuki-training" target="_blank" class="link-item">Training Code</a></div>')
461
+ gr.HTML('<p style="color: #525252; font-size: 0.75rem; margin-top: 24px;">Licensed under Apache 2.0</p>')
462
+
463
+ # Event handlers
464
+ generate_btn.click(
465
+ fn=generate_code,
466
+ inputs=[prompt_input, max_new_tokens, temperature, top_p, top_k, repetition_penalty],
467
+ outputs=output
468
+ )
469
+
470
+ prompt_input.submit(
471
+ fn=generate_code,
472
+ inputs=[prompt_input, max_new_tokens, temperature, top_p, top_k, repetition_penalty],
473
+ outputs=output
474
+ )
475
+
476
+ ex1.click(lambda: "module Main where", outputs=prompt_input)
477
+ ex2.click(lambda: "open import Data.Nat", outputs=prompt_input)
478
+ ex3.click(lambda: "int main() {", outputs=prompt_input)
479
+ ex4.click(lambda: "def hello():", outputs=prompt_input)
480
+
481
+
482
+ # Launch
483
+ if __name__ == "__main__":
484
+ demo.launch(share=False, show_error=True, show_api=False)
485
+