Spaces:
Sleeping
Sleeping
| import os | |
| import requests | |
| import gradio as gr | |
| import re | |
| # Registry for Key Status | |
| key_status_registry = {} | |
| class AIService: | |
| def get_all_keys(prefix): | |
| # ααααα½αααααααΎ Key αααα½αα αααααααΆαα Gemini αα·ααααΌααααααααααα | |
| # ααΆααΉααααααααΎααααααααΌα ααΆ GEMINI_API_KEY α¬ GROQ_API_KEY ααααΆαααααααα | |
| env_name = prefix.rstrip('_') # αααααααΆ _ α ααααΎααααΈα±ααααααΌαααΉαααααα Standard | |
| key = os.environ.get(env_name) | |
| if key: | |
| return [key] | |
| return [] | |
| def get_status_html(engine, target_lang=None): | |
| if "Gemini" in engine: | |
| prefix = "GEMINI_API_KEY" | |
| elif "Llama" in engine: | |
| prefix = "GROQ_API_KEY" | |
| else: | |
| prefix = "SEA_LION_API_KEY" | |
| keys = AIService.get_all_keys(prefix) | |
| label = engine.split(" ")[-1] | |
| status_label = "ααααΆαααΆα/Status" | |
| html = f"<div style='display: flex; gap: 8px; align-items: center; margin-bottom: 10px;'><b style='color: #94a3b8; font-size: 12px;'>{label} {status_label}:</b>" | |
| if not keys: | |
| html += "<span style='color: #ef4444; font-size: 10px;'>αααα·αααΎα Key</span>" | |
| else: | |
| for k in keys: | |
| state = key_status_registry.get(k, "ready") | |
| color = "#22c55e" if state == "ready" else "#ef4444" | |
| html += f"<div style='width: 10px; height: 10px; background: {color}; border-radius: 50%; box-shadow: 0 0 5px {color};'></div>" | |
| return html + "</div>" | |
| def call_api(engine, prompt): | |
| temp = 0.8 | |
| if "Gemini" in engine: | |
| keys = AIService.get_all_keys("GEMINI_API_KEY") | |
| for key in keys: | |
| try: | |
| # ααααΎαααΌααα Gemini 2.0 Flash ααααΌαααΆα | |
| url = f"https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key={key}" | |
| res = requests.post(url, json={ | |
| "contents": [{"parts": [{"text": prompt}]}], | |
| "generationConfig": {"temperature": temp}, | |
| "safetySettings": [ | |
| {"category": "HARM_CATEGORY_HARASSMENT", "threshold": "BLOCK_NONE"}, | |
| {"category": "HARM_CATEGORY_HATE_SPEECH", "threshold": "BLOCK_NONE"}, | |
| {"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", "threshold": "BLOCK_NONE"}, | |
| {"category": "HARM_CATEGORY_DANGEROUS_CONTENT", "threshold": "BLOCK_NONE"} | |
| ] | |
| }, timeout=45) | |
| if res.status_code == 200: | |
| key_status_registry[key] = "ready" | |
| return res.json()['candidates'][0]['content']['parts'][0]['text'].strip() | |
| key_status_registry[key] = "dead" | |
| except: continue | |
| elif "Llama" in engine: | |
| keys = AIService.get_all_keys("GROQ_API_KEY") | |
| for key in keys: | |
| try: | |
| res = requests.post("https://api.groq.com/openai/v1/chat/completions", | |
| headers={"Authorization": f"Bearer {key}"}, | |
| json={"model": "llama-3.3-70b-versatile", "messages": [{"role": "user", "content": prompt}], "temperature": temp}, timeout=30) | |
| if res.status_code == 200: | |
| key_status_registry[key] = "ready" | |
| return res.json()['choices'][0]['message']['content'].strip() | |
| key_status_registry[key] = "dead" | |
| except: continue | |
| else: | |
| key = os.environ.get("SEA_LION_API_KEY") | |
| try: | |
| res = requests.post("https://api.sea-lion.ai/v1/chat/completions", | |
| headers={"Authorization": f"Bearer {key}"}, | |
| json={ | |
| "model": "aisingapore/Gemma-SEA-LION-v4-27B-IT", | |
| "messages": [{"role": "system", "content": "You are an expert translator. Output ONLY translation."}, | |
| {"role": "user", "content": prompt}], | |
| "temperature": 0.7 | |
| }, timeout=60) | |
| if res.status_code == 200: | |
| key_status_registry[key] = "ready" | |
| return res.json()['choices'][0]['message']['content'].strip() | |
| key_status_registry[key] = "dead" | |
| except: pass | |
| return None | |
| def translator_hub(text, target_lang, engine): | |
| if not text.strip(): return "", AIService.get_status_html(engine) | |
| lang_name = re.sub(r'[^\w\s]', '', target_lang).strip() | |
| instruction = f"""Translate to {lang_name} STRICTLY: | |
| 1. OUTPUT ONLY translation. No notes. | |
| 2. SLANG & IDIOMS: Adapt naturally. | |
| 3. CONTEXT: Use proper pronouns (αα, α’αΌα, α’α, α―α) based on mood. | |
| 4. SRT FORMAT: Preserve timing/numbering. | |
| 5. NO MIXED LANGUAGES: No English words in output.""" | |
| prompt = f"{instruction}\n\nCONTENT:\n{text}" | |
| result = AIService.call_api(engine, prompt) | |
| if result: | |
| cleaned = re.sub(r'```[a-zA-Z]*\n?|```', '', result).strip() | |
| return cleaned, AIService.get_status_html(engine) | |
| return "β Error: αα·αα’αΆα ααΆαααααα API ααΆααα (αα·αα·ααα Key αααααα)", AIService.get_status_html(engine) | |
| # CSS configuration | |
| custom_css = """ | |
| body { background: #0f172a !important; } | |
| .gr-markdown h1 { background: linear-gradient(90deg, #60a5fa, #f472b6); -webkit-background-clip: text; color: transparent !important; } | |
| .btn-trans { background: #10b981 !important; color: white !important; } | |
| """ | |
| with gr.Blocks(title="SRT Pro") as demo: | |
| gr.Markdown("<h1>π¬ SMART TRANSLATOR PRO</h1>") | |
| with gr.Row(): | |
| with gr.Column(): | |
| lang_opt = gr.Dropdown(["π°π Khmer", "πΊπΈ English", "π¨π³ Chinese", "πΉπ Thai"], value="π°π Khmer", label="Language") | |
| engine_opt = gr.Radio(["π Gemini", "π¦ Llama", "π¦ SEA-LION"], value="π Gemini", label="Model") | |
| status_ui = gr.HTML(AIService.get_status_html("π Gemini")) | |
| input_box = gr.Textbox(label="Original Content", lines=10, placeholder="ααΆααα’ααααααα ααΈααα...") | |
| btn_trans = gr.Button("β‘ Translate", variant="primary", elem_classes="btn-trans") | |
| with gr.Column(): | |
| output_box = gr.Textbox(label="Result", lines=20, interactive=False) | |
| btn_copy = gr.Button("π Copy Result") | |
| engine_opt.change(AIService.get_status_html, inputs=[engine_opt], outputs=[status_ui]) | |
| btn_trans.click(translator_hub, [input_box, lang_opt, engine_opt], [output_box, status_ui]) | |
| btn_copy.click(None, output_box, js="(v) => { navigator.clipboard.writeText(v); alert('β α αααααα½α ααΆαα!'); }") | |
| if __name__ == "__main__": | |
| # αααα αΌα CSS αααα»α launch() ααΎααααΈαα½ααα»α Gradio 6.0 Warning | |
| demo.launch(server_name="0.0.0.0", server_port=7860, css=custom_css, ssr_mode=False) |