Jobin Thavu Varghese commited on
Commit
b06e275
·
1 Parent(s): 1d14820
.gitignore ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ .venv
2
+ .DS_Store
LICENSE ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Jobin Thavu Varghese
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
app.py ADDED
@@ -0,0 +1,95 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ from services.ocr import upload_file, ocr, ocr_languages
3
+ from services.interleave import interleave
4
+ from services.translation import translation_languages, translation
5
+ from services.transliteration import transliterate_languages, transliterate
6
+
7
+ img_path="bmc/qr-code.png"
8
+
9
+ html_header = f"""
10
+ <div style="display:flex; align-items:center; justify-content:space-between;">
11
+ <h1 style="margin:0;">LMX</h1>
12
+ </div>
13
+ """
14
+
15
+ html_footer = f"""
16
+ <footer>
17
+ </footer>
18
+ """
19
+
20
+ with gr.Blocks(title="LMX", analytics_enabled=True) as interface:
21
+
22
+ with gr.Row():
23
+ gr.HTML(html_header)
24
+ gr.Button(variant="primary", scale=1, min_width=5, value="☕️ Buy me a coffee", size="lg", link_target="_blank", link="https://buymeacoffee.com/jobvargh")
25
+ gr.Button(variant="primary", scale=1, min_width=5, value="Github", size="lg", link_target="_blank", link="https://github.com/jobinv12/LMX")
26
+
27
+
28
+ with gr.Tab("OCR"):
29
+ with gr.Row():
30
+ with gr.Column():
31
+ ocr_path = gr.Textbox(interactive=False, visible=False)
32
+ ocr_languages = gr.Dropdown(label="Source language", choices=ocr_languages, filterable=True, info="Select source language")
33
+ ocr_upload_file = gr.UploadButton(label="Upload a Image", file_types=[".png",".jpeg",".webp",".jpg"], file_count="single")
34
+ ocr_file = gr.Image(height=250, width=700, type="filepath", show_label=False, buttons=[], container=False)
35
+ ocr_upload_file.upload(upload_file, inputs=ocr_upload_file, outputs=[ocr_file, ocr_path])
36
+
37
+ with gr.Column():
38
+ ocr_output = gr.TextArea(label="Output", lines=15 ,interactive=False)
39
+
40
+ with gr.Row():
41
+ clear_btn = gr.ClearButton(value="Clear", variant="secondary")
42
+ ocr_submit_btn = gr.Button(value="Run", variant="huggingface")
43
+
44
+ ocr_submit_btn.click(fn=ocr, inputs=[ocr_path, ocr_languages], outputs=ocr_output)
45
+
46
+ with gr.Tab("Transliteration"):
47
+ with gr.Row():
48
+ with gr.Column():
49
+ transliteration_src_lang = gr.Dropdown(label="Source Language", choices=transliterate_languages, filterable=True, interactive=True)
50
+ transliteration_input_area = gr.TextArea(label="Input")
51
+
52
+ with gr.Column():
53
+ transliteration_trgt_lang = gr.Dropdown(label="Target Language", choices=transliterate_languages, filterable=True, interactive=True)
54
+ transliteration_output_area = gr.TextArea(label="Output", interactive=False)
55
+
56
+ with gr.Row():
57
+ clear_btn = gr.ClearButton(value="Clear", variant="secondary")
58
+ transliteration_submit_btn = gr.Button(value="Run", variant="huggingface")
59
+
60
+ transliteration_submit_btn.click(fn=transliterate, inputs=[transliteration_src_lang, transliteration_trgt_lang, transliteration_input_area], outputs=transliteration_output_area)
61
+
62
+ with gr.Tab("Translation"):
63
+ with gr.Row():
64
+ with gr.Column():
65
+ translation_src_lang = gr.Dropdown(label="Source Language", choices=translation_languages, filterable=True, interactive=True)
66
+ translation_input_area = gr.TextArea(label="Input")
67
+ with gr.Column():
68
+ translation_trgt_lang = gr.Dropdown(label="Target Language", choices=translation_languages, filterable=True, interactive=True)
69
+ translation_output_area = gr.TextArea(label="Output", interactive=False)
70
+
71
+ with gr.Row():
72
+ clear_btn = gr.ClearButton(value="Clear", variant="secondary")
73
+ translation_submit_btn = gr.Button(value="Run", variant="huggingface")
74
+
75
+ translation_submit_btn.click(fn=translation, inputs=[translation_src_lang, translation_trgt_lang, translation_input_area], outputs=translation_output_area)
76
+
77
+
78
+ with gr.Tab("Interleave"):
79
+ with gr.Row():
80
+ interleave_input_area = gr.TextArea(label="First Input", type="text")
81
+ interleave_input2_area = gr.TextArea(label="Second Input", type="text")
82
+
83
+ with gr.Row():
84
+ clear_btn = gr.ClearButton(value="Clear", variant="secondary")
85
+ interleave_submit_btn = gr.Button(value="Run" ,variant="huggingface")
86
+
87
+ with gr.Row():
88
+ interleave_output_area = gr.TextArea(label="Output", interactive=False, type="text")
89
+ interleave_submit_btn.click(fn=interleave, inputs=[interleave_input_area, interleave_input2_area], outputs=[interleave_output_area])
90
+
91
+ with gr.Row():
92
+ gr.HTML(html_template=html_footer)
93
+
94
+ if __name__ == "__main__":
95
+ interface.launch(pwa=True, share=True, allowed_paths=["assets", "bmc"])
pyproject.toml ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ [project]
2
+ name = "alephlm"
3
+ version = "0.1.0"
4
+ description = "Add your description here"
5
+ readme = "README.md"
6
+ requires-python = ">=3.12"
7
+ dependencies = []
requirements.txt ADDED
@@ -0,0 +1,91 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ aiofiles==24.1.0
2
+ alabaster==1.0.0
3
+ annotated-doc==0.0.4
4
+ annotated-types==0.7.0
5
+ anyio==4.12.1
6
+ babel==2.18.0
7
+ brotli==1.2.0
8
+ certifi==2026.2.25
9
+ charset-normalizer==3.4.6
10
+ click==8.3.1
11
+ colorama==0.4.6
12
+ cython==3.2.4
13
+ docutils==0.22.4
14
+ fastapi==0.135.1
15
+ ffmpy==1.0.0
16
+ filelock==3.25.2
17
+ fsspec==2026.2.0
18
+ gradio==6.9.0
19
+ gradio-client==2.3.0
20
+ groovy==0.1.2
21
+ h11==0.16.0
22
+ hf-xet==1.4.2
23
+ httpcore==1.0.9
24
+ httpx==0.28.1
25
+ huggingface-hub==0.36.2
26
+ idna==3.11
27
+ imagesize==2.0.0
28
+ indic-nlp-library-itt==0.1.1
29
+ indictranstoolkit==1.1.1
30
+ jinja2==3.1.6
31
+ joblib==1.5.3
32
+ lxml==6.0.2
33
+ markdown-it-py==4.0.0
34
+ markupsafe==3.0.3
35
+ mdurl==0.1.2
36
+ mlx==0.31.1
37
+ mlx-metal==0.31.1
38
+ morfessor==2.0.6
39
+ mpmath==1.3.0
40
+ networkx==3.6.1
41
+ numpy==2.4.3
42
+ orjson==3.11.7
43
+ packaging==26.0
44
+ pandas==3.0.1
45
+ pillow==12.1.1
46
+ portalocker==3.2.0
47
+ pydantic==2.12.5
48
+ pydantic-core==2.41.5
49
+ pydub==0.25.1
50
+ pygments==2.19.2
51
+ python-dateutil==2.9.0.post0
52
+ python-multipart==0.0.22
53
+ pytz==2026.1.post1
54
+ pyyaml==6.0.3
55
+ regex==2026.2.28
56
+ requests==2.32.5
57
+ rich==14.3.3
58
+ roman-numerals==4.1.0
59
+ sacrebleu==2.6.0
60
+ sacremoses==0.1.1
61
+ safehttpx==0.1.7
62
+ safetensors==0.7.0
63
+ semantic-version==2.10.0
64
+ setuptools==82.0.1
65
+ shellingham==1.5.4
66
+ six==1.17.0
67
+ snowballstemmer==3.0.1
68
+ sphinx==9.1.0
69
+ sphinx-argparse==0.5.2
70
+ sphinx-rtd-theme==3.1.0
71
+ sphinxcontrib-applehelp==2.0.0
72
+ sphinxcontrib-devhelp==2.0.0
73
+ sphinxcontrib-htmlhelp==2.1.0
74
+ sphinxcontrib-jquery==4.1
75
+ sphinxcontrib-jsmath==1.0.1
76
+ sphinxcontrib-qthelp==2.0.0
77
+ sphinxcontrib-serializinghtml==2.0.0
78
+ starlette==0.52.1
79
+ sympy==1.14.0
80
+ tabulate==0.10.0
81
+ tokenizers==0.21.4
82
+ tomlkit==0.13.3
83
+ torch==2.10.0
84
+ torchvision==0.25.0
85
+ tqdm==4.67.3
86
+ transformers==4.53.2
87
+ typer==0.24.1
88
+ typing-extensions==4.15.0
89
+ typing-inspection==0.4.2
90
+ urllib3==2.6.3
91
+ uvicorn==0.42.0
services/__pycache__/interleave.cpython-311.pyc ADDED
Binary file (1.59 kB). View file
 
