diff --git a/README.md b/README.md index dcae8cbe..cb8595da 100644 --- a/README.md +++ b/README.md @@ -109,13 +109,10 @@ Each project is inspired by key themes from the [*Machine Learning Systems*](htt ### Milestone Targets -**Part I: The Essentials (Chapters 1-4)** - **Week 1**: Environment setup (`setup`) and basic command familiarity - **Week 3**: Basic tensor operations (`tensor`) working - **Week 5**: Train MLP on MNIST (`mlp`) with manual backprop achieving >90% accuracy - **Week 7**: Train CNN on CIFAR-10 (`cnn`) basic implementation achieving >70% accuracy - -**Part II: Engineering Principles (Chapters 5-13)** - **Week 9**: Data pipeline (`data`) operational with efficient loading - **Week 11**: Complete autograd engine and training framework (`training`) working - **Week 13**: Optimized system with profiling tools (`profiling`) @@ -202,17 +199,12 @@ TinyTorch/ ### πŸ“‹ Project Sequence Each project builds on the previous ones. Click the links to jump to specific instructions: -### πŸ“– Part I: The Essentials (Chapters 1-4) | Order | Project | Status | Description | Instructions | |-------|---------|--------|-------------|--------------| | 0 | **Setup** | πŸš€ **START HERE** | Environment & CLI setup | [`projects/setup/README.md`](projects/setup/README.md) | | 1 | **Tensor** | ⏳ Coming Next | Basic tensor operations | [`projects/tensor/README.md`](projects/tensor/README.md) | | 2 | **MLP** | ⏳ Future | Multi-layer perceptron (manual backprop) | [`projects/mlp/README.md`](projects/mlp/README.md) | | 3 | **CNN** | ⏳ Future | Convolutional networks (basic) | [`projects/cnn/README.md`](projects/cnn/README.md) | - -### πŸ—οΈ Part II: Engineering Principles (Chapters 5-13) -| Order | Project | Status | Description | Instructions | -|-------|---------|--------|-------------|--------------| | 4 | **Data** | ⏳ Future | Data loading pipeline | [`projects/data/README.md`](projects/data/README.md) | | 5 | **Training** | ⏳ Future | Autograd engine & optimization | [`projects/training/README.md`](projects/training/README.md) | | 6 | **Profiling** | ⏳ Future | Performance profiling | [`projects/profiling/README.md`](projects/profiling/README.md) | @@ -226,9 +218,9 @@ Each project builds on the previous ones. Click the links to jump to specific in 1. **πŸ“– Read the overview** (you're here!) 2. **🎯 Detailed guidance**: [`COURSE_GUIDE.md`](COURSE_GUIDE.md) (comprehensive walkthrough) -3. **πŸ”§ Environment setup**: [`projects/setup/README.md`](projects/setup/README.md) -4. **βœ… Verify setup**: Run `python3 projects/setup/check_setup.py` -5. **πŸ“– Part I - Start with The Essentials**: [`projects/tensor/README.md`](projects/tensor/README.md) +3. **πŸš€ One-command setup**: `python3 bin/tito.py setup` (sets up everything!) +4. **βœ… Run activation**: Follow the command it gives you (usually `bin/activate-tinytorch.sh`) +5. **πŸ“– Start building**: [`projects/setup/README.md`](projects/setup/README.md) ### Prerequisites - **Python 3.8+** (type hints and modern features required) @@ -242,18 +234,14 @@ Each project builds on the previous ones. Click the links to jump to specific in git clone cd TinyTorch -# Automated setup (creates virtual environment + installs dependencies) -python3 projects/setup/create_env.py +# ONE SMART COMMAND - shows clear commands to copy +python3 bin/tito.py setup +# ↳ First time: Creates environment, installs dependencies, shows activation command +# ↳ Already exists: Shows activation command to copy +# ↳ Already active: Can show deactivation command -# Activate environment (do this every time you work) -source tinytorch-env/bin/activate # macOS/Linux -# OR: tinytorch-env\Scripts\activate # Windows - -# Verify setup -python3 projects/setup/check_setup.py - -# Check system status -python3 bin/tito.py info --show-architecture +# Copy and run the highlighted command, then: +tito info # Check system status ``` ### For Instructors @@ -271,9 +259,9 @@ python3 bin/tito.py course-status ### For Students ```bash -# Start with environment setup (IMPORTANT!) -python3 projects/setup/create_env.py -source tinytorch-env/bin/activate # Always activate first! +# ONE SMART COMMAND - handles everything (IMPORTANT!) +python3 bin/tito.py setup +# ↳ Shows clear commands to copy and paste! # Start with Project 0: Setup cd projects/setup/ diff --git a/bin/activate-tinytorch.sh b/bin/activate-tinytorch.sh new file mode 100755 index 00000000..836e6ea4 --- /dev/null +++ b/bin/activate-tinytorch.sh @@ -0,0 +1,29 @@ +#!/bin/bash +# TinyTorch Environment Activation & Setup + +# Check if virtual environment exists, create if not +if [ ! -d "tinytorch-env" ]; then + echo "πŸ†• First time setup - creating environment..." + python3 -m venv tinytorch-env || { + echo "❌ Failed to create virtual environment" + exit 1 + } + echo "πŸ“¦ Installing dependencies..." + tinytorch-env/bin/pip install -r requirements.txt || { + echo "❌ Failed to install dependencies" + exit 1 + } + echo "βœ… Environment created!" +fi + +echo "πŸ”₯ Activating TinyTorch environment..." +source tinytorch-env/bin/activate + +# Create tito alias for convenience +alias tito="python3 bin/tito.py" + +echo "βœ… Ready to build ML systems!" +echo "πŸ’‘ Quick commands:" +echo " tito info - Check system status" +echo " tito test - Run tests" +echo " tito doctor - Diagnose issues" diff --git a/bin/tito.py b/bin/tito.py index 9e9978de..b5ff44e5 100755 --- a/bin/tito.py +++ b/bin/tito.py @@ -12,119 +12,517 @@ import sys import os import argparse from pathlib import Path +import numpy as np + +# Rich imports for beautiful terminal output +from rich.console import Console +from rich.table import Table +from rich.panel import Panel +from rich.text import Text +from rich.tree import Tree +from rich.progress import Progress, SpinnerColumn, BarColumn, TextColumn # Add the project root to Python path sys.path.insert(0, str(Path(__file__).parent.parent)) +# Create Rich console instance +console = Console() + def print_banner(): - """Print the TinyTorch banner.""" - print("πŸ”₯ TinyπŸ”₯Torch: Build ML Systems from Scratch πŸ”₯") - print("=" * 50) + """Print the TinyTorch banner using Rich.""" + banner_text = Text("TinyπŸ”₯Torch: Build ML Systems from Scratch", style="bold red") + console.print(Panel(banner_text, style="bright_blue", padding=(1, 2))) + +def check_setup_status(): + """Check if setup project is complete.""" + try: + from tinytorch.core.utils import hello_tinytorch + return "βœ… Implemented" + except ImportError: + return "❌ Not Implemented" + +def check_tensor_status(): + """Check if tensor project is complete.""" + try: + from tinytorch.core.tensor import Tensor + # Test actual functionality, not just import + t1 = Tensor([1, 2, 3]) + t2 = Tensor([4, 5, 6]) + result = t1 + t2 # Should work if implemented + return "βœ… Implemented" + except (ImportError, NotImplementedError): + return "⏳ Not Started" + +def check_mlp_status(): + """Check if MLP project is complete.""" + try: + from tinytorch.core.modules import MLP + # Test actual functionality + mlp = MLP(input_size=10, hidden_size=5, output_size=2) + from tinytorch.core.tensor import Tensor + x = Tensor([[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]]) + output = mlp(x) # Should work if implemented + return "βœ… Implemented" + except (ImportError, NotImplementedError, AttributeError): + return "⏳ Not Started" + +def check_cnn_status(): + """Check if CNN project is complete.""" + try: + from tinytorch.core.modules import Conv2d + # Test actual functionality + conv = Conv2d(in_channels=3, out_channels=16, kernel_size=3) + from tinytorch.core.tensor import Tensor + x = Tensor(np.random.randn(1, 3, 32, 32)) + output = conv(x) # Should work if implemented + return "βœ… Implemented" + except (ImportError, NotImplementedError, AttributeError): + return "⏳ Not Started" + +def check_data_status(): + """Check if data project is complete.""" + try: + from tinytorch.core.dataloader import DataLoader + # Test actual functionality + data = [(np.random.randn(3, 32, 32), 0) for _ in range(10)] + loader = DataLoader(data, batch_size=2, shuffle=True) + batch = next(iter(loader)) # Should work if implemented + return "βœ… Implemented" + except (ImportError, NotImplementedError, AttributeError, StopIteration): + return "⏳ Not Started" + +def check_training_status(): + """Check if training project is complete.""" + try: + from tinytorch.core.optimizer import SGD + from tinytorch.core.tensor import Tensor + # Test actual functionality + t = Tensor([1.0, 2.0, 3.0], requires_grad=True) + optimizer = SGD([t], lr=0.01) + t.backward() # Should work if autograd is implemented + optimizer.step() # Should work if optimizer is implemented + return "βœ… Implemented" + except (ImportError, NotImplementedError, AttributeError): + return "⏳ Not Started" + +def check_profiling_status(): + """Check if profiling project is complete.""" + try: + from tinytorch.core.profiler import Profiler + # Test basic functionality + profiler = Profiler() + profiler.start("test") + profiler.end("test") + return "βœ… Implemented" + except (ImportError, NotImplementedError, AttributeError): + return "⏳ Not Started" + +def check_compression_status(): + """Check if compression project is complete.""" + try: + from tinytorch.core.compression import Pruner + # Test basic functionality + pruner = Pruner(sparsity=0.5) + return "βœ… Implemented" + except (ImportError, NotImplementedError, AttributeError): + return "⏳ Not Started" + +def check_kernels_status(): + """Check if kernels project is complete.""" + try: + from tinytorch.core.kernels import optimized_matmul + # Test basic functionality + a = np.random.randn(3, 3) + b = np.random.randn(3, 3) + result = optimized_matmul(a, b) + return "βœ… Implemented" + except (ImportError, NotImplementedError, AttributeError): + return "⏳ Not Started" + +def check_benchmarking_status(): + """Check if benchmarking project is complete.""" + try: + from tinytorch.core.benchmark import Benchmark + # Test basic functionality + benchmark = Benchmark() + return "βœ… Implemented" + except (ImportError, NotImplementedError, AttributeError): + return "⏳ Not Started" + +def check_mlops_status(): + """Check if MLOps project is complete.""" + try: + from tinytorch.core.mlops import ModelMonitor + from tinytorch.core.tensor import Tensor + # Test that the methods are actually implemented, not just placeholders + monitor = ModelMonitor(model=None, baseline_metrics={}) + # Try to use a method that should be implemented + test_inputs = Tensor([1.0, 2.0, 3.0]) + test_predictions = Tensor([0.5, 0.8, 0.2]) + monitor.log_prediction(test_inputs, test_predictions) + return "βœ… Implemented" + except (ImportError, NotImplementedError, AttributeError, TypeError): + return "⏳ Not Started" + +def validate_environment(): + """Validate environment setup before running commands.""" + issues = [] + + # Check virtual environment + in_venv = (hasattr(sys, 'real_prefix') or + (hasattr(sys, 'base_prefix') and sys.base_prefix != sys.prefix)) + if not in_venv: + issues.append("Virtual environment not activated. Run: source tinytorch-env/bin/activate") + + # Check Python version + if sys.version_info < (3, 8): + issues.append(f"Python 3.8+ required, found {sys.version_info.major}.{sys.version_info.minor}") + + # Check core dependencies + try: + import numpy + import pytest + except ImportError as e: + issues.append(f"Missing dependency: {e.name}. Run: pip install -r requirements.txt") + + # Check TinyTorch package structure + tinytorch_path = Path(__file__).parent.parent / "tinytorch" + if not tinytorch_path.exists(): + issues.append("TinyTorch package not found. Check project structure.") + + if issues: + issue_text = Text() + issue_text.append("❌ Environment Issues Detected\n\n", style="bold red") + for issue in issues: + issue_text.append(f" β€’ {issue}\n", style="yellow") + issue_text.append("\nRun 'python3 bin/tito.py doctor' for detailed diagnosis", style="dim") + + console.print(Panel(issue_text, title="Environment Problems", border_style="red")) + return False + + return True def cmd_version(args): """Show TinyTorch version.""" - print("TinyπŸ”₯Torch v0.1.0") - print("Machine Learning Systems Course") + version_text = Text() + version_text.append("TinyπŸ”₯Torch v0.1.0\n", style="bold red") + version_text.append("Machine Learning Systems Course", style="cyan") + console.print(Panel(version_text, title="Version Info", border_style="bright_blue")) def cmd_info(args): """Show system information and status.""" print_banner() - print() + console.print() - # Python environment info - print("πŸ“‹ System Information") - print("-" * 30) - print(f"Python: {sys.version.split()[0]}") - print(f"Platform: {sys.platform}") - print(f"Working Directory: {os.getcwd()}") + # System Information Panel + info_text = Text() + info_text.append(f"Python: {sys.version.split()[0]}\n", style="cyan") + info_text.append(f"Platform: {sys.platform}\n", style="cyan") + info_text.append(f"Working Directory: {os.getcwd()}\n", style="cyan") - # Virtual environment check - in_venv = (hasattr(sys, 'real_prefix') or - (hasattr(sys, 'base_prefix') and sys.base_prefix != sys.prefix)) - venv_status = "βœ… Active" if in_venv else "❌ Not Active" - print(f"Virtual Environment: {venv_status}") + # Virtual environment check - use same robust detection as doctor + venv_path = Path("tinytorch-env") + venv_exists = venv_path.exists() + in_venv = ( + # Method 1: Check VIRTUAL_ENV environment variable (most reliable for activation) + os.environ.get('VIRTUAL_ENV') is not None or + # Method 2: Check sys.prefix vs sys.base_prefix (works for running Python in venv) + (hasattr(sys, 'base_prefix') and sys.base_prefix != sys.prefix) or + # Method 3: Check for sys.real_prefix (older Python versions) + hasattr(sys, 'real_prefix') + ) - print() + if venv_exists and in_venv: + venv_style = "green" + venv_icon = "βœ…" + venv_status = "Ready & Active" + elif venv_exists: + venv_style = "yellow" + venv_icon = "βœ…" + venv_status = "Ready (Not Active)" + else: + venv_style = "red" + venv_icon = "❌" + venv_status = "Not Found" - # Course navigation - print("πŸ“‹ Course Navigation") - print("-" * 30) - print("πŸ“– Course Overview: README.md") - print("🎯 Detailed Guide: COURSE_GUIDE.md") - print("πŸš€ Start Here: projects/setup/README.md") + info_text.append(f"Virtual Environment: {venv_icon} ", style=venv_style) + info_text.append(venv_status, style=f"bold {venv_style}") - print() + console.print(Panel(info_text, title="πŸ“‹ System Information", border_style="bright_blue")) + console.print() + + # Course Navigation Panel + nav_text = Text() + nav_text.append("πŸ“– Course Overview: ", style="dim") + nav_text.append("README.md\n", style="cyan underline") + nav_text.append("🎯 Detailed Guide: ", style="dim") + nav_text.append("COURSE_GUIDE.md\n", style="cyan underline") + nav_text.append("πŸš€ Start Here: ", style="dim") + nav_text.append("projects/setup/README.md", style="cyan underline") + + console.print(Panel(nav_text, title="πŸ“‹ Course Navigation", border_style="bright_green")) + console.print() # Implementation status - print("πŸš€ Implementation Status") - print("-" * 30) + projects = [ + ("Setup", "hello_tinytorch function", check_setup_status), + ("Tensor", "basic tensor operations", check_tensor_status), + ("MLP", "multi-layer perceptron (manual)", check_mlp_status), + ("CNN", "convolutional networks (basic)", check_cnn_status), + ("Data", "data loading pipeline", check_data_status), + ("Training", "autograd engine & optimization", check_training_status), + ("Profiling", "performance profiling", check_profiling_status), + ("Compression", "model compression", check_compression_status), + ("Kernels", "custom compute kernels", check_kernels_status), + ("Benchmarking", "performance benchmarking", check_benchmarking_status), + ("MLOps", "production monitoring", check_mlops_status), + ] - # Check if hello function exists - try: - from tinytorch.core.utils import hello_tinytorch - hello_status = "βœ… Implemented" - if args.hello: - print(f"Hello Message: {hello_tinytorch()}") - except ImportError: - hello_status = "❌ Not Implemented" + # Project Status Table + status_table = Table(title="πŸš€ Project Implementation Status", show_header=True, header_style="bold blue") + status_table.add_column("ID", style="dim", width=3, justify="center") + status_table.add_column("Project", style="bold cyan", width=12) + status_table.add_column("Status", width=18, justify="center") + status_table.add_column("Description", style="dim", width=40) - print(f"hello_tinytorch(): {hello_status}") + for i, (name, desc, check_func) in enumerate(projects): + status_text = check_func() + if "βœ…" in status_text: + status_style = "[green]βœ… Implemented[/green]" + elif "❌" in status_text: + status_style = "[red]❌ Not Implemented[/red]" + else: + status_style = "[yellow]⏳ Not Started[/yellow]" + + status_table.add_row(str(i), name, status_style, desc) - # TODO: Add checks for other components as they're implemented - print("tensor operations: ⏳ Coming in Project 1") - print("autograd engine: ⏳ Coming in Project 4") - print("neural networks: ⏳ Coming in Project 2") - print("training system: ⏳ Coming in Project 6") + console.print(status_table) + + if args.hello and check_setup_status() == "βœ… Implemented": + try: + from tinytorch.core.utils import hello_tinytorch + hello_text = Text(hello_tinytorch(), style="bold red") + console.print() + console.print(Panel(hello_text, style="bright_red", padding=(1, 2))) + except ImportError: + pass if args.show_architecture: - print() - print("πŸ—οΈ System Architecture") - print("-" * 30) - print(""" -β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” -β”‚ TinyTorch System β”‚ -β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ -β”‚ CLI Interface (bin/tito.py) β”‚ -β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ -β”‚ Training Orchestration (trainer.py) β”‚ -β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ -β”‚ Model Definition β”‚ Data Pipeline β”‚ Optimization β”‚ -β”‚ (modules.py) β”‚ (dataloader.py) β”‚ (optimizer.py) β”‚ -β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ -β”‚ Automatic Differentiation Engine (autograd) β”‚ -β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ -β”‚ Tensor Operations & Storage (tensor.py) β”‚ -β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ -β”‚ Profiling & MLOps (profiler.py, mlops.py) β”‚ -β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ - """) + console.print() + + # Create architecture tree + arch_tree = Tree("πŸ—οΈ TinyTorch System Architecture", style="bold blue") + + cli_branch = arch_tree.add("CLI Interface", style="cyan") + cli_branch.add("bin/tito.py - Command line tools", style="dim") + + training_branch = arch_tree.add("Training Orchestration", style="cyan") + training_branch.add("trainer.py - Training loop management", style="dim") + + core_branch = arch_tree.add("Core Components", style="cyan") + model_sub = core_branch.add("Model Definition", style="yellow") + model_sub.add("modules.py - Neural network layers", style="dim") + + data_sub = core_branch.add("Data Pipeline", style="yellow") + data_sub.add("dataloader.py - Efficient data loading", style="dim") + + opt_sub = core_branch.add("Optimization", style="yellow") + opt_sub.add("optimizer.py - SGD, Adam, etc.", style="dim") + + autograd_branch = arch_tree.add("Automatic Differentiation Engine", style="cyan") + autograd_branch.add("autograd.py - Gradient computation", style="dim") + + tensor_branch = arch_tree.add("Tensor Operations & Storage", style="cyan") + tensor_branch.add("tensor.py - Core tensor implementation", style="dim") + + system_branch = arch_tree.add("System Tools", style="cyan") + system_branch.add("profiler.py - Performance measurement", style="dim") + system_branch.add("mlops.py - Production monitoring", style="dim") + + console.print(Panel(arch_tree, title="πŸ—οΈ System Architecture", border_style="bright_blue")) def cmd_test(args): """Run tests for a specific project.""" - print(f"πŸ§ͺ Running tests for project: {args.project}") + valid_projects = ["setup", "tensor", "mlp", "cnn", "data", "training", + "profiling", "compression", "kernels", "benchmarking", "mlops"] - if args.project == "setup": - # Run setup tests + if args.all: + # Run all tests with progress bar import subprocess - test_file = "projects/setup/test_setup.py" + failed_projects = [] + + # Count existing test files + existing_tests = [p for p in valid_projects if Path(f"projects/{p}/test_{p}.py").exists()] + + console.print(Panel(f"πŸ§ͺ Running tests for {len(existing_tests)} projects", + title="Test Suite", border_style="bright_cyan")) + + with Progress( + SpinnerColumn(), + TextColumn("[progress.description]{task.description}"), + BarColumn(), + TextColumn("[progress.percentage]{task.percentage:>3.0f}%"), + console=console + ) as progress: + + task = progress.add_task("Running tests...", total=len(existing_tests)) + + for project in existing_tests: + progress.update(task, description=f"Testing {project}...") + + test_file = f"projects/{project}/test_{project}.py" + result = subprocess.run([sys.executable, "-m", "pytest", test_file, "-v"], + capture_output=True, text=True) + + if result.returncode != 0: + failed_projects.append(project) + console.print(f"[red]❌ {project} tests failed[/red]") + else: + console.print(f"[green]βœ… {project} tests passed[/green]") + + progress.advance(task) + + # Results summary + if failed_projects: + console.print(Panel(f"[red]❌ Failed projects: {', '.join(failed_projects)}[/red]", + title="Test Results", border_style="red")) + return 1 + else: + console.print(Panel("[green]βœ… All tests passed![/green]", + title="Test Results", border_style="green")) + return 0 + + elif args.project in valid_projects: + # Run specific project tests + import subprocess + test_file = f"projects/{args.project}/test_{args.project}.py" + + console.print(Panel(f"πŸ§ͺ Running tests for project: [bold cyan]{args.project}[/bold cyan]", + title="Single Project Test", border_style="bright_cyan")) + + if not Path(test_file).exists(): + console.print(Panel(f"[yellow]⏳ Test file not found: {test_file}\n" + f"Project '{args.project}' may not be implemented yet.[/yellow]", + title="Test Not Found", border_style="yellow")) + return 1 + + console.print(f"[dim]Running: pytest {test_file} -v[/dim]") + console.print() + result = subprocess.run([sys.executable, "-m", "pytest", test_file, "-v"], capture_output=False) + + # Show result summary + if result.returncode == 0: + console.print(Panel(f"[green]βœ… All tests passed for {args.project}![/green]", + title="Test Results", border_style="green")) + else: + console.print(Panel(f"[red]❌ Some tests failed for {args.project}[/red]", + title="Test Results", border_style="red")) + return result.returncode else: - print(f"Tests for project '{args.project}' not yet implemented.") + console.print(Panel(f"[red]❌ Unknown project: {args.project}[/red]\n" + f"Valid projects: {', '.join(valid_projects)}", + title="Invalid Project", border_style="red")) return 1 def cmd_submit(args): """Submit project for grading.""" - print(f"πŸ“€ Submitting project: {args.project}") - print("🚧 Submission system not yet implemented.") - print("For now, make sure all tests pass with:") - print(f" python -m pytest projects/{args.project}/test_*.py -v") + submit_text = Text() + submit_text.append(f"πŸ“€ Submitting project: {args.project}\n\n", style="bold cyan") + submit_text.append("🚧 Submission system not yet implemented.\n\n", style="yellow") + submit_text.append("For now, make sure all tests pass with:\n", style="dim") + submit_text.append(f" python -m pytest projects/{args.project}/test_*.py -v", style="bold white") + + console.print(Panel(submit_text, title="Project Submission", border_style="bright_yellow")) def cmd_status(args): """Check project status.""" - print(f"πŸ“Š Status for project: {args.project}") - print("🚧 Status system not yet implemented.") + status_text = Text() + status_text.append(f"πŸ“Š Status for project: {args.project}\n\n", style="bold cyan") + status_text.append("🚧 Status system not yet implemented.", style="yellow") + + console.print(Panel(status_text, title="Project Status", border_style="bright_yellow")) + + + + +def cmd_doctor(args): + """Run comprehensive environment diagnosis.""" + console.print(Panel("πŸ”¬ TinyTorch Environment Diagnosis", + title="System Doctor", border_style="bright_magenta")) + console.print() + + # Environment checks table + env_table = Table(title="Environment Check", show_header=True, header_style="bold blue") + env_table.add_column("Component", style="cyan", width=20) + env_table.add_column("Status", justify="left") + env_table.add_column("Details", style="dim", width=30) + + # Python environment + env_table.add_row("Python", "[green]βœ… OK[/green]", f"{sys.version.split()[0]} ({sys.platform})") + + # Virtual environment - check if it exists and if we're using it + venv_path = Path("tinytorch-env") + venv_exists = venv_path.exists() + in_venv = ( + # Method 1: Check VIRTUAL_ENV environment variable (most reliable for activation) + os.environ.get('VIRTUAL_ENV') is not None or + # Method 2: Check sys.prefix vs sys.base_prefix (works for running Python in venv) + (hasattr(sys, 'base_prefix') and sys.base_prefix != sys.prefix) or + # Method 3: Check for sys.real_prefix (older Python versions) + hasattr(sys, 'real_prefix') + ) + + if venv_exists and in_venv: + venv_status = "[green]βœ… Ready & Active[/green]" + elif venv_exists: + venv_status = "[yellow]βœ… Ready (Not Active)[/yellow]" + else: + venv_status = "[red]❌ Not Found[/red]" + env_table.add_row("Virtual Environment", venv_status, "tinytorch-env") + + # Dependencies + dependencies = ['numpy', 'matplotlib', 'pytest', 'yaml', 'black', 'rich'] + for dep in dependencies: + try: + module = __import__(dep) + version = getattr(module, '__version__', 'unknown') + env_table.add_row(dep.title(), "[green]βœ… OK[/green]", f"v{version}") + except ImportError: + env_table.add_row(dep.title(), "[red]❌ Missing[/red]", "Not installed") + + console.print(env_table) + console.print() + + # Project structure table + struct_table = Table(title="Project Structure", show_header=True, header_style="bold magenta") + struct_table.add_column("Path", style="cyan", width=25) + struct_table.add_column("Status", justify="left") + struct_table.add_column("Type", style="dim", width=25) + + required_paths = [ + ('tinytorch/', 'Package directory'), + ('tinytorch/core/', 'Core module directory'), + ('projects/', 'Project directory'), + ('bin/tito.py', 'CLI script'), + ('requirements.txt', 'Dependencies file') + ] + + for path, desc in required_paths: + if Path(path).exists(): + struct_table.add_row(path, "[green]βœ… Found[/green]", desc) + else: + struct_table.add_row(path, "[red]❌ Missing[/red]", desc) + + console.print(struct_table) + console.print() + + # Project implementations + console.print(Panel("πŸ“‹ Implementation Status", + title="Project Status", border_style="bright_blue")) + cmd_info(argparse.Namespace(hello=False, show_architecture=False)) def main(): """Main CLI entry point.""" @@ -136,6 +534,8 @@ def main(): subparsers = parser.add_subparsers(dest="command", help="Available commands") + + # Info command info_parser = subparsers.add_parser("info", help="Show system information") info_parser.add_argument("--hello", action="store_true", help="Show hello message") @@ -143,7 +543,8 @@ def main(): # Test command test_parser = subparsers.add_parser("test", help="Run project tests") - test_parser.add_argument("--project", required=True, help="Project to test") + test_parser.add_argument("--project", help="Project to test") + test_parser.add_argument("--all", action="store_true", help="Run all project tests") # Submit command submit_parser = subparsers.add_parser("submit", help="Submit project") @@ -153,6 +554,9 @@ def main(): status_parser = subparsers.add_parser("status", help="Check project status") status_parser.add_argument("--project", required=True, help="Project to check") + # Doctor command + doctor_parser = subparsers.add_parser("doctor", help="Run environment diagnosis") + args = parser.parse_args() # Handle version flag @@ -160,6 +564,19 @@ def main(): cmd_version(args) return 0 + # Environment validation (skip for doctor and info commands) + if args.command not in ["doctor", "info"] and not validate_environment(): + return 1 + + # Validate test command arguments + if args.command == "test": + if not args.all and not args.project: + error_text = Text() + error_text.append("❌ Error: Must specify either --project or --all\n\n", style="bold red") + error_text.append("Usage: python bin/tito.py test --project | --all", style="cyan") + console.print(Panel(error_text, title="Invalid Arguments", border_style="red")) + return 1 + # Handle commands if args.command == "info": cmd_info(args) @@ -169,6 +586,8 @@ def main(): cmd_submit(args) elif args.command == "status": cmd_status(args) + elif args.command == "doctor": + cmd_doctor(args) else: parser.print_help() return 1 diff --git a/projects/setup/README.md b/projects/setup/README.md index 85ce8319..4ecb5a8f 100644 --- a/projects/setup/README.md +++ b/projects/setup/README.md @@ -13,55 +13,46 @@ By the end of this project, you will: ## πŸ“‹ Setup Checklist -### Step 1: Environment Setup +### Step 1: One-Command Environment Setup -**Check Python Version** +**The Only Command You Need** πŸš€ ```bash -python3 --version # Should be 3.8 or higher +bin/activate-tinytorch.sh ``` -**Create Virtual Environment** (REQUIRED) +This smart script handles everything: +- πŸ†• **First time**: Creates environment, installs dependencies, activates it +- πŸ’€ **Already exists**: Just activates the existing environment +- βœ… **Already active**: Already good to go! + +**Super Simple Workflow!** ⚑ ```bash -# Create isolated environment for TinyTorch -python3 -m venv tinytorch-env +# First time or any time - just run: +bin/activate-tinytorch.sh -# Activate it (you'll do this every time) -source tinytorch-env/bin/activate # macOS/Linux -# OR on Windows: tinytorch-env\Scripts\activate +# Then you're ready: +tito info # Check system status +tito test # Run tests +tito doctor # Diagnose any issues -# Verify you're in the virtual environment -which python # Should show path with tinytorch-env +# When done: +deactivate # Exit the environment ``` -**Install Dependencies** -```bash -# Make sure you're in the activated virtual environment! -pip install --upgrade pip -pip install -r requirements.txt -``` - -**Verify Installation** -```bash -python3 -c "import numpy, matplotlib, yaml; print('βœ… Core dependencies installed')" -``` - -> **⚠️ Important**: Always activate your virtual environment before working: -> ```bash -> source tinytorch-env/bin/activate # Run this every time you start working -> ``` +> **πŸ’‘ Dead simple!** One script does everything - no setup commands, no complexity. ### Step 2: System Verification **Test the CLI** ```bash -python3 bin/tito.py --version -python3 bin/tito.py info +tito --version # (after running bin/activate-tinytorch.sh) +tito info ``` You should see the TinyπŸ”₯Torch banner and system status. **Check Project Structure** ```bash -python3 bin/tito.py info --show-architecture +tito info --show-architecture ``` This shows the system architecture you'll be building. @@ -70,13 +61,13 @@ This shows the system architecture you'll be building. **Learn Status Commands** ```bash # Check implementation status -python3 bin/tito.py info +tito info # Test specific project (you'll use this constantly) -python3 bin/tito.py test --project setup +tito test --project setup # Get help on any command -python3 bin/tito.py train --help +tito --help ``` ## πŸš€ Hello World Implementation @@ -112,7 +103,7 @@ def hello_tinytorch() -> str: python3 -m pytest projects/setup/test_setup.py -v # Or run the CLI test command -python3 bin/tito.py test --project setup +tito test --project setup # Run comprehensive setup check python3 projects/setup/check_setup.py @@ -150,7 +141,7 @@ Next steps: cat README.md You can now submit this project: - python3 bin/tito.py submit --project setup + tito submit --project setup ``` ## πŸ“š What You've Learned diff --git a/requirements.txt b/requirements.txt index f41f252b..1b4cc4eb 100644 --- a/requirements.txt +++ b/requirements.txt @@ -14,6 +14,9 @@ PyYAML>=6.0 pytest>=7.0.0 pytest-cov>=4.0.0 +# Rich terminal formatting +rich>=13.0.0 + # Optional performance (uncomment if needed) # numba>=0.58.0