masumtechnonext commited on
Commit
f8f32bf
·
verified ·
1 Parent(s): 152b70e

Upload app.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. app.py +34 -25
app.py CHANGED
@@ -1,59 +1,68 @@
 
1
  import os
2
 
3
  import gradio as gr
4
  import torch
5
- from transformers import Wav2Vec2ForCTC, Wav2Vec2Processor
 
 
6
 
7
  MODEL_ID = os.environ.get("HF_ASR_MODEL", "masumtechnonext/wav2vec2-arabic-letter-verifier")
8
  HF_TOKEN = os.environ.get("HF_TOKEN")
 
9
 
10
- processor = Wav2Vec2Processor.from_pretrained(MODEL_ID, token=HF_TOKEN)
11
- model = Wav2Vec2ForCTC.from_pretrained(MODEL_ID, token=HF_TOKEN)
12
  model.eval()
13
 
 
 
 
 
 
 
14
 
15
- def transcribe(audio):
 
16
  if audio is None:
17
- return "", "Record or upload audio first."
18
 
19
  sample_rate, waveform = audio
20
  waveform = torch.tensor(waveform, dtype=torch.float32)
21
  if waveform.ndim > 1:
22
  waveform = waveform.mean(dim=-1)
 
 
23
 
24
- inputs = processor(
25
- waveform.numpy(),
26
- sampling_rate=sample_rate,
27
- return_tensors="pt",
28
- padding=True,
29
- )
30
 
31
  with torch.no_grad():
32
- logits = model(inputs.input_values).logits
33
 
34
- predicted_ids = torch.argmax(logits, dim=-1)
35
- transcription = processor.batch_decode(predicted_ids)[0].strip()
36
- return transcription
37
 
 
 
 
38
 
39
- def verify(audio, expected_letter):
40
- transcription = transcribe(audio)
41
- if not expected_letter:
42
- return transcription, "Enter an expected letter to verify."
43
 
44
- is_match = transcription.strip() == expected_letter.strip()
45
- verdict = "✅ Match" if is_match else "❌ No match"
46
- return transcription, verdict
47
 
48
 
49
  demo = gr.Interface(
50
- fn=verify,
51
  inputs=[
52
  gr.Audio(sources=["microphone", "upload"], type="numpy", label="Speak the letter"),
53
- gr.Textbox(label="Expected letter (optional)"),
54
  ],
55
  outputs=[
56
- gr.Textbox(label="Transcription"),
57
  gr.Textbox(label="Verification"),
58
  ],
59
  title="Arabic Letter Verifier",
 
1
+ import json
2
  import os
3
 
4
  import gradio as gr
5
  import torch
6
+ import torchaudio
7
+ from huggingface_hub import hf_hub_download
8
+ from transformers import Wav2Vec2FeatureExtractor, Wav2Vec2ForSequenceClassification
9
 
10
  MODEL_ID = os.environ.get("HF_ASR_MODEL", "masumtechnonext/wav2vec2-arabic-letter-verifier")
11
  HF_TOKEN = os.environ.get("HF_TOKEN")
12
+ SAMPLE_RATE = 16000
13
 
14
+ feature_extractor = Wav2Vec2FeatureExtractor.from_pretrained(MODEL_ID, token=HF_TOKEN)
15
+ model = Wav2Vec2ForSequenceClassification.from_pretrained(MODEL_ID, token=HF_TOKEN)
16
  model.eval()
17
 
18
+ id2label = {int(k): v for k, v in model.config.id2label.items()}
19
+ calibration_path = hf_hub_download(MODEL_ID, "calibration.json", token=HF_TOKEN)
20
+ with open(calibration_path) as f:
21
+ THRESHOLD = json.load(f)["confidence_threshold"]
22
+ UNKNOWN_ID = next(i for i, label in id2label.items() if label == "Unknown")
23
+ LETTERS = sorted(label for label in id2label.values() if label != "Unknown")
24
 
25
+
26
+ def predict(audio, target_letter):
27
  if audio is None:
28
+ return "Record or upload audio first.", ""
29
 
30
  sample_rate, waveform = audio
31
  waveform = torch.tensor(waveform, dtype=torch.float32)
32
  if waveform.ndim > 1:
33
  waveform = waveform.mean(dim=-1)
34
+ if sample_rate != SAMPLE_RATE:
35
+ waveform = torchaudio.functional.resample(waveform, sample_rate, SAMPLE_RATE)
36
 
37
+ inputs = feature_extractor(waveform.numpy(), sampling_rate=SAMPLE_RATE, return_tensors="pt")
 
 
 
 
 
38
 
39
  with torch.no_grad():
40
+ logits = model(**inputs).logits[0]
41
 
42
+ probs = torch.softmax(logits, dim=-1)
43
+ pred_id = int(torch.argmax(probs))
44
+ confidence = float(probs[pred_id])
45
 
46
+ accepted = confidence >= THRESHOLD and pred_id != UNKNOWN_ID
47
+ predicted_label = id2label[pred_id] if accepted else "Unrecognized"
48
+ prediction = f"{predicted_label} ({confidence:.1%} confidence)"
49
 
50
+ if not target_letter:
51
+ return prediction, "Pick an expected letter to verify."
 
 
52
 
53
+ is_correct = accepted and predicted_label == target_letter
54
+ verdict = "✅ Correct" if is_correct else "❌ Incorrect"
55
+ return prediction, verdict
56
 
57
 
58
  demo = gr.Interface(
59
+ fn=predict,
60
  inputs=[
61
  gr.Audio(sources=["microphone", "upload"], type="numpy", label="Speak the letter"),
62
+ gr.Dropdown(choices=LETTERS, label="Expected letter", value=None),
63
  ],
64
  outputs=[
65
+ gr.Textbox(label="Prediction"),
66
  gr.Textbox(label="Verification"),
67
  ],
68
  title="Arabic Letter Verifier",