|
import gradio as gr |
|
import random |
|
|
|
|
|
from transformers import MarianMTModel, MarianTokenizer |
|
|
|
model_name = "Helsinki-NLP/opus-mt-th-en" |
|
tokenizer = MarianTokenizer.from_pretrained(model_name) |
|
model = MarianMTModel.from_pretrained(model_name) |
|
|
|
def translate_th_to_en(th_text: str) -> str: |
|
""" |
|
ใช้โมเดล MarianMT แปลภาษาไทย -> อังกฤษ |
|
รันบน CPU (Hugging Face Spaces) ได้โดยไม่ต้องใช้ GPU |
|
""" |
|
th_text = th_text.strip() |
|
if not th_text: |
|
return "" |
|
inputs = tokenizer(th_text, return_tensors="pt", max_length=512, truncation=True) |
|
translation_tokens = model.generate(**inputs, max_length=512) |
|
en_text = tokenizer.decode(translation_tokens[0], skip_special_tokens=True) |
|
return en_text |
|
|
|
|
|
|
|
|
|
|
|
def approximate_temperature(planet_type, distance_au): |
|
if planet_type == "ดาวหิน (Rocky Planet)": |
|
base_temp = 15 |
|
elif planet_type == "ดาวก๊าซ (Gas Giant)": |
|
base_temp = 30 |
|
elif planet_type == "ดาวน้ำแข็ง (Icy Planet)": |
|
base_temp = -50 |
|
else: |
|
base_temp = 0 |
|
|
|
if distance_au > 1.0: |
|
diff = (distance_au - 1.0) * 20 |
|
approx_temp = base_temp - diff |
|
else: |
|
diff = (1.0 - distance_au) * 30 |
|
approx_temp = base_temp + diff |
|
|
|
return round(approx_temp) |
|
|
|
def approximate_gravity(diameter_earth): |
|
return round(diameter_earth, 2) |
|
|
|
|
|
|
|
|
|
|
|
def child_friendly_summary( |
|
name_th, planet_type_th, temp_c, gravity_g, oxygen_percent, life_th |
|
): |
|
if temp_c > 40: |
|
temp_comment = "ร้อนจัดเลย!" |
|
elif temp_c < -10: |
|
temp_comment = "หนาวสุดขั้ว!" |
|
else: |
|
temp_comment = "อากาศกำลังดีเลย!" |
|
|
|
if gravity_g > 1.5: |
|
gravity_comment = f"แรงโน้มถ่วงประมาณ {gravity_g}g อาจเดินลำบากนะ!" |
|
elif gravity_g < 0.5: |
|
gravity_comment = f"แรงโน้มถ่วงแค่ {gravity_g}g ระวังลอยได้!" |
|
else: |
|
gravity_comment = f"แรงโน้มถ่วง ~{gravity_g}g กำลังโอเค" |
|
|
|
o2_comment = f"ออกซิเจน {oxygen_percent}%" |
|
|
|
summary_th = ( |
|
f"ดาว {name_th} เป็น{planet_type_th}\n" |
|
f"อุณหภูมิราว {temp_c}°C ({temp_comment})\n" |
|
f"{gravity_comment}\n" |
|
f"บรรยากาศมี {o2_comment}\n" |
|
f"มีสิ่งมีชีวิต: {life_th}\n" |
|
f"ว้าว! น่าสนใจมาก!" |
|
) |
|
return summary_th |
|
|
|
|
|
|
|
|
|
|
|
def generate_three_prompts_en( |
|
planet_name_en, planet_type_en, distance_au, diameter_factor, |
|
temp_c, gravity_g, oxygen_percent, life_en |
|
): |
|
base_info = ( |
|
f"Planet {planet_name_en}, {planet_type_en}, at ~{distance_au} AU from its star, " |
|
f"diameter ~{diameter_factor}x Earth, surface temp ~{temp_c}C, gravity ~{gravity_g}g, " |
|
f"oxygen ~{oxygen_percent}%. " |
|
) |
|
|
|
|
|
prompt1 = ( |
|
f"{base_info}A breathtaking orbital view of this planet showing its vibrant atmosphere, " |
|
f"highly detailed, cinematic lighting, wide shot --ar 16:9" |
|
) |
|
|
|
|
|
prompt2 = ( |
|
f"{base_info}Alien life form on the planet: {life_en}, " |
|
f"illustration focusing on creature design, environment details, " |
|
f"fantasy concept art, photorealistic --ar 9:16" |
|
) |
|
|
|
|
|
prompt3 = ( |
|
f"{base_info}Planetary surface landscape, unique terrain and color palette, " |
|
f"epic environment shot, detailed textures, natural light, hyperrealistic --ar 16:9" |
|
) |
|
|
|
return prompt1, prompt2, prompt3 |
|
|
|
|
|
|
|
|
|
|
|
def generate_planet_info( |
|
planet_name_th, |
|
planet_type_th, |
|
distance_str, |
|
diameter_str, |
|
oxygen_percent, |
|
life_th |
|
): |
|
|
|
try: |
|
distance_au = float(distance_str) |
|
except: |
|
distance_au = 1.0 |
|
|
|
try: |
|
diameter_factor = float(diameter_str) |
|
except: |
|
diameter_factor = 1.0 |
|
|
|
|
|
temp_c = approximate_temperature(planet_type_th, distance_au) |
|
gravity_g = approximate_gravity(diameter_factor) |
|
|
|
|
|
child_summary = child_friendly_summary( |
|
planet_name_th, planet_type_th, temp_c, |
|
gravity_g, oxygen_percent, life_th |
|
) |
|
|
|
|
|
detail_th = ( |
|
f"ชื่อดาวเคราะห์: {planet_name_th}\n" |
|
f"ชนิดดาว: {planet_type_th}\n" |
|
f"ระยะห่าง: ~{distance_au} AU\n" |
|
f"ขนาด: ~{diameter_factor} เท่าโลก\n" |
|
f"อุณหภูมิ: ~{temp_c} °C\n" |
|
f"แรงโน้มถ่วง: ~{gravity_g} g\n" |
|
f"เปอร์เซ็นต์ออกซิเจน: {oxygen_percent}%\n" |
|
f"สิ่งมีชีวิต: {life_th}\n" |
|
) |
|
|
|
|
|
planet_name_en = translate_th_to_en(planet_name_th) |
|
|
|
life_en = translate_th_to_en(life_th) |
|
|
|
|
|
type_map = { |
|
"ดาวหิน (Rocky Planet)": "rocky planet", |
|
"ดาวก๊าซ (Gas Giant)": "gas giant", |
|
"ดาวน้ำแข็ง (Icy Planet)": "icy planet", |
|
} |
|
planet_type_en = type_map.get(planet_type_th, "mysterious planet") |
|
|
|
|
|
prompt1, prompt2, prompt3 = generate_three_prompts_en( |
|
planet_name_en, planet_type_en, distance_au, diameter_factor, |
|
temp_c, gravity_g, oxygen_percent, life_en |
|
) |
|
|
|
prompt_all = ( |
|
f"--- Prompt #1 ---\n{prompt1}\n\n" |
|
f"--- Prompt #2 ---\n{prompt2}\n\n" |
|
f"--- Prompt #3 ---\n{prompt3}\n" |
|
) |
|
|
|
return child_summary, detail_th, prompt_all |
|
|
|
|
|
|
|
|
|
|
|
|
|
import gradio as gr |
|
|
|
css_code = """ |
|
body { |
|
background-color: #F9FBFF; |
|
font-family: "Kanit", sans-serif; |
|
} |
|
#title { |
|
color: #4A90E2; |
|
text-align: center; |
|
font-size: 2rem; |
|
margin-top: 20px; |
|
margin-bottom: 10px; |
|
font-weight: bold; |
|
} |
|
.game-desc { |
|
margin: 0 auto; |
|
width: 90%; |
|
background-color: #ECF6FF; |
|
border: 2px dashed #B3DAFF; |
|
border-radius: 10px; |
|
padding: 15px; |
|
color: #333; |
|
margin-bottom: 20px; |
|
} |
|
.btn-main { |
|
background-color: #FFE066; |
|
border: 2px solid #FFCA28; |
|
font-weight: bold; |
|
font-size: 1.1rem; |
|
padding: 10px 30px; |
|
border-radius: 10px; |
|
margin-right: 10px; |
|
} |
|
#child-summary, #detail-th, #prompt-en { |
|
background-color: #FFFDF5; |
|
border: 2px solid #FFE082; |
|
border-radius: 10px; |
|
padding: 10px; |
|
margin-bottom: 20px; |
|
} |
|
""" |
|
|
|
def welcome_text(): |
|
return "ยินดีต้อนรับสู่ Planetary Adventure! ลองกรอกข้อมูลแล้วกด 'สร้างโลกแฟนตาซี' สิ!" |
|
|
|
copy_button_html = """ |
|
<button style="background-color: #F06292; border: 2px solid #E91E63; font-weight: bold; |
|
font-size: 1.0rem; padding: 8px 20px; border-radius: 10px;" |
|
onclick="copyPromptText()"> |
|
คัดลอก Prompt |
|
</button> |
|
<script> |
|
function copyPromptText() { |
|
const promptBox = document.querySelector('#prompt-en textarea'); |
|
if (!promptBox) { |
|
alert('ไม่พบข้อความ Prompt!'); |
|
return; |
|
} |
|
const promptText = promptBox.value; |
|
navigator.clipboard.writeText(promptText); |
|
alert('คัดลอก Prompt แล้ว! เอาไปใช้กับ Midjourney ได้เลย~'); |
|
} |
|
</script> |
|
""" |
|
|
|
with gr.Blocks(css=css_code) as demo: |
|
gr.Markdown("<h1 id='title'>Planetary Adventure (Thai + %O2 + 3 English Prompts w/ Real Translation)</h1>") |
|
gr.Markdown(""" |
|
<div class="game-desc"> |
|
<p>ออกแบบดาวเคราะห์ในฝันของหนูน้อย (ภาษาไทย) แล้วให้ระบบแปลเป็นอังกฤษผ่าน MarianMT!</p> |
|
<ul> |
|
<li>กรอกชื่อดาว, ชนิดดาว, ระยะห่าง, ขนาด (เท่าโลก)</li> |
|
<li>เลื่อน %O2 ในบรรยากาศ</li> |
|
<li>พิมพ์สิ่งมีชีวิตเป็นภาษาไทย</li> |
|
<li>กดปุ่ม <strong>"สร้างโลกแฟนตาซี"</strong></li> |
|
</ul> |
|
<p>รับ <em>สรุปสำหรับเด็ก</em> (ไทย), <em>รายละเอียด</em> (ไทย), และ <em>3 Prompts อังกฤษ</em> นำไปใช้ใน Midjourney ได้ทันที!</p> |
|
</div> |
|
""") |
|
|
|
planet_name_th = gr.Textbox(label="ชื่อดาวเคราะห์ (ภาษาไทย)", placeholder="ตัวอย่าง: ดาวซานาดา") |
|
planet_type_th = gr.Dropdown( |
|
label="ชนิดดาว", |
|
choices=["ดาวหิน (Rocky Planet)", "ดาวก๊าซ (Gas Giant)", "ดาวน้ำแข็ง (Icy Planet)"], |
|
value="ดาวหิน (Rocky Planet)" |
|
) |
|
distance_au = gr.Textbox(label="ระยะห่างจากดาวฤกษ์ (หน่วย AU)", placeholder="เช่น 0.8, 1, 2") |
|
diameter_factor = gr.Textbox(label="ขนาด (เท่าเส้นผ่านศูนย์กลางโลก)", placeholder="เช่น 1, 2, 0.5") |
|
|
|
oxygen_slider = gr.Slider( |
|
minimum=0, |
|
maximum=100, |
|
step=1, |
|
value=21, |
|
label="% ออกซิเจนในบรรยากาศ" |
|
) |
|
|
|
life_th = gr.Textbox(label="สิ่งมีชีวิตบนดาว (ภาษาไทย)", placeholder="ตัวอย่าง: สัตว์เลื้อยคลานขนาดยักษ์") |
|
|
|
create_btn = gr.Button("สร้างโลกแฟนตาซี", elem_classes="btn-main") |
|
|
|
child_summary_out = gr.Textbox(label="สรุป (สำหรับเด็ก)", interactive=False, elem_id="child-summary") |
|
detail_th_out = gr.Textbox(label="รายละเอียด (ภาษาไทย)", interactive=False, elem_id="detail-th") |
|
prompt_en_out = gr.Textbox(label="3 Prompts (English)", interactive=False, elem_id="prompt-en") |
|
|
|
gr.HTML(copy_button_html) |
|
|
|
create_btn.click( |
|
fn=generate_planet_info, |
|
inputs=[ |
|
planet_name_th, |
|
planet_type_th, |
|
distance_au, |
|
diameter_factor, |
|
oxygen_slider, |
|
life_th |
|
], |
|
outputs=[child_summary_out, detail_th_out, prompt_en_out] |
|
) |
|
|
|
demo.load(fn=welcome_text, inputs=None, outputs=child_summary_out) |
|
|
|
demo.launch() |
|
|