Jintonic92 commited on
Commit
ca27c07
ยท
verified ยท
1 Parent(s): 1883518

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +295 -8
app.py CHANGED
@@ -1,11 +1,87 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  @st.cache_resource
2
  def load_answer_verifier():
3
  """๋‹ต์•ˆ ๊ฒ€์ฆ ๋ชจ๋ธ ๋กœ๋“œ"""
4
  from src.ThirdModule.module3 import AnswerVerifier
5
  return AnswerVerifier()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
  def generate_similar_question(wrong_q, misconception_id, generator):
8
- """์œ ์‚ฌ ๋ฌธ์ œ ์ƒ์„ฑ ๋ฐ ๊ฒ€์ฆ"""
9
  logger.info(f"Generating similar question for misconception_id: {misconception_id}")
10
 
11
  # ์ž…๋ ฅ ๋ฐ์ดํ„ฐ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ
@@ -13,14 +89,14 @@ def generate_similar_question(wrong_q, misconception_id, generator):
13
  logger.error(f"Invalid wrong_q type: {type(wrong_q)}")
14
  st.error("์œ ์‚ฌ ๋ฌธ์ œ ์ƒ์„ฑ์— ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ ํ˜•์‹์ด ์ž˜๋ชป๋˜์—ˆ์Šต๋‹ˆ๋‹ค.")
15
  return None
16
-
17
  # misconception_id๊ฐ€ ์œ ํšจํ•œ์ง€ ํ™•์ธ
18
  if pd.isna(misconception_id):
19
  logger.warning("misconception_id is NaN")
20
  return None
21
-
22
  try:
23
- # ๋ฐ์ดํ„ฐ ์ค€๋น„
24
  input_data = {
25
  'construct_name': str(wrong_q.get('ConstructName', '')),
26
  'subject_name': str(wrong_q.get('SubjectName', '')),
@@ -30,9 +106,27 @@ def generate_similar_question(wrong_q, misconception_id, generator):
30
  'misconception_id': int(misconception_id)
31
  }
32
 
33
- # ์œ ์‚ฌ ๋ฌธ์ œ ์ƒ์„ฑ
34
- generated_q, _ = generator.generate_similar_question_with_text(**input_data)
35
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
36
  if generated_q:
37
  verifier = load_answer_verifier()
38
  with st.spinner("๋‹ต์•ˆ์„ ๊ฒ€์ฆํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค..."):
@@ -59,10 +153,203 @@ def generate_similar_question(wrong_q, misconception_id, generator):
59
  'choices': generated_q.choices,
60
  'correct': generated_q.correct_answer,
61
  'explanation': generated_q.explanation
62
- }
63
  except Exception as e:
64
  logger.error(f"Error in generate_similar_question: {str(e)}")
65
  st.error(f"๋ฌธ์ œ ์ƒ์„ฑ ์ค‘ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค: {str(e)}")
66
  return None
67
 
68
- return None
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ logging.basicConfig(level=logging.DEBUG)
9
+
10
+
11
+ # Streamlit ํŽ˜์ด์ง€ ๊ธฐ๋ณธ ์„ค์ •
12
+ st.set_page_config(
13
+ page_title="MisconcepTutor",
14
+ layout="wide",
15
+ initial_sidebar_state="expanded"
16
+ )
17
+
18
  @st.cache_resource
19
  def load_answer_verifier():
20
  """๋‹ต์•ˆ ๊ฒ€์ฆ ๋ชจ๋ธ ๋กœ๋“œ"""
21
  from src.ThirdModule.module3 import AnswerVerifier
22
  return AnswerVerifier()
