ProfSule commited on
Commit
de74c3c
Β·
verified Β·
1 Parent(s): 947f7dd

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +325 -0
app.py ADDED
@@ -0,0 +1,325 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import openai
3
+ import json
4
+ import random
5
+ from datetime import datetime
6
+
7
+ # Configure OpenRouter API
8
+ openai.api_base = "https://openrouter.ai/api/v1"
9
+ openai.api_key = "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" # Replace with your actual key
10
+
11
+ class ScienceTalkGame:
12
+ def __init__(self):
13
+ self.reset_session()
14
+
15
+ def reset_session(self):
16
+ self.session = {
17
+ "engagement_scores": {"Maya": 3, "Jamal": 4, "Aisha": 2, "Emma": 4},
18
+ "teaching_points": 0,
19
+ "choices_made": [],
20
+ "current_scenario": "grade2_plants",
21
+ "turn_count": 0
22
+ }
23
+
24
+ def get_current_scenario(self):
25
+ return {
26
+ "title": "🌱 Grade 2: Plant Investigation",
27
+ "setup": """Your 2nd grade students are examining classroom plants. Some are healthy and green, others are yellow and droopy. You've gathered them for a science talk to explore what they notice.""",
28
+ "learning_goals": "Students will observe plant differences, share ideas about plant needs, and connect to their cultural knowledge about plants.",
29
+ "students": {
30
+ "Maya": "Mexican-American, bilingual, has grandmother's gardening knowledge, sometimes shy about sharing in English",
31
+ "Jamal": "African-American, urban background, very curious and asks lots of questions, eager to share",
32
+ "Aisha": "Somali-American, thoughtful observer, needs processing time, connects to family farming knowledge",
33
+ "Emma": "White suburban, enthusiastic about science, has science books at home, sometimes dominates discussions"
34
+ }
35
+ }
36
+
37
+ def generate_student_responses(self, teacher_input):
38
+ scenario = self.get_current_scenario()
39
+
40
+ # Create context-aware prompt based on engagement levels
41
+ engagement_context = []
42
+ for student, level in self.session["engagement_scores"].items():
43
+ if level >= 4:
44
+ engagement_context.append(f"{student} is highly engaged and eager to participate")
45
+ elif level >= 3:
46
+ engagement_context.append(f"{student} is moderately engaged")
47
+ elif level >= 2:
48
+ engagement_context.append(f"{student} is somewhat hesitant but paying attention")
49
+ else:
50
+ engagement_context.append(f"{student} is disengaged and may not participate")
51
+
52
+ prompt = f"""You are role-playing four 2nd grade students (age 7-8) in a science discussion about plants. Respond as all four students would, showing their different personalities and backgrounds:
53
+
54
+ **Maya**: Mexican-American, bilingual, her grandmother has a big garden with vegetables and herbs. Sometimes mixes Spanish words, a bit shy but has valuable knowledge to share.
55
+
56
+ **Jamal**: African-American, lives in the city, very curious and energetic, asks lots of "what if" questions, eager to share observations.
57
+
58
+ **Aisha**: Somali-American, family has farming background, thoughtful and observant, needs a moment to process before speaking, often makes connections to family experiences.
59
+
60
+ **Emma**: White suburban, has lots of science books, enthusiastic but sometimes talks over others, uses formal science vocabulary.
61
+
62
+ Current engagement levels: {', '.join(engagement_context)}
63
+
64
+ The teacher just said: "{teacher_input}"
65
+
66
+ Respond as each student would, showing their authentic 2nd grade thinking, cultural backgrounds, and current engagement levels. Format your response as:
67
+
68
+ **Maya:** [her response]
69
+ **Jamal:** [his response]
70
+ **Aisha:** [her response]
71
+ **Emma:** [her response]
72
+
73
+ Make the responses feel natural for 7-year-olds discussing plants they're looking at."""
74
+
75
+ try:
76
+ response = openai.ChatCompletion.create(
77
+ model="openai/gpt-3.5-turbo",
78
+ messages=[{"role": "user", "content": prompt}],
79
+ temperature=0.8,
80
+ max_tokens=400
81
+ )
82
+ return response.choices[0].message.content
83
+ except Exception as e:
84
+ return f"**Error generating student responses:** {str(e)}\n\nPlease check your OpenRouter API key configuration."
85
+
86
+ def generate_teaching_choices(self, context=""):
87
+ """Generate contextual teaching choices based on the situation"""
88
+ base_choices = [
89
+ "🌟 Build on cultural knowledge: Ask Maya about her grandmother's gardening wisdom",
90
+ "🀝 Create inclusive space: Make sure all students get a chance to share their thinking",
91
+ "πŸ”¬ Promote investigation: Guide students to plan how they could test their ideas",
92
+ "βš–οΈ Manage participation: Redirect from dominant voices to quieter students"
93
+ ]
94
+
95
+ # Add scenario-specific choices
96
+ contextual_choices = [
97
+ "🌱 Connect to home experiences: Ask what students notice about plants where they live",
98
+ "πŸ’­ Support thinking time: Give students a moment to observe before sharing",
99
+ "πŸ—£οΈ Encourage peer discussion: Have students share ideas with a partner first",
100
+ "πŸ“Š Document observations: Help students record what they notice systematically"
101
+ ]
102
+
103
+ # Randomly select 4 choices to keep it fresh
104
+ all_choices = base_choices + contextual_choices
105
+ return random.sample(all_choices, 4)
106
+
107
+ def assess_teaching_choice(self, choice_text):
108
+ """Assess the pedagogical quality of the teaching choice"""
109
+ feedback = ""
110
+ points = 0
111
+ engagement_impact = {}
112
+
113
+ # Analyze choice for different pedagogical moves
114
+ choice_lower = choice_text.lower()
115
+
116
+ if "cultural" in choice_lower or "grandmother" in choice_lower:
117
+ feedback = "🌟 Excellent! You're building on Maya's cultural assets. This validates her family knowledge and shows other students that diverse knowledge is valued in science."
118
+ points = 3
119
+ engagement_impact = {"Maya": 2, "Aisha": 1} # Cultural validation helps both students
120
+
121
+ elif "inclusive" in choice_lower or "all students" in choice_lower:
122
+ feedback = "βœ… Great equity move! Creating space for all voices helps build a classroom community where everyone's thinking is valued."
123
+ points = 2
124
+ engagement_impact = {"Aisha": 2, "Maya": 1} # Helps quieter students
125
+
126
+ elif "investigation" in choice_lower or "test" in choice_lower:
127
+ feedback = "πŸ”¬ Good scientific thinking! You're helping students engage in authentic science practices."
128
+ points = 2
129
+ engagement_impact = {"Jamal": 1, "Emma": 1} # Appeals to curious students
130
+
131
+ elif "manage" in choice_lower or "redirect" in choice_lower:
132
+ feedback = "βš–οΈ Important facilitation move! Managing participation ensures equitable discourse."
133
+ points = 2
134
+ engagement_impact = {"Emma": -1, "Aisha": 2, "Maya": 1} # Redistributes participation
135
+
136
+ elif "home" in choice_lower or "where they live" in choice_lower:
137
+ feedback = "🏠 Nice connection! Linking to students' lived experiences makes science relevant and accessible."
138
+ points = 2
139
+ engagement_impact = {"Maya": 1, "Aisha": 1, "Jamal": 1}
140
+
141
+ elif "thinking time" in choice_lower or "moment to" in choice_lower:
142
+ feedback = "πŸ’­ Thoughtful move! Wait time benefits all students, especially those who need processing time."
143
+ points = 2
144
+ engagement_impact = {"Aisha": 2, "Maya": 1}
145
+
146
+ elif "peer discussion" in choice_lower or "partner" in choice_lower:
147
+ feedback = "πŸ—£οΈ Smart strategy! Peer talk builds confidence before whole-group sharing."
148
+ points = 2
149
+ engagement_impact = {"Maya": 1, "Aisha": 1}
150
+
151
+ else:
152
+ feedback = "Consider how this choice supports equitable participation and builds on student thinking."
153
+ points = 1
154
+ engagement_impact = {}
155
+
156
+ return feedback, points, engagement_impact
157
+
158
+ def update_engagement(self, impact_dict):
159
+ """Update student engagement based on teaching choices"""
160
+ for student, change in impact_dict.items():
161
+ current = self.session["engagement_scores"][student]
162
+ new_score = max(1, min(5, current + change)) # Keep between 1-5
163
+ self.session["engagement_scores"][student] = new_score
164
+
165
+ def get_engagement_display(self):
166
+ """Create visual representation of student engagement"""
167
+ display = "## πŸ“Š Student Engagement Levels\n\n"
168
+ for student, score in self.session["engagement_scores"].items():
169
+ stars = "⭐" * score + "β˜†" * (5-score)
170
+ display += f"**{student}:** {stars} ({score}/5)\n\n"
171
+ return display
172
+
173
+ def get_scenario_info(self):
174
+ scenario = self.get_current_scenario()
175
+ return f"""## {scenario['title']}
176
+
177
+ **Situation:** {scenario['setup']}
178
+
179
+ **Learning Goals:** {scenario['learning_goals']}
180
+
181
+ **Your Students:**
182
+ - **Maya:** {scenario['students']['Maya']}
183
+ - **Jamal:** {scenario['students']['Jamal']}
184
+ - **Aisha:** {scenario['students']['Aisha']}
185
+ - **Emma:** {scenario['students']['Emma']}
186
+ """
187
+
188
+ # Initialize game
189
+ game = ScienceTalkGame()
190
+
191
+ def start_new_session():
192
+ """Reset the game for a new session"""
193
+ game.reset_session()
194
+ scenario_info = game.get_scenario_info()
195
+ engagement_display = game.get_engagement_display()
196
+ welcome_msg = """## Welcome to Science Talk Adventure! 🌟
197
+
198
+ You're about to practice facilitating an equitable science discussion with a diverse group of 2nd graders. Your goal is to:
199
+
200
+ 1. **Include all student voices** - especially those who might be hesitant to share
201
+ 2. **Build on cultural assets** - honor the knowledge students bring from home
202
+ 3. **Promote scientific thinking** - help students observe, question, and investigate
203
+ 4. **Manage participation** - ensure discussions are equitable
204
+
205
+ **To begin:** Type what you would say to start the science talk, then click 'Send Response'."""
206
+
207
+ return scenario_info, engagement_display, welcome_msg, f"**Teaching Points:** {game.session['teaching_points']}", ""
208
+
209
+ def process_teacher_input(teacher_input):
210
+ """Process teacher's response and generate student reactions"""
211
+ if not teacher_input or not teacher_input.strip():
212
+ return "Please enter what you would say to your students.", "", ""
213
+
214
+ # Generate student responses
215
+ student_response = game.generate_student_responses(teacher_input)
216
+
217
+ # Generate teaching choice options
218
+ choices = game.generate_teaching_choices()
219
+ choice_display = "## 🎯 How do you respond? Choose your next move:\n\n"
220
+ for i, choice in enumerate(choices, 1):
221
+ choice_display += f"**Option {i}:** {choice}\n\n"
222
+
223
+ # Update turn count
224
+ game.session["turn_count"] += 1
225
+
226
+ return student_response, choice_display, ""
227
+
228
+ def handle_teaching_choice(choice_num):
229
+ """Process the selected teaching choice"""
230
+ if choice_num < 1 or choice_num > 4:
231
+ return "Please select a valid choice (1-4).", "", ""
232
+
233
+ # Get the choice (this is simplified - in full version, we'd track the actual choices)
234
+ choice_options = game.generate_teaching_choices()
235
+ if choice_num <= len(choice_options):
236
+ selected_choice = choice_options[choice_num - 1]
237
+
238
+ # Assess the choice
239
+ feedback, points, engagement_impact = game.assess_teaching_choice(selected_choice)
240
+
241
+ # Update game state
242
+ game.session["teaching_points"] += points
243
+ game.update_engagement(engagement_impact)
244
+ game.session["choices_made"].append({
245
+ "choice": selected_choice,
246
+ "points": points,
247
+ "turn": game.session["turn_count"]
248
+ })
249
+
250
+ # Create response
251
+ updated_engagement = game.get_engagement_display()
252
+ points_display = f"**Teaching Points:** {game.session['teaching_points']}"
253
+
254
+ return feedback, updated_engagement, points_display
255
+
256
+ return "Choice not found.", "", ""
257
+
258
+ # Create Gradio interface
259
+ def create_interface():
260
+ with gr.Blocks(title="Science Talk Adventure", theme=gr.themes.Soft()) as interface:
261
+ gr.Markdown("# 🌱 Science Talk Adventure: Practice Equitable Science Discussions")
262
+ gr.Markdown("*An interactive simulation for preservice elementary teachers*")
263
+
264
+ with gr.Row():
265
+ with gr.Column(scale=2):
266
+ scenario_info = gr.Markdown(game.get_scenario_info())
267
+
268
+ conversation_area = gr.Markdown("*Students will respond here after you speak...*")
269
+
270
+ teacher_input = gr.Textbox(
271
+ label="πŸ’¬ What do you say to your students?",
272
+ placeholder="Type your response here... (e.g., 'What do you notice about these plants?')",
273
+ lines=3
274
+ )
275
+
276
+ send_btn = gr.Button("Send Response", variant="primary", size="lg")
277
+
278
+ choices_display = gr.Markdown("")
279
+
280
+ with gr.Row():
281
+ choice1_btn = gr.Button("Choice 1", variant="secondary")
282
+ choice2_btn = gr.Button("Choice 2", variant="secondary")
283
+ choice3_btn = gr.Button("Choice 3", variant="secondary")
284
+ choice4_btn = gr.Button("Choice 4", variant="secondary")
285
+
286
+ feedback_display = gr.Markdown("")
287
+
288
+ with gr.Column(scale=1):
289
+ engagement_display = gr.Markdown(game.get_engagement_display())
290
+ points_display = gr.Markdown(f"**Teaching Points:** {game.session['teaching_points']}")
291
+
292
+ gr.Markdown("---")
293
+ restart_btn = gr.Button("πŸ”„ Start New Session", variant="outline")
294
+
295
+ gr.Markdown("""
296
+ ### πŸ’‘ Tips for Success:
297
+ - **Listen for cultural knowledge** students share
298
+ - **Create wait time** for all students to think
299
+ - **Build on student ideas** rather than immediately correcting
300
+ - **Notice who's participating** and who might need encouragement
301
+ """)
302
+
303
+ # Event handlers
304
+ restart_btn.click(
305
+ start_new_session,
306
+ outputs=[scenario_info, engagement_display, conversation_area, points_display, feedback_display]
307
+ )
308
+
309
+ send_btn.click(
310
+ process_teacher_input,
311
+ inputs=[teacher_input],
312
+ outputs=[conversation_area, choices_display, feedback_display]
313
+ )
314
+
315
+ choice1_btn.click(lambda: handle_teaching_choice(1), outputs=[feedback_display, engagement_display, points_display])
316
+ choice2_btn.click(lambda: handle_teaching_choice(2), outputs=[feedback_display, engagement_display, points_display])
317
+ choice3_btn.click(lambda: handle_teaching_choice(3), outputs=[feedback_display, engagement_display, points_display])
318
+ choice4_btn.click(lambda: handle_teaching_choice(4), outputs=[feedback_display, engagement_display, points_display])
319
+
320
+ return interface
321
+
322
+ # Launch the app
323
+ if __name__ == "__main__":
324
+ demo = create_interface()
325
+ demo.launch()