huggingworld commited on
Commit
e00d319
·
verified ·
1 Parent(s): 7b7deb1

Update assets/app.js

Browse files
Files changed (1) hide show
  1. assets/app.js +90 -50
assets/app.js CHANGED
@@ -1,8 +1,10 @@
1
  import { env, AutoModelForCausalLM, Tensor } from '/assets/transformers.min.js';
2
 
 
 
3
 
4
  // Declare global UI elements and model instance
5
- let dnaInput, maxTokensInput, temperatureInput, deviceInput, generateBtn, outputDisplay, statusDisplay;
6
  let carbonModel = null;
7
 
8
  const MODEL_REPO = 'huggingworld/Carbon-500M-ONNX';
@@ -56,6 +58,22 @@ function idToKmer(id) {
56
  return kmer;
57
  }
58
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
59
  // ==========================================
60
  // 🧠 MODEL INITIALIZATION
61
  // ==========================================
@@ -64,33 +82,50 @@ async function initializeModel() {
64
  generateBtn.disabled = true;
65
 
66
  const selectedDevice = deviceInput.value;
67
- const dtypeSetting = selectedDevice === 'webgpu' ? 'q4f16' : 'fp16';
68
 
69
  try {
70
- statusDisplay.textContent = `📥 Allocating Carbon layers onto engine target [${selectedDevice.toUpperCase()}]...`;
71
  statusDisplay.style.color = '#888888';
72
 
 
 
73
  if (carbonModel) {
74
  carbonModel = null;
75
  }
76
 
77
  carbonModel = await AutoModelForCausalLM.from_pretrained(MODEL_REPO, {
78
  device: selectedDevice,
79
- dtype: dtypeSetting
 
 
 
 
 
 
 
 
 
 
 
 
 
80
  });
81
 
82
- statusDisplay.textContent = `🟢 Carbon Model Ready (${selectedDevice.toUpperCase()} Activated)`;
83
  statusDisplay.style.color = '#317f3f';
 
84
  generateBtn.disabled = false;
85
  } catch (error) {
86
  console.error('❌ Initialization Failure:', error);
87
  statusDisplay.textContent = `❌ Engine Error: ${error.message}`;
88
  statusDisplay.style.color = '#b00020';
 
89
  }
90
  }
91
 
92
  // ==========================================
93
- // ⚡ INFERENCE EXECUTION LOOP
94
  // ==========================================
95
 
