captainspock commited on
Commit
5279796
·
verified ·
1 Parent(s): 7565a00

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +80 -2
index.html CHANGED
@@ -212,6 +212,27 @@
212
  </div>
213
  </div>
214
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
215
  <!-- Action Bar -->
216
  <div class="p-4 bg-gray-100 border-t-2 border-black flex gap-3 shrink-0">
217
  <button id="btn-play"
@@ -640,6 +661,10 @@
640
  currentBall: null,
641
  progress: { unlockedIndex: 0, stars: {} },
642
  winCondition: null,
 
 
 
 
643
  };
644
  function loadProgress() {
645
  const saved = localStorage.getItem(STORAGE_KEY);
@@ -1062,11 +1087,21 @@
1062
  const TOOL_SCHEMA = [{"type": "function", "function": {"name": "add", "description": "Add a shape into the game scene.", "parameters": {"type": "object", "properties": {"shape": {"type": "string", "enum": ["circle", "square", "triangle", "star", "rectangle", "line", "ellipse"], "description": "The kind shape to add. Required."}, "location": {"type": "string", "description": "The [x, y] coordinates where the shape will be placed or a descriptive string. Required."}, "size": {"type": "number", "description": "The size of the object (between 0.1 and 10.0). Default is 1.0."}, "rotation": {"type": "integer", "description": "The initial clockwise rotation of the object in degrees (0-360). Default is 0."}, "friction": {"type": "number", "description": "The friction of the object (between 0.0 and 1.0). Default is 0.0."}, "restitution": {"type": "number", "description": "The bounciness of the object (between 0.0 and 1.0). Default is 0.0."}, "mass": {"type": "number", "description": "The mass of the object (between 1.0 and 10.0). Default is 1.0."}, "delay": {"type": "number", "description": "The time in seconds to wait before the object appears in the scene. Default is 0.0."}, "static": {"type": "boolean", "description": "Whether the object is static (immovable) or dynamic. Default is False."}, "velocity": {"type": "array", "items": {"type": "number"}, "description": "The initial [vx, vy] velocity vector of the object (values between -10.0 and 10.0). Default is [0.0, 0.0]."}, "color": {"type": "string", "description": "The color of the object as a string or hex code (e.g., \"red\", \"blue\", \"#FF00FF\"). Default is \"red\"."}}, "required": ["shape", "location"]}, "return": {"type": "string", "description": "A unique identifier for the added shape."}}}];
1063
  async function initModel() {
1064
  try {
 
 
 
1065
  tokenizer = await AutoTokenizer.from_pretrained(MODEL_ID);
1066
  model = await AutoModelForCausalLM.from_pretrained(MODEL_ID, {
1067
  device: "webgpu",
1068
  dtype: "q4",
1069
  });
 
 
 
 
 
 
 
1070
  document.getElementById("loading-overlay").classList.add("hidden");
1071
  } catch (e) {
1072
  console.error(e);
@@ -1087,6 +1122,8 @@
1087
  try {
1088
  const lines = input.split('\n').map(l => l.trim()).filter(l => l.length > 0 && !l.startsWith("//"));
1089
  for (const line of lines) {
 
 
1090
  // 2. Prepare Messages
1091
  const messages = [
1092
  { role: "developer", content: systemPrompt },
@@ -1099,8 +1136,49 @@
1099
  add_generation_prompt: true,
1100
  return_dict: true,
1101
  });
1102
- // 4. Generate
1103
- const output = await model.generate({ ...inputs, max_new_tokens: 128, do_sample: false });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1104
  const decoded = tokenizer.decode(output.slice(0, [inputs.input_ids.dims[1], null]), { skip_special_tokens: false });
1105
  // 5. Parse Output
1106
  // Format: <start_function_call>call:add{...}<end_function_call>
 
212
  </div>
213
  </div>
214
 
215
+ <!-- Performance Metrics -->
216
+ <div class="p-3 bg-gray-50 border-2 border-black shadow-neo-sm">
217
+ <div class="text-xs font-bold mb-2 flex items-center gap-2">
218
+ <i class="fas fa-tachometer-alt"></i> PERFORMANCE
219
+ </div>
220
+ <div class="grid grid-cols-3 gap-2 text-[10px] font-mono">
221
+ <div class="bg-white p-1 border border-black">
222
+ <div class="text-gray-500 uppercase">Model Load</div>
223
+ <div class="font-bold" id="metric-compilation">-</div>
224
+ </div>
225
+ <div class="bg-white p-1 border border-black">
226
+ <div class="text-gray-500 uppercase">TTFT</div>
227
+ <div class="font-bold" id="metric-ttft">-</div>
228
+ </div>
229
+ <div class="bg-white p-1 border border-black">
230
+ <div class="text-gray-500 uppercase">TPS</div>
231
+ <div class="font-bold" id="metric-tps">-</div>
232
+ </div>
233
+ </div>
234
+ </div>
235
+
236
  <!-- Action Bar -->
237
  <div class="p-4 bg-gray-100 border-t-2 border-black flex gap-3 shrink-0">
238
  <button id="btn-play"
 
661
  currentBall: null,
662
  progress: { unlockedIndex: 0, stars: {} },
663
  winCondition: null,
664
+ // Performance metrics
665
+ modelCompilationTime: 0,
666
+ lastTTFT: 0,
667
+ lastTPS: 0,
668
  };
669
  function loadProgress() {
670
  const saved = localStorage.getItem(STORAGE_KEY);
 
1087
  const TOOL_SCHEMA = [{"type": "function", "function": {"name": "add", "description": "Add a shape into the game scene.", "parameters": {"type": "object", "properties": {"shape": {"type": "string", "enum": ["circle", "square", "triangle", "star", "rectangle", "line", "ellipse"], "description": "The kind shape to add. Required."}, "location": {"type": "string", "description": "The [x, y] coordinates where the shape will be placed or a descriptive string. Required."}, "size": {"type": "number", "description": "The size of the object (between 0.1 and 10.0). Default is 1.0."}, "rotation": {"type": "integer", "description": "The initial clockwise rotation of the object in degrees (0-360). Default is 0."}, "friction": {"type": "number", "description": "The friction of the object (between 0.0 and 1.0). Default is 0.0."}, "restitution": {"type": "number", "description": "The bounciness of the object (between 0.0 and 1.0). Default is 0.0."}, "mass": {"type": "number", "description": "The mass of the object (between 1.0 and 10.0). Default is 1.0."}, "delay": {"type": "number", "description": "The time in seconds to wait before the object appears in the scene. Default is 0.0."}, "static": {"type": "boolean", "description": "Whether the object is static (immovable) or dynamic. Default is False."}, "velocity": {"type": "array", "items": {"type": "number"}, "description": "The initial [vx, vy] velocity vector of the object (values between -10.0 and 10.0). Default is [0.0, 0.0]."}, "color": {"type": "string", "description": "The color of the object as a string or hex code (e.g., \"red\", \"blue\", \"#FF00FF\"). Default is \"red\"."}}, "required": ["shape", "location"]}, "return": {"type": "string", "description": "A unique identifier for the added shape."}}}];
1088
  async function initModel() {
1089
  try {
1090
+ const compilationStart = performance.now();
1091
+ console.log("⏱️ Starting model compilation...");
1092
+
1093
  tokenizer = await AutoTokenizer.from_pretrained(MODEL_ID);
1094
  model = await AutoModelForCausalLM.from_pretrained(MODEL_ID, {
1095
  device: "webgpu",
1096
  dtype: "q4",
1097
  });
1098
+
1099
+ const compilationEnd = performance.now();
1100
+ STATE.modelCompilationTime = compilationEnd - compilationStart;
1101
+ console.log(`✅ Model compiled in ${STATE.modelCompilationTime.toFixed(2)}ms (${(STATE.modelCompilationTime / 1000).toFixed(2)}s)`);
1102
+
1103
+ // Update UI
1104
+ document.getElementById("metric-compilation").innerText = `${(STATE.modelCompilationTime / 1000).toFixed(2)}s`;
1105
  document.getElementById("loading-overlay").classList.add("hidden");
1106
  } catch (e) {
1107
  console.error(e);
 
1122
  try {
1123
  const lines = input.split('\n').map(l => l.trim()).filter(l => l.length > 0 && !l.startsWith("//"));
1124
  for (const line of lines) {
1125
+ console.log(`\n🎯 Processing command: "${line}"`);
1126
+
1127
  // 2. Prepare Messages
1128
  const messages = [
1129
  { role: "developer", content: systemPrompt },
 
1136
  add_generation_prompt: true,
1137
  return_dict: true,
1138
  });
1139
+
1140
+ // 4. Generate with performance tracking
1141
+ const generationStart = performance.now();
1142
+ let ttftRecorded = false;
1143
+ let ttft = 0;
1144
+ let firstTokenTime = 0;
1145
+
1146
+ const output = await model.generate({
1147
+ ...inputs,
1148
+ max_new_tokens: 128,
1149
+ do_sample: false,
1150
+ callback_function: (tokens) => {
1151
+ // Record TTFT on first token
1152
+ if (!ttftRecorded && tokens.length > 0) {
1153
+ firstTokenTime = performance.now();
1154
+ ttft = firstTokenTime - generationStart;
1155
+ ttftRecorded = true;
1156
+ console.log(`⚡ Time to First Token (TTFT): ${ttft.toFixed(2)}ms`);
1157
+ }
1158
+ }
1159
+ });
1160
+
1161
+ const generationEnd = performance.now();
1162
+ const totalTime = generationEnd - generationStart;
1163
+ const inputTokenCount = inputs.input_ids.dims[1];
1164
+ const outputTokenCount = output.length - inputTokenCount;
1165
+ const tps = outputTokenCount / (totalTime / 1000);
1166
+
1167
+ // Store metrics
1168
+ STATE.lastTTFT = ttft;
1169
+ STATE.lastTPS = tps;
1170
+
1171
+ // Log performance
1172
+ console.log(`📊 Performance Metrics:`);
1173
+ console.log(` - Total generation time: ${totalTime.toFixed(2)}ms`);
1174
+ console.log(` - Input tokens: ${inputTokenCount}`);
1175
+ console.log(` - Output tokens: ${outputTokenCount}`);
1176
+ console.log(` - Tokens Per Second (TPS): ${tps.toFixed(2)} tok/s`);
1177
+
1178
+ // Update UI
1179
+ document.getElementById("metric-ttft").innerText = `${ttft.toFixed(0)}ms`;
1180
+ document.getElementById("metric-tps").innerText = `${tps.toFixed(1)} t/s`;
1181
+
1182
  const decoded = tokenizer.decode(output.slice(0, [inputs.input_ids.dims[1], null]), { skip_special_tokens: false });
1183
  // 5. Parse Output
1184
  // Format: <start_function_call>call:add{...}<end_function_call>