Bc-AI commited on
Commit
760fed1
Β·
verified Β·
1 Parent(s): d810fc0

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +94 -61
app.py CHANGED
@@ -1,5 +1,4 @@
1
- # app.py β€” CodVa-2 Demo with streaming
2
-
3
  import os
4
  import math
5
  import time
@@ -10,14 +9,17 @@ import gradio as gr
10
  from dataclasses import dataclass
11
  from typing import Tuple, Generator
12
  from tokenizers import Tokenizer
13
- from huggingface_hub import hf_hub_download, login, HfApi # login not hf_login
14
 
 
 
 
15
  HF_TOKEN = os.environ.get("HF_TOKEN", "")
16
  HF_DATASET_REPO = "Bc-AI/nova1_data"
17
  HF_MODEL_REPO = os.environ.get("MODEL_REPO", "hugging-science/CodVa-2-session-002")
18
 
19
  if HF_TOKEN:
20
- login(token=HF_TOKEN) # login not hf_login
21
 
22
  # ─────────────────────────────────────────────────────────────────────────────
23
  # CONFIG
@@ -241,11 +243,16 @@ tok_path = hf_hub_download(
241
  token=HF_TOKEN or None,
242
  )
243
  tokenizer = Tokenizer.from_file(tok_path)
244
- EOS_ID = (
245
- tokenizer.token_to_id("<|endoftext|>")
246
- or tokenizer.token_to_id("</s>")
247
- or -1
248
- )
 
 
 
 
 
249
  print(f"[init] tokenizer | vocab={tokenizer.get_vocab_size()} | eos={EOS_ID}")
250
 
251
  print("[init] loading model...")
@@ -281,11 +288,8 @@ else:
281
  print("[init] WARNING: no weights found β€” random init")
282
 
283
  model.eval()
284
- # Compile for ~30% CPU speedup (optional, remove if it causes issues)
285
- print("[init] model ready (CPU inference, no compile)")
286
-
287
  n_params = sum(p.numel() for p in model.parameters())
288
- print(f"[init] ready | {n_params/1e6:.1f}M params")
289
 
290
  # ─────────────────────────────────────────────────────────────────────────────
291
  # STREAMING GENERATION
@@ -293,22 +297,29 @@ print(f"[init] ready | {n_params/1e6:.1f}M params")
293
  @torch.no_grad()
294
  def generate_stream(
295
  prompt: str,
 
296
  max_new: int = 256,
297
  temperature: float = 0.8,
298
  top_p: float = 0.95,
299
  top_k: int = 50,
300
  ) -> Generator[Tuple[str, str], None, None]:
301
  """
302
- Yields (full_text_so_far, stats_string) after every token.
303
- Gradio detects the generator and streams automatically.
 
304
  """
305
  if not prompt or not prompt.strip():
306
  yield "", "⚠️ Please enter a prompt"
307
  return
308
 
309
- enc = tokenizer.encode(prompt)
 
 
 
 
310
  ids = enc.ids
311
- # Truncate prompt if too long
 
312
  if len(ids) > cfg.max_len - max_new:
313
  ids = ids[-(cfg.max_len - max_new):]
314
 