services/__pycache__/interleave.cpython-312.pyc ADDED
Binary file (1.19 kB). View file
 
services/__pycache__/ocr.cpython-311.pyc ADDED
Binary file (3.52 kB). View file
 
services/__pycache__/ocr.cpython-312.pyc ADDED
Binary file (3.49 kB). View file
 
services/__pycache__/translation.cpython-311.pyc ADDED
Binary file (378 Bytes). View file
 
services/__pycache__/translation.cpython-312.pyc ADDED
Binary file (12.7 kB). View file
 
services/__pycache__/transliteration.cpython-311.pyc ADDED
Binary file (1.32 kB). View file
 
services/__pycache__/transliteration.cpython-312.pyc ADDED
Binary file (6.96 kB). View file
 
services/interleave.py ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ def interleave(first_input_text:str, second_input_text:str) -> str:
2
+ first_input = [
3
+ line.strip() for line in first_input_text.splitlines() if line.strip()
4
+ ]
5
+ second_input = [
6
+ line.strip() for line in second_input_text.splitlines() if line.strip()
7
+ ]
8
+
9
+ result = "\n\n".join(f"{x}\n{y}" for x, y in zip(first_input, second_input))
10
+
11
+ return result
services/ocr.py ADDED
@@ -0,0 +1,74 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ from datetime import datetime
3
+ import shutil
4
+ import mlx.core as mx
5
+ from mlx_vlm import load, generate
6
+ from mlx_vlm.prompt_utils import apply_chat_template
7
+ from mlx_vlm.utils import load_config
8
+
9
+ ocr_languages = [
10
+ "English", "Afrikaans", "Amharic", "Arabic", "Assamese", "Azerbaijani",
11
+ "Azerbaijani - Cyrillic", "Belarusian", "Bengali", "Tibetan", "Bosnian",
12
+ "Breton", "Bulgarian", "Catalan; Valencian", "Cebuano", "Czech",
13
+ "Chinese", "Cherokee", "Corsican", "Welsh",
14
+ "Danish", "Danish - Fraktur", "German", "German",
15
+ "Dzongkha", "Greek", "Esperanto",
16
+ "Estonian", "Basque", "Faroese", "Persian", "Filipino",
17
+ "Finnish", "French", "French", "Western Frisian",
18
+ "Scottish Gaelic", "Irish", "Galician", "Gujarati",
19
+ "Haitian; Haitian Creole", "Hebrew", "Hindi", "Croatian", "Hungarian",
20
+ "Armenian", "Inuktitut", "Indonesian", "Icelandic", "Italian",
21
+ "Javanese", "Japanese", "Kannada", "Georgian", "Georgian - Old", "Kazakh",
22
+ "Central Khmer", "Kirghiz; Kyrgyz", "Kurmanji", "Korean",
23
+ "Korean", "Kurdish", "Lao", "Latin", "Latvian",
24
+ "Lithuanian", "Luxembourgish", "Malayalam", "Marathi", "Macedonian",
25
+ "Maltese", "Mongolian", "Maori", "Malay", "Burmese", "Nepali",
26
+ "Dutch; Flemish", "Norwegian", "Occitan", "Oriya",
27
+ "Panjabi; Punjabi", "Polish", "Portuguese", "Pushto; Pashto", "Quechua",
28
+ "Romanian; Moldavian; Moldovan", "Russian", "Sanskrit", "Sinhala; Sinhalese",
29
+ "Slovak", "Slovak - Fraktur", "Slovenian", "Sindhi", "Spanish; Castilian",
30
+ "Spanish; Castilian - Old", "Albanian", "Serbian", "Serbian - Latin",
31
+ "Sundanese", "Swahili", "Swedish", "Syriac", "Tamil", "Tatar", "Telugu",
32
+ "Tajik", "Thai", "Tigrinya", "Tonga", "Turkish",
33
+ "Uighur; Uyghur", "Ukrainian", "Urdu", "Uzbek",
34
+ "Vietnamese", "Yiddish", "Yoruba"
35
+ ]
36
+
37
+ model_id = "mlx-community/olmOCR-2-7B-1025-8bit"
38
+
39
+ try:
40
+ # Load the model
41
+ model, processor = load(model_id, trust_remote_code=True)
42
+ config = load_config(model_id)
43
+ print("olmocr2 model loaded successfully")
44
+ except Exception as e:
45
+ print(f"Failed to load deepseekocr2 model {e}")
46
+
47
+ def upload_file(file):
48
+
49
+ if file is None:
50
+ return "No file uploaded"
51
+
52
+ timestamp = datetime.now().strftime("%Y%m%d")
53
+
54
+ original_name = os.path.basename(file.name)
55
+
56
+ name, ext = os.path.splitext(original_name)
57
+
58
+ new_filename = f"{name}_{timestamp}{ext}"
59
+
60
+ dest_path = os.path.join("assets", new_filename)
61
+
62
+ shutil.copy(file, dest_path)
63
+
64
+ return dest_path, dest_path
65
+
66
+ def ocr(image_path:str, language:str) -> str:
67
+
68
+ prompt = f"Convert the {language} document to markdown."
69
+
70
+ formatted_output = apply_chat_template(processor, config, prompt, num_images=1)
71
+
72
+ output = generate(model, processor, formatted_output, [image_path], verbose=False, max_tokens=2000)
73
+
74
+ return output.text
services/translation.py ADDED
@@ -0,0 +1,352 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ from transformers import AutoModelForImageTextToText, AutoProcessor
3
+
4
+ translation_languages: list = ['English', 'Abkhaz', 'Acehnese', 'Acholi',
5
+ 'Afar', 'Afrikaans', 'Albanian', 'Alur',
6
+ 'Amharic', 'Arabic', 'Armenian', 'Assamese',
7
+ 'Avar', 'Awadhi', 'Aymara', 'Azerbaijani',
8
+ 'Balinese', 'Baluchi', 'Bambara', 'Baoulé',
9
+ 'Bashkir', 'Basque', 'Batak Karo', 'Batak Simalungun',
10
+ 'Batak Toba', 'Belarusian', 'Bemba', 'Bengali', 'Betawi',
11
+ 'Bhojpuri', 'Bikol', 'Bosnian', 'Breton', 'Bulgarian',
12
+ 'Buryat', 'Cantonese', 'Catalan', 'Cebuano', 'Chamorro',
13
+ 'Chechen', 'Chichewa', 'Chinese (Simplified)',
14
+ 'Chinese (Traditional)', 'Chuukese', 'Chuvash',
15
+ 'Corsican', 'Crimean Tatar (Cyrillic)',
16
+ 'Crimean Tatar (Latin)', 'Croatian', 'Czech',
17
+ 'Danish', 'Dari', 'Dhivehi', 'Dinka', 'Dogri',
18
+ 'Dombe', 'Dutch', 'Dyula', 'Dzongkha', 'Esperanto',
19
+ 'Estonian', 'Ewe', 'Faroese', 'Fijian', 'Filipino',
20
+ 'Finnish', 'Fon', 'French', 'French (Canada)', 'Frisian',
21
+ 'Friulian', 'Fulani', 'Ga', 'Galician', 'Georgian', 'German',
22
+ 'Greek', 'Guarani', 'Gujarati', 'Haitian Creole', 'Hakha Chin',
23
+ 'Hausa', 'Hawaiian', 'Hebrew', 'Hiligaynon', 'Hindi',
24
+ 'Hmong', 'Hungarian', 'Hunsrik', 'Iban', 'Icelandic',
25
+ 'Igbo', 'Ilocano', 'Indonesian', 'Inuktut (Latin)',
26
+ 'Inuktut (Syllabics)', 'Irish', 'Italian',
27
+ 'Jamaican Patois', 'Japanese', 'Javanese', 'Jingpo',
28
+ 'Kalaallisut', 'Kannada', 'Kanuri', 'Kapampangan',
29
+ 'Kazakh', 'Khasi', 'Khmer', 'Kiga', 'Kikongo',
30
+ 'Kinyarwanda', 'Kituba', 'Kokborok', 'Komi', 'Konkani',
31
+ 'Korean', 'Krio', 'Kurdish (Kurmanji)', 'Kurdish (Sorani)',
32
+ 'Kyrgyz', 'Lao', 'Latgalian', 'Latin', 'Latvian',
33
+ 'Ligurian', 'Limburgish', 'Lingala', 'Lithuanian',
34
+ 'Lombard', 'Luganda', 'Luo', 'Luxembourgish',
35
+ 'Macedonian', 'Madurese', 'Maithili', 'Makassar',
36
+ 'Malagasy', 'Malay', 'Malay (Jawi)', 'Malayalam',
37
+ 'Maltese', 'Mam', 'Manx', 'Maori', 'Marathi',
38
+ 'Marshallese', 'Marwadi', 'Mauritian Creole',
39
+ 'Meadow Mari', 'Meiteilon (Manipuri)', 'Minang',
40
+ 'Mizo', 'Mongolian', 'Myanmar (Burmese)',
41
+ 'Nahuatl (Eastern Huasteca)', 'Ndau', 'Ndebele (South)',
42
+ 'Nepalbhasa (Newari)', 'Nepali', 'NKo', 'Norwegian',
43
+ 'Nuer', 'Occitan', 'Odia (Oriya)', 'Oromo', 'Ossetian',
44
+ 'Pangasinan', 'Papiamento', 'Pashto', 'Persian',
45
+ 'Polish', 'Portuguese (Brazil)', 'Portuguese (Portugal)',
46
+ 'Punjabi (Gurmukhi)', 'Punjabi (Shahmukhi)', 'Quechua',
47
+ 'Qʼeqchiʼ', 'Romani', 'Romanian', 'Rundi', 'Russian',
48
+ 'Sami (North)', 'Samoan', 'Sango', 'Sanskrit', 'Santali (Latin)',
49
+ 'Santali (Ol Chiki)', 'Scots Gaelic', 'Sepedi', 'Serbian',
50
+ 'Sesotho', 'Seychellois Creole', 'Shan', 'Shona', 'Sicilian',
51
+ 'Silesian', 'Sindhi', 'Sinhala', 'Slovak', 'Slovenian', 'Somali',
52
+ 'Spanish', 'Sundanese', 'Susu', 'Swahili', 'Swati', 'Swedish',
53
+ 'Tahitian', 'Tajik', 'Tamazight', 'Tamazight (Tifinagh)', 'Tamil',
54
+ 'Tatar', 'Telugu', 'Tetum', 'Thai', 'Tibetan', 'Tigrinya', 'Tiv',
55
+ 'Tok Pisin', 'Tongan', 'Tshiluba', 'Tsonga', 'Tswana', 'Tulu',
56
+ 'Tumbuka', 'Turkish', 'Turkmen', 'Tuvan', 'Twi', 'Udmurt',
57
+ 'Ukrainian', 'Urdu', 'Uyghur', 'Uzbek', 'Venda', 'Venetian',
58
+ 'Vietnamese', 'Waray', 'Welsh', 'Wolof', 'Xhosa', 'Yakut',
59
+ 'Yiddish', 'Yoruba', 'Yucatec Maya', 'Zapotec', 'Zulu']
60
+
61
+ languages_iso_codes: dict = {
62
+ "English": "en",
63
+ "Abkhaz": "ab",
64
+ "Acehnese": "ace",
65
+ "Acholi": "ach",
66
+ "Afar": "aa",
67
+ "Afrikaans": "af",
68
+ "Albanian": "sq",
69
+ "Alur": "alz",
70
+ "Amharic": "am",
71
+ "Arabic": "ar",
72
+ "Armenian": "hy",
73
+ "Assamese": "as",
74
+ "Avar": "av",
75
+ "Awadhi": "awa",
76
+ "Aymara": "ay",
77
+ "Azerbaijani": "az",
78
+ "Balinese": "ban",
79
+ "Baluchi": "bal",
80
+ "Bambara": "bm",
81
+ "Baoulé": "bci",
82
+ "Bashkir": "ba",
83
+ "Basque": "eu",
84
+ "Batak Karo": "btx",
85
+ "Batak Simalungun": "bts",
86
+ "Batak Toba": "bbc",
87
+ "Belarusian": "be",
88
+ "Bemba": "bem",
89
+ "Bengali": "bn",
90
+ "Betawi": "bew",
91
+ "Bhojpuri": "bho",
92
+ "Bikol": "bik",
93
+ "Bosnian": "bs",
94
+ "Breton": "br",
95
+ "Bulgarian": "bg",
96
+ "Buryat": "bua",
97
+ "Cantonese": "yue",
98
+ "Catalan": "ca",
99
+ "Cebuano": "ceb",
100
+ "Chamorro": "ch",
101
+ "Chechen": "ce",
102
+ "Chichewa": "ny",
103
+ "Chinese (Simplified)": "zh-CN",
104
+ "Chinese (Traditional)": "zh-TW",
105
+ "Chuukese": "chk",
106
+ "Chuvash": "cv",
107
+ "Corsican": "co",
108
+ "Crimean Tatar (Cyrillic)": "crh-Cyrl",
109
+ "Crimean Tatar (Latin)": "crh-Latn",
110
+ "Croatian": "hr",
111
+ "Czech": "cs",
112
+ "Danish": "da",
113
+ "Dari": "prs",
114
+ "Dhivehi": "dv",
115
+ "Dinka": "din",
116
+ "Dogri": "doi",
117
+ "Dombe": "dov",
118
+ "Dutch": "nl",
119
+ "Dyula": "dyu",
120
+ "Dzongkha": "dz",
121
+ "Esperanto": "eo",
122
+ "Estonian": "et",
123
+ "Ewe": "ee",
124
+ "Faroese": "fo",
125
+ "Fijian": "fj",
126
+ "Filipino": "fil",
127
+ "Finnish": "fi",
128
+ "Fon": "fon",
129
+ "French": "fr",
130
+ "French (Canada)": "fr-CA",
131
+ "Frisian": "fy",
132
+ "Friulian": "fur",
133
+ "Fulani": "ff",
134
+ "Ga": "gaa",
135
+ "Galician": "gl",
136
+ "Georgian": "ka",
137
+ "German": "de",
138
+ "Greek": "el",
139
+ "Guarani": "gn",
140
+ "Gujarati": "gu",
141
+ "Haitian Creole": "ht",
142
+ "Hakha Chin": "cnh",
143
+ "Hausa": "ha",
144
+ "Hawaiian": "haw",
145
+ "Hebrew": "he",
146
+ "Hiligaynon": "hil",
147
+ "Hindi": "hi",
148
+ "Hmong": "hmn",
149
+ "Hungarian": "hu",
150
+ "Hunsrik": "hrx",
151
+ "Iban": "iba",
152
+ "Icelandic": "is",
153
+ "Igbo": "ig",
154
+ "Ilocano": "ilo",
155
+ "Indonesian": "id",
156
+ "Inuktut (Latin)": "iu-Latn",
157
+ "Inuktut (Syllabics)": "iu-Cans",
158
+ "Irish": "ga",
159
+ "Italian": "it",
160
+ "Jamaican Patois": "jam",
161
+ "Japanese": "ja",
162
+ "Javanese": "jv",
163
+ "Jingpo": "kac",
164
+ "Kalaallisut": "kl",
165
+ "Kannada": "kn",
166
+ "Kanuri": "kr",
167
+ "Kapampangan": "pam",
168
+ "Kazakh": "kk",
169
+ "Khasi": "kha",
170
+ "Khmer": "km",
171
+ "Kiga": "cgg",
172
+ "Kikongo": "kg",
173
+ "Kinyarwanda": "rw",
174
+ "Kituba": "ktu",
175
+ "Kokborok": "trp",
176
+ "Komi": "kv",
177
+ "Konkani": "gom",
178
+ "Korean": "ko",
179
+ "Krio": "kri",
180
+ "Kurdish (Kurmanji)": "ku",
181
+ "Kurdish (Sorani)": "ckb",
182
+ "Kyrgyz": "ky",
183
+ "Lao": "lo",
184
+ "Latgalian": "ltg",
185
+ "Latin": "la",
186
+ "Latvian": "lv",
187
+ "Ligurian": "lij",
188
+ "Limburgish": "li",
189
+ "Lingala": "ln",
190
+ "Lithuanian": "lt",
191
+ "Lombard": "lmo",
192
+ "Luganda": "lg",
193
+ "Luo": "luo",
194
+ "Luxembourgish": "lb",
195
+ "Macedonian": "mk",
196
+ "Madurese": "mad",
197
+ "Maithili": "mai",
198
+ "Makassar": "mak",
199
+ "Malagasy": "mg",
200
+ "Malay": "ms",
201
+ "Malay (Jawi)": "ms-Arab",
202
+ "Malayalam": "ml",
203
+ "Maltese": "mt",
204
+ "Mam": "mam",
205
+ "Manx": "gv",
206
+ "Maori": "mi",
207
+ "Marathi": "mr",
208
+ "Marshallese": "mh",
209
+ "Marwadi": "mwr",
210
+ "Mauritian Creole": "mfe",
211
+ "Meadow Mari": "mhr",
212
+ "Meiteilon (Manipuri)": "mni",
213
+ "Minang": "min",
214
+ "Mizo": "lus",
215
+ "Mongolian": "mn",
216
+ "Myanmar (Burmese)": "my",
217
+ "Nahuatl (Eastern Huasteca)": "nhe",
218
+ "Ndau": "ndc",
219
+ "Ndebele (South)": "nr",
220
+ "Nepalbhasa (Newari)": "new",
221
+ "Nepali": "ne",
222
+ "NKo": "nqo",
223
+ "Norwegian": "no",
224
+ "Nuer": "nus",
225
+ "Occitan": "oc",
226
+ "Odia (Oriya)": "or",
227
+ "Oromo": "om",
228
+ "Ossetian": "os",
229
+ "Pangasinan": "pag",
230
+ "Papiamento": "pap",
231
+ "Pashto": "ps",
232
+ "Persian": "fa",
233
+ "Polish": "pl",
234
+ "Portuguese (Brazil)": "pt-BR",
235
+ "Portuguese (Portugal)": "pt-PT",
236
+ "Punjabi (Gurmukhi)": "pa",
237
+ "Punjabi (Shahmukhi)": "pa-Arab",
238
+ "Quechua": "qu",
239
+ "Qʼeqchiʼ": "kek",
240
+ "Romani": "rom",
241
+ "Romanian": "ro",
242
+ "Rundi": "rn",
243
+ "Russian": "ru",
244
+ "Sami (North)": "se",
245
+ "Samoan": "sm",
246
+ "Sango": "sg",
247
+ "Sanskrit": "sa",
248
+ "Santali (Latin)": "sat-Latn",
249
+ "Santali (Ol Chiki)": "sat",
250
+ "Scots Gaelic": "gd",
251
+ "Sepedi": "nso",
252
+ "Serbian": "sr",
253
+ "Sesotho": "st",
254
+ "Seychellois Creole": "crs",
255
+ "Shan": "shn",
256
+ "Shona": "sn",
257
+ "Sicilian": "scn",
258
+ "Silesian": "szl",
259
+ "Sindhi": "sd",
260
+ "Sinhala": "si",
261
+ "Slovak": "sk",
262
+ "Slovenian": "sl",
263
+ "Somali": "so",
264
+ "Spanish": "es",
265
+ "Sundanese": "su",
266
+ "Susu": "sus",
267
+ "Swahili": "sw",
268
+ "Swati": "ss",
269
+ "Swedish": "sv",
270
+ "Tahitian": "ty",
271
+ "Tajik": "tg",
272
+ "Tamazight": "tzm",
273
+ "Tamazight (Tifinagh)": "zgh",
274
+ "Tamil": "ta",
275
+ "Tatar": "tt",
276
+ "Telugu": "te",
277
+ "Tetum": "tet",
278
+ "Thai": "th",
279
+ "Tibetan": "bo",
280
+ "Tigrinya": "ti",
281
+ "Tiv": "tiv",
282
+ "Tok Pisin": "tpi",
283
+ "Tongan": "to",
284
+ "Tshiluba": "lua",
285
+ "Tsonga": "ts",
286
+ "Tswana": "tn",
287
+ "Tulu": "tcy",
288
+ "Tumbuka": "tum",
289
+ "Turkish": "tr",
290
+ "Turkmen": "tk",
291
+ "Tuvan": "tyv",
292
+ "Twi": "tw",
293
+ "Udmurt": "udm",
294
+ "Ukrainian": "uk",
295
+ "Urdu": "ur",
296
+ "Uyghur": "ug",
297
+ "Uzbek": "uz",
298
+ "Venda": "ve",
299
+ "Venetian": "vec",
300
+ "Vietnamese": "vi",
301
+ "Waray": "war",
302
+ "Welsh": "cy",
303
+ "Wolof": "wo",
304
+ "Xhosa": "xh",
305
+ "Yakut": "sah",
306
+ "Yiddish": "yi",
307
+ "Yoruba": "yo",
308
+ "Yucatec Maya": "yua",
309
+ "Zapotec": "zap",
310
+ "Zulu": "zu"
311
+ }
312
+
313
+ model_id = "google/translategemma-4b-it"
314
+
315
+ try:
316
+ processor = AutoProcessor.from_pretrained(model_id)
317
+ model = AutoModelForImageTextToText.from_pretrained(model_id, device_map="auto")
318
+ print("Translation model loaded successfully")
319
+ except Exception as e:
320
+ print(f"Failed to load translation model {e}")
321
+
322
+ def translation(src_lang:str, trgt_lang:str, text:str) -> str:
323
+
324
+ src_lang_iso = languages_iso_codes[src_lang]
325
+ trgt_lang_iso = languages_iso_codes[trgt_lang]
326
+
327
+ messages = [
328
+ {
329
+ "role": "user",
330
+ "content": [
331
+ {
332
+ "type": "text",
333
+ "source_lang_code": src_lang_iso,
334
+ "target_lang_code": trgt_lang_iso,
335
+ "text": text,
336
+ }
337
+ ],
338
+ }
339
+ ]
340
+
341
+ inputs = processor.apply_chat_template(
342
+ messages, tokenize=True, add_generation_prompt=True, return_dict=True, return_tensors="pt"
343
+ ).to(model.device, dtype=torch.bfloat16)
344
+ input_len = len(inputs['input_ids'][0])
345
+
346
+ with torch.inference_mode():
347
+ generation = model.generate(**inputs, do_sample=False, max_new_tokens=2000)
348
+
349
+ generation = generation[0][input_len:]
350
+ decoded = processor.decode(generation, skip_special_tokens=True)
351
+
352
+ return decoded
services/transliteration.py ADDED
@@ -0,0 +1,105 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ from transformers import AutoModelForSeq2SeqLM, AutoTokenizer
3
+ from IndicTransToolkit.processor import IndicProcessor
4
+
5
+ DEVICE = "cuda" if torch.cuda.is_available() else "cpu"
6
+
7
+
8
+ transliterate_languages: list = [
9
+ "English",
10
+ "Assamese",
11
+ "Bengali",
12
+ "Bodo",
13
+ "Dogri",
14
+ "Konkani",
15
+ "Gujarati",
16
+ "Hindi",
17
+ "Kannada",
18
+ "Kashmiri",
19
+ "Kashmiri",
20
+ "Maithili",
21
+ "Malayalam",
22
+ "Marathi",
23
+ "Manipuri",
24
+ "Manipuri",
25
+ "Nepali",
26
+ "Odia",
27
+ "Punjabi",
28
+ "Sanskrit",
29
+ "Santali",
30
+ "Sindhi",
31
+ "Sindhi",
32
+ "Tamil",
33
+ "Telugu",
34
+ "Urdu"
35
+ ]
36
+
37
+ transliteration_iso_codes: dict = {
38
+ "English": "eng_Latn",
39
+ "Assamese": "asm_Beng",
40
+ "Bengali": "ben_Beng",
41
+ "Bodo": "brx_Deva",
42
+ "Dogri": "doi_Deva",
43
+ "Konkani": "gom_Deva",
44
+ "Gujarati": "guj_Gujr",
45
+ "Hindi": "hin_Deva",
46
+ "Kannada": "kan_Knda",
47
+ "Kashmiri (Arabic)": "kas_Arab",
48
+ "Kashmiri (Devanagari)": "kas_Deva",
49
+ "Maithili": "mai_Deva",
50
+ "Malayalam": "mal_Mlym",
51
+ "Marathi": "mar_Deva",
52
+ "Manipuri (Bengali)": "mni_Beng",
53
+ "Manipuri (Meitei)": "mni_Mtei",
54
+ "Nepali": "npi_Deva",
55
+ "Odia": "ory_Orya",
56
+ "Punjabi": "pan_Guru",
57
+ "Sanskrit": "san_Deva",
58
+ "Santali": "sat_Olck",
59
+ "Sindhi (Arabic)": "snd_Arab",
60
+ "Sindhi (Devanagari) ()": "snd_Deva",
61
+ "Tamil": "tam_Taml",
62
+ "Telugu": "tel_Telu",
63
+ "Urdu": "urd_Arab"
64
+ }
65
+
66
+ def indic_transliteration(model_name:str, src_lang:str, trgt_lang:str, text:str) -> str:
67
+
68
+ model_id = model_name
69
+ try:
70
+ tokenizer = AutoTokenizer.from_pretrained(model_id, trust_remote_code=True)
71
+ model = AutoModelForSeq2SeqLM.from_pretrained(model_id,trust_remote_code=True,torch_dtype=torch.bfloat16).to(DEVICE)
72
+ print(f"{model_id} model loaded sucessfully.")
73
+ except Exception as e:
74
+ print(f"Failed to load {model_id} model.")
75
+
76
+ ip = IndicProcessor(inference=True)
77
+
78
+ batch = ip.preprocess_batch(
79
+ [text],
80
+ src_lang=src_lang,
81
+ tgt_lang=trgt_lang
82
+ )
83
+
84
+ inputs = tokenizer(batch, truncation=True, padding="longest", return_tensors="pt", return_attention_mask=True).to(DEVICE)
85
+
86
+ with torch.no_grad():
87
+ generated_tokens = model.generate(**inputs, use_cache=True, min_length=0, max_length=2048, num_beams=5, num_return_sequences=1)
88
+
89
+ generated_tokens = tokenizer.batch_decode(generated_tokens, skip_special_tokens=True, clean_up_tokenization_spaces=True)
90
+
91
+ translations = ip.postprocess_batch(generated_tokens, lang=trgt_lang)
92
+
93
+ return "\n".join(translations)
94
+
95
+ def transliterate(src_lang:str, trgt_lang:str, text:str) -> str:
96
+
97
+ src_lang_iso:str = transliteration_iso_codes.get(src_lang)
98
+ trgt_lang_iso:str = transliteration_iso_codes.get(trgt_lang)
99
+
100
+ if "eng_Latn" in src_lang_iso and "eng_Latn" not in trgt_lang_iso:
101
+ return indic_transliteration("ai4bharat/indictrans2-en-indic-1B", src_lang_iso, trgt_lang_iso, text)
102
+ elif "eng_Latn" not in src_lang_iso and "eng_Latn" in trgt_lang_iso:
103
+ return indic_transliteration("ai4bharat/indictrans2-indic-en-1B", src_lang_iso, trgt_lang_iso, text)
104
+ else:
105
+ return indic_transliteration("ai4bharat/indictrans2-indic-indic-1B", src_lang_iso, trgt_lang_iso, text)
uv.lock ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ version = 1
2
+ revision = 3
3
+ requires-python = ">=3.12"
4
+
5
+ [[package]]
6
+ name = "alephlm"
7
+ version = "0.1.0"
8
+ source = { virtual = "." }