Spaces:
Sleeping
Sleeping
File size: 8,641 Bytes
8e2391b dd7ea47 bc7679f 7b3b0be e436ee8 e67dc65 4a03fb5 37b2308 8dc8ce9 00bba9a dd0d837 8dc8ce9 394eebf 92e1442 30dc47c dd0d837 30dc47c dd0d837 30dc47c 4a03fb5 3435a4d 7b3b0be 0f15f5c 364c005 394eebf 37b2308 364c005 8326d73 0f15f5c dd0d837 34af201 364c005 34af201 8326d73 34af201 9ffd2f1 364c005 dd0d837 364c005 0f15f5c 364c005 dd7ea47 34af201 bc7679f 1dc43c7 dd7ea47 92e1442 da663a0 8326d73 a9e0c2a 8326d73 cca8473 34af201 dd7ea47 7b3b0be 36a7ff5 7b3b0be dd7ea47 dd0d837 34af201 92e1442 8326d73 dd0d837 aae96c1 dd0d837 30dc47c 8326d73 30dc47c dd7ea47 7b3b0be 8326d73 92e1442 dd7ea47 7b3b0be aae96c1 | 1 2 3 4 5 6 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 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 | import os
import requests
import gradio as gr
import re
from datetime import datetime
# === α‘. αααααα Logic αααααΆααααααΌαααΌαααΆα (Theme) ααΆααααΌαααΆα ===
def get_seasonal_config():
month = datetime.now().month
# αααΌααααΆ (αα·α
ααα·ααΆ, ααααΌ, ααααΆ) - αααααααααααΆαα
if month in [11, 12, 1]:
return {
"bg": "#0f172a", "accent": "#38bdf8", "btn": "#0369a1",
"title": "βοΈ WINTER FROST EDITION"
}
# αααΌααααα
(ααΈααΆ, ααααΆ, α§αααΆ) - αααααΆα/ααΉαααααΌα
elif month in [3, 4, 5]:
return {
"bg": "#1c1917", "accent": "#fbbf24", "btn": "#b45309",
"title": "βοΈ SUMMER BLAZE EDITION"
}
# αααΌαααααα/ααααΉαααΎαααα»α (αααααα) - αααααααααααα
else:
return {
"bg": "#064e3b", "accent": "#10b981", "btn": "#047857",
"title": "πΏ RAINY FOREST EDITION"
}
# ααΆαααααΆαααααααααααΆααααα
αα
α»αααααα
s_theme = get_seasonal_config()
# Registry for Key Status
key_status_registry = {}
class AIService:
@staticmethod
def get_all_keys(prefix):
env_name = prefix.rstrip('_')
key = os.environ.get(env_name)
if key:
return [key]
return []
@staticmethod
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"
# ααααΎααα accent ααΆααααΌαααΆααααααΆαα Label
html = f"<div style='display: flex; gap: 8px; align-items: center; margin-bottom: 10px;'><b style='color: {s_theme['accent']}; 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>"
@staticmethod
def call_api(engine, prompt):
temp = 0.85
if "Gemini" in engine:
keys = AIService.get_all_keys("GEMINI_API_KEY")
models = ["gemini-3-flash", "gemini-2.5-flash", "gemini-1.5-flash"]
for key in keys:
for model_name in models:
try:
url = f"https://generativelanguage.googleapis.com/v1beta/models/{model_name}:generateContent?key={key}"
res = requests.post(url, json={
"contents": [{"parts": [{"text": prompt}]}],
"generationConfig": {"temperature": temp}
}, timeout=30)
if res.status_code == 200:
key_status_registry[key] = "ready"
return res.json()['candidates'][0]['content']['parts'][0]['text'].strip()
except: continue
key_status_registry[key] = "dead"
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()
except: continue
else: # SEA-LION
keys = AIService.get_all_keys("SEA_LION_API_KEY")
for key in keys:
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": "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()
except: continue
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 the content into {lang_name} naturally.
STRICT RULES:
1. OUTPUT ONLY the translated text. NO explanations or notes.
2. If the input is SRT format, strictly preserve the timing and numbering.
3. CONTEXT & EMOTION: Understand the scene. Use natural slang and idioms (Modern/Classic).
4. PRONOUNS:
- Family: αα, ααα’αΌα, αα, α’αΌα, αααΆαα/ααα, αααΆ/αα»α, ααΌα, ααΌ, ααΈα...
- Couples/Home: ααααΈ, ααααααα, αα, α’αΌα...
- Conflict/Enemies: ααΎα, α’α, α’αα αα, α―α... (Allow swear words and insults if in context).
5. VARIATION: If asked again, try to find better synonyms or more natural flow."""
prompt = f"{instruction}\n\nCONTENT TO TRANSLATE:\n{text}"
result = AIService.call_api(engine, prompt)
if result:
return re.sub(r'```[a-zA-Z]*\n?|```', '', result).strip(), AIService.get_status_html(engine)
return "β Error: API Key α¬ Model αα·αααααΎαααΆα", AIService.get_status_html(engine)
# === α’. ααααααα½α CSS α±ααααΎαααΆα Dynamic Theme ===
custom_css = f"""
body, .gradio-container {{ background-color: {s_theme['bg']} !important; color: white !important; }}
.btn-trans {{ background-color: {s_theme['btn']} !important; color: white !important; border: 1px solid {s_theme['accent']} !important; }}
.btn-clear {{ background-color: #475569 !important; color: white !important; }}
h1 {{ color: {s_theme['accent']} !important; text-shadow: 0 0 10px {s_theme['accent']}55; }}
.fieldset, .input-label {{ color: {s_theme['accent']} !important; }}
"""
with gr.Blocks(title=f"SRT Pro - {s_theme['title']}", css=custom_css) as demo:
gr.Markdown(f"<h1 style='text-align: center;'>π¬ {s_theme['title']}</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 Engine")
status_ui = gr.HTML(AIService.get_status_html("π Gemini"))
input_box = gr.Textbox(label="Original Content", lines=10, placeholder="αααα
αΌαα’ααααα α¬ SRT αα
ααΈααα...")
with gr.Row():
btn_clear = gr.Button("ποΈ Clear", elem_classes="btn-clear")
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")
# Events
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('β
α
αααααα½α
ααΆαα!'); }}")
btn_clear.click(lambda: ("", ""), None, [input_box, output_box])
if __name__ == "__main__":
# Launch αααααα·ααΈ
demo.launch(server_name="0.0.0.0", server_port=7860, css=custom_css, ssr_mode=False) |