Rathapoom commited on
Commit
2c0669a
1 Parent(s): 495351d

Update app.py

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