dalinstone commited on
Commit
e100fec
Β·
1 Parent(s): 53f582b

this fixes the requirements.txt

Browse files
Files changed (2) hide show
  1. app.py +26 -29
  2. requirements.txt +0 -2
app.py CHANGED
@@ -1,5 +1,3 @@
1
- # main_grader.py
2
-
3
  import gradio as gr
4
  import docx
5
  import asyncio
@@ -12,9 +10,6 @@ import os
12
  from pathlib import Path
13
  import time
14
 
15
- # --- Configuration and Prompts ---
16
-
17
- # This rubric is embedded in the prompt sent to the Gemini API.
18
  GRADING_RUBRIC = """
19
  ### NURSING ESSAY GRADING RUBRIC
20
 
@@ -39,8 +34,6 @@ GRADING_RUBRIC = """
39
  * **Professional Tone:** Maintains a scholarly and professional tone appropriate for nursing. (5 points)
40
  """
41
 
42
- # The main prompt for the Gemini API.
43
- # It instructs the AI on its role, the rubric, and the required JSON output format.
44
  GEMINI_PROMPT = f"""
45
  You are an expert-level college university grader for a nursing department. Your task is to evaluate a short health science essay based on a strict rubric and provide your feedback in a structured JSON format.
46
 
@@ -85,8 +78,6 @@ You are an expert-level college university grader for a nursing department. Your
85
  """
86
 
87
 
88
- # --- Data Structures ---
89
-
90
  @dataclass
91
  class GradingResult:
92
  """Holds the structured result of a single graded essay."""
@@ -111,11 +102,13 @@ class EssayParser:
111
  return "\n".join([para.text for para in doc.paragraphs if para.text])
112
  except Exception as e:
113
  # Handles cases where the file is corrupted or not a valid docx
114
- raise IOError(f"Could not read file: {os.path.basename(file_path)}. Error: {e}")
 
115
 
116
 
117
  class GeminiGrader:
118
  """Manages interaction with the Google Gemini API for grading."""
 
119
  def __init__(self, api_key: str):
120
  """Initializes the Gemini model."""
121
  try:
@@ -130,8 +123,10 @@ class GeminiGrader:
130
  safety_settings = [
131
  {"category": "HARM_CATEGORY_HARASSMENT", "threshold": "BLOCK_NONE"},
132
  {"category": "HARM_CATEGORY_HATE_SPEECH", "threshold": "BLOCK_NONE"},
133
- {"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", "threshold": "BLOCK_NONE"},
134
- {"category": "HARM_CATEGORY_DANGEROUS_CONTENT", "threshold": "BLOCK_NONE"},
 
 
135
  ]
136
  self.model = genai.GenerativeModel(
137
  model_name="gemini-1.5-pro-latest",
@@ -152,11 +147,13 @@ class GeminiGrader:
152
  # Clean the response to ensure it's valid JSON
153
  cleaned_response = response.text.strip().replace("```json", "").replace("```", "")
154
  data = json.loads(cleaned_response)
155
-
156
  # Validate the structure of the returned JSON
157
- required_keys = ["finalGrade", "pointDeductions", "feedback", "summary"]
 
158
  if not all(key in data for key in required_keys):
159
- raise KeyError("The model's response was missing one or more required keys.")
 
160
 
161
  return GradingResult(
162
  file_name=file_name,
@@ -190,7 +187,7 @@ async def grade_papers_concurrently(
190
  It's triggered by the Gradio button click.
191
  """
192
  start_time = time.time()
193
-
194
  if not api_key:
195
  raise gr.Error("Google API Key is required.")
196
  if not files:
