File size: 6,830 Bytes
a52f96d
 
 
 
 
 
 
a4ee801
a52f96d
c99cd73
85ce009
a52f96d
 
 
 
 
b4b1e11
a52f96d
 
 
 
a4ee801
a52f96d
 
 
85ce009
 
 
4bbb666
 
85ce009
4bbb666
85ce009
4bbb666
a4ee801
ec32884
4bbb666
ec32884
85ce009
4bbb666
a4ee801
 
c99cd73
a4ee801
85ce009
a52f96d
 
 
 
 
 
 
 
 
 
 
 
 
 
a4ee801
 
a52f96d
 
 
 
c99cd73
a52f96d
 
 
 
a4ee801
 
 
 
 
 
 
 
 
c99cd73
a4ee801
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
a52f96d
 
 
 
 
 
 
 
 
4bbb666
a52f96d
 
 
85ce009
 
 
4bbb666
 
85ce009
4bbb666
a52f96d
85ce009
4bbb666
 
 
 
 
85ce009
 
 
4bbb666
a52f96d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ff6c480
a52f96d
 
 
 
c99cd73
 
 
 
a52f96d
 
 
 
 
 
 
c99cd73
a52f96d
c99cd73
a52f96d
 
 
 
 
ff6c480
 
a52f96d
 
 
c99cd73
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
"""
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)