Spaces:
Sleeping
Sleeping
adding app file
Browse files
app.py
ADDED
@@ -0,0 +1,110 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import gradio as gr
|
2 |
+
import pandas as pd
|
3 |
+
import base64
|
4 |
+
import os
|
5 |
+
from openai import OpenAI
|
6 |
+
|
7 |
+
client = OpenAI()
|
8 |
+
|
9 |
+
def process_excel_file(file_path, non_question_columns_str):
|
10 |
+
# Load the Excel file into a DataFrame
|
11 |
+
df = pd.read_excel(file_path, header=0, index_col=None)
|
12 |
+
|
13 |
+
# Convert non-question columns string to a list and make it lowercase for comparison
|
14 |
+
non_question_columns = [col.strip().lower() for col in non_question_columns_str.split(',')]
|
15 |
+
# Identify columns that are considered as questions and non-questions
|
16 |
+
question_columns = [col for col in df.columns if col.lower() not in non_question_columns]
|
17 |
+
non_question_data = df[[col for col in df.columns if col.lower() in non_question_columns]]
|
18 |
+
|
19 |
+
# Filter the DataFrame to include only question columns
|
20 |
+
df_questions = df[question_columns]
|
21 |
+
# Drop Timestamp column
|
22 |
+
df_questions.drop(columns=["Timestamp"], inplace=True)
|
23 |
+
|
24 |
+
|
25 |
+
# Extract headers as questions
|
26 |
+
questions = list(df_questions.columns)
|
27 |
+
|
28 |
+
# Extract the last row as answer keys
|
29 |
+
answer_keys = df_questions.iloc[-1].to_dict()
|
30 |
+
|
31 |
+
# Extract participant answers (excluding the last row which is the answer keys)
|
32 |
+
participant_answers = df_questions.iloc[:-1]
|
33 |
+
|
34 |
+
return questions, answer_keys, participant_answers, non_question_data
|
35 |
+
|
36 |
+
def process_and_grade(file_path, non_question_columns_str):
|
37 |
+
questions, answer_keys, participant_answers, non_question_data = process_excel_file(file_path, non_question_columns_str)
|
38 |
+
|
39 |
+
# Initialize columns for individual question scores based on numeric indices and total score
|
40 |
+
num_questions = len(questions)
|
41 |
+
for i in range(num_questions):
|
42 |
+
participant_answers[f"Q{i+1} Score"] = 0 # Creates score columns .
|
43 |
+
participant_answers['Total Points'] = 0
|
44 |
+
participant_answers['Grade'] = 0
|
45 |
+
|
46 |
+
# Grade each participant's answers and calculate total score
|
47 |
+
for index, row in participant_answers.iterrows():
|
48 |
+
total_score = 0
|
49 |
+
for i, question in enumerate(questions, start=1):
|
50 |
+
participant_answer = row[question]
|
51 |
+
correct_answer = answer_keys[question]
|
52 |
+
score = grade_answer(question, participant_answer, correct_answer)
|
53 |
+
participant_answers.at[index, f"Q{i} Score"] = score # Update score using numeric index
|
54 |
+
total_score += score
|
55 |
+
participant_answers.at[index, 'Total Points'] = total_score # Update total points
|
56 |
+
participant_answers.at[index, 'Grade'] = (total_score/(num_questions*2))*100
|
57 |
+
|
58 |
+
# Concatenate non-question data with updated participant answers for final DataFrame
|
59 |
+
final_df = pd.concat([non_question_data.iloc[:-1].reset_index(drop=True), participant_answers.reset_index(drop=True)], axis=1)
|
60 |
+
|
61 |
+
# Save to a new Excel file
|
62 |
+
output_file_path = "graded_results.xlsx"
|
63 |
+
final_df.to_excel(output_file_path, index=False)
|
64 |
+
|
65 |
+
return output_file_path
|
66 |
+
|
67 |
+
|
68 |
+
def grade_answer(question, participant_answer, key_answer):
|
69 |
+
"""
|
70 |
+
Call the fine-tuned model to grade an answer based on the question,
|
71 |
+
the participant's answer, and the key answer.
|
72 |
+
"""
|
73 |
+
if participant_answer.strip() == "-" or participant_answer.strip() == "":
|
74 |
+
return 0
|
75 |
+
|
76 |
+
task="Evaluate the correctness of a participant's answer compared to the intended answer"
|
77 |
+
prompt = f"{task}, Question: {question}\nIntended Answer: {key_answer}\nParticipant Answer: {participant_answer}\n"
|
78 |
+
|
79 |
+
|
80 |
+
response = client.completions.create(
|
81 |
+
model=os.environ['model_ft_id'],
|
82 |
+
prompt=prompt,
|
83 |
+
max_tokens=1,
|
84 |
+
temperature=0,
|
85 |
+
)
|
86 |
+
|
87 |
+
# Assuming the model's response is directly the score (0, 1, or 2)
|
88 |
+
try:
|
89 |
+
score = int(response.choices[0].text.strip())
|
90 |
+
return score
|
91 |
+
except ValueError:
|
92 |
+
# Handle unexpected model response
|
93 |
+
return 0
|
94 |
+
|
95 |
+
|
96 |
+
# Set up the Gradio interface
|
97 |
+
iface = gr.Interface(
|
98 |
+
fn=process_and_grade,
|
99 |
+
inputs=[
|
100 |
+
gr.File(file_count="single", type="filepath"),
|
101 |
+
gr.Textbox(lines=2, placeholder="Column1, Column2, Column3, ...", label="Non-Question Columns"),
|
102 |
+
# Remove model_id if it's set globally or passed in another way
|
103 |
+
],
|
104 |
+
outputs=gr.File(label="Download Graded Results"),
|
105 |
+
title="Essay Question Grading",
|
106 |
+
description="Upload a spreadsheet and specify non-question columns (separated by commas) to grade. Format your Excel file with the 1st row for questions and the last row for key answers.",
|
107 |
+
allow_flagging="never"
|
108 |
+
)
|
109 |
+
|
110 |
+
iface.launch()
|