Update index.html
Browse files- 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 |
-
|
| 1103 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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>
|