| | import gradio as gr |
| | from transformers import AutoModelForSequenceClassification, AutoTokenizer |
| | import torch |
| | import numpy as np |
| |
|
| | |
| | |
| | |
| | MODEL_NAME = "JacobLinCool/IELTS_essay_scoring_safetensors" |
| |
|
| | model = AutoModelForSequenceClassification.from_pretrained(MODEL_NAME) |
| | tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME) |
| |
|
| | model.eval() |
| |
|
| | |
| | |
| | |
| | def score_essay(essay: str): |
| | if not essay.strip(): |
| | return { |
| | "Task Achievement": 0.0, |
| | "Coherence & Cohesion": 0.0, |
| | "Vocabulary": 0.0, |
| | "Grammar": 0.0, |
| | "Overall": 0.0, |
| | "Feedback": "Please write an essay to get a score." |
| | } |
| |
|
| | |
| | inputs = tokenizer( |
| | essay, |
| | return_tensors="pt", |
| | truncation=True, |
| | max_length=512 |
| | ) |
| |
|
| | |
| | with torch.no_grad(): |
| | outputs = model(**inputs) |
| |
|
| | preds = outputs.logits.squeeze().cpu().numpy() |
| |
|
| | |
| | |
| | |
| | scores = preds.copy() |
| | for i in range(len(scores)): |
| | if scores[i] < 4.0: |
| | scores[i] = scores[i]*1.25 + 0.3 |
| | elif scores[i] < 6.0: |
| | scores[i] = scores[i]*1.1 + 0.2 |
| | elif scores[i] < 8.0: |
| | scores[i] = scores[i]*1.05 + 0.1 |
| | else: |
| | scores[i] = scores[i] |
| |
|
| | |
| | |
| | |
| | wc = len(essay.split()) |
| | if wc >= 250: |
| | scores += 0.3 |
| | elif wc >= 200: |
| | scores += 0.15 |
| |
|
| | |
| | |
| | |
| | scores = np.clip(scores, 0, 9) |
| | rounded = np.round(scores * 2) / 2 |
| |
|
| | ta, cc, vocab, gram, overall_dummy = rounded |
| |
|
| | |
| | |
| | |
| | overall = 0.3*ta + 0.25*cc + 0.2*vocab + 0.25*gram |
| | overall = np.clip(overall, 0, 9) |
| | overall = np.round(overall * 2) / 2 |
| | rounded[-1] = overall |
| |
|
| | labels = ["Task Achievement", "Coherence & Cohesion", "Vocabulary", "Grammar", "Overall"] |
| |
|
| | |
| | |
| | |
| | feedback_lines = [] |
| |
|
| | if ta < 5: |
| | feedback_lines.append("Task: Ideas are underdeveloped; give examples and elaboration.") |
| | if cc < 5: |
| | feedback_lines.append("Coherence: Improve transitions; use connectors like 'however', 'moreover'.") |
| | if vocab < 5: |
| | feedback_lines.append("Vocabulary: Use a wider range of words and avoid repetition.") |
| | if gram < 5: |
| | feedback_lines.append("Grammar: Check articles, plurals, tenses, and sentence structures.") |
| | if overall >= 5: |
| | feedback_lines.append("Overall: Good attempt! Refine grammar and vocabulary to increase your band.") |
| |
|
| | feedback = "\n".join(feedback_lines[:4]) |
| |
|
| | result = {label: float(score) for label, score in zip(labels, rounded)} |
| | result["Feedback"] = feedback |
| | return result |
| |
|
| | |
| | |
| | |
| | with gr.Blocks() as demo: |
| | gr.Markdown("## 📝 Refined Automated IELTS Writing Scorer") |
| | gr.Markdown( |
| | "Paste your IELTS Task 2 essay below. " |
| | "The system estimates band scores with mini feedback." |
| | ) |
| |
|
| | essay_input = gr.Textbox( |
| | lines=12, |
| | placeholder="Paste your IELTS essay here..." |
| | ) |
| |
|
| | score_output = gr.JSON(label="Estimated IELTS Band Scores + Feedback") |
| |
|
| | submit_btn = gr.Button("Score Essay") |
| | submit_btn.click( |
| | fn=score_essay, |
| | inputs=essay_input, |
| | outputs=score_output |
| | ) |
| |
|
| | gr.Markdown( |
| | "⚠️ Note: AI-based estimator; not an official IELTS score." |
| | ) |
| |
|
| | |
| | |
| | |
| | demo.launch() |
| |
|