Update app.py
Browse files
app.py
CHANGED
@@ -1,15 +1,31 @@
|
|
1 |
import gradio as gr
|
2 |
import random
|
3 |
|
4 |
-
|
5 |
-
|
6 |
-
#########################
|
7 |
|
8 |
-
|
|
|
|
|
|
|
|
|
9 |
"""
|
10 |
-
|
|
|
11 |
"""
|
12 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
13 |
if planet_type == "ดาวหิน (Rocky Planet)":
|
14 |
base_temp = 15
|
15 |
elif planet_type == "ดาวก๊าซ (Gas Giant)":
|
@@ -19,7 +35,6 @@ def approximate_temperature(planet_type, distance_au):
|
|
19 |
else:
|
20 |
base_temp = 0
|
21 |
|
22 |
-
# ปรับตามระยะทาง
|
23 |
if distance_au > 1.0:
|
24 |
diff = (distance_au - 1.0) * 20
|
25 |
approx_temp = base_temp - diff
|
@@ -30,58 +45,89 @@ def approximate_temperature(planet_type, distance_au):
|
|
30 |
return round(approx_temp)
|
31 |
|
32 |
def approximate_gravity(diameter_earth):
|
33 |
-
|
34 |
-
แรงโน้มถ่วงสมมุติ (g) = diameter_earth เท่า
|
35 |
-
"""
|
36 |
-
return round(1.0 * diameter_earth, 2)
|
37 |
|
38 |
-
|
39 |
-
|
40 |
-
|
|
|
41 |
def child_friendly_summary(
|
42 |
-
name_th, planet_type_th, temp_c, gravity_g,
|
43 |
):
|
44 |
-
"""
|
45 |
-
สร้างข้อความสรุป (ภาษาไทย) ให้เด็กอ่านเข้าใจง่าย
|
46 |
-
เช่น "ดาว ซานาดา เป็นดาวหิน อุณหภูมิใกล้ๆ 20°C มีบรรยากาศ..."
|
47 |
-
"""
|
48 |
if temp_c > 40:
|
49 |
-
temp_comment = "
|
50 |
elif temp_c < -10:
|
51 |
-
temp_comment = "
|
52 |
else:
|
53 |
-
temp_comment = "
|
54 |
|
55 |
if gravity_g > 1.5:
|
56 |
-
gravity_comment = f"แรงโน้มถ่วงประมาณ {gravity_g}g
|
57 |
elif gravity_g < 0.5:
|
58 |
-
gravity_comment = f"
|
59 |
else:
|
60 |
-
gravity_comment = f"
|
|
|
|
|
61 |
|
62 |
summary_th = (
|
63 |
-
f"ดาว {name_th} เป็น{planet_type_th}
|
64 |
-
f"อุณหภูมิราว
|
65 |
f"{gravity_comment}\n"
|
66 |
-
f"
|
67 |
f"มีสิ่งมีชีวิต: {life_th}\n"
|
68 |
-
f"
|
69 |
)
|
70 |
return summary_th
|
71 |
|
72 |
|
73 |
-
|
74 |
-
# ฟังก์ชันสร้าง
|
75 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
76 |
def generate_planet_info(
|
77 |
-
planet_name_th,
|
78 |
-
planet_type_th,
|
79 |
-
distance_str,
|
80 |
-
diameter_str,
|
81 |
-
|
82 |
-
life_th
|
83 |
):
|
84 |
-
#
|
85 |
try:
|
86 |
distance_au = float(distance_str)
|
87 |
except:
|
@@ -92,52 +138,61 @@ def generate_planet_info(
|
|
92 |
except:
|
93 |
diameter_factor = 1.0
|
94 |
|
95 |
-
#
|
96 |
temp_c = approximate_temperature(planet_type_th, distance_au)
|
97 |
gravity_g = approximate_gravity(diameter_factor)
|
98 |
|
99 |
-
#
|
100 |
child_summary = child_friendly_summary(
|
101 |
-
planet_name_th, planet_type_th, temp_c,
|
|
|
102 |
)
|
103 |
|
104 |
-
#
|
105 |
detail_th = (
|
106 |
f"ชื่อดาวเคราะห์: {planet_name_th}\n"
|
107 |
f"ชนิดดาว: {planet_type_th}\n"
|
108 |
-
f"
|
109 |
f"ขนาด: ~{diameter_factor} เท่าโลก\n"
|
110 |
-
f"
|
111 |
f"แรงโน้มถ่วง: ~{gravity_g} g\n"
|
112 |
-
f"
|
113 |
f"สิ่งมีชีวิต: {life_th}\n"
|
114 |
)
|
115 |
|
116 |
-
#
|
117 |
-
|
|
|
|
|
|
|
|
|
118 |
type_map = {
|
119 |
-
"ดาวหิน (Rocky Planet)": "
|
120 |
-
"ดาวก๊าซ (Gas Giant)": "
|
121 |
-
"ดาวน้ำแข็ง (Icy Planet)": "
|
122 |
}
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
f"
|
|
|
|
|
133 |
)
|
134 |
|
135 |
-
return child_summary, detail_th,
|
136 |
|
137 |
|
138 |
-
|
139 |
-
#
|
140 |
-
|
|
|
|
|
141 |
|
142 |
css_code = """
|
143 |
body {
|
@@ -181,9 +236,8 @@ body {
|
|
181 |
"""
|
182 |
|
183 |
def welcome_text():
|
184 |
-
return "ยินดีต้อนรับสู่ Planetary Adventure! ลองกรอกข้อมูลแล้วกด 'สร้างโลกแฟนตาซี'
|
185 |
|
186 |
-
# ปุ่ม Copy Prompt (HTML + JS)
|
187 |
copy_button_html = """
|
188 |
<button style="background-color: #F06292; border: 2px solid #E91E63; font-weight: bold;
|
189 |
font-size: 1.0rem; padding: 8px 20px; border-radius: 10px;"
|
@@ -199,63 +253,66 @@ function copyPromptText() {
|
|
199 |
}
|
200 |
const promptText = promptBox.value;
|
201 |
navigator.clipboard.writeText(promptText);
|
202 |
-
alert('คัดลอก Prompt แล้ว!
|
203 |
}
|
204 |
</script>
|
205 |
"""
|
206 |
|
207 |
with gr.Blocks(css=css_code) as demo:
|
208 |
-
gr.Markdown("<h1 id='title'>Planetary Adventure (Thai
|
209 |
gr.Markdown("""
|
210 |
<div class="game-desc">
|
211 |
-
<p
|
212 |
-
<
|
213 |
-
<li
|
|
|
|
|
214 |
<li>กดปุ่ม <strong>"สร้างโลกแฟนตาซี"</strong></li>
|
215 |
-
|
216 |
-
|
217 |
-
</ol>
|
218 |
</div>
|
219 |
""")
|
220 |
|
221 |
-
|
222 |
-
|
223 |
label="ชนิดดาว",
|
224 |
choices=["ดาวหิน (Rocky Planet)", "ดาวก๊าซ (Gas Giant)", "ดาวน้ำแข็ง (Icy Planet)"],
|
225 |
value="ดาวหิน (Rocky Planet)"
|
226 |
)
|
227 |
-
distance_au = gr.Textbox(label="ระยะห่างจากดาวฤกษ์ (หน่วย AU)", placeholder="เช่น 0.8
|
228 |
-
diameter_factor = gr.Textbox(label="
|
229 |
-
|
230 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
231 |
|
232 |
create_btn = gr.Button("สร้างโลกแฟนตาซี", elem_classes="btn-main")
|
233 |
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
elem_id="child-summary"
|
238 |
-
)
|
239 |
-
detail_th_output = gr.Textbox(
|
240 |
-
label="รายละเอียด (เทคนิค)",
|
241 |
-
interactive=False,
|
242 |
-
elem_id="detail-th"
|
243 |
-
)
|
244 |
-
prompt_en_output = gr.Textbox(
|
245 |
-
label="Prompt ภาษาอังกฤษ",
|
246 |
-
interactive=False,
|
247 |
-
elem_id="prompt-en"
|
248 |
-
)
|
249 |
|
250 |
gr.HTML(copy_button_html)
|
251 |
|
252 |
-
# เมื่อกดปุ่ม
|
253 |
create_btn.click(
|
254 |
fn=generate_planet_info,
|
255 |
-
inputs=[
|
256 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
257 |
)
|
258 |
|
259 |
-
demo.load(fn=welcome_text, inputs=None, outputs=
|
260 |
|
261 |
demo.launch()
|
|
|
1 |
import gradio as gr
|
2 |
import random
|
3 |
|
4 |
+
# ==== เพิ่ม: โหลดโมเดล MarianMT และ Tokenizer สำหรับแปลไทย->อังกฤษ ====
|
5 |
+
from transformers import MarianMTModel, MarianTokenizer
|
|
|
6 |
|
7 |
+
model_name = "Helsinki-NLP/opus-mt-th-en"
|
8 |
+
tokenizer = MarianTokenizer.from_pretrained(model_name)
|
9 |
+
model = MarianMTModel.from_pretrained(model_name)
|
10 |
+
|
11 |
+
def translate_th_to_en(th_text: str) -> str:
|
12 |
"""
|
13 |
+
ใช้โมเดล MarianMT แปลภาษาไทย -> อังกฤษ
|
14 |
+
รันบน CPU (Hugging Face Spaces) ได้โดยไม่ต้องใช้ GPU
|
15 |
"""
|
16 |
+
th_text = th_text.strip()
|
17 |
+
if not th_text:
|
18 |
+
return ""
|
19 |
+
inputs = tokenizer(th_text, return_tensors="pt", max_length=512, truncation=True)
|
20 |
+
translation_tokens = model.generate(**inputs, max_length=512)
|
21 |
+
en_text = tokenizer.decode(translation_tokens[0], skip_special_tokens=True)
|
22 |
+
return en_text
|
23 |
+
|
24 |
+
|
25 |
+
##############################################
|
26 |
+
# ฟังก์ชันคำนวณ: อุณหภูมิ & แรงโน้มถ่วง
|
27 |
+
##############################################
|
28 |
+
def approximate_temperature(planet_type, distance_au):
|
29 |
if planet_type == "ดาวหิน (Rocky Planet)":
|
30 |
base_temp = 15
|
31 |
elif planet_type == "ดาวก๊าซ (Gas Giant)":
|
|
|
35 |
else:
|
36 |
base_temp = 0
|
37 |
|
|
|
38 |
if distance_au > 1.0:
|
39 |
diff = (distance_au - 1.0) * 20
|
40 |
approx_temp = base_temp - diff
|
|
|
45 |
return round(approx_temp)
|
46 |
|
47 |
def approximate_gravity(diameter_earth):
|
48 |
+
return round(diameter_earth, 2)
|
|
|
|
|
|
|
49 |
|
50 |
+
|
51 |
+
##############################################
|
52 |
+
# สรุปข้อมูล (ภาษาไทย) สำหรับเด็ก
|
53 |
+
##############################################
|
54 |
def child_friendly_summary(
|
55 |
+
name_th, planet_type_th, temp_c, gravity_g, oxygen_percent, life_th
|
56 |
):
|
|
|
|
|
|
|
|
|
57 |
if temp_c > 40:
|
58 |
+
temp_comment = "ร้อนจัดเลย!"
|
59 |
elif temp_c < -10:
|
60 |
+
temp_comment = "หนาวสุดขั้ว!"
|
61 |
else:
|
62 |
+
temp_comment = "อากาศกำลังดีเลย!"
|
63 |
|
64 |
if gravity_g > 1.5:
|
65 |
+
gravity_comment = f"แรงโน้มถ่วงประมาณ {gravity_g}g อาจเดินลำบากนะ!"
|
66 |
elif gravity_g < 0.5:
|
67 |
+
gravity_comment = f"แรงโน้มถ่วงแค่ {gravity_g}g ระวังลอยได้!"
|
68 |
else:
|
69 |
+
gravity_comment = f"แรงโน้มถ่วง ~{gravity_g}g กำลังโอเค"
|
70 |
+
|
71 |
+
o2_comment = f"ออกซิเจน {oxygen_percent}%"
|
72 |
|
73 |
summary_th = (
|
74 |
+
f"ดาว {name_th} เป็น{planet_type_th}\n"
|
75 |
+
f"อุณหภูมิราว {temp_c}°C ({temp_comment})\n"
|
76 |
f"{gravity_comment}\n"
|
77 |
+
f"บรรยากาศมี {o2_comment}\n"
|
78 |
f"มีสิ่งมีชีวิต: {life_th}\n"
|
79 |
+
f"ว้าว! น่าสนใจมาก!"
|
80 |
)
|
81 |
return summary_th
|
82 |
|
83 |
|
84 |
+
##############################################
|
85 |
+
# ฟังก์ชันสร้าง 3 Prompts (ภาษาอังกฤษ)
|
86 |
+
##############################################
|
87 |
+
def generate_three_prompts_en(
|
88 |
+
planet_name_en, planet_type_en, distance_au, diameter_factor,
|
89 |
+
temp_c, gravity_g, oxygen_percent, life_en
|
90 |
+
):
|
91 |
+
base_info = (
|
92 |
+
f"Planet {planet_name_en}, {planet_type_en}, at ~{distance_au} AU from its star, "
|
93 |
+
f"diameter ~{diameter_factor}x Earth, surface temp ~{temp_c}C, gravity ~{gravity_g}g, "
|
94 |
+
f"oxygen ~{oxygen_percent}%. "
|
95 |
+
)
|
96 |
+
|
97 |
+
# Prompt 1: ภาพดาวจากอวกาศ
|
98 |
+
prompt1 = (
|
99 |
+
f"{base_info}A breathtaking orbital view of this planet showing its vibrant atmosphere, "
|
100 |
+
f"highly detailed, cinematic lighting, wide shot --ar 16:9"
|
101 |
+
)
|
102 |
+
|
103 |
+
# Prompt 2: สิ่งมีชีวิต
|
104 |
+
prompt2 = (
|
105 |
+
f"{base_info}Alien life form on the planet: {life_en}, "
|
106 |
+
f"illustration focusing on creature design, environment details, "
|
107 |
+
f"fantasy concept art, photorealistic --ar 9:16"
|
108 |
+
)
|
109 |
+
|
110 |
+
# Prompt 3: พื้นผิวดาว
|
111 |
+
prompt3 = (
|
112 |
+
f"{base_info}Planetary surface landscape, unique terrain and color palette, "
|
113 |
+
f"epic environment shot, detailed textures, natural light, hyperrealistic --ar 16:9"
|
114 |
+
)
|
115 |
+
|
116 |
+
return prompt1, prompt2, prompt3
|
117 |
+
|
118 |
+
|
119 |
+
##############################################
|
120 |
+
# ฟังก์ชันหลัก (รับ input ไทย -> สร้างผลลัพธ์)
|
121 |
+
##############################################
|
122 |
def generate_planet_info(
|
123 |
+
planet_name_th, # ชื่อดาว (ไทย)
|
124 |
+
planet_type_th, # ชนิดดาว (ไทย)
|
125 |
+
distance_str, # ระยะห่าง (string)
|
126 |
+
diameter_str, # ขนาด (string)
|
127 |
+
oxygen_percent, # slider (int)
|
128 |
+
life_th # สิ่งมีชีวิต (ไทย)
|
129 |
):
|
130 |
+
# parse float
|
131 |
try:
|
132 |
distance_au = float(distance_str)
|
133 |
except:
|
|
|
138 |
except:
|
139 |
diameter_factor = 1.0
|
140 |
|
141 |
+
# คำนวณ
|
142 |
temp_c = approximate_temperature(planet_type_th, distance_au)
|
143 |
gravity_g = approximate_gravity(diameter_factor)
|
144 |
|
145 |
+
# 1) สรุปสำหรับเด็ก (ภาษาไทย)
|
146 |
child_summary = child_friendly_summary(
|
147 |
+
planet_name_th, planet_type_th, temp_c,
|
148 |
+
gravity_g, oxygen_percent, life_th
|
149 |
)
|
150 |
|
151 |
+
# 2) รายละเอียด (ไทย)
|
152 |
detail_th = (
|
153 |
f"ชื่อดาวเคราะห์: {planet_name_th}\n"
|
154 |
f"ชนิดดาว: {planet_type_th}\n"
|
155 |
+
f"ระยะห่าง: ~{distance_au} AU\n"
|
156 |
f"ขนาด: ~{diameter_factor} เท่าโลก\n"
|
157 |
+
f"อุณหภูมิ: ~{temp_c} °C\n"
|
158 |
f"แรงโน้มถ่วง: ~{gravity_g} g\n"
|
159 |
+
f"เปอร์เซ็นต์ออกซิเจน: {oxygen_percent}%\n"
|
160 |
f"สิ่งมีชีวิต: {life_th}\n"
|
161 |
)
|
162 |
|
163 |
+
# 3) แปลเป็นอังกฤษผ่าน MarianMT
|
164 |
+
planet_name_en = translate_th_to_en(planet_name_th)
|
165 |
+
# แปล life_th ด้วย
|
166 |
+
life_en = translate_th_to_en(life_th)
|
167 |
+
|
168 |
+
# แมปชนิดดาว -> อังกฤษ
|
169 |
type_map = {
|
170 |
+
"ดาวหิน (Rocky Planet)": "rocky planet",
|
171 |
+
"ดาวก๊าซ (Gas Giant)": "gas giant",
|
172 |
+
"ดาวน้ำแข็ง (Icy Planet)": "icy planet",
|
173 |
}
|
174 |
+
planet_type_en = type_map.get(planet_type_th, "mysterious planet")
|
175 |
+
|
176 |
+
# 4) สร้าง 3 prompts
|
177 |
+
prompt1, prompt2, prompt3 = generate_three_prompts_en(
|
178 |
+
planet_name_en, planet_type_en, distance_au, diameter_factor,
|
179 |
+
temp_c, gravity_g, oxygen_percent, life_en
|
180 |
+
)
|
181 |
+
|
182 |
+
prompt_all = (
|
183 |
+
f"--- Prompt #1 ---\n{prompt1}\n\n"
|
184 |
+
f"--- Prompt #2 ---\n{prompt2}\n\n"
|
185 |
+
f"--- Prompt #3 ---\n{prompt3}\n"
|
186 |
)
|
187 |
|
188 |
+
return child_summary, detail_th, prompt_all
|
189 |
|
190 |
|
191 |
+
##############################################
|
192 |
+
# ส่วน UI (Gradio)
|
193 |
+
##############################################
|
194 |
+
|
195 |
+
import gradio as gr
|
196 |
|
197 |
css_code = """
|
198 |
body {
|
|
|
236 |
"""
|
237 |
|
238 |
def welcome_text():
|
239 |
+
return "ยินดีต้อนรับสู่ Planetary Adventure! ลองกรอกข้อมูลแล้วกด 'สร้างโลกแฟนตาซี' สิ!"
|
240 |
|
|
|
241 |
copy_button_html = """
|
242 |
<button style="background-color: #F06292; border: 2px solid #E91E63; font-weight: bold;
|
243 |
font-size: 1.0rem; padding: 8px 20px; border-radius: 10px;"
|
|
|
253 |
}
|
254 |
const promptText = promptBox.value;
|
255 |
navigator.clipboard.writeText(promptText);
|
256 |
+
alert('คัดลอก Prompt แล้ว! เอาไปใช้กับ Midjourney ได้เลย~');
|
257 |
}
|
258 |
</script>
|
259 |
"""
|
260 |
|
261 |
with gr.Blocks(css=css_code) as demo:
|
262 |
+
gr.Markdown("<h1 id='title'>Planetary Adventure (Thai + %O2 + 3 English Prompts w/ Real Translation)</h1>")
|
263 |
gr.Markdown("""
|
264 |
<div class="game-desc">
|
265 |
+
<p>ออกแบบดาวเคราะห์ในฝันของหนูน้อย (ภาษาไทย) แล้วให้ระบบแปลเป็นอังกฤษผ่าน MarianMT!</p>
|
266 |
+
<ul>
|
267 |
+
<li>กรอกชื่อดาว, ชนิดดาว, ระยะห่าง, ขนาด (เท่าโลก)</li>
|
268 |
+
<li>เลื่อน %O2 ในบรรยากาศ</li>
|
269 |
+
<li>พิมพ์สิ่งมีชีวิตเป็นภาษาไทย</li>
|
270 |
<li>กดปุ่ม <strong>"สร้างโลกแฟนตาซี"</strong></li>
|
271 |
+
</ul>
|
272 |
+
<p>รับ <em>สรุปสำหรับเด็ก</em> (ไทย), <em>รายละเอียด</em> (ไทย), และ <em>3 Prompts อังกฤษ</em> นำไปใช้ใน Midjourney ได้ทันที!</p>
|
|
|
273 |
</div>
|
274 |
""")
|
275 |
|
276 |
+
planet_name_th = gr.Textbox(label="ชื่อดาวเคราะห์ (ภาษาไทย)", placeholder="ตัวอย่าง: ดาวซานาดา")
|
277 |
+
planet_type_th = gr.Dropdown(
|
278 |
label="ชนิดดาว",
|
279 |
choices=["ดาวหิน (Rocky Planet)", "ดาวก๊าซ (Gas Giant)", "ดาวน้ำแข็ง (Icy Planet)"],
|
280 |
value="ดาวหิน (Rocky Planet)"
|
281 |
)
|
282 |
+
distance_au = gr.Textbox(label="ระยะห่างจากดาวฤกษ์ (หน่วย AU)", placeholder="เช่น 0.8, 1, 2")
|
283 |
+
diameter_factor = gr.Textbox(label="ขนาด (เท่าเส้นผ่านศูนย์กลางโลก)", placeholder="เช่น 1, 2, 0.5")
|
284 |
+
|
285 |
+
oxygen_slider = gr.Slider(
|
286 |
+
minimum=0,
|
287 |
+
maximum=100,
|
288 |
+
step=1,
|
289 |
+
value=21,
|
290 |
+
label="% ออกซิเจนในบรรยากาศ"
|
291 |
+
)
|
292 |
+
|
293 |
+
life_th = gr.Textbox(label="สิ่งมีชีวิตบนดาว (ภาษาไทย)", placeholder="ตัวอย่าง: สัตว์เลื้อยคลานขนาดยักษ์")
|
294 |
|
295 |
create_btn = gr.Button("สร้างโลกแฟนตาซี", elem_classes="btn-main")
|
296 |
|
297 |
+
child_summary_out = gr.Textbox(label="สรุป (สำหรับเด็ก)", interactive=False, elem_id="child-summary")
|
298 |
+
detail_th_out = gr.Textbox(label="รายละเอียด (ภาษาไทย)", interactive=False, elem_id="detail-th")
|
299 |
+
prompt_en_out = gr.Textbox(label="3 Prompts (English)", interactive=False, elem_id="prompt-en")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
300 |
|
301 |
gr.HTML(copy_button_html)
|
302 |
|
|
|
303 |
create_btn.click(
|
304 |
fn=generate_planet_info,
|
305 |
+
inputs=[
|
306 |
+
planet_name_th,
|
307 |
+
planet_type_th,
|
308 |
+
distance_au,
|
309 |
+
diameter_factor,
|
310 |
+
oxygen_slider,
|
311 |
+
life_th
|
312 |
+
],
|
313 |
+
outputs=[child_summary_out, detail_th_out, prompt_en_out]
|
314 |
)
|
315 |
|
316 |
+
demo.load(fn=welcome_text, inputs=None, outputs=child_summary_out)
|
317 |
|
318 |
demo.launch()
|