minsuas commited on
Commit
ad27fcf
ยท
verified ยท
1 Parent(s): 383b796

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +22 -306
app.py CHANGED
@@ -6,13 +6,10 @@ from src.SecondModule.module2 import SimilarQuestionGenerator
6
  from src.ThirdModule.module3 import AnswerVerifier
7
  import logging
8
  from typing import Optional, Tuple
9
- from latex_formatter import LatexFormatter # LaTeX ํฌ๋งทํ„ฐ import
10
 
11
  logging.basicConfig(level=logging.DEBUG)
12
 
13
-
14
-
15
-
16
  # Initialize Misconception Model
17
  @st.cache_resource
18
  def load_misconception_model():
@@ -22,19 +19,6 @@ def load_misconception_model():
22
  misconception_embs_paths=[os.path.join(data_path, f'embs_misconception-9.npy')]
23
  )
24
 
25
- # Example integration
26
- def start_quiz_with_predictions():
27
- model = load_misconception_model()
28
- df = load_data()
29
- if df is None or df.empty:
30
- st.error("๋ฐ์ดํ„ฐ๋ฅผ ๋ถˆ๋Ÿฌ์˜ฌ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.")
31
- return
32
- df = model.preprocess(df)
33
- predictions = model.predict(df)
34
- st.session_state.questions = predictions.sample(n=10, random_state=42)
35
- st.session_state.current_step = 'quiz'
36
-
37
-
38
  # Streamlit ํŽ˜์ด์ง€ ๊ธฐ๋ณธ ์„ค์ •
