Chillarmo commited on
Commit
a66e866
·
verified ·
1 Parent(s): 0eb7e14

Update index.js

Browse files
Files changed (1) hide show
  1. index.js +58 -36
index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { pipeline } from 'https://cdn.jsdelivr.net/npm/@huggingface/transformers@3.7.6';
2
 
3
  // Get DOM elements
4
  const status = document.getElementById('status');
@@ -13,7 +13,8 @@ const recordingTimeDisplay = document.getElementById('recordingTime');
13
  const visualizerBars = document.querySelectorAll('.bar');
14
 
15
  // State
16
- let transcriber = null;
 
17
  let mediaStream = null;
18
  let audioContext = null;
19
  let mediaRecorder = null;
@@ -32,45 +33,48 @@ async function initModel() {
32
  status.className = 'loading';
33
 
34
  const device = useWebGPUCheckbox.checked ? 'webgpu' : 'wasm';
 
35
 
36
- // Load your custom ATOM model
37
- // IMPORTANT: This automatically loads the custom tokenizer from Chillarmo/ATOM
38
- // The tokenizer is specific to your model's training and must be used
39
- transcriber = await pipeline(
40
- 'automatic-speech-recognition',
41
- 'Chillarmo/ATOM',
42
- {
43
- device: device,
44
- // Ensure we use the model's own tokenizer, not a default one
45
- revision: 'main', // Use main branch which has your custom tokenizer
46
- progress_callback: (progress) => {
47
- if (progress.status === 'downloading') {
48
- const percent = Math.round((progress.loaded / progress.total) * 100);
49
- status.textContent = `Downloading ${progress.file}: ${percent}%`;
50
- } else if (progress.status === 'loading') {
51
- status.textContent = `Loading ${progress.file}...`;
52
- } else if (progress.status === 'progress') {
53
- const percent = Math.round(progress.progress);
54
- status.textContent = `Loading model: ${percent}%`;
55
- }
56
  }
57
  }
58
- );
 
 
59
 
60
- console.log('ATOM model loaded successfully with custom Armenian tokenizer');
61
- status.textContent = 'Model & custom tokenizer loaded! Ready to transcribe Armenian speech.';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
62
  status.className = 'ready';
63
  startBtn.disabled = false;
64
  } catch (error) {
65
  console.error('Model loading error:', error);
66
  status.textContent = `Error loading model: ${error.message}`;
67
  status.className = 'error';
68
-
69
- // Log more details for debugging tokenizer issues
70
  console.error('Full error details:', error);
71
- if (error.message.includes('tokenizer')) {
72
- status.textContent = 'Error: Custom tokenizer failed to load. Check console.';
73
- }
74
  }
75
  }
76
 