@@ -203,7 +200,7 @@ async def grade_papers_concurrently(
203
 
204
  file_paths = [file.name for file in files]
205
  total_files = len(file_paths)
206
-
207
  # Use a ThreadPoolExecutor to run synchronous tasks concurrently
208
  with ThreadPoolExecutor(max_workers=10) as executor:
209
  # Create a future for each file processing task
@@ -228,12 +225,12 @@ async def grade_papers_concurrently(
228
  # --- Format the final output ---
229
  successful_grades = [res for res in results if res.success]
230
  failed_grades = [res for res in results if not res.success]
231
-
232
  output_markdown = ""
233
  for result in successful_grades:
234
  output_markdown += f"### βœ… Grade for: **{result.file_name}**\n"
235
  output_markdown += f"**Final Grade:** {result.grade}/100\n\n"
236
-
237
  # Format point deductions
238
  deductions_str = ""
239
  for category, points in result.deductions.items():
@@ -241,7 +238,7 @@ async def grade_papers_concurrently(
241
  deductions_str += f"- **{category}:** Lost {points} points. *Reason: {result.feedback.get(category, 'N/A')}*\n"
242
  if not deductions_str:
243
  deductions_str = "Excellent work! No points were deducted.\n"
244
-
245
  output_markdown += "**Point Deductions Breakdown:**\n" + deductions_str + "\n"
246
  output_markdown += f"**Summary:** {result.summary}\n"
247
  output_markdown += "---\n"
@@ -252,15 +249,15 @@ async def grade_papers_concurrently(
252
  output_markdown += f"- **File:** {result.file_name}\n"
253
  output_markdown += f" - **Error:** {result.error_message}\n"
254
  output_markdown += "---\n"
255
-
256
  end_time = time.time()
257
  runtime = f"Total runtime: {end_time - start_time:.2f} seconds."
258
-
259
  status = (
260
  f"Grading complete. {len(successful_grades)} papers graded successfully, "
261
  f"{len(failed_grades)} failed."
262
  )
263
-
264
  return output_markdown, f"{status}\n{runtime}"
265
 
266
 
@@ -303,27 +300,27 @@ with gr.Blocks(theme=gr.themes.Soft(), title="Nursing Essay Grader") as demo:
303
  type="password",
304
  scale=1
305
  )
306
-
307
  file_uploads = gr.File(
308
  label="Upload Word Document Essays",
309
  file_count="multiple",
310
  file_types=[".docx"],
311
- type="filepath" # Use filepath for easier handling
312
  )
313
-
314
  grade_button = gr.Button("πŸš€ Grade All Papers", variant="primary")
315
-
316
  gr.Markdown("---")
317
  gr.Markdown("## πŸ“Š Grading Results")
318
 
319
  results_output = gr.Markdown(label="Formatted Grades")
320
-
321
  status_output = gr.Textbox(
322
  label="Runtime Status",
323
  lines=2,
324
  interactive=False
325
  )
326
-
327
  grade_button.click(
328
  fn=grade_papers_concurrently,
329
  inputs=[file_uploads, api_key_input],
 
 
 
1
  import gradio as gr
2
  import docx
3
  import asyncio
 
10
  from pathlib import Path
11
  import time
12
 
 
 
 
13
  GRADING_RUBRIC = """
14
  ### NURSING ESSAY GRADING RUBRIC
15
 
 
34
  * **Professional Tone:** Maintains a scholarly and professional tone appropriate for nursing. (5 points)
35
  """
36
 
 
 
37
  GEMINI_PROMPT = f"""
38
  You are an expert-level college university grader for a nursing department. Your task is to evaluate a short health science essay based on a strict rubric and provide your feedback in a structured JSON format.
39
 
 
78
  """
79
 
80
 
 
 
81
  @dataclass
82
  class GradingResult:
83
  """Holds the structured result of a single graded essay."""
 
102
  return "\n".join([para.text for para in doc.paragraphs if para.text])
103
  except Exception as e:
104
  # Handles cases where the file is corrupted or not a valid docx
105
+ raise IOError(
106
+ f"Could not read file: {os.path.basename(file_path)}. Error: {e}")
107
 
108
 
109
  class GeminiGrader:
110
  """Manages interaction with the Google Gemini API for grading."""
111
+
112
  def __init__(self, api_key: str):
113
  """Initializes the Gemini model."""
114
  try:
 
123
  safety_settings = [
124
  {"category": "HARM_CATEGORY_HARASSMENT", "threshold": "BLOCK_NONE"},
125
  {"category": "HARM_CATEGORY_HATE_SPEECH", "threshold": "BLOCK_NONE"},
126
+ {"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT",
127
+ "threshold": "BLOCK_NONE"},
128
+ {"category": "HARM_CATEGORY_DANGEROUS_CONTENT",
129
+ "threshold": "BLOCK_NONE"},
130
  ]
131
  self.model = genai.GenerativeModel(
132
  model_name="gemini-1.5-pro-latest",
 
147
  # Clean the response to ensure it's valid JSON
148
  cleaned_response = response.text.strip().replace("```json", "").replace("```", "")
149
  data = json.loads(cleaned_response)
150
+
151
  # Validate the structure of the returned JSON
152
+ required_keys = ["finalGrade",
153
+ "pointDeductions", "feedback", "summary"]
154
  if not all(key in data for key in required_keys):
155
+ raise KeyError(
156
+ "The model's response was missing one or more required keys.")
157
 
158
  return GradingResult(
159
  file_name=file_name,
 
187
  It's triggered by the Gradio button click.
188
  """
189
  start_time = time.time()
190
+
191
  if not api_key:
192
  raise gr.Error("Google API Key is required.")
193
  if not files:
 
200
 
201
  file_paths = [file.name for file in files]
202
  total_files = len(file_paths)
203
+
204
  # Use a ThreadPoolExecutor to run synchronous tasks concurrently
205
  with ThreadPoolExecutor(max_workers=10) as executor:
206
  # Create a future for each file processing task
 
225
  # --- Format the final output ---
226
  successful_grades = [res for res in results if res.success]
227
  failed_grades = [res for res in results if not res.success]
228
+
229
  output_markdown = ""
230
  for result in successful_grades:
231
  output_markdown += f"### βœ… Grade for: **{result.file_name}**\n"
232
  output_markdown += f"**Final Grade:** {result.grade}/100\n\n"
233
+
234
  # Format point deductions
235
  deductions_str = ""
236
  for category, points in result.deductions.items():
 
238
  deductions_str += f"- **{category}:** Lost {points} points. *Reason: {result.feedback.get(category, 'N/A')}*\n"
239
  if not deductions_str:
240
  deductions_str = "Excellent work! No points were deducted.\n"
241
+
242
  output_markdown += "**Point Deductions Breakdown:**\n" + deductions_str + "\n"
243
  output_markdown += f"**Summary:** {result.summary}\n"
244
  output_markdown += "---\n"
 
249
  output_markdown += f"- **File:** {result.file_name}\n"
250
  output_markdown += f" - **Error:** {result.error_message}\n"
251
  output_markdown += "---\n"
252
+
253
  end_time = time.time()
254
  runtime = f"Total runtime: {end_time - start_time:.2f} seconds."
255
+
256
  status = (
257
  f"Grading complete. {len(successful_grades)} papers graded successfully, "
258
  f"{len(failed_grades)} failed."
259
  )
260
+
261
  return output_markdown, f"{status}\n{runtime}"
262
 
263
 
 
300
  type="password",
301
  scale=1
302
  )
303
+
304
  file_uploads = gr.File(
305
  label="Upload Word Document Essays",
306
  file_count="multiple",
307
  file_types=[".docx"],
308
+ type="filepath" # Use filepath for easier handling
309
  )
310
+
311
  grade_button = gr.Button("πŸš€ Grade All Papers", variant="primary")
312
+
313
  gr.Markdown("---")
314
  gr.Markdown("## πŸ“Š Grading Results")
315
 
316
  results_output = gr.Markdown(label="Formatted Grades")
317
+
318
  status_output = gr.Textbox(
319
  label="Runtime Status",
320
  lines=2,
321
  interactive=False
322
  )
323
+
324
  grade_button.click(
325
  fn=grade_papers_concurrently,
326
  inputs=[file_uploads, api_key_input],
requirements.txt CHANGED
@@ -2,5 +2,3 @@ gradio
2
  google-generativeai==0.5.*
3
  python-docx
4
  asyncio
5
- json
6
-
 
2
  google-generativeai==0.5.*
3
  python-docx
4
  asyncio