Spaces:
Sleeping
Sleeping
Create app(backup).py
Browse files- app(backup).py +173 -0
app(backup).py
ADDED
@@ -0,0 +1,173 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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"]
|
7 |
+
|
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
|
14 |
+
if question_type == "Multiple Choice":
|
15 |
+
num_questions = 3
|
16 |
+
elif question_type == "Fill in the Blank":
|
17 |
+
num_questions = 10
|
18 |
+
elif question_type == "True/False":
|
19 |
+
num_questions = 5 # Generate 5 true/false questions
|
20 |
+
else: # Open-ended
|
21 |
+
num_questions = 3
|
22 |
+
|
23 |
+
# Base prompt
|
24 |
+
prompt = f"Generate {num_questions} {question_type.lower()} exam questions based on {cognitive_level.lower()} level from the following material: {knowledge_material}. {extra_instructions}"
|
25 |
+
|
26 |
+
# If case-based medical situation is selected, modify the prompt
|
27 |
+
if case_based:
|
28 |
+
prompt = f"Generate {num_questions} {question_type.lower()} exam questions based on {cognitive_level.lower()} level from the following medical material: {knowledge_material}. The questions should be based on case-based medical situations, such as patient scenarios. {extra_instructions}"
|
29 |
+
if question_type != "Fill in the Blank":
|
30 |
+
prompt += " Provide answers with short explanations."
|
31 |
+
|
32 |
+
# Add specific handling for Multiple Choice and True/False
|
33 |
+
if question_type == "Multiple Choice" and num_choices:
|
34 |
+
prompt += f" Each multiple choice question should have {num_choices} choices."
|
35 |
+
|
36 |
+
if question_type == "True/False":
|
37 |
+
prompt += " Provide short explanations for each question based on the given material, without stating True or False explicitly."
|
38 |
+
|
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")
|
61 |
+
username_input = st.text_input("Enter your username:")
|
62 |
+
if st.button("Login"):
|
63 |
+
if username_input:
|
64 |
+
st.session_state['username'] = username_input
|
65 |
+
st.success(f"Welcome, {username_input}!")
|
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.")
|