@@ -232,16 +236,33 @@ async function processAudioChunk(chunks) {
232
  // Get audio data as Float32Array
233
  const audioData = audioBuffer.getChannelData(0);
234
 
235
- // Transcribe with ATOM model
236
- // This uses the custom Armenian tokenizer that comes with the model
237
- // The tokenizer is critical - it was trained with the model
238
- const result = await transcriber(audioData, {
239
  sampling_rate: audioBuffer.sampleRate,
240
  });
241
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
242
  // Add to transcription
243
- if (result && result.text && result.text.trim()) {
244
- addTranscription(result.text.trim());
 
245
  chunkCount++;
246
  chunkCountDisplay.textContent = chunkCount;
247
  }
@@ -260,6 +281,7 @@ async function processAudioChunk(chunks) {
260
  console.error('Error processing audio:', error);
261
  status.textContent = `Processing error: ${error.message}`;
262
  status.className = 'error';
 
263
 
264
  // Restore recording status if still recording
265
  setTimeout(() => {
 
1
+ import { WhisperForConditionalGeneration, WhisperProcessor } from 'https://cdn.jsdelivr.net/npm/@huggingface/transformers@3.7.6';
2
 
3
  // Get DOM elements
4
  const status = document.getElementById('status');
 
13
  const visualizerBars = document.querySelectorAll('.bar');
14
 
15
  // State
16
+ let model = null;
17
+ let processor = null;
18
  let mediaStream = null;
19
  let audioContext = null;
20
  let mediaRecorder = null;
 
33
  status.className = 'loading';
34
 
35
  const device = useWebGPUCheckbox.checked ? 'webgpu' : 'wasm';
36
+ const dtype = useWebGPUCheckbox.checked ? 'fp32' : 'fp32';
37
 
38
+ // Load processor (includes the custom Armenian tokenizer)
39
+ status.textContent = 'Loading custom Armenian processor/tokenizer...';
40
+ processor = await WhisperProcessor.from_pretrained('Chillarmo/ATOM', {
41
+ progress_callback: (progress) => {
42
+ if (progress.status === 'downloading') {
43
+ const percent = Math.round((progress.loaded / progress.total) * 100);
44
+ status.textContent = `Downloading ${progress.file}: ${percent}%`;
 
 
 
 
 
 
 
 
 
 
 
 
 
45
  }
46
  }
47
+ });
48
+
49
+ console.log('✓ ATOM Processor loaded (includes custom tokenizer)');
50
 
51
+ // Load model
52
+ status.textContent = 'Loading ATOM model...';
53
+ model = await WhisperForConditionalGeneration.from_pretrained('Chillarmo/ATOM', {
54
+ device: device,
55
+ dtype: dtype,
56
+ progress_callback: (progress) => {
57
+ if (progress.status === 'downloading') {
58
+ const percent = Math.round((progress.loaded / progress.total) * 100);
59
+ status.textContent = `Downloading model ${progress.file}: ${percent}%`;
60
+ } else if (progress.status === 'loading') {
61
+ status.textContent = `Loading ${progress.file}...`;
62
+ }
63
+ }
64
+ });
65
+
66
+ console.log('✓ ATOM Model loaded');
67
+ console.log('Model config:', model.config);
68
+ console.log('Processor:', processor);
69
+
70
+ status.textContent = 'ATOM ready! Model + custom tokenizer loaded successfully.';
71
  status.className = 'ready';
72
  startBtn.disabled = false;
73
  } catch (error) {
74
  console.error('Model loading error:', error);
75
  status.textContent = `Error loading model: ${error.message}`;
76
  status.className = 'error';
 
 
77
  console.error('Full error details:', error);
 
 
 
78
  }
79
  }
80
 
 
236
  // Get audio data as Float32Array
237
  const audioData = audioBuffer.getChannelData(0);
238
 
239
+ console.log('Processing audio chunk:', audioData.length, 'samples at', audioBuffer.sampleRate, 'Hz');
240
+
241
+ // Process audio with the processor (includes custom tokenizer)
242
+ const inputs = await processor(audioData, {
243
  sampling_rate: audioBuffer.sampleRate,
244
  });
245
 
246
+ console.log('Processor output:', inputs);
247
+
248
+ // Generate with the model
249
+ const outputs = await model.generate({
250
+ ...inputs,
251
+ });
252
+
253
+ console.log('Model outputs:', outputs);
254
+
255
+ // Decode the output tokens using the custom tokenizer
256
+ const decoded = processor.batch_decode(outputs, {
257
+ skip_special_tokens: true,
258
+ });
259
+
260
+ console.log('Decoded text:', decoded);
261
+
262
  // Add to transcription
263
+ const text = decoded[0].trim();
264
+ if (text) {
265
+ addTranscription(text);
266
  chunkCount++;
267
  chunkCountDisplay.textContent = chunkCount;
268
  }
 
281
  console.error('Error processing audio:', error);
282
  status.textContent = `Processing error: ${error.message}`;
283
  status.className = 'error';
284
+ console.error('Full processing error:', error);
285
 
286
  // Restore recording status if still recording
287
  setTimeout(() => {