96
  async function runInference() {
@@ -102,19 +137,16 @@ async function runInference() {
102
  outputDisplay.textContent = 'Processing structure...';
103
 
104
  try {
105
- // 1. Clean data inputs
106
  let rawInput = dnaInput.value.toUpperCase().replace(/[^ACGTN]/g, '');
107
  if (rawInput.length === 0) {
108
  throw new Error("No valid genomic bases found.");
109
  }
110
 
111
- // 2. Pad to fit 6-mer boundary block splits
112
  const remainder = rawInput.length % 6;
113
  if (remainder !== 0) {
114
  rawInput = "A".repeat(6 - remainder) + rawInput;
115
  }
116
 
117
- // 3. Build numerical token array manually using Carbon offsets
118
  let inputIds = [DNA_TAG_ID];
119
  for (let i = 0; i < rawInput.length; i += 6) {
120
  const chunk = rawInput.slice(i, i + 6);
@@ -125,7 +157,6 @@ async function runInference() {
125
  let temp = temperatureInput ? parseFloat(temperatureInput.value) : 0.7;
126
  if (temp <= 0) temp = 0.7;
127
 
128
- // 4. Instantiate Int64 Tensors matching model layout expectations
129
  const inputSequenceTensor = new Tensor(
130
  'int64',
131
  BigInt64Array.from(inputIds.map(id => BigInt(id))),
@@ -138,59 +169,63 @@ async function runInference() {
138
  [1, inputIds.length]
139
  );
140
 
141
- // 5. Submit context tensors directly to CausalLM generator
142
- const generatedOutputTensors = await carbonModel.generate({
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
143
  input_ids: inputSequenceTensor,
144
  attention_mask: attentionMaskTensor,
145
  max_new_tokens: maxTokens,
146
  min_new_tokens: 15,
147
  do_sample: temp > 0,
148
  temperature: temp,
149
- repetition_penalty: 1.15
 
150
  });
151
 
152
  const duration = ((performance.now() - startTime) / 1000).toFixed(2);
153
 
154
- // 6. Comprehensive extraction pattern to parse out BigInt matrix output arrays
155
- let fullSequenceArray = [];
156
- if (generatedOutputTensors) {
157
- if (typeof generatedOutputTensors.tolist === 'function') {
158
- const nestedList = generatedOutputTensors.tolist();
159
- // Check if nested inside a batch index array wrapper: [[tokens]] vs [tokens]
160
- fullSequenceArray = Array.isArray(nestedList[0]) ? nestedList[0] : nestedList;
161
- } else if (generatedOutputTensors.data) {
162
- fullSequenceArray = Array.from(generatedOutputTensors.data);
163
- } else if (Array.isArray(generatedOutputTensors)) {
164
- fullSequenceArray = generatedOutputTensors;
165
- }
166
- }
167
-
168
- // 7. Isolate newly generated tokens from the prompt sequence inputs
169
- let generatedTokens = [];
170
- const plainOutputArray = fullSequenceArray.map(t => Number(t));
171
-
172
- // FIX: Safely check index position zero of array primitive elements instead of matching arrays to integers
173
- if (plainOutputArray.length > inputIds.length && plainOutputArray[0] === DNA_TAG_ID) {
174
- generatedTokens = plainOutputArray.slice(inputIds.length);
175
- } else {
176
- generatedTokens = plainOutputArray;
177
- }
178
-
179
- // 8. Translate vocabulary ranges back into pure DNA characters
180
- let generatedSequence = "";
181
- for (let token of generatedTokens) {
182
- const numericId = Number(token);
183
- if (numericId >= DNA_OFFSET && numericId <= OOV_TOKEN_ID) {
184
- generatedSequence += idToKmer(numericId);
185
- }
186
- }
187
-
188
  if (!generatedSequence) {
189
- generatedSequence = `[Generation tracking completed but output vector map evaluation was empty]\nRaw tokens: [${plainOutputArray.join(', ')}]`;
 
 
 
190
  }
191
 
192
- outputDisplay.textContent = `${generatedSequence}\n\n[Inference completed in ${duration}s on ${deviceInput.value.toUpperCase()}]`;
193
-
194
  } catch (error) {
195
  console.error("❌ Generation Pipeline Error:", error);
196
  outputDisplay.textContent = `❌ Generation Error: ${error.message}`;
@@ -209,9 +244,11 @@ document.addEventListener('DOMContentLoaded', () => {
209
  maxTokensInput = document.getElementById('max-tokens');
210
  temperatureInput = document.getElementById('temperature');
211
  deviceInput = document.getElementById('execution-device');
 
212
  generateBtn = document.getElementById('generateBtn');
213
  outputDisplay = document.getElementById('output-display');
214
  statusDisplay = document.getElementById('status-message');
 
215
 
216
  if (generateBtn) {
217
  generateBtn.addEventListener('click', runInference);
@@ -219,6 +256,9 @@ document.addEventListener('DOMContentLoaded', () => {
219
  if (deviceInput) {
220
  deviceInput.addEventListener('change', initializeModel);
221
  }
 
 
 
222
 
223
  initializeModel();
224
  });
 
1
  import { env, AutoModelForCausalLM, Tensor } from '/assets/transformers.min.js';
2
 
3
+ // Prevent browser cache exhaustion under quota restrictions
4
+ env.useBrowserCache = false;
5
 
6
  // Declare global UI elements and model instance
7
+ let dnaInput, maxTokensInput, temperatureInput, deviceInput, dtypeInput, generateBtn, outputDisplay, statusDisplay, progressBar;
8
  let carbonModel = null;
9
 
10
  const MODEL_REPO = 'huggingworld/Carbon-500M-ONNX';
 
58
  return kmer;
59
  }
60
 
61
+ /**
62
+ * Converts a raw string of DNA bases into HTML color-coded spans matching international standards.
63
+ */
64
+ function colorCodeSequence(sequence) {
65
+ return sequence.split('').map(base => {
66
+ switch(base) {
67
+ case 'A': return '<span class="dna-a">A</span>';
68
+ case 'C': return '<span class="dna-c">C</span>';
69
+ case 'G': return '<span class="dna-g">G</span>';
70
+ case 'T': return '<span class="dna-t">T</span>';
71
+ case 'N': return '<span class="dna-n">N</span>';
72
+ default: return base; // Pass through unexpected layout structures or spacing safely
73
+ }
74
+ }).join('');
75
+ }
76
+
77
  // ==========================================
78
  // 🧠 MODEL INITIALIZATION
79
  // ==========================================
 
82
  generateBtn.disabled = true;
83
 
84
  const selectedDevice = deviceInput.value;
85
+ const dtypeSetting = dtypeInput ? dtypeInput.value : 'fp16';
86
 
87
  try {
88
+ statusDisplay.textContent = `📥 Allocating Carbon layers onto engine target [${selectedDevice.toUpperCase()} (${dtypeSetting.toUpperCase()})]...`;
89
  statusDisplay.style.color = '#888888';
90
 
91
+ if (progressBar) progressBar.style.width = '0%';
92
+
93
  if (carbonModel) {
94
  carbonModel = null;
95
  }
96
 
97
  carbonModel = await AutoModelForCausalLM.from_pretrained(MODEL_REPO, {
98
  device: selectedDevice,
99
+ dtype: dtypeSetting,
100
+ progress_callback: (e) => {
101
+ if (e.status === 'initiate') {
102
+ statusDisplay.textContent = `🎬 Initiating download: ${e.file}...`;
103
+ } else if (e.status === 'progress') {
104
+ statusDisplay.textContent = `📥 Downloading ${e.file}: ${Math.round(e.progress)}%`;
105
+ if (progressBar) progressBar.style.width = `${e.progress}%`;
106
+ } else if (e.status === 'progress_total') {
107
+ if (progressBar) progressBar.style.width = `${e.progress}%`;
108
+ statusDisplay.textContent = `📦 Aggregate Downloading Progress: ${Math.round(e.progress)}%`;
109
+ } else if (e.status === 'done') {
110
+ statusDisplay.textContent = `✨ Loaded file asset: ${e.file}`;
111
+ }
112
+ }
113
  });
114
 
115
+ statusDisplay.textContent = `🟢 Carbon Model Ready (${selectedDevice.toUpperCase()} + ${dtypeSetting.toUpperCase()} Activated)`;
116
  statusDisplay.style.color = '#317f3f';
117
+ if (progressBar) progressBar.style.width = '100%';
118
  generateBtn.disabled = false;
119
  } catch (error) {
120
  console.error('❌ Initialization Failure:', error);
121
  statusDisplay.textContent = `❌ Engine Error: ${error.message}`;
122
  statusDisplay.style.color = '#b00020';
123
+ if (progressBar) progressBar.style.width = '0%';
124
  }
125
  }
126
 
127
  // ==========================================
128
+ // ⚡ INFERENCE EXECUTION LOOP (STREAMING + COLOR ACTIVATED)
129
  // ==========================================
130
 
131
  async function runInference() {
 
137
  outputDisplay.textContent = 'Processing structure...';
138
 
139
  try {
 
140
  let rawInput = dnaInput.value.toUpperCase().replace(/[^ACGTN]/g, '');
141
  if (rawInput.length === 0) {
142
  throw new Error("No valid genomic bases found.");
143
  }
144
 
 
145
  const remainder = rawInput.length % 6;
146
  if (remainder !== 0) {
147
  rawInput = "A".repeat(6 - remainder) + rawInput;
148
  }
149
 
 
150
  let inputIds = [DNA_TAG_ID];
151
  for (let i = 0; i < rawInput.length; i += 6) {
152
  const chunk = rawInput.slice(i, i + 6);
 
157
  let temp = temperatureInput ? parseFloat(temperatureInput.value) : 0.7;
158
  if (temp <= 0) temp = 0.7;
159
 
 
160
  const inputSequenceTensor = new Tensor(
161
  'int64',
162
  BigInt64Array.from(inputIds.map(id => BigInt(id))),
 
169
  [1, inputIds.length]
170
  );
171
 
172
+ // Streaming state monitors
173
+ let generatedSequence = "";
174
+ let tokenCount = 0;
175
+
176
+ // Custom Streamer configuration to hook directly into the token stream
177
+ const customStreamer = {
178
+ put: (value) => {
179
+ let tokens = [];
180
+ if (value && typeof value.tolist === 'function') {
181
+ tokens = value.tolist().flat();
182
+ } else if (value && value.data) {
183
+ tokens = Array.from(value.data);
184
+ } else if (Array.isArray(value)) {
185
+ tokens = value;
186
+ }
187
+
188
+ for (const token of tokens) {
189
+ const numericId = Number(token);
190
+ tokenCount++;
191
+
192
+ // Skip prompt sequence tokens
193
+ if (tokenCount <= inputIds.length) {
194
+ continue;
195
+ }
196
+
197
+ // Decode token step-by-step, wrap in color spans, and stream
198
+ if (numericId >= DNA_OFFSET && numericId <= OOV_TOKEN_ID) {
199
+ generatedSequence += idToKmer(numericId);
200
+
201
+ const HTMLRenderMatrix = colorCodeSequence(generatedSequence);
202
+ outputDisplay.innerHTML = `${HTMLRenderMatrix}\n\n<span class="meta-text">[Streaming on ${deviceInput.value.toUpperCase()}...]</span>`;
203
+ }
204
+ }
205
+ },
206
+ end: () => {}
207
+ };
208
+
209
+ await carbonModel.generate({
210
  input_ids: inputSequenceTensor,
211
  attention_mask: attentionMaskTensor,
212
  max_new_tokens: maxTokens,
213
  min_new_tokens: 15,
214
  do_sample: temp > 0,
215
  temperature: temp,
216
+ repetition_penalty: 1.15,
217
+ streamer: customStreamer
218
  });
219
 
220
  const duration = ((performance.now() - startTime) / 1000).toFixed(2);
221
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
222
  if (!generatedSequence) {
223
+ outputDisplay.textContent = `[Generation tracking completed but output vector map evaluation was empty]`;
224
+ } else {
225
+ const FinalHTMLRenderMatrix = colorCodeSequence(generatedSequence);
226
+ outputDisplay.innerHTML = `${FinalHTMLRenderMatrix}\n\n<span class="meta-text">[Inference completed in ${duration}s on ${deviceInput.value.toUpperCase()}]</span>`;
227
  }
228
 
 
 
229
  } catch (error) {
230
  console.error("❌ Generation Pipeline Error:", error);
231
  outputDisplay.textContent = `❌ Generation Error: ${error.message}`;
 
244
  maxTokensInput = document.getElementById('max-tokens');
245
  temperatureInput = document.getElementById('temperature');
246
  deviceInput = document.getElementById('execution-device');
247
+ dtypeInput = document.getElementById('execution-dtype');
248
  generateBtn = document.getElementById('generateBtn');
249
  outputDisplay = document.getElementById('output-display');
250
  statusDisplay = document.getElementById('status-message');
251
+ progressBar = document.getElementById('progress-bar');
252
 
253
  if (generateBtn) {
254
  generateBtn.addEventListener('click', runInference);
 
256
  if (deviceInput) {
257
  deviceInput.addEventListener('change', initializeModel);
258
  }
259
+ if (dtypeInput) {
260
+ dtypeInput.addEventListener('change', initializeModel);
261
+ }
262
 
263
  initializeModel();
264
  });