Spaces:
Sleeping
Sleeping
Upload 2 files
Browse files- app/ui/ui_colab.py +80 -0
- app/ui/ui_spaces.py +69 -0
app/ui/ui_colab.py
ADDED
@@ -0,0 +1,80 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import gradio as gr
|
2 |
+
import os
|
3 |
+
from app.core.orchestrator import launch_training
|
4 |
+
from app.utils.validation import safe_tag
|
5 |
+
|
6 |
+
DEFAULTS = {'tokenizer_name': 'google/gemma-3-270m', 'block_size': 512}
|
7 |
+
ALGOS_BY_ARCH = {'Official Gemma (Baseline)': ['backprop'], 'Custom Research Transformer (Experimental)': ['feedback_alignment','synthetic_gradients','forward_forward']}
|
8 |
+
|
9 |
+
def on_arch_change(arch):
|
10 |
+
return gr.update(choices=ALGOS_BY_ARCH[arch], value=ALGOS_BY_ARCH[arch][0])
|
11 |
+
|
12 |
+
def run_job(exp_tag, arch, dataset, tokenizer_name, algorithm, batch_size, epochs, max_batches,
|
13 |
+
grad_accum, lr, weight_decay, main_lr, synth_lr, ff_lr, ff_thresh, block_size, push_github):
|
14 |
+
try:
|
15 |
+
safe_tag(exp_tag)
|
16 |
+
except Exception as e:
|
17 |
+
yield f"❌ Invalid experiment tag: {e}"
|
18 |
+
return
|
19 |
+
|
20 |
+
params = {'epochs': int(epochs), 'grad_accum_steps': int(grad_accum)}
|
21 |
+
if algorithm == 'backprop':
|
22 |
+
params.update({'learning_rate': float(lr), 'weight_decay': float(weight_decay)})
|
23 |
+
elif algorithm == 'synthetic_gradients':
|
24 |
+
params.update({'main_learning_rate': float(main_lr), 'synth_learning_rate': float(synth_lr)})
|
25 |
+
elif algorithm == 'feedback_alignment':
|
26 |
+
params.update({'learning_rate': float(lr)})
|
27 |
+
elif algorithm == 'forward_forward':
|
28 |
+
params.update({'learning_rate': float(ff_lr), 'threshold': float(ff_thresh)})
|
29 |
+
|
30 |
+
results_file = os.path.join('local_results', f"{exp_tag}_results.json")
|
31 |
+
cfg = {
|
32 |
+
'exp_tag': exp_tag,
|
33 |
+
'model_architecture': arch,
|
34 |
+
'algorithm': algorithm,
|
35 |
+
'dataset_name': dataset,
|
36 |
+
'tokenizer_name': tokenizer_name or DEFAULTS['tokenizer_name'],
|
37 |
+
'batch_size': int(batch_size),
|
38 |
+
'results_file': results_file,
|
39 |
+
'params': params,
|
40 |
+
'max_batches_per_epoch': int(max_batches),
|
41 |
+
'block_size': int(block_size or DEFAULTS['block_size']),
|
42 |
+
}
|
43 |
+
if push_github and (not os.getenv('GITHUB_TOKEN') or not os.getenv('GITHUB_RESULTS_REPO')):
|
44 |
+
yield "❌ To push results to GitHub, set GITHUB_TOKEN and GITHUB_RESULTS_REPO environment variables in Colab (do not print them)."
|
45 |
+
return
|
46 |
+
|
47 |
+
yield from launch_training(cfg, timeout_sec=60*60*3)
|
48 |
+
|
49 |
+
with gr.Blocks(theme=gr.themes.Soft()) as colab:
|
50 |
+
gr.Markdown("# 🧪 LLM Algorithm Lab — Colab UI (Full)")
|
51 |
+
with gr.Row():
|
52 |
+
with gr.Column():
|
53 |
+
exp_tag = gr.Textbox(label="Experiment Tag", value="exp")
|
54 |
+
arch = gr.Dropdown(choices=list(ALGOS_BY_ARCH.keys()), value="Official Gemma (Baseline)")
|
55 |
+
algo = gr.Dropdown(choices=ALGOS_BY_ARCH["Official Gemma (Baseline)"], value="backprop")
|
56 |
+
arch.change(on_arch_change, inputs=arch, outputs=algo)
|
57 |
+
dataset = gr.Textbox(label="HF Dataset", value="stas/tiny-stories")
|
58 |
+
tokenizer_name = gr.Textbox(label="Tokenizer/Model ID", value="google/gemma-3-270m")
|
59 |
+
block_size = gr.Slider(128, 2048, value=512, step=64, label="Block Size")
|
60 |
+
batch_size = gr.Slider(1, 256, value=16, step=1, label="Batch Size")
|
61 |
+
epochs = gr.Slider(1, 50, value=3, step=1, label="Epochs")
|
62 |
+
max_batches = gr.Slider(0, 50000, value=0, step=50, label="Max Batches / Epoch (0=full)")
|
63 |
+
grad_accum = gr.Slider(1, 64, value=1, step=1, label="Grad Accum (baseline)")
|
64 |
+
with gr.Accordion("Optimizer / LR", open=False):
|
65 |
+
lr = gr.Number(label="LR (BP/FA)", value=5e-5)
|
66 |
+
weight_decay = gr.Number(label="Weight Decay (BP)", value=0.01)
|
67 |
+
main_lr = gr.Number(label="Main LR (SG)", value=1e-5)
|
68 |
+
synth_lr = gr.Number(label="Synth LR (SG)", value=1e-4)
|
69 |
+
ff_lr = gr.Number(label="Layer LR (FF)", value=1e-4)
|
70 |
+
ff_thresh = gr.Number(label="Goodness Threshold (FF)", value=2.0)
|
71 |
+
with gr.Column():
|
72 |
+
push_github = gr.Checkbox(label="Push results to GitHub (requires token in env)", value=False)
|
73 |
+
start = gr.Button("Start Training", variant="primary")
|
74 |
+
logs = gr.Textbox(label="Live Logs", lines=26)
|
75 |
+
start.click(run_job,
|
76 |
+
inputs=[exp_tag, arch, dataset, tokenizer_name, algo, batch_size, epochs, max_batches, grad_accum, lr, weight_decay, main_lr, synth_lr, ff_lr, ff_thresh, block_size, push_github],
|
77 |
+
outputs=logs)
|
78 |
+
|
79 |
+
def build():
|
80 |
+
return colab
|
app/ui/ui_spaces.py
ADDED
@@ -0,0 +1,69 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import gradio as gr
|
2 |
+
import os
|
3 |
+
from app.core.orchestrator import launch_training
|
4 |
+
|
5 |
+
DEMO_LIMITS = {'max_batches_per_epoch': 100, 'batch_size': 8, 'epochs': 1}
|
6 |
+
|
7 |
+
# Wrapper that streams logs and appends them
|
8 |
+
def on_start(exp_tag, model_arch, dataset, batch_size, algorithm, epochs, max_batches):
|
9 |
+
cfg = {
|
10 |
+
'exp_tag': exp_tag or 'demo',
|
11 |
+
'model_architecture': model_arch,
|
12 |
+
'algorithm': algorithm,
|
13 |
+
'dataset_name': dataset,
|
14 |
+
'batch_size': min(int(batch_size), DEMO_LIMITS['batch_size']),
|
15 |
+
'results_file': os.path.join('local_results', f"{exp_tag or 'demo'}_results.json"),
|
16 |
+
'params': {'epochs': min(int(epochs), DEMO_LIMITS['epochs'])},
|
17 |
+
'max_batches_per_epoch': min(int(max_batches), DEMO_LIMITS['max_batches_per_epoch']),
|
18 |
+
'tokenizer_name': 'google/gemma-3-270m',
|
19 |
+
'block_size': 256,
|
20 |
+
}
|
21 |
+
|
22 |
+
logs_accum = "" # keep full history here
|
23 |
+
for log_line in launch_training(cfg, timeout_sec=20*60):
|
24 |
+
logs_accum += log_line + "\n" # append new line
|
25 |
+
yield logs_accum # send full accumulated logs
|
26 |
+
|
27 |
+
with gr.Blocks(theme=gr.themes.Soft()) as demo:
|
28 |
+
gr.Markdown("# 🧪 LLM Algorithm Lab — Demo (Spaces)")
|
29 |
+
with gr.Row():
|
30 |
+
with gr.Column():
|
31 |
+
exp_tag = gr.Textbox(label="Experiment Tag", value="demo")
|
32 |
+
|
33 |
+
model_arch = gr.Dropdown(
|
34 |
+
choices=["Official Gemma (Baseline)", "Custom Research Transformer (Experimental)"],
|
35 |
+
value="Official Gemma (Baseline)",
|
36 |
+
interactive=True,
|
37 |
+
allow_custom_value=False
|
38 |
+
)
|
39 |
+
|
40 |
+
algorithm = gr.Dropdown(
|
41 |
+
choices=["backprop", "feedback_alignment", "synthetic_gradients", "forward_forward"],
|
42 |
+
value="backprop",
|
43 |
+
interactive=True,
|
44 |
+
allow_custom_value=False
|
45 |
+
)
|
46 |
+
|
47 |
+
dataset = gr.Textbox(
|
48 |
+
label="HF Dataset",
|
49 |
+
value="roneneldan/TinyStories"
|
50 |
+
)
|
51 |
+
|
52 |
+
batch_size = gr.Slider(1, 16, value=8, step=1, label="Batch Size (clamped)")
|
53 |
+
epochs = gr.Slider(1, 3, value=1, step=1, label="Epochs (demo)")
|
54 |
+
max_batches = gr.Slider(10, 500, value=100, step=10, label="Max Batches / Epoch")
|
55 |
+
|
56 |
+
with gr.Column():
|
57 |
+
start = gr.Button("Start Demo Run", variant="primary")
|
58 |
+
logs = gr.Textbox(label="Live Logs", lines=20)
|
59 |
+
|
60 |
+
start.click(
|
61 |
+
on_start,
|
62 |
+
inputs=[exp_tag, model_arch, dataset, batch_size, algorithm, epochs, max_batches],
|
63 |
+
outputs=logs
|
64 |
+
)
|
65 |
+
|
66 |
+
def build():
|
67 |
+
return demo
|
68 |
+
|
69 |
+
|