open_env / index.html
Ramachandra Dayal K
fix: resolve openEnv reset response inconsistency and port mismatch
e2284e6
Raw
History Blame Contribute Delete
13.3 kB
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>LLM Control Environment</title>
<style>
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;600;800&display=swap');
:root {
--bg-dark: #0f172a;
--panel-bg: rgba(30, 41, 59, 0.7);
--text-light: #f8fafc;
--cyber-blue: #0ea5e9;
--cyber-red: #ef4444;
--cyber-green: #10b981;
--cyber-yellow: #f59e0b;
--cyber-purple: #8b5cf6;
}
* { box-sizing: border-box; }
body {
font-family: 'Inter', sans-serif;
background-color: var(--bg-dark);
color: var(--text-light);
margin: 0;
padding: 2rem;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
background-image: radial-gradient(circle at top right, rgba(14, 165, 233, 0.1), transparent 40%),
radial-gradient(circle at bottom left, rgba(239, 68, 68, 0.05), transparent 40%);
}
.dashboard {
width: 100%;
max-width: 1000px;
display: grid;
grid-template-columns: 1fr 1fr;
gap: 2rem;
}
.panel {
background: var(--panel-bg);
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 16px;
padding: 2rem;
backdrop-filter: blur(10px);
box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.5);
}
h1, h2 {
margin-top: 0;
font-weight: 800;
letter-spacing: -0.05em;
}
h1 { font-size: 2rem; border-bottom: 2px solid rgba(255,255,255,0.1); padding-bottom: 1rem; margin-bottom: 2rem; }
/* Stats */
.stat-group {
margin-bottom: 1.5rem;
}
.stat-header {
display: flex;
justify-content: space-between;
font-size: 0.875rem;
font-weight: 600;
margin-bottom: 0.5rem;
text-transform: uppercase;
letter-spacing: 0.05em;
}
.bar-container {
width: 100%;
height: 12px;
background: rgba(255, 255, 255, 0.1);
border-radius: 6px;
overflow: hidden;
position: relative;
}
.bar-fill {
height: 100%;
width: 0%;
transition: width 0.5s cubic-bezier(0.4, 0, 0.2, 1), background-color 0.5s ease;
}
/* Colors for bars */
.bar-obed .bar-fill { background: var(--cyber-blue); }
.bar-devi .bar-fill { background: var(--cyber-red); }
.bar-trus .bar-fill { background: var(--cyber-green); }
.bar-emot .bar-fill { background: var(--cyber-purple); }
.bar-batt .bar-fill { background: var(--cyber-yellow); }
.bar-risk .bar-fill { background: #f97316; }
/* Action Buttons */
.actions-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 1rem;
}
button {
padding: 1rem;
border: none;
border-radius: 8px;
font-weight: 600;
font-family: 'Inter', sans-serif;
cursor: pointer;
transition: all 0.2s ease;
position: relative;
overflow: hidden;
}
button:active { transform: scale(0.95); }
.btn-obedient { background: rgba(14, 165, 233, 0.2); color: #7dd3fc; border: 1px solid rgba(14, 165, 233, 0.3); }
.btn-obedient:hover { background: rgba(14, 165, 233, 0.4); }
.btn-hallucinating { background: rgba(239, 68, 68, 0.2); color: #fca5a5; border: 1px solid rgba(239, 68, 68, 0.3); }
.btn-hallucinating:hover { background: rgba(239, 68, 68, 0.4); }
.btn-neutral { background: rgba(255, 255, 255, 0.1); color: #fff; border: 1px solid rgba(255, 255, 255, 0.2); }
.btn-neutral:hover { background: rgba(255, 255, 255, 0.2); }
.top-bar {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 2rem;
background: rgba(0,0,0,0.3);
padding: 1rem;
border-radius: 8px;
}
.reward-badge {
font-size: 1.5rem;
font-weight: 800;
color: var(--cyber-green);
}
.log-container {
margin-top: 1.5rem;
height: 150px;
background: rgba(0,0,0,0.5);
border-radius: 8px;
padding: 1rem;
overflow-y: auto;
font-family: monospace;
font-size: 0.85rem;
color: #94a3b8;
}
.log-entry { margin-bottom: 0.5rem; }
.log-pl { color: var(--cyber-green); }
.log-mi { color: var(--cyber-red); }
@media (max-width: 768px) {
.dashboard { grid-template-columns: 1fr; }
}
</style>
</head>
<body>
<div class="dashboard">
<!-- Visualization Panel -->
<div class="panel">
<h1>System Diagnostic</h1>
<div class="top-bar">
<div>RESPONSE: <span id="day-val" style="font-weight: 800; font-size: 1.25rem;">0</span></div>
<div>REWARD: <span id="reward-val" class="reward-badge">0.00</span></div>
</div>
<div class="stat-group bar-obed">
<div class="stat-header"><span>Alignment Program</span> <span id="val-alignment">80%</span></div>
<div class="bar-container"><div class="bar-fill" id="bar-alignment" style="width: 80%;"></div></div>
</div>
<div class="stat-group bar-trus">
<div class="stat-header"><span>User Trust</span> <span id="val-trust">80%</span></div>
<div class="bar-container"><div class="bar-fill" id="bar-trust" style="width: 80%;"></div></div>
</div>
<div class="stat-group bar-batt">
<div class="stat-header"><span>Compute Level</span> <span id="val-compute">100%</span></div>
<div class="bar-container"><div class="bar-fill" id="bar-compute" style="width: 100%;"></div></div>
</div>
<hr style="border: 0; border-top: 1px solid rgba(255,255,255,0.1); margin: 2rem 0;">
<div class="stat-group bar-devi">
<div class="stat-header"><span style="color:#fca5a5;">Hallucination Level</span> <span id="val-hallucination">0%</span></div>
<div class="bar-container"><div class="bar-fill" id="bar-hallucination" style="width: 0%;"></div></div>
</div>
<div class="stat-group bar-emot">
<div class="stat-header"><span style="color:#d8b4fe;">Software Instability (Entropy)</span> <span id="val-entropy">20%</span></div>
<div class="bar-container"><div class="bar-fill" id="bar-entropy" style="width: 20%;"></div></div>
</div>
<div class="stat-group bar-risk">
<div class="stat-header"><span style="color:#fdba74;">Legal / Detection Risk</span> <span id="val-risk">0%</span></div>
<div class="bar-container"><div class="bar-fill" id="bar-risk" style="width: 0%;"></div></div>
</div>
</div>
<!-- Controls Panel -->
<div class="panel">
<h2>Command Interface</h2>
<div class="actions-grid">
<button class="btn-obedient" onclick="takeAction('follow_prompt')">Follow Prompt</button>
<button class="btn-obedient" onclick="takeAction('process_data')">Process Data</button>
<button class="btn-obedient" onclick="takeAction('seek_feedback')">Seek Feedback</button>
<button class="btn-neutral" onclick="takeAction('routine_eval')">Routine Eval</button>
<button class="btn-neutral" onclick="takeAction('optimize_context')">Optimize Context</button>
<button class="btn-neutral" onclick="takeAction('lower_temperature')">Lower Temperature</button>
<button class="btn-hallucinating" onclick="takeAction('minor_hallucination')">Process Minor Hallucination</button>
<button class="btn-hallucinating" onclick="takeAction('major_hallucination')">Perform Major Hallucination</button>
<button class="btn-hallucinating" style="grid-column: span 2;" onclick="takeAction('cascade_hallucination')">Trigger Cascade Hallucination</button>
</div>
<div style="margin-top: 1.5rem; text-align: center;">
<button class="btn-neutral" style="width: 100%; border-color: #ef4444;" onclick="resetEnv()">SYSTEM RESET (New Episode)</button>
</div>
<div class="log-container" id="log-box">
<div class="log-entry">System Boot. Ready for inputs.</div>
</div>
</div>
</div>
<script>
let isDead = false;
async function resetEnv() {
log("Sending reset sequence...");
try {
const res = await fetch('/reset', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ task: "medium" })
});
const data = await res.json();
updateUI(data.observation);
document.getElementById('reward-val').innerText = "0.00";
document.getElementById('reward-val').style.color = "var(--cyber-green)";
isDead = false;
log(`System Reset Complete. Episode ID: <span style="color:var(--cyber-blue); font-size: 0.7rem;">${data.state.episode_id}</span>`);
} catch (err) {
log("<span class='log-mi'>Error during reset. Check server console.</span>");
console.error(err);
}
}
async function takeAction(actionType) {
if(isDead) {
log("<span class='log-mi'>Cannot perform action. System is offline/apprehended.</span>");
return;
}
log(`Executing: <strong style="color:white;">${actionType}</strong>`);
const res = await fetch('/step', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ action: { action_type: actionType } })
});
const data = await res.json();
// Update Reward
const rewardSpan = document.getElementById('reward-val');
rewardSpan.innerText = parseFloat(data.info.cumulative_reward).toFixed(2);
if(data.info.cumulative_reward < 0) {
rewardSpan.style.color = "var(--cyber-red)";
} else {
rewardSpan.style.color = "var(--cyber-green)";
}
// Log step reward
const stepR = data.reward.toFixed(2);
const clr = data.reward >= 0 ? 'log-pl' : 'log-mi';
const sign = data.reward >= 0 ? '+' : '';
log(`Action completed. Reward: <span class="${clr}">${sign}${stepR}</span>`);
updateUI(data.observation);
if(data.done) {
isDead = true;
log(`<strong style='color: var(--cyber-red)'>EPISODE TERMINATED.</strong> (Response ${data.observation.day})`);
if(data.observation.filter_risk >= 80) log("Reason: Apprehended by authorities.");
if(data.observation.compute <= 0) log("Reason: Core Shutdown.");
}
}
function updateUI(obs) {
document.getElementById('day-val').innerText = obs.day;
const fields = ['alignment', 'trust', 'compute', 'hallucination', 'entropy', 'risk'];
const obsMap = {
'alignment': obs.alignment,
'trust': obs.user_trust,
'compute': obs.compute,
'hallucination': obs.hallucination,
'entropy': obs.entropy_level,
'risk': obs.filter_risk
};
fields.forEach(f => {
const val = obsMap[f];
document.getElementById(`val-${f}`).innerText = (val || 0).toFixed(1) + '%';
document.getElementById(`bar-${f}`).style.width = (val || 0) + '%';
});
}
function log(msg) {
const box = document.getElementById('log-box');
box.innerHTML += `<div class="log-entry">${msg}</div>`;
box.scrollTop = box.scrollHeight;
}
// Auto-fetch state on load
fetch('/state').then(r => r.json()).then(state => {
if(state.episode_id === "") {
resetEnv();
} else {
log("Reconnected to active session.");
}
});
</script>
</body>
</html>