Javedalam commited on
Commit
bb12dec
·
verified ·
1 Parent(s): ff7fea2

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +150 -69
index.html CHANGED
@@ -1,72 +1,153 @@
1
- <script type="module">
2
- const btn = document.getElementById("submit");
3
- const out = document.getElementById("to");
4
- const fromEl = document.getElementById("from");
5
- const srcEl = document.getElementById("src_lang");
6
- const tgtEl = document.getElementById("tgt_lang");
7
- const wrap = document.getElementById("progress-wrap");
8
- const bar = document.getElementById("loadProgress");
9
- const txt = document.getElementById("progressText");
10
-
11
- btn.disabled = false;
12
- btn.value = "Translate";
13
-
14
- let translator = null;
15
-
16
- function showProgressUI(show, message="") {
17
- wrap.style.display = show ? "" : "none";
18
- txt.textContent = message || "";
19
- bar.value = 0;
20
- bar.max = 1;
21
- }
22
-
23
- async function getTranslator() {
24
- if (translator) return translator;
25
-
26
- showProgressUI(true, "Loading model…");
27
-
28
- const { pipeline, env } = await import("https://cdn.jsdelivr.net/npm/@xenova/transformers@3.0.0");
29
- env.useBrowserCache = true;
30
- env.allowLocalModels = false;
31
-
32
- translator = await pipeline("translation", "Xenova/nllb-200-distilled-600M", {
33
- device: (navigator.gpu ? "webgpu" : "wasm"),
34
- progress_callback: (p) => {
35
- if (p.status) {
36
- txt.textContent = p.status;
37
- }
38
- if (typeof p.loaded === "number" && typeof p.total === "number" && p.total > 0) {
39
- bar.max = p.total;
40
- bar.value = p.loaded;
41
- const pct = Math.round((p.loaded / p.total) * 100);
42
- txt.textContent = `Downloading ${p.file || "model"}… ${pct}%`;
43
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
44
  }
45
- });
 
 
 
46
 
47
- txt.textContent = "Model ready ✔";
48
- bar.max = 1; bar.value = 1;
49
- return translator;
50
- }
51
-
52
- btn.addEventListener("click", async () => {
53
- btn.disabled = true;
54
- const prev = btn.value;
55
- btn.value = "Working…";
56
-
57
- try {
58
- const t = await getTranslator();
59
- const text = (fromEl.value || "").trim();
60
- if (!text) { out.value = "Please type some text."; return; }
61
- const result = await t(text, { src_lang: srcEl.value, tgt_lang: tgtEl.value, max_length: 128 });
62
- out.value = result[0]?.translation_text || "(no output)";
63
- } catch (e) {
64
- console.error(e);
65
- out.value = "Error: see console.";
66
- txt.textContent = "Error loading or running model.";
67
- } finally {
68
- btn.disabled = false;
69
- btn.value = prev;
70
  }
71
- });
72
- </script>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
6
+ <meta name="viewport" content="width=device-width, initial-scale=1"/>
7
+ <title>NLLB Translation (WebGPU/WASM) + Progress</title>
8
+ <style>
9
+ body { font: 14px/1.5 system-ui, -apple-system, Segoe UI, Roboto, sans-serif; margin: 16px; }
10
+ h1 { margin-top:0; }
11
+ label { display:block; margin: 8px 0 4px; }
12
+ textarea { width: 100%; min-height: 120px; }
13
+ select, input[type="submit"] { padding: 8px; font: inherit; }
14
+ #row { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
15
+ #progress-wrap { margin: 10px 0; display:none; }
16
+ #footer { opacity:.7; margin-top:12px; font-size:12px; }
17
+ .muted { opacity:.8 }
18
+ </style>
19
+ </head>
20
+ <body>
21
+ <h1>NLLB translation in browser</h1>
22
+
23
+ <div id="row">
24
+ <div>
25
+ <label for="src_lang">Source language</label>
26
+ <select id="src_lang">
27
+ <option value="eng_Latn" selected>English (eng_Latn)</option>
28
+ <option value="spa_Latn">Spanish (spa_Latn)</option>
29
+ <option value="fra_Latn">French (fra_Latn)</option>
30
+ <option value="hin_Deva">Hindi (hin_Deva)</option>
31
+ </select>
32
+ </div>
33
+ <div>
34
+ <label for="tgt_lang">Target language</label>
35
+ <select id="tgt_lang">
36
+ <option value="spa_Latn" selected>Spanish (spa_Latn)</option>
37
+ <option value="eng_Latn">English (eng_Latn)</option>
38
+ <option value="fra_Latn">French (fra_Latn)</option>
39
+ <option value="hin_Deva">Hindi (hin_Deva)</option>
40
+ </select>
41
+ </div>
42
+ </div>
43
+
44
+ <label for="from">Input text</label>
45
+ <textarea id="from" placeholder="Type text to translate"></textarea>
46
+
47
+ <!-- Progress UI -->
48
+ <div id="progress-wrap">
49
+ <progress id="loadProgress" value="0" max="1" style="width:100%;"></progress>
50
+ <div id="progressText" class="muted">Initializing…</div>
51
+ </div>
52
+
53
+ <input type="submit" id="submit" value="Loading..." disabled />
54
+
55
+ <label for="to" style="margin-top:12px">Output</label>
56
+ <textarea id="to" readonly>Output will be here...</textarea>
57
+
58
+ <div id="footer" class="muted">
59
+ Tip: first load downloads the model; later loads are much faster thanks to browser cache.
60
+ </div>
61
+
62
+ <!-- Load UMD bundle (no ESM/dynamic import).
63
+ If jsDelivr is blocked, try unpkg:
64
+ https://unpkg.com/@xenova/transformers@3.0.0/dist/transformers.min.js
65
+ -->
66
+ <script src="https://cdn.jsdelivr.net/npm/@xenova/transformers@3.0.0/dist/transformers.min.js"></script>
67
+
68
+ <script>
69
+ // Grab DOM elements
70
+ const btn = document.getElementById("submit");
71
+ const out = document.getElementById("to");
72
+ const fromEl = document.getElementById("from");
73
+ const srcEl = document.getElementById("src_lang");
74
+ const tgtEl = document.getElementById("tgt_lang");
75
+ const wrap = document.getElementById("progress-wrap");
76
+ const bar = document.getElementById("loadProgress");
77
+ const txt = document.getElementById("progressText");
78
+
79
+ // Show UI immediately
80
+ btn.disabled = false;
81
+ btn.value = "Translate";
82
+
83
+ // Transformers.js UMD exposes window.transformers
84
+ const tf = window.transformers;
85
+ if (!tf) {
86
+ document.body.insertAdjacentHTML('beforeend',
87
+ '<p style="color:#b00">Failed to load Transformers.js. Check CDN/network.</p>');
88
+ }
89
+
90
+ let translator = null;
91
+
92
+ function showProgressUI(show, message) {
93
+ wrap.style.display = show ? "" : "none";
94
+ if (message) txt.textContent = message;
95
+ bar.value = 0; bar.max = 1;
96
+ }
97
+
98
+ function progressCallback(p) {
99
+ if (p.status) txt.textContent = p.status;
100
+ if (typeof p.loaded === "number" && typeof p.total === "number" && p.total > 0) {
101
+ bar.max = p.total;
102
+ bar.value = p.loaded;
103
+ const pct = Math.round((p.loaded / p.total) * 100);
104
+ txt.textContent = `Downloading ${p.file || "model"}… ${pct}%`;
105
  }
106
+ }
107
+
108
+ async function getTranslator() {
109
+ if (translator) return translator;
110
 
111
+ showProgressUI(true, "Loading model…");
112
+ try {
113
+ const { pipeline, env } = tf;
114
+ env.useBrowserCache = true;
115
+ env.allowLocalModels = false;
116
+ // WASM fallback uses threads; harmless if WebGPU available
117
+ env.backends.onnx.wasm.numThreads = Math.max(4, Math.min(8, navigator.hardwareConcurrency || 4));
118
+
119
+ translator = await pipeline("translation", "Xenova/nllb-200-distilled-600M", {
120
+ device: (navigator.gpu ? "webgpu" : "wasm"),
121
+ progress_callback: progressCallback
122
+ // If you hit issues with quant hints, you can add:
123
+ // dtype: { encoder_model: "q8", decoder_model_merged: "q8" },
124
+ });
125
+
126
+ txt.textContent = "Model ready ";
127
+ bar.max = 1; bar.value = 1;
128
+ return translator;
129
+ } catch (e) {
130
+ console.error(e);
131
+ txt.textContent = "Error loading model — see console.";
132
+ throw e;
133
+ }
134
  }
135
+
136
+ btn.addEventListener("click", async () => {
137
+ const prev = btn.value;
138
+ btn.disabled = true; btn.value = "Working…";
139
+ try {
140
+ const t = await getTranslator();
141
+ const text = (fromEl.value || "").trim();
142
+ if (!text) { out.value = "Please type some text."; return; }
143
+ const res = await t(text, { src_lang: srcEl.value, tgt_lang: tgtEl.value, max_length: 128 });
144
+ out.value = res?.[0]?.translation_text || "(no output)";
145
+ } catch (e) {
146
+ out.value = "Translation failed. See console for details.";
147
+ } finally {
148
+ btn.disabled = false; btn.value = prev;
149
+ }
150
+ });
151
+ </script>
152
+ </body>
153
+ </html>