Abdul-Haseeb commited on
Commit
e69209e
·
verified ·
1 Parent(s): 77eaffc

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +236 -236
app.py CHANGED
@@ -1,236 +1,236 @@
1
- import streamlit as st
2
- import requests
3
- from pipelines import generate_quiz
4
- from dotenv import load_dotenv
5
- import shelve
6
- from dataclasses import dataclass
7
- from typing import Literal
8
- import streamlit.components.v1 as components
9
-
10
- load_dotenv()
11
-
12
- st.title(":red[DEV] *the Quizbot* 🤖")
13
- st.subheader("Hey there! I'm **Dev** the QuizBot! Ready to flaunt your smarts in a topic of your choice?", divider='grey')
14
-
15
- @st.experimental_dialog("Invalid Choice", width="small")
16
- def warn():
17
- st.write("Please choose from the given options.")
18
-
19
- @dataclass
20
- class Message:
21
- origin: Literal["human", "ai"]
22
- message: str
23
-
24
- def load_css():
25
- with open("static/styles.css", "r") as f:
26
- st.markdown(f"<style>{f.read()}</style>", unsafe_allow_html=True)
27
-
28
- def initialize_session_state():
29
- defaults = {
30
- "quiz": None,
31
- "current_question_index": 0,
32
- "responses": [],
33
- "interactions": [],
34
- "quiz_completed": False,
35
- "topic": None,
36
- "messages": load_chat_history()
37
- }
38
- for key, value in defaults.items():
39
- if key not in st.session_state:
40
- st.session_state[key] = value
41
-
42
- def load_chat_history():
43
- with shelve.open("chat_history") as db:
44
- return db.get("messages", [])
45
-
46
- def save_chat_history(messages):
47
- with shelve.open("chat_history") as db:
48
- db["messages"] = messages
49
-
50
- def fetch_wikipedia_link(topic):
51
- api_url = f"https://en.wikipedia.org/api/rest_v1/page/summary/{topic}"
52
- response = requests.get(api_url)
53
- if response.status_code == 200:
54
- return response.json()['content_urls']['desktop']['page']
55
- st.error("Failed to fetch Wikipedia content.")
56
- return None
57
-
58
- load_css()
59
- initialize_session_state()
60
-
61
- placeholder = st.container()
62
-
63
- if st.session_state.quiz is None:
64
- st.session_state.interactions = []
65
- with st.form("generate_quiz_form"):
66
- st.markdown('**Enter a Topic:**')
67
- cols = st.columns((4, 1))
68
- topic = cols[0].text_input("Topic:", label_visibility="collapsed")
69
- generate_button = cols[1].form_submit_button("Generate Quiz")
70
-
71
- if generate_button:
72
- if topic:
73
- link = fetch_wikipedia_link(topic)
74
- if link:
75
- for _ in range(2):
76
- try:
77
- quiz = generate_quiz(link)
78
- if quiz:
79
- st.session_state.quiz = quiz
80
- st.session_state.current_question_index = 0
81
- st.session_state.responses = []
82
- st.session_state.quiz_completed = False
83
- st.rerun()
84
- except Exception as e:
85
- st.error(f"Failed to generate quiz: {e}")
86
- else:
87
- st.error("Please enter a topic.")
88
- else:
89
- with st.form("quiz_form"):
90
- if st.session_state.quiz_completed:
91
- st.markdown("## Results")
92
- score = sum(1 for interaction in st.session_state.interactions if interaction["is_correct"])
93
- if score > len(st.session_state.quiz['questions']):
94
- score = len(st.session_state.quiz['questions'])
95
- st.markdown(f"Your score: {score} out of {len(st.session_state.quiz['questions'])}")
96
-
97
- try_again_button = st.form_submit_button("Try Again")
98
- if try_again_button:
99
- for key in ["quiz", "current_question_index", "responses", "interactions", "quiz_completed", "topic"]:
100
- st.session_state[key] = None if key == "quiz" else 0 if key == "current_question_index" else []
101
- st.cache_data.clear()
102
- st.rerun()
103
- else:
104
- current_question_index = st.session_state.current_question_index
105
- if current_question_index < len(st.session_state.quiz["questions"]):
106
- question = st.session_state.quiz["questions"][current_question_index]
107
- question_text = question.get('question', question.get('statement', question.get('prompt', '')))
108
- options = question.get("options", [])
109
- st.markdown(f"**Question {current_question_index + 1}:** {question_text}")
110
- if options:
111
- st.markdown("Choices:")
112
- for option in options:
113
- st.markdown(option)
114
-
115
- user_response = st.text_input("Your answer:", key=f"input_{current_question_index}")
116
-
117
- submit_button = st.form_submit_button("Submit Answer")
118
- if submit_button:
119
- st.session_state[f"answer_{current_question_index}"] = user_response
120
-
121
- correct_answer = question.get("right_option", question.get("answer"))
122
- if options and options[0].lower() in ['true', 'false']:
123
- invalid_option = user_response.lower() not in ["true", "false"]
124
- else:
125
- valid_options = [opt[0].lower() for opt in options]
126
- invalid_option = user_response.lower() not in valid_options and question.get("statement") is None
127
-
128
- is_correct = user_response.lower() == correct_answer.lower()
129
-
130
- st.session_state.responses.append(user_response)
131
- st.session_state.interactions.append({
132
- "question": question_text,
133
- "user_response": user_response,
134
- "correct_answer": correct_answer,
135
- "is_correct": is_correct,
136
- "invalid_option": invalid_option,
137
- "options": options
138
- })
139
-
140
- if not invalid_option:
141
- st.session_state.current_question_index += 1
142
-
143
- if st.session_state.current_question_index >= len(st.session_state.quiz["questions"]):
144
- st.session_state.quiz_completed = True
145
-
146
- st.rerun()
147
- else:
148
- warn()
149
-
150
- with placeholder.container():
151
- if st.session_state.interactions:
152
- i = 0
153
- for idx, interaction in enumerate(st.session_state.interactions):
154
- if interaction['invalid_option']:
155
- continue
156
-
157
- options_html = "<br>".join(interaction['options'])
158
- question_html = f"Question {i + 1}: {interaction['question']}<br>Choices:<br>{options_html}"
159
-
160
- div = f"""
161
- <div class="chat-row">
162
- <img class="chat-icon" src="app/static/ai_icon.png" width=32 height=32>
163
- <div class="chat-bubble ai-bubble">
164
- {question_html}
165
- </div>
166
- </div>
167
- """
168
- st.markdown(div, unsafe_allow_html=True)
169
-
170
- user_response_html = f"Your answer: {interaction['user_response']}"
171
- div = f"""
172
- <div class="chat-row row-reverse">
173
- <img class="chat-icon" src="app/static/user_icon.png" width=32 height=32>
174
- <div class="chat-bubble human-bubble">
175
- {user_response_html}
176
- </div>
177
- </div>
178
- """
179
- if idx == len(st.session_state.interactions) - 1:
180
- div = f'<div id="last-message">{div}</div>'
181
-
182
- st.markdown(div, unsafe_allow_html=True)
183
-
184
- feedback_html = f"Correct! The correct answer is: {interaction['correct_answer']}" if interaction['is_correct'] else f"Wrong. The correct answer is: {interaction['correct_answer']}"
185
- div = f"""
186
- <div class="chat-row">
187
- <img class="chat-icon" src="app/static/ai_icon.png" width=32 height=32>
188
- <div class="chat-bubble ai-bubble">
189
- {feedback_html}
190
- </div>
191
- </div>
192
- """
193
- st.markdown(div, unsafe_allow_html=True)
194
- i += 1
195
-
196
- save_chat_history(st.session_state.messages)
197
-
198
- components.html("""
199
- <script>
200
- const streamlitDoc = window.parent.document;
201
-
202
- function scrollToBottom() {
203
- const lastMessage = streamlitDoc.getElementById('last-message');
204
- if (lastMessage) {
205
- lastMessage.scrollIntoView({ behavior: 'smooth' });
206
- }
207
- }
208
-
209
- function focusInput() {
210
- const answerInput = streamlitDoc.getElementById('answer_input');
211
- if (answerInput) {
212
- answerInput.focus();
213
- }
214
- }
215
-
216
- scrollToBottom();
217
- focusInput();
218
-
219
- const buttons = Array.from(
220
- streamlitDoc.querySelectorAll('.stButton > button')
221
- );
222
- const submitButton = buttons.find(
223
- el => el.innerText === 'Submit Answer'
224
- );
225
-
226
- streamlitDoc.addEventListener('keydown', function(e) {
227
- if (e.key === 'Enter') {
228
- submitButton.click();
229
- setTimeout(() => {
230
- scrollToBottom();
231
- focusInput();
232
- }, 500);
233
- }
234
- });
235
- </script>
236
- """, height=0, width=0)
 