@@ -343,32 +354,40 @@ def generate_stream(
343
  generated.append(next_tok)
344
  x = torch.cat([x, torch.tensor([[next_tok]])], dim=1)
345
 
346
- # Decode full output so far
347
- # Full decode is safer than incremental for BPE tokenizers
348
- out_text = tokenizer.decode(generated, skip_special_tokens=False)
 
 
 
 
349
 
350
- # Build stats string
351
  elapsed = time.time() - t0
352
  tps = len(generated) / max(elapsed, 1e-3)
353
  stats = (
354
  f"⏱ {elapsed:.1f}s | "
355
  f"πŸ”€ {len(generated)} / {max_new} tokens | "
356
  f"⚑ {tps:.1f} tok/s | "
 
357
  f"🌑 {temperature} top-p {top_p} top-k {int(top_k)}"
358
  )
359
 
360
- yield prompt + out_text, stats
361
 
362
  # Stop on EOS
363
  if EOS_ID >= 0 and next_tok == EOS_ID:
364
  break
365
 
366
- # Final yield with done marker
367
- out_text = tokenizer.decode(generated, skip_special_tokens=False)
368
- elapsed = time.time() - t0
369
- tps = len(generated) / max(elapsed, 1e-3)
 
 
 
370
  yield (
371
- prompt + out_text,
372
  f"βœ… Done | ⏱ {elapsed:.1f}s | "
373
  f"πŸ”€ {len(generated)} tokens | ⚑ {tps:.1f} tok/s"
374
  )
@@ -377,46 +396,59 @@ def generate_stream(
377
  # GRADIO UI
378
  # ─────────────────────────────────────────────────────────────────────────────
379
  EXAMPLES = [
380
- ["def fibonacci(n):\n ", 128, 0.2, 0.95, 50],
381
- ["class BinarySearchTree:\n def __init__(self):\n ", 256, 0.4, 0.95, 50],
382
- ["# Sort a list using quicksort\ndef quicksort(arr):\n ", 200, 0.3, 0.95, 50],
383
- ["import torch\nimport torch.nn as nn\n\nclass Attention(nn.Module):\n ", 300, 0.5, 0.95, 50],
384
- ["SELECT users.name, orders.total FROM users JOIN orders ON ", 128, 0.4, 0.90, 40],
385
- ["def binary_search(arr, target):\n left, right = 0, len(arr) - 1\n ", 150, 0.2, 0.95, 50],
386
- ["// React component for a todo list\nfunction TodoApp() {\n ", 200, 0.6, 0.95, 50],
387
- ["fn quicksort(arr: &mut Vec<i32>) {\n ", 200, 0.3, 0.95, 50],
 
 
388
  ]
389
 
390
  CSS = """
391
- .container { max-width: 960px; margin: auto; }
392
- .code-box { font-family: 'JetBrains Mono', 'Fira Code', 'Courier New', monospace !important;
393
- font-size: 13px !important; line-height: 1.5 !important; }
394
- .stats-text { font-size: 11px !important; color: #888 !important; }
395
- footer { display: none !important; }
 
396
  """
397
 
398
- with gr.Blocks(title="CodVa-2 Demo") as demo:
399
 
 
 
400
  gr.Markdown("""
401
- # 🧠 CodVa-2 β€” Code Language Model
402
- **213M parameters** Β· Trained on 9.24B tokens of code Β· PPL ~7.9 on validation
403
-
404
- Architecture highlights:
405
- **Differential Attention** Β· **Local/Global alternating layers** Β· **Dual-path FFN** Β· **Token Importance Gate**
406
  """)
407
 
408
  with gr.Row():
409
  # ── Left: inputs ──────────────────────────────────────────────────────
410
  with gr.Column(scale=1):
411
  prompt_box = gr.Textbox(
412
- label="Prompt",
413
- placeholder="Start your code here...",
414
  lines=10,
415
  elem_classes=["code-box"],
416
  )
 
 
 
 
 
 
 
 
417
  with gr.Row():
418
  max_new_slider = gr.Slider(16, 512, value=256, step=16,
419
- label="Max tokens")
420
  temp_slider = gr.Slider(0.0, 2.0, value=0.8, step=0.05,
421
  label="Temperature")
422
  with gr.Row():
@@ -432,7 +464,7 @@ with gr.Blocks(title="CodVa-2 Demo") as demo:
432
  # ── Right: output ─────────────────────────────────────────────────────
433
  with gr.Column(scale=1):
434
  output_box = gr.Textbox(
435
- label="Output (streaming)",
436
  lines=20,
437
  interactive=False,
438
  elem_classes=["code-box"],
@@ -441,36 +473,38 @@ with gr.Blocks(title="CodVa-2 Demo") as demo:
441
  label="",
442
  lines=1,
443
  interactive=False,
444
- elem_classes=["stats-text"],
445
  )
446
 
447
  gr.Examples(
448
  examples=EXAMPLES,
449
- inputs=[prompt_box, max_new_slider, temp_slider, topp_slider, topk_slider],
450
- label="πŸ“‹ Examples β€” click to load",
451
- examples_per_page=8,
452
  )
453
 
454
  gr.Markdown("""
455
  ---
456
  πŸ’‘ **Tips:**
457
- `temp 0.1–0.3` = precise completions Β· `temp 0.7–1.2` = creative exploration
458
- Lower `top-p` = more focused Β· Higher `top-k` = more diverse vocabulary
 
 
 
459
  """)
460
 
461
  # ── Wire up events ────────────────────────────────────────────────────────
462
  gen_event = gen_btn.click(
463
  fn=generate_stream,
464
- inputs=[prompt_box, max_new_slider, temp_slider, topp_slider, topk_slider],
465
  outputs=[output_box, stats_box],
466
  )
467
- # Also trigger on Enter in the prompt box
468
  prompt_box.submit(
469
  fn=generate_stream,
470
- inputs=[prompt_box, max_new_slider, temp_slider, topp_slider, topk_slider],
471
  outputs=[output_box, stats_box],
472
  )
473
- # Stop button cancels the running generator
474
  stop_btn.click(fn=None, cancels=[gen_event])
475
 
476
  clear_btn.click(
@@ -483,5 +517,4 @@ if __name__ == "__main__":
483
  server_name="0.0.0.0",
484
  server_port=7860,
485
  show_error=True,
486
- css=CSS, # <-- moved here
487
  )
 
1
+ # app.py β€” CodVa-2 Demo (PRETRAIN model, domain tokens only)
 
2
  import os
3
  import math
4
  import time
 
9
  from dataclasses import dataclass
10
  from typing import Tuple, Generator
11
  from tokenizers import Tokenizer
12
+ from huggingface_hub import hf_hub_download, login, HfApi
13
 
14
+ # ─────────────────────────────────────────────────────────────────────────────
15
+ # AUTH
16
+ # ─────────────────────────────────────────────────────────────────────────────
17
  HF_TOKEN = os.environ.get("HF_TOKEN", "")
18
  HF_DATASET_REPO = "Bc-AI/nova1_data"
19
  HF_MODEL_REPO = os.environ.get("MODEL_REPO", "hugging-science/CodVa-2-session-002")
20
 
21
  if HF_TOKEN:
22
+ login(token=HF_TOKEN)
23
 
24
  # ─────────────────────────────────────────────────────────────────────────────
25
  # CONFIG
 
243
  token=HF_TOKEN or None,
244
  )
245
  tokenizer = Tokenizer.from_file(tok_path)
246
+
247
+ # Domain tokens
248
+ DOMAIN_TOKENS = {
249
+ "Code": "<|domain_code|>",
250
+ "Math": "<|domain_math|>",
251
+ "General": "<|domain_general|>",
252
+ "Reasoning": "<|domain_reasoning|>",
253
+ }
254
+
255
+ EOS_ID = tokenizer.token_to_id("<|endoftext|>") or tokenizer.token_to_id("</s>") or -1
256
  print(f"[init] tokenizer | vocab={tokenizer.get_vocab_size()} | eos={EOS_ID}")
257
 
258
  print("[init] loading model...")
 
288
  print("[init] WARNING: no weights found β€” random init")
289
 
290
  model.eval()
 
 
 
291
  n_params = sum(p.numel() for p in model.parameters())
292
+ print(f"[init] ready | {n_params/1e6:.1f}M params | CPU inference")
293
 
294
  # ─────────────────────────────────────────────────────────────────────────────
295
  # STREAMING GENERATION
 
297
  @torch.no_grad()
298
  def generate_stream(
299
  prompt: str,
300
+ domain: str,
301
  max_new: int = 256,
302
  temperature: float = 0.8,
303
  top_p: float = 0.95,
304
  top_k: int = 50,
305
  ) -> Generator[Tuple[str, str], None, None]:
306
  """
307
+ Pretrain-style generation with domain token prepending.
308
+ Model sees: <|domain_X|>{prompt}
309
+ Continues from there.
310
  """
311
  if not prompt or not prompt.strip():
312
  yield "", "⚠️ Please enter a prompt"
313
  return
314
 
315
+ # Prepend domain token (matches training data format)
316
+ domain_token = DOMAIN_TOKENS.get(domain, "<|domain_code|>")
317
+ full_prompt = domain_token + prompt.strip()
318
+
319
+ enc = tokenizer.encode(full_prompt)
320
  ids = enc.ids
321
+
322
+ # Truncate if too long
323
  if len(ids) > cfg.max_len - max_new:
324
  ids = ids[-(cfg.max_len - max_new):]
325
 
 
354
  generated.append(next_tok)
355
  x = torch.cat([x, torch.tensor([[next_tok]])], dim=1)
356
 
357
+ # Decode what we have so far (strip domain token from display)
358
+ full_text = tokenizer.decode(ids + generated, skip_special_tokens=False)
359
+
360
+ # Remove domain token from display
361
+ display_text = full_text
362
+ for tok in DOMAIN_TOKENS.values():
363
+ display_text = display_text.replace(tok, "")
364
 
365
+ # Build stats
366
  elapsed = time.time() - t0
367
  tps = len(generated) / max(elapsed, 1e-3)
368
  stats = (
369
  f"⏱ {elapsed:.1f}s | "
370
  f"πŸ”€ {len(generated)} / {max_new} tokens | "
371
  f"⚑ {tps:.1f} tok/s | "
372
+ f"🎯 {domain} | "
373
  f"🌑 {temperature} top-p {top_p} top-k {int(top_k)}"
374
  )
375
 
376
+ yield display_text, stats
377
 
378
  # Stop on EOS
379
  if EOS_ID >= 0 and next_tok == EOS_ID:
380
  break
381
 
382
+ # Final yield
383
+ full_text = tokenizer.decode(ids + generated, skip_special_tokens=False)
384
+ for tok in DOMAIN_TOKENS.values():
385
+ full_text = full_text.replace(tok, "")
386
+
387
+ elapsed = time.time() - t0
388
+ tps = len(generated) / max(elapsed, 1e-3)
389
  yield (
390
+ full_text,
391
  f"βœ… Done | ⏱ {elapsed:.1f}s | "
392
  f"πŸ”€ {len(generated)} tokens | ⚑ {tps:.1f} tok/s"
393
  )
 
396
  # GRADIO UI
397
  # ─────────────────────────────────────────────────────────────────────────────
398
  EXAMPLES = [
399
+ ["def fibonacci(n):\n ", "Code", 128, 0.2, 0.95, 50],
400
+ ["class BinaryTree:\n def __init__(self):\n ", "Code", 256, 0.3, 0.95, 50],
401
+ ["import torch\nimport torch.nn as nn\n\n", "Code", 200, 0.4, 0.95, 50],
402
+ ["SELECT users.name, orders.total FROM ", "Code", 100, 0.3, 0.90, 40],
403
+ ["# Quicksort implementation\ndef quicksort(arr):\n ", "Code", 200, 0.2, 0.95, 50],
404
+ ["Problem: Find the derivative of f(x) = x^3 + 2x^2 - 5x + 1\n\nSolution: ", "Math", 150, 0.4, 0.95, 50],
405
+ ["Theorem: The sum of angles in a triangle equals 180 degrees.\n\nProof: ", "Math", 200, 0.5, 0.95, 50],
406
+ ["Let $f(x) = \\int_0^x t^2 dt$. Then ", "Math", 128, 0.3, 0.95, 50],
407
+ ["The history of the Roman Empire began ", "General", 200, 0.7, 0.95, 50],
408
+ ["Photosynthesis is the process by which ", "General", 150, 0.5, 0.95, 50],
409
  ]
410
 
411
  CSS = """
412
+ .container { max-width: 1100px; margin: auto; }
413
+ .code-box {
414
+ font-family: 'JetBrains Mono', 'Fira Code', 'Courier New', monospace !important;
415
+ font-size: 13px !important;
416
+ line-height: 1.5 !important;
417
+ }
418
  """
419
 
420
+ with gr.Blocks(title="CodVa-2 Pretrain Demo") as demo:
421
 
422
+ gr.HTML(f"<style>{CSS}</style>")
423
+
424
  gr.Markdown("""
425
+ # 🧠 CodVa-2 β€” Pretrained Code LM
426
+ **213M parameters** Β· Differential Attention Β· Trained on code/math/general corpus
427
+
428
+ This is a **pretrained** model (not instruction-tuned). It continues text in the style of its training domain.
429
+ Use the domain selector to control what kind of continuation you get.
430
  """)
431
 
432
  with gr.Row():
433
  # ── Left: inputs ──────────────────────────────────────────────────────
434
  with gr.Column(scale=1):
435
  prompt_box = gr.Textbox(
436
+ label="Prompt (raw text, model will continue)",
437
+ placeholder="def fibonacci(n):\n ",
438
  lines=10,
439
  elem_classes=["code-box"],
440
  )
441
+
442
+ domain_dropdown = gr.Dropdown(
443
+ choices=list(DOMAIN_TOKENS.keys()),
444
+ value="Code",
445
+ label="Domain (prepends domain token)",
446
+ info="Code, Math, General, or Reasoning β€” tells the model what style to use"
447
+ )
448
+
449
  with gr.Row():
450
  max_new_slider = gr.Slider(16, 512, value=256, step=16,
451
+ label="Max new tokens")
452
  temp_slider = gr.Slider(0.0, 2.0, value=0.8, step=0.05,
453
  label="Temperature")
454
  with gr.Row():
 
464
  # ── Right: output ─────────────────────────────────────────────────────
465
  with gr.Column(scale=1):
466
  output_box = gr.Textbox(
467
+ label="Generated continuation (streaming)",
468
  lines=20,
469
  interactive=False,
470
  elem_classes=["code-box"],
 
473
  label="",
474
  lines=1,
475
  interactive=False,
 
476
  )
477
 
478
  gr.Examples(
479
  examples=EXAMPLES,
480
+ inputs=[prompt_box, domain_dropdown, max_new_slider, temp_slider, topp_slider, topk_slider],
481
+ label="πŸ“‹ Example prompts β€” click to load",
482
+ examples_per_page=10,
483
  )
484
 
485
  gr.Markdown("""
486
  ---
487
  πŸ’‘ **Tips:**
488
+ - **Domain matters:** Code domain β†’ code syntax, Math β†’ equations, General β†’ prose
489
+ - **Lower temp (0.1-0.3)** = deterministic, predictable (good for code)
490
+ - **Higher temp (0.7-1.2)** = creative, varied (good for text)
491
+ - This model has seen **~2B tokens** (20% trained). Expect coherent syntax but sometimes wrong logic.
492
+ - By 10B tokens it should be much stronger.
493
  """)
494
 
495
  # ── Wire up events ────────────────────────────────────────────────────────
496
  gen_event = gen_btn.click(
497
  fn=generate_stream,
498
+ inputs=[prompt_box, domain_dropdown, max_new_slider, temp_slider, topp_slider, topk_slider],
499
  outputs=[output_box, stats_box],
500
  )
501
+
502
  prompt_box.submit(
503
  fn=generate_stream,
504
+ inputs=[prompt_box, domain_dropdown, max_new_slider, temp_slider, topp_slider, topk_slider],
505
  outputs=[output_box, stats_box],
506
  )
507
+
508
  stop_btn.click(fn=None, cancels=[gen_event])
509
 
510
  clear_btn.click(
 
517
  server_name="0.0.0.0",
518
  server_port=7860,
519
  show_error=True,
 
520
  )