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.")