1
+ import streamlit as st
2
+ import requests
3
+ from pipelines import generate_quiz
4
+ from dotenv import load_dotenv
5
+ import shelve
6
+ from dataclasses import dataclass
7
+ from typing import Literal
8
+ import streamlit.components.v1 as components
9
+
10
+ load_dotenv()
11
+
12
+ st.title(":red[DEV] *the Quizbot* 🤖")
13
+ st.subheader("Hey there! I'm **Dev** the QuizBot! Ready to flaunt your smarts in a topic of your choice?", divider='grey')
14
+
15
+ @st.experimental_dialog("Invalid Choice", width="small")
16
+ def warn():
17
+ st.write("Please choose from the given options.")
18
+
19
+ @dataclass
20
+ class Message:
21
+ origin: Literal["human", "ai"]
22
+ message: str
23
+
24
+ def load_css():
25
+ with open("static/styles.css", "r") as f:
26
+ st.markdown(f"<style>{f.read()}</style>", unsafe_allow_html=True)
27
+
28
+ def initialize_session_state():
29
+ defaults = {
30
+ "quiz": None,
31
+ "current_question_index": 0,
32
+ "responses": [],
33
+ "interactions": [],
34
+ "quiz_completed": False,
35
+ "topic": None,
36
+ "messages": load_chat_history()
37
+ }
38
+ for key, value in defaults.items():
39
+ if key not in st.session_state:
40
+ st.session_state[key] = value
41
+
42
+ def load_chat_history():
43
+ with shelve.open("chat_history") as db:
44
+ return db.get("messages", [])
45
+
46
+ def save_chat_history(messages):
47
+ with shelve.open("chat_history") as db:
48
+ db["messages"] = messages
49
+
50
+ def fetch_wikipedia_link(topic):
51
+ api_url = f"https://en.wikipedia.org/api/rest_v1/page/summary/{topic}"
52
+ response = requests.get(api_url)
53
+ if response.status_code == 200:
54
+ return response.json()['content_urls']['desktop']['page']
55
+ st.error("Failed to fetch Wikipedia content.")
56
+ return None
57
+
58
+ load_css()
59
+ initialize_session_state()
60
+
61
+ placeholder = st.container()
62
+
63
+ if st.session_state.quiz is None:
64
+ st.session_state.interactions = []
65
+ with st.form("generate_quiz_form"):
66
+ st.markdown('**Enter a Topic:**')
67
+ cols = st.columns((4, 1))
68
+ topic = cols[0].text_input("Topic:", label_visibility="collapsed")
69
+ generate_button = cols[1].form_submit_button("Generate Quiz")
70
+
71
+ if generate_button:
72
+ if topic:
73
+ link = fetch_wikipedia_link(topic)
74
+ if link:
75
+ for _ in range(2):
76
+ try:
77
+ quiz = generate_quiz(link)
78
+ if quiz:
79
+ st.session_state.quiz = quiz
80
+ st.session_state.current_question_index = 0
81
+ st.session_state.responses = []
82
+ st.session_state.quiz_completed = False
83
+ st.rerun()
84
+ except Exception as e:
85
+ st.error(f"Failed to generate quiz: {e}")
86
+ else:
87
+ st.error("Please enter a topic.")
88
+ else:
89
+ with st.form("quiz_form"):
90
+ if st.session_state.quiz_completed:
91
+ st.markdown("## Results")
92
+ score = sum(1 for interaction in st.session_state.interactions if interaction["is_correct"])
93
+ if score > len(st.session_state.quiz['questions']):
94
+ score = len(st.session_state.quiz['questions'])
95
+ st.markdown(f"Your score: {score} out of {len(st.session_state.quiz['questions'])}")
96
+
97
+ try_again_button = st.form_submit_button("Try Again")
98
+ if try_again_button:
99
+ for key in ["quiz", "current_question_index", "responses", "interactions", "quiz_completed", "topic"]:
100
+ st.session_state[key] = None if key == "quiz" else 0 if key == "current_question_index" else []
101
+ st.cache_data.clear()
102
+ st.rerun()
103
+ else:
104
+ current_question_index = st.session_state.current_question_index
105
+ if current_question_index < len(st.session_state.quiz["questions"]):
106
+ question = st.session_state.quiz["questions"][current_question_index]
107
+ question_text = question.get('question', question.get('statement', question.get('prompt', '')))
108
+ options = question.get("options", [])
109
+ st.markdown(f"**Question {current_question_index + 1}:** {question_text}")
110
+ if options:
111
+ st.markdown("Choices:")
112
+ for option in options:
113
+ st.markdown(option)
114
+
115
+ user_response = st.text_input("Your answer:", key=f"input_{current_question_index}")
116
+
117
+ submit_button = st.form_submit_button("Submit Answer")
118
+ if submit_button:
119
+ st.session_state[f"answer_{current_question_index}"] = user_response
120
+
121
+ correct_answer = question.get("right_option", question.get("answer"))
122
+ if options and options[0].lower() in ['true', 'false']:
123
+ invalid_option = user_response.lower() not in ["true", "false"]
124
+ else:
125
+ valid_options = [opt[0].lower() for opt in options]
126
+ invalid_option = user_response.lower() not in valid_options and question.get("statement") is None
127
+
128
+ is_correct = user_response.lower() == correct_answer.lower()
129
+
130
+ st.session_state.responses.append(user_response)
131
+ st.session_state.interactions.append({
132
+ "question": question_text,
133
+ "user_response": user_response,
134
+ "correct_answer": correct_answer,
135
+ "is_correct": is_correct,
136
+ "invalid_option": invalid_option,
137
+ "options": options
138
+ })
139
+
140
+ if not invalid_option:
141
+ st.session_state.current_question_index += 1
142
+
143
+ if st.session_state.current_question_index >= len(st.session_state.quiz["questions"]):
144
+ st.session_state.quiz_completed = True
145
+
146
+ st.rerun()
147
+ else:
148
+ warn()
149
+
150
+ with placeholder.container():
151
+ if st.session_state.interactions:
152
+ i = 0
153
+ for idx, interaction in enumerate(st.session_state.interactions):
154
+ if interaction['invalid_option']:
155
+ continue
156
+
157
+ options_html = "<br>".join(interaction['options'])
158
+ question_html = f"Question {i + 1}: {interaction['question']}<br>Choices:<br>{options_html}"
159
+
160
+ div = f"""
161
+ <div class="chat-row">
162
+ <img class="chat-icon" src="static/ai_icon.png" width=32 height=32>
163
+ <div class="chat-bubble ai-bubble">
164
+ {question_html}
165
+ </div>
166
+ </div>
167
+ """
168
+ st.markdown(div, unsafe_allow_html=True)
169
+
170
+ user_response_html = f"Your answer: {interaction['user_response']}"
171
+ div = f"""
172
+ <div class="chat-row row-reverse">
173
+ <img class="chat-icon" src="static/user_icon.png" width=32 height=32>
174
+ <div class="chat-bubble human-bubble">
175
+ {user_response_html}
176
+ </div>
177
+ </div>
178
+ """
179
+ if idx == len(st.session_state.interactions) - 1:
180
+ div = f'<div id="last-message">{div}</div>'
181
+
182
+ st.markdown(div, unsafe_allow_html=True)
183
+
184
+ feedback_html = f"Correct! The correct answer is: {interaction['correct_answer']}" if interaction['is_correct'] else f"Wrong. The correct answer is: {interaction['correct_answer']}"
185
+ div = f"""
186
+ <div class="chat-row">
187
+ <img class="chat-icon" src="static/ai_icon.png" width=32 height=32>
188
+ <div class="chat-bubble ai-bubble">
189
+ {feedback_html}
190
+ </div>
191
+ </div>
192
+ """
193
+ st.markdown(div, unsafe_allow_html=True)
194
+ i += 1
195
+
196
+ save_chat_history(st.session_state.messages)
197
+
198
+ components.html("""
199
+ <script>
200
+ const streamlitDoc = window.parent.document;
201
+
202
+ function scrollToBottom() {
203
+ const lastMessage = streamlitDoc.getElementById('last-message');
204
+ if (lastMessage) {
205
+ lastMessage.scrollIntoView({ behavior: 'smooth' });
206
+ }
207
+ }
208
+
209
+ function focusInput() {
210
+ const answerInput = streamlitDoc.getElementById('answer_input');
211
+ if (answerInput) {
212
+ answerInput.focus();
213
+ }
214
+ }
215
+
216
+ scrollToBottom();
217
+ focusInput();
218
+
219
+ const buttons = Array.from(
220
+ streamlitDoc.querySelectorAll('.stButton > button')
221
+ );
222
+ const submitButton = buttons.find(
223
+ el => el.innerText === 'Submit Answer'
224
+ );
225
+
226
+ streamlitDoc.addEventListener('keydown', function(e) {
227
+ if (e.key === 'Enter') {
228
+ submitButton.click();
229
+ setTimeout(() => {
230
+ scrollToBottom();
231
+ focusInput();
232
+ }, 500);
233
+ }
234
+ });
235
+ </script>
236
+ """, height=0, width=0)