namish10 commited on
Commit
81e5178
·
verified ·
1 Parent(s): b37e8f2

Upload index.html with huggingface_hub

Browse files
Files changed (1) hide show
  1. index.html +146 -140
index.html CHANGED
@@ -19,32 +19,33 @@
19
  .result { background: #1a1a2e; color: #0f0; padding: 20px; border-radius: 10px; margin: 15px 0; font-family: 'Courier New', monospace; font-size: 14px; line-height: 1.6; max-height: 400px; overflow-y: auto; white-space: pre-wrap; word-wrap: break-word; }
20
  .metrics { display: flex; gap: 10px; flex-wrap: wrap; margin: 15px 0; }
21
  .metric { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 10px 20px; border-radius: 25px; font-weight: bold; }
22
- .score { font-size: 48px; font-weight: bold; text-align: center; }
23
- .pass { color: #10b981; }
24
- .fail { color: #ef4444; }
 
25
  .agent-info { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 15px; margin: 15px 0; }
26
  .agent-card { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 15px; border-radius: 10px; text-align: center; }
27
  .agent-card h3 { margin: 0 0 5px 0; font-size: 14px; }
28
  .agent-card p { margin: 0; font-size: 24px; font-weight: bold; }
29
- .status { text-align: center; padding: 10px; border-radius: 10px; margin: 10px 0; font-weight: bold; }
30
- .status.ready { background: #d4edda; color: #155724; }
31
- .status.error { background: #f8d7da; color: #721c24; }
32
  </style>
33
  </head>
34
  <body>
35
  <div class="container">
36
  <h1>ContextFlow OpenEnv</h1>
37
- <p class="subtitle">Learning Confusion Prediction Environment</p>
38
 
39
- <div id="status" class="status ready">Click "Reset Environment" to start</div>
40
 
41
  <div class="card">
42
  <h2>Environment Setup</h2>
43
  <div class="controls">
44
  <select id="difficulty">
45
- <option value="easy">Easy (50 steps)</option>
46
- <option value="medium" selected>Medium (75 steps)</option>
47
- <option value="hard">Hard (100 steps)</option>
48
  </select>
49
  <button onclick="reset()">Reset Environment</button>
50
  </div>
@@ -76,7 +77,7 @@
76
 
77
  <div class="card">
78
  <h2>Results</h2>
79
- <div id="result" class="result">Waiting for environment...</div>
80
  </div>
81
 
82
  <div class="card">
@@ -85,32 +86,34 @@
85
  </div>
86
 
87
  <div class="card">
88
- <h2>Active Agents</h2>
89
  <div class="agent-info">
90
  <div class="agent-card">
91
- <h3>RL Predictor</h3>
92
  <p>Q-Learning</p>
93
  </div>
94
  <div class="agent-card">
95
- <h3>Knowledge Graph</h3>
96
- <p>Prerequisites</p>
97
  </div>
98
  <div class="agent-card">
99
- <h3>Peer Learning</h3>
100
- <p>Connect Learners</p>
101
  </div>
102
  <div class="agent-card">
103
- <h3>Recall System</h3>
104
- <p>Spaced Repetition</p>
105
  </div>
106
  </div>
107
  </div>
108
  </div>
109
 
110
  <script>
 
111
  let episodeId = null;
112
  let stepCount = 0;
113
  let episodeReward = 0;
 
114
 
115
  const confusionSlider = document.getElementById('confusion');
116
  const confusionValue = document.getElementById('confusionValue');
@@ -123,142 +126,145 @@
123
  confusionValue.textContent = parseFloat(confusionSlider.value).toFixed(2);
124
  };
125
 
126
- const state = {
127
- step_count: 0,
128
- max_steps: 75,
129
- predictions: [],
130
- interventions: [],
131
- rewards: [],
132
- ground_truth: [],
133
- multimodal_fused: true,
134
- agent_epsilon: 1.0
135
- };
136
-
137
- function generateConfusion(step, difficulty) {
138
- const configs = {
139
- easy: { base: 0.3, noise: 0.1, spikeProb: 0.08 },
140
- medium: { base: 0.5, noise: 0.2, spikeProb: 0.12 },
141
- hard: { base: 0.6, noise: 0.3, spikeProb: 0.15 }
142
- };
143
- const cfg = configs[difficulty] || configs.medium;
144
- let confusion = cfg.base + Math.sin(step * 0.1) * 0.2;
145
- confusion += (Math.random() - 0.5) * 2 * cfg.noise;
146
- if (Math.random() < cfg.spikeProb) confusion += 0.3;
147
- return Math.max(0, Math.min(1, confusion));
148
  }
149
 
150
- function reset() {
151
- const difficulty = document.getElementById('difficulty').value;
152
- state.step_count = 0;
153
- state.max_steps = difficulty === 'easy' ? 50 : difficulty === 'hard' ? 100 : 75;
154
- state.predictions = [];
155
- state.interventions = [];
156
- state.rewards = [];
157
- state.ground_truth = [];
158
- state.agent_epsilon = 1.0;
159
- state.multimodal_fused = true;
160
- stepCount = 0;
161
- episodeReward = 0;
162
- episodeId = 'ep_' + Date.now();
163
-
164
- const gt = generateConfusion(0, difficulty);
165
- state.ground_truth.push(gt);
166
-
167
- statusEl.className = 'status ready';
168
- statusEl.textContent = `Episode: ${episodeId.slice(0,12)}... | Difficulty: ${difficulty} | Steps: 0/${state.max_steps}`;
169
 
170
- resultEl.innerHTML = JSON.stringify({
171
- "Episode Started": {
172
- episode_id: episodeId,
173
- difficulty: difficulty,
174
- multimodal_fused: state.multimodal_fused,
175
- available_interventions: ["hint", "simplify", "breakdown", "example", "scaffold", "peer_connect", "break", "encourage"],
176
- prediction_window: difficulty === 'easy' ? 3 : difficulty === 'hard' ? 7 : 5,
177
- ground_truth_confusion: gt.toFixed(3),
178
- agent_state: { epsilon: state.agent_epsilon.toFixed(3) }
179
- }
180
- }, null, 2);
181
-
182
- metricsEl.innerHTML = '';
183
- stepBtn.disabled = false;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
184
  }
185
 
186
- function step() {
 
 
187
  const predicted = parseFloat(confusionSlider.value);
188
  const intervention = document.getElementById('intervention').value;
189
 
190
- state.step_count++;
191
- stepCount++;
192
-
193
- const gt = state.ground_truth[state.ground_truth.length - 1];
194
- const error = Math.abs(predicted - gt);
195
- let reward = (1 - error) * 0.4;
196
-
197
- if (state.ground_truth.length > 1) {
198
- const prev = state.ground_truth[state.ground_truth.length - 2];
199
- if (gt > prev && predicted > prev) reward += 0.2;
200
- }
201
-
202
- if (intervention) {
203
- state.interventions.push({ step: stepCount, type: intervention, intensity: 0.7 });
204
- if (gt > 0.5) reward += 0.3;
205
- }
206
-
207
- episodeReward += reward;
208
- state.rewards.push(reward);
209
- state.predictions.push(predicted);
210
-
211
- const nextGt = generateConfusion(state.step_count, document.getElementById('difficulty').value);
212
- state.ground_truth.push(nextGt);
213
- state.agent_epsilon = Math.max(0.01, state.agent_epsilon * 0.995);
214
-
215
- const done = stepCount >= state.max_steps;
216
 
217
- if (done) {
218
- const preds = state.predictions;
219
- const gts = state.ground_truth.slice(0, preds.length);
220
- const mae = preds.reduce((sum, p, i) => sum + Math.abs(p - gts[i]), 0) / preds.length;
221
- let spikes = 0, detected = 0;
222
- for (let i = 1; i < gts.length; i++) {
223
- if (gts[i] > 0.6) { spikes++; if (preds[i] > 0.6) detected++; }
 
 
 
 
 
 
 
 
 
 
 
 
 
224
  }
225
- const edr = spikes > 0 ? detected / spikes : 0;
226
- const ie = state.interventions.length > 0 ? state.interventions.length / preds.length : 0;
227
- const score = (1 - mae) * 0.4 + edr * 0.3 + ie * 0.3;
228
- const threshold = document.getElementById('difficulty').value === 'easy' ? 0.5 : document.getElementById('difficulty').value === 'hard' ? 0.7 : 0.6;
229
- const passed = score >= threshold;
230
 
231
- resultEl.innerHTML = JSON.stringify({
232
- "Episode Complete": {
233
- step: stepCount,
234
- total_reward: episodeReward.toFixed(3),
235
- grader_result: {
236
- score: score.toFixed(3),
237
- passed: passed,
238
- feedback: `MAE: ${mae.toFixed(3)} | Early Detection: ${(edr*100).toFixed(0)}% | Intervention Effect: ${(ie*100).toFixed(0)}%`,
239
- metrics: { mae: mae.toFixed(3), early_detection_rate: edr.toFixed(3), intervention_effectiveness: ie.toFixed(3), total_predictions: preds.length, total_interventions: state.interventions.length }
 
 
 
 
 
240
  }
241
- }
242
- }, null, 2);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
243
 
244
- metricsEl.innerHTML = `<div class="metric" style="font-size:36px;">${passed ? 'PASSED' : 'FAILED'}</div><div class="metric">Score: ${score.toFixed(3)}</div><div class="metric">MAE: ${mae.toFixed(3)}</div><div class="metric">E.D.R: ${(edr*100).toFixed(0)}%</div><div class="metric">Reward: ${episodeReward.toFixed(2)}</div>`;
245
- stepBtn.disabled = true;
246
- statusEl.textContent = `${passed ? 'PASSED' : 'FAILED'} - Click Reset to try again`;
247
- } else {
248
- resultEl.innerHTML = JSON.stringify({
249
- step: stepCount,
250
- reward: reward.toFixed(3),
251
- ground_truth: gt.toFixed(3),
252
- prediction_error: error.toFixed(3),
253
- prediction: predicted.toFixed(2),
254
- intervention: intervention || null,
255
- agent_state: { epsilon: state.agent_epsilon.toFixed(3) }
256
- }, null, 2);
257
- statusEl.textContent = `Episode: ${episodeId.slice(0,12)}... | Steps: ${stepCount}/${state.max_steps} | Reward: ${episodeReward.toFixed(2)}`;
258
  }
259
  }
260
 
261
- window.onload = reset;
262
  </script>
263
  </body>
264
  </html>
 
19
  .result { background: #1a1a2e; color: #0f0; padding: 20px; border-radius: 10px; margin: 15px 0; font-family: 'Courier New', monospace; font-size: 14px; line-height: 1.6; max-height: 400px; overflow-y: auto; white-space: pre-wrap; word-wrap: break-word; }
20
  .metrics { display: flex; gap: 10px; flex-wrap: wrap; margin: 15px 0; }
21
  .metric { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 10px 20px; border-radius: 25px; font-weight: bold; }
22
+ .status { text-align: center; padding: 10px; border-radius: 10px; margin: 10px 0; font-weight: bold; }
23
+ .status.ready { background: #d4edda; color: #155724; }
24
+ .status.error { background: #f8d7da; color: #721c24; }
25
+ .status.loading { background: #fff3cd; color: #856404; }
26
  .agent-info { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 15px; margin: 15px 0; }
27
  .agent-card { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 15px; border-radius: 10px; text-align: center; }
28
  .agent-card h3 { margin: 0 0 5px 0; font-size: 14px; }
29
  .agent-card p { margin: 0; font-size: 24px; font-weight: bold; }
30
+ .loading { text-align: center; padding: 50px; }
31
+ .spinner { border: 4px solid #f3f3f3; border-top: 4px solid #667eea; border-radius: 50%; width: 50px; height: 50px; animation: spin 1s linear infinite; margin: 0 auto; }
32
+ @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } }
33
  </style>
34
  </head>
35
  <body>
36
  <div class="container">
37
  <h1>ContextFlow OpenEnv</h1>
38
+ <p class="subtitle">Learning Confusion Prediction with RL Agents</p>
39
 
40
+ <div id="status" class="status loading">Connecting to ContextFlow API...</div>
41
 
42
  <div class="card">
43
  <h2>Environment Setup</h2>
44
  <div class="controls">
45
  <select id="difficulty">
46
+ <option value="easy">Easy (50 steps, threshold: 0.5)</option>
47
+ <option value="medium" selected>Medium (75 steps, threshold: 0.6)</option>
48
+ <option value="hard">Hard (100 steps, threshold: 0.7)</option>
49
  </select>
50
  <button onclick="reset()">Reset Environment</button>
51
  </div>
 
77
 
78
  <div class="card">
79
  <h2>Results</h2>
80
+ <div id="result" class="result">Click "Reset Environment" to start...</div>
81
  </div>
82
 
83
  <div class="card">
 
86
  </div>
87
 
88
  <div class="card">
89
+ <h2>Active ContextFlow Agents</h2>
90
  <div class="agent-info">
91
  <div class="agent-card">
92
+ <h3>RL Doubt Predictor</h3>
93
  <p>Q-Learning</p>
94
  </div>
95
  <div class="agent-card">
96
+ <h3>Behavioral Analyzer</h3>
97
+ <p>Signal Fusion</p>
98
  </div>
99
  <div class="agent-card">
100
+ <h3>Knowledge Graph</h3>
101
+ <p>Prerequisites</p>
102
  </div>
103
  <div class="agent-card">
104
+ <h3>Gesture Recognizer</h3>
105
+ <p>Hand Tracking</p>
106
  </div>
107
  </div>
108
  </div>
109
  </div>
110
 
111
  <script>
112
+ const API_BASE = 'https://namish10-contextflow-env-api.hf.space';
113
  let episodeId = null;
114
  let stepCount = 0;
115
  let episodeReward = 0;
116
+ let currentDifficulty = 'medium';
117
 
118
  const confusionSlider = document.getElementById('confusion');
119
  const confusionValue = document.getElementById('confusionValue');
 
126
  confusionValue.textContent = parseFloat(confusionSlider.value).toFixed(2);
127
  };
128
 
129
+ async function checkAPI() {
130
+ try {
131
+ const resp = await fetch(API_BASE + '/health');
132
+ const data = await resp.json();
133
+ statusEl.className = 'status ready';
134
+ statusEl.textContent = 'Connected to ContextFlow API - ' + data.status;
135
+ } catch (e) {
136
+ statusEl.className = 'status error';
137
+ statusEl.textContent = 'API Connection Failed: ' + e.message;
138
+ }
 
 
 
 
 
 
 
 
 
 
 
 
139
  }
140
 
141
+ async function reset() {
142
+ currentDifficulty = document.getElementById('difficulty').value;
143
+ statusEl.className = 'status loading';
144
+ statusEl.textContent = 'Resetting environment...';
145
+ stepBtn.disabled = true;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
146
 
147
+ try {
148
+ const resp = await fetch(API_BASE + '/reset?difficulty=' + currentDifficulty, {
149
+ method: 'POST',
150
+ headers: { 'Content-Type': 'application/json' }
151
+ });
152
+
153
+ const data = await resp.json();
154
+ episodeId = data.episode_id;
155
+ stepCount = 0;
156
+ episodeReward = 0;
157
+
158
+ const obs = data.observation;
159
+ statusEl.className = 'status ready';
160
+ statusEl.textContent = `Episode: ${episodeId.substring(0, 12)}... | ${obs.learning_context.difficulty.toUpperCase()} | Steps: 0/${currentDifficulty === 'easy' ? 50 : currentDifficulty === 'hard' ? 100 : 75}`;
161
+
162
+ resultEl.innerHTML = JSON.stringify({
163
+ "Episode Started": {
164
+ episode_id: episodeId,
165
+ difficulty: obs.learning_context.difficulty,
166
+ topic: obs.learning_context.topic,
167
+ multimodal_fused: obs.multimodal_fused,
168
+ prediction_window: obs.prediction_window,
169
+ available_interventions: obs.available_interventions,
170
+ agent_state: { epsilon: 1.0 }
171
+ }
172
+ }, null, 2);
173
+
174
+ metricsEl.innerHTML = '';
175
+ stepBtn.disabled = false;
176
+
177
+ } catch (e) {
178
+ statusEl.className = 'status error';
179
+ statusEl.textContent = 'Error: ' + e.message;
180
+ }
181
  }
182
 
183
+ async function step() {
184
+ if (!episodeId) return;
185
+
186
  const predicted = parseFloat(confusionSlider.value);
187
  const intervention = document.getElementById('intervention').value;
188
 
189
+ statusEl.className = 'status loading';
190
+ statusEl.textContent = 'Processing step...';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
191
 
192
+ try {
193
+ const resp = await fetch(API_BASE + '/step', {
194
+ method: 'POST',
195
+ headers: { 'Content-Type': 'application/json' },
196
+ body: JSON.stringify({
197
+ episode_id: episodeId,
198
+ action_type: intervention ? 'trigger_intervention' : 'predict_confusion',
199
+ predicted_confusion: predicted,
200
+ intervention_type: intervention || null,
201
+ intervention_intensity: intervention ? 0.7 : null
202
+ })
203
+ });
204
+
205
+ const data = await resp.json();
206
+ stepCount++;
207
+
208
+ if (data.error) {
209
+ statusEl.className = 'status error';
210
+ statusEl.textContent = data.error;
211
+ return;
212
  }
 
 
 
 
 
213
 
214
+ const reward = data.reward;
215
+ const obs = data.observation;
216
+ episodeReward += reward.total;
217
+
218
+ if (data.done) {
219
+ const grader = data.info.grader_result;
220
+ statusEl.className = grader.passed ? 'status ready' : 'status error';
221
+ statusEl.textContent = grader.passed ? 'EPISODE PASSED!' : 'Episode Ended';
222
+
223
+ resultEl.innerHTML = JSON.stringify({
224
+ "Episode Complete": {
225
+ total_steps: stepCount,
226
+ total_reward: episodeReward.toFixed(3),
227
+ grader_result: grader
228
  }
229
+ }, null, 2);
230
+
231
+ metricsEl.innerHTML = `
232
+ <div class="metric" style="font-size:28px;${grader.passed ? '' : 'background: linear-gradient(135deg, #ef4444 0%, #dc2626 100%);'}">${grader.passed ? 'PASSED' : 'FAILED'}</div>
233
+ <div class="metric">Score: ${grader.score.toFixed(3)}</div>
234
+ <div class="metric">MAE: ${grader.metrics.mae.toFixed(3)}</div>
235
+ <div class="metric">Early Detection: ${(grader.metrics.early_detection_rate * 100).toFixed(0)}%</div>
236
+ <div class="metric">Interventions: ${grader.metrics.total_interventions}</div>
237
+ `;
238
+
239
+ stepBtn.disabled = true;
240
+ } else {
241
+ statusEl.className = 'status ready';
242
+ statusEl.textContent = `Episode: ${episodeId.substring(0, 12)}... | Steps: ${stepCount}/${currentDifficulty === 'easy' ? 50 : currentDifficulty === 'hard' ? 100 : 75} | Reward: ${episodeReward.toFixed(2)}`;
243
+
244
+ resultEl.innerHTML = JSON.stringify({
245
+ step: stepCount,
246
+ reward: reward.total.toFixed(3),
247
+ ground_truth: reward.metadata.ground_truth.toFixed(3),
248
+ prediction_error: reward.metadata.prediction_error.toFixed(3),
249
+ prediction: predicted.toFixed(2),
250
+ intervention: intervention || null,
251
+ learner_state: obs.learner_state
252
+ }, null, 2);
253
+
254
+ metricsEl.innerHTML = `
255
+ <div class="metric">Step: ${stepCount}</div>
256
+ <div class="metric">Reward: ${reward.total.toFixed(3)}</div>
257
+ <div class="metric">Error: ${reward.metadata.prediction_error.toFixed(3)}</div>
258
+ `;
259
+ }
260
 
261
+ } catch (e) {
262
+ statusEl.className = 'status error';
263
+ statusEl.textContent = 'Error: ' + e.message;
 
 
 
 
 
 
 
 
 
 
 
264
  }
265
  }
266
 
267
+ checkAPI();
268
  </script>
269
  </body>
270
  </html>