innocentpeter commited on
Commit
924f487
·
verified ·
1 Parent(s): 9ddbcda

Upload 11 files

Browse files
Files changed (11) hide show
  1. .gitattributes +35 -35
  2. README.md +14 -14
  3. app.py +40 -0
  4. assistant.py +38 -0
  5. config.yaml +9 -0
  6. main.py +0 -0
  7. requirements.txt +0 -0
  8. speech_input.py +15 -0
  9. translation.py +81 -0
  10. tts_engine.py +31 -0
  11. utils.py +0 -0
.gitattributes CHANGED
@@ -1,35 +1,35 @@
1
- *.7z filter=lfs diff=lfs merge=lfs -text
2
- *.arrow filter=lfs diff=lfs merge=lfs -text
3
- *.bin filter=lfs diff=lfs merge=lfs -text
4
- *.bz2 filter=lfs diff=lfs merge=lfs -text
5
- *.ckpt filter=lfs diff=lfs merge=lfs -text
6
- *.ftz filter=lfs diff=lfs merge=lfs -text
7
- *.gz filter=lfs diff=lfs merge=lfs -text
8
- *.h5 filter=lfs diff=lfs merge=lfs -text
9
- *.joblib filter=lfs diff=lfs merge=lfs -text
10
- *.lfs.* filter=lfs diff=lfs merge=lfs -text
11
- *.mlmodel filter=lfs diff=lfs merge=lfs -text
12
- *.model filter=lfs diff=lfs merge=lfs -text
13
- *.msgpack filter=lfs diff=lfs merge=lfs -text
14
- *.npy filter=lfs diff=lfs merge=lfs -text
15
- *.npz filter=lfs diff=lfs merge=lfs -text
16
- *.onnx filter=lfs diff=lfs merge=lfs -text
17
- *.ot filter=lfs diff=lfs merge=lfs -text
18
- *.parquet filter=lfs diff=lfs merge=lfs -text
19
- *.pb filter=lfs diff=lfs merge=lfs -text
20
- *.pickle filter=lfs diff=lfs merge=lfs -text
21
- *.pkl filter=lfs diff=lfs merge=lfs -text
22
- *.pt filter=lfs diff=lfs merge=lfs -text
23
- *.pth filter=lfs diff=lfs merge=lfs -text
24
- *.rar filter=lfs diff=lfs merge=lfs -text
25
- *.safetensors filter=lfs diff=lfs merge=lfs -text
26
- saved_model/**/* filter=lfs diff=lfs merge=lfs -text
27
- *.tar.* filter=lfs diff=lfs merge=lfs -text
28
- *.tar filter=lfs diff=lfs merge=lfs -text
29
- *.tflite filter=lfs diff=lfs merge=lfs -text
30
- *.tgz filter=lfs diff=lfs merge=lfs -text
31
- *.wasm filter=lfs diff=lfs merge=lfs -text
32
- *.xz filter=lfs diff=lfs merge=lfs -text
33
- *.zip filter=lfs diff=lfs merge=lfs -text
34
- *.zst filter=lfs diff=lfs merge=lfs -text
35
- *tfevents* filter=lfs diff=lfs merge=lfs -text
 
