Spaces:
Sleeping
Sleeping
File size: 8,580 Bytes
821850b |
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 |
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.")
|