import gradio as gr from transformers import MarianMTModel, MarianTokenizer import torch import random # ตรวจสอบว่าใช้งาน GPU หรือไม่ (ในกรณีนี้ไม่มี GPU) device = torch.device("cpu") # เลือกโมเดลแปลภาษาที่มีขนาดเล็กลง # คุณสามารถค้นหาโมเดลที่เล็กกว่าได้ที่ Hugging Face Model Hub # ในตัวอย่างนี้ยังคงใช้ "Helsinki-NLP/opus-mt-th-en" แต่คุณสามารถเปลี่ยนได้ตามต้องการ model_name = "Helsinki-NLP/opus-mt-th-en" tokenizer = MarianTokenizer.from_pretrained(model_name) model = MarianMTModel.from_pretrained(model_name).to(device) model.eval() # ตั้งค่าโมเดลเป็นโหมดประเมินผล # แคชสำหรับการแปลข้อความที่ไม่อยู่ในรายการคงที่ translation_cache = {} def translate_batch(th_texts): """แปลข้อความแบบแบทช์เพื่อเพิ่มความเร็ว""" inputs = tokenizer(th_texts, return_tensors="pt", padding=True, truncation=True, max_length=512).to(device) with torch.no_grad(): translated = model.generate(**inputs, max_length=512) en_texts = [tokenizer.decode(t, skip_special_tokens=True) for t in translated] return en_texts def translate_th_to_en(th_text: str) -> str: th_text = th_text.strip() if not th_text: return "" # ตรวจสอบแคชก่อน if th_text in translation_cache: return translation_cache[th_text] # แปลข้อความ en_text = translate_batch([th_text])[0] # เก็บในแคช translation_cache[th_text] = en_text return en_text # ตัวเลือก (ภาษาไทย) สำหรับ Dropdown body_shapes_th = [ "ตัวเหนียวขยุกขยิก", "ตัวปุกปุยกลม", "ตัวเต็มไปด้วยหนาม", "ตัวเล็กเหมือนแมลง", "ตัวโปร่งแสงลอยได้", "ตัวโคลนยืดหยุ่น", "ตัวหินแข็งแรง", "ตัวทรงพีระมิด", "ตัวระยิบระยับ", "ตัวเหมือนฟองสบู่" ] heads_th = [ "หัวตาเดียว", "หัวสองเขาเหมือนมังกร", "หัวมีเขาใหญ่มาก", "หัวผีแสยะยิ้ม", "หัวกระต่ายน่ารัก", "หัวปลาหมึกสุดแปลก", "หัวเพลิงลุก", "หัวงูพ่นพิษ", "หัววุ้นใส", "หัวเมฆหมอก" ] arms_legs_th = [ "แขนหนวดปลาหมึกและขาปลาหมึก", "แขนกลและเท้าสเก็ต", "ปีกขนนกและอุ้งเท้าสิงโต", "แขนเรืองแสงและขายานโฮเวอร์", "แขนไม้หุ่นเชิดและขายักษ์แมงมุม", "แขนโลหะ", "แขนเหล็กข้อต่อ", "ปีกค้างคาว", "ขาไก่ยักษ์", "แขนขนนุ่ม" ] skin_patterns_th = [ "ลายสีรุ้ง", "จุดม่วงเรืองแสง", "เกล็ดเหล็ก", "ขนนกวิบวับ", "จุดกลมกากเพชร", "ลายหินอ่อน", "ลายไฟลุก", "ลายฟ้าแลบ", "ลายสเกลปลา", "ลายหมอก" ] abilities_th = [ "พ่นไฟ", "ปล่อยฟองสบู่", "ควบคุมสายฟ้า", "ร้องเพลงกล่อม", "วาร์ประยะสั้น", "เสกสิ่งของ", "ปล่อยพลังงานแสง", "ควบคุมแรงโน้มถ่วง", "เปลี่ยนรูปร่าง", "เสกภาพลวงตา" ] moods_th = [ "เป็นมิตร", "ขี้หงุดหงิด", "ตลกโปกฮา", "ซนเป็นลิง", "ขี้อาย", "ขี้เล่น", "เศร้าสร้อย", "จริงจัง", "มีความสุข", "ขี้ตกใจ" ] # แปลล่วงหน้าสำหรับรายการคงที่ # คุณสามารถแปลข้อความเหล่านี้ล่วงหน้านอกโปรแกรมและใส่ค่าลงไปตรงนี้เพื่อความรวดเร็ว body_shapes_en = { "ตัวเหนียวขยุกขยิก": "a squishy and wobbly body", "ตัวปุกปุยกลม": "a round and fluffy body", "ตัวเต็มไปด้วยหนาม": "a spiky body", "ตัวเล็กเหมือนแมลง": "a small, insect-like body", "ตัวโปร่งแสงลอยได้": "a translucent, floating body", "ตัวโคลนยืดหยุ่น": "a flexible, slime-like body", "ตัวหินแข็งแรง": "a strong, rocky body", "ตัวทรงพีระมิด": "a pyramidal body", "ตัวระยิบระยับ": "a sparkling body", "ตัวเหมือนฟองสบู่": "a bubble-like body" } heads_en = { "หัวตาเดียว": "a single-eyed head", "หัวสองเขาเหมือนมังกร": "a two-horned dragon-like head", "หัวมีเขาใหญ่มาก": "a head with very large horns", "หัวผีแสยะยิ้ม": "a smiling ghostly head", "หัวกระต่ายน่ารัก": "a cute rabbit head", "หัวปลาหมึกสุดแปลก": "a bizarre squid head", "หัวเพลิงลุก": "a flaming head", "หัวงูพ่นพิษ": "a venomous snake head", "หัววุ้นใส": "a transparent jelly head", "หัวเมฆหมอก": "a misty cloud head" } arms_legs_en = { "แขนหนวดปลาหมึกและขาปลาหมึก": "octopus-like tentacles and legs", "แขนกลและเท้าสเก็ต": "mechanical arms and skating feet", "ปีกขนนกและอุ้งเท้าสิงโต": "feathered wings and lion-like paws", "แขนเรืองแสงและขายานโฮเวอร์": "glowing arms and hover jets", "แขนไม้หุ่นเชิดและขายักษ์แมงมุม": "puppet wooden arms and giant spider legs", "แขนโลหะ": "metal arms", "แขนเหล็กข้อต่อ": "jointed iron arms", "ปีกค้างคาว": "bat wings", "ขาไก่ยักษ์": "giant chicken legs", "แขนขนนุ่ม": "soft feathered arms" } skin_patterns_en = { "ลายสีรุ้ง": "rainbow patterns", "จุดม่วงเรืองแสง": "glowing purple spots", "เกล็ดเหล็ก": "iron scales", "ขนนกวิบวับ": "shimmering feathers", "จุดกลมกากเพชร": "diamond-like round dots", "ลายหินอ่อน": "marble patterns", "ลายไฟลุก": "flaming patterns", "ลายฟ้าแลบ": "lightning patterns", "ลายสเกลปลา": "fish scale patterns", "ลายหมอก": "misty patterns" } abilities_en = { "พ่นไฟ": "breathe fire", "ปล่อยฟองสบู่": "release soap bubbles", "ควบคุมสายฟ้า": "control lightning", "ร้องเพลงกล่อม": "sing a lullaby", "วาร์ประยะสั้น": "short-range warp", "เสกสิ่งของ": "conjure objects", "ปล่อยพลังงานแสง": "emit light energy", "ควบคุมแรงโน้มถ่วง": "control gravity", "เปลี่ยนรูปร่าง": "shape-shift", "เสกภาพลวงตา": "create illusions" } moods_en = { "เป็นมิตร": "friendly", "ขี้หงุดหงิด": "irritable", "ตลกโปกฮา": "funny", "ซนเป็นลิง": "mischievous like a monkey", "ขี้อาย": "shy", "ขี้เล่น": "playful", "เศร้าสร้อย": "sorrowful", "จริงจัง": "serious", "มีความสุข": "happy", "ขี้ตกใจ": "easily startled" } def generate_monster_lab( body_dd, body_tb, head_dd, head_tb, arms_dd, arms_tb, skin_dd, skin_tb, ability_dd, ability_tb, mood_dd, mood_tb, ): # ถ้า textbox มีข้อความ -> ใช้ค่านั้น, ถ้าว่าง -> ใช้ dropdown body_th = body_tb.strip() if body_tb.strip() else body_dd head_th = head_tb.strip() if head_tb.strip() else head_dd arms_th = arms_tb.strip() if arms_tb.strip() else arms_dd skin_th = skin_tb.strip() if skin_tb.strip() else skin_dd ability_th = ability_tb.strip() if ability_tb.strip() else ability_dd mood_th = mood_tb.strip() if mood_tb.strip() else mood_dd desc_th = ( f"มอนสเตอร์อารมณ์{mood_th} มี{body_th} " f"พร้อมด้วย{head_th}, {arms_th}, " f"ผิว/ลายแบบ{skin_th}, และพลังพิเศษคือ{ability_th}!" ) # แปลเป็นภาษาอังกฤษ โดยใช้การแปลล่วงหน้าสำหรับรายการคงที่ body_en = body_shapes_en.get(body_th, translate_th_to_en(body_th)) head_en = heads_en.get(head_th, translate_th_to_en(head_th)) arms_en = arms_legs_en.get(arms_th, translate_th_to_en(arms_th)) skin_en = skin_patterns_en.get(skin_th, translate_th_to_en(skin_th)) ability_en = abilities_en.get(ability_th, translate_th_to_en(ability_th)) mood_en = moods_en.get(mood_th, translate_th_to_en(mood_th)) prompt_en = ( f"This is a {mood_en} monster with {body_en}, " f"a {head_en}, {arms_en}, covered in {skin_en} skin, " f"and it can {ability_en}!" ) return desc_th, prompt_en def random_monster(): bd = random.choice(body_shapes_th) hd = random.choice(heads_th) ar = random.choice(arms_legs_th) sk = random.choice(skin_patterns_th) ab = random.choice(abilities_th) md = random.choice(moods_th) # Clear textbox return (bd, "", hd, "", ar, "", sk, "", ab, "", md, "") # ---- CSS ---- css_code = """ body { background-color: #FFF7EA; font-family: "Kanit", sans-serif; } #title { color: #FF6F91; text-align: center; font-size: 2rem; margin-top: 20px; margin-bottom: 10px; font-weight: bold; } .game-desc { margin: 0 auto; width: 80%; background-color: #FFF2F0; border: 2px dashed #FAB1A0; border-radius: 10px; padding: 15px; color: #333; margin-bottom: 20px; } /* ปุ่มหลัก (สร้างมอนสเตอร์) */ .btn-main { background-color: #FFC107; border: 2px solid #FFA000; font-weight: bold; font-size: 1.1rem; /* กำหนดความสูงและความยาว (horizontal padding) เยอะๆ */ padding: 10px 40px; border-radius: 10px; margin-right: 10px; } /* ปุ่มสุ่ม (รอง) => ตัวเล็กลงในความยาว (horizontal padding) แต่ความสูงเท่ากัน */ .btn-random { background-color: #FFE08E; border: 2px solid #FFC107; font-weight: normal; font-size: 1.1rem; /* ใช้ padding vertical เท่ากัน แต่ลด horizontal padding ลง */ padding: 10px 15px; border-radius: 8px; } .btn-random:hover { background-color: #FFF3C4; } #desc-th, #prompt-en { background-color: #FFFAE6; border: 2px solid #FFE082; border-radius: 10px; padding: 10px; margin-bottom: 20px; } """ def initial_text(): return "ยังไม่ได้สร้างมอนสเตอร์ ลองเลือกหรือพิมพ์ แล้วกด 'สร้างมอนสเตอร์!' หรือจะกดสุ่มดูก็ได้จ้า" # ปุ่ม copy copy_button_html = """ """ with gr.Blocks(css=css_code) as demo: gr.Markdown("
หนูน้อยจ๊ะ เลือกได้ว่าจะใช้ค่าใน Dropdown หรือจะ พิมพ์เอง
หากอยากลุ้นโชค กดปุ่ม (ขวามือ) "สุ่มมอนสเตอร์สุดเซอร์ไพรส์!"
เมื่อพร้อมแล้ว กดปุ่ม (ซ้าย) "สร้างมอนสเตอร์!" เพื่อดูรายละเอียดและ Prompt