Update app.py
Browse files
app.py
CHANGED
@@ -4,6 +4,31 @@ import datetime
|
|
4 |
from openai import OpenAI
|
5 |
from typing import Dict, List, Set
|
6 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
7 |
# Initialize OpenAI client
|
8 |
client = OpenAI()
|
9 |
|
@@ -15,6 +40,32 @@ st.set_page_config(
|
|
15 |
initial_sidebar_state="collapsed",
|
16 |
)
|
17 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
18 |
# Initialize session state variables
|
19 |
def init_session_state():
|
20 |
if 'story' not in st.session_state:
|
@@ -56,33 +107,29 @@ def generate_story_continuation(user_input: str, level: str) -> str:
|
|
56 |
return "I'm having trouble continuing the story. Please try again."
|
57 |
|
58 |
def get_vocabulary_suggestions() -> List[str]:
|
59 |
-
"""Get contextual vocabulary suggestions
|
60 |
try:
|
61 |
-
# Get the last few story entries for context
|
62 |
recent_story = '\n'.join([entry['content'] for entry in st.session_state.story[-3:]] if st.session_state.story else "Story just started")
|
63 |
|
64 |
response = client.chat.completions.create(
|
65 |
model="gpt-4o-mini",
|
66 |
messages=[
|
67 |
-
{"role": "system", "content": f"""You are a
|
68 |
-
|
69 |
-
|
70 |
-
-
|
71 |
-
|
72 |
-
|
73 |
-
Format: word1 (type), word2 (type), etc."""},
|
74 |
-
{"role": "user", "content": f"Story context:\n{recent_story}\n\nSuggest 5 relevant, interesting words:"}
|
75 |
],
|
76 |
-
max_tokens=
|
77 |
temperature=0.8
|
78 |
)
|
79 |
-
|
80 |
-
# Parse the response to get words and their types
|
81 |
-
word_suggestions = response.choices[0].message.content.split(', ')
|
82 |
-
return word_suggestions
|
83 |
except Exception as e:
|
84 |
st.error(f"Error getting vocabulary suggestions: {str(e)}")
|
85 |
-
return ["
|
|
|
|
|
86 |
|
87 |
# In the main UI section, update how vocabulary suggestions are displayed:
|
88 |
if st.button("Get Vocabulary Ideas"):
|
@@ -99,22 +146,40 @@ def get_vocabulary_suggestions() -> List[str]:
|
|
99 |
</div>
|
100 |
""".format(st.session_state.feedback), unsafe_allow_html=True)
|
101 |
|
102 |
-
|
103 |
-
|
|
|
104 |
try:
|
105 |
response = client.chat.completions.create(
|
106 |
model="gpt-4o-mini",
|
107 |
messages=[
|
108 |
-
{"role": "system", "content": "
|
109 |
-
{"role": "user", "content": "
|
110 |
],
|
111 |
-
max_tokens=
|
112 |
temperature=0.7
|
113 |
)
|
114 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
115 |
except Exception as e:
|
116 |
st.error(f"Error generating creative prompt: {str(e)}")
|
117 |
-
return
|
|
|
|
|
|
|
118 |
|
119 |
def provide_feedback(text: str, level: str) -> Dict[str, str]:
|
120 |
"""Provide educational feedback with grammar explanation and encouragement."""
|
@@ -197,20 +262,21 @@ if st.session_state.should_reset:
|
|
197 |
reset_story()
|
198 |
|
199 |
# Main UI Layout
|
200 |
-
st.
|
|
|
201 |
|
202 |
# Sidebar for settings
|
203 |
with st.sidebar:
|
204 |
-
st.
|
|
|
|
|
|
|
|
|
205 |
level = st.radio(
|
206 |
"Select your English level:",
|
207 |
-
('Beginner', 'Intermediate', 'Advanced')
|
|
|
208 |
)
|
209 |
-
st.session_state.level = level
|
210 |
-
|
211 |
-
if st.button("Start New Story"):
|
212 |
-
st.session_state.should_reset = True
|
213 |
-
st.rerun()
|
214 |
|
215 |
# Main content area
|
216 |
col1, col2 = st.columns([3, 1])
|
@@ -254,22 +320,27 @@ with col1:
|
|
254 |
st.warning("Please write something to continue the story.")
|
255 |
|
256 |
with col2:
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
|
|
|
|
|
261 |
|
262 |
-
# Help and Suggestions Box
|
263 |
-
st.header("Writing Help")
|
264 |
if st.button("Get Vocabulary Ideas"):
|
265 |
vocab_suggestions = get_vocabulary_suggestions()
|
266 |
-
st.
|
267 |
for word in vocab_suggestions:
|
268 |
-
st.
|
269 |
|
270 |
-
if st.button("Get
|
271 |
-
|
272 |
-
st.
|
|
|
|
|
|
|
|
|
|
|
273 |
|
274 |
# Achievements Box
|
275 |
st.header("Your Achievements")
|
|
|
4 |
from openai import OpenAI
|
5 |
from typing import Dict, List, Set
|
6 |
|
7 |
+
# Custom CSS for Thai-English bilingual display
|
8 |
+
st.markdown("""
|
9 |
+
<style>
|
10 |
+
.thai-eng {
|
11 |
+
font-size: 1.1em;
|
12 |
+
padding: 10px;
|
13 |
+
background-color: #f8f9fa;
|
14 |
+
border-radius: 8px;
|
15 |
+
margin: 10px 0;
|
16 |
+
}
|
17 |
+
.thai {
|
18 |
+
color: #1e88e5;
|
19 |
+
font-family: 'Sarabun', sans-serif;
|
20 |
+
}
|
21 |
+
.eng {
|
22 |
+
color: #333;
|
23 |
+
}
|
24 |
+
.highlight {
|
25 |
+
background-color: #e3f2fd;
|
26 |
+
padding: 2px 5px;
|
27 |
+
border-radius: 4px;
|
28 |
+
}
|
29 |
+
</style>
|
30 |
+
""", unsafe_allow_html=True)
|
31 |
+
|
32 |
# Initialize OpenAI client
|
33 |
client = OpenAI()
|
34 |
|
|
|
40 |
initial_sidebar_state="collapsed",
|
41 |
)
|
42 |
|
43 |
+
def show_welcome_section():
|
44 |
+
st.markdown("""
|
45 |
+
<div class="thai-eng">
|
46 |
+
<div class="thai">
|
47 |
+
🌟 ยินดีต้อนรับสู่ JoyStory - แอพฝึกเขียนภาษาอังกฤษแสนสนุก!
|
48 |
+
<br>
|
49 |
+
เรียนรู้ภาษาอังกฤษผ่านการเขียนเรื่องราวด้วยตัวเอง พร้อมผู้ช่วย AI ที่จะช่วยแนะนำและให้กำลังใจ
|
50 |
+
</div>
|
51 |
+
<div class="eng">
|
52 |
+
Welcome to JoyStory - Fun English Writing Adventure!
|
53 |
+
</div>
|
54 |
+
</div>
|
55 |
+
""", unsafe_allow_html=True)
|
56 |
+
|
57 |
+
st.markdown("""
|
58 |
+
<div class="thai-eng">
|
59 |
+
<div class="thai">
|
60 |
+
📝 วิธีการใช้งาน:
|
61 |
+
<br>• เลือกระดับภาษาของน้องๆ ที่เมนูด้านข้าง
|
62 |
+
<br>• เริ่มเขียนเรื่องราวที่น้องๆ อยากเล่า
|
63 |
+
<br>• AI จะช่วยต่อเรื่องและให้คำแนะนำ
|
64 |
+
<br>• สะสมคะแนนและรางวัลจากการเขียน
|
65 |
+
</div>
|
66 |
+
</div>
|
67 |
+
""", unsafe_allow_html=True)
|
68 |
+
|
69 |
# Initialize session state variables
|
70 |
def init_session_state():
|
71 |
if 'story' not in st.session_state:
|
|
|
107 |
return "I'm having trouble continuing the story. Please try again."
|
108 |
|
109 |
def get_vocabulary_suggestions() -> List[str]:
|
110 |
+
"""Get contextual vocabulary suggestions with Thai translations."""
|
111 |
try:
|
|
|
112 |
recent_story = '\n'.join([entry['content'] for entry in st.session_state.story[-3:]] if st.session_state.story else "Story just started")
|
113 |
|
114 |
response = client.chat.completions.create(
|
115 |
model="gpt-4o-mini",
|
116 |
messages=[
|
117 |
+
{"role": "system", "content": f"""You are a Thai-English bilingual teacher.
|
118 |
+
Suggest 5 English words with their Thai translations and examples.
|
119 |
+
Format each suggestion as:
|
120 |
+
word (type) - คำแปล | example sentence
|
121 |
+
Make sure words match {st.session_state.level} level."""},
|
122 |
+
{"role": "user", "content": f"Story context:\n{recent_story}\n\nSuggest 5 relevant words with Thai translations:"}
|
|
|
|
|
123 |
],
|
124 |
+
max_tokens=200,
|
125 |
temperature=0.8
|
126 |
)
|
127 |
+
return response.choices[0].message.content.split('\n')
|
|
|
|
|
|
|
128 |
except Exception as e:
|
129 |
st.error(f"Error getting vocabulary suggestions: {str(e)}")
|
130 |
+
return ["happy (adj) - มีความสุข | I am happy today",
|
131 |
+
"run (verb) - วิ่ง | The dog runs fast",
|
132 |
+
"tree (noun) - ต้นไม้ | A tall tree"]
|
133 |
|
134 |
# In the main UI section, update how vocabulary suggestions are displayed:
|
135 |
if st.button("Get Vocabulary Ideas"):
|
|
|
146 |
</div>
|
147 |
""".format(st.session_state.feedback), unsafe_allow_html=True)
|
148 |
|
149 |
+
# Update the creative prompt function
|
150 |
+
def get_creative_prompt() -> Dict[str, str]:
|
151 |
+
"""Generate a bilingual creative prompt."""
|
152 |
try:
|
153 |
response = client.chat.completions.create(
|
154 |
model="gpt-4o-mini",
|
155 |
messages=[
|
156 |
+
{"role": "system", "content": "Create a story prompt in both English and Thai."},
|
157 |
+
{"role": "user", "content": "Generate a simple, engaging story prompt for children:"}
|
158 |
],
|
159 |
+
max_tokens=100,
|
160 |
temperature=0.7
|
161 |
)
|
162 |
+
prompt_eng = response.choices[0].message.content
|
163 |
+
|
164 |
+
# Get Thai translation
|
165 |
+
response_thai = client.chat.completions.create(
|
166 |
+
model="gpt-4o-mini",
|
167 |
+
messages=[
|
168 |
+
{"role": "system", "content": "Translate this prompt to natural, child-friendly Thai:"},
|
169 |
+
{"role": "user", "content": prompt_eng}
|
170 |
+
],
|
171 |
+
max_tokens=100,
|
172 |
+
temperature=0.7
|
173 |
+
)
|
174 |
+
prompt_thai = response_thai.choices[0].message.content
|
175 |
+
|
176 |
+
return {"eng": prompt_eng, "thai": prompt_thai}
|
177 |
except Exception as e:
|
178 |
st.error(f"Error generating creative prompt: {str(e)}")
|
179 |
+
return {
|
180 |
+
"eng": "What happens next in your story?",
|
181 |
+
"thai": "เรื่องราวต่อไปจะเป็นอย่างไร?"
|
182 |
+
}
|
183 |
|
184 |
def provide_feedback(text: str, level: str) -> Dict[str, str]:
|
185 |
"""Provide educational feedback with grammar explanation and encouragement."""
|
|
|
262 |
reset_story()
|
263 |
|
264 |
# Main UI Layout
|
265 |
+
st.markdown("# 📖 JoyStory")
|
266 |
+
show_welcome_section()
|
267 |
|
268 |
# Sidebar for settings
|
269 |
with st.sidebar:
|
270 |
+
st.markdown("""
|
271 |
+
<div class="thai">
|
272 |
+
🎯 เลือกระดับของน้องๆ
|
273 |
+
</div>
|
274 |
+
""", unsafe_allow_html=True)
|
275 |
level = st.radio(
|
276 |
"Select your English level:",
|
277 |
+
('Beginner', 'Intermediate', 'Advanced'),
|
278 |
+
index=['Beginner', 'Intermediate', 'Advanced'].index(st.session_state.level)
|
279 |
)
|
|
|
|
|
|
|
|
|
|
|
280 |
|
281 |
# Main content area
|
282 |
col1, col2 = st.columns([3, 1])
|
|
|
320 |
st.warning("Please write something to continue the story.")
|
321 |
|
322 |
with col2:
|
323 |
+
st.markdown("""
|
324 |
+
<div class="thai-eng">
|
325 |
+
<div class="thai">✨ เครื่องมือช่วยเขียน</div>
|
326 |
+
<div class="eng">Writing Tools</div>
|
327 |
+
</div>
|
328 |
+
""", unsafe_allow_html=True)
|
329 |
|
|
|
|
|
330 |
if st.button("Get Vocabulary Ideas"):
|
331 |
vocab_suggestions = get_vocabulary_suggestions()
|
332 |
+
st.markdown("#### 📚 คำศัพท์น่ารู้ | Useful Words")
|
333 |
for word in vocab_suggestions:
|
334 |
+
st.markdown(f"• {word}")
|
335 |
|
336 |
+
if st.button("Get Writing Prompt"):
|
337 |
+
prompt = get_creative_prompt()
|
338 |
+
st.markdown("""
|
339 |
+
<div class="thai-eng">
|
340 |
+
<div class="thai">💭 {}</div>
|
341 |
+
<div class="eng">💭 {}</div>
|
342 |
+
</div>
|
343 |
+
""".format(prompt["thai"], prompt["eng"]), unsafe_allow_html=True)
|
344 |
|
345 |
# Achievements Box
|
346 |
st.header("Your Achievements")
|