Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -5,11 +5,8 @@ import os
|
|
| 5 |
from dotenv import load_dotenv
|
| 6 |
|
| 7 |
# --- Configuration ---
|
| 8 |
-
# Load environment variables from a .env file if it exists (for local development)
|
| 9 |
load_dotenv()
|
| 10 |
|
| 11 |
-
# It's recommended to set your GOOGLE_API_KEY as a secret in your Hugging Face Space settings.
|
| 12 |
-
# The key should be named GOOGLE_API_KEY.
|
| 13 |
try:
|
| 14 |
api_key = os.environ.get("GOOGLE_API_KEY")
|
| 15 |
if not api_key:
|
|
@@ -18,19 +15,16 @@ try:
|
|
| 18 |
model = genai.GenerativeModel('gemini-2.5-flash')
|
| 19 |
except Exception as e:
|
| 20 |
print(f"Error configuring GenerativeAI: {e}")
|
| 21 |
-
# Handle the case where the API key is not set, e.g., by disabling the interface or showing an error.
|
| 22 |
model = None
|
| 23 |
|
| 24 |
# --- Data Loading ---
|
| 25 |
try:
|
| 26 |
df = pd.read_csv('qp_with_ms_images (1).csv')
|
| 27 |
-
# Clean up column names that might have extra spaces
|
| 28 |
df.columns = df.columns.str.strip()
|
| 29 |
except FileNotFoundError:
|
| 30 |
print("Error: 'qp_with_ms_images (1).csv' not found. Please upload the data file to your Space.")
|
| 31 |
-
df = pd.DataFrame()
|
| 32 |
|
| 33 |
-
# --- Provided Topics List ---
|
| 34 |
TOPICS = """
|
| 35 |
SL 1.1 - Operations with numbers in the form a × 10k where 1 < a < 10 and k is an integer.
|
| 36 |
SL 1.2 - Arithmetic sequences and series. Use of the formulae for the nth term and the sum of the first n terms of the sequence. Use of sigma notation for sums of arithmetic sequences. Applications. Analysis, interpretation and prediction where a model is not perfectly arithmetic in real life.
|
|
@@ -125,57 +119,69 @@ AHL 5.19 - Maclaurin series to obtain expansions for eˣ, sinx, cosx, ln(1+x), (
|
|
| 125 |
def generate_test(total_marks, topic_name, level):
|
| 126 |
"""
|
| 127 |
Generates a test paper using the Gemini LLM based on user inputs.
|
|
|
|
| 128 |
"""
|
| 129 |
if model is None or df.empty:
|
| 130 |
return "Error: Application is not configured correctly. Please check API key and data file."
|
| 131 |
|
| 132 |
-
# Filter
|
| 133 |
if level == 'SL':
|
| 134 |
filtered_df = df[df['Level'] == 'SL'].copy()
|
| 135 |
-
else:
|
| 136 |
filtered_df = df.copy()
|
| 137 |
|
| 138 |
-
#
|
| 139 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 140 |
if len(filtered_df) > 300:
|
| 141 |
-
filtered_df = filtered_df.
|
| 142 |
|
| 143 |
question_data = filtered_df[[
|
| 144 |
'Question Number', 'Date', 'Topic', 'Level', 'Max Marks', 'QP Content'
|
| 145 |
]].to_string(index=False)
|
| 146 |
|
| 147 |
-
# --- Prompt
|
| 148 |
-
|
| 149 |
-
You are an expert test creator for the International Baccalaureate (IB) Mathematics program.
|
| 150 |
-
Your task is to create a test paper based on the user's request using a provided question bank.
|
| 151 |
-
|
| 152 |
-
**User Request:**
|
| 153 |
-
- Total Marks: {total_marks}
|
| 154 |
-
- Topic: "{topic_name}"
|
| 155 |
-
- Level: {level}
|
| 156 |
-
|
| 157 |
-
**Instructions:**
|
| 158 |
-
1. Carefully select a combination of questions from the provided **QUESTION BANK** that best fit the requested topic and level.
|
| 159 |
-
2. The total marks of all selected questions should be as close as possible to the requested **Total Marks ({total_marks})**.
|
| 160 |
-
3. When
|
| 161 |
-
4. If multiple questions
|
| 162 |
-
5. Present the final test in a clean, well-formatted markdown format. It should look like a real test paper.
|
| 163 |
-
6. For each question,
|
| 164 |
-
|
| 165 |
-
|
| 166 |
-
|
| 167 |
-
**
|
| 168 |
-
|
| 169 |
-
|
| 170 |
-
|
| 171 |
-
|
| 172 |
-
|
| 173 |
-
|
| 174 |
-
|
| 175 |
-
|
| 176 |
-
|
| 177 |
-
|
| 178 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 179 |
|
| 180 |
try:
|
| 181 |
response = model.generate_content(prompt)
|
|
@@ -185,29 +191,23 @@ Now, create the test based on the user's request, ensuring that the **latest ava
|
|
| 185 |
|
| 186 |
# --- Gradio Interface ---
|
| 187 |
with gr.Blocks(theme=gr.themes.Soft()) as demo:
|
| 188 |
-
gr.Markdown("# 📝 IB Mathematics Test Generator")
|
| 189 |
gr.Markdown(
|
| 190 |
-
"Enter the desired total marks, a topic name, and the level (SL/AHL)
|
| 191 |
-
"
|
| 192 |
)
|
| 193 |
|
| 194 |
with gr.Row():
|
| 195 |
with gr.Column(scale=1):
|
| 196 |
total_marks_input = gr.Slider(
|
| 197 |
-
minimum=10,
|
| 198 |
-
maximum=150,
|
| 199 |
-
step=1,
|
| 200 |
-
value=50,
|
| 201 |
-
label="Total Marks for the Test"
|
| 202 |
)
|
| 203 |
topic_input = gr.Textbox(
|
| 204 |
label="Topic Name",
|
| 205 |
placeholder="e.g., Trigonometry, Calculus, Algebra, Vectors..."
|
| 206 |
)
|
| 207 |
level_input = gr.Radio(
|
| 208 |
-
choices=['SL', 'AHL'],
|
| 209 |
-
label="Select Level",
|
| 210 |
-
value='AHL'
|
| 211 |
)
|
| 212 |
generate_button = gr.Button("Generate Test", variant="primary")
|
| 213 |
|
|
@@ -221,4 +221,7 @@ with gr.Blocks(theme=gr.themes.Soft()) as demo:
|
|
| 221 |
)
|
| 222 |
|
| 223 |
if __name__ == "__main__":
|
| 224 |
-
demo.launch()
|
|
|
|
|
|
|
|
|
|
|
|
| 5 |
from dotenv import load_dotenv
|
| 6 |
|
| 7 |
# --- Configuration ---
|
|
|
|
| 8 |
load_dotenv()
|
| 9 |
|
|
|
|
|
|
|
| 10 |
try:
|
| 11 |
api_key = os.environ.get("GOOGLE_API_KEY")
|
| 12 |
if not api_key:
|
|
|
|
| 15 |
model = genai.GenerativeModel('gemini-2.5-flash')
|
| 16 |
except Exception as e:
|
| 17 |
print(f"Error configuring GenerativeAI: {e}")
|
|
|
|
| 18 |
model = None
|
| 19 |
|
| 20 |
# --- Data Loading ---
|
| 21 |
try:
|
| 22 |
df = pd.read_csv('qp_with_ms_images (1).csv')
|
|
|
|
| 23 |
df.columns = df.columns.str.strip()
|
| 24 |
except FileNotFoundError:
|
| 25 |
print("Error: 'qp_with_ms_images (1).csv' not found. Please upload the data file to your Space.")
|
| 26 |
+
df = pd.DataFrame()
|
| 27 |
|
|
|
|
| 28 |
TOPICS = """
|
| 29 |
SL 1.1 - Operations with numbers in the form a × 10k where 1 < a < 10 and k is an integer.
|
| 30 |
SL 1.2 - Arithmetic sequences and series. Use of the formulae for the nth term and the sum of the first n terms of the sequence. Use of sigma notation for sums of arithmetic sequences. Applications. Analysis, interpretation and prediction where a model is not perfectly arithmetic in real life.
|
|
|
|
| 119 |
def generate_test(total_marks, topic_name, level):
|
| 120 |
"""
|
| 121 |
Generates a test paper using the Gemini LLM based on user inputs.
|
| 122 |
+
Prioritizes the most recent questions from the topic.
|
| 123 |
"""
|
| 124 |
if model is None or df.empty:
|
| 125 |
return "Error: Application is not configured correctly. Please check API key and data file."
|
| 126 |
|
| 127 |
+
# --- Filter and sort by latest date ---
|
| 128 |
if level == 'SL':
|
| 129 |
filtered_df = df[df['Level'] == 'SL'].copy()
|
| 130 |
+
else:
|
| 131 |
filtered_df = df.copy()
|
| 132 |
|
| 133 |
+
# Sort by date descending (newest first)
|
| 134 |
+
if 'Date' in filtered_df.columns:
|
| 135 |
+
try:
|
| 136 |
+
filtered_df['Date'] = pd.to_datetime(filtered_df['Date'], errors='coerce')
|
| 137 |
+
filtered_df = filtered_df.sort_values(by='Date', ascending=False)
|
| 138 |
+
except Exception:
|
| 139 |
+
pass # If Date parsing fails, skip sorting
|
| 140 |
+
|
| 141 |
+
# Limit dataset size for LLM input
|
| 142 |
if len(filtered_df) > 300:
|
| 143 |
+
filtered_df = filtered_df.head(300)
|
| 144 |
|
| 145 |
question_data = filtered_df[[
|
| 146 |
'Question Number', 'Date', 'Topic', 'Level', 'Max Marks', 'QP Content'
|
| 147 |
]].to_string(index=False)
|
| 148 |
|
| 149 |
+
# --- Enhanced Prompt (with latest question priority) ---
|
| 150 |
+
prompt = f"""
|
| 151 |
+
You are an expert test creator for the International Baccalaureate (IB) Mathematics program.
|
| 152 |
+
Your task is to create a test paper based on the user's request using a provided question bank.
|
| 153 |
+
|
| 154 |
+
**User Request:**
|
| 155 |
+
- Total Marks: {total_marks}
|
| 156 |
+
- Topic: "{topic_name}"
|
| 157 |
+
- Level: {level}
|
| 158 |
+
|
| 159 |
+
**Instructions:**
|
| 160 |
+
1. Carefully select a combination of questions from the provided **QUESTION BANK** that best fit the requested topic and level.
|
| 161 |
+
2. The total marks of all selected questions should be as close as possible to the requested **Total Marks ({total_marks})**.
|
| 162 |
+
3. When choosing questions, **prioritize the latest (most recent) questions based on the 'Date' field**.
|
| 163 |
+
4. If multiple questions fit equally well, choose the newest ones first.
|
| 164 |
+
5. Present the final test in a clean, well-formatted markdown format. It should look like a real test paper.
|
| 165 |
+
6. For each question, include:
|
| 166 |
+
- **Question ID** (from 'Question Number')
|
| 167 |
+
- **Date**
|
| 168 |
+
- **Topic Code**
|
| 169 |
+
- **Maximum Marks**
|
| 170 |
+
7. Display the full question content exactly as it appears in 'QP Content'.
|
| 171 |
+
8. Use the provided **TOPICS LIST** to identify relevant topic codes.
|
| 172 |
+
|
| 173 |
+
**TOPICS LIST:**
|
| 174 |
+
---
|
| 175 |
+
{TOPICS}
|
| 176 |
+
---
|
| 177 |
+
|
| 178 |
+
**QUESTION BANK (sorted by most recent first):**
|
| 179 |
+
---
|
| 180 |
+
{question_data}
|
| 181 |
+
---
|
| 182 |
+
|
| 183 |
+
Now, create the test based on the user's request, making sure to use the **latest available questions** first.
|
| 184 |
+
"""
|
| 185 |
|
| 186 |
try:
|
| 187 |
response = model.generate_content(prompt)
|
|
|
|
| 191 |
|
| 192 |
# --- Gradio Interface ---
|
| 193 |
with gr.Blocks(theme=gr.themes.Soft()) as demo:
|
| 194 |
+
gr.Markdown("# 📝 IB Mathematics Test Generator (Latest Question Priority)")
|
| 195 |
gr.Markdown(
|
| 196 |
+
"Enter the desired total marks, a topic name, and the level (SL/AHL). "
|
| 197 |
+
"This version prioritizes the **latest available questions** when generating your test."
|
| 198 |
)
|
| 199 |
|
| 200 |
with gr.Row():
|
| 201 |
with gr.Column(scale=1):
|
| 202 |
total_marks_input = gr.Slider(
|
| 203 |
+
minimum=10, maximum=150, step=1, value=50, label="Total Marks for the Test"
|
|
|
|
|
|
|
|
|
|
|
|
|
| 204 |
)
|
| 205 |
topic_input = gr.Textbox(
|
| 206 |
label="Topic Name",
|
| 207 |
placeholder="e.g., Trigonometry, Calculus, Algebra, Vectors..."
|
| 208 |
)
|
| 209 |
level_input = gr.Radio(
|
| 210 |
+
choices=['SL', 'AHL'], label="Select Level", value='AHL'
|
|
|
|
|
|
|
| 211 |
)
|
| 212 |
generate_button = gr.Button("Generate Test", variant="primary")
|
| 213 |
|
|
|
|
| 221 |
)
|
| 222 |
|
| 223 |
if __name__ == "__main__":
|
| 224 |
+
demo.launch()
|
| 225 |
+
# --- Provided Topics List ---
|
| 226 |
+
|
| 227 |
+
|