Jintonic92 commited on
Commit
c620b9d
·
verified ·
1 Parent(s): 30353ba

Delete app_ori(latex 전).py

Browse files
Files changed (1) hide show
  1. app_ori(latex 전).py +0 -413
app_ori(latex 전).py DELETED
@@ -1,413 +0,0 @@
1
- import streamlit as st
2
- import pandas as pd
3
- import os
4
- from src.SecondModule.module2 import SimilarQuestionGenerator
5
- from src.ThirdModule.module3 import AnswerVerifier
6
- import logging
7
- from typing import Optional, Tuple
8
- #from latex_formatter import LatexFormatter # LaTeX 포맷터 import
9
- from pylatexenc.latex2text import LatexNodes2Text
10
-
11
-
12
- logging.basicConfig(level=logging.DEBUG)
13
-
14
-
15
- # Streamlit 페이지 기본 설정
16
- st.set_page_config(
17
- page_title="MisconcepTutor",
18
- layout="wide",
19
- initial_sidebar_state="expanded"
20
- )
21
-
22
- @st.cache_resource
23
- def load_answer_verifier():
24
- """답안 검증 모델 로드"""
25
- from src.ThirdModule.module3 import AnswerVerifier
26
- return AnswerVerifier()
27
-
28
- # 경로 설정
29
- base_path = os.path.dirname(os.path.abspath(__file__))
30
- data_path = os.path.join(base_path, 'Data')
31
- misconception_csv_path = os.path.join(data_path, 'misconception_mapping.csv')
32
-
33
- # 로깅 설정
34
- logging.basicConfig(level=logging.INFO)
35
- logger = logging.getLogger(__name__)
36
-
37
- # 세션 상태 초기화 - 가장 먼저 실행되도록 최상단에 배치
38
- if 'initialized' not in st.session_state:
39
- st.session_state.initialized = True
40
- st.session_state.wrong_questions = []
41
- st.session_state.misconceptions = []
42
- st.session_state.current_question_index = 0
43
- st.session_state.generated_questions = []
44
- st.session_state.current_step = 'initial'
45
- st.session_state.selected_wrong_answer = None
46
- st.session_state.questions = []
47
- logger.info("Session state initialized")
48
-
49
- # 문제 생성기 초기화
50
- @st.cache_resource
51
- def load_question_generator():
52
- """문제 생성 모델 로드"""
53
- if not os.path.exists(misconception_csv_path):
54
- st.error(f"CSV 파일이 존재하지 않습니다: {misconception_csv_path}")
55
- raise FileNotFoundError(f"CSV 파일이 존재하지 않습니다: {misconception_csv_path}")
56
- return SimilarQuestionGenerator(misconception_csv_path=misconception_csv_path)
57
-
58
- # CSV 데이터 로드 함수
59
- @st.cache_data
60
- def load_data(data_file = '/train.csv'):
61
- try:
62
- file_path = os.path.join(data_path, data_file.lstrip('/'))
63
- df = pd.read_csv(file_path)
64
- logger.info(f"Data loaded successfully from {file_path}")
65
- return df
66
- except FileNotFoundError:
67
- st.error(f"파일을 찾을 수 없습니다: {data_file}")
68
- logger.error(f"File not found: {data_file}")
69
- return None
70
-
71
- def start_quiz():
72
- """퀴즈 시작 및 초기화"""
73
- df = load_data()
74
- if df is None or df.empty:
75
- st.error("데이터를 불러올 수 없습니다. 데이터셋을 확인해주세요.")
76
- return
77
-
78
- st.session_state.questions = df.sample(n=10, random_state=42)
79
- st.session_state.current_step = 'quiz'
80
- st.session_state.current_question_index = 0
81
- st.session_state.wrong_questions = []
82
- st.session_state.misconceptions = []
83
- st.session_state.generated_questions = []
84
- logger.info("Quiz started")
85
-
86
-
87
- def generate_similar_question(wrong_q, misconception_id, generator):
88
- """유사 문제 생성"""
89
- logger.info(f"Generating similar question for misconception_id: {misconception_id}")
90
-
91
- # 입력 데이터 유효성 검사
92
- if not isinstance(wrong_q, dict):
93
- logger.error(f"Invalid wrong_q type: {type(wrong_q)}")
94
- st.error("유사 문제 생성에 필요한 데이터 형식이 잘못되었습니다.")
95
- return None
96
-
97
- try:
98
- # misconception_id가 없거나 NaN인 경우 다른 misconception 사용
99
- if pd.isna(misconception_id):
100
- logger.info("Original misconception_id is NaN, trying to find alternative")
101
- # 현재까지 나온 misconception들 중에서 선택
102
- available_misconceptions = [m for m in st.session_state.misconceptions if not pd.isna(m)]
103
-
104
- if available_misconceptions:
105
- # 가장 최근에 나온 misconception 선택
106
- misconception_id = available_misconceptions[-1]
107
- logger.info(f"Using alternative misconception_id: {misconception_id}")
108
- else:
109
- # 기본 misconception ID 사용 (예: 가장 기본적인 misconception)
110
- misconception_id = 2001 # 적절한 기본값으로 수정 필요
111
- logger.info(f"Using default misconception_id: {misconception_id}")
112
-
113
- # 데이터 준비 (튜플 변환 방지)
114
- input_data = {
115
- 'construct_name': str(wrong_q.get('ConstructName', '')),
116
- 'subject_name': str(wrong_q.get('SubjectName', '')),
117
- 'question_text': str(wrong_q.get('QuestionText', '')),
118
- 'correct_answer_text': str(wrong_q.get(f'Answer{wrong_q["CorrectAnswer"]}Text', '')),
119
- 'wrong_answer_text': str(wrong_q.get(f'Answer{st.session_state.selected_wrong_answer}Text', '')),
120
- 'misconception_id': int(misconception_id)
121
- }
122
-
123
- logger.info(f"Prepared input data: {input_data}")
124
-
125
- with st.spinner("📝 유사 문제를 생성하고 있습니다..."):
126
- # 유사 문제 생성 호출
127
- generated_q, _ = generator.generate_similar_question_with_text(
128
- construct_name=input_data['construct_name'],
129
- subject_name=input_data['subject_name'],
130
- question_text=input_data['question_text'],
131
- correct_answer_text=input_data['correct_answer_text'],
132
- wrong_answer_text=input_data['wrong_answer_text'],
133
- misconception_id=input_data['misconception_id']
134
- )
135
-
136
- if generated_q:
137
- verifier = load_answer_verifier()
138
- with st.status("🤔 AI가 문제를 검토하고 있습니다..."):
139
- st.write("답안의 정확성을 검증하고 있습니다...")
140
- verified_answer = verifier.verify_answer(
141
- question=generated_q.question,
142
- choices=generated_q.choices
143
- )
144
-
145
- if verified_answer:
146
- logger.info(f"Answer verified: {verified_answer}")
147
- st.write("✅ 검증 완료!")
148
- result = {
149
- 'question': generated_q.question,
150
- 'choices': generated_q.choices,
151
- 'correct': verified_answer,
152
- 'explanation': generated_q.explanation
153
- }
154
- st.session_state['current_similar_question_answer'] = verified_answer
155
- return result
156
- else:
157
- logger.warning("Answer verification failed, using original answer")
158
- st.write("⚠️ 검증에 실패했습니다. 원본 답안을 사용합니다.")
159
- result = {
160
- 'question': generated_q.question,
161
- 'choices': generated_q.choices,
162
- 'correct': generated_q.correct_answer,
163
- 'explanation': generated_q.explanation
164
- }
165
- st.session_state['current_similar_question_answer'] = generated_q.correct_answer
166
- return result
167
-
168
- except Exception as e:
169
- logger.error(f"Error in generate_similar_question: {str(e)}")
170
- st.error(f"문제 생성 중 오류가 발생했습니다: {str(e)}")
171
- return None
172
-
173
- return None
174
-
175
- def handle_answer(answer, current_q):
176
- """답변 처리"""
177
- if answer != current_q['CorrectAnswer']:
178
- wrong_q_dict = current_q.to_dict()
179
- st.session_state.wrong_questions.append(wrong_q_dict)
180
- st.session_state.selected_wrong_answer = answer
181
-
182
- misconception_key = f'Misconception{answer}Id'
183
- misconception_id = current_q.get(misconception_key)
184
- st.session_state.misconceptions.append(misconception_id)
185
-
186
- st.session_state.current_question_index += 1
187
- if st.session_state.current_question_index >= 10:
188
- st.session_state.current_step = 'review'
189
-
190
- # 전역 LaTeX 포맷터 인스턴스 생성
191
- #latex_formatter = LatexFormatter()
192
-
193
- def display_math_content(content: str):
194
- """수학 내용을 화면에 표시"""
195
- try:
196
- # LaTeX 텍스트를 Streamlit에서 렌더링
197
- st.latex(content) # LaTeX로 렌더링
198
- except Exception as e:
199
- logger.error(f"Error displaying LaTeX content: {e}")
200
- # 텍스트로 대체 표시
201
- formatted_content = LatexNodes2Text().latex_to_text(content)
202
- st.write(f"**Error rendering LaTeX. Showing text instead:** {formatted_content}")
203
-
204
- def format_answer_choice(choice: str) -> str:
205
- """선택지 LaTeX 포맷팅"""
206
- formatted_content = LatexNodes2Text().latex_to_text(choice)
207
- return formatted_content
208
-
209
- def main():
210
- """메인 애플리케이션 로직"""
211
- st.title("MisconcepTutor")
212
-
213
- # Generator 초기화
214
- generator = load_question_generator()
215
-
216
- # 초기 화면
217
- if st.session_state.current_step == 'initial':
218
- st.write("#### 학습을 시작하겠습니다. 10개의 문제를 풀어볼까요?")
219
- if st.button("학습 시작", key="start_quiz"):
220
- start_quiz()
221
- st.rerun()
222
-
223
- # 퀴즈 화면
224
- elif st.session_state.current_step == 'quiz':
225
- current_q = st.session_state.questions.iloc[st.session_state.current_question_index]
226
-
227
- # 진행 상황 표시
228
- progress = st.session_state.current_question_index / 10
229
- st.progress(progress)
230
- st.write(f"### 문제 {st.session_state.current_question_index + 1}/10")
231
-
232
- # 문제 표시
233
- st.markdown("---")
234
- #display_math_question(current_q['QuestionText'])
235
- display_math_content(current_q['QuestionText']) # display_math_question 대신 display_math_content 사용
236
-
237
- # 보기 표시
238
- col1, col2 = st.columns(2)
239
- with col1:
240
- if st.button(f"A) {format_answer_choice(current_q['AnswerAText'])}", key="A"):
241
- handle_answer('A', current_q)
242
- st.rerun()
243
- if st.button(f"C) {format_answer_choice(current_q['AnswerCText'])}", key="C"):
244
- handle_answer('C', current_q)
245
- st.rerun()
246
- with col2:
247
- if st.button(f"B) {format_answer_choice(current_q['AnswerBText'])}", key="B"):
248
- handle_answer('B', current_q)
249
- st.rerun()
250
- if st.button(f"D) {format_answer_choice(current_q['AnswerDText'])}", key="D"):
251
- handle_answer('D', current_q)
252
- st.rerun()
253
-
254
- # 복습 화면
255
- elif st.session_state.current_step == 'review':
256
- st.write("### 학습 결과")
257
-
258
- # 결과 통계
259
- col1, col2, col3 = st.columns(3)
260
- col1.metric("총 문제 수", 10)
261
- col2.metric("맞은 문제", 10 - len(st.session_state.wrong_questions))
262
- col3.metric("틀린 문제", len(st.session_state.wrong_questions))
263
-
264
- # 결과에 따른 메시지 표시
265
- if len(st.session_state.wrong_questions) == 0:
266
- st.balloons() # 축하 효과
267
- st.success("🎉 축하합니다! 모든 문제를 맞추셨어요!")
268
- st.markdown("""
269
- ### 🏆 수학왕이십니다!
270
- 완벽한 점수를 받으셨네요! 수학적 개념을 정확하게 이해하고 계신 것 같습니다.
271
- """)
272
- elif len(st.session_state.wrong_questions) <= 3:
273
- st.success("잘 하셨어요! 조금만 더 연습하면 완벽할 거예요!")
274
- else:
275
- st.info("천천히 개념을 복습해보아요. 연습하다 보면 늘어날 거예요!")
276
-
277
- # 네비게이션 버튼
278
- col1, col2 = st.columns(2)
279
- with col1:
280
- if st.button("🔄 새로운 문제 세트 시작하기", use_container_width=True):
281
- start_quiz()
282
- st.rerun()
283
- with col2:
284
- if st.button("🏠 처음으로 돌아가기", use_container_width=True):
285
- st.session_state.clear()
286
- st.rerun()
287
-
288
- # 틀린 문제 분석 부분
289
- if st.session_state.wrong_questions:
290
- st.write("### ✍️ 틀린 문제 분석")
291
- tabs = st.tabs([f"📝 틀린 문제 #{i + 1}" for i in range(len(st.session_state.wrong_questions))])
292
-
293
- for i, (tab, (wrong_q, misconception_id)) in enumerate(zip(
294
- tabs,
295
- zip(st.session_state.wrong_questions, st.session_state.misconceptions)
296
- )):
297
- with tab:
298
- st.write("**📋 문제:**")
299
- st.write(wrong_q['QuestionText'])
300
- st.write("**✅ 정답:**", wrong_q['CorrectAnswer'])
301
-
302
- st.write("---")
303
- st.write("**🔍 관련된 Misconception:**")
304
- if misconception_id and not pd.isna(misconception_id):
305
- misconception_text = generator.get_misconception_text(misconception_id)
306
- st.info(f"Misconception ID: {int(misconception_id)}\n\n{misconception_text}")
307
- else:
308
- st.info("Misconception 정보가 없습니다.")
309
-
310
- if st.button(f"📚 유사 문제 풀기", key=f"retry_{i}"):
311
- st.session_state[f"show_similar_question_{i}"] = True
312
- st.session_state[f"similar_question_answered_{i}"] = False
313
- st.rerun()
314
-
315
- if st.session_state.get(f"show_similar_question_{i}", False):
316
- st.divider()
317
- new_question = generate_similar_question(wrong_q, misconception_id, generator)
318
- if new_question:
319
- st.write("### 🎯 유사 문제")
320
- #st.write(new_question['question'])
321
- display_math_content(new_question['question']) # 함수 교체
322
-
323
-
324
- # 답변 상태 확인
325
- answered = st.session_state.get(f"similar_question_answered_{i}", False)
326
-
327
- # 보기 표시
328
- st.write("**보기:**")
329
- col1, col2 = st.columns(2)
330
-
331
-
332
- # 답변하지 않은 경우에만 버튼 활성화
333
- if not answered:
334
- with col1:
335
- for option in ['A', 'C']:
336
- if st.button(
337
- f"{option}) {LatexNodes2Text().latex_to_text(new_question['choices'][option])}",
338
- key=f"similar_{option}_{i}"
339
- ):
340
- st.session_state[f"similar_question_answered_{i}"] = True
341
- st.session_state[f"selected_answer_{i}"] = option
342
- correct_answer = st.session_state.get('current_similar_question_answer')
343
- if option == correct_answer:
344
- st.session_state[f"is_correct_{i}"] = True
345
- else:
346
- st.session_state[f"is_correct_{i}"] = False
347
- st.rerun()
348
-
349
- with col2:
350
- for option in ['B', 'D']:
351
- if st.button(
352
- f"{option}) {LatexNodes2Text().latex_to_text(new_question['choices'][option])}",
353
- key=f"similar_{option}_{i}"
354
- ):
355
- st.session_state[f"similar_question_answered_{i}"] = True
356
- st.session_state[f"selected_answer_{i}"] = option
357
- correct_answer = st.session_state.get('current_similar_question_answer')
358
- if option == correct_answer:
359
- st.session_state[f"is_correct_{i}"] = True
360
- else:
361
- st.session_state[f"is_correct_{i}"] = False
362
- st.rerun()
363
- # 답변한 경우 결과 표시
364
- if answered:
365
- is_correct = st.session_state.get(f"is_correct_{i}", False)
366
- correct_answer = st.session_state.get('current_similar_question_answer')
367
- if is_correct:
368
- st.success("✅ 정답입니다!")
369
- else:
370
- st.error(f"❌ 틀렸습니다. 정답은 {correct_answer}입니다.")
371
-
372
- # 해설 표시
373
- st.write("---")
374
- st.write("**📝 해설:**", new_question['explanation'])
375
-
376
- # 다시 풀기 버튼
377
- if st.button("🔄 다시 풀기", key=f"reset_{i}"):
378
- st.session_state[f"similar_question_answered_{i}"] = False
379
- st.session_state[f"selected_answer_{i}"] = None
380
- st.session_state[f"is_correct_{i}"] = None
381
- st.rerun()
382
-
383
- # 문제 닫기 버튼
384
- if st.button("❌ 문제 닫기", key=f"close_{i}"):
385
- st.session_state[f"show_similar_question_{i}"] = False
386
- st.session_state[f"similar_question_answered_{i}"] = False
387
- st.session_state[f"selected_answer_{i}"] = None
388
- st.session_state[f"is_correct_{i}"] = None
389
- st.rerun()
390
-
391
- # 화면 아래 여백 추가
392
- st.markdown("<br>" * 5, unsafe_allow_html=True) # 5줄의 빈 줄 추가
393
- st.markdown("""
394
- <div style="height: 100px;">
395
- </div>
396
- """, unsafe_allow_html=True) # 추가 여백
397
- else:
398
- st.error("유사 문제를 생성할 수 없습니다.")
399
- if st.button("❌ 닫기", key=f"close_error_{i}"):
400
- st.session_state[f"show_similar_question_{i}"] = False
401
- st.rerun()
402
- # 화면 아래 여백 추가
403
- st.markdown("<br>" * 5, unsafe_allow_html=True) # 5줄의 빈 줄 추가
404
- st.markdown("""
405
- <div style="height: 100px;">
406
- </div>
407
- """, unsafe_allow_html=True) # 추가 여백
408
- if __name__ == "__main__":
409
- main()
410
-
411
- # random_state 42에서 정답
412
- # D C A A C
413
- # A B B B B