File size: 6,007 Bytes
7dc1531
 
7565dd4
7dc1531
 
 
f684b64
7dc1531
 
 
 
 
 
 
 
 
 
 
 
 
7565dd4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7dc1531
7565dd4
7dc1531
 
 
 
7565dd4
7dc1531
 
7565dd4
7dc1531
 
7565dd4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7dc1531
7565dd4
7dc1531
 
b55addf
7565dd4
 
b55addf
7565dd4
 
 
7dc1531
 
b55addf
7565dd4
7dc1531
 
 
b55addf
 
 
 
 
 
 
 
 
 
7dc1531
7565dd4
 
7dc1531
 
b55addf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
import gradio as gr
from transformers import pipeline
import difflib

# --- Model Loading ---
# We use the 'text2text-generation' pipeline. 
# device=-1 forces CPU usage, which is required for the free tier.
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

# --- Helper Functions for Scoring & Visuals ---

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':
            # Mistake: Red strikethrough
            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':
            # Correction: Green bold
            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':
            # Mistake -> Correction
            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:
            # Unchanged text
            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() # 0.0 to 1.0
    
    # Calculate score out of 100
    score = int(similarity * 100)
    
    if score == 100:
        feedback = "Perfect! Your grammar is flawless."
        color = "#16a34a" # Green
    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" # Yellow/Orange
    else:
        feedback = "Needs improvement. Pay close attention to the corrections below."
        color = "#dc2626" # Red
        
    return score, feedback, color

# --- Core Logic ---
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:
        # 1. Get corrected text from AI
        results = corrector(text, max_length=128)
        corrected_text = results[0]['generated_text']
        
        # 2. Generate Visual Diff
        diff_html = diff_texts(text, corrected_text)
        
        # 3. Calculate Score
        score, feedback, color = calculate_rubric_score(text, corrected_text)
        
        # 4. Construct HTML Report
        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>"

# --- User Interface ---
# CSS to hide footer and API links visually
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>.
        """
    )
    
    # Vertical Layout
    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()