1
+ *.7z filter=lfs diff=lfs merge=lfs -text
2
+ *.arrow filter=lfs diff=lfs merge=lfs -text
3
+ *.bin filter=lfs diff=lfs merge=lfs -text
4
+ *.bz2 filter=lfs diff=lfs merge=lfs -text
5
+ *.ckpt filter=lfs diff=lfs merge=lfs -text
6
+ *.ftz filter=lfs diff=lfs merge=lfs -text
7
+ *.gz filter=lfs diff=lfs merge=lfs -text
8
+ *.h5 filter=lfs diff=lfs merge=lfs -text
9
+ *.joblib filter=lfs diff=lfs merge=lfs -text
10
+ *.lfs.* filter=lfs diff=lfs merge=lfs -text
11
+ *.mlmodel filter=lfs diff=lfs merge=lfs -text
12
+ *.model filter=lfs diff=lfs merge=lfs -text
13
+ *.msgpack filter=lfs diff=lfs merge=lfs -text
14
+ *.npy filter=lfs diff=lfs merge=lfs -text
15
+ *.npz filter=lfs diff=lfs merge=lfs -text
16
+ *.onnx filter=lfs diff=lfs merge=lfs -text
17
+ *.ot filter=lfs diff=lfs merge=lfs -text
18
+ *.parquet filter=lfs diff=lfs merge=lfs -text
19
+ *.pb filter=lfs diff=lfs merge=lfs -text
20
+ *.pickle filter=lfs diff=lfs merge=lfs -text
21
+ *.pkl filter=lfs diff=lfs merge=lfs -text
22
+ *.pt filter=lfs diff=lfs merge=lfs -text
23
+ *.pth filter=lfs diff=lfs merge=lfs -text
24
+ *.rar filter=lfs diff=lfs merge=lfs -text
25
+ *.safetensors filter=lfs diff=lfs merge=lfs -text
26
+ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
27
+ *.tar.* filter=lfs diff=lfs merge=lfs -text
28
+ *.tar filter=lfs diff=lfs merge=lfs -text
29
+ *.tflite filter=lfs diff=lfs merge=lfs -text
30
+ *.tgz filter=lfs diff=lfs merge=lfs -text
31
+ *.wasm filter=lfs diff=lfs merge=lfs -text
32
+ *.xz filter=lfs diff=lfs merge=lfs -text
33
+ *.zip filter=lfs diff=lfs merge=lfs -text
34
+ *.zst filter=lfs diff=lfs merge=lfs -text
35
+ *tfevents* filter=lfs diff=lfs merge=lfs -text
README.md CHANGED
@@ -1,14 +1,14 @@
1
- ---
2
- title: TalkAI
3
- emoji: 🚀
4
- colorFrom: purple
5
- colorTo: indigo
6
- sdk: gradio
7
- sdk_version: 5.47.2
8
- app_file: app.py
9
- pinned: false
10
- license: mit
11
- short_description: Translation
12
- ---
13
-
14
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
+ ---
2
+ title: TalkAI
3
+ emoji: 🚀
4
+ colorFrom: purple
5
+ colorTo: indigo
6
+ sdk: gradio
7
+ sdk_version: 5.47.2
8
+ app_file: app.py
9
+ pinned: false
10
+ license: mit
11
+ short_description: Translation
12
+ ---
13
+
14
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
app.py ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ from translator import Translator, CONFIG
3
+ from tts_engine import TTSEngine
4
+
5
+ translator = Translator(n2n_enabled=CONFIG["features"]["nigerian_to_nigerian_enabled"])
6
+ tts_engine = TTSEngine(use_coqui=False) # default: pyttsx3
7
+
8
+ def translate_and_speak(input_text, input_lang, output_lang, use_coqui, clone_voice):
9
+ # Translate
10
+ translated = translator.translate(input_text, input_lang, output_lang)
11
+
12
+ # TTS
13
+ tts_engine.use_coqui = use_coqui
14
+ audio_path = tts_engine.speak(translated, lang=output_lang, voice_clone=clone_voice)
15
+
16
+ return translated, audio_path
17
+
18
+
19
+ with gr.Blocks() as demo:
20
+ gr.Markdown("## 🌍 Nigerian Voice Translator Assistant")
21
+
22
+ with gr.Row():
23
+ input_lang = gr.Dropdown(choices=["yoruba","hausa","igbo","pidgin","esan","tiv","calabar","benin"], value="yoruba", label="Input Language")
24
+ output_lang = gr.Dropdown(choices=["english","yoruba","hausa","igbo","pidgin","esan","tiv","calabar","benin"], value="english", label="Output Language")
25
+
26
+ input_text = gr.Textbox(label="Enter text")
27
+ use_coqui = gr.Checkbox(label="Use Coqui TTS (natural accents)", value=False)
28
+ clone_voice = gr.Checkbox(label="Clone my voice if available", value=False)
29
+
30
+ translate_btn = gr.Button("Translate & Speak")
31
+ output_text = gr.Textbox(label="Translation")
32
+ output_audio = gr.Audio(label="Spoken Output", type="filepath")
33
+
34
+ translate_btn.click(
35
+ fn=translate_and_speak,
36
+ inputs=[input_text, input_lang, output_lang, use_coqui, clone_voice],
37
+ outputs=[output_text, output_audio]
38
+ )
39
+
40
+ demo.launch()
assistant.py ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import yaml
2
+ from translation import Translator
3
+ from tts_engine import TTSManager
4
+ from speech_input import SpeechInput
5
+
6
+ class VoiceTranslatorAssistant:
7
+ def __init__(self, config_file="config.yaml"):
8
+ with open(config_file, "r", encoding="utf-8") as f:
9
+ config = yaml.safe_load(f)
10
+
11
+ self.lang_a = config.get("default_language", "yoruba").lower()
12
+ self.lang_b = config.get("output_language", "english").lower()
13
+ self.n2n_enabled = config.get("features", {}).get("nigerian_to_nigerian_enabled", False)
14
+
15
+ self.translator = Translator(n2n_enabled=self.n2n_enabled)
16
+ self.tts = TTSManager(engine=config["speech"]["engine"], rate=config["speech"]["rate"], volume=config["speech"]["volume"])
17
+ self.speech = SpeechInput()
18
+
19
+ def run(self):
20
+ print(f"🌍 Two-Way Translator: {self.lang_a.upper()} ↔ {self.lang_b.upper()}")
21
+ while True:
22
+ # Speaker A
23
+ text_a = self.speech.listen(f"{self.lang_a.upper()} (Speaker A)")
24
+ if not text_a or text_a.lower() in ["quit", "exit", "stop"]:
25
+ break
26
+ trans_a = self.translator.translate(text_a, self.lang_a, self.lang_b)
27
+ print(f"👤 A said: {text_a}\n➡️ {trans_a}")
28
+ self.tts.speak(trans_a, lang=self.lang_b, speaker="B")
29
+
30
+ # Speaker B
31
+ text_b = self.speech.listen(f"{self.lang_b.upper()} (Speaker B)")
32
+ if not text_b or text_b.lower() in ["quit", "exit", "stop"]:
33
+ break
34
+ trans_b = self.translator.translate(text_b, self.lang_b, self.lang_a)
35
+ print(f"👤 B said: {text_b}\n➡️ {trans_b}")
36
+ self.tts.speak(trans_b, lang=self.lang_a, speaker="A")
37
+
38
+ print("👋 Session ended.")
config.yaml ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ default_language: hausa
2
+ output_language: english
3
+
4
+ features:
5
+ nigerian_to_nigerian_enabled: true
6
+
7
+ speech:
8
+ rate: 150
9
+ volume: 1.0
main.py ADDED
File without changes
requirements.txt ADDED
File without changes
speech_input.py ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import speech_recognition as sr
2
+
3
+ class SpeechInput:
4
+ def __init__(self):
5
+ self.recognizer = sr.Recognizer()
6
+
7
+ def listen(self, prompt="Speak/Type now..."):
8
+ print(f"\n[{prompt}] 🎙️ Listening...")
9
+ try:
10
+ with sr.Microphone() as source:
11
+ audio = self.recognizer.listen(source, timeout=5, phrase_time_limit=10)
12
+ return self.recognizer.recognize_google(audio)
13
+ except Exception:
14
+ # fallback: manual typing
15
+ return input(f"[{prompt}] (typing fallback): ")
translation.py ADDED
@@ -0,0 +1,81 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import yaml
2
+ from transformers import MarianMTModel, MarianTokenizer
3
+
4
+ # ---------------- Load config ----------------
5
+ CONFIG_FILE = "config.yaml"
6
+
7
+ def load_config():
8
+ with open(CONFIG_FILE, "r", encoding="utf-8") as f:
9
+ return yaml.safe_load(f)
10
+
11
+ CONFIG = load_config()
12
+
13
+ # ---------------- Marian models ----------------
14
+ MARIAN_MODELS = {
15
+ "yoruba": {
16
+ "to_en": "Helsinki-NLP/opus-mt-yo-en",
17
+ "to_lang": "Helsinki-NLP/opus-mt-en-yo"
18
+ },
19
+ "hausa": {
20
+ "to_en": "Helsinki-NLP/opus-mt-ha-en",
21
+ "to_lang": "Helsinki-NLP/opus-mt-en-ha"
22
+ },
23
+ "igbo": {
24
+ "to_en": "Helsinki-NLP/opus-mt-ig-en",
25
+ "to_lang": "Helsinki-NLP/opus-mt-en-ig"
26
+ },
27
+ "pidgin": {
28
+ "to_en": "Helsinki-NLP/opus-mt-pcm-en",
29
+ "to_lang": "Helsinki-NLP/opus-mt-en-pcm"
30
+ },
31
+ }
32
+
33
+ # ---------------- Fallback dictionary ----------------
34
+ CUSTOM_DICT = {
35
+ "esan": {"Koyo": "Greetings", "Wa gié": "Come here"},
36
+ "tiv": {"M sugh u": "Good morning", "M gbee": "I am fine"},
37
+ "calabar": {"Nsidibe": "Welcome", "Abadie": "How are you?"},
38
+ "benin": {"Oba gha to kpere": "Long live the king", "Koyo": "Greetings"},
39
+ "pidgin": {
40
+ "How far": "How are you?",
41
+ "Wetin dey happen": "What’s going on?",
42
+ "Omo": "Kid / person (informal)",
43
+ },
44
+ }
45
+
46
+
47
+ class Translator:
48
+ def __init__(self, n2n_enabled=False):
49
+ self.n2n_enabled = n2n_enabled
50
+
51
+ def translate_with_marian(self, model_name, text):
52
+ tokenizer = MarianTokenizer.from_pretrained(model_name)
53
+ model = MarianMTModel.from_pretrained(model_name)
54
+ inputs = tokenizer(text, return_tensors="pt")
55
+ translated = model.generate(**inputs)
56
+ return tokenizer.decode(translated[0], skip_special_tokens=True)
57
+
58
+ def translate(self, text, input_lang, output_lang):
59
+ if not text.strip():
60
+ return ""
61
+
62
+ # ---- Marian supported ----
63
+ if input_lang in MARIAN_MODELS:
64
+ if output_lang == "english":
65
+ return self.translate_with_marian(MARIAN_MODELS[input_lang]["to_en"], text)
66
+ elif output_lang == input_lang:
67
+ return text
68
+ elif output_lang in MARIAN_MODELS:
69
+ if self.n2n_enabled:
70
+ en_text = self.translate_with_marian(MARIAN_MODELS[input_lang]["to_en"], text)
71
+ return self.translate_with_marian(MARIAN_MODELS[output_lang]["to_lang"], en_text)
72
+ else:
73
+ return f"(🚧 Nigerian↔Nigerian to {output_lang} not enabled)"
74
+ # ---- Dictionary fallback ----
75
+ else:
76
+ if output_lang == "english":
77
+ return CUSTOM_DICT.get(input_lang, {}).get(text, text)
78
+ elif output_lang == input_lang:
79
+ return text
80
+ else:
81
+ return f"(⚠️ Dictionary doesn't support {input_lang}→{output_lang})"
tts_engine.py ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import pyttsx3
3
+ from TTS.api import TTS
4
+
5
+ class TTSEngine:
6
+ def __init__(self, use_coqui=False):
7
+ self.use_coqui = use_coqui
8
+ if self.use_coqui:
9
+ # Multilingual model (supports Yoruba/Hausa/Igbo accents)
10
+ self.tts = TTS("tts_models/multilingual/multi-dataset/your_tts", progress_bar=False, gpu=False)
11
+
12
+ def speak(self, text, lang="english", voice_clone=False):
13
+ """
14
+ Returns path to generated audio file (for Gradio playback).
15
+ """
16
+ if not text:
17
+ return None
18
+
19
+ out_file = "output.wav"
20
+
21
+ if self.use_coqui:
22
+ if voice_clone and os.path.exists("my_voice.wav"):
23
+ self.tts.tts_to_file(text=text, file_path=out_file, speaker_wav="my_voice.wav", language=lang)
24
+ else:
25
+ self.tts.tts_to_file(text=text, file_path=out_file, language=lang)
26
+ else:
27
+ engine = pyttsx3.init()
28
+ engine.save_to_file(text, out_file)
29
+ engine.runAndWait()
30
+
31
+ return out_file
utils.py ADDED
File without changes