github-actions[bot] commited on
Commit
c341525
·
0 Parent(s):

Sync from GitHub (HuggingFaceIntegerations)

Browse files
Files changed (5) hide show
  1. Makefile +30 -0
  2. README.md +39 -0
  3. app.py +152 -0
  4. requirements.txt +10 -0
  5. test_app.py +69 -0
Makefile ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .PHONY: install test debug one-test format format-check lint all
2
+
3
+ install:
4
+ python -m pip install --upgrade pip
5
+ python -m pip install -r requirements.txt
6
+
7
+ test:
8
+ python -m pytest -vv \
9
+ --cov=app \
10
+ --cov-report=term-missing \
11
+ --cov-fail-under=80
12
+
13
+ debug:
14
+ python -m pytest -vv -x
15
+
16
+ # Run a single test by node id (file::test_name)
17
+ # Usage: make one-test T=test_app.py::test_hi_to_en_uses_hi_en_pipe
18
+ one-test:
19
+ python -m pytest -vv "$(T)"
20
+
21
+ format:
22
+ black *.py
23
+
24
+ format-check:
25
+ black --check *.py
26
+
27
+ lint:
28
+ pylint --disable=R,C,no-member app.py test_app.py
29
+
30
+ all: install lint format-check test
README.md ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ title: Hindi ↔ English + Hinglish Translator
3
+ emoji: 🌐
4
+ colorFrom: blue
5
+ colorTo: purple
6
+ sdk: gradio
7
+ sdk_version: 6.6.0
8
+ app_file: app.py
9
+ license: mit
10
+ short_description: Hindi↔English translator + Hinglish transliteration
11
+ tags:
12
+ - translation
13
+ - machine-translation
14
+ - hindi
15
+ - hinglish
16
+ - indic-languages
17
+ - gradio
18
+ models:
19
+ - Helsinki-NLP/opus-mt-hi-en
20
+ - Helsinki-NLP/opus-mt-en-hi
21
+ ---
22
+
23
+ # Hindi ↔ English + Hinglish Translator
24
+
25
+ A simple, fast multilingual translator demo built with Hugging Face Transformers and Gradio.
26
+
27
+ ## Features
28
+ - **Hindi → English** — Neural machine translation (MarianMT)
29
+ - **English → Hindi** — Neural machine translation (MarianMT)
30
+ - **Hindi → Hinglish** — Roman transliteration using ITRANS scheme
31
+
32
+ ### Powered by
33
+ - [Helsinki-NLP/opus-mt-hi-en](https://huggingface.co/Helsinki-NLP/opus-mt-hi-en)
34
+ - [Helsinki-NLP/opus-mt-en-hi](https://huggingface.co/Helsinki-NLP/opus-mt-en-hi)
35
+ - [indic-transliteration library](https://github.com/AnimeshSinha1309/indic-transliteration)
36
+
37
+ Just type or paste text, select a task, adjust max length if needed, and click **Translate**!
38
+
39
+ Made with ❤️ in India 🇮🇳
app.py ADDED
@@ -0,0 +1,152 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from functools import lru_cache
2
+ from typing import Literal, Any
3
+
4
+ import gradio as gr
5
+ from transformers import pipeline
6
+ from indic_transliteration import sanscript
7
+ from indic_transliteration.sanscript import transliterate
8
+ import os
9
+ os.environ["TF_ENABLE_ONEDNN_OPTS"] = "0" # silences oneDNN
10
+
11
+ # Model identifiers (Helsinki-NLP MarianMT models)
12
+ HI_EN_MODEL = "Helsinki-NLP/opus-mt-hi-en"
13
+ EN_HI_MODEL = "Helsinki-NLP/opus-mt-en-hi"
14
+
15
+ TaskType = Literal[
16
+ "Hindi → English",
17
+ "English → Hindi",
18
+ "Hindi → Hinglish (transliteration)",
19
+ ]
20
+
21
+
22
+ @lru_cache(maxsize=None)
23
+ def get_hi_en_pipe() -> pipeline:
24
+ """Lazy-load Hindi → English translation pipeline"""
25
+ return pipeline("translation", model=HI_EN_MODEL)
26
+
27
+
28
+ @lru_cache(maxsize=None)
29
+ def get_en_hi_pipe() -> pipeline:
30
+ """Lazy-load English → Hindi translation pipeline"""
31
+ return pipeline("translation", model=EN_HI_MODEL)
32
+
33
+
34
+ def translate(
35
+ text: str | None,
36
+ task: TaskType,
37
+ max_length: int = 256,
38
+ ) -> str:
39
+ """
40
+ Main translation function used by the Gradio interface.
41
+ Handles empty input gracefully and supports three tasks.
42
+ """
43
+ text = (text or "").strip()
44
+ if not text:
45
+ return ""
46
+
47
+ try:
48
+ if task == "Hindi → English":
49
+ pipe = get_hi_en_pipe()
50
+ result = pipe(
51
+ text,
52
+ max_length=max_length,
53
+ num_beams=4,
54
+ early_stopping=True,
55
+ )
56
+ return result[0]["translation_text"]
57
+
58
+ if task == "English → Hindi":
59
+ pipe = get_en_hi_pipe()
60
+ result = pipe(
61
+ text,
62
+ max_length=max_length,
63
+ num_beams=4,
64
+ early_stopping=True,
65
+ )
66
+ return result[0]["translation_text"]
67
+
68
+ if task == "Hindi → Hinglish (transliteration)":
69
+ return transliterate(text, sanscript.DEVANAGARI, sanscript.ITRANS)
70
+
71
+ return "Unsupported task selected"
72
+
73
+ except (ValueError, RuntimeError, OSError) as e:
74
+ return f"Translation error: {str(e)}"
75
+ except Exception as e: # pylint: disable=broad-exception-caught
76
+ return f"Unexpected error during translation: {str(e)}"
77
+
78
+
79
+ def build_demo() -> gr.Blocks:
80
+ """Build and configure the Gradio interface"""
81
+ with gr.Blocks(title="Hindi ↔ English + Hinglish Translator") as demo:
82
+ gr.Markdown(
83
+ """
84
+ # Hindi ↔ English + Hinglish Translator
85
+
86
+ - **Hindi → English** & **English → Hindi**: Neural machine translation
87
+ - **Hindi → Hinglish**: Roman transliteration (Devanagari → ITRANS)
88
+ """
89
+ )
90
+
91
+ with gr.Row():
92
+ task = gr.Dropdown(
93
+ choices=[
94
+ "Hindi → English",
95
+ "English → Hindi",
96
+ "Hindi → Hinglish (transliteration)",
97
+ ],
98
+ value="Hindi → English",
99
+ label="Task",
100
+ interactive=True,
101
+ )
102
+ max_len = gr.Slider(
103
+ 32, 512, value=256, step=16,
104
+ label="Max output length",
105
+ info="Higher values allow longer translations (slower)",
106
+ )
107
+
108
+ input_text = gr.Textbox(
109
+ label="Input text",
110
+ lines=5,
111
+ placeholder="नमस्ते दुनिया! या Hello world...",
112
+ )
113
+
114
+ translate_btn = gr.Button("Translate", variant="primary")
115
+
116
+ output_text = gr.Textbox(
117
+ label="Output",
118
+ lines=5,
119
+ interactive=False,
120
+ )
121
+
122
+ translate_btn.click(
123
+ fn=translate,
124
+ inputs=[input_text, task, max_len],
125
+ outputs=output_text,
126
+ )
127
+
128
+ gr.Examples(
129
+ examples=[
130
+ ["नमस्ते! सब ठीक है?", "Hindi → English", 128],
131
+ ["How are you today?", "English → Hindi", 128],
132
+ ["नमस्ते भाई, क्या हाल है?", "Hindi → Hinglish (transliteration)", 128],
133
+ ["खुश रहो और मुस्कुराते रहो", "Hindi → Hinglish (transliteration)", 128],
134
+ ],
135
+ inputs=[input_text, task, max_len],
136
+ label="Quick examples",
137
+ )
138
+
139
+ return demo
140
+
141
+
142
+ demo = build_demo()
143
+
144
+
145
+ if __name__ == "__main__":
146
+ # pragma: no cover - UI launch not tested
147
+ demo.launch(
148
+ # share=False,
149
+ # inbrowser=False,
150
+ # server_name="0.0.0.0",
151
+ # server_port=7860,
152
+ )
requirements.txt ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ gradio==6.6.0
2
+ transformers==4.45
3
+ tf-keras==2.20.1
4
+ torch==2.10.0
5
+ sentencepiece==0.2.1
6
+ indic-transliteration
7
+ pytest==9.0.2
8
+ pytest-cov==7.0.0
9
+ black==26.1.0
10
+ pylint==4.0.4
test_app.py ADDED
@@ -0,0 +1,69 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import app
2
+ import gradio as gr
3
+
4
+
5
+ class DummyPipe:
6
+ def __init__(self, out_text: str):
7
+ self.out_text = out_text
8
+
9
+ def __call__(self, text, **kwargs): # accept all kwargs → matches real pipeline
10
+ return [{"translation_text": self.out_text}]
11
+
12
+
13
+ def test_translate_empty_returns_empty():
14
+ assert app.translate("", "Hindi → English") == ""
15
+ assert app.translate(" ", "English → Hindi") == ""
16
+ assert app.translate(None, "Hindi → Hinglish (transliteration)") == ""
17
+
18
+
19
+ def test_hi_to_en_uses_hi_en_pipe(monkeypatch):
20
+ app.get_hi_en_pipe.cache_clear()
21
+ monkeypatch.setattr(app, "get_hi_en_pipe", lambda: DummyPipe("hello"))
22
+ assert app.translate("नमस्ते", "Hindi → English") == "hello"
23
+
24
+
25
+ def test_en_to_hi_uses_en_hi_pipe(monkeypatch):
26
+ app.get_en_hi_pipe.cache_clear()
27
+ monkeypatch.setattr(app, "get_en_hi_pipe", lambda: DummyPipe("नमस्ते"))
28
+ assert app.translate("hello", "English → Hindi") == "नमस्ते"
29
+
30
+
31
+ def test_hi_to_hinglish_transliteration_nonempty():
32
+ out = app.translate("नमस्ते भाई कैसे हो?", "Hindi → Hinglish (transliteration)")
33
+ assert isinstance(out, str)
34
+ assert len(out) > 0
35
+
36
+ def test_build_demo_returns_blocks():
37
+ demo = app.build_demo()
38
+ assert isinstance(demo, gr.Blocks)
39
+ assert demo.title == "Hindi ↔ English + Hinglish Translator" # or whatever your title is
40
+
41
+ def get_all_component_types(block):
42
+ types = set()
43
+ def recurse(b):
44
+ if hasattr(b, 'children'):
45
+ for child in b.children or []:
46
+ types.add(type(child).__name__)
47
+ recurse(child)
48
+ recurse(block)
49
+ return types
50
+
51
+
52
+ def test_build_demo_has_expected_components():
53
+ demo = app.build_demo()
54
+ component_types = get_all_component_types(demo)
55
+
56
+ assert "Dropdown" in component_types
57
+ assert "Slider" in component_types
58
+ assert "Textbox" in component_types
59
+ assert "Button" in component_types
60
+
61
+ def test_translate_catches_translation_error(monkeypatch):
62
+ def broken_pipe(*args, **kwargs):
63
+ raise RuntimeError("mock model crash")
64
+
65
+ monkeypatch.setattr(app, "get_hi_en_pipe", lambda: broken_pipe)
66
+
67
+ result = app.translate("नमस्ते", "Hindi → English")
68
+ assert "error" in result.lower()
69
+ assert "mock model crash" in result # or just check prefix