Upload 3 files
Browse files
app.js
CHANGED
|
@@ -1357,6 +1357,39 @@ async function fetchWithProgress(url, onProgress) {
|
|
| 1357 |
return new Blob(chunks);
|
| 1358 |
}
|
| 1359 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1360 |
// Initializer Flow
|
| 1361 |
async function init() {
|
| 1362 |
const loadingOverlay = document.querySelector("#loadingOverlay");
|
|
@@ -1376,11 +1409,7 @@ async function init() {
|
|
| 1376 |
|
| 1377 |
// Step 1. Load Vocabulary
|
| 1378 |
updateProgress(5, "Downloading vocabulary metadata...");
|
| 1379 |
-
const
|
| 1380 |
-
if (!vocabResponse.ok) {
|
| 1381 |
-
throw new Error(`Failed to load vocabulary json: ${vocabResponse.statusText}`);
|
| 1382 |
-
}
|
| 1383 |
-
const vocab = await vocabResponse.json();
|
| 1384 |
stoi = vocab.stoi;
|
| 1385 |
itos = Object.fromEntries(Object.entries(vocab.itos).map(([key, value]) => [Number(key), value]));
|
| 1386 |
vocabSize = vocab.vocab_size;
|
|
@@ -1388,13 +1417,13 @@ async function init() {
|
|
| 1388 |
|
| 1389 |
// Step 2. Download ONNX Model
|
| 1390 |
updateProgress(15, "Downloading AI model...");
|
| 1391 |
-
const modelBlob = await
|
| 1392 |
// Map 0-100% of download to 15-80% progress indicator
|
| 1393 |
const pct = 15 + (loaded / total) * 65;
|
| 1394 |
const loadedMB = (loaded / (1024 * 1024)).toFixed(1);
|
| 1395 |
const totalMB = (total / (1024 * 1024)).toFixed(1);
|
| 1396 |
updateProgress(pct, `Downloading AI model (${loadedMB}MB / ${totalMB}MB)...`);
|
| 1397 |
-
});
|
| 1398 |
|
| 1399 |
// Step 3. Initialize inference session
|
| 1400 |
updateProgress(82, "Initializing neural network engine...");
|
|
|
|
| 1357 |
return new Blob(chunks);
|
| 1358 |
}
|
| 1359 |
|
| 1360 |
+
const MODEL_CACHE_NAME = "nanomaestro-cache-v1";
|
| 1361 |
+
|
| 1362 |
+
// Fetch with browser Cache Storage API fallback
|
| 1363 |
+
async function fetchWithCache(url, onProgress, isJson = false) {
|
| 1364 |
+
if (!('caches' in window)) {
|
| 1365 |
+
const response = await fetch(url);
|
| 1366 |
+
if (!response.ok) throw new Error(`HTTP ${response.status} fetching ${url}`);
|
| 1367 |
+
return isJson ? response.json() : response.blob();
|
| 1368 |
+
}
|
| 1369 |
+
|
| 1370 |
+
const cache = await caches.open(MODEL_CACHE_NAME);
|
| 1371 |
+
const cachedResponse = await cache.match(url);
|
| 1372 |
+
|
| 1373 |
+
if (cachedResponse) {
|
| 1374 |
+
console.log(`Loaded from browser cache: ${url}`);
|
| 1375 |
+
if (onProgress) onProgress(1, 1);
|
| 1376 |
+
return isJson ? cachedResponse.json() : cachedResponse.blob();
|
| 1377 |
+
}
|
| 1378 |
+
|
| 1379 |
+
console.log(`Cache miss. Downloading remotely: ${url}`);
|
| 1380 |
+
if (isJson) {
|
| 1381 |
+
const response = await fetch(url);
|
| 1382 |
+
if (!response.ok) throw new Error(`HTTP ${response.status} fetching ${url}`);
|
| 1383 |
+
await cache.put(url, response.clone());
|
| 1384 |
+
return response.json();
|
| 1385 |
+
} else {
|
| 1386 |
+
const blob = await fetchWithProgress(url, onProgress);
|
| 1387 |
+
const responseToCache = new Response(blob);
|
| 1388 |
+
await cache.put(url, responseToCache);
|
| 1389 |
+
return blob;
|
| 1390 |
+
}
|
| 1391 |
+
}
|
| 1392 |
+
|
| 1393 |
// Initializer Flow
|
| 1394 |
async function init() {
|
| 1395 |
const loadingOverlay = document.querySelector("#loadingOverlay");
|
|
|
|
| 1409 |
|
| 1410 |
// Step 1. Load Vocabulary
|
| 1411 |
updateProgress(5, "Downloading vocabulary metadata...");
|
| 1412 |
+
const vocab = await fetchWithCache("https://huggingface.co/utkucoban/NanoMaestro-Realtime/resolve/main/NanoMaestro-Realtime/NM2.4%20ONNX%20int8/vocab.json", null, true);
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1413 |
stoi = vocab.stoi;
|
| 1414 |
itos = Object.fromEntries(Object.entries(vocab.itos).map(([key, value]) => [Number(key), value]));
|
| 1415 |
vocabSize = vocab.vocab_size;
|
|
|
|
| 1417 |
|
| 1418 |
// Step 2. Download ONNX Model
|
| 1419 |
updateProgress(15, "Downloading AI model...");
|
| 1420 |
+
const modelBlob = await fetchWithCache("https://huggingface.co/utkucoban/NanoMaestro-Realtime/resolve/main/NanoMaestro-Realtime/NM2.4%20ONNX%20int8/model_int8.onnx", (loaded, total) => {
|
| 1421 |
// Map 0-100% of download to 15-80% progress indicator
|
| 1422 |
const pct = 15 + (loaded / total) * 65;
|
| 1423 |
const loadedMB = (loaded / (1024 * 1024)).toFixed(1);
|
| 1424 |
const totalMB = (total / (1024 * 1024)).toFixed(1);
|
| 1425 |
updateProgress(pct, `Downloading AI model (${loadedMB}MB / ${totalMB}MB)...`);
|
| 1426 |
+
}, false);
|
| 1427 |
|
| 1428 |
// Step 3. Initialize inference session
|
| 1429 |
updateProgress(82, "Initializing neural network engine...");
|