exam_maker_mirror2 / pages /2_Text_prompt.py
louiecerv's picture
sync to remote
821850b
raw
history blame
8.58 kB
import streamlit as st
import sqlite3
import time
import datetime
from PIL import Image
import google.generativeai as genai
import os
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import A4, letter
from io import BytesIO
import tempfile
import json
import re
from reportlab.platypus import Paragraph, Frame, Spacer
from reportlab.lib.styles import getSampleStyleSheet
import shutil
from pdfutils import generate_quiz_content, create_pdf, create_json, generate_metadata, merge_json_strings, generate_text, clean_markdown
MODEL_ID = "gemini-2.0-flash-exp"
api_key = os.getenv("GEMINI_API_KEY")
model_id = MODEL_ID
genai.configure(api_key=api_key)
if "model" not in st.session_state:
st.session_state.model = genai.GenerativeModel(MODEL_ID)
if "chat" not in st.session_state:
st.session_state.chat = st.session_state.model.start_chat()
def get_system_instruction(username):
""" Retrieves the system instruction for the user from the database. """
conn = sqlite3.connect('users.db')
c = conn.cursor()
c.execute('SELECT instruction FROM system_instructions WHERE username=?', (username,))
instruction = c.fetchone()
conn.close()
if instruction:
return instruction[0]
else:
return "Default system instruction."
def save_user_prompt(username, prompt_time, prompt_type):
""" Saves the user prompt to the database for monitoring purposes. """
conn = sqlite3.connect('users.db')
c = conn.cursor()
c.execute('INSERT INTO user_prompts(username, prompt_time, prompt_type) VALUES (?,?,?)', (username, prompt_time, prompt_type))
conn.commit()
conn.close()
def show_text_prompt():
st.subheader("Text Prompt")
username = st.session_state["username"]
st.write(f"Welcome, {username}! This page allows you to generate questions based on user inputs.")
# Display username and logout button on every page
st.sidebar.write(f"Current user: {st.session_state['username']}")
# User inputs
# Course selection
course = st.text_input("Enter Course",
"e.g.,Bachelor of Secondary Education")
# Year level selection
year_level = st.selectbox("Select Year Level",
["1st Year",
"2nd Year",
"3rd Year",
"4th Year"])
# Subject selection
subject = st.text_input("Enter Subject",
"e.g.,The Teaching Profession, Facilitating Learner-Centered Teaching")
# Topic selection
topic = st.text_input("Enter Topic",
"e.g., Teacher as a professional, Introduction to Learner-Centered Teaching")
# Question type selection
question_type = st.selectbox("Select Question Type",
["Multiple Choice",
"True or False",
"Short Response",
"Essay Type"])
difficulty = st.selectbox("Select Difficulty",["easy","average","hard"])
#number of questions to generate
if question_type != "Essay Type":
num_questions = st.selectbox("Number of Questions to Generate",
[10, 20, 30, 40, 50])
else:
num_questions = st.selectbox("Number of Questions to Generate",
[1, 2, 3, 4, 5])
# Combine user inputs into a prompt
prompt = f"""Refer to the uploaded document. Generate a {question_type} question for a {year_level} {course} student
in {subject} on the topic of {topic} with a {difficulty} difficulty level.
The questions should require higher order thinking skills.
"""
if question_type == "Multiple Choice":
prompt += """Provide 4 choices. Provide the correct answer in the format 'Answer: A'.
Use the following JSON format for each question:
[{
"question": "Your question here?",
"options": ["Option A", "Option B", "Option C", "Option D"],
"correct_answer": "full text of the correct answer"
}, ... more questions]
Ensure that the response only contains the JSON array of questions and nothing else.
"""
elif question_type == "True or False":
prompt += """Indicate whether the statement is true or false. Keep the statement brief and concise.
Use the following JSON format for each question:
[{
"statement": "Your statement here",
"options": ["True", "False"],
"correct_answer": True"
}, ... more questions]
Ensure that the response only contains the JSON array of questions and nothing else.
"""
elif question_type == "Short Response":
prompt += """Create question that require a word or short phrase as answer. Use the following JSON format for each question:
[{
"question": "Your question here?",
"correct_answer": A word or phrase"
}, ... more questions]
Ensure that the response only contains the JSON array of questions and nothing else.
"""
elif question_type == "Essay Type":
prompt += """Create questions that require a short essay between 300 to 500 words.
Provide a detailed answer. Use the following JSON format for each question:
[{
"question": "Your question here?",
"correct_answer": The essay answer goes here."
}, ... more questions]
Ensure that the response only contains the JSON array of questions and nothing else.
"""
if not question_type == "Essay Type":
prompt += f"Generate 10 questions. Do not repeat questions you have already given in previous prompts. Exclude markdown tags in the response."
else:
prompt += f" Generate {num_questions} questions. Do not repeat questions you have already given in previous prompts. Exclude markdown tags in the response"
full_quiz = ""
# Send button
if st.button("Generate Questions"):
if question_type == "Essay Type":
#prompt once
with st.spinner('Generating questions...'):
full_quiz = clean_markdown(generate_text(prompt))
else:
if num_questions == 10:
#prompt once
with st.spinner('Generating questions...'):
full_quiz = clean_markdown(generate_text(prompt))
else:
#prompt multiple times
times = num_questions//10
for i in range(times):
with st.spinner('Generating questions...'):
response = generate_text(prompt)
if i==0:
full_quiz = clean_markdown(response)
else:
full_quiz = merge_json_strings(full_quiz, response)
metadata = generate_metadata(subject, topic, num_questions, question_type)
try:
# Attempt to load the string as JSON to validate it
content = json.loads(full_quiz)
except json.JSONDecodeError:
st.error("Error: Invalid JSON string for quiz content.")
st.stop()
json_string = create_json(metadata, content)
quiz_markdown = generate_quiz_content(json_string)
st.markdown(quiz_markdown)
pdf_path = create_pdf(json_string)
if pdf_path:
"""Click the button to download the generated PDF."""
try:
with open(pdf_path, "rb") as f:
st.download_button("Download PDF", f, file_name=os.path.basename(pdf_path))
except Exception as e:
st.error(f"Error handling file download: {e}")
else:
st.error("Failed to generate the PDF. Please try again.")
#record the prompt for monitoring
save_user_prompt(username, datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"), "Multimodal")
if st.session_state["authenticated"]:
show_text_prompt()
else:
if not st.session_state["is_starting"]:
st.write("You are not authenticated. Please log in to access this page.")