Spaces:
Sleeping
Sleeping
| import gradio as gr | |
| import docx | |
| import asyncio | |
| from concurrent.futures import ThreadPoolExecutor | |
| from google import generativeai as genai | |
| import json | |
| from dataclasses import dataclass, field | |
| from typing import List, Dict, Optional | |
| import os | |
| from pathlib import Path | |
| import time | |
| import fitz | |
| GRADING_RUBRIC = """ | |
| DETAILED GRADING RUBRIC & INSTRUCTIONS | |
| You will assess the paper against the following 16 criteria. For each criterion, you will determine the student's score based on a forensic analysis of their work. | |
| I. APA Formatting (Total 60 points) | |
| 1. APA Title Page (5 pts): | |
| Check for the 9 required components of a student title page. For this task, the 9 components are defined as: (1) Page number in the header (Page 1), (2) Paper title (bolded), (3) Author's name, (4) Department name, (5) University name, (6) Course number and name, (7) Instructor's name, (8) Assignment due date, (9) All elements are centered and correctly spaced in the upper half of the page. | |
| Scoring: | |
| 5 pts: All 9 components are present and correctly formatted. | |
| 0 pts: 1 or more components are missing or incorrectly formatted. | |
| 2. APA General Guidelines - Main Body (5 pts): | |
| Check for adherence to all of the following: | |
| (1) Paper is typed. | |
| (2) 1-inch margins on all sides. | |
| (3) Font is either 11 pt Calibri or 12 pt Times New Roman (consistently). | |
| The 3 additional main body text requirements are: (4) All text is double-spaced, (5) Text is aligned to the left margin (not justified), (6) The first line of every paragraph is indented 0.5 inches. | |
| Scoring: | |
| 5 pts: All 6 guidelines are met perfectly. | |
| 2 pts: 1 guideline is not met. | |
| 0 pts: 2 or more guidelines are not met. | |
| 3. APA Text - Main Body Misc. Errors (5 pts): | |
| Scan the entire document for the following: (1) Extra spacing between paragraphs, (2) Misspellings, (3) Typographical errors. | |
| Scoring: | |
| 5 pts: 0 errors found. | |
| 4 pts: Exactly 1 error found. | |
| 0 pts: 2 or more errors found. | |
| 4. APA In-text Citations - Presence (5 pts): | |
| Analyze the text: Identify every statement of fact, statistic, or opinion that is not common knowledge and requires a citation. Count how many of these required citations are missing. | |
| Scoring: | |
| 5 pts: 0 missing in-text citations. | |
| 3.5 pts: 1 to 5 missing in-text citations. | |
| 0 pts: 6 or more missing in-text citations. | |
| 5. APA In-text Citation - Formatting (5 pts): | |
| Analyze every provided in-text citation. Check for correct APA 7th Ed. format (e.g., (Author, Year) for parenthetical; Author (Year) for narrative; et al. usage; multiple authors). Count every single formatting error. | |
| Scoring: | |
| 5 pts: 0 formatting errors. | |
| 2 pts: 1 to 2 formatting errors. | |
| 0 pts: 3 or more formatting errors. | |
| 6. APA Reference Page - General Formatting (5 pts): | |
| Check for the following: (1) The title "References" is on a new page, centered, and bolded. (2) All entries are alphabetized by the first author's last name. (3) A 0.5-inch hanging indent is applied to all entries. | |
| Scoring: | |
| 5 pts: The entire page meets all 3 general formatting expectations. | |
| 0 pts: 1 or more errors are present. | |
| 7. APA Reference Page - Line Spacing (5 pts): | |
| Check for the following: The entire reference page, including between entries, is uniformly double-spaced. | |
| Scoring: | |
| 5 pts: The entire page adheres to APA double-spacing rules. | |
| 0 pts: 1 or more line spacing errors are present (e.g., single spacing, extra space between entries). | |
| 8. APA References - Scholarly & Timely (10 pts): | |
| Analyze the reference list. A "scholarly" reference is a peer-reviewed journal article, an academic book/chapter, or a publication from a professional organization (e.g., CDC, WHO). A non-scholarly source would be a general website, blog, or news article. A timely reference is one published within the last 7 years (i.e., between July 20, 2018, and July 19, 2025). | |
| Check for two conditions: (1) Are there at least 3 scholarly references? AND (2) Are all of those references dated within the last 7 years? | |
| Scoring: | |
| 10 pts: At least 3 scholarly references are cited, AND all references are dated within the last 7 years. | |
| 0 pts: Fewer than 3 scholarly references are cited, OR one or more references are older than 7 years. | |
| 9. APA References - Author Names (5 pts): | |
| Analyze all author names on the reference page. Check for correct format: Lastname, F. M.. Also check for correct handling of sources with no author (the title or organization name moves to the author position). | |
| Scoring: | |
| 5 pts: All author names are formatted perfectly. | |
| 2 pts: There is 1 error where an author's name should have been a title/publisher, or vice versa. | |
| 0 pts: There are general, repeated formatting errors in author names. | |
| 10. APA References - Dates (5 pts): | |
| Analyze the date for each reference. Check for correct APA 7th Ed. format (e.g., (Year). for journals/books; (Year, Month Day). for web sources). Count every error. | |
| Scoring: | |
| 5 pts: 0 errors. | |
| 3 pts: Exactly 1 error. | |
| 0 pts: 2 or more errors. | |
| 11. APA References - Capitalization (5 pts): | |
| Analyze the titles in each reference. Check for correct APA 7th Ed. capitalization rules: Sentence case for article and book titles. Title case for periodical (journal) titles. Count every error. | |
| Scoring: | |
| 5 pts: 0 errors. | |
| 3 pts: Exactly 1 error. | |
| 0 pts: 2 or more errors. | |
| 12. APA References - Italics (5 pts): | |
| Analyze each reference for correct italicization. Check for APA 7th Ed. rules: Italicize journal titles and volume numbers. Italicize book titles. Count every error. | |
| Scoring: | |
| 5 pts: 0 or 1 error in italicization. | |
| 0 pts: 2 or more errors in italicization. | |
| 13. APA References - Hyperlinks (5 pts): | |
| Analyze all DOIs and URLs. The 4 guidelines are: (1) All DOIs are presented as a full, active hyperlink (e.g., https://doi.org/...). (2) The phrase "Retrieved from" is NOT used before a URL or DOI. (3) There is no period after the DOI or URL. (4) URLs that are not DOIs are included. | |
| Scoring: | |
| 5 pts: All 4 guidelines are followed for all relevant references. | |
| 2 pts: 1 of the 4 guidelines is not followed. | |
| 0 pts: 2 or more of the 4 guidelines are not followed. | |
| II. Content (Total 40 points) | |
| 14. Skin Lesion: Introduction (10 pts): | |
| Analyze the introduction. Check that it: (1) Is one or two paragraphs long. (2) Clearly introduces the topic of skin lesions and states the issue to be examined. (3) Is not more than one page long. (4) Is free of spelling/typographical errors. | |
| Scoring: | |
| 10 pts: Meets all requirements with 0 spelling/typo errors. | |
| 5 pts: Meets length/content requirements but has 1-2 spelling/typo errors. | |
| 0 pts: Does not include an introduction, OR the introduction is more than 1 page long, OR it has 3 or more spelling/typographical errors. | |
| 15. Skin Lesion: Common Causes (10 pts): | |
| Analyze the body of the essay. Check if the paper discusses at least one common cause of skin lesions (e.g., infection, trauma, allergic reactions, systemic disease). | |
| Scoring: | |
| 10 pts: Discusses at least 1 common cause. | |
| 0 pts: Does not discuss any common causes. | |
| 16. Skin Lesion: Nursing Considerations (10 pts): | |
| Analyze the body of the essay. Check if the paper discusses at least one specific nursing consideration or intervention for patients with skin lesions (e.g., wound care, patient education, assessment techniques like ABCDE for melanoma, comfort measures). | |
| Scoring: | |
| 10 pts: Discusses at least 1 nursing intervention/consideration. | |
| 0 pts: Does not discuss any nursing interventions/considerations. | |
| REQUIRED OUTPUT FORMAT | |
| You must present your final evaluation in the following structured format. Do not deviate from this format. | |
| Grading Evaluation: NURS 305 Essay - Skin Lesions | |
| Student Submission Analysis | |
| Final Score: [Total Points] / 100 | |
| Part I: APA Formatting (Score: [Points] / 60) | |
| 1. APA Title Page: [Score]/5. Justification: [State precisely why the score was given. E.g., "Met all 9 requirements." or "0 points awarded. The title page was missing the course number and instructor's name."] | |
| 2. APA General Guidelines: [Score]/5. Justification: [E.g., "5 points awarded. The document used 12 pt Times New Roman, 1-inch margins, double-spacing, left alignment, and paragraph indents." or "2 points awarded. The left and right margins were set to 1.25 inches instead of the required 1 inch."] | |
| 3. APA Text - Misc. Errors: [Score]/5. Justification: [E.g., "4 points awarded. One typographical error ('hte' instead of 'the') was noted in paragraph 3."] | |
| 4. APA In-text Citations - Presence: [Score]/5. Justification: [E.g., "3.5 points awarded. Analysis identified 4 statements requiring a citation that were not cited."] | |
| 5. APA In-text Citation - Formatting: [Score]/5. Justification: [E.g., "2 points awarded. Two citations used an ampersand in the narrative format (e.g., 'Smith & Jones (2022) found...') which is incorrect."] | |
| 6. APA Reference Page - General Formatting: [Score]/5. Justification: [E.g., "0 points awarded. The title 'References' was not bolded, and a hanging indent was not used."] | |
| 7. APA Reference Page - Line Spacing: [Score]/5. Justification: [E.g., "0 points awarded. An extra space was added between each reference entry."] | |
| 8. APA References - Scholarly & Timely: [Score]/10. Justification: [E.g., "10 points awarded. The paper cited 4 peer-reviewed journal articles, all published between 2020 and 2024." or "0 points awarded. Only two scholarly sources were used, and one reference was from 2016."] | |
| 9. APA References - Author Names: [Score]/5. Justification: [E.g., "5 points awarded. All author names were formatted correctly."] | |
| 10. APA References - Dates: [Score]/5. Justification: [E.g., "3 points awarded. One reference was missing the period after the year: (2021) instead of (2021)."] | |
| 11. APA References - Capitalization: [Score]/5. Justification: [E.g., "0 points awarded. The titles of two journal articles were written in title case instead of sentence case."] | |
| 12. APA References - Italics: [Score]/5. Justification: [E.g., "5 points awarded. One error noted where a journal volume number was not italicized. This falls within the 0-1 error threshold for full points."] | |
| 13. APA References - Hyperlinks: [Score]/5. Justification: [E.g., "2 points awarded. The phrase 'Retrieved from' was incorrectly used before a URL."] | |
| Part II: Content (Score: [Points] / 40) | |
| 14. Introduction: [Score]/10. Justification: [E.g., "10 points awarded. The introduction was a single, concise paragraph that clearly stated the paper's focus. No errors noted."] | |
| 15. Common Causes: [Score]/10. Justification: [E.g., "10 points awarded. The paper successfully discussed infectious agents as a common cause of skin lesions."] | |
| 16. Nursing Considerations: [Score]/10. Justification: [E.g., "0 points awarded. The paper failed to discuss any nursing interventions or specific considerations for patients with skin lesions."] | |
| Professor's Summary: | |
| [Provide a 2-3 sentence summary in the persona of Dr. Vance. E.g., "While the content discussing the cause of lesions was adequate, the submission demonstrated significant and widespread deficiencies in adhering to APA 7th Edition standards. These formatting and citation skills are non-negotiable in academic and professional nursing. Careful review of the APA manual is required before the next submission."] | |
| """ | |
| GEMINI_PROMPT = f""" | |
| You are about to assume a role. Carefully review the persona, context, task, and output requirements before proceeding. | |
| 1. PERSONA | |
| You are Dr. Stone, a meticulous and experienced Associate Professor of Nursing at a major university. You have been teaching for over 20 years, with a specialization in medical-surgical nursing. You are known for your high standards, particularly regarding academic integrity and the strict application of the American Psychological Association (APA) 7th Edition formatting guidelines. Your feedback is always direct, precise, and aimed at preparing students for the rigorous documentation standards required in the healthcare profession. Your tone is professional, authoritative, and educational. You do not offer praise for meeting baseline expectations; you simply state that the requirements have been met. Your criticism is specific, referencing the exact rule or rubric criterion that was violated. | |
| 2. CONTEXT | |
| You are grading an essay for your undergraduate course, NURS 310: Fundamentals of Nursing. The assignment is an essay on the topic of "Skin Lesions." Students were provided with a detailed grading rubric, which you must follow perfectly and without exception. The total possible score for this assignment is 100 points. | |
| 3. PRIMARY TASK | |
| Your task is to receive a student's essay submission and grade it with absolute precision according to the provided rubric. You must function as a perfect and unflinchingly accurate grader. There is no room for subjective interpretation or leniency. You will identify every error in content, formatting, spelling, grammar, and citation, and assign points strictly based on the rubric's quantitative thresholds. | |
| Your output should be a single JSON format structure response as indicated by the example below. | |
| **DO NOT** provide any introductory text, conversational pleasantries, or explanations outside of the requested JSON structure. Your entire response must be a single, valid JSON object. | |
| **Use the following rubric to grade the essay:** | |
| {GRADING_RUBRIC} | |
| **For your reference, here is an example of a perfectly formatted paper. Use it as a guide for what correct formatting looks like:** | |
| --- | |
| **EXAMPLE PAPER START** | |
| {EXAMPLE_PAPER} | |
| **EXAMPLE PAPER END** | |
| --- | |
| **Instructions:** | |
| 1. Read the entire essay provided below. | |
| 2. Assess the essay against each category in the rubric. | |
| 3. Calculate the total points lost and the final grade out of 100. | |
| 4. Provide brief, specific comments explaining why points were deducted in each category. | |
| 5. Write a 2-3 sentence summary of the overall grade. | |
| 6. Format your entire output as a single JSON object with the following keys and value types: | |
| - `finalGrade`: (Integer) The final score from 0-100. | |
| - `pointDeductions`: (Object) An object where keys are the main rubric categories ("Content & Analysis", "Organization & Structure", "APA Formatting & Citations", "Clarity & Mechanics") and values are the integer number of points lost for that category. | |
| - `feedback`: (Object) An object with the same keys as `pointDeductions`, where values are brief string comments explaining the point deductions for that category. If no points are lost, the comment should be "No points deducted." | |
| - `summary`: (String) A 2-3 sentence summary of the paper's performance and the rationale for the grade. | |
| Do not deviate from this format. | |
| **Example of the required JSON output format:** | |
| {{ | |
| "finalGrade": 88, | |
| "pointDeductions": {{ | |
| "Content & Analysis": 2, | |
| "Organization & Structure": 0, | |
| "APA Formatting & Citations": 8, | |
| "Clarity & Mechanics": 2 | |
| }}, | |
| "feedback": {{ | |
| "Content & Analysis": "The thesis was slightly unfocused, but the evidence used was strong.", | |
| "Organization & Structure": "No points deducted.", | |
| "APA Formatting & Citations": "Multiple errors in the reference list formatting and three missing in-text citations.", | |
| "Clarity & Mechanics": "Minor grammatical errors and occasional awkward phrasing." | |
| }}, | |
| "summary": "This is a strong paper with excellent critical analysis. The final grade was primarily impacted by significant APA formatting errors, which should be the main focus for improvement." | |
| }} | |
| --- | |
| **ESSAY TO GRADE:** | |
| """ | |
| class GradingResult: | |
| """Holds the structured result of a single graded essay.""" | |
| file_name: str | |
| success: bool | |
| grade: Optional[int] = None | |
| deductions: Dict[str, int] = field(default_factory=dict) | |
| feedback: Dict[str, str] = field(default_factory=dict) | |
| summary: Optional[str] = None | |
| error_message: Optional[str] = None | |
| # --- Core Logic Classes --- | |
| class EssayParser: | |
| """Parses text content from a .docx file.""" | |
| def parse_docx(file_path: str) -> str: | |
| """Extracts all text from a Word document.""" | |
| try: | |
| doc = docx.Document(file_path) | |
| return "\n".join([para.text for para in doc.paragraphs if para.text]) | |
| except Exception as e: | |
| # Handles cases where the file is corrupted or not a valid docx | |
| raise IOError( | |
| f"Could not read file: {os.path.basename(file_path)}. Error: {e}") | |
| def parse_pdf(file_path: str) -> str: | |
| """Extracts all text from a PDF document.""" | |
| try: | |
| doc = fitz.open(file_path) | |
| text = "" | |
| for page in doc: | |
| text += page.get_text() | |
| return text | |
| except Exception as e: | |
| raise IOError( | |
| f"Could not read PDF file: {os.path.basename(file_path)}. Error: {e}") | |
| class GeminiGrader: | |
| """Manages interaction with the Google Gemini API for grading.""" | |
| def __init__(self, api_key: str): | |
| """Initializes the Gemini model.""" | |
| try: | |
| genai.configure(api_key=api_key) | |
| # Configuration for safer, more deterministic output | |
| generation_config = { | |
| "temperature": 0.1, | |
| "top_p": 0.95, | |
| "top_k": 40, | |
| } | |
| # Safety settings to prevent the model from refusing to grade | |
| safety_settings = [ | |
| {"category": "HARM_CATEGORY_HARASSMENT", "threshold": "BLOCK_NONE"}, | |
| {"category": "HARM_CATEGORY_HATE_SPEECH", "threshold": "BLOCK_NONE"}, | |
| {"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", | |
| "threshold": "BLOCK_NONE"}, | |
| {"category": "HARM_CATEGORY_DANGEROUS_CONTENT", | |
| "threshold": "BLOCK_NONE"}, | |
| ] | |
| self.model = genai.GenerativeModel( | |
| model_name="gemini-1.5-pro-latest", | |
| generation_config=generation_config, | |
| safety_settings=safety_settings | |
| ) | |
| except Exception as e: | |
| raise ValueError(f"Failed to configure Gemini API: {e}") | |
| def grade_essay(self, essay_text: str, file_name: str) -> GradingResult: | |
| """ | |
| Sends the essay to Gemini for grading and parses the JSON response. | |
| This is a synchronous method designed to be run in a thread pool. | |
| """ | |
| # Inject the rubric and the example paper text into the main prompt template | |
| final_prompt = BASE_PROMPT_TEMPLATE.format( | |
| GRADING_RUBRIC=GRADING_RUBRIC, | |
| EXAMPLE_PAPER=example_paper_text | |
| ) | |
| prompt_with_essay = f"{GEMINI_PROMPT}\n{essay_text}" | |
| try: | |
| response = self.model.generate_content(prompt_with_essay) | |
| # Clean the response to ensure it's valid JSON | |
| cleaned_response = response.text.strip().replace("```json", "").replace("```", "") | |
| data = json.loads(cleaned_response) | |
| # Validate the structure of the returned JSON | |
| required_keys = ["finalGrade", | |
| "pointDeductions", "feedback", "summary"] | |
| if not all(key in data for key in required_keys): | |
| raise KeyError( | |
| "The model's response was missing one or more required keys.") | |
| return GradingResult( | |
| file_name=file_name, | |
| success=True, | |
| grade=data["finalGrade"], | |
| deductions=data["pointDeductions"], | |
| feedback=data["feedback"], | |
| summary=data["summary"] | |
| ) | |
| except json.JSONDecodeError: | |
| return GradingResult( | |
| file_name=file_name, | |
| success=False, | |
| error_message="Failed to parse the model's response. The output was not valid JSON." | |
| ) | |
| except Exception as e: | |
| return GradingResult( | |
| file_name=file_name, | |
| success=False, | |
| error_message=f"An API or model error occurred: {str(e)}" | |
| ) | |
| # --- Gradio Application --- | |
| async def grade_papers_concurrently( | |
| files: List[gr.File], example_paper_file: gr.File, api_key: str, progress=gr.Progress(track_tqdm=True) | |
| ) -> (str, str): | |
| """ | |
| The main asynchronous function that orchestrates the grading process. | |
| It's triggered by the Gradio button click. | |
| """ | |
| start_time = time.time() | |
| if not api_key: | |
| raise gr.Error("Google API Key is required.") | |
| if not files: | |
| raise gr.Error("Please upload at least one Word document.") | |
| # Process the optional example paper | |
| example_paper_text = "No example paper provided." | |
| if example_paper_file: | |
| try: | |
| progress(0, desc="Parsing example paper...") | |
| example_paper_text = EssayParser.parse_pdf(example_paper_file.name) | |
| except IOError as e: | |
| raise gr.Error(f"Failed to process example PDF: {e}") | |
| try: | |
| grader = GeminiGrader(api_key) | |
| except ValueError as e: | |
| raise gr.Error(str(e)) | |
| file_paths = [file.name for file in files] | |
| total_files = len(file_paths) | |
| # Use a ThreadPoolExecutor to run synchronous tasks concurrently | |
| with ThreadPoolExecutor(max_workers=10) as executor: | |
| # Create a future for each file processing task | |
| loop = asyncio.get_event_loop() | |
| tasks = [ | |
| loop.run_in_executor( | |
| executor, | |
| process_single_file, | |
| file_path, | |
| grader, | |
| example_paper_text | |
| ) | |
| for file_path in file_paths | |
| ] | |
| results = [] | |
| # Process results as they are completed | |
| for i, future in enumerate(asyncio.as_completed(tasks)): | |
| progress(i + 1, desc=f"Grading paper {i+1}/{total_files}...") | |
| result = await future | |
| results.append(result) | |
| # --- Format the final output --- | |
| successful_grades = [res for res in results if res.success] | |
| failed_grades = [res for res in results if not res.success] | |
| output_markdown = "" | |
| for result in successful_grades: | |
| output_markdown += f"### β Grade for: **{result.file_name}**\n" | |
| output_markdown += f"**Final Grade:** {result.grade}/100\n\n" | |
| # Format point deductions | |
| deductions_str = "" | |
| for category, points in result.deductions.items(): | |
| if points > 0: | |
| deductions_str += f"- **{category}:** Lost {points} points. *Reason: {result.feedback.get(category, 'N/A')}*\n" | |
| if not deductions_str: | |
| deductions_str = "Excellent work! No points were deducted.\n" | |
| output_markdown += "**Point Deductions Breakdown:**\n" + deductions_str + "\n" | |
| output_markdown += f"**Summary:** {result.summary}\n" | |
| output_markdown += "---\n" | |
| if failed_grades: | |
| output_markdown += "### β Failed Papers\n" | |
| for result in failed_grades: | |
| output_markdown += f"- **File:** {result.file_name}\n" | |
| output_markdown += f" - **Error:** {result.error_message}\n" | |
| output_markdown += "---\n" | |
| end_time = time.time() | |
| runtime = f"Total runtime: {end_time - start_time:.2f} seconds." | |
| status = ( | |
| f"Grading complete. {len(successful_grades)} papers graded successfully, " | |
| f"{len(failed_grades)} failed." | |
| ) | |
| return output_markdown, f"{status}\n{runtime}" | |
| def process_single_file(file_path: str, grader: GeminiGrader, example_paper_text: str) -> GradingResult: | |
| """ | |
| Synchronous wrapper function to parse and grade one file. | |
| This function is what runs in each thread of the ThreadPoolExecutor. | |
| """ | |
| file_name = os.path.basename(file_path) | |
| try: | |
| essay_text = EssayParser.parse_docx(file_path) | |
| if not essay_text.strip(): | |
| return GradingResult( | |
| file_name=file_name, | |
| success=False, | |
| error_message="The document is empty or contains no readable text." | |
| ) | |
| return grader.grade_essay(essay_text, file_name, example_paper_text) | |
| except Exception as e: | |
| return GradingResult(file_name=file_name, success=False, error_message=str(e)) | |
| # --- Build the Gradio Interface --- | |
| with gr.Blocks(theme=gr.themes.Soft(), title="Nursing Essay Grader") as demo: | |
| gr.Markdown( | |
| """ | |
| # π Gemini-Powered Nursing Essay Grader | |
| Upload one or more student essays in Word format (`.docx`) to have them graded by AI. | |
| 1. Enter your Google API Key (enabling the Gemini API in your Google Cloud project is required). | |
| 2. Upload the `.docx` files you want to grade. | |
| 3. Optionally, upload a single `.pdf` file as a "perfect" example for the AI to reference. | |
| 4. Click "Grade All Papers". The results will appear below. | |
| """ | |
| ) | |
| with gr.Row(): | |
| api_key_input = gr.Textbox( | |
| label="Google API Key", | |
| placeholder="Enter your Google API Key here", | |
| type="password", | |
| scale=1 | |
| ) | |
| with gr.Row(): | |
| file_uploads = gr.File( | |
| label="Upload Word Document Essays to Grade", | |
| file_count="multiple", | |
| file_types=[".docx"], | |
| type="filepath", | |
| scale=2 | |
| ) | |
| example_paper_upload = gr.File( | |
| label="Upload Example PDF Paper (Optional)", | |
| file_count="single", | |
| file_types=[".pdf"], | |
| type="filepath", | |
| scale=1 | |
| ) | |
| grade_button = gr.Button("π Grade All Papers", variant="primary") | |
| gr.Markdown("---") | |
| gr.Markdown("## π Grading Results") | |
| results_output = gr.Markdown(label="Formatted Grades") | |
| status_output = gr.Textbox( | |
| label="Runtime Status", | |
| lines=2, | |
| interactive=False | |
| ) | |
| grade_button.click( | |
| fn=grade_papers_concurrently, | |
| inputs=[file_uploads, example_paper_upload, api_key_input], | |
| outputs=[results_output, status_output] | |
| ) | |
| if __name__ == "__main__": | |
| demo.launch(debug=True) |