Spaces:
Runtime error
Runtime error
Update app.py
Browse files
app.py
CHANGED
|
@@ -1,122 +1,149 @@
|
|
| 1 |
-
|
| 2 |
-
import os, re
|
| 3 |
-
from typing import List, Optional
|
| 4 |
-
|
| 5 |
import gradio as gr
|
| 6 |
-
import
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
|
| 20 |
-
)
|
| 21 |
-
|
| 22 |
-
|
| 23 |
-
|
| 24 |
-
|
| 25 |
-
|
| 26 |
-
|
| 27 |
-
|
| 28 |
-
|
| 29 |
-
|
| 30 |
-
|
| 31 |
-
)
|
| 32 |
-
|
| 33 |
-
|
| 34 |
-
|
| 35 |
-
|
| 36 |
-
"
|
| 37 |
-
"
|
| 38 |
-
"
|
| 39 |
-
"
|
| 40 |
-
"
|
| 41 |
-
"
|
| 42 |
-
"
|
| 43 |
-
"
|
| 44 |
-
"
|
| 45 |
-
"
|
| 46 |
-
"
|
| 47 |
-
"
|
| 48 |
-
"
|
| 49 |
-
|
| 50 |
-
|
| 51 |
-
|
| 52 |
-
|
| 53 |
-
|
| 54 |
-
|
| 55 |
-
|
| 56 |
-
|
| 57 |
-
|
| 58 |
-
|
| 59 |
-
|
| 60 |
-
|
| 61 |
-
|
| 62 |
-
|
| 63 |
-
|
| 64 |
-
|
| 65 |
-
|
| 66 |
-
|
| 67 |
-
|
| 68 |
-
|
| 69 |
-
|
| 70 |
-
|
| 71 |
-
|
| 72 |
-
|
| 73 |
-
|
| 74 |
-
|
| 75 |
-
|
| 76 |
-
|
| 77 |
-
|
| 78 |
-
|
| 79 |
-
|
| 80 |
-
|
| 81 |
-
|
| 82 |
-
|
| 83 |
-
|
| 84 |
-
|
| 85 |
-
|
| 86 |
-
|
| 87 |
-
|
| 88 |
-
|
| 89 |
-
|
| 90 |
-
|
| 91 |
-
|
| 92 |
-
|
| 93 |
-
|
| 94 |
-
|
| 95 |
-
|
| 96 |
-
|
| 97 |
-
|
| 98 |
-
|
| 99 |
-
|
| 100 |
-
|
| 101 |
-
|
| 102 |
-
|
| 103 |
-
with gr.
|
| 104 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 105 |
with gr.Row():
|
| 106 |
-
|
| 107 |
-
|
| 108 |
-
|
| 109 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 110 |
|
| 111 |
-
with gr.Tab("Batch"):
|
| 112 |
-
src_list = gr.Textbox(label="Mỗi dòng 1 câu/đoạn", lines=10)
|
| 113 |
with gr.Row():
|
| 114 |
-
|
| 115 |
-
|
| 116 |
-
|
| 117 |
-
|
| 118 |
-
|
| 119 |
-
|
| 120 |
-
|
| 121 |
-
|
| 122 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
|
|
|
|
|
|
|
|
|
| 2 |
import gradio as gr
|
| 3 |
+
from huggingface_hub import InferenceClient
|
| 4 |
+
|
| 5 |
+
# -------- Settings --------
|
| 6 |
+
DEFAULT_MODEL = os.getenv("HYMT_MODEL", "tencent/Hunyuan-MT-7B-fp8")
|
| 7 |
+
HF_TOKEN = os.getenv("HF_TOKEN", None) # có thể để trống (ẩn danh, sẽ bị rate-limit)
|
| 8 |
+
|
| 9 |
+
# Ngôn ngữ được model hỗ trợ (trích từ model card)
|
| 10 |
+
LANGS = [
|
| 11 |
+
("Chinese (简体中文)", "zh"),
|
| 12 |
+
("Traditional Chinese (繁體中文)", "zh-Hant"),
|
| 13 |
+
("Cantonese (粤语)", "yue"),
|
| 14 |
+
("English (English)", "en"),
|
| 15 |
+
("Vietnamese (Tiếng Việt)", "vi"),
|
| 16 |
+
("Japanese (日本語)", "ja"),
|
| 17 |
+
("Korean (한국어)", "ko"),
|
| 18 |
+
("Thai (ไทย)", "th"),
|
| 19 |
+
("French (Français)", "fr"),
|
| 20 |
+
("Spanish (Español)", "es"),
|
| 21 |
+
("Portuguese (Português)", "pt"),
|
| 22 |
+
("Italian (Italiano)", "it"),
|
| 23 |
+
("German (Deutsch)", "de"),
|
| 24 |
+
("Russian (Русский)", "ru"),
|
| 25 |
+
("Arabic (العربية)", "ar"),
|
| 26 |
+
("Turkish (Türkçe)", "tr"),
|
| 27 |
+
("Indonesian (Bahasa Indonesia)", "id"),
|
| 28 |
+
("Malay (Bahasa Melayu)", "ms"),
|
| 29 |
+
("Filipino (Filipino)", "tl"),
|
| 30 |
+
("Hindi (हिन्दी)", "hi"),
|
| 31 |
+
("Polish (Polski)", "pl"),
|
| 32 |
+
("Czech (Čeština)", "cs"),
|
| 33 |
+
("Dutch (Nederlands)", "nl"),
|
| 34 |
+
("Khmer (ភាសាខ្មែរ)", "km"),
|
| 35 |
+
("Burmese (မြန်မာ)", "my"),
|
| 36 |
+
("Persian (فارسی)", "fa"),
|
| 37 |
+
("Gujarati (ગુજરાતી)", "gu"),
|
| 38 |
+
("Urdu (اردو)", "ur"),
|
| 39 |
+
("Telugu (తెలుగు)", "te"),
|
| 40 |
+
("Marathi (मराठी)", "mr"),
|
| 41 |
+
("Hebrew (עברית)", "he"),
|
| 42 |
+
("Bengali (বাংলা)", "bn"),
|
| 43 |
+
("Tamil (தமிழ்)", "ta"),
|
| 44 |
+
("Ukrainian (Українська)", "uk"),
|
| 45 |
+
("Tibetan (བོད་ཡིག)", "bo"),
|
| 46 |
+
("Kazakh (Қазақша)", "kk"),
|
| 47 |
+
("Mongolian (Монгол)", "mn"),
|
| 48 |
+
("Uyghur (ئۇيغۇرچە)", "ug"),
|
| 49 |
+
]
|
| 50 |
+
|
| 51 |
+
ZH_CODES = {"zh", "zh-Hant", "yue"}
|
| 52 |
+
|
| 53 |
+
def build_prompt(src_lang: str, tgt_lang: str, text: str) -> str:
|
| 54 |
+
"""
|
| 55 |
+
Theo gợi ý prompt trong model card:
|
| 56 |
+
- ZH <=> XX: dùng template tiếng Trung
|
| 57 |
+
- XX <=> XX (không có ZH): dùng template tiếng Anh
|
| 58 |
+
"""
|
| 59 |
+
if src_lang in ZH_CODES or tgt_lang in ZH_CODES:
|
| 60 |
+
# Template ZH <=> XX
|
| 61 |
+
return f"把下面的文本翻译成{tgt_lang},不要额外解释。\n\n{text.strip()}"
|
| 62 |
+
else:
|
| 63 |
+
# Template XX <=> XX (không có ZH)
|
| 64 |
+
return f"Translate the following segment into {tgt_lang}, without additional explanation.\n\n{text.strip()}"
|
| 65 |
+
|
| 66 |
+
def call_hf_inference(model: str, prompt: str) -> str:
|
| 67 |
+
"""
|
| 68 |
+
Gọi Serverless Inference API (text-generation).
|
| 69 |
+
Không cần GPU trên Space. Có thể dùng ẩn danh hoặc set HF_TOKEN trong Secrets.
|
| 70 |
+
"""
|
| 71 |
+
client = InferenceClient(token=HF_TOKEN)
|
| 72 |
+
# Tham số khuyến nghị từ model card
|
| 73 |
+
try:
|
| 74 |
+
out = client.text_generation(
|
| 75 |
+
model=model,
|
| 76 |
+
prompt=prompt,
|
| 77 |
+
max_new_tokens=512,
|
| 78 |
+
temperature=0.7,
|
| 79 |
+
top_p=0.6,
|
| 80 |
+
repetition_penalty=1.05,
|
| 81 |
+
stream=False,
|
| 82 |
+
# truncate không bật để tránh cắt prompt
|
| 83 |
+
)
|
| 84 |
+
return out.strip()
|
| 85 |
+
except Exception as e:
|
| 86 |
+
return f"[Lỗi] Không thể gọi Inference API: {e}"
|
| 87 |
+
|
| 88 |
+
def translate(text: str, src: str, tgt: str, model_choice: str):
|
| 89 |
+
if not text or not text.strip():
|
| 90 |
+
return "Vui lòng nhập nội dung cần dịch."
|
| 91 |
+
if src == tgt:
|
| 92 |
+
return text.strip()
|
| 93 |
+
|
| 94 |
+
prompt = build_prompt(src, tgt, text)
|
| 95 |
+
# Lưu ý: Hunyuan-MT là causal LM định hướng prompt, không yêu cầu định dạng chat đặc biệt
|
| 96 |
+
result = call_hf_inference(model_choice, prompt)
|
| 97 |
+
return result
|
| 98 |
+
|
| 99 |
+
def ui():
|
| 100 |
+
with gr.Blocks(title="Hunyuan-MT Translation (HF Inference API)", fill_height=True) as demo:
|
| 101 |
+
gr.Markdown(
|
| 102 |
+
"""
|
| 103 |
+
# Tencent Hunyuan-MT (Serverless)
|
| 104 |
+
Chạy trên **Hugging Face Space (CPU free)** bằng **Serverless Inference API**.
|
| 105 |
+
- Chọn mô hình `tencent/Hunyuan-MT-7B` hoặc `tencent/Hunyuan-MT-7B-fp8`.
|
| 106 |
+
- Chọn ngôn ngữ nguồn/đích rồi bấm **Dịch**.
|
| 107 |
+
> Gợi ý: vào *Settings → Repository secrets* thêm `HF_TOKEN` để tăng hạn mức.
|
| 108 |
+
"""
|
| 109 |
+
)
|
| 110 |
+
|
| 111 |
with gr.Row():
|
| 112 |
+
model_choice = gr.Dropdown(
|
| 113 |
+
choices=[
|
| 114 |
+
"tencent/Hunyuan-MT-7B-fp8",
|
| 115 |
+
"tencent/Hunyuan-MT-7B",
|
| 116 |
+
],
|
| 117 |
+
value=DEFAULT_MODEL,
|
| 118 |
+
label="Model (Serverless)"
|
| 119 |
+
)
|
| 120 |
|
|
|
|
|
|
|
| 121 |
with gr.Row():
|
| 122 |
+
src = gr.Dropdown(choices=[l for l, _ in LANGS], value="English (English)", label="Nguồn")
|
| 123 |
+
tgt = gr.Dropdown(choices=[l for l, _ in LANGS], value="Vietnamese (Tiếng Việt)", label="Đích")
|
| 124 |
+
|
| 125 |
+
# Map label -> code cho back-end
|
| 126 |
+
label2code = {label: code for label, code in LANGS}
|
| 127 |
+
|
| 128 |
+
def _on_translate(text, src_label, tgt_label, model_id):
|
| 129 |
+
src_code = label2code[src_label]
|
| 130 |
+
tgt_code = label2code[tgt_label]
|
| 131 |
+
return translate(text, src_code, tgt_code, model_id)
|
| 132 |
+
|
| 133 |
+
inp = gr.Textbox(label="Nội dung cần dịch", lines=8, placeholder="Nhập văn bản…")
|
| 134 |
+
btn = gr.Button("Dịch", variant="primary")
|
| 135 |
+
out = gr.Textbox(label="Kết quả", lines=8)
|
| 136 |
+
|
| 137 |
+
btn.click(_on_translate, [inp, src, tgt, model_choice], [out])
|
| 138 |
+
|
| 139 |
+
gr.Markdown(
|
| 140 |
+
"""
|
| 141 |
+
#### Lưu ý
|
| 142 |
+
- Đây là demo qua **Serverless Inference API** nên tốc độ/phản hồi phụ thuộc hạn mức serverless.
|
| 143 |
+
- Với lượng lớn/nhanh hơn, hãy nâng cấp phần cứng (GPU) hoặc tự triển khai TGI/vLLM.
|
| 144 |
+
"""
|
| 145 |
+
)
|
| 146 |
+
return demo
|
| 147 |
+
|
| 148 |
+
if __name__ == "__main__":
|
| 149 |
+
ui().launch()
|