Rahmath1/self_improving_agent
0
1import sys2import os3sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))4 5try:6 from openenv.core.env_server.http_server import create_app7except Exception as e:8 raise ImportError("openenv-core is required. Install with: pip install openenv-core") from e9 10from fastapi.responses import HTMLResponse11from fastapi import Request12from models import AdvanceAgentAction, AdvanceAgentObservation13from server.Advance_agent_environment import AdvanceAgentEnvironment14 15 16def env_factory() -> AdvanceAgentEnvironment:17 return AdvanceAgentEnvironment()18 19app = create_app(20 env=env_factory,21 action_cls=AdvanceAgentAction,22 observation_cls=AdvanceAgentObservation,23 env_name="Advance_agent_environment",24 max_concurrent_envs=1,25)26 27 28DASHBOARD_HTML = """<!DOCTYPE html>29<html>30<head>31 <title>π€ EDA OpenEnv Dashboard</title>32 <style>33 * { box-sizing: border-box; margin: 0; padding: 0; }34 body { font-family: 'Segoe UI', Arial, sans-serif; background: #0f0f0f; color: #fff; padding: 20px; }35 h1 { color: #4fc3f7; margin-bottom: 4px; font-size: 24px; }36 .subtitle { color: #888; margin-bottom: 20px; font-size: 13px; }37 .row { display: flex; gap: 16px; flex-wrap: wrap; margin-bottom: 16px; }38 .box { background: #1a1a2e; padding: 16px; border-radius: 10px; border: 1px solid #2a2a4a; flex: 1; min-width: 200px; }39 .box h3 { color: #4fc3f7; margin-bottom: 12px; font-size: 14px; text-transform: uppercase; letter-spacing: 1px; }40 button { background: #4fc3f7; color: #000; border: none; padding: 9px 18px; border-radius: 6px; cursor: pointer; margin: 4px; font-size: 13px; font-weight: bold; transition: opacity 0.2s; }41 button:hover { opacity: 0.8; }42 .btn-green { background: #66bb6a; }43 .btn-orange { background: #ffa726; }44 .btn-red { background: #ef5350; color: white; }45 .btn-gray { background: #444; color: white; }46 select { background: #2a2a4a; color: white; border: 1px solid #444; padding: 8px 12px; border-radius: 6px; margin: 4px; font-size: 13px; }47 .pipeline { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin: 10px 0; }48 .step-box { padding: 8px 14px; border-radius: 20px; font-size: 12px; font-weight: bold; border: 2px solid #444; color: #888; transition: all 0.3s; }49 .step-done { background: #1b5e20; border-color: #66bb6a; color: #66bb6a; }50 .step-next { background: #1a237e; border-color: #4fc3f7; color: #4fc3f7; animation: pulse 1.5s infinite; }51 .step-pending { background: #1a1a1a; border-color: #333; color: #555; }52 .arrow { color: #444; font-size: 18px; }53 @keyframes pulse { 0%,100% { opacity:1; } 50% { opacity:0.5; } }54 .metric { text-align: center; padding: 10px; }55 .metric-val { font-size: 32px; font-weight: bold; color: #4fc3f7; }56 .metric-val.good { color: #66bb6a; }57 .metric-val.bad { color: #ef5350; }58 .metric-label { font-size: 11px; color: #888; margin-top: 4px; text-transform: uppercase; }59 .task-badge { display: inline-block; padding: 6px 14px; border-radius: 20px; font-size: 13px; font-weight: bold; margin: 6px 0; }60 .easy { background: #1b5e20; color: #66bb6a; }61 .medium { background: #e65100; color: #ffa726; }62 .hard { background: #b71c1c; color: #ef9a9a; }63 .log { background: #0a0a1a; padding: 12px; border-radius: 8px; height: 180px; overflow-y: auto; font-family: monospace; font-size: 12px; color: #00ff00; border: 1px solid #1a1a3a; }64 .log .warn { color: #ffa726; }65 .log .error { color: #ef5350; }66 .log .success { color: #66bb6a; }67 .log .info { color: #4fc3f7; }68 .dataset-table { width: 100%; border-collapse: collapse; font-size: 12px; margin-top: 8px; }69 .dataset-table th { background: #1a237e; padding: 6px 10px; text-align: left; color: #4fc3f7; }70 .dataset-table td { padding: 5px 10px; border-bottom: 1px solid #1a1a3a; color: #ccc; }71 .dataset-table tr:hover td { background: #1a1a3a; }72 .reward-bar { height: 8px; background: #1a1a3a; border-radius: 4px; margin-top: 6px; overflow: hidden; }73 .reward-fill { height: 100%; background: linear-gradient(90deg, #4fc3f7, #66bb6a); border-radius: 4px; transition: width 0.5s; }74 .history-item { padding: 6px 10px; margin: 3px 0; border-radius: 6px; font-size: 12px; display: flex; justify-content: space-between; }75 .history-ok { background: #0d2818; border-left: 3px solid #66bb6a; }76 .history-pen { background: #2d0d0d; border-left: 3px solid #ef5350; }77 .cols-list { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }78 .col-tag { background: #1a237e; color: #4fc3f7; padding: 3px 10px; border-radius: 12px; font-size: 11px; }79 #spinner { display: none; color: #ffa726; font-size: 13px; margin-left: 8px; }80 </style>81</head>82<body>83<h1>π€ EDA OpenEnv Agent Dashboard</h1>84<p class="subtitle">Meta PyTorch OpenEnv Hackathon β Real-world RL environment for Exploratory Data Analysis</p>85 86<!-- Controls -->87<div class="row">88 <div class="box" style="flex: 2">89 <h3>βοΈ Controls</h3>90 <div style="display:flex; align-items:center; flex-wrap:wrap; gap:8px; margin-bottom:10px">91 <select id="taskSelect">92 <option value="">π² Random Task</option>93 <option value="detect_missing">π’ detect_missing (easy)</option>94 <option value="find_correlation">π‘ find_correlation (medium)</option>95 <option value="generate_insight">π΄ generate_insight (hard)</option>96 </select>97 <button onclick="resetEnv()" class="btn-green">π Reset</button>98 <button onclick="autoPlay()" class="btn-orange">β‘ Auto Play</button>99 <button onclick="stopAuto()" class="btn-gray">βΉ Stop</button>100 <span id="spinner">β³ Running...</span>101 </div>102 <div style="margin-bottom:8px">103 <select id="actionSelect">104 <option value="clean_data">clean_data</option>105 <option value="eda">eda</option>106 <option value="feature_engineering">feature_engineering</option>107 <option value="train_model">train_model</option>108 <option value="missing">missing</option>109 <option value="correlation">correlation</option>110 <option value="insight">insight</option>111 </select>112 <button onclick="takeStep()" class="btn-blue" style="background:#4fc3f7">βΆοΈ Step</button>113 </div>114 </div>115 116 <!-- Task Info -->117 <div class="box">118 <h3>π― Current Task</h3>119 <div id="taskBadge" class="task-badge easy">β</div>120 <p style="font-size:12px; color:#aaa; margin-top:8px" id="taskObjective">Reset to start a new episode</p>121 </div>122 123 <!-- Score -->124 <div class="box">125 <h3>π Score</h3>126 <div class="row" style="gap:0; margin:0">127 <div class="metric">128 <div class="metric-val" id="totalReward">β</div>129 <div class="metric-label">Cumulative Reward</div>130 </div>131 <div class="metric">132 <div class="metric-val" id="stepCount">0</div>133 <div class="metric-label">Steps Taken</div>134 </div>135 </div>136 <div class="reward-bar"><div class="reward-fill" id="rewardBar" style="width:0%"></div></div>137 </div>138</div>139 140<!-- Pipeline Progress -->141<div class="box" style="margin-bottom:16px">142 <h3>πΊοΈ Pipeline Progress</h3>143 <div class="pipeline" id="pipeline">144 <div class="step-box step-next" id="pipe_clean_data">clean_data</div>145 <div class="arrow">β</div>146 <div class="step-box step-pending" id="pipe_eda">eda</div>147 <div class="arrow">β</div>148 <div class="step-box step-pending" id="pipe_feature_engineering">feature_engineering</div>149 <div class="arrow">β</div>150 <div class="step-box step-pending" id="pipe_train_model">train_model</div>151 <div class="arrow">β</div>152 <div class="step-box step-pending" id="pipe_task_action">task action</div>153 </div>154</div>155 156<!-- Main content -->157<div class="row">158 <!-- Dataset -->159 <div class="box" style="flex:2">160 <h3>π Dataset Preview</h3>161 <div id="colsList" class="cols-list"></div>162 <div style="overflow-x:auto; margin-top:10px">163 <table class="dataset-table" id="dataTable">164 <tr><td colspan="5" style="color:#555; text-align:center; padding:20px">Reset to load dataset</td></tr>165 </table>166 </div>167 </div>168 169 <!-- Step History -->170 <div class="box">171 <h3>π Step History</h3>172 <div id="historyList" style="max-height:220px; overflow-y:auto">173 <p style="color:#555; font-size:12px; text-align:center; padding:20px">No steps yet</p>174 </div>175 </div>176</div>177 178<!-- Log -->179<div class="box">180 <h3>π Log</h3>181 <div class="log" id="log">Waiting for reset...\n</div>182</div>183 184<script>185const PIPELINE = ['clean_data','eda','feature_engineering','train_model'];186const TASK_ACTIONS = {detect_missing:'missing', find_correlation:'correlation', generate_insight:'insight'};187let history = [];188let autoTimer = null;189let stepNum = 0;190let currentTask = '';191let totalReward = 0;192 193function log(msg, cls='') {194 const el = document.getElementById('log');195 const line = cls ? `<span class="${cls}">${msg}</span>` : msg;196 el.innerHTML += line + '\\n';197 el.scrollTop = el.scrollHeight;198}199 200function getCompleted() {201 return history.filter(h => !h.is_penalty).map(h => h.action);202}203 204function updatePipeline() {205 const completed = getCompleted();206 const nextIdx = PIPELINE.findIndex(s => !completed.includes(s));207 const pipelineDone = nextIdx === -1;208 209 PIPELINE.forEach((s, i) => {210 const el = document.getElementById('pipe_' + s);211 if (!el) return;212 el.className = 'step-box';213 if (completed.includes(s)) el.classList.add('step-done');214 else if (i === nextIdx) el.classList.add('step-next');215 else el.classList.add('step-pending');216 });217 218 const taskEl = document.getElementById('pipe_task_action');219 const taskAction = TASK_ACTIONS[currentTask] || 'task action';220 taskEl.textContent = taskAction;221 if (pipelineDone && completed.includes(taskAction)) {222 taskEl.className = 'step-box step-done';223 } else if (pipelineDone) {224 taskEl.className = 'step-box step-next';225 } else {226 taskEl.className = 'step-box step-pending';227 }228 229 // Auto-select next action230 if (!pipelineDone) {231 document.getElementById('actionSelect').value = PIPELINE[nextIdx];232 } else {233 document.getElementById('actionSelect').value = taskAction;234 }235}236 237function renderDataset(obs) {238 if (!obs || !obs.columns) return;239 240 // Columns241 const colsEl = document.getElementById('colsList');242 colsEl.innerHTML = obs.columns.map(c => `<span class="col-tag">${c}</span>`).join('');243 244 // Table245 const table = document.getElementById('dataTable');246 const headers = obs.columns.map(c => `<th>${c}</th>`).join('');247 const rows = (obs.dataset_head || []).map(row => {248 const cells = obs.columns.map(c => {249 const v = row[c];250 const display = v === null || v === undefined ? '<span style="color:#ef5350">NaN</span>' : v;251 return `<td>${display}</td>`;252 }).join('');253 return `<tr>${cells}</tr>`;254 }).join('');255 table.innerHTML = `<tr>${headers}</tr>${rows}`;256}257 258function updateStats(reward, done) {259 stepNum++;260 totalReward += reward;261 const display = totalReward.toFixed(4);262 const el = document.getElementById('totalReward');263 el.textContent = display;264 el.className = 'metric-val ' + (totalReward > 0 ? 'good' : 'bad');265 document.getElementById('stepCount').textContent = stepNum;266 // Bar: normalise to 0-100% assuming max ~5267 const pct = Math.min(100, Math.max(0, (totalReward / 3) * 100));268 document.getElementById('rewardBar').style.width = pct + '%';269}270 271function addHistoryItem(action, reward, is_penalty, feedback) {272 const list = document.getElementById('historyList');273 if (list.querySelector('p')) list.innerHTML = '';274 const cls = is_penalty ? 'history-pen' : 'history-ok';275 const icon = is_penalty ? 'β οΈ' : 'β
';276 const item = document.createElement('div');277 item.className = 'history-item ' + cls;278 item.innerHTML = `<span>${icon} <b>${action}</b></span><span style="color:${is_penalty?'#ef5350':'#66bb6a'}">${reward.toFixed(4)}</span>`;279 list.appendChild(item);280 list.scrollTop = list.scrollHeight;281}282 283async function resetEnv() {284 stopAuto();285 history = []; stepNum = 0; totalReward = 0;286 document.getElementById('historyList').innerHTML = '<p style="color:#555; font-size:12px; text-align:center; padding:20px">No steps yet</p>';287 document.getElementById('totalReward').textContent = 'β';288 document.getElementById('stepCount').textContent = '0';289 document.getElementById('rewardBar').style.width = '0%';290 document.getElementById('log').innerHTML = '';291 292 const taskName = document.getElementById('taskSelect').value;293 const body = taskName ? JSON.stringify({task_name: taskName}) : JSON.stringify({});294 295 log('π Resetting environment...', 'info');296 try {297 const res = await fetch('/reset', {298 method: 'POST',299 headers: {'Content-Type':'application/json'},300 body: body301 });302 const data = await res.json();303 const obs = data.observation || data;304 currentTask = obs.task || '';305 306 // Task badge307 const diff = obs.difficulty || 'easy';308 const badge = document.getElementById('taskBadge');309 badge.textContent = (diff === 'easy' ? 'π’' : diff === 'medium' ? 'π‘' : 'π΄') + ' ' + (obs.task || 'β');310 badge.className = 'task-badge ' + diff;311 document.getElementById('taskObjective').textContent = obs.objective || '';312 313 renderDataset(obs);314 updatePipeline();315 log(`β
Reset done! Task: ${obs.task} | Difficulty: ${obs.difficulty}`, 'success');316 } catch(e) {317 log('β Reset failed: ' + e, 'error');318 }319}320 321async function takeStep(autoAction) {322 const action = autoAction || document.getElementById('actionSelect').value;323 document.getElementById('spinner').style.display = 'inline';324 try {325 const res = await fetch('/step', {326 method: 'POST',327 headers: {'Content-Type':'application/json'},328 body: JSON.stringify({action: {action_type: action}})329 });330 const data = await res.json();331 const obs = data.observation || data;332 const reward = data.reward ?? obs.reward ?? 0;333 const done = data.done ?? obs.done ?? false;334 335 // Detect penalty (negative or small reward with wrong order)336 const is_penalty = reward < 0.1 && action !== TASK_ACTIONS[currentTask] && !PIPELINE.includes(action);337 338 history.push({action, reward, is_penalty});339 addHistoryItem(action, reward, is_penalty, '');340 updateStats(reward, done);341 renderDataset(obs);342 updatePipeline();343 344 const icon = done ? 'π' : (reward >= 0.5 ? 'β
' : 'β οΈ');345 log(`${icon} Step ${stepNum}: ${action} β reward=${reward.toFixed(4)} done=${done}`, reward < 0.1 ? 'warn' : 'success');346 347 if (done) {348 log(`π Episode complete! Total reward: ${totalReward.toFixed(4)}`, 'success');349 stopAuto();350 }351 } catch(e) {352 log('β Step failed: ' + e, 'error');353 }354 document.getElementById('spinner').style.display = 'none';355}356 357function getNextAction() {358 const completed = getCompleted();359 const nextPipe = PIPELINE.find(s => !completed.includes(s));360 if (nextPipe) return nextPipe;361 return TASK_ACTIONS[currentTask] || 'missing';362}363 364function autoPlay() {365 if (autoTimer) return;366 log('β‘ Auto-play started...', 'info');367 autoTimer = setInterval(() => takeStep(getNextAction()), 1200);368}369 370function stopAuto() {371 if (autoTimer) { clearInterval(autoTimer); autoTimer = null; log('βΉ Stopped.', 'warn'); }372}373 374window.onload = () => resetEnv();375</script>376</body>377</html>"""378 379 380@app.get("/dashboard", response_class=HTMLResponse)381def dashboard():382 return HTMLResponse(content=DASHBOARD_HTML)383 384 385def main(host: str = "0.0.0.0", port: int = 8000):386 import uvicorn387 uvicorn.run(app, host=host, port=port)388 389 390if __name__ == "__main__":391 import argparse392 parser = argparse.ArgumentParser()393 parser.add_argument("--port", type=int, default=8000)394 args = parser.parse_args()395 main(port=args.port)