jasleen02 commited on
Commit
9c8b886
·
verified ·
1 Parent(s): adc0cc3

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +71 -78
index.html CHANGED
@@ -1,34 +1,77 @@
 
1
  <!DOCTYPE html>
2
  <html lang="en">
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>Swedish → English Translator</title>
7
 
8
- <script src="https://cdn.jsdelivr.net/npm/onnxruntime-web@1.20.1/dist/ort.min.js"></script>
 
 
 
 
 
 
 
 
 
 
 
9
 
10
  <style>
11
- body { max-width: 900px; margin: 0 auto; padding: 24px; font-family: Arial, sans-serif; }
12
- #status { color: #555; margin: 8px 0 18px; }
13
- #error { color: #b00020; white-space: pre-wrap; margin-top: 12px; }
14
- textarea { width: 100%; min-height: 120px; padding: 12px; box-sizing: border-box; font-size: 16px; }
15
- button { margin: 14px 0; padding: 10px 18px; font-size: 16px; cursor: pointer; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
  </style>
17
  </head>
18
 
19
  <body>
20
- <h1>Swedish → English Translator</h1>
21
  <p>
22
- This is our own character-level Transformer from the lab, running directly in your browser.
23
- Sentences up to 120 characters work best (that is what it was trained on).
24
  </p>
25
 
26
- <p id="status">Loading model…</p>
27
 
28
  <label for="input">Swedish text</label>
29
- <textarea id="input" placeholder="Skriv en svensk mening här..." disabled></textarea>
 
 
 
 
30
 
31
  <br>
 
32
  <button id="translate-button" disabled>Translate</button>
33
 
34
  <label for="output">English translation</label>
@@ -36,17 +79,9 @@
36
 
37
  <p id="error"></p>
38
 
39
- <script>
40
- // Files produced by export_onnx.py, placed next to this page
41
- const ENCODER_URL = "encoder.onnx";
42
- const DECODER_URL = "decoder.onnx";
43
- const VOCAB_URL = "vocab.json";
44
-
45
- // Same constants as the notebook
46
- const TRAIN_MAX_LEN = 120; // max_len
47
- const MAX_LEN = TRAIN_MAX_LEN + 2; // + <s> and </s>
48
-
49
- ort.env.wasm.wasmPaths = "https://cdn.jsdelivr.net/npm/onnxruntime-web@1.20.1/dist/";
50
 
51
  const status = document.getElementById("status");
52
  const input = document.getElementById("input");
@@ -54,68 +89,32 @@
54
  const button = document.getElementById("translate-button");
55
  const errorBox = document.getElementById("error");
56
 
57
- let encoder, decoder, token2idx, idx2token;
58
 
59
  async function loadModel() {
60
  try {
61
- token2idx = await (await fetch(VOCAB_URL)).json();
62
- idx2token = Object.fromEntries(Object.entries(token2idx).map(([t, i]) => [i, t]));
63
 
64
- const opts = { executionProviders: ["wasm"] };
65
- encoder = await ort.InferenceSession.create(ENCODER_URL, opts);
66
- decoder = await ort.InferenceSession.create(DECODER_URL, opts);
 
67
 
68
  status.textContent = "Model ready. Enter Swedish text and click Translate.";
69
  input.disabled = false;
70
  button.disabled = false;
71
  } catch (error) {
72
  console.error(error);
73
- status.textContent = "The model could not load.";
74
  errorBox.textContent = String(error);
75
  }
76
  }
77
 
78
- // seqs2tensors: <s> + characters + </s>, unknown characters -> <unk> (1)
79
- function encode(text) {
80
- const chars = Array.from(text); // iterates by code point, like Python's list(str)
81
- return [token2idx["<s>"], ...chars.map(c => token2idx[c] ?? 1), token2idx["</s>"]];
82
- }
83
-
84
- const toTensor = ids =>
85
- new ort.Tensor("int64", BigInt64Array.from(ids, BigInt), [1, ids.length]);
86
-
87
- function argmax(arr) {
88
- let best = 0;
89
- for (let i = 1; i < arr.length; i++) if (arr[i] > arr[best]) best = i;
90
- return best;
91
- }
92
-
93
- // Same loop as greedy_decode_batched in the notebook
94
- async function translate(text) {
95
- const src = encode(text);
96
- const memory = (await encoder.run({ src: toTensor(src) })).memory;
97
-
98
- const eos = token2idx["</s>"];
99
- const tgt = [token2idx["<s>"]];
100
- const maxLen = Math.min(src.length + 20, MAX_LEN);
101
-
102
- for (let step = 0; step < maxLen - 1; step++) {
103
- const logits = (await decoder.run({ tgt: toTensor(tgt), memory })).logits.data;
104
- const next = argmax(logits);
105
- tgt.push(next);
106
- if (next === eos) break;
107
- }
108
-
109
- return tgt.slice(1)
110
- .filter(i => i !== eos)
111
- .map(i => idx2token[i] ?? "<unk>")
112
- .join("");
113
- }
114
-
115
- async function run() {
116
  const text = input.value.trim();
 
117
  if (!text) {
118
- output.value = "Skriv något först.";
119
  return;
120
  }
121
 
@@ -124,10 +123,9 @@
124
  errorBox.textContent = "";
125
 
126
  try {
127
- output.value = await translate(text);
128
- status.textContent = text.length > TRAIN_MAX_LEN
129
- ? `Done. Note: the input is longer than ${TRAIN_MAX_LEN} characters, so the result may be poor.`
130
- : "Done.";
131
  } catch (error) {
132
  console.error(error);
133
  status.textContent = "Translation failed.";
@@ -135,11 +133,6 @@
135
  } finally {
136
  button.disabled = false;
137
  }
138
- }
139
-
140
- button.addEventListener("click", run);
141
- input.addEventListener("keydown", e => {
142
- if (e.key === "Enter" && !e.shiftKey) { e.preventDefault(); run(); }
143
  });
144
 
145
  loadModel();
 
1
+
2
  <!DOCTYPE html>
3
  <html lang="en">
4
  <head>
5
  <meta charset="UTF-8">
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
 
7
 
8
+ <title>English → Swedish Translator</title>
9
+
10
+ <script
11
+ type="module"
12
+ crossorigin
13
+ src="https://cdn.jsdelivr.net/npm/@gradio/lite/dist/lite.js">
14
+ </script>
15
+
16
+ <link
17
+ rel="stylesheet"
18
+ crossorigin
19
+ href="https://cdn.jsdelivr.net/npm/@gradio/lite/dist/lite.css">
20
 
21
  <style>
22
+ body {
23
+ max-width: 900px;
24
+ margin: 0 auto;
25
+ padding: 24px;
26
+ font-family: Arial, sans-serif;
27
+ }
28
+
29
+ #status {
30
+ color: #555;
31
+ margin: 8px 0 18px;
32
+ }
33
+
34
+ #error {
35
+ color: #b00020;
36
+ white-space: pre-wrap;
37
+ margin-top: 12px;
38
+ }
39
+
40
+ textarea {
41
+ width: 100%;
42
+ min-height: 120px;
43
+ padding: 12px;
44
+ box-sizing: border-box;
45
+ font-size: 16px;
46
+ }
47
+
48
+ button {
49
+ margin: 14px 0;
50
+ padding: 10px 18px;
51
+ font-size: 16px;
52
+ cursor: pointer;
53
+ }
54
  </style>
