""" Gradio app for MentorFlow - Teacher-Student RL System Deployed on Hugging Face Spaces with GPU support """ import sys import os import subprocess from pathlib import Path import gradio as gr # Import directly, no patch needed # Add project paths sys.path.insert(0, str(Path(__file__).parent)) sys.path.insert(0, str(Path(__file__).parent / "teacher_agent_dev")) sys.path.insert(0, str(Path(__file__).parent / "student_agent_dev")) def run_comparison(iterations: int, seed: int, use_deterministic: bool, device: str): """ Run strategy comparison with LM Student. """ # Set device environment variable for subprocess if device == "cuda": try: import torch if torch.cuda.is_available(): try: gpu_name = torch.cuda.get_device_name(0) gpu_count = torch.cuda.device_count() print(f"✅ GPU available: {gpu_name} (Count: {gpu_count})") except Exception as e: print(f"⚠️ GPU detection failed: {e}") else: print("⚠️ CUDA not available, falling back to CPU") device = "cpu" except ImportError: print("⚠️ PyTorch not available, falling back to CPU") device = "cpu" except Exception as e: print(f"⚠️ GPU check error: {e}, falling back to CPU") device = "cpu" # Set environment variable for subprocess os.environ["CUDA_DEVICE"] = device print(f"🔧 Using device: {device}") # Prepare command cmd = [ sys.executable, "teacher_agent_dev/compare_strategies.py", "--iterations", str(iterations), ] if use_deterministic: cmd.append("--deterministic") else: cmd.extend(["--seed", str(int(seed))]) try: env = os.environ.copy() env["CUDA_DEVICE"] = os.environ.get("CUDA_DEVICE", device) result = subprocess.run( cmd, cwd=str(Path(__file__).parent), env=env, capture_output=True, text=True, timeout=3600 # 1 hour timeout ) stdout_text = result.stdout stderr_text = result.stderr full_output = f"=== STDOUT ===\n{stdout_text}\n\n=== STDERR ===\n{stderr_text}" if result.returncode != 0: return f"❌ Error occurred:\n{full_output}", None # Check multiple possible locations for the plot plot_paths = [ Path(__file__).parent / "teacher_agent_dev" / "comparison_all_strategies.png", Path(__file__).parent / "comparison_all_strategies.png", Path.cwd() / "teacher_agent_dev" / "comparison_all_strategies.png", ] plot_path = None for path in plot_paths: if path.exists(): plot_path = path break if plot_path: return f"✅ Comparison complete!\n\n{stdout_text}", str(plot_path) else: error_msg = f"⚠️ Plot not found at expected locations.\n" error_msg += f"Checked: {[str(p) for p in plot_paths]}\n\n" error_msg += f"Output:\n{full_output}" return error_msg, None except subprocess.TimeoutExpired: return "❌ Timeout: Comparison took longer than 1 hour", None except Exception as e: import traceback return f"❌ Error: {str(e)}\n\n{traceback.format_exc()}", None def check_gpu(): """Check if GPU is available on Hugging Face Spaces.""" try: import torch if torch.cuda.is_available(): try: gpu_name = torch.cuda.get_device_name(0) gpu_count = torch.cuda.device_count() cuda_version = torch.version.cuda return f"✅ GPU Available: {gpu_name} (Count: {gpu_count}, CUDA: {cuda_version})" except Exception as e: return f"✅ GPU Detected (accessing: {str(e)[:50]}...)" else: if os.getenv("SPACE_ID"): hf_hardware = os.getenv("SPACE_HARDWARE", "unknown") if "gpu" in hf_hardware.lower() or "t4" in hf_hardware.lower() or "l4" in hf_hardware.lower(): return f"⚠️ GPU Hardware ({hf_hardware}) allocated but not accessible yet. Try running anyway." return f"⚠️ No GPU on this Space (hardware: {hf_hardware}). Please configure GPU tier." return "⚠️ No GPU available, will use CPU" except ImportError: return "⚠️ PyTorch not installed" except Exception as e: return f"⚠️ GPU check error: {str(e)}" # Create Gradio interface with gr.Blocks(title="MentorFlow - Strategy Comparison") as demo: gr.Markdown(""" # 🎓 MentorFlow - Teacher-Student RL System Compare three training strategies using LM Student (DistilBERT): 1. **Random Strategy**: Random questions until student can pass difficult questions 2. **Progressive Strategy**: Easy → Medium → Hard within each family 3. **Teacher Strategy**: RL teacher agent learns optimal curriculum ## Usage 1. Set parameters below 2. Click "Run Comparison" to start training 3. View results and generated plots """) # GPU Status with gr.Row(): gpu_status = gr.Textbox(label="GPU Status", value=check_gpu(), interactive=False) refresh_btn = gr.Button("🔄 Refresh GPU Status") refresh_btn.click(fn=check_gpu, outputs=gpu_status, api_name="check_gpu") # Parameters with gr.Row(): with gr.Column(): iterations = gr.Slider(minimum=50, maximum=500, value=100, step=50, label="Iterations") seed = gr.Number(value=42, label="Random Seed") use_deterministic = gr.Checkbox(value=True, label="Deterministic Mode") device = gr.Radio(choices=["cuda", "cpu"], value="cuda", label="Device") with gr.Column(): run_btn = gr.Button("🚀 Run Comparison", variant="primary", size="lg") # Output with gr.Row(): with gr.Column(scale=1): output_text = gr.Textbox(label="Output", lines=15, max_lines=30, interactive=False) with gr.Column(scale=1): output_plot = gr.Image(label="Comparison Plot", type="filepath", height=500) # Run comparison run_btn.click( fn=run_comparison, inputs=[iterations, seed, use_deterministic, device], outputs=[output_text, output_plot], api_name="run_comparison" ) if __name__ == "__main__": # Standard HF Spaces configuration demo.launch(server_name="0.0.0.0", server_port=7860)