singhalamaan116's picture
Create app.py
9dae807 verified
import gradio as gr
from transformers import pipeline
# -----------------------
# 1. Language + model config
# -----------------------
LANG_CODES = {
"English": "en",
"French": "fr",
"German": "de",
"Spanish": "es",
"Swedish": "sv",
}
# Map (src_lang_code, tgt_lang_code) -> MarianMT model
MODEL_MAP = {
("en", "fr"): "Helsinki-NLP/opus-mt-en-fr",
("fr", "en"): "Helsinki-NLP/opus-mt-fr-en",
("en", "de"): "Helsinki-NLP/opus-mt-en-de",
("de", "en"): "Helsinki-NLP/opus-mt-de-en",
("en", "es"): "Helsinki-NLP/opus-mt-en-es",
("es", "en"): "Helsinki-NLP/opus-mt-es-en",
("en", "sv"): "Helsinki-NLP/opus-mt-en-sv",
("sv", "en"): "Helsinki-NLP/opus-mt-sv-en",
}
# Lazy-loaded translation pipelines
_translation_pipelines = {}
# One small LLM for explanations / feedback
explain_llm = pipeline("text2text-generation", model="google/flan-t5-small")
def get_translation_pipeline(src_code: str, tgt_code: str):
"""
Returns a transformers pipeline for a given language pair, loading it lazily.
"""
key = (src_code, tgt_code)
if key not in MODEL_MAP:
raise ValueError(f"Language pair {src_code}->{tgt_code} not supported yet.")
if key not in _translation_pipelines:
model_name = MODEL_MAP[key]
task = f"translation_{src_code}_to_{tgt_code}"
_translation_pipelines[key] = pipeline(task, model=model_name)
return _translation_pipelines[key]
# -----------------------
# 2. Core translation logic
# -----------------------
def _apply_style_hints(text: str, tone: str, domain: str, tgt_lang: str) -> str:
"""
MarianMT isn't instruction-tuned, but we can still stuff a hint into the input.
It won't be perfect, but conceptually shows tone/domain-aware translation.
"""
hints = []
if domain != "General":
hints.append(f"{domain} context")
if tone != "Neutral":
hints.append(f"{tone} tone")
if hints:
hint_str = ", ".join(hints)
# Just prepend some natural-language hints in English.
styled = f"[{hint_str} in {tgt_lang}] {text}"
return styled
return text
def translate_text(text: str, src_lang: str, tgt_lang: str, tone: str, domain: str):
"""
Main translation function for the UI.
"""
text = (text or "").strip()
if not text:
return "Please enter some text to translate."
if src_lang == tgt_lang:
return text # trivial case
src_code = LANG_CODES[src_lang]
tgt_code = LANG_CODES[tgt_lang]
try:
translator = get_translation_pipeline(src_code, tgt_code)
except ValueError as e:
return str(e)
styled_input = _apply_style_hints(text, tone, domain, tgt_lang)
out = translator(styled_input, max_length=512)
translated = out[0]["translation_text"]
return translated.strip()
def back_translate(text: str, src_lang: str, tgt_lang: str, tone: str, domain: str):
"""
Translate from src -> tgt, then back tgt -> src to check meaning preservation.
"""
text = (text or "").strip()
if not text:
return "Please enter some text to translate.", ""
if src_lang == tgt_lang:
return text, text
# First translation: src -> tgt
forward = translate_text(text, src_lang, tgt_lang, tone, domain)
# Back translation: tgt -> src (no style hints on the way back)
backward = translate_text(forward, tgt_lang, src_lang, "Neutral", "General")
return forward, backward
def explain_translation(src_text: str, translated_text: str, src_lang: str, tgt_lang: str):
"""
Use Flan-T5 to explain the translation in simple terms.
"""
src_text = (src_text or "").strip()
translated_text = (translated_text or "").strip()
if not src_text or not translated_text:
return "Provide both the original text and the translation to get an explanation."
prompt = (
"You are a helpful language teacher. "
"Explain this translation to a learner in simple terms. "
"Mention important word choices, tone, and any interesting grammar.\n\n"
f"Source language: {src_lang}\n"
f"Target language: {tgt_lang}\n\n"
f"Original text:\n{src_text}\n\n"
f"Translation:\n{translated_text}\n\n"
"Explanation (in English, 1–2 short paragraphs):"
)
out = explain_llm(prompt, max_new_tokens=256, temperature=0.4)
return out[0]["generated_text"].strip()
def learning_mode_feedback(src_text: str, user_translation: str, src_lang: str, tgt_lang: str):
"""
Compare user's translation to model translation and give feedback.
"""
src_text = (src_text or "").strip()
user_translation = (user_translation or "").strip()
if not src_text or not user_translation:
return "Please provide both the original text and your translation."
# Model's best guess (neutral, general)
model_translation = translate_text(src_text, src_lang, tgt_lang, "Neutral", "General")
prompt = (
"You are a friendly language teacher. Compare the student's translation to the model translation. "
"Explain what is good, what could be improved, and give 2–4 concrete suggestions. "
"Be encouraging, not harsh.\n\n"
f"Source language: {src_lang}\n"
f"Target language: {tgt_lang}\n\n"
f"Original text:\n{src_text}\n\n"
f"Student's translation:\n{user_translation}\n\n"
f"Model's translation:\n{model_translation}\n\n"
"Feedback (in English, short and structured):"
)
out = explain_llm(prompt, max_new_tokens=320, temperature=0.4)
feedback = out[0]["generated_text"].strip()
return f"**Model translation:**\n\n{model_translation}\n\n---\n\n**Feedback:**\n\n{feedback}"
# -----------------------
# 3. Gradio UI
# -----------------------
LANG_CHOICES = list(LANG_CODES.keys())
TONES = ["Neutral", "Formal", "Informal", "Simplified"]
DOMAINS = ["General", "Business", "Technical", "Casual"]
with gr.Blocks(title="PolyglotLab – Smart Translator & Learning Studio") as demo:
gr.Markdown(
"""
# 🌈 PolyglotLab – Smart Translator & Learning Studio
A translation playground built with Hugging Face + Gradio.
- ✨ Multi-language translation (English, French, German, Spanish, Swedish)
- 🎭 Tone hints (neutral, formal, informal, simplified)
- 🧩 Domain hints (business, technical, casual)
- 🔁 Back-translation checks for meaning
- 📚 Learning mode with feedback on *your* translations
"""
)
with gr.Tab("Smart Translate"):
with gr.Row():
src_lang_in = gr.Dropdown(LANG_CHOICES, value="English", label="Source language")
tgt_lang_in = gr.Dropdown(LANG_CHOICES, value="French", label="Target language")
text_in = gr.Textbox(
label="Text to translate",
lines=4,
placeholder="Type or paste text here...",
)
with gr.Row():
tone_in = gr.Dropdown(TONES, value="Neutral", label="Tone hint")
domain_in = gr.Dropdown(DOMAINS, value="General", label="Domain / context")
explain_checkbox = gr.Checkbox(value=True, label="Explain the translation")
translate_btn = gr.Button("Translate ✨")
translated_out = gr.Textbox(label="Translation", lines=4)
explanation_out = gr.Markdown(label="Explanation")
def translate_and_explain(text, src, tgt, tone, domain, do_explain):
translation = translate_text(text, src, tgt, tone, domain)
if not do_explain:
return translation, ""
exp = explain_translation(text, translation, src, tgt)
return translation, exp
translate_btn.click(
fn=translate_and_explain,
inputs=[text_in, src_lang_in, tgt_lang_in, tone_in, domain_in, explain_checkbox],
outputs=[translated_out, explanation_out],
)
with gr.Tab("Back-translation Check"):
gr.Markdown(
"Translate from source to target, then back to source to see if the meaning is preserved."
)
bt_src_lang = gr.Dropdown(LANG_CHOICES, value="English", label="Source language")
bt_tgt_lang = gr.Dropdown(LANG_CHOICES, value="German", label="Target language")
bt_text_in = gr.Textbox(
label="Original text",
lines=4,
placeholder="Type a sentence to test...",
)
bt_tone_in = gr.Dropdown(TONES, value="Neutral", label="Tone hint")
bt_domain_in = gr.Dropdown(DOMAINS, value="General", label="Domain / context")
bt_btn = gr.Button("Run Back-translation 🔁")
bt_forward_out = gr.Textbox(label="Forward translation (src → tgt)", lines=4)
bt_backward_out = gr.Textbox(label="Back-translation (tgt → src)", lines=4)
bt_btn.click(
fn=back_translate,
inputs=[bt_text_in, bt_src_lang, bt_tgt_lang, bt_tone_in, bt_domain_in],
outputs=[bt_forward_out, bt_backward_out],
)
with gr.Tab("Learning Mode"):
gr.Markdown(
"""
Paste a sentence and your own translation.
The model will show its translation and give you friendly feedback.
"""
)
lm_src_lang = gr.Dropdown(LANG_CHOICES, value="English", label="Source language")
lm_tgt_lang = gr.Dropdown(LANG_CHOICES, value="French", label="Target language")
lm_src_text = gr.Textbox(
label="Original text",
lines=4,
placeholder="Enter a sentence in the source language...",
)
lm_user_translation = gr.Textbox(
label="Your translation",
lines=4,
placeholder="Write your translation here...",
)
lm_btn = gr.Button("Get feedback 🧑‍🏫")
lm_feedback_out = gr.Markdown(label="Feedback")
lm_btn.click(
fn=learning_mode_feedback,
inputs=[lm_src_text, lm_user_translation, lm_src_lang, lm_tgt_lang],
outputs=lm_feedback_out,
)
if __name__ == "__main__":
demo.launch()