|
import os |
|
import difflib |
|
from groq import Groq |
|
import gradio as gr |
|
from transformers import pipeline |
|
import pytesseract |
|
from sentence_transformers import SentenceTransformer, util |
|
from PIL import Image |
|
from typing import List |
|
import requests |
|
|
|
|
|
model1 = SentenceTransformer('sentence-transformers/all-MiniLM-L6-v2') |
|
|
|
|
|
client = Groq(api_key=os.environ.get("GROQ_API_KEY")) |
|
|
|
|
|
system_prompt = { |
|
"role": "system", |
|
"content": "You are a useful assistant. You reply with efficient answers." |
|
} |
|
|
|
|
|
async def chat_groq(message, history): |
|
messages = [system_prompt] |
|
|
|
for msg in history: |
|
messages.append({"role": "user", "content": str(msg[0])}) |
|
messages.append({"role": "assistant", "content": str(msg[1])}) |
|
|
|
messages.append({"role": "user", "content": str(message)}) |
|
|
|
response_content = '' |
|
|
|
stream = client.chat.completions.create( |
|
model="llama3-70b-8192", |
|
messages=messages, |
|
max_tokens=1024, |
|
temperature=1.3, |
|
stream=True |
|
) |
|
|
|
for chunk in stream: |
|
content = chunk.choices[0].delta.content |
|
if content: |
|
response_content += chunk.choices[0].delta.content |
|
yield response_content |
|
|
|
|
|
def extract_text_from_image(filepath: str, languages: List[str]): |
|
image = Image.open(filepath) |
|
lang_str = '+'.join(languages) |
|
return pytesseract.image_to_string(image=image, lang=lang_str) |
|
|
|
|
|
def get_embedding(text): |
|
return model1.encode(text, convert_to_tensor=True) |
|
|
|
|
|
def calculate_similarity(text1, text2): |
|
embedding1 = get_embedding(text1) |
|
embedding2 = get_embedding(text2) |
|
similarity = util.pytorch_cos_sim(embedding1, embedding2) |
|
return similarity.item() |
|
|
|
|
|
def assign_badge(grade): |
|
if grade == 5: |
|
return "Gold Badge π" |
|
elif grade == 4: |
|
return "Silver Badge π₯" |
|
elif grade == 3: |
|
return "Bronze Badge π₯" |
|
else: |
|
return "Keep Improving Badge πͺ" |
|
|
|
|
|
def generate_visual_feedback(student_answer, model_answer): |
|
diff = difflib.ndiff(student_answer.split(), model_answer.split()) |
|
highlighted_diff = ' '.join( |
|
[f"**{word}**" if word.startswith('-') else word for word in diff if not word.startswith('?')] |
|
) |
|
return highlighted_diff |
|
|
|
|
|
def detailed_feedback(similarity_score): |
|
if similarity_score >= 0.9: |
|
return {"Clarity": "Excellent", "Completeness": "Complete", "Accuracy": "Accurate"} |
|
elif similarity_score >= 0.8: |
|
return {"Clarity": "Good", "Completeness": "Almost Complete", "Accuracy": "Mostly Accurate"} |
|
elif similarity_score >= 0.7: |
|
return {"Clarity": "Fair", "Completeness": "Partial", "Accuracy": "Some Errors"} |
|
else: |
|
return {"Clarity": "Needs Improvement", "Completeness": "Incomplete", "Accuracy": "Inaccurate"} |
|
|
|
|
|
def get_grade(similarity_score): |
|
if similarity_score >= 0.9: |
|
return 5 |
|
elif similarity_score >= 0.8: |
|
return 4 |
|
elif similarity_score >= 0.7: |
|
return 3 |
|
elif similarity_score >= 0.6: |
|
return 2 |
|
else: |
|
return 1 |
|
|
|
|
|
def evaluate_answer(image, languages, model_answer): |
|
student_answer = extract_text_from_image(image, languages) |
|
similarity_score = calculate_similarity(student_answer, model_answer) |
|
grade = get_grade(similarity_score) |
|
feedback = f"Student's answer: {student_answer}\nTeacher's answer: {model_answer}" |
|
visual_feedback = generate_visual_feedback(student_answer, model_answer) |
|
badge = assign_badge(grade) |
|
detailed_feedback_msg = detailed_feedback(similarity_score) |
|
prompt = f"The student got grade: {grade} when the student's answer is: {student_answer} and the teacher's answer is: {model_answer}. Justify the grade given to the student." |
|
return grade, similarity_score * 100, feedback, visual_feedback, badge, detailed_feedback_msg, prompt |
|
|
|
|
|
async def gradio_interface(image, languages: List[str], model_answer, prompt="", history=[]): |
|
grade, similarity_score, feedback, visual_feedback, badge, detailed_feedback_msg, prompt = evaluate_answer(image, languages, model_answer) |
|
response = "" |
|
async for result in chat_groq(prompt, history): |
|
response = result |
|
return grade, similarity_score, feedback, visual_feedback, badge, detailed_feedback_msg, response |
|
|
|
|
|
language_choices = pytesseract.get_languages() |
|
|
|
|
|
interface = gr.Interface( |
|
fn=gradio_interface, |
|
inputs=[ |
|
gr.Image(type="filepath", label="Input"), |
|
gr.CheckboxGroup(language_choices, type="value", value=['eng'], label='Language'), |
|
gr.Textbox(lines=2, placeholder="Enter your model answer here", label="Model Answer"), |
|
gr.Textbox(lines=2, placeholder="Enter your prompt here", label="Prompt") |
|
], |
|
outputs=[ |
|
gr.Text(label="Grade"), |
|
gr.Number(label="Similarity Score (%)"), |
|
gr.Text(label="Feedback"), |
|
gr.HTML(label="Visual Feedback"), |
|
gr.Text(label="Badge"), |
|
gr.JSON(label="Detailed Feedback"), |
|
gr.Text(label="Generated Response") |
|
], |
|
title="Enhanced Automated Grading System", |
|
description="Upload an image of your answer sheet to get a grade from 1 to 5, similarity score, visual feedback, badge, and detailed feedback based on the model answer.", |
|
live=True |
|
) |
|
|
|
if __name__ == "__main__": |
|
interface.queue() |
|
interface.launch() |
|
|