"""Terminal demo of the Plane Mode Scholar autopilot — fine-tuned Nemotron coach. Records a real, local FLY autopilot run (no network, no mocks) so the agent chain and grounded coach output can be captured as a submittable demo. PMS_GGUF_DIR=models/nemotron python scripts/demo_autopilot.py """ from __future__ import annotations import json import os import sys import tempfile import time from pathlib import Path ROOT = Path(__file__).resolve().parents[1] sys.path.insert(0, str(ROOT)) os.environ.setdefault("PMS_INFERENCE_BACKEND", "llamacpp") os.environ.setdefault("PMS_LLAMACPP_MODE", "embedded") os.environ.setdefault("PMS_USE_FINETUNED", "true") os.environ.setdefault("PMS_GGUF_DIR", str(ROOT / "models" / "nemotron")) os.environ.setdefault("PMS_LLAMACPP_N_GPU_LAYERS", "0") os.environ.setdefault("PMS_MAX_NEW_TOKENS", "320") C = { "reset": "\033[0m", "dim": "\033[2m", "bold": "\033[1m", "teal": "\033[38;5;43m", "copper": "\033[38;5;173m", "amber": "\033[38;5;214m", "green": "\033[38;5;48m", "blue": "\033[38;5;75m", "purple": "\033[38;5;141m", "red": "\033[38;5;203m", "gray": "\033[38;5;245m", } PHASE_COLOR = { "BOOT": "teal", "PACK": "teal", "SESSION": "blue", "PLAN": "amber", "RETRIEVE": "purple", "EXPLAIN": "green", "QUIZ": "blue", "MEMORY": "copper", "DONE": "teal", "ERROR": "red", } DEMO_NOTES = """# Introduction to Machine Learning ## Chapter 1: Supervised Learning Supervised learning trains a model on labeled input-output pairs so it can predict the output for unseen inputs. Classification predicts discrete labels; regression predicts continuous values. ## Chapter 2: Gradient Descent Gradient descent minimizes a loss function by repeatedly stepping in the direction of the negative gradient. The learning rate controls the step size: too large overshoots the minimum, too small converges slowly. ## Chapter 3: Overfitting and Regularization A model overfits when it memorizes training noise and fails to generalize. Regularization (L1/L2) and dropout penalize complexity to improve test accuracy. """ def c(text: str, color: str) -> str: return f"{C.get(color, '')}{text}{C['reset']}" def slow_print(text: str, delay: float = 0.012) -> None: for ch in text: sys.stdout.write(ch) sys.stdout.flush() time.sleep(delay) sys.stdout.write("\n") sys.stdout.flush() def banner() -> None: line = "═" * 64 print(c(line, "teal")) print(c(" ✈ PLANE MODE SCHOLAR // AUTOPILOT DEMO", "bold")) print(c(" Fine-tuned NVIDIA Nemotron 3 Nano 4B · offline study coach", "gray")) print(c(line, "teal")) print() def chain_step(phase: str, message: str) -> None: color = PHASE_COLOR.get(phase, "gray") tag = c(f"[{phase:<8}]", color) print(f" {tag} {c(message, 'gray')}") def main() -> None: banner() from plane_mode_scholar.core import llm from plane_mode_scholar.core.study_agent import StudyAgent from plane_mode_scholar.gradio_ui.layout import STATE, quick_upload_pack user_id = "demo_judge" tmp = Path(tempfile.mkdtemp()) / "intro_to_ml.md" tmp.write_text(DEMO_NOTES, encoding="utf-8") print(c("▸ Uploading study material: intro_to_ml.md", "copper")) pack = quick_upload_pack([str(tmp)], user_id) print(c(f" ✓ Indexed pack {pack.get('pack_id', '')[:24]}… " f"({pack.get('file_count', 1)} file, 3 chapters)", "green")) print() print(c("▸ Backend:", "copper"), c(f"{os.environ['PMS_INFERENCE_BACKEND']} (GGUF + study-coach LoRA)", "gray")) print(c("▸ Tap FLY → autonomous monitor → plan → act loop", "copper")) print() print(c("─" * 64, "teal")) print(c(" AGENT CHAIN", "amber")) print(c("─" * 64, "teal")) agent = StudyAgent(STATE.store, STATE.orchestrator) coach_text = "" quiz_shown = False t_start = time.time() for event in agent.run_autopilot(user_id=user_id, pack_id=pack["pack_id"], max_steps=4): phase = event.get("phase", "") msg = event.get("message", "") data = event.get("data", {}) if phase == "STREAM": continue if phase == "EXPLAIN": chain_step("EXPLAIN", f"Coach explanation ready ({data.get('inference_ms', 0)} ms)") coach_text = data.get("response", msg) print() print(c(" ┌─ COACH ─────────────────────────────────────────────────", "green")) for para in coach_text.split("\n"): slow_print(c(" │ ", "green") + para, delay=0.004) print(c(" └─────────────────────────────────────────────────────────", "green")) print() continue if phase == "QUIZ" and not quiz_shown: q = data.get("question", {}) chain_step("QUIZ", "Generated a comprehension check") print() print(c(" ┌─ QUIZ ──────────────────────────────────────────────────", "blue")) print(c(" │ ", "blue") + c(q.get("question", msg), "bold")) for i, opt in enumerate(q.get("options", [])): print(c(" │ ", "blue") + f"{'ABCD'[i]}. {opt}") print(c(" └─────────────────────────────────────────────────────────", "blue")) print() quiz_shown = True continue chain_step(phase, msg) time.sleep(0.25) elapsed = time.time() - t_start print(c("─" * 64, "teal")) print(c(f" ✓ Autopilot complete in {elapsed:.1f}s — " f"grounded, offline, fine-tuned.", "green")) print(c("─" * 64, "teal")) if __name__ == "__main__": main()