Spaces:
Sleeping
Sleeping
File size: 9,985 Bytes
213f539 4c5cb00 6d71955 ad1a715 90853bd 213f539 4c5cb00 2e4c356 4c5cb00 ad1a715 4c5cb00 ad1a715 4c5cb00 ad1a715 4c5cb00 ad1a715 4c5cb00 ad1a715 213f539 ad1a715 4c5cb00 ad1a715 2e4c356 e3da1c7 4c5cb00 6d71955 58d3b83 eaab3cb 58d3b83 6d71955 58d3b83 e3da1c7 4c5cb00 58d3b83 6d71955 58d3b83 6d71955 a9150c4 58d3b83 a9150c4 4c5cb00 a9150c4 58d3b83 a9150c4 58d3b83 e3da1c7 58d3b83 6d71955 4c5cb00 58d3b83 54ba6a8 58d3b83 54ba6a8 58d3b83 6d71955 102fc7c 4c5cb00 6d71955 58d3b83 6d71955 4c5cb00 6d71955 58d3b83 2c0669a ad1a715 2e4c356 a417e3e ad1a715 a417e3e 2c0669a 9f4a1d9 2e4c356 2c0669a 2e4c356 2c0669a 2e4c356 2c0669a 2e4c356 2c0669a 2e4c356 2c0669a 2e4c356 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 |
import streamlit as st
import openai
from openai import OpenAI
import time
import gspread
from oauth2client.service_account import ServiceAccountCredentials
import PyPDF2
import io
# Set up OpenAI client
client = OpenAI(api_key=st.secrets["OPENAI_API_KEY"])
# Constants
WORD_LIMIT = 8000
# Google Sheets setup remains the same
scope = ["https://spreadsheets.google.com/feeds", "https://www.googleapis.com/auth/drive"]
creds = ServiceAccountCredentials.from_json_keyfile_name("genexam-2c8c645ecc0d.json", scope)
client_gs = gspread.authorize(creds)
sheet = client_gs.open("GeneXam user").sheet1
def check_user_in_sheet(username):
try:
users_list = sheet.col_values(1)
if username in users_list:
return True
return False
except Exception as e:
st.error(f"Error checking user: {str(e)}")
return False
def update_api_usage(username):
try:
users_list = sheet.col_values(1)
row_number = users_list.index(username) + 1
api_usage = int(sheet.cell(row_number, 2).value)
api_usage += 1
sheet.update_cell(row_number, 2, api_usage)
except Exception as e:
st.error(f"Error updating API usage: {str(e)}")
def extract_text_from_pdf(pdf_file):
"""Simple PDF text extraction with word limit check"""
try:
pdf_reader = PyPDF2.PdfReader(io.BytesIO(pdf_file.read()))
text_content = ""
for page in pdf_reader.pages:
text_content += page.extract_text() + "\n"
word_count = len(text_content.split())
if word_count > WORD_LIMIT:
return None, f"PDF content exceeds {WORD_LIMIT:,} words (contains {word_count:,} words). Please use a shorter document."
return text_content, None
except Exception as e:
return None, f"Error processing PDF: {str(e)}"
def generate_questions_with_retry(knowledge_material, question_type, cognitive_level, extra_instructions, case_based, num_choices=None, max_retries=3):
# Adjust number of questions based on type
if question_type == "Multiple Choice":
num_questions = 3
format_instructions = f"""
For each multiple choice question:
1. Present the question clearly
2. Provide {num_choices} choices labeled with A, B, C{', D' if num_choices > 3 else ''}{', E' if num_choices > 4 else ''} after get new line from question
3. After all questions, provide an ANSWER KEY section with:
- The correct answer letter for each question
- A brief explanation of why this is the correct answer
- Why other options are incorrect
"""
elif question_type == "Fill in the Blank":
num_questions = 10
format_instructions = """
For each fill-in-the-blank question:
1. Present the question with a clear blank space indicated by _____
2. After all questions, provide an ANSWER KEY section with:
- The correct answer for each blank
- A brief explanation of why this answer is correct
- Any alternative acceptable answers if applicable
"""
elif question_type == "True/False":
num_questions = 5
format_instructions = """
For each true/false question:
1. Present the statement clearly
2. After all questions, provide an ANSWER KEY section with:
- Whether the statement is True or False
- A detailed explanation of why the statement is true or false
- The specific part of the source material that supports this answer
"""
else: # Open-ended
num_questions = 3
format_instructions = """
For each open-ended question:
1. Present the question clearly
2. After all questions, provide an ANSWER KEY section with:
- A structured scoring checklist of key points (minimum 3-5 points per question)
- Each key point should be worth a specific number of marks
- Total marks available for each question
- Sample answer that would receive full marks
- Common points that students might miss
"""
# Base prompt
prompt = f"""Generate {num_questions} {question_type.lower()} exam questions based on {cognitive_level.lower()} level from the following material:
{knowledge_material}
{format_instructions}
{extra_instructions}
Please format the output clearly with:
1. Questions section (numbered 1, 2, 3, etc.)
2. Answer Key section (clearly separated from questions)
3. Each answer should include explanation for better understanding
Make sure all questions and answers are directly related to the provided material."""
# Modify prompt for case-based medical situations
if case_based:
prompt = f"""Generate {num_questions} {question_type.lower()} case-based medical exam questions based on {cognitive_level.lower()} level.
Use this material as the medical knowledge base:
{knowledge_material}
Each question should:
1. Start with a medical case scenario/patient presentation
2. Include relevant clinical details
3. Ask about diagnosis, treatment, or management
4. Be at {cognitive_level.lower()} cognitive level
{format_instructions}
{extra_instructions}
Please format the output with:
1. Cases and Questions (numbered 1, 2, 3, etc.)
2. Detailed Answer Key section including:
- Correct answers
- Clinical reasoning
- Key diagnostic or treatment considerations
- Common pitfalls to avoid"""
retries = 0
while retries < max_retries:
try:
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role": "system", "content": "You are an expert exam question generator with deep knowledge in medical education. Create clear, well-structured questions with detailed answer keys and explanations."},
{"role": "user", "content": prompt}
],
temperature=0.7,
max_tokens=3000 # Increased to accommodate answers and explanations
)
return response.choices[0].message.content
except Exception as e:
retries += 1
st.warning(f"Attempt {retries} failed. Retrying... Error: {str(e)}")
if retries == max_retries:
st.error(f"Failed to generate questions after {max_retries} attempts. Error: {str(e)}")
return None
time.sleep(2)
# ระบบ login
# Main Streamlit interface
if 'username' not in st.session_state:
st.title("Login")
username_input = st.text_input("Enter your username:")
if st.button("Login"):
if username_input:
if check_user_in_sheet(username_input):
st.session_state['username'] = username_input
st.success(f"Welcome, {username_input}!")
update_api_usage(username_input)
else:
st.warning("Username not found. Please try again.")
else:
st.warning("Please enter a valid username.")
else:
st.title(f"Welcome, {st.session_state['username']}! Generate your exam questions")
# Create tabs for input methods
tab1, tab2 = st.tabs(["Text Input", "PDF Upload"])
with tab1:
knowledge_material = st.text_area("Enter knowledge material to generate exam questions:")
word_count = len(knowledge_material.split())
if word_count > WORD_LIMIT:
st.error(f"Text exceeds {WORD_LIMIT:,} words. Please shorten your content.")
with tab2:
st.info(f"Maximum content length: {WORD_LIMIT:,} words")
uploaded_file = st.file_uploader("Upload a PDF file", type="pdf")
if uploaded_file is not None:
pdf_content, error = extract_text_from_pdf(uploaded_file)
if error:
st.error(error)
else:
st.success("PDF processed successfully!")
knowledge_material = pdf_content
# Question generation options
col1, col2 = st.columns(2)
with col1:
question_type = st.selectbox(
"Select question type:",
["Multiple Choice", "Fill in the Blank", "Open-ended", "True/False"]
)
if question_type == "Multiple Choice":
num_choices = st.selectbox("Select number of choices:", [3, 4, 5])
cognitive_level = st.selectbox(
"Select cognitive level:",
["Recall", "Understanding", "Application", "Analysis", "Synthesis", "Evaluation"]
)
with col2:
case_based = st.checkbox("Generate case-based medical exam questions")
extra_instructions = st.text_area("Additional instructions (optional):")
# Generate questions button
if st.button("Generate Questions"):
if 'knowledge_material' in locals() and knowledge_material.strip():
with st.spinner("Generating questions..."):
# Your existing generate_questions_with_retry function call here
questions = generate_questions_with_retry(
knowledge_material,
question_type,
cognitive_level,
extra_instructions,
case_based,
num_choices if question_type == "Multiple Choice" else None
)
if questions:
st.write("### Generated Exam Questions:")
st.write(questions)
# Download button
st.download_button(
label="Download Questions",
data=questions,
file_name='generated_questions.txt',
mime='text/plain'
)
else:
st.warning("Please enter knowledge material or upload a PDF file first.") |