|
|
import gradio as gr |
|
|
from transformers import pipeline |
|
|
import difflib |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
print("Initializing model...") |
|
|
|
|
|
try: |
|
|
corrector = pipeline( |
|
|
"text2text-generation", |
|
|
model="HamadML/grammer_correction", |
|
|
device=-1 |
|
|
) |
|
|
print("Model loaded successfully.") |
|
|
except Exception as e: |
|
|
print(f"Error loading model: {e}") |
|
|
corrector = None |
|
|
|
|
|
|
|
|
|
|
|
def diff_texts(text1, text2): |
|
|
""" |
|
|
Compares two strings and returns HTML highlighting differences. |
|
|
Red strikethrough for deletions, Green bold for insertions. |
|
|
""" |
|
|
d = difflib.SequenceMatcher(None, text1, text2) |
|
|
html = [] |
|
|
for tag, i1, i2, j1, j2 in d.get_opcodes(): |
|
|
if tag == 'delete': |
|
|
|
|
|
html.append(f'<span style="color: #ef4444; text-decoration: line-through; background-color: #fee2e2; padding: 0 2px; border-radius: 2px;">{text1[i1:i2]}</span>') |
|
|
elif tag == 'insert': |
|
|
|
|
|
html.append(f'<span style="color: #16a34a; font-weight: bold; background-color: #dcfce7; padding: 0 2px; border-radius: 2px;">{text2[j1:j2]}</span>') |
|
|
elif tag == 'replace': |
|
|
|
|
|
html.append(f'<span style="color: #ef4444; text-decoration: line-through; background-color: #fee2e2; padding: 0 2px; border-radius: 2px;">{text1[i1:i2]}</span>') |
|
|
html.append(f'<span style="color: #16a34a; font-weight: bold; background-color: #dcfce7; padding: 0 2px; border-radius: 2px;">{text2[j1:j2]}</span>') |
|
|
else: |
|
|
|
|
|
html.append(text1[i1:i2]) |
|
|
return "".join(html) |
|
|
|
|
|
def calculate_rubric_score(original, corrected): |
|
|
""" |
|
|
Generates a simple score and feedback based on text similarity. |
|
|
""" |
|
|
matcher = difflib.SequenceMatcher(None, original, corrected) |
|
|
similarity = matcher.ratio() |
|
|
|
|
|
|
|
|
score = int(similarity * 100) |
|
|
|
|
|
if score == 100: |
|
|
feedback = "Perfect! Your grammar is flawless." |
|
|
color = "#16a34a" |
|
|
elif score >= 90: |
|
|
feedback = "Excellent work! Just a few minor tweaks needed." |
|
|
color = "#16a34a" |
|
|
elif score >= 70: |
|
|
feedback = "Good effort. You have some grammar errors to fix." |
|
|
color = "#ca8a04" |
|
|
else: |
|
|
feedback = "Needs improvement. Pay close attention to the corrections below." |
|
|
color = "#dc2626" |
|
|
|
|
|
return score, feedback, color |
|
|
|
|
|
|
|
|
def evaluate_text(text): |
|
|
if not text or not text.strip(): |
|
|
return "" |
|
|
|
|
|
if corrector is None: |
|
|
return "<p style='color:red;'>Error: The model failed to load.</p>" |
|
|
|
|
|
try: |
|
|
|
|
|
results = corrector(text, max_length=128) |
|
|
corrected_text = results[0]['generated_text'] |
|
|
|
|
|
|
|
|
diff_html = diff_texts(text, corrected_text) |
|
|
|
|
|
|
|
|
score, feedback, color = calculate_rubric_score(text, corrected_text) |
|
|
|
|
|
|
|
|
report_html = f""" |
|
|
<div style="font-family: sans-serif; padding: 24px; border: 1px solid #e5e7eb; border-radius: 12px; background: white; box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);"> |
|
|
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; border-bottom: 2px solid #f3f4f6; padding-bottom: 15px;"> |
|
|
<h2 style="margin: 0; color: #1f2937; font-size: 1.5em;">Teacher's Report</h2> |
|
|
<div style="background: {color}; color: white; padding: 8px 20px; border-radius: 99px; font-weight: bold; font-size: 1.2em;"> |
|
|
{score}/100 |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
<div style="margin-bottom: 25px;"> |
|
|
<p style="color: #6b7280; margin: 0 0 8px 0; font-size: 0.85em; text-transform: uppercase; letter-spacing: 0.1em; font-weight: bold;">Feedback</p> |
|
|
<p style="margin: 0; color: #374151; font-size: 1.1em; font-style: italic;">"{feedback}"</p> |
|
|
</div> |
|
|
|
|
|
<div> |
|
|
<p style="color: #6b7280; margin: 0 0 12px 0; font-size: 0.85em; text-transform: uppercase; letter-spacing: 0.1em; font-weight: bold;">Correction View</p> |
|
|
<div style="line-height: 1.8; font-size: 1.2em; color: #1f2937; background: #f9fafb; padding: 15px; border-radius: 8px; border: 1px solid #e5e7eb;"> |
|
|
{diff_html} |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
""" |
|
|
return report_html |
|
|
|
|
|
except Exception as e: |
|
|
return f"<p style='color:red;'>Error during processing: {str(e)}</p>" |
|
|
|
|
|
|
|
|
|
|
|
css = """ |
|
|
footer {display: none !important;} |
|
|
.api-link {display: none !important;} |
|
|
""" |
|
|
|
|
|
with gr.Blocks(title="Grammar Evaluator", theme=gr.themes.Soft(), css=css) as demo: |
|
|
gr.Markdown( |
|
|
""" |
|
|
# 📝 AI Grammar Tool (Helper) |
|
|
Type your sentence below. The AI will grade it, cross out mistakes in <span style='color: red; text-decoration: line-through;'>red</span>, and write corrections in <span style='color: green; font-weight: bold;'>green</span>. |
|
|
""" |
|
|
) |
|
|
|
|
|
|
|
|
input_box = gr.Textbox( |
|
|
label="Student Writing", |
|
|
placeholder="Example: I has went to the store yesterday...", |
|
|
lines=5 |
|
|
) |
|
|
|
|
|
submit_btn = gr.Button("Check My Text", variant="primary", size="lg") |
|
|
|
|
|
output_html = gr.HTML(label="Evaluation Report") |
|
|
|
|
|
submit_btn.click(fn=evaluate_text, inputs=input_box, outputs=output_html) |
|
|
input_box.submit(fn=evaluate_text, inputs=input_box, outputs=output_html) |
|
|
|
|
|
if __name__ == "__main__": |
|
|
demo.launch() |