39
  st.set_page_config(
40
  page_title="MisconcepTutor",
@@ -47,7 +31,7 @@ def load_answer_verifier():
47
  """๋‹ต์•ˆ ๊ฒ€์ฆ ๋ชจ๋ธ ๋กœ๋“œ"""
48
  from src.ThirdModule.module3 import AnswerVerifier
49
  return AnswerVerifier()
50
-
51
  # ๊ฒฝ๋กœ ์„ค์ •
52
  base_path = os.path.dirname(os.path.abspath(__file__))
53
  data_path = os.path.join(base_path, 'Data')
@@ -57,7 +41,7 @@ misconception_csv_path = os.path.join(data_path, 'misconception_mapping.csv')
57
  logging.basicConfig(level=logging.INFO)
58
  logger = logging.getLogger(__name__)
59
 
60
- # ์„ธ์…˜ ์ƒํƒœ ์ดˆ๊ธฐํ™” - ๊ฐ€์žฅ ๋จผ์ € ์‹คํ–‰๋˜๋„๋ก ์ตœ์ƒ๋‹จ์— ๋ฐฐ์น˜
61
  if 'initialized' not in st.session_state:
62
  st.session_state.initialized = True
63
  st.session_state.wrong_questions = []
@@ -80,7 +64,7 @@ def load_question_generator():
80
 
81
  # CSV ๋ฐ์ดํ„ฐ ๋กœ๋“œ ํ•จ์ˆ˜
82
  @st.cache_data
83
- def load_data(data_file = '/train.csv'):
84
  try:
85
  file_path = os.path.join(data_path, data_file.lstrip('/'))
86
  df = pd.read_csv(file_path)
@@ -106,106 +90,17 @@ def start_quiz():
106
  st.session_state.generated_questions = []
107
  logger.info("Quiz started")
108
 
109
-
110
- def generate_similar_question(wrong_q, misconception_id, generator):
111
- """์œ ์‚ฌ ๋ฌธ์ œ ์ƒ์„ฑ"""
112
- logger.info(f"Generating similar question for misconception_id: {misconception_id}")
113
-
114
- # ์ž…๋ ฅ ๋ฐ์ดํ„ฐ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ
115
- if not isinstance(wrong_q, dict):
116
- logger.error(f"Invalid wrong_q type: {type(wrong_q)}")
117
- st.error("์œ ์‚ฌ ๋ฌธ์ œ ์ƒ์„ฑ์— ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ ํ˜•์‹์ด ์ž˜๋ชป๋˜์—ˆ์Šต๋‹ˆ๋‹ค.")
118
- return None
119
-
120
- try:
121
- # misconception_id๊ฐ€ ์—†๊ฑฐ๋‚˜ NaN์ธ ๊ฒฝ์šฐ ๋‹ค๋ฅธ misconception ์‚ฌ์šฉ
122
- if pd.isna(misconception_id):
123
- logger.info("Original misconception_id is NaN, trying to find alternative")
124
- # ํ˜„์žฌ๊นŒ์ง€ ๋‚˜์˜จ misconception๋“ค ์ค‘์—์„œ ์„ ํƒ
125
- available_misconceptions = [m for m in st.session_state.misconceptions if not pd.isna(m)]
126
-
127
- if available_misconceptions:
128
- # ๊ฐ€์žฅ ์ตœ๊ทผ์— ๋‚˜์˜จ misconception ์„ ํƒ
129
- misconception_id = available_misconceptions[-1]
130
- logger.info(f"Using alternative misconception_id: {misconception_id}")
131
- else:
132
- # ๊ธฐ๋ณธ misconception ID ์‚ฌ์šฉ (์˜ˆ: ๊ฐ€์žฅ ๊ธฐ๋ณธ์ ์ธ misconception)
133
- misconception_id = 2001 # ์ ์ ˆํ•œ ๊ธฐ๋ณธ๊ฐ’์œผ๋กœ ์ˆ˜์ • ํ•„์š”
134
- logger.info(f"Using default misconception_id: {misconception_id}")
135
-
136
- # ๋ฐ์ดํ„ฐ ์ค€๋น„ (ํŠœํ”Œ ๋ณ€ํ™˜ ๋ฐฉ์ง€)
137
- input_data = {
138
- 'construct_name': str(wrong_q.get('ConstructName', '')),
139
- 'subject_name': str(wrong_q.get('SubjectName', '')),
140
- 'question_text': str(wrong_q.get('QuestionText', '')),
141
- 'correct_answer_text': str(wrong_q.get(f'Answer{wrong_q["CorrectAnswer"]}Text', '')),
142
- 'wrong_answer_text': str(wrong_q.get(f'Answer{st.session_state.selected_wrong_answer}Text', '')),
143
- 'misconception_id': int(misconception_id)
144
- }
145
-
146
- logger.info(f"Prepared input data: {input_data}")
147
-
148
- with st.spinner("๐Ÿ“ ์œ ์‚ฌ ๋ฌธ์ œ๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค..."):
149
- # ์œ ์‚ฌ ๋ฌธ์ œ ์ƒ์„ฑ ํ˜ธ์ถœ
150
- generated_q, _ = generator.generate_similar_question_with_text(
151
- construct_name=input_data['construct_name'],
152
- subject_name=input_data['subject_name'],
153
- question_text=input_data['question_text'],
154
- correct_answer_text=input_data['correct_answer_text'],
155
- wrong_answer_text=input_data['wrong_answer_text'],
156
- misconception_id=input_data['misconception_id']
157
- )
158
-
159
- if generated_q:
160
- verifier = load_answer_verifier()
161
- with st.status("๐Ÿค” AI๊ฐ€ ๋ฌธ์ œ๋ฅผ ๊ฒ€ํ† ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค..."):
162
- st.write("๋‹ต์•ˆ์˜ ์ •ํ™•์„ฑ์„ ๊ฒ€์ฆํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค...")
163
- verified_answer = verifier.verify_answer(
164
- question=generated_q.question,
165
- choices=generated_q.choices
166
- )
167
-
168
- if verified_answer:
169
- logger.info(f"Answer verified: {verified_answer}")
170
- st.write("โœ… ๊ฒ€์ฆ ์™„๋ฃŒ!")
171
- result = {
172
- 'question': generated_q.question,
173
- 'choices': generated_q.choices,
174
- 'correct': verified_answer,
175
- 'explanation': generated_q.explanation
176
- }
177
- st.session_state['current_similar_question_answer'] = verified_answer
178
- return result
179
- else:
180
- logger.warning("Answer verification failed, using original answer")
181
- st.write("โš ๏ธ ๊ฒ€์ฆ์— ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค. ์›๋ณธ ๋‹ต์•ˆ์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.")
182
- result = {
183
- 'question': generated_q.question,
184
- 'choices': generated_q.choices,
185
- 'correct': generated_q.correct_answer,
186
- 'explanation': generated_q.explanation
187
- }
188
- st.session_state['current_similar_question_answer'] = generated_q.correct_answer
189
- return result
190
-
191
- except Exception as e:
192
- logger.error(f"Error in generate_similar_question: {str(e)}")
193
- st.error(f"๋ฌธ์ œ ์ƒ์„ฑ ์ค‘ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค: {str(e)}")
194
- return None
195
-
196
- return None
197
-
198
  def handle_answer(answer, current_q):
199
  """๋‹ต๋ณ€ ์ฒ˜๋ฆฌ"""
200
  if answer != current_q['CorrectAnswer']:
201
  wrong_q_dict = current_q.to_dict()
202
  st.session_state.wrong_questions.append(wrong_q_dict)
203
  st.session_state.selected_wrong_answer = answer
204
-
205
  misconception_key = f'Misconception{answer}Id'
206
  misconception_id = current_q.get(misconception_key)
207
  st.session_state.misconceptions.append(misconception_id)
208
-
209
  st.session_state.current_question_index += 1
210
  if st.session_state.current_question_index >= 10:
211
  st.session_state.current_step = 'review'
@@ -218,16 +113,12 @@ def display_math_content(content: str):
218
  formatted_content = latex_formatter.format_expression(content)
219
  st.markdown(formatted_content, unsafe_allow_html=True)
220
 
221
- def format_answer_choice(choice: str) -> str:
222
- """์„ ํƒ์ง€ LaTeX ํฌ๋งทํŒ…"""
223
- return latex_formatter.format_expression(choice)
224
-
225
  def main():
226
  """๋ฉ”์ธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋กœ์ง"""
227
  st.title("MisconcepTutor")
228
-
229
- # Generator ์ดˆ๊ธฐํ™”
230
- generator = load_question_generator()
231
 
232
  # ์ดˆ๊ธฐ ํ™”๋ฉด
233
  if st.session_state.current_step == 'initial':
@@ -239,91 +130,48 @@ def main():
239
  # ํ€ด์ฆˆ ํ™”๋ฉด
240
  elif st.session_state.current_step == 'quiz':
241
  current_q = st.session_state.questions.iloc[st.session_state.current_question_index]
242
-
243
  # ์ง„ํ–‰ ์ƒํ™ฉ ํ‘œ์‹œ
244
  progress = st.session_state.current_question_index / 10
245
  st.progress(progress)
246
  st.write(f"### ๋ฌธ์ œ {st.session_state.current_question_index + 1}/10")
247
-
248
  # ๋ฌธ์ œ ํ‘œ์‹œ
249
  st.markdown("---")
250
- #display_math_question(current_q['QuestionText'])
251
- display_math_content(current_q['QuestionText']) # display_math_question ๋Œ€์‹  display_math_content ์‚ฌ์šฉ
252
 
253
- #st.write(current_q['QuestionText'])
254
-
255
- # # ๋ณด๊ธฐ ํ‘œ์‹œ
256
- # col1, col2 = st.columns(2)
257
- # with col1:
258
- # if st.button(f"A) {current_q['AnswerAText']}", key="A"):
259
- # handle_answer('A', current_q)
260
- # st.rerun()
261
- # if st.button(f"C) {current_q['AnswerCText']}", key="C"):
262
- # handle_answer('C', current_q)
263
- # st.rerun()
264
- # with col2:
265
- # if st.button(f"B) {current_q['AnswerBText']}", key="B"):
266
- # handle_answer('B', current_q)
267
- # st.rerun()
268
- # if st.button(f"D) {current_q['AnswerDText']}", key="D"):
269
- # handle_answer('D', current_q)
270
- # st.rerun()
271
-
272
  # ๋ณด๊ธฐ ํ‘œ์‹œ
273
  col1, col2 = st.columns(2)
274
  with col1:
275
  if st.button(latex_formatter.format_expression(f"A) {current_q['AnswerAText']}"), key="A"):
276
  handle_answer('A', current_q)
277
  st.rerun()
278
- if st.button(latex_formatter.format_expression(f"C) {current_q['AnswerAText']}"), key="C"):
279
  handle_answer('C', current_q)
280
  st.rerun()
281
  with col2:
282
- if st.button(latex_formatter.format_expression(f"B) {current_q['AnswerAText']}"), key="B"):
283
  handle_answer('B', current_q)
284
  st.rerun()
285
- if st.button(latex_formatter.format_expression(f"D) {current_q['AnswerAText']}"), key="D"):
286
  handle_answer('D', current_q)
287
  st.rerun()
 
288
  # ๋ณต์Šต ํ™”๋ฉด
289
  elif st.session_state.current_step == 'review':
290
  st.write("### ํ•™์Šต ๊ฒฐ๊ณผ")
291
-
292
  # ๊ฒฐ๊ณผ ํ†ต๊ณ„
293
  col1, col2, col3 = st.columns(3)
294
  col1.metric("์ด ๋ฌธ์ œ ์ˆ˜", 10)
295
  col2.metric("๋งž์€ ๋ฌธ์ œ", 10 - len(st.session_state.wrong_questions))
296
  col3.metric("ํ‹€๋ฆฐ ๋ฌธ์ œ", len(st.session_state.wrong_questions))
297
-
298
- # ๊ฒฐ๊ณผ์— ๋”ฐ๋ฅธ ๋ฉ”์‹œ์ง€ ํ‘œ์‹œ
299
- if len(st.session_state.wrong_questions) == 0:
300
- st.balloons() # ์ถ•ํ•˜ ํšจ๊ณผ
301
- st.success("๐ŸŽ‰ ์ถ•ํ•˜ํ•ฉ๋‹ˆ๋‹ค! ๋ชจ๋“  ๋ฌธ์ œ๋ฅผ ๋งž์ถ”์…จ์–ด์š”!")
302
- st.markdown("""
303
- ### ๐Ÿ† ์ˆ˜ํ•™์™•์ด์‹ญ๋‹ˆ๋‹ค!
304
- ์™„๋ฒฝํ•œ ์ ์ˆ˜๋ฅผ ๋ฐ›์œผ์…จ๋„ค์š”! ์ˆ˜ํ•™์  ๊ฐœ๋…์„ ์ •ํ™•ํ•˜๊ฒŒ ์ดํ•ดํ•˜๊ณ  ๊ณ„์‹  ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.
305
- """)
306
- elif len(st.session_state.wrong_questions) <= 3:
307
- st.success("์ž˜ ํ•˜์…จ์–ด์š”! ์กฐ๊ธˆ๋งŒ ๋” ์—ฐ์Šตํ•˜๋ฉด ์™„๋ฒฝํ•  ๊ฑฐ์˜ˆ์š”!")
308
- else:
309
- st.info("์ฒœ์ฒœํžˆ ๊ฐœ๋…์„ ๋ณต์Šตํ•ด๋ณด์•„์š”. ์—ฐ์Šตํ•˜๋‹ค ๋ณด๋ฉด ๋Š˜์–ด๋‚  ๊ฑฐ์˜ˆ์š”!")
310
-
311
- # ๋„ค๋น„๊ฒŒ์ด์…˜ ๋ฒ„ํŠผ
312
- col1, col2 = st.columns(2)
313
- with col1:
314
- if st.button("๐Ÿ”„ ์ƒˆ๋กœ์šด ๋ฌธ์ œ ์„ธํŠธ ์‹œ์ž‘ํ•˜๊ธฐ", use_container_width=True):
315
- start_quiz()
316
- st.rerun()
317
- with col2:
318
- if st.button("๐Ÿ  ์ฒ˜์Œ์œผ๋กœ ๋Œ์•„๊ฐ€๊ธฐ", use_container_width=True):
319
- st.session_state.clear()
320
- st.rerun()
321
-
322
- # ํ‹€๋ฆฐ ๋ฌธ์ œ ๋ถ„์„ ๋ถ€๋ถ„
323
  if st.session_state.wrong_questions:
324
  st.write("### โœ๏ธ ํ‹€๋ฆฐ ๋ฌธ์ œ ๋ถ„์„")
325
  tabs = st.tabs([f"๐Ÿ“ ํ‹€๋ฆฐ ๋ฌธ์ œ #{i + 1}" for i in range(len(st.session_state.wrong_questions))])
326
-
327
  for i, (tab, (wrong_q, misconception_id)) in enumerate(zip(
328
  tabs,
329
  zip(st.session_state.wrong_questions, st.session_state.misconceptions)
@@ -332,146 +180,14 @@ def main():
332
  st.write("**๐Ÿ“‹ ๋ฌธ์ œ:**")
333
  st.write(wrong_q['QuestionText'])
334
  st.write("**โœ… ์ •๋‹ต:**", wrong_q['CorrectAnswer'])
335
-
336
  st.write("---")
337
  st.write("**๐Ÿ” ๊ด€๋ จ๋œ Misconception:**")
338
  if misconception_id and not pd.isna(misconception_id):
339
- misconception_text = generator.get_misconception_text(misconception_id)
340
  st.info(f"Misconception ID: {int(misconception_id)}\n\n{misconception_text}")
341
  else:
342
  st.info("Misconception ์ •๋ณด๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.")
343
-
344
- if st.button(f"๐Ÿ“š ์œ ์‚ฌ ๋ฌธ์ œ ํ’€๊ธฐ", key=f"retry_{i}"):
345
- st.session_state[f"show_similar_question_{i}"] = True
346
- st.session_state[f"similar_question_answered_{i}"] = False
347
- st.rerun()
348
-
349
- if st.session_state.get(f"show_similar_question_{i}", False):
350
- st.divider()
351
- new_question = generate_similar_question(wrong_q, misconception_id, generator)
352
- if new_question:
353
- st.write("### ๐ŸŽฏ ์œ ์‚ฌ ๋ฌธ์ œ")
354
- #st.write(new_question['question'])
355
- display_math_question(new_question['question'])
356
 
357
-
358
- # ๋‹ต๋ณ€ ์ƒํƒœ ํ™•์ธ
359
- answered = st.session_state.get(f"similar_question_answered_{i}", False)
360
-
361
- # ๋ณด๊ธฐ ํ‘œ์‹œ
362
- st.write("**๋ณด๊ธฐ:**")
363
- col1, col2 = st.columns(2)
364
-
365
- # # ๋‹ต๋ณ€ํ•˜์ง€ ์•Š์€ ๊ฒฝ์šฐ์—๋งŒ ๋ฒ„ํŠผ ํ™œ์„ฑํ™”
366
- # if not answered:
367
- # with col1:
368
- # for option in ['A', 'C']:
369
- # if st.button(
370
- # f"{option}) {new_question['choices'][option]}",
371
- # key=f"similar_{option}_{i}"
372
- # ):
373
- # st.session_state[f"similar_question_answered_{i}"] = True
374
- # st.session_state[f"selected_answer_{i}"] = option
375
- # correct_answer = st.session_state.get('current_similar_question_answer')
376
- # if option == correct_answer:
377
- # st.session_state[f"is_correct_{i}"] = True
378
- # else:
379
- # st.session_state[f"is_correct_{i}"] = False
380
- # st.rerun()
381
-
382
- # with col2:
383
- # for option in ['B', 'D']:
384
- # if st.button(
385
- # f"{option}) {new_question['choices'][option]}",
386
- # key=f"similar_{option}_{i}"
387
- # ):
388
- # st.session_state[f"similar_question_answered_{i}"] = True
389
- # st.session_state[f"selected_answer_{i}"] = option
390
- # correct_answer = st.session_state.get('current_similar_question_answer')
391
- # if option == correct_answer:
392
- # st.session_state[f"is_correct_{i}"] = True
393
- # else:
394
- # st.session_state[f"is_correct_{i}"] = False
395
- # st.rerun()
396
- # ๋‹ต๋ณ€ํ•˜์ง€ ์•Š์€ ๊ฒฝ์šฐ์—๋งŒ ๋ฒ„ํŠผ ํ™œ์„ฑํ™”
397
- if not answered:
398
- with col1:
399
- for option in ['A', 'C']:
400
- if st.button(
401
- f"{option}) {format_math_expression(new_question['choices'][option])}",
402
- key=f"similar_{option}_{i}"
403
- ):
404
- st.session_state[f"similar_question_answered_{i}"] = True
405
- st.session_state[f"selected_answer_{i}"] = option
406
- correct_answer = st.session_state.get('current_similar_question_answer')
407
- if option == correct_answer:
408
- st.session_state[f"is_correct_{i}"] = True
409
- else:
410
- st.session_state[f"is_correct_{i}"] = False
411
- st.rerun()
412
-
413
- with col2:
414
- for option in ['B', 'D']:
415
- if st.button(
416
- f"{option}) {format_math_expression(new_question['choices'][option])}",
417
- key=f"similar_{option}_{i}"
418
- ):
419
- st.session_state[f"similar_question_answered_{i}"] = True
420
- st.session_state[f"selected_answer_{i}"] = option
421
- correct_answer = st.session_state.get('current_similar_question_answer')
422
- if option == correct_answer:
423
- st.session_state[f"is_correct_{i}"] = True
424
- else:
425
- st.session_state[f"is_correct_{i}"] = False
426
- st.rerun()
427
- # ๋‹ต๋ณ€ํ•œ ๊ฒฝ์šฐ ๊ฒฐ๊ณผ ํ‘œ์‹œ
428
- if answered:
429
- is_correct = st.session_state.get(f"is_correct_{i}", False)
430
- correct_answer = st.session_state.get('current_similar_question_answer')
431
- if is_correct:
432
- st.success("โœ… ์ •๋‹ต์ž…๋‹ˆ๋‹ค!")
433
- else:
434
- st.error(f"โŒ ํ‹€๋ ธ์Šต๋‹ˆ๋‹ค. ์ •๋‹ต์€ {correct_answer}์ž…๋‹ˆ๋‹ค.")
435
-
436
- # ํ•ด์„ค ํ‘œ์‹œ
437
- st.write("---")
438
- st.write("**๐Ÿ“ ํ•ด์„ค:**", new_question['explanation'])
439
-
440
- # ๋‹ค์‹œ ํ’€๊ธฐ ๋ฒ„ํŠผ
441
- if st.button("๐Ÿ”„ ๋‹ค์‹œ ํ’€๊ธฐ", key=f"reset_{i}"):
442
- st.session_state[f"similar_question_answered_{i}"] = False
443
- st.session_state[f"selected_answer_{i}"] = None
444
- st.session_state[f"is_correct_{i}"] = None
445
- st.rerun()
446
-
447
- # ๋ฌธ์ œ ๋‹ซ๊ธฐ ๋ฒ„ํŠผ
448
- if st.button("โŒ ๋ฌธ์ œ ๋‹ซ๊ธฐ", key=f"close_{i}"):
449
- st.session_state[f"show_similar_question_{i}"] = False
450
- st.session_state[f"similar_question_answered_{i}"] = False
451
- st.session_state[f"selected_answer_{i}"] = None
452
- st.session_state[f"is_correct_{i}"] = None
453
- st.rerun()
454
-
455
- # ํ™”๋ฉด ์•„๋ž˜ ์—ฌ๋ฐฑ ์ถ”๊ฐ€
456
- st.markdown("<br>" * 5, unsafe_allow_html=True) # 5์ค„์˜ ๋นˆ ์ค„ ์ถ”๊ฐ€
457
- st.markdown("""
458
- <div style="height: 100px;">
459
- </div>
460
- """, unsafe_allow_html=True) # ์ถ”๊ฐ€ ์—ฌ๋ฐฑ
461
- else:
462
- st.error("์œ ์‚ฌ ๋ฌธ์ œ๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.")
463
- if st.button("โŒ ๋‹ซ๊ธฐ", key=f"close_error_{i}"):
464
- st.session_state[f"show_similar_question_{i}"] = False
465
- st.rerun()
466
- # ํ™”๋ฉด ์•„๋ž˜ ์—ฌ๋ฐฑ ์ถ”๊ฐ€
467
- st.markdown("<br>" * 5, unsafe_allow_html=True) # 5์ค„์˜ ๋นˆ ์ค„ ์ถ”๊ฐ€
468
- st.markdown("""
469
- <div style="height: 100px;">
470
- </div>
471
- """, unsafe_allow_html=True) # ์ถ”๊ฐ€ ์—ฌ๋ฐฑ
472
  if __name__ == "__main__":
473
  main()
474
-
475
- # random_state 42์—์„œ ์ •๋‹ต
476
- # D C A A C
477
- # A B B B B
 
6
  from src.ThirdModule.module3 import AnswerVerifier
7
  import logging
8
  from typing import Optional, Tuple
9
+ from latex_formatter import LatexFormatter
10
 
11
  logging.basicConfig(level=logging.DEBUG)
12
 
 
 
 
13
  # Initialize Misconception Model
14
  @st.cache_resource
15
  def load_misconception_model():
 
19
  misconception_embs_paths=[os.path.join(data_path, f'embs_misconception-9.npy')]
20
  )
21
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22
  # Streamlit ํŽ˜์ด์ง€ ๊ธฐ๋ณธ ์„ค์ •
23
  st.set_page_config(
24
  page_title="MisconcepTutor",
 
31
  """๋‹ต์•ˆ ๊ฒ€์ฆ ๋ชจ๋ธ ๋กœ๋“œ"""
32
  from src.ThirdModule.module3 import AnswerVerifier
33
  return AnswerVerifier()
34
+
35
  # ๊ฒฝ๋กœ ์„ค์ •
36
  base_path = os.path.dirname(os.path.abspath(__file__))
37
  data_path = os.path.join(base_path, 'Data')
 
41
  logging.basicConfig(level=logging.INFO)
42
  logger = logging.getLogger(__name__)
43
 
44
+ # ์„ธ์…˜ ์ƒํƒœ ์ดˆ๊ธฐํ™”
45
  if 'initialized' not in st.session_state:
46
  st.session_state.initialized = True
47
  st.session_state.wrong_questions = []
 
64
 
65
  # CSV ๋ฐ์ดํ„ฐ ๋กœ๋“œ ํ•จ์ˆ˜
66
  @st.cache_data
67
+ def load_data(data_file='/train.csv'):
68
  try:
69
  file_path = os.path.join(data_path, data_file.lstrip('/'))
70
  df = pd.read_csv(file_path)
 
90
  st.session_state.generated_questions = []
91
  logger.info("Quiz started")
92
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
93
  def handle_answer(answer, current_q):
94
  """๋‹ต๋ณ€ ์ฒ˜๋ฆฌ"""
95
  if answer != current_q['CorrectAnswer']:
96
  wrong_q_dict = current_q.to_dict()
97
  st.session_state.wrong_questions.append(wrong_q_dict)
98
  st.session_state.selected_wrong_answer = answer
99
+
100
  misconception_key = f'Misconception{answer}Id'
101
  misconception_id = current_q.get(misconception_key)
102
  st.session_state.misconceptions.append(misconception_id)
103
+
104
  st.session_state.current_question_index += 1
105
  if st.session_state.current_question_index >= 10:
106
  st.session_state.current_step = 'review'
 
113
  formatted_content = latex_formatter.format_expression(content)
114
  st.markdown(formatted_content, unsafe_allow_html=True)
115
 
 
 
 
 
116
  def main():
117
  """๋ฉ”์ธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋กœ์ง"""
118
  st.title("MisconcepTutor")
119
+
120
+ # Misconception Model ๋กœ๋“œ
121
+ misconception_model = load_misconception_model()
122
 
123
  # ์ดˆ๊ธฐ ํ™”๋ฉด
124
  if st.session_state.current_step == 'initial':
 
130
  # ํ€ด์ฆˆ ํ™”๋ฉด
131
  elif st.session_state.current_step == 'quiz':
132
  current_q = st.session_state.questions.iloc[st.session_state.current_question_index]
133
+
134
  # ์ง„ํ–‰ ์ƒํ™ฉ ํ‘œ์‹œ
135
  progress = st.session_state.current_question_index / 10
136
  st.progress(progress)
137
  st.write(f"### ๋ฌธ์ œ {st.session_state.current_question_index + 1}/10")
138
+
139
  # ๋ฌธ์ œ ํ‘œ์‹œ
140
  st.markdown("---")
141
+ display_math_content(current_q['QuestionText'])
 
142
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
143
  # ๋ณด๊ธฐ ํ‘œ์‹œ
144
  col1, col2 = st.columns(2)
145
  with col1:
146
  if st.button(latex_formatter.format_expression(f"A) {current_q['AnswerAText']}"), key="A"):
147
  handle_answer('A', current_q)
148
  st.rerun()
149
+ if st.button(latex_formatter.format_expression(f"C) {current_q['AnswerCText']}"), key="C"):
150
  handle_answer('C', current_q)
151
  st.rerun()
152
  with col2:
153
+ if st.button(latex_formatter.format_expression(f"B) {current_q['AnswerBText']}"), key="B"):
154
  handle_answer('B', current_q)
155
  st.rerun()
156
+ if st.button(latex_formatter.format_expression(f"D) {current_q['AnswerDText']}"), key="D"):
157
  handle_answer('D', current_q)
158
  st.rerun()
159
+
160
  # ๋ณต์Šต ํ™”๋ฉด
161
  elif st.session_state.current_step == 'review':
162
  st.write("### ํ•™์Šต ๊ฒฐ๊ณผ")
163
+
164
  # ๊ฒฐ๊ณผ ํ†ต๊ณ„
165
  col1, col2, col3 = st.columns(3)
166
  col1.metric("์ด ๋ฌธ์ œ ์ˆ˜", 10)
167
  col2.metric("๋งž์€ ๋ฌธ์ œ", 10 - len(st.session_state.wrong_questions))
168
  col3.metric("ํ‹€๋ฆฐ ๋ฌธ์ œ", len(st.session_state.wrong_questions))
169
+
170
+ # ํ‹€๋ฆฐ ๋ฌธ์ œ ๋ถ„์„
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
171
  if st.session_state.wrong_questions:
172
  st.write("### โœ๏ธ ํ‹€๋ฆฐ ๋ฌธ์ œ ๋ถ„์„")
173
  tabs = st.tabs([f"๐Ÿ“ ํ‹€๋ฆฐ ๋ฌธ์ œ #{i + 1}" for i in range(len(st.session_state.wrong_questions))])
174
+
175
  for i, (tab, (wrong_q, misconception_id)) in enumerate(zip(
176
  tabs,
177
  zip(st.session_state.wrong_questions, st.session_state.misconceptions)
 
180
  st.write("**๐Ÿ“‹ ๋ฌธ์ œ:**")
181
  st.write(wrong_q['QuestionText'])
182
  st.write("**โœ… ์ •๋‹ต:**", wrong_q['CorrectAnswer'])
183
+
184
  st.write("---")
185
  st.write("**๐Ÿ” ๊ด€๋ จ๋œ Misconception:**")
186
  if misconception_id and not pd.isna(misconception_id):
187
+ misconception_text = misconception_model.misconception_names.get(misconception_id, "์ •๋ณด ์—†์Œ")
188
  st.info(f"Misconception ID: {int(misconception_id)}\n\n{misconception_text}")
189
  else:
190
  st.info("Misconception ์ •๋ณด๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.")
 
 
 
 
 
 
 
 
 
 
 
 
 
191
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
192
  if __name__ == "__main__":
193
  main()