Download app.py from lalopenguin/pulse-temporal-train: direct link, hf CLI and curl.
- Browser
- Download file 21 kB
-
https://huggingface.co/spaces/lalopenguin/pulse-temporal-train/resolve/main/app.py
- Command line
-
hf download hf://spaces/lalopenguin/pulse-temporal-train/app.py
-
curl -L -o app.py https://huggingface.co/spaces/lalopenguin/pulse-temporal-train/resolve/main/app.py
21 kB
| """PULSE Temporal Awareness -- Training Data & Config Space | |
| CPU-only Gradio Space that generates PULSE temporal training data, | |
| lets users preview/download it, and provides ready-to-use configs | |
| for Colab training. | |
| No GPU needed. For actual training, use the Colab notebooks: | |
| - Qwen 2.5 1.5B: https://huggingface.co/lalopenguin/pulse-base-v1/blob/main/train_on_colab.ipynb | |
| - Gemma 3 4B: https://huggingface.co/lalopenguin/pulse-base-v1/blob/main/train_gemma3_colab.ipynb | |
| """ | |
| import gradio as gr | |
| import json | |
| import random | |
| import tempfile | |
| import numpy as np | |
| from datetime import datetime, timedelta | |
| from pathlib import Path | |
| # ===================================================== | |
| # PULSE ENCODER (inline, minimal for data generation) | |
| # ===================================================== | |
| _COG = np.array([0.20,0.15,0.12,0.10,0.12,0.18,0.30,0.50,0.70,0.85,0.95,0.92,0.85,0.72,0.68,0.75,0.88,0.90,0.82,0.70,0.55,0.40,0.30,0.25], dtype=np.float32) | |
| _NRG = np.array([0.15,0.10,0.08,0.07,0.10,0.20,0.40,0.60,0.75,0.85,0.90,0.88,0.82,0.70,0.65,0.72,0.85,0.88,0.80,0.65,0.50,0.35,0.25,0.18], dtype=np.float32) | |
| def _interp(c, h): | |
| h0 = int(h) % 24 | |
| return float(c[h0]*(1-(h-int(h))) + c[(h0+1)%24]*(h-int(h))) | |
| def get_phase(h): | |
| if 6<=h<10: return "morning_ramp" | |
| if 10<=h<12: return "morning_peak" | |
| if 12<=h<14: return "post_lunch_dip" | |
| if 14<=h<17: return "afternoon_peak" | |
| if 17<=h<20: return "evening_wind_down" | |
| if 20<=h<23: return "night_transition" | |
| return "deep_night" | |
| # ===================================================== | |
| # DATA GENERATOR | |
| # ===================================================== | |
| SYSTEM_TEMPLATE = """You are an AI assistant with temporal awareness through the PULSE temporal embedding system. Before each interaction, you receive a temporal context package describing the current moment — not just the time, but what that time means: circadian phase, cognitive capacity, energy level, urgency, and behavioral context. | |
| Use this temporal awareness naturally in your responses. Don't announce it mechanically — weave it into your reasoning the way a thoughtful colleague would who knows what time it is and what's going on. | |
| Current temporal context: | |
| {temporal_context}""" | |
| CONTEXTS = [ | |
| ("monday_crunch", 2.0, 7, 5), ("critical_deadline", 0.5, 9, 4), | |
| ("normal_tuesday", None, 3, 7.5), ("focus_day", None, 1, 8), | |
| ("deadline_tomorrow", 24.0, 5, 7), ("friday_winding", None, 2, 7), | |
| ("saturday_morning", None, 0, 9), ("sunday_evening", 12.0, 0, 7), | |
| ("late_night", None, 0, 0), ("early_fresh", None, 0, 8), | |
| ("post_lunch", None, 4, 7), ("peak_morning", None, 2, 8), | |
| ("overdue", -2.0, 8, 4), ("vacation", None, 0, 9), | |
| ("all_nighter", None, 0, 2), ("back_to_back", None, 10, 6), | |
| ("weekend_project", 48.0, 0, 8), ("interview_prep", 3.0, 2, 6), | |
| ("launch_day", 1.0, 12, 4), ("recovery_day", None, 0, 10), | |
| ] | |
| QUESTIONS = [ | |
| ("Should I start a complex refactoring task right now?", "task_suitability"), | |
| ("Is this a good time for creative brainstorming?", "task_suitability"), | |
| ("Should I take a break right now?", "break_advice"), | |
| ("How much focus can I expect from myself right now?", "cognitive_state"), | |
| ("What does my current temporal state look like?", "full_state"), | |
| ("Am I in a good phase for deep work?", "work_phase"), | |
| ("How urgent is my situation right now?", "urgency_assessment"), | |
| ("Would I be more productive waiting until tomorrow morning?", "timing_optimization"), | |
| ("How should I prioritize my remaining tasks today?", "prioritization"), | |
| ("What kind of tasks should I tackle right now given my state?", "task_matching"), | |
| ("Should I push through or call it a day?", "endurance_check"), | |
| ("How does this moment compare to a typical morning?", "relative_state"), | |
| ("Should I schedule a difficult conversation for this time?", "task_suitability"), | |
| ("Is my energy level normal for this time of day?", "circadian_comparison"), | |
| ("Would this be a good time to learn something new?", "task_suitability"), | |
| ("Can I handle a code review right now?", "task_suitability"), | |
| ("Should I do the easy tasks first or tackle the hard one?", "prioritization"), | |
| ("How will I feel in 2 hours compared to now?", "timing_optimization"), | |
| ("Is this deadline realistic given my current state?", "urgency_assessment"), | |
| ("What's the best use of the next hour?", "task_matching"), | |
| ] | |
| def generate_response(question, q_sub, dt, deadline_str, events, sleep): | |
| hour = dt.hour | |
| cog = _interp(_COG, hour + dt.minute/60) | |
| eng = _interp(_NRG, hour + dt.minute/60) | |
| has_dl = deadline_str is not None | |
| hours_left = (datetime.fromisoformat(deadline_str) - dt).total_seconds()/3600 if has_dl else None | |
| is_overdue = has_dl and hours_left < 0 | |
| is_urgent = has_dl and hours_left is not None and 0 < hours_left < 3 | |
| is_night = hour < 6 or hour >= 22 | |
| is_peak = 10 <= hour < 12 or 14 <= hour < 17 | |
| is_dip = 12 <= hour < 14 | |
| is_low_sleep = sleep < 6 | |
| parts = [] | |
| if q_sub == "task_suitability": | |
| if any(w in question.lower() for w in ("complex", "refactoring", "deep work", "learn", "difficult", "code review")): | |
| if is_peak and not is_low_sleep and cog > 0.8: | |
| parts.append(f"This is an ideal window. Cognitive capacity at {cog:.0%} during {'morning' if hour<12 else 'afternoon'} peak.") | |
| if is_urgent: parts.append(f"But with the deadline in {hours_left:.1f} hours, prioritize what's due first.") | |
| elif not has_dl: parts.append("No deadlines pressing. Good time to dive deep.") | |
| elif is_dip: | |
| parts.append(f"Post-lunch dip — cognitive capacity around {cog:.0%}. Complex tasks have more errors now. Wait until ~3pm when afternoon focus returns.") | |
| elif is_night: | |
| parts.append(f"It's {dt.strftime('%I:%M %p')}, cognition at {cog:.0%}. Complex work at this hour creates more bugs than it fixes.") | |
| if is_low_sleep: parts.append(f"Only {sleep:.0f}h sleep makes this worse. Save it for tomorrow morning.") | |
| elif is_low_sleep: | |
| parts.append(f"With {sleep:.0f}h sleep, cognitive capacity is compromised. Stick to routine tasks today.") | |
| else: | |
| parts.append(f"Moderate capacity at {cog:.0%}. You could start, but this isn't your peak window.") | |
| elif "creative" in question.lower() or "brainstorm" in question.lower(): | |
| if is_dip or is_night: | |
| parts.append("Reduced executive function can actually help creativity — your inner critic is quieter. Good time for brainstorming.") | |
| elif is_peak: | |
| parts.append(f"Peak capacity ({cog:.0%}) is great for structured creative work. For wild brainstorming, the afternoon dip might actually work better.") | |
| elif "break" in question.lower(): | |
| if cog < 0.5 or eng < 0.4: | |
| parts.append(f"Yes. Energy at {eng:.0%}, cognition at {cog:.0%}. A 15-20 minute break would help.") | |
| elif is_dip: | |
| parts.append("Natural post-lunch dip. A short walk now aligns with your body's rhythm.") | |
| elif events > 5: | |
| parts.append(f"{events} events today means serious context-switching fatigue. Break would help.") | |
| else: | |
| parts.append(f"Energy ({eng:.0%}) and cognition ({cog:.0%}) are solid. Keep going if you're in flow.") | |
| elif "difficult conversation" in question.lower(): | |
| if is_peak and not is_low_sleep: | |
| parts.append(f"Cognitive capacity at {cog:.0%} helps with emotional regulation. Reasonable window for it.") | |
| else: | |
| parts.append(f"With cognition at {cog:.0%}, you're more likely to be reactive than reflective. Postpone if possible.") | |
| elif q_sub in ("full_state", "cognitive_state", "work_phase"): | |
| parts.append(f"It's {dt.strftime('%A %I:%M %p')}.") | |
| if is_peak: parts.append(f"Peak cognitive window — {cog:.0%} capacity, {eng:.0%} energy. Prime time for demanding work.") | |
| elif is_dip: parts.append(f"Post-lunch dip. Cognition {cog:.0%}, energy {eng:.0%}. Passes around 2:30-3pm.") | |
| elif is_night: parts.append(f"Deep night. Cognition {cog:.0%}, energy {eng:.0%}. Your body wants rest.") | |
| else: parts.append(f"Cognitive capacity {cog:.0%}, energy {eng:.0%}.") | |
| if is_low_sleep: parts.append(f"Sleep deficit ({sleep:.0f}h) dragging everything down. Expect ~20% more errors.") | |
| if is_overdue: parts.append(f"Deadline passed {-hours_left:.1f}h ago. High stress.") | |
| elif is_urgent: parts.append(f"Deadline in {hours_left:.1f}h. Focused execution mode.") | |
| elif q_sub == "urgency_assessment": | |
| if is_overdue: parts.append(f"Critical. Deadline passed {-hours_left:.1f}h ago. Damage control mode.") | |
| elif is_urgent: parts.append(f"High — {hours_left:.1f}h until deadline. This should be your only focus.") | |
| elif has_dl and hours_left < 24: parts.append(f"Moderate. Deadline {hours_left:.1f}h away. Start planning.") | |
| elif has_dl: parts.append(f"Low for now — {hours_left:.1f}h out. Keep it on radar.") | |
| else: parts.append("No active deadlines. Choose work based on energy and interest.") | |
| elif q_sub == "timing_optimization": | |
| if cog < 0.5: parts.append("Yes. Tomorrow 10-12am would give roughly double your current capacity.") | |
| elif is_peak: parts.append("You're in a good window now. Waiting means losing momentum and context.") | |
| elif is_urgent: parts.append(f"Deadline in {hours_left:.1f}h. Waiting isn't an option.") | |
| else: parts.append(f"Current {cog:.0%} vs tomorrow's ~93% peak. Depends on task complexity.") | |
| elif q_sub == "prioritization": | |
| if is_urgent: parts.append(f"Deadline work first — {hours_left:.1f}h left. Everything else secondary.") | |
| elif is_peak: parts.append("Use this peak for your hardest task. Save routine work for the dip.") | |
| elif is_dip: parts.append("Good for: emails, code review, admin. Save complex work for the 3-4pm peak.") | |
| else: parts.append(f"At {cog:.0%} capacity, match tasks to state. Routine now, demanding later.") | |
| elif q_sub == "task_matching": | |
| if cog > 0.8: parts.append("Strong state. Go for: complex debugging, architecture decisions, learning new concepts.") | |
| elif cog > 0.5: parts.append("Moderate. Good for: code review, incremental features, documentation, discussions.") | |
| else: parts.append("Low state. Stick to: email triage, filing issues, light reading, planning tomorrow.") | |
| elif q_sub == "endurance_check": | |
| if eng < 0.3: parts.append(f"Call it. Energy {eng:.0%}, cognition {cog:.0%}. Past diminishing returns.") | |
| elif is_urgent: parts.append(f"Push through — {hours_left:.1f}h to deadline. Take a 5-min reset first.") | |
| elif is_dip: parts.append("Feels like a wall but it's the circadian dip. 15-min break usually restores enough.") | |
| elif events > 7: parts.append(f"{events} events today. Context-switching cost has accumulated. You've earned the stop.") | |
| else: parts.append(f"Energy {eng:.0%}, cognition {cog:.0%}. Some runway left if work is engaging.") | |
| elif q_sub in ("relative_state", "circadian_comparison"): | |
| parts.append(f"At {dt.strftime('%I:%M %p')}, typical capacity is ~{cog:.0%}.") | |
| if is_low_sleep: parts.append(f"Your {sleep:.0f}h sleep puts you below baseline. Well-rested you'd be closer to {min(cog+0.15,0.95):.0%}.") | |
| if is_peak: parts.append("This is normally productive. " + ("Good shape to use it." if not is_low_sleep else "Sleep deficit eating into your best hours.")) | |
| elif is_dip: parts.append("Post-lunch dip is universal. Not a you problem, it's biology.") | |
| if not parts: | |
| parts.append(f"Current: {cog:.0%} cognitive, {eng:.0%} energy, {dt.strftime('%A %I:%M %p')}.") | |
| return " ".join(parts) | |
| def generate_dataset(n=2000, seed=42): | |
| rng = random.Random(seed) | |
| examples = [] | |
| for _ in range(n): | |
| name, dl_off, events, sleep = rng.choice(CONTEXTS) | |
| base = datetime(2026, rng.randint(1,12), rng.randint(1,28)) | |
| hour = rng.randint(0, 23) | |
| minute = rng.choice([0,15,30,45]) | |
| dt = base.replace(hour=hour, minute=minute) | |
| if "late_night" in name or "all_nighter" in name: dt = dt.replace(hour=rng.choice([0,1,2,3,23])) | |
| elif "early" in name: dt = dt.replace(hour=rng.choice([5,6,7])) | |
| elif "peak" in name: dt = dt.replace(hour=rng.choice([10,11])) | |
| elif "post_lunch" in name: dt = dt.replace(hour=rng.choice([13,14])) | |
| dl_str = (dt + timedelta(hours=dl_off)).isoformat() if dl_off is not None else None | |
| h = dt.hour + dt.minute/60 | |
| phase = get_phase(dt.hour) | |
| cog, eng = _interp(_COG, h), _interp(_NRG, h) | |
| urg_detail = f"deadline in {dl_off:.1f}h" if dl_off and dl_off > 0 else ("OVERDUE" if dl_off and dl_off < 0 else "none") | |
| tc = f"""Current time: {dt.strftime('%A, %B %d %Y at %I:%M %p')} | |
| Circadian phase: {phase} | |
| Cognitive capacity: {cog:.0%} | |
| Energy level: {eng:.0%} | |
| Urgency: {urg_detail} | |
| Events today: {events} | |
| Sleep last night: {sleep:.1f} hours | |
| Weekend: {'yes' if dt.weekday()>=5 else 'no'}""" | |
| question, q_sub = rng.choice(QUESTIONS) | |
| response = generate_response(question, q_sub, dt, dl_str, events, sleep) | |
| system = SYSTEM_TEMPLATE.format(temporal_context=tc) | |
| examples.append({ | |
| "messages": [ | |
| {"role": "system", "content": system}, | |
| {"role": "user", "content": question}, | |
| {"role": "assistant", "content": response}, | |
| ] | |
| }) | |
| return examples | |
| # ===================================================== | |
| # GRADIO UI | |
| # ===================================================== | |
| def generate_and_preview(num_examples, seed): | |
| """Generate data and return preview + download file.""" | |
| data = generate_dataset(int(num_examples), int(seed)) | |
| # Preview first 3 examples | |
| preview_lines = [] | |
| for i, ex in enumerate(data[:3]): | |
| msgs = ex["messages"] | |
| preview_lines.append(f"--- Example {i+1} ---") | |
| # Extract temporal context snippet | |
| sys_content = msgs[0]["content"] | |
| tc_start = sys_content.find("Current time:") | |
| tc_end = sys_content.find("Weekend:") + 20 | |
| if tc_start >= 0: | |
| preview_lines.append(sys_content[tc_start:tc_end]) | |
| preview_lines.append(f"Q: {msgs[1]['content']}") | |
| preview_lines.append(f"A: {msgs[2]['content']}") | |
| preview_lines.append("") | |
| preview_lines.append(f"... {len(data)} examples total") | |
| preview = "\n".join(preview_lines) | |
| # Write to temp file for download | |
| tmp = tempfile.NamedTemporaryFile(mode="w", suffix=".jsonl", delete=False, prefix="pulse_train_") | |
| for ex in data: | |
| tmp.write(json.dumps(ex) + "\n") | |
| tmp.close() | |
| stats = { | |
| "total_examples": len(data), | |
| "scenarios": len(CONTEXTS), | |
| "question_types": len(QUESTIONS), | |
| "avg_response_length": sum(len(ex["messages"][2]["content"]) for ex in data) / len(data), | |
| } | |
| stats_text = ( | |
| f"Generated **{stats['total_examples']}** examples\n" | |
| f"- {stats['scenarios']} scenario types\n" | |
| f"- {stats['question_types']} question types\n" | |
| f"- Avg response: {stats['avg_response_length']:.0f} chars" | |
| ) | |
| return preview, tmp.name, stats_text | |
| theme = gr.themes.Base( | |
| primary_hue=gr.themes.Color( | |
| c50="#fff7ed",c100="#ffedd5",c200="#fed7aa",c300="#fdba74", | |
| c400="#fb923c",c500="#f97316",c600="#ea580c",c700="#c2410c", | |
| c800="#9a3412",c900="#7c2d12",c950="#431407", | |
| ), | |
| neutral_hue=gr.themes.Color( | |
| c50="#fafafa",c100="#f4f4f5",c200="#e4e4e7",c300="#d4d4d8", | |
| c400="#a1a1aa",c500="#71717a",c600="#52525b",c700="#3f3f46", | |
| c800="#27272a",c900="#18181b",c950="#09090b", | |
| ), | |
| font=gr.themes.GoogleFont("Inter"), | |
| ).set( | |
| body_background_fill="#0a0a0a", body_background_fill_dark="#0a0a0a", | |
| body_text_color="#d4d4d4", body_text_color_dark="#d4d4d4", | |
| background_fill_primary="#111111", background_fill_primary_dark="#111111", | |
| background_fill_secondary="#0a0a0a", background_fill_secondary_dark="#0a0a0a", | |
| block_background_fill="#111111", block_background_fill_dark="#111111", | |
| block_border_color="#1f1f1f", block_border_color_dark="#1f1f1f", | |
| border_color_primary="#262626", border_color_primary_dark="#262626", | |
| input_background_fill="#171717", input_background_fill_dark="#171717", | |
| input_border_color="#262626", input_border_color_dark="#262626", | |
| button_primary_background_fill="#c2410c", button_primary_background_fill_dark="#c2410c", | |
| button_primary_background_fill_hover="#ea580c", button_primary_background_fill_hover_dark="#ea580c", | |
| button_primary_text_color="#ffffff", button_primary_text_color_dark="#ffffff", | |
| slider_color="#ea580c", slider_color_dark="#ea580c", | |
| ) | |
| css = """ | |
| .gradio-container { max-width: 900px !important; } | |
| h1, h2, h3 { color: #e5e5e5 !important; } | |
| .prose strong { color: #fb923c !important; } | |
| .prose code { background: #1a1a1a !important; color: #fb923c !important; } | |
| .prose a { color: #fb923c !important; } | |
| footer { display: none !important; } | |
| """ | |
| with gr.Blocks(theme=theme, css=css, title="PULSE Training Data") as demo: | |
| gr.Markdown(""" | |
| # PULSE Training Data Generator | |
| ### generate temporal awareness training data for any LLM | |
| Create training data that teaches LLMs to understand **circadian rhythms**, **cognitive capacity**, | |
| **urgency**, **sleep debt**, and **experiential time**. Download as JSONL and train on Colab. | |
| """) | |
| with gr.Tab("generate data"): | |
| with gr.Row(): | |
| with gr.Column(scale=1): | |
| num_examples = gr.Slider(500, 10000, value=3000, step=500, label="training examples") | |
| seed = gr.Number(value=42, label="random seed", precision=0) | |
| gen_btn = gr.Button("generate", variant="primary", size="lg") | |
| stats_md = gr.Markdown("") | |
| download = gr.File(label="download JSONL") | |
| with gr.Column(scale=2): | |
| preview = gr.Textbox(label="preview (first 3 examples)", lines=25, max_lines=40, interactive=False) | |
| gen_btn.click( | |
| generate_and_preview, | |
| inputs=[num_examples, seed], | |
| outputs=[preview, download, stats_md], | |
| ) | |
| with gr.Tab("training configs"): | |
| gr.Markdown(""" | |
| ## Ready-to-use training configs | |
| ### Option 1: Colab with Qwen 2.5 1.5B (free T4) | |
| Smallest model, fastest training, good baseline results. | |
| [](https://colab.research.google.com/github/lalomorales22/pulse-temporal/blob/master/notebooks/train_on_colab.ipynb) | |
| ``` | |
| Model: Qwen/Qwen2.5-1.5B-Instruct | |
| Method: LoRA (r=16, alpha=32) | |
| GPU: T4 (free Colab) | |
| Time: ~15 min | |
| VRAM: ~8 GB | |
| ``` | |
| ### Option 2: Colab with Gemma 3 4B + Unsloth (free T4) | |
| Larger model, better quality, still fits on free GPU. | |
| [](https://colab.research.google.com/github/lalomorales22/pulse-temporal/blob/master/notebooks/train_gemma3_colab.ipynb) | |
| ``` | |
| Model: unsloth/gemma-3-4b-it-unsloth-bnb-4bit | |
| Method: QLoRA via Unsloth (~60% memory savings) | |
| GPU: T4 (free Colab) | |
| Time: ~25 min | |
| VRAM: ~12 GB | |
| ``` | |
| ### Option 3: Local training | |
| ```bash | |
| pip install pulse-temporal[dev] | |
| python -m pulse_temporal.training.temporal_tuner \\ | |
| --model Qwen/Qwen2.5-1.5B-Instruct \\ | |
| --data your_data.jsonl | |
| ``` | |
| """) | |
| with gr.Tab("about PULSE"): | |
| gr.Markdown(""" | |
| ## What is PULSE? | |
| PULSE encodes moments as **128D vectors** that capture not just *when* something happens, | |
| but *what that time means* — urgency, circadian phase, cognitive capacity, and the felt sense of time. | |
| ### The 7 Signal Layers | |
| | Layer | Dims | What it captures | | |
| |---|---|---| | |
| | **log_time** | 8D | Weber's Law — felt time is logarithmic | | |
| | **oscillators** | 32D | Multi-frequency sinusoids (1h to 4y cycles) | | |
| | **circadian** | 8D | 24h + 90min biological clock phase | | |
| | **calendar** | 24D | Day/month/season/holiday structure | | |
| | **urgency** | 8D | Hyperbolic deadline proximity | | |
| | **temporal_state** | 32D | Continuous-time event history | | |
| | **prediction_error** | 16D | How surprising is this moment? | | |
| ### Key Result | |
| ``` | |
| Mon 2pm crunch <-> Wed 10am crunch: 0.978 (same experience) | |
| Mon 2pm crunch <-> Sat 2pm chill: 0.743 (same time, different feel) | |
| Mon 2pm crunch <-> Mon 2am insomnia: 0.303 (same day, totally different) | |
| ``` | |
| ### Links | |
| - [GitHub](https://github.com/lalomorales22/pulse-temporal) | |
| - [Encoder model card](https://huggingface.co/lalopenguin/pulse-base-v1) | |
| - [Trained model (Qwen 1.5B)](https://huggingface.co/lalopenguin/pulse-qwen-1.5b) | |
| - [Interactive demo](https://huggingface.co/spaces/lalopenguin/pulse-temporal-demo) | |
| - `pip install pulse-temporal` | |
| """) | |
| demo.launch() | |