Spaces:
Sleeping
Sleeping
Update app(backup2).py
Browse files- app(backup2).py +157 -25
app(backup2).py
CHANGED
@@ -6,22 +6,48 @@ import gspread
|
|
6 |
from oauth2client.service_account import ServiceAccountCredentials
|
7 |
import PyPDF2
|
8 |
import io
|
|
|
|
|
9 |
|
10 |
-
#
|
11 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
12 |
|
13 |
# Constants
|
14 |
-
WORD_LIMIT =
|
|
|
15 |
|
16 |
-
#
|
|
|
|
|
|
|
17 |
scope = ["https://spreadsheets.google.com/feeds", "https://www.googleapis.com/auth/drive"]
|
18 |
creds = ServiceAccountCredentials.from_json_keyfile_name("genexam-2c8c645ecc0d.json", scope)
|
19 |
client_gs = gspread.authorize(creds)
|
20 |
sheet = client_gs.open("GeneXam user").sheet1
|
21 |
|
22 |
def check_user_in_sheet(username):
|
|
|
23 |
try:
|
24 |
-
users_list = sheet.col_values(1)
|
25 |
if username in users_list:
|
26 |
return True
|
27 |
return False
|
@@ -29,15 +55,59 @@ def check_user_in_sheet(username):
|
|
29 |
st.error(f"Error checking user: {str(e)}")
|
30 |
return False
|
31 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
32 |
def update_api_usage(username):
|
|
|
33 |
try:
|
34 |
users_list = sheet.col_values(1)
|
35 |
row_number = users_list.index(username) + 1
|
36 |
-
|
37 |
-
|
38 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
39 |
except Exception as e:
|
40 |
-
|
41 |
|
42 |
def extract_text_from_pdf(pdf_file):
|
43 |
"""Simple PDF text extraction with word limit check"""
|
@@ -54,7 +124,15 @@ def extract_text_from_pdf(pdf_file):
|
|
54 |
except Exception as e:
|
55 |
return None, f"Error processing PDF: {str(e)}"
|
56 |
|
57 |
-
def generate_questions_with_retry(knowledge_material, question_type, cognitive_level, extra_instructions, case_based, num_choices=None, max_retries=3):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
58 |
# Adjust number of questions based on type
|
59 |
if question_type == "Multiple Choice":
|
60 |
num_questions = 3
|
@@ -65,7 +143,6 @@ def generate_questions_with_retry(knowledge_material, question_type, cognitive_l
|
|
65 |
3. After all questions, provide an ANSWER KEY section with:
|
66 |
- The correct answer letter for each question
|
67 |
- A brief explanation of why this is the correct answer
|
68 |
-
- Why other options are incorrect
|
69 |
"""
|
70 |
elif question_type == "Fill in the Blank":
|
71 |
num_questions = 10
|
@@ -162,23 +239,68 @@ Please format the output with:
|
|
162 |
return None
|
163 |
time.sleep(2)
|
164 |
|
165 |
-
# ระบบ login
|
166 |
# Main Streamlit interface
|
|
|
|
|
|
|
167 |
if 'username' not in st.session_state:
|
168 |
-
st.
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
176 |
else:
|
177 |
-
st.warning("
|
178 |
-
|
179 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
180 |
else:
|
181 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
182 |
|
183 |
# Create tabs for input methods
|
184 |
tab1, tab2 = st.tabs(["Text Input", "PDF Upload"])
|
@@ -226,8 +348,8 @@ else:
|
|
226 |
if st.button("Generate Questions"):
|
227 |
if 'knowledge_material' in locals() and knowledge_material.strip():
|
228 |
with st.spinner("Generating questions..."):
|
229 |
-
# Your existing generate_questions_with_retry function call here
|
230 |
questions = generate_questions_with_retry(
|
|
|
231 |
knowledge_material,
|
232 |
question_type,
|
233 |
cognitive_level,
|
@@ -240,6 +362,16 @@ else:
|
|
240 |
st.write("### Generated Exam Questions:")
|
241 |
st.write(questions)
|
242 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
243 |
# Download button
|
244 |
st.download_button(
|
245 |
label="Download Questions",
|
|
|
6 |
from oauth2client.service_account import ServiceAccountCredentials
|
7 |
import PyPDF2
|
8 |
import io
|
9 |
+
from datetime import datetime
|
10 |
+
from PIL import Image
|
11 |
|
12 |
+
# Add some custom CSS to improve the layout
|
13 |
+
st.markdown("""
|
14 |
+
<style>
|
15 |
+
.stImage {
|
16 |
+
text-align: center;
|
17 |
+
display: block;
|
18 |
+
margin-left: auto;
|
19 |
+
margin-right: auto;
|
20 |
+
}
|
21 |
+
|
22 |
+
.stTitle {
|
23 |
+
text-align: center;
|
24 |
+
padding-bottom: 20px;
|
25 |
+
}
|
26 |
+
|
27 |
+
div[data-testid="stVerticalBlock"] > div:has(div.stButton) {
|
28 |
+
text-align: center;
|
29 |
+
padding: 10px 0;
|
30 |
+
}
|
31 |
+
</style>
|
32 |
+
""", unsafe_allow_html=True)
|
33 |
|
34 |
# Constants
|
35 |
+
WORD_LIMIT = 11000
|
36 |
+
DAILY_API_LIMIT = 30 # Set your desired limit per user per day
|
37 |
|
38 |
+
# Set up OpenAI client
|
39 |
+
client = OpenAI(api_key=st.secrets["OPENAI_API_KEY"])
|
40 |
+
|
41 |
+
# Google Sheets setup
|
42 |
scope = ["https://spreadsheets.google.com/feeds", "https://www.googleapis.com/auth/drive"]
|
43 |
creds = ServiceAccountCredentials.from_json_keyfile_name("genexam-2c8c645ecc0d.json", scope)
|
44 |
client_gs = gspread.authorize(creds)
|
45 |
sheet = client_gs.open("GeneXam user").sheet1
|
46 |
|
47 |
def check_user_in_sheet(username):
|
48 |
+
"""Check if user exists in sheet"""
|
49 |
try:
|
50 |
+
users_list = sheet.col_values(1) # UserID column
|
51 |
if username in users_list:
|
52 |
return True
|
53 |
return False
|
|
|
55 |
st.error(f"Error checking user: {str(e)}")
|
56 |
return False
|
57 |
|
58 |
+
def get_user_stats(username):
|
59 |
+
"""Get user's current API usage statistics"""
|
60 |
+
try:
|
61 |
+
users_list = sheet.col_values(1) # UserID column
|
62 |
+
row_number = users_list.index(username) + 1
|
63 |
+
|
64 |
+
daily_count = int(sheet.cell(row_number, 2).value) # DailyAPICount
|
65 |
+
total_count = int(sheet.cell(row_number, 3).value) # TotalAPICount
|
66 |
+
last_used = sheet.cell(row_number, 4).value # LastUsedDate
|
67 |
+
|
68 |
+
return {
|
69 |
+
'daily_count': daily_count,
|
70 |
+
'total_count': total_count,
|
71 |
+
'last_used': last_used
|
72 |
+
}
|
73 |
+
except Exception as e:
|
74 |
+
st.error(f"Error getting user stats: {str(e)}")
|
75 |
+
return None
|
76 |
+
|
77 |
def update_api_usage(username):
|
78 |
+
"""Update both daily and total API usage counts"""
|
79 |
try:
|
80 |
users_list = sheet.col_values(1)
|
81 |
row_number = users_list.index(username) + 1
|
82 |
+
today = datetime.now().strftime('%Y-%m-%d')
|
83 |
+
|
84 |
+
# Get current values
|
85 |
+
stats = get_user_stats(username)
|
86 |
+
if not stats:
|
87 |
+
return False, "Error retrieving user statistics"
|
88 |
+
|
89 |
+
# Reset daily count if it's a new day
|
90 |
+
daily_count = stats['daily_count']
|
91 |
+
if stats['last_used'] != today:
|
92 |
+
daily_count = 0
|
93 |
+
|
94 |
+
# Check daily limit
|
95 |
+
if daily_count >= DAILY_API_LIMIT:
|
96 |
+
return False, f"You have reached your daily limit of {DAILY_API_LIMIT} generations. Please try again tomorrow."
|
97 |
+
|
98 |
+
# Update counts
|
99 |
+
new_daily_count = daily_count + 1
|
100 |
+
new_total_count = stats['total_count'] + 1
|
101 |
+
|
102 |
+
# Update all values in sheet
|
103 |
+
sheet.update_cell(row_number, 2, new_daily_count) # Update DailyAPICount
|
104 |
+
sheet.update_cell(row_number, 3, new_total_count) # Update TotalAPICount
|
105 |
+
sheet.update_cell(row_number, 4, today) # Update LastUsedDate
|
106 |
+
|
107 |
+
return True, None
|
108 |
+
|
109 |
except Exception as e:
|
110 |
+
return False, f"Error updating API usage: {str(e)}"
|
111 |
|
112 |
def extract_text_from_pdf(pdf_file):
|
113 |
"""Simple PDF text extraction with word limit check"""
|
|
|
124 |
except Exception as e:
|
125 |
return None, f"Error processing PDF: {str(e)}"
|
126 |
|
127 |
+
def generate_questions_with_retry(username, knowledge_material, question_type, cognitive_level, extra_instructions, case_based, num_choices=None, max_retries=3):
|
128 |
+
"""Generate questions and update API usage"""
|
129 |
+
|
130 |
+
# Check and update API usage before generating
|
131 |
+
can_generate, error_message = update_api_usage(username)
|
132 |
+
if not can_generate:
|
133 |
+
st.error(error_message)
|
134 |
+
return None
|
135 |
+
|
136 |
# Adjust number of questions based on type
|
137 |
if question_type == "Multiple Choice":
|
138 |
num_questions = 3
|
|
|
143 |
3. After all questions, provide an ANSWER KEY section with:
|
144 |
- The correct answer letter for each question
|
145 |
- A brief explanation of why this is the correct answer
|
|
|
146 |
"""
|
147 |
elif question_type == "Fill in the Blank":
|
148 |
num_questions = 10
|
|
|
239 |
return None
|
240 |
time.sleep(2)
|
241 |
|
|
|
242 |
# Main Streamlit interface
|
243 |
+
# Initialize session state variables
|
244 |
+
if 'login_step' not in st.session_state:
|
245 |
+
st.session_state.login_step = 'username'
|
246 |
if 'username' not in st.session_state:
|
247 |
+
st.session_state.username = None
|
248 |
+
|
249 |
+
# Login system
|
250 |
+
if st.session_state.username is None:
|
251 |
+
# Center align the content
|
252 |
+
col1, col2, col3 = st.columns([1,2,1])
|
253 |
+
|
254 |
+
with col2:
|
255 |
+
# Display logo
|
256 |
+
st.image("GenExam.png", width=200) # Assuming the image is saved as logo.png
|
257 |
+
|
258 |
+
st.title("Login")
|
259 |
+
username_input = st.text_input("Enter your username:")
|
260 |
+
|
261 |
+
if st.session_state.login_step == 'username' and st.button("Login", use_container_width=True):
|
262 |
+
if username_input:
|
263 |
+
if check_user_in_sheet(username_input):
|
264 |
+
stats = get_user_stats(username_input)
|
265 |
+
if stats:
|
266 |
+
st.success(f"Welcome, {username_input}! 👋")
|
267 |
+
st.info(f"""
|
268 |
+
📊 Your API Usage Statistics:
|
269 |
+
- Today's Usage: {stats['daily_count']}/{DAILY_API_LIMIT} generations
|
270 |
+
- Total All-Time Usage: {stats['total_count']} generations
|
271 |
+
""")
|
272 |
+
st.session_state.login_step = 'enter_app'
|
273 |
+
else:
|
274 |
+
st.warning("Username not found. Please try again.")
|
275 |
else:
|
276 |
+
st.warning("Please enter a valid username.")
|
277 |
+
|
278 |
+
if st.session_state.login_step == 'enter_app':
|
279 |
+
if st.button("🎯 Enter GeneXam Application", use_container_width=True):
|
280 |
+
st.session_state.username = username_input
|
281 |
+
st.rerun()
|
282 |
+
|
283 |
+
# Show instructions
|
284 |
+
if st.session_state.login_step == 'username':
|
285 |
+
st.markdown("""
|
286 |
+
### How to Login:
|
287 |
+
1. Enter your username and click 'Login' to verify your account
|
288 |
+
2. After verification, click 'Enter GeneXam Application' to start using the system
|
289 |
+
""")
|
290 |
+
|
291 |
else:
|
292 |
+
# Main application code (ส่วนที่เหลือเหมือนเดิม)
|
293 |
+
st.title(f"Welcome to GeneXam, {st.session_state.username}! 🎓")
|
294 |
+
|
295 |
+
# Show current usage stats
|
296 |
+
stats = get_user_stats(st.session_state.username)
|
297 |
+
if stats:
|
298 |
+
remaining = DAILY_API_LIMIT - stats['daily_count']
|
299 |
+
st.info(f"""
|
300 |
+
📊 Usage Statistics:
|
301 |
+
- Daily Generations Remaining: {remaining}/{DAILY_API_LIMIT}
|
302 |
+
- Total All-Time Generations: {stats['total_count']}
|
303 |
+
""")
|
304 |
|
305 |
# Create tabs for input methods
|
306 |
tab1, tab2 = st.tabs(["Text Input", "PDF Upload"])
|
|
|
348 |
if st.button("Generate Questions"):
|
349 |
if 'knowledge_material' in locals() and knowledge_material.strip():
|
350 |
with st.spinner("Generating questions..."):
|
|
|
351 |
questions = generate_questions_with_retry(
|
352 |
+
st.session_state['username'],
|
353 |
knowledge_material,
|
354 |
question_type,
|
355 |
cognitive_level,
|
|
|
362 |
st.write("### Generated Exam Questions:")
|
363 |
st.write(questions)
|
364 |
|
365 |
+
# Update displayed stats after generation
|
366 |
+
new_stats = get_user_stats(st.session_state['username'])
|
367 |
+
if new_stats:
|
368 |
+
remaining = DAILY_API_LIMIT - new_stats['daily_count']
|
369 |
+
st.info(f"""
|
370 |
+
📊 Updated Usage Statistics:
|
371 |
+
- Daily Generations Remaining: {remaining}/{DAILY_API_LIMIT}
|
372 |
+
- Total All-Time Generations: {new_stats['total_count']}
|
373 |
+
""")
|
374 |
+
|
375 |
# Download button
|
376 |
st.download_button(
|
377 |
label="Download Questions",
|