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 # Initialize sentence transformer model model1 = SentenceTransformer('sentence-transformers/all-MiniLM-L6-v2') # Initialize Groq client client = Groq(api_key=os.environ.get("GROQ_API_KEY")) # System prompt for Groq system_prompt = { "role": "system", "content": "You are a useful assistant. You reply with efficient answers." } # Function to interact with Groq for generating response 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 # Extract text from an image using Tesseract def extract_text_from_image(filepath: str, languages: List[str]): image = Image.open(filepath) lang_str = '+'.join(languages) # Join languages for Tesseract return pytesseract.image_to_string(image=image, lang=lang_str) # Function to get embeddings for text using SentenceTransformer def get_embedding(text): return model1.encode(text, convert_to_tensor=True) # Calculate similarity between two texts using cosine similarity def calculate_similarity(text1, text2): embedding1 = get_embedding(text1) embedding2 = get_embedding(text2) similarity = util.pytorch_cos_sim(embedding1, embedding2) return similarity.item() # Assign badges based on the grade 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 💪" # Generate visual feedback by comparing answers 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 # Categorize feedback into clarity, completeness, and accuracy 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"} # Assign grades based on similarity score 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 # Function to evaluate student's answer by comparing it to a model answer 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 # Main interface function for Gradio 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 # Get the Groq response return grade, similarity_score, feedback, visual_feedback, badge, detailed_feedback_msg, response # Get available Tesseract languages language_choices = pytesseract.get_languages() # Define Gradio interface 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()