mirror of
https://github.com/MLSysBook/TinyTorch.git
synced 2026-05-01 19:37:30 -05:00
- Add complete MilestoneSystem class with 5 epic milestones - Integrate milestone detection into module completion workflow - Implement milestone CLI commands (status, timeline, test, demo) - Add milestone progress tracking and storage (.tito/milestones.json) - Create epic celebration system for milestone unlocks - Register milestone commands in main CLI Features: - 5 milestones: Basic Inference → Computer Vision → Full Training → Advanced Vision → Language Generation - Visual progress tracking with Rich library - Module completion triggers milestone evaluation - Epic ASCII art celebrations for achievements - Timeline views (tree and horizontal progress bar) - Milestone testing and validation The milestone system transforms module completion into meaningful capability achievements that prepare students for ML engineering careers.
255 lines
10 KiB
Python
255 lines
10 KiB
Python
"""
|
|
TinyTorch CLI Main Entry Point
|
|
|
|
A professional command-line interface with proper architecture:
|
|
- Clean separation of concerns
|
|
- Proper error handling
|
|
- Logging support
|
|
- Configuration management
|
|
- Extensible command system
|
|
"""
|
|
|
|
import argparse
|
|
import logging
|
|
import os
|
|
import sys
|
|
from pathlib import Path
|
|
from typing import Dict, Type, Optional, List
|
|
|
|
from .core.config import CLIConfig
|
|
from .core.console import get_console, print_banner, print_error, print_ascii_logo
|
|
from .core.exceptions import TinyTorchCLIError
|
|
from rich.panel import Panel
|
|
from .commands.base import BaseCommand
|
|
from .commands.notebooks import NotebooksCommand
|
|
from .commands.info import InfoCommand
|
|
from .commands.test import TestCommand
|
|
from .commands.doctor import DoctorCommand
|
|
from .commands.export import ExportCommand
|
|
from .commands.reset import ResetCommand
|
|
from .commands.jupyter import JupyterCommand
|
|
from .commands.nbdev import NbdevCommand
|
|
from .commands.status import StatusCommand
|
|
from .commands.system import SystemCommand
|
|
from .commands.module import ModuleCommand
|
|
from .commands.package import PackageCommand
|
|
from .commands.nbgrader import NBGraderCommand
|
|
from .commands.book import BookCommand
|
|
from .commands.checkpoint import CheckpointCommand
|
|
from .commands.grade import GradeCommand
|
|
from .commands.demo import DemoCommand
|
|
from .commands.logo import LogoCommand
|
|
from .commands.milestone import MilestoneCommand
|
|
|
|
# Configure logging
|
|
logging.basicConfig(
|
|
level=logging.INFO,
|
|
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
|
|
handlers=[
|
|
logging.FileHandler('tito-cli.log'),
|
|
logging.StreamHandler(sys.stderr)
|
|
]
|
|
)
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
class TinyTorchCLI:
|
|
"""Main CLI application class."""
|
|
|
|
def __init__(self):
|
|
"""Initialize the CLI application."""
|
|
self.config = CLIConfig.from_project_root()
|
|
self.console = get_console()
|
|
self.commands: Dict[str, Type[BaseCommand]] = {
|
|
# Hierarchical command groups only
|
|
'system': SystemCommand,
|
|
'module': ModuleCommand,
|
|
'package': PackageCommand,
|
|
'nbgrader': NBGraderCommand,
|
|
'checkpoint': CheckpointCommand,
|
|
'milestone': MilestoneCommand,
|
|
# Convenience commands
|
|
'export': ExportCommand,
|
|
'test': TestCommand,
|
|
'book': BookCommand,
|
|
'grade': GradeCommand,
|
|
'demo': DemoCommand,
|
|
'logo': LogoCommand,
|
|
}
|
|
|
|
def create_parser(self) -> argparse.ArgumentParser:
|
|
"""Create the main argument parser."""
|
|
parser = argparse.ArgumentParser(
|
|
prog="tito",
|
|
description="TinyTorch CLI - Build ML systems from scratch",
|
|
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
epilog="""
|
|
Command Groups:
|
|
system System environment and configuration commands
|
|
module Module development and management commands
|
|
package Package management and nbdev integration commands
|
|
nbgrader Assignment management and auto-grading commands
|
|
checkpoint Track ML systems engineering progress through checkpoints
|
|
milestone Epic capability achievements and ML systems mastery
|
|
|
|
Convenience Commands:
|
|
export Export modules to package (quick shortcut)
|
|
test Run tests (quick shortcut)
|
|
book Build and manage Jupyter Book
|
|
grade Simplified grading interface (wraps NBGrader)
|
|
demo Run AI capability demos (show what your framework can do!)
|
|
|
|
Examples:
|
|
tito system info Show system information
|
|
tito module status --metadata Module status with metadata
|
|
tito module view 01_setup Start coding in Jupyter Lab
|
|
tito export 01_tensor Export specific module to package
|
|
tito checkpoint timeline Visual progress timeline
|
|
tito book build Build the Jupyter Book locally
|
|
"""
|
|
)
|
|
|
|
# Global options
|
|
parser.add_argument(
|
|
'--version',
|
|
action='version',
|
|
version='TinyTorch CLI 0.1.0'
|
|
)
|
|
parser.add_argument(
|
|
'--verbose', '-v',
|
|
action='store_true',
|
|
help='Enable verbose output'
|
|
)
|
|
parser.add_argument(
|
|
'--no-color',
|
|
action='store_true',
|
|
help='Disable colored output'
|
|
)
|
|
|
|
# Subcommands
|
|
subparsers = parser.add_subparsers(
|
|
dest='command',
|
|
help='Available commands',
|
|
metavar='COMMAND'
|
|
)
|
|
|
|
# Add command parsers
|
|
for command_name, command_class in self.commands.items():
|
|
# Create temporary instance to get metadata
|
|
temp_command = command_class(self.config)
|
|
cmd_parser = subparsers.add_parser(
|
|
command_name,
|
|
help=temp_command.description
|
|
)
|
|
temp_command.add_arguments(cmd_parser)
|
|
|
|
return parser
|
|
|
|
def validate_environment(self) -> bool:
|
|
"""Validate the environment and show issues if any."""
|
|
issues = self.config.validate()
|
|
|
|
if issues:
|
|
print_error(
|
|
"Environment validation failed:\n" + "\n".join(f" • {issue}" for issue in issues),
|
|
"Environment Issues"
|
|
)
|
|
self.console.print("\n[dim]Run 'tito doctor' for detailed diagnosis[/dim]")
|
|
# Return True to allow command execution despite validation issues
|
|
# This is temporary for development
|
|
return True
|
|
|
|
return True
|
|
|
|
def run(self, args: Optional[List[str]] = None) -> int:
|
|
"""Run the CLI application."""
|
|
try:
|
|
parser = self.create_parser()
|
|
parsed_args = parser.parse_args(args)
|
|
|
|
# Update config with global options
|
|
if hasattr(parsed_args, 'verbose') and parsed_args.verbose:
|
|
self.config.verbose = True
|
|
logging.getLogger().setLevel(logging.DEBUG)
|
|
|
|
if hasattr(parsed_args, 'no_color') and parsed_args.no_color:
|
|
self.config.no_color = True
|
|
|
|
# Show banner for interactive commands (except logo which has its own display)
|
|
if parsed_args.command and not self.config.no_color and parsed_args.command != 'logo':
|
|
print_banner()
|
|
|
|
# Validate environment for most commands (skip for doctor)
|
|
skip_validation = (
|
|
parsed_args.command in [None, 'version', 'help'] or
|
|
(parsed_args.command == 'system' and
|
|
hasattr(parsed_args, 'system_command') and
|
|
parsed_args.system_command == 'doctor')
|
|
)
|
|
if not skip_validation:
|
|
if not self.validate_environment():
|
|
return 1
|
|
|
|
# Handle no command
|
|
if not parsed_args.command:
|
|
# Show ASCII logo first
|
|
print_ascii_logo()
|
|
|
|
# Show enhanced help with command groups
|
|
self.console.print(Panel(
|
|
"[bold]Command Groups:[/bold]\n"
|
|
" [bold green]system[/bold green] - System environment and configuration\n"
|
|
" [bold green]module[/bold green] - Module development and management\n"
|
|
" [bold green]package[/bold green] - Package management and nbdev integration\n"
|
|
" [bold green]nbgrader[/bold green] - Assignment management and auto-grading\n"
|
|
" [bold green]checkpoint[/bold green] - Track ML systems engineering progress\n"
|
|
" [bold magenta]milestone[/bold magenta] - Epic capability achievements and ML mastery\n\n"
|
|
"[bold]Convenience Commands:[/bold]\n"
|
|
" [bold green]export[/bold green] - Export modules to package\n"
|
|
" [bold green]test[/bold green] - Run tests\n"
|
|
" [bold green]book[/bold green] - Build and manage Jupyter Book\n"
|
|
" [bold green]logo[/bold green] - Learn about TinyTorch philosophy\n"
|
|
"[bold]Quick Start:[/bold]\n"
|
|
" [dim]tito system info[/dim] - Show system information\n"
|
|
" [dim]tito module status --metadata[/dim] - Module status with metadata\n"
|
|
" [dim]tito module view 01_setup[/dim] - Start coding in Jupyter Lab\n"
|
|
" [dim]tito checkpoint timeline[/dim] - Visual progress timeline\n"
|
|
" [dim]tito milestone status[/dim] - See your epic achievement progress\n"
|
|
"[bold]Get Help:[/bold]\n"
|
|
" [dim]tito system[/dim] - Show system subcommands\n"
|
|
" [dim]tito module[/dim] - Show module subcommands\n"
|
|
" [dim]tito package[/dim] - Show package subcommands\n"
|
|
" [dim]tito --help[/dim] - Show full help",
|
|
title="Welcome to TinyTorch!",
|
|
border_style="bright_green"
|
|
))
|
|
return 0
|
|
|
|
# Execute command
|
|
if parsed_args.command in self.commands:
|
|
command_class = self.commands[parsed_args.command]
|
|
command = command_class(self.config)
|
|
return command.execute(parsed_args)
|
|
else:
|
|
print_error(f"Unknown command: {parsed_args.command}")
|
|
return 1
|
|
|
|
except KeyboardInterrupt:
|
|
self.console.print("\n[yellow]Operation cancelled by user[/yellow]")
|
|
return 130
|
|
except TinyTorchCLIError as e:
|
|
logger.error(f"CLI error: {e}")
|
|
print_error(str(e))
|
|
return 1
|
|
except Exception as e:
|
|
logger.exception("Unexpected error in CLI")
|
|
print_error(f"Unexpected error: {e}")
|
|
return 1
|
|
|
|
def main() -> int:
|
|
"""Main entry point for the CLI."""
|
|
cli = TinyTorchCLI()
|
|
return cli.run()
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main()) |