23
+
24
+ # ๊ฒฝ๋กœ ์„ค์ •
25
+ base_path = os.path.dirname(os.path.abspath(__file__))
26
+ data_path = os.path.join(base_path, 'Data')
27
+ misconception_csv_path = os.path.join(data_path, 'misconception_mapping.csv')
28
+
29
+ # ๋กœ๊น… ์„ค์ •
30
+ logging.basicConfig(level=logging.INFO)
31
+ logger = logging.getLogger(__name__)
32
+
33
+ # ์„ธ์…˜ ์ƒํƒœ ์ดˆ๊ธฐํ™” - ๊ฐ€์žฅ ๋จผ์ € ์‹คํ–‰๋˜๋„๋ก ์ตœ์ƒ๋‹จ์— ๋ฐฐ์น˜
34
+ if 'initialized' not in st.session_state:
35
+ st.session_state.initialized = True
36
+ st.session_state.wrong_questions = []
37
+ st.session_state.misconceptions = []
38
+ st.session_state.current_question_index = 0
39
+ st.session_state.generated_questions = []
40
+ st.session_state.current_step = 'initial'
41
+ st.session_state.selected_wrong_answer = None
42
+ st.session_state.questions = []
43
+ logger.info("Session state initialized")
44
+
45
+ # ๋ฌธ์ œ ์ƒ์„ฑ๊ธฐ ์ดˆ๊ธฐํ™”
46
+ @st.cache_resource
47
+ def load_question_generator():
48
+ """๋ฌธ์ œ ์ƒ์„ฑ ๋ชจ๋ธ ๋กœ๋“œ"""
49
+ if not os.path.exists(misconception_csv_path):
50
+ st.error(f"CSV ํŒŒ์ผ์ด ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค: {misconception_csv_path}")
51
+ raise FileNotFoundError(f"CSV ํŒŒ์ผ์ด ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค: {misconception_csv_path}")
52
+ return SimilarQuestionGenerator(misconception_csv_path=misconception_csv_path)
53
+
54
+ # CSV ๋ฐ์ดํ„ฐ ๋กœ๋“œ ํ•จ์ˆ˜
55
+ @st.cache_data
56
+ def load_data(data_file = '/train.csv'):
57
+ try:
58
+ file_path = os.path.join(data_path, data_file.lstrip('/'))
59
+ df = pd.read_csv(file_path)
60
+ logger.info(f"Data loaded successfully from {file_path}")
61
+ return df
62
+ except FileNotFoundError:
63
+ st.error(f"ํŒŒ์ผ์„ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค: {data_file}")
64
+ logger.error(f"File not found: {data_file}")
65
+ return None
66
+
67
+ def start_quiz():
68
+ """ํ€ด์ฆˆ ์‹œ์ž‘ ๋ฐ ์ดˆ๊ธฐํ™”"""
69
+ df = load_data()
70
+ if df is None or df.empty:
71
+ st.error("๋ฐ์ดํ„ฐ๋ฅผ ๋ถˆ๋Ÿฌ์˜ฌ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ๋ฐ์ดํ„ฐ์…‹์„ ํ™•์ธํ•ด์ฃผ์„ธ์š”.")
72
+ return
73
+
74
+ st.session_state.questions = df.sample(n=10, random_state=42)
75
+ st.session_state.current_step = 'quiz'
76
+ st.session_state.current_question_index = 0
77
+ st.session_state.wrong_questions = []
78
+ st.session_state.misconceptions = []
79
+ st.session_state.generated_questions = []
80
+ logger.info("Quiz started")
81
+
82
 
83
  def generate_similar_question(wrong_q, misconception_id, generator):
84
+ """์œ ์‚ฌ ๋ฌธ์ œ ์ƒ์„ฑ"""
85
  logger.info(f"Generating similar question for misconception_id: {misconception_id}")
86
 
87
  # ์ž…๋ ฅ ๋ฐ์ดํ„ฐ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ
 
89
  logger.error(f"Invalid wrong_q type: {type(wrong_q)}")
90
  st.error("์œ ์‚ฌ ๋ฌธ์ œ ์ƒ์„ฑ์— ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ ํ˜•์‹์ด ์ž˜๋ชป๋˜์—ˆ์Šต๋‹ˆ๋‹ค.")
91
  return None
92
+
93
  # misconception_id๊ฐ€ ์œ ํšจํ•œ์ง€ ํ™•์ธ
94
  if pd.isna(misconception_id):
95
  logger.warning("misconception_id is NaN")
96
  return None
97
+
98
  try:
99
+ # ๋ฐ์ดํ„ฐ ์ค€๋น„ (ํŠœํ”Œ ๋ณ€ํ™˜ ๋ฐฉ์ง€)
100
  input_data = {
101
  'construct_name': str(wrong_q.get('ConstructName', '')),
102
  'subject_name': str(wrong_q.get('SubjectName', '')),
 
106
  'misconception_id': int(misconception_id)
107
  }
108
 
109
+ logger.info(f"Prepared input data: {input_data}")
 
110
 
111
+ # ์œ ์‚ฌ ๋ฌธ์ œ ์ƒ์„ฑ ํ˜ธ์ถœ
112
+ generated_q, _ = generator.generate_similar_question_with_text(
113
+ construct_name=input_data['construct_name'],
114
+ subject_name=input_data['subject_name'],
115
+ question_text=input_data['question_text'],
116
+ correct_answer_text=input_data['correct_answer_text'],
117
+ wrong_answer_text=input_data['wrong_answer_text'],
118
+ misconception_id=input_data['misconception_id']
119
+ )
120
+ # Before module 3 integration code
121
+ # if generated_q:
122
+ # return {
123
+ # 'question': generated_q.question,
124
+ # 'choices': generated_q.choices,
125
+ # 'correct': generated_q.correct_answer,
126
+ # 'explanation': generated_q.explanation
127
+ # }
128
+
129
+ # integrating module3
130
  if generated_q:
