Rathapoom commited on
Commit
9a241fb
·
verified ·
1 Parent(s): ef91894

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +166 -102
app.py CHANGED
@@ -1,6 +1,9 @@
 
 
1
  import streamlit as st
2
  import openai
3
  import time
 
4
 
5
  # Set your OpenAI API key from Hugging Face Secrets
6
  openai.api_key = st.secrets["OPENAI_API_KEY"]
@@ -8,6 +11,33 @@ openai.api_key = st.secrets["OPENAI_API_KEY"]
8
  # Initialize OpenAI client
9
  client = openai.OpenAI(api_key=openai.api_key)
10
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
  # Function to generate exam questions using OpenAI API with retry logic
12
  def generate_questions_with_retry(knowledge_material, question_type, cognitive_level, extra_instructions, case_based, num_choices=None, max_retries=3):
13
  # Adjust the number of questions based on the type
@@ -40,7 +70,7 @@ def generate_questions_with_retry(knowledge_material, question_type, cognitive_l
40
  while retries < max_retries:
41
  try:
42
  response = client.chat.completions.create(
43
- model="gpt-4o-mini",
44
  messages=[
45
  {"role": "system", "content": "You are a helpful assistant for generating exam questions."},
46
  {"role": "user", "content": prompt}
@@ -54,7 +84,7 @@ def generate_questions_with_retry(knowledge_material, question_type, cognitive_l
54
  st.error("Failed to connect to OpenAI API after several attempts.")
55
  return None
56
 
57
- # Login page
58
  if 'username' not in st.session_state:
59
  # Show the login form if the username is not set
60
  st.title("Login")
@@ -66,108 +96,142 @@ if 'username' not in st.session_state:
66
  else:
67
  st.warning("Please enter a valid username.")
68
  else:
69
- # Main App after login
70
- st.title(f"Welcome, {st.session_state['username']}! Generate your exam questions")
71
-
72
- # Input field for knowledge material (text) with 3,000-word limit
73
- knowledge_material = st.text_area("Enter knowledge material to generate exam questions:")
74
-
75
- # Word count check
76
- if len(knowledge_material.split()) > 3000:
77
- st.warning("Please limit the knowledge material to 3,000 words or fewer.")
78
-
79
- # File uploader for PDFs (limited to 5 MB)
80
- uploaded_file = st.file_uploader("Upload a file (PDF)", type="pdf")
81
 
82
- if uploaded_file is not None:
83
- if uploaded_file.size > 5 * 1024 * 1024: # 5 MB limit
84
- st.warning("File size exceeds 5 MB. Please upload a smaller file.")
 
 
 
 
 
 
 
 
 
 
 
85
  else:
86
- # Here you can add code to extract text from the PDF if needed
87
- # For simplicity, we're focusing on the text input for now
88
- st.success("File uploaded successfully! (Text extraction not implemented yet.)")
89
-
90
- # Select question type
91
- question_type = st.selectbox("Select question type:",
92
- ["Multiple Choice", "Fill in the Blank", "Open-ended", "True/False"])
93
 
94
- # For multiple choice, let users select the number of choices
95
- num_choices = None
96
- if question_type == "Multiple Choice":
97
- num_choices = st.selectbox("Select the number of choices for each question:", [3, 4, 5])
98
-
99
- # Select cognitive level
100
- cognitive_level = st.selectbox("Select cognitive level:",
101
- ["Recall", "Understanding", "Application", "Analysis", "Synthesis", "Evaluation"])
102
-
103
- # Checkbox for Case-Based Medical Situations
104
- case_based = st.checkbox("Generate case-based medical exam questions")
105
-
106
- # Extra input field for additional instructions (placed below cognitive level)
107
- extra_instructions = st.text_area("Enter additional instructions (e.g., how you want the questions to be phrased):")
108
-
109
- # Generate questions button
110
- if 'previous_questions' not in st.session_state:
111
- st.session_state['previous_questions'] = []
112
-
113
- if st.button("Generate Questions"):
114
- if len(knowledge_material.split()) <= 3000:
115
- # Generate questions with retry logic
116
- questions = generate_questions_with_retry(
117
- knowledge_material,
118
- question_type,
119
- cognitive_level,
120
- extra_instructions,
121
- case_based,
122
- num_choices
123
- )
124
 
125
- if questions:
126
- st.write("Generated Exam Questions:")
127
- st.write(questions)
128
-
129
- # Avoid showing repeated content in future requests
130
- st.session_state['previous_questions'].append(questions)
131
-
132
- # Option to download the questions as a text file
133
- st.download_button(
134
- label="Download Questions",
135
- data=questions,
136
- file_name='generated_questions.txt',
137
- mime='text/plain'
138
- )
139
- else:
140
- st.warning("Please reduce the word count to 3,000 or fewer.")
141
-
142
- # Button to generate more questions based on the same material
143
- if st.button("Generate More Questions"):
144
- if len(knowledge_material.split()) <= 3000:
145
- # Regenerate new questions, trying to avoid repeated content
146
- questions = generate_questions_with_retry(
147
- knowledge_material,
148
- question_type,
149
- cognitive_level,
150
- extra_instructions,
151
- case_based,
152
- num_choices
153
- )
154
 
155
- # Check if the new set of questions is not the same as the previous set
156
- if questions and questions not in st.session_state['previous_questions']:
157
- st.write("Generated More Exam Questions:")
158
- st.write(questions)
159
-
160
- # Append the new questions to the session state
161
- st.session_state['previous_questions'].append(questions)
162
-
163
- # Option to download the new set of questions
164
- st.download_button(
165
- label="Download More Questions",
166
- data=questions,
167
- file_name='more_generated_questions.txt',
168
- mime='text/plain'
169
- )
170
- else:
171
- st.warning("New questions seem to overlap with the previous ones. Try adjusting the instructions.")
172
- else:
173
- st.warning("Please reduce the word count to 3,000 or fewer.")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gspread
2
+ from oauth2client.service_account import ServiceAccountCredentials
3
  import streamlit as st
4
  import openai
5
  import time
6
+ from datetime import datetime
7
 
8
  # Set your OpenAI API key from Hugging Face Secrets
9
  openai.api_key = st.secrets["OPENAI_API_KEY"]
 
11
  # Initialize OpenAI client
12
  client = openai.OpenAI(api_key=openai.api_key)
13
 
14
+ # Google Sheets setup
15
+ scope = ["https://spreadsheets.google.com/feeds", "https://www.googleapis.com/auth/drive"]
16
+ creds = ServiceAccountCredentials.from_json_keyfile_name("path/to/credentials.json", scope)
17
+ client_gs = gspread.authorize(creds)
18
+ sheet = client_gs.open("API_Usage").sheet1 # Open the Google Sheet
19
+
20
+ # Function to get user data from Google Sheets
21
+ def get_user_data(user_id):
22
+ users = sheet.get_all_records()
23
+ for user in users:
24
+ if user['UserID'] == user_id:
25
+ return user
26
+ return None
27
+
28
+ # Function to update user data in Google Sheets
29
+ def update_user_data(user_id, daily_api_count, total_api_count, last_used_date):
30
+ cell = sheet.find(user_id)
31
+ if cell:
32
+ sheet.update_cell(cell.row, cell.col + 1, daily_api_count) # Update DailyAPICount
33
+ sheet.update_cell(cell.row, cell.col + 2, total_api_count) # Update TotalAPICount
34
+ sheet.update_cell(cell.row, cell.col + 3, last_used_date) # Update LastUsedDate
35
+ else:
36
+ sheet.append_row([user_id, daily_api_count, total_api_count, last_used_date]) # Add new user if not found
37
+
38
+ # Admin user ID
39
+ admin_user_id = "admin"
40
+
41
  # Function to generate exam questions using OpenAI API with retry logic
42
  def generate_questions_with_retry(knowledge_material, question_type, cognitive_level, extra_instructions, case_based, num_choices=None, max_retries=3):
43
  # Adjust the number of questions based on the type
 
70
  while retries < max_retries:
71
  try:
72
  response = client.chat.completions.create(
73
+ model="GPT-4o mini",
74
  messages=[
75
  {"role": "system", "content": "You are a helpful assistant for generating exam questions."},
76
  {"role": "user", "content": prompt}
 
84
  st.error("Failed to connect to OpenAI API after several attempts.")
85
  return None
86
 
87
+ # Main logic for the app
88
  if 'username' not in st.session_state:
89
  # Show the login form if the username is not set
90
  st.title("Login")
 
96
  else:
97
  st.warning("Please enter a valid username.")
98
  else:
99
+ user_id = st.session_state['username']
100
+ user_data = get_user_data(user_id)
 
 
 
 
 
 
 
 
 
 
101
 
102
+ if not user_data:
103
+ st.error("Invalid User ID. Please contact the admin for access.")
104
+ else:
105
+ # Get today's date
106
+ today = datetime.now().strftime("%Y-%m-%d")
107
+
108
+ # Reset daily API count if it's a new day
109
+ if user_data['LastUsedDate'] != today:
110
+ update_user_data(user_id, 0, user_data['TotalAPICount'], today)
111
+ user_data['DailyAPICount'] = 0
112
+
113
+ # Check if the user has reached their daily limit (except for admin)
114
+ if user_id != admin_user_id and user_data['DailyAPICount'] >= 5:
115
+ st.warning("You have reached your daily limit of 5 API calls.")
116
  else:
117
+ # Main app for generating questions
118
+ st.title(f"Welcome, {user_id}! Generate your exam questions")
 
 
 
 
 
119
 
120
+ # Input field for knowledge material (text) with 3,000-word limit
121
+ knowledge_material = st.text_area("Enter knowledge material to generate exam questions:")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
122
 
123
+ # Word count check
124
+ if len(knowledge_material.split()) > 3000:
125
+ st.warning("Please limit the knowledge material to 3,000 words or fewer.")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
126
 
127
+ # File uploader for PDFs (limited to 5 MB)
128
+ uploaded_file = st.file_uploader("Upload a file (PDF)", type="pdf")
129
+
130
+ if uploaded_file is not None:
131
+ if uploaded_file.size > 5 * 1024 * 1024: # 5 MB limit
132
+ st.warning("File size exceeds 5 MB. Please upload a smaller file.")
133
+ else:
134
+ st.success("File uploaded successfully! (Text extraction not implemented yet.)")
135
+
136
+ # Select question type
137
+ question_type = st.selectbox("Select question type:",
138
+ ["Multiple Choice", "Fill in the Blank", "Open-ended", "True/False"])
139
+
140
+ # For multiple choice, let users select the number of choices
141
+ num_choices = None
142
+ if question_type == "Multiple Choice":
143
+ num_choices = st.selectbox("Select the number of choices for each question:", [3, 4, 5])
144
+
145
+ # Select cognitive level
146
+ cognitive_level = st.selectbox("Select cognitive level:",
147
+ ["Recall", "Understanding", "Application", "Analysis", "Synthesis", "Evaluation"])
148
+
149
+ # Checkbox for Case-Based Medical Situations
150
+ case_based = st.checkbox("Generate case-based medical exam questions")
151
+
152
+ # Extra input field for additional instructions (placed below cognitive level)
153
+ extra_instructions = st.text_area("Enter additional instructions (e.g., how you want the questions to be phrased):")
154
+
155
+ # Generate questions button
156
+ if 'previous_questions' not in st.session_state:
157
+ st.session_state['previous_questions'] = []
158
+
159
+ if st.button("Generate Questions"):
160
+ if len(knowledge_material.split()) <= 3000:
161
+ # Generate questions with retry logic
162
+ questions = generate_questions_with_retry(
163
+ knowledge_material,
164
+ question_type,
165
+ cognitive_level,
166
+ extra_instructions,
167
+ case_based,
168
+ num_choices
169
+ )
170
+
171
+ if questions:
172
+ st.write("Generated Exam Questions:")
173
+ st.write(questions)
174
+
175
+ # Avoid showing repeated content in future requests
176
+ st.session_state['previous_questions'].append(questions)
177
+
178
+ # Update user API usage
179
+ new_daily_api_count = user_data['DailyAPICount'] + 1
180
+ new_total_api_count = user_data['TotalAPICount'] + 1
181
+ update_user_data(user_id, new_daily_api_count, new_total_api_count, today)
182
+
183
+ st.success(f"API call #{new_daily_api_count} successful today!")
184
+ st.info(f"Total API calls: {new_total_api_count}")
185
+
186
+ # Option to download the questions as a text file
187
+ st.download_button(
188
+ label="Download Questions",
189
+ data=questions,
190
+ file_name='generated_questions.txt',
191
+ mime='text/plain'
192
+ )
193
+ else:
194
+ st.warning("Please reduce the word count to 3,000 or fewer.")
195
+
196
+ # Button to generate more questions based on the same material
197
+ if st.button("Generate More Questions"):
198
+ if len(knowledge_material.split()) <= 3000:
199
+ # Regenerate new questions, trying to avoid repeated content
200
+ questions = generate_questions_with_retry(
201
+ knowledge_material,
202
+ question_type,
203
+ cognitive_level,
204
+ extra_instructions,
205
+ case_based,
206
+ num_choices
207
+ )
208
+
209
+ # Check if the new set of questions is not the same as the previous set
210
+ if questions and questions not in st.session_state['previous_questions']:
211
+ st.write("Generated More Exam Questions:")
212
+ st.write(questions)
213
+
214
+ # Append the new questions to the session state
215
+ st.session_state['previous_questions'].append(questions)
216
+
217
+ # Update user API usage for more questions
218
+ new_daily_api_count = user_data['DailyAPICount'] + 1
219
+ new_total_api_count = user_data['TotalAPICount'] + 1
220
+ update_user_data(user_id, new_daily_api_count, new_total_api_count, today)
221
+
222
+ st.success(f"API call #{new_daily_api_count} successful today!")
223
+ st.info(f"Total API calls: {new_total_api_count}")
224
+
225
+ # Option to download the new set of questions
226
+ st.download_button(
227
+ label="Download More Questions",
228
+ data=questions,
229
+ file_name='more_generated_questions.txt',
230
+ mime='text/plain'
231
+ )
232
+ else:
233
+ st.warning("New questions seem to overlap with the previous ones. Try adjusting the instructions.")
234
+ else:
235
+ st.warning("Please reduce the word count to 3,000 or fewer.")
236
+
237
+