BurhaanZargar commited on
Commit
079cf4d
Β·
1 Parent(s): 85071eb
Files changed (1) hide show
  1. app.py +69 -137
app.py CHANGED
@@ -8,14 +8,9 @@ import tempfile
8
  from gtts import gTTS
9
  import os
10
 
11
- # Device configuration
12
  DEVICE = "cuda" if torch.cuda.is_available() else "cpu"
13
 
14
- # Supabase configuration
15
- SUPABASE_URL = "https://gptmdbhzblfybdnohqnh.supabase.co"
16
- SUPABASE_API_KEY = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
17
-
18
- # Load translation models
19
  model_en_to_indic = AutoModelForSeq2SeqLM.from_pretrained("ai4bharat/indictrans2-en-indic-1B", trust_remote_code=True).to(DEVICE)
20
  tokenizer_en_to_indic = AutoTokenizer.from_pretrained("ai4bharat/indictrans2-en-indic-1B", trust_remote_code=True)
21
  model_indic_to_en = AutoModelForSeq2SeqLM.from_pretrained("ai4bharat/indictrans2-indic-en-1B", trust_remote_code=True).to(DEVICE)
@@ -24,18 +19,21 @@ tokenizer_indic_to_en = AutoTokenizer.from_pretrained("ai4bharat/indictrans2-ind
24
  ip = IndicProcessor(inference=True)
25
  asr = pipeline("automatic-speech-recognition", model="openai/whisper-small")
26
 
 
 
 
27
 
 
28
  def save_to_supabase(input_text, output_text, direction):
29
  if not input_text.strip() or not output_text.strip():
30
  return "Nothing to save."
31
 
32
- table_name = "translations" if direction == "en_to_ks" else "ks_to_en_translations"
33
  payload = {
34
  "timestamp": datetime.utcnow().isoformat(),
35
  "input_text": input_text,
36
  "output_text": output_text
37
  }
38
-
39
  headers = {
40
  "apikey": SUPABASE_API_KEY,
41
  "Authorization": f"Bearer {SUPABASE_API_KEY}",
@@ -43,185 +41,119 @@ def save_to_supabase(input_text, output_text, direction):
43
  }
44
 
45
  try:
46
- response = requests.post(
47
- f"{SUPABASE_URL}/rest/v1/{table_name}",
48
- headers=headers,
49
- json=payload,
50
- timeout=10
51
- )
52
  return "βœ… Saved successfully!" if response.status_code == 201 else "❌ Failed to save."
53
  except Exception as e:
54
- print("SAVE EXCEPTION:", e)
55
- return "❌ Save request error."
56
-
57
-
58
- def get_translation_history(direction="en_to_ks"):
59
- table_name = "translations" if direction == "en_to_ks" else "ks_to_en_translations"
60
 
 
 
61
  headers = {
62
  "apikey": SUPABASE_API_KEY,
63
  "Authorization": f"Bearer {SUPABASE_API_KEY}"
64
  }
65
 
66
  try:
67
- response = requests.get(
68
- f"{SUPABASE_URL}/rest/v1/{table_name}?order=timestamp.desc&limit=10",
69
- headers=headers,
70
- timeout=10
71
- )
72
- if response.status_code == 200:
73
- records = response.json()
74
- return "\n\n".join(
75
- [f"Input: {r['input_text']} β†’ Output: {r['output_text']}" for r in records]
76
- )
77
  return "Failed to load history."
78
  except Exception as e:
79
- print("HISTORY FETCH ERROR:", e)
80
  return "Error loading history."
81
 
82
-
83
  def translate(text, direction):
84
  if not text.strip():
85
- return "Please enter some text.", gr.update(), gr.update()
86
 
87
  if direction == "en_to_ks":
88
- src_lang = "eng_Latn"
89
- tgt_lang = "kas_Arab"
90
- model = model_en_to_indic
91
- tokenizer = tokenizer_en_to_indic
92
  else:
93
- src_lang = "kas_Arab"
94
- tgt_lang = "eng_Latn"
95
- model = model_indic_to_en
96
- tokenizer = tokenizer_indic_to_en
97
 
98
  try:
99
- processed = ip.preprocess_batch([text], src_lang=src_lang, tgt_lang=tgt_lang)
100
- batch = tokenizer(processed, return_tensors="pt", padding=True).to(DEVICE)
101
-
102
  with torch.no_grad():
103
- outputs = model.generate(
104
- **batch,
105
- max_length=256,
106
- num_beams=5,
107
- num_return_sequences=1
108
- )
109
-
110
- translated = tokenizer.batch_decode(outputs, skip_special_tokens=True)
111
- result = ip.postprocess_batch(translated, lang=tgt_lang)[0]
112
-
113
- return result, gr.update(), gr.update()
114
  except Exception as e:
115
- print("Translation Error:", e)
116
  return "⚠️ Translation failed.", gr.update(), gr.update()
117
 
118
-
119
- def transcribe_audio(audio_path):
120
  try:
121
- result = asr(audio_path)
122
- return result["text"]
 
 
123
  except Exception as e:
124
- print("STT Error:", e)
125
- return "⚠️ Transcription failed."
126
 
 
 
 
 
127
 
128
- def synthesize_tts(text, direction):
129
- if direction == "ks_to_en" and text.strip():
130
- try:
131
- tts = gTTS(text=text, lang="en")
132
- tmp_file = tempfile.NamedTemporaryFile(delete=False, suffix=".mp3")
133
- tts.save(tmp_file.name)
134
- tmp_file.close()
135
- return tmp_file.name
136
- except Exception as e:
137
- print("TTS Error:", e)
138
- return None
139
 
 
 
140
 
 
141
  def switch_direction(direction, input_text_val, output_text_val):
142
  new_direction = "ks_to_en" if direction == "en_to_ks" else "en_to_ks"
143
  input_label = "Kashmiri Text" if new_direction == "ks_to_en" else "English Text"
144
  output_label = "English Translation" if new_direction == "ks_to_en" else "Kashmiri Translation"
145
- return (
146
- new_direction,
147
- gr.update(value=output_text_val, label=input_label),
148
- gr.update(value=input_text_val, label=output_label)
149
- )
150
-
151
-
152
- def handle_audio_translation(audio_path, direction):
153
- if direction == "en_to_ks":
154
- transcription = transcribe_audio(audio_path)
155
- if transcription.startswith("⚠️"):
156
- return transcription, "", "", None
157
- translation, _, _ = translate(transcription, direction)
158
- return transcription, translation, transcription, None
159
- else:
160
- # Assume audio_path is not used; rely on text in the input box
161
- transcription = transcribe_audio(audio_path)
162
- translation, _, _ = translate(transcription, direction)
163
- tts_audio = synthesize_tts(translation, direction)
164
- return transcription, translation, transcription, tts_audio
165
-
166
 
167
  # === Gradio Interface ===
168
  with gr.Blocks() as interface:
169
- gr.HTML("""
170
- <div style="display: flex; justify-content: space-between; align-items: center; padding: 10px;">
171
- <img src="https://raw.githubusercontent.com/BurhaanRasheedZargar/Images/211321a234613a9c3dd944fe9367cf13d1386239/assets/left_logo.png" style="height:150px; width:auto;">
172
- <h2 style="margin: 0; text-align: center;">English ↔ Kashmiri Translator</h2>
173
- <img src="https://raw.githubusercontent.com/BurhaanRasheedZargar/Images/77797f7f7cbee328fa0f9d31cf3e290441e04cd3/assets/right_logo.png">
174
- </div>
175
- """)
176
-
177
  translation_direction = gr.State(value="en_to_ks")
178
 
179
  with gr.Row():
180
- input_text = gr.Textbox(lines=2, label="English Text", placeholder="Enter text....")
181
- output_text = gr.Textbox(lines=2, label="Kashmiri Translation", placeholder="Translated text....")
182
 
183
  with gr.Row():
184
  translate_button = gr.Button("Translate")
185
  save_button = gr.Button("Save Translation")
186
- switch_button = gr.Button("Switch")
187
 
188
  save_status = gr.Textbox(label="Save Status", interactive=False)
189
- history_box = gr.Textbox(lines=10, label="Translation History", interactive=False)
190
 
191
  with gr.Row():
192
- audio_input = gr.Audio(type="filepath", label="πŸŽ™οΈ Upload or record English audio")
193
- audio_output = gr.Audio(label="πŸ”Š English Output Audio")
194
 
195
- stt_translate_button = gr.Button("🎀 Transcribe & Translate")
196
 
197
  # Events
198
- translate_button.click(
199
- fn=translate,
200
- inputs=[input_text, translation_direction],
201
- outputs=[output_text, input_text, output_text]
202
- )
203
-
204
- save_button.click(
205
- fn=save_to_supabase,
206
- inputs=[input_text, output_text, translation_direction],
207
- outputs=save_status
208
- ).then(
209
- fn=get_translation_history,
210
- inputs=translation_direction,
211
- outputs=history_box
212
- )
213
-
214
- switch_button.click(
215
- fn=switch_direction,
216
- inputs=[translation_direction, input_text, output_text],
217
- outputs=[translation_direction, input_text, output_text]
218
- )
219
-
220
- stt_translate_button.click(
221
- fn=handle_audio_translation,
222
- inputs=[audio_input, translation_direction],
223
- outputs=[input_text, output_text, input_text, audio_output]
224
- )
225
 
226
  if __name__ == "__main__":
227
- interface.queue().launch(share=True)
 
8
  from gtts import gTTS
9
  import os
10
 
 
11
  DEVICE = "cuda" if torch.cuda.is_available() else "cpu"
12
 
13
+ # Load models
 
 
 
 
14
  model_en_to_indic = AutoModelForSeq2SeqLM.from_pretrained("ai4bharat/indictrans2-en-indic-1B", trust_remote_code=True).to(DEVICE)
15
  tokenizer_en_to_indic = AutoTokenizer.from_pretrained("ai4bharat/indictrans2-en-indic-1B", trust_remote_code=True)
16
  model_indic_to_en = AutoModelForSeq2SeqLM.from_pretrained("ai4bharat/indictrans2-indic-en-1B", trust_remote_code=True).to(DEVICE)
 
19
  ip = IndicProcessor(inference=True)
20
  asr = pipeline("automatic-speech-recognition", model="openai/whisper-small")
21
 
22
+ # --- Supabase settings ---
23
+ SUPABASE_URL = "https://gptmdbhzblfybdnohqnh.supabase.co"
24
+ SUPABASE_API_KEY = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
25
 
26
+ # --- Supabase utilities ---
27
  def save_to_supabase(input_text, output_text, direction):
28
  if not input_text.strip() or not output_text.strip():
29
  return "Nothing to save."
30
 
31
+ table = "translations" if direction == "en_to_ks" else "ks_to_en_translations"
32
  payload = {
33
  "timestamp": datetime.utcnow().isoformat(),
34
  "input_text": input_text,
35
  "output_text": output_text
36
  }
 
37
  headers = {
38
  "apikey": SUPABASE_API_KEY,
39
  "Authorization": f"Bearer {SUPABASE_API_KEY}",
 
41
  }
42
 
43
  try:
44
+ response = requests.post(f"{SUPABASE_URL}/rest/v1/{table}", json=payload, headers=headers)
 
 
 
 
 
45
  return "βœ… Saved successfully!" if response.status_code == 201 else "❌ Failed to save."
46
  except Exception as e:
47
+ print("Save error:", e)
48
+ return "❌ Save error."
 
 
 
 
49
 
50
+ def get_translation_history(direction):
51
+ table = "translations" if direction == "en_to_ks" else "ks_to_en_translations"
52
  headers = {
53
  "apikey": SUPABASE_API_KEY,
54
  "Authorization": f"Bearer {SUPABASE_API_KEY}"
55
  }
56
 
57
  try:
58
+ res = requests.get(f"{SUPABASE_URL}/rest/v1/{table}?order=timestamp.desc&limit=10", headers=headers)
59
+ if res.status_code == 200:
60
+ data = res.json()
61
+ return "\n\n".join([f"Input: {r['input_text']} β†’ Output: {r['output_text']}" for r in data])
 
 
 
 
 
 
62
  return "Failed to load history."
63
  except Exception as e:
64
+ print("History error:", e)
65
  return "Error loading history."
66
 
67
+ # --- Translation ---
68
  def translate(text, direction):
69
  if not text.strip():
70
+ return "Enter some text.", gr.update(), gr.update()
71
 
72
  if direction == "en_to_ks":
73
+ src_lang, tgt_lang = "eng_Latn", "kas_Arab"
74
+ model, tokenizer = model_en_to_indic, tokenizer_en_to_indic
 
 
75
  else:
76
+ src_lang, tgt_lang = "kas_Arab", "eng_Latn"
77
+ model, tokenizer = model_indic_to_en, tokenizer_indic_to_en
 
 
78
 
79
  try:
80
+ batch = ip.preprocess_batch([text], src_lang=src_lang, tgt_lang=tgt_lang)
81
+ tokens = tokenizer(batch, return_tensors="pt", padding=True).to(DEVICE)
 
82
  with torch.no_grad():
83
+ output = model.generate(**tokens, max_length=256, num_beams=5)
84
+ result = tokenizer.batch_decode(output, skip_special_tokens=True)
85
+ final = ip.postprocess_batch(result, lang=tgt_lang)[0]
86
+ return final, gr.update(), gr.update()
 
 
 
 
 
 
 
87
  except Exception as e:
88
+ print("Translation error:", e)
89
  return "⚠️ Translation failed.", gr.update(), gr.update()
90
 
91
+ # --- TTS for English output only ---
92
+ def synthesize_tts(text):
93
  try:
94
+ tts = gTTS(text=text, lang="en")
95
+ with tempfile.NamedTemporaryFile(delete=False, suffix=".mp3") as f:
96
+ tts.save(f.name)
97
+ return f.name
98
  except Exception as e:
99
+ print("TTS error:", e)
100
+ return None
101
 
102
+ # --- STT only for en_to_ks ---
103
+ def handle_audio_translation(audio_path, direction):
104
+ if direction != "en_to_ks":
105
+ return "⚠️ Audio input is only supported for English to Kashmiri.", "", "", None
106
 
107
+ try:
108
+ transcription = asr(audio_path)["text"]
109
+ except Exception as e:
110
+ print("STT error:", e)
111
+ return "⚠️ Transcription failed.", "", "", None
 
 
 
 
 
 
112
 
113
+ translated, _, _ = translate(transcription, direction)
114
+ return transcription, translated, transcription, None
115
 
116
+ # --- Switch UI direction ---
117
  def switch_direction(direction, input_text_val, output_text_val):
118
  new_direction = "ks_to_en" if direction == "en_to_ks" else "en_to_ks"
119
  input_label = "Kashmiri Text" if new_direction == "ks_to_en" else "English Text"
120
  output_label = "English Translation" if new_direction == "ks_to_en" else "Kashmiri Translation"
121
+ return new_direction, gr.update(value=output_text_val, label=input_label), gr.update(value=input_text_val, label=output_label)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
122
 
123
  # === Gradio Interface ===
124
  with gr.Blocks() as interface:
125
+ gr.HTML("<h2 style='text-align:center;'>English ↔ Kashmiri Translator</h2>")
 
 
 
 
 
 
 
126
  translation_direction = gr.State(value="en_to_ks")
127
 
128
  with gr.Row():
129
+ input_text = gr.Textbox(label="English Text", placeholder="Enter text here...")
130
+ output_text = gr.Textbox(label="Kashmiri Translation", placeholder="Translated text...")
131
 
132
  with gr.Row():
133
  translate_button = gr.Button("Translate")
134
  save_button = gr.Button("Save Translation")
135
+ switch_button = gr.Button("Switch Direction")
136
 
137
  save_status = gr.Textbox(label="Save Status", interactive=False)
138
+ history = gr.Textbox(label="Translation History", lines=8, interactive=False)
139
 
140
  with gr.Row():
141
+ audio_input = gr.Audio(type="filepath", label="πŸŽ™οΈ Record English audio")
142
+ audio_output = gr.Audio(label="πŸ”Š English TTS")
143
 
144
+ stt_button = gr.Button("🎀 Transcribe & Translate (EN β†’ KS Only)")
145
 
146
  # Events
147
+ translate_button.click(fn=translate, inputs=[input_text, translation_direction], outputs=[output_text, input_text, output_text])
148
+
149
+ save_button.click(fn=save_to_supabase, inputs=[input_text, output_text, translation_direction], outputs=save_status)\
150
+ .then(fn=get_translation_history, inputs=translation_direction, outputs=history)
151
+
152
+ switch_button.click(fn=switch_direction, inputs=[translation_direction, input_text, output_text],
153
+ outputs=[translation_direction, input_text, output_text])
154
+
155
+ stt_button.click(fn=handle_audio_translation, inputs=[audio_input, translation_direction],
156
+ outputs=[input_text, output_text, input_text, audio_output])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
157
 
158
  if __name__ == "__main__":
159
+ interface.queue().launch()