55
  </head>
56
 
57
  <body>
58
+ <h1>English → Swedish Translator</h1>
59
  <p>
60
+ This translation model runs directly in your browser.
61
+ The first translation can take a little while because the model must download.
62
  </p>
63
 
64
+ <p id="status">Loading translation model…</p>
65
 
66
  <label for="input">Swedish text</label>
67
+ <textarea
68
+ id="input"
69
+ placeholder="Write an Swedish sentence here..."
70
+ disabled
71
+ ></textarea>
72
 
73
  <br>
74
+
75
  <button id="translate-button" disabled>Translate</button>
76
 
77
  <label for="output">English translation</label>
 
79
 
80
  <p id="error"></p>
81
 
82
+ <script type="module">
83
+ import { pipeline, env } from
84
+ "https://cdn.jsdelivr.net/npm/@huggingface/transformers@3.0.2";
 
 
 
 
 
 
 
 
85
 
86
  const status = document.getElementById("status");
87
  const input = document.getElementById("input");
 
89
  const button = document.getElementById("translate-button");
90
  const errorBox = document.getElementById("error");
91
 
92
+ let translator;
93
 
94
  async function loadModel() {
95
  try {
96
+ env.allowLocalModels = false;
 
97
 
98
+ translator = await pipeline(
99
+ "translation",
100
+ "Xenova/opus-mt-en-sv"
101
+ );
102
 
103
  status.textContent = "Model ready. Enter Swedish text and click Translate.";
104
  input.disabled = false;
105
  button.disabled = false;
106
  } catch (error) {
107
  console.error(error);
108
+ status.textContent = "The translation model could not load.";
109
  errorBox.textContent = String(error);
110
  }
111
  }
112
 
113
+ button.addEventListener("click", async () => {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
114
  const text = input.value.trim();
115
+
116
  if (!text) {
117
+ output.value = "Please write something first.";
118
  return;
119
  }
120
 
 
123
  errorBox.textContent = "";
124
 
125
  try {
126
+ const result = await translator(text);
127
+ output.value = result[0].translation_text;
128
+ status.textContent = "Done.";
 
129
  } catch (error) {
130
  console.error(error);
131
  status.textContent = "Translation failed.";
 
133
  } finally {
134
  button.disabled = false;
135
  }
 
 
 
 
 
136
  });
137
 
138
  loadModel();