131
  verifier = load_answer_verifier()
132
  with st.spinner("๋‹ต์•ˆ์„ ๊ฒ€์ฆํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค..."):
 
153
  'choices': generated_q.choices,
154
  'correct': generated_q.correct_answer,
155
  'explanation': generated_q.explanation
156
+ }
157
  except Exception as e:
158
  logger.error(f"Error in generate_similar_question: {str(e)}")
159
  st.error(f"๋ฌธ์ œ ์ƒ์„ฑ ์ค‘ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค: {str(e)}")
160
  return None
161
 
162
+ return None
163
+
164
+ def handle_answer(answer, current_q):
165
+ """๋‹ต๋ณ€ ์ฒ˜๋ฆฌ"""
166
+ if answer != current_q['CorrectAnswer']:
167
+ wrong_q_dict = current_q.to_dict()
168
+ st.session_state.wrong_questions.append(wrong_q_dict)
169
+ st.session_state.selected_wrong_answer = answer
170
+
171
+ misconception_key = f'Misconception{answer}Id'
172
+ misconception_id = current_q.get(misconception_key)
173
+ st.session_state.misconceptions.append(misconception_id)
174
+
175
+ st.session_state.current_question_index += 1
176
+ if st.session_state.current_question_index >= 10:
177
+ st.session_state.current_step = 'review'
178
+
179
+ def main():
180
+ """๋ฉ”์ธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋กœ์ง"""
181
+ st.title("MisconcepTutor")
182
+
183
+ # Generator ์ดˆ๊ธฐํ™”
184
+ generator = load_question_generator()
185
+
186
+ # ์ดˆ๊ธฐ ํ™”๋ฉด
187
+ if st.session_state.current_step == 'initial':
188
+ st.write("#### ํ•™์Šต์„ ์‹œ์ž‘ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. 10๊ฐœ์˜ ๋ฌธ์ œ๋ฅผ ํ’€์–ด๋ณผ๊นŒ์š”?")
189
+ if st.button("ํ•™์Šต ์‹œ์ž‘", key="start_quiz"):
190
+ start_quiz()
191
+ st.rerun()
192
+
193
+ # ํ€ด์ฆˆ ํ™”๋ฉด
194
+ elif st.session_state.current_step == 'quiz':
195
+ current_q = st.session_state.questions.iloc[st.session_state.current_question_index]
196
+
197
+ # ์ง„ํ–‰ ์ƒํ™ฉ ํ‘œ์‹œ
198
+ progress = st.session_state.current_question_index / 10
199
+ st.progress(progress)
200
+ st.write(f"### ๋ฌธ์ œ {st.session_state.current_question_index + 1}/10")
201
+
202
+ # ๋ฌธ์ œ ํ‘œ์‹œ
203
+ st.markdown("---")
204
+ st.write(current_q['QuestionText'])
205
+
206
+ # ๋ณด๊ธฐ ํ‘œ์‹œ
207
+ col1, col2 = st.columns(2)
208
+ with col1:
209
+ if st.button(f"A) {current_q['AnswerAText']}", key="A"):
210
+ handle_answer('A', current_q)
211
+ st.rerun()
212
+ if st.button(f"C) {current_q['AnswerCText']}", key="C"):
213
+ handle_answer('C', current_q)
214
+ st.rerun()
215
+ with col2:
216
+ if st.button(f"B) {current_q['AnswerBText']}", key="B"):
217
+ handle_answer('B', current_q)
218
+ st.rerun()
219
+ if st.button(f"D) {current_q['AnswerDText']}", key="D"):
220
+ handle_answer('D', current_q)
221
+ st.rerun()
222
+
223
+ # ๋ณต์Šต ํ™”๋ฉด
224
+ elif st.session_state.current_step == 'review':
225
+ st.write("### ํ•™์Šต ๊ฒฐ๊ณผ")
226
+
227
+ # ๊ฒฐ๊ณผ ํ†ต๊ณ„
228
+ col1, col2, col3 = st.columns(3)
229
+ col1.metric("์ด ๋ฌธ์ œ ์ˆ˜", 10)
230
+ col2.metric("๋งž์€ ๋ฌธ์ œ", 10 - len(st.session_state.wrong_questions))
231
+ col3.metric("ํ‹€๋ฆฐ ๋ฌธ์ œ", len(st.session_state.wrong_questions))
232
+
233
+ # ๊ฒฐ๊ณผ์— ๋”ฐ๋ฅธ ๋ฉ”์‹œ์ง€ ํ‘œ์‹œ
234
+ if len(st.session_state.wrong_questions) == 0:
235
+ st.balloons() # ์ถ•ํ•˜ ํšจ๊ณผ
236
+ st.success("๐ŸŽ‰ ์ถ•ํ•˜ํ•ฉ๋‹ˆ๋‹ค! ๋ชจ๋“  ๋ฌธ์ œ๋ฅผ ๋งž์ถ”์…จ์–ด์š”!")
237
+ st.markdown("""
238
+ ### ๐Ÿ† ์ˆ˜ํ•™์™•์ด์‹ญ๋‹ˆ๋‹ค!
239
+ ์™„๋ฒฝํ•œ ์ ์ˆ˜๋ฅผ ๋ฐ›์œผ์…จ๋„ค์š”! ์ˆ˜ํ•™์  ๊ฐœ๋…์„ ์ •ํ™•ํ•˜๊ฒŒ ์ดํ•ดํ•˜๊ณ  ๊ณ„์‹  ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.
240
+ """)
241
+ elif len(st.session_state.wrong_questions) <= 3:
242
+ st.success("์ž˜ ํ•˜์…จ์–ด์š”! ์กฐ๊ธˆ๋งŒ ๋” ์—ฐ์Šตํ•˜๋ฉด ์™„๋ฒฝํ•  ๊ฑฐ์˜ˆ์š”!")
243
+ else:
244
+ st.info("์ฒœ์ฒœํžˆ ๊ฐœ๋…์„ ๋ณต์Šตํ•ด๋ณด์•„์š”. ์—ฐ์Šตํ•˜๋‹ค ๋ณด๋ฉด ๋Š˜์–ด๋‚  ๊ฑฐ์˜ˆ์š”!")
245
+
246
+ # ๋„ค๋น„๊ฒŒ์ด์…˜ ๋ฒ„ํŠผ
247
+ col1, col2 = st.columns(2)
248
+ with col1:
249
+ if st.button("๐Ÿ”„ ์ƒˆ๋กœ์šด ๋ฌธ์ œ ์„ธํŠธ ์‹œ์ž‘ํ•˜๊ธฐ", use_container_width=True):
250
+ start_quiz()
251
+ st.rerun()
252
+ with col2:
253
+ if st.button("๐Ÿ  ์ฒ˜์Œ์œผ๋กœ ๋Œ์•„๊ฐ€๊ธฐ", use_container_width=True):
254
+ st.session_state.clear()
255
+ st.rerun()
256
+
257
+ # ํ‹€๋ฆฐ ๋ฌธ์ œ ๋ถ„์„
258
+ if st.session_state.wrong_questions:
259
+ st.write("### โœ๏ธ ํ‹€๋ฆฐ ๋ฌธ์ œ ๋ถ„์„")
260
+ for i, (wrong_q, misconception_id) in enumerate(zip(
261
+ st.session_state.wrong_questions,
262
+ st.session_state.misconceptions
263
+ )):
264
+ with st.expander(f"๐Ÿ“ ํ‹€๋ฆฐ ๋ฌธ์ œ #{i + 1}"):
265
+ st.write("**๐Ÿ“‹ ๋ฌธ์ œ:**")
266
+ st.write(wrong_q['QuestionText'])
267
+ st.write("**โœ… ์ •๋‹ต:**", wrong_q['CorrectAnswer'])
268
+
269
+ st.write("---")
270
+ st.write("**๐Ÿ” ๊ด€๋ จ๋œ Misconception:**")
271
+ if misconception_id and not pd.isna(misconception_id):
272
+ misconception_text = generator.get_misconception_text(misconception_id)
273
+ st.info(f"Misconception ID: {int(misconception_id)}\n\n{misconception_text}")
274
+ else:
275
+ st.info("Misconception ์ •๋ณด๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.")
276
+
277
+ # ํ‹€๋ฆฐ ๋ฌธ์ œ ๋ถ„์„ ๋ถ€๋ถ„์—์„œ
278
+ if st.button(f"๐Ÿ“š ์œ ์‚ฌ ๋ฌธ์ œ ํ’€๊ธฐ #{i + 1}", key=f"retry_{i}"):
279
+ # ์œ ์‚ฌ ๋ฌธ์ œ ์ƒ์„ฑ ์ƒํƒœ๋ฅผ ์„ธ์…˜์— ์ €์žฅ
280
+ st.session_state[f"show_similar_question_{i}"] = True
281
+ st.session_state[f"similar_question_answered_{i}"] = False
282
+ # ๊ธฐ์กด ๋‹ต๋ณ€ ๊ธฐ๋ก ์ดˆ๊ธฐํ™”
283
+ st.rerun()
284
+
285
+ # ์œ ์‚ฌ ๋ฌธ์ œ๊ฐ€ ์ƒ์„ฑ๋œ ์ƒํƒœ์ธ ๊ฒฝ์šฐ
286
+ if st.session_state.get(f"show_similar_question_{i}", False):
287
+ with st.spinner("์œ ์‚ฌ ๋ฌธ์ œ๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค..."):
288
+ new_question = generate_similar_question(wrong_q, misconception_id, generator)
289
+ if new_question:
290
+ st.write("### ๐ŸŽฏ ์œ ์‚ฌ ๋ฌธ์ œ")
291
+ st.write(new_question['question'])
292
+
293
+ # ๋‹ต๋ณ€ ์ƒํƒœ ํ™•์ธ
294
+ answered = st.session_state.get(f"similar_question_answered_{i}", False)
295
+ selected_answer = st.session_state.get(f"selected_answer_{i}", None)
296
+
297
+ # ๋ณด๊ธฐ ํ‘œ์‹œ
298
+ st.write("**๋ณด๊ธฐ:**")
299
+ col1, col2 = st.columns(2)
300
+
301
+ # ๋‹ต๋ณ€ํ•˜์ง€ ์•Š์€ ๊ฒฝ์šฐ์—๋งŒ ๋ฒ„ํŠผ ํ™œ์„ฑํ™”
302
+ if not answered:
303
+ with col1:
304
+ for option in ['A', 'C']:
305
+ if st.button(
306
+ f"{option}) {new_question['choices'][option]}",
307
+ key=f"similar_{option}_{i}"
308
+ ):
309
+ st.session_state[f"similar_question_answered_{i}"] = True
310
+ st.session_state[f"selected_answer_{i}"] = option
311
+ st.rerun()
312
+
313
+ with col2:
314
+ for option in ['B', 'D']:
315
+ if st.button(
316
+ f"{option}) {new_question['choices'][option]}",
317
+ key=f"similar_{option}_{i}"
318
+ ):
319
+ st.session_state[f"similar_question_answered_{i}"] = True
320
+ st.session_state[f"selected_answer_{i}"] = option
321
+ st.rerun()
322
+
323
+ # ๋‹ต๋ณ€ํ•œ ๊ฒฝ์šฐ ๊ฒฐ๊ณผ ํ‘œ์‹œ
324
+ if answered:
325
+ selected = st.session_state[f"selected_answer_{i}"]
326
+ if selected == new_question['correct']:
327
+ st.success("โœ… ์ •๋‹ต์ž…๋‹ˆ๋‹ค!")
328
+ else:
329
+ st.error(f"โŒ ํ‹€๋ ธ์Šต๋‹ˆ๋‹ค. ์ •๋‹ต์€ {new_question['correct']}์ž…๋‹ˆ๋‹ค.")
330
+
331
+ # ํ•ด์„ค ํ‘œ์‹œ
332
+ st.write("---")
333
+ st.write("**๐Ÿ“ ํ•ด์„ค:**", new_question['explanation'])
334
+
335
+ # ๋‹ค์‹œ ํ’€๊ธฐ ๋ฒ„ํŠผ
336
+ if st.button("๐Ÿ”„ ๋‹ค์‹œ ํ’€๊ธฐ", key=f"reset_{i}"):
337
+ st.session_state[f"similar_question_answered_{i}"] = False
338
+ st.session_state[f"selected_answer_{i}"] = None
339
+ st.rerun()
340
+
341
+ # ๋ฌธ์ œ ๋‹ซ๊ธฐ ๋ฒ„ํŠผ
342
+ if st.button("โŒ ๋ฌธ์ œ ๋‹ซ๊ธฐ", key=f"close_{i}"):
343
+ st.session_state[f"show_similar_question_{i}"] = False
344
+ st.rerun()
345
+ else:
346
+ st.error("์œ ์‚ฌ ๋ฌธ์ œ๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.")
347
+ if st.button("โŒ ๋‹ซ๊ธฐ", key=f"close_error_{i}"):
348
+ st.session_state[f"show_similar_question_{i}"] = False
349
+ st.rerun()
350
+ if __name__ == "__main__":
351
+ main()
352
+
353
+ # random_state 42์—์„œ ์ •๋‹ต
354
+ # D C A A C
355
+ # A B B B B