Zlovoblachko commited on
Commit
66bc07b
Β·
1 Parent(s): 638736c

initial commit

Browse files
Files changed (3) hide show
  1. README.md +53 -8
  2. app.py +498 -0
  3. requirements.txt +6 -0
README.md CHANGED
@@ -1,14 +1,59 @@
1
  ---
2
- title: Lang Learn App
3
- emoji: πŸ‘€
4
- colorFrom: green
5
- colorTo: blue
6
  sdk: gradio
7
- sdk_version: 5.31.0
8
  app_file: app.py
9
  pinned: false
10
- license: cc-by-4.0
11
- short_description: An application prototype
12
  ---
13
 
14
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  ---
2
+ title: Language Learning App - Grammar Checker
3
+ emoji: πŸŽ“
4
+ colorFrom: blue
5
+ colorTo: green
6
  sdk: gradio
7
+ sdk_version: 4.15.0
8
  app_file: app.py
9
  pinned: false
10
+ license: mit
 
11
  ---
12
 
13
+ # Language Learning Application - Grammar Checker
14
+
15
+ An AI-powered language learning application that provides:
16
+
17
+ ## Features
18
+
19
+ - **πŸ“ Writing Analysis**: Submit your writing for automated grammar checking and error correction
20
+ - **πŸ‹οΈ Exercise Creation**: Generate grammar exercises from text containing errors
21
+ - **✏️ Exercise Practice**: Practice with generated exercises and get scored feedback
22
+ - **πŸ“Š Progress Tracking**: Track student progress across submissions and exercises
23
+
24
+ ## How to Use
25
+
26
+ ### For Students:
27
+ 1. **Writing Analysis**: Enter your name and paste your writing in the "Writing Analysis" tab
28
+ 2. **Exercise Practice**: Use exercise IDs to practice grammar exercises
29
+ 3. **View Progress**: Check your improvement over time
30
+
31
+ ### For Teachers:
32
+ 1. **Create Exercises**: Use the "Exercise Creation" tab to generate exercises from error-containing text
33
+ 2. **Monitor Progress**: Track student submissions and exercise performance
34
+ 3. **Assign Practice**: Share exercise IDs with students for targeted practice
35
+
36
+ ## Technology
37
+
38
+ - **Neural Networks**: Uses advanced T5 and ELECTRA models for grammar error detection and correction
39
+ - **Models**:
40
+ - `Zlovoblachko/Realec-2step-ft-realec` for grammar correction
41
+ - `Zlovoblachko/4tag-electra-grammar-error-detection` for error detection
42
+ - **Database**: SQLite for storing submissions, exercises, and progress
43
+ - **Interface**: Gradio for easy-to-use web interface
44
+
45
+ ## Example Usage
46
+
47
+ 1. **Submit Writing**: "I have went to the store yesterday" β†’ "I went to the store yesterday"
48
+ 2. **Create Exercise**: Input text with errors β†’ Get numbered sentences for practice
49
+ 3. **Practice**: Correct the sentences β†’ Get immediate feedback and scoring
50
+
51
+ ## Educational Value
52
+
53
+ This application helps language learners by:
54
+ - Providing immediate feedback on grammar errors
55
+ - Creating personalized practice exercises
56
+ - Tracking learning progress over time
57
+ - Offering detailed error analysis and corrections
58
+
59
+ Perfect for ESL students, writing practice, and grammar skill development!
app.py ADDED
@@ -0,0 +1,498 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import sqlite3
3
+ import json
4
+ import os
5
+ from datetime import datetime
6
+ import torch
7
+ import nltk
8
+ from transformers import AutoModelForSeq2SeqLM, AutoTokenizer, ElectraTokenizer, ElectraForTokenClassification
9
+ import torch.nn as nn
10
+
11
+ # Download NLTK data
12
+ try:
13
+ nltk.data.find('tokenizers/punkt')
14
+ except LookupError:
15
+ nltk.download('punkt')
16
+
17
+ # Initialize SQLite database for storing submissions and exercises
18
+ def init_database():
19
+ conn = sqlite3.connect('language_app.db')
20
+ c = conn.cursor()
21
+
22
+ # Users table
23
+ c.execute('''CREATE TABLE IF NOT EXISTS users (
24
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
25
+ username TEXT UNIQUE NOT NULL,
26
+ email TEXT UNIQUE NOT NULL,
27
+ role TEXT NOT NULL,
28
+ password_hash TEXT NOT NULL,
29
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
30
+ )''')
31
+
32
+ # Tasks table
33
+ c.execute('''CREATE TABLE IF NOT EXISTS tasks (
34
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
35
+ title TEXT NOT NULL,
36
+ description TEXT NOT NULL,
37
+ image_url TEXT,
38
+ creator_id INTEGER,
39
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
40
+ )''')
41
+
42
+ # Submissions table
43
+ c.execute('''CREATE TABLE IF NOT EXISTS submissions (
44
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
45
+ task_id INTEGER,
46
+ student_name TEXT NOT NULL,
47
+ content TEXT NOT NULL,
48
+ analysis_result TEXT,
49
+ analysis_html TEXT,
50
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
51
+ )''')
52
+
53
+ # Exercises table
54
+ c.execute('''CREATE TABLE IF NOT EXISTS exercises (
55
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
56
+ title TEXT NOT NULL,
57
+ instructions TEXT NOT NULL,
58
+ sentences TEXT NOT NULL,
59
+ image_url TEXT,
60
+ submission_id INTEGER,
61
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
62
+ )''')
63
+
64
+ # Exercise attempts table
65
+ c.execute('''CREATE TABLE IF NOT EXISTS exercise_attempts (
66
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
67
+ exercise_id INTEGER,
68
+ student_name TEXT NOT NULL,
69
+ responses TEXT NOT NULL,
70
+ score REAL,
71
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
72
+ )''')
73
+
74
+ conn.commit()
75
+ conn.close()
76
+
77
+ # Neural Network Model (simplified version of your existing model)
78
+ class SimpleGrammarChecker:
79
+ def __init__(self):
80
+ self.model_name = "Zlovoblachko/Realec-2step-ft-realec"
81
+ self.ged_model_name = "Zlovoblachko/4tag-electra-grammar-error-detection"
82
+ self.load_models()
83
+
84
+ def load_models(self):
85
+ try:
86
+ # Load T5 model
87
+ self.tokenizer = AutoTokenizer.from_pretrained(self.model_name)
88
+ self.model = AutoModelForSeq2SeqLM.from_pretrained(self.model_name)
89
+
90
+ # Load GED model
91
+ self.ged_tokenizer = ElectraTokenizer.from_pretrained(self.ged_model_name)
92
+ self.ged_model = ElectraForTokenClassification.from_pretrained(self.ged_model_name)
93
+
94
+ print("Models loaded successfully!")
95
+ except Exception as e:
96
+ print(f"Error loading models: {e}")
97
+ self.model = None
98
+ self.ged_model = None
99
+
100
+ def analyze_text(self, text):
101
+ if not self.model or not text.strip():
102
+ return "Model not available or empty text", ""
103
+
104
+ try:
105
+ # Tokenize and generate correction
106
+ inputs = self.tokenizer(text, return_tensors="pt", truncation=True, max_length=512)
107
+
108
+ with torch.no_grad():
109
+ outputs = self.model.generate(
110
+ input_ids=inputs.input_ids,
111
+ attention_mask=inputs.attention_mask,
112
+ max_length=512,
113
+ num_beams=4,
114
+ early_stopping=True
115
+ )
116
+
117
+ corrected_text = self.tokenizer.decode(outputs[0], skip_special_tokens=True)
118
+
119
+ # Get GED predictions if available
120
+ error_spans = []
121
+ if self.ged_model:
122
+ error_spans = self.get_error_spans(text)
123
+
124
+ # Generate HTML output
125
+ html_output = self.generate_html_analysis(text, corrected_text, error_spans)
126
+
127
+ return corrected_text, html_output
128
+
129
+ except Exception as e:
130
+ return f"Error during analysis: {str(e)}", ""
131
+
132
+ def get_error_spans(self, text):
133
+ try:
134
+ inputs = self.ged_tokenizer(text, return_tensors="pt", truncation=True, padding=True)
135
+
136
+ with torch.no_grad():
137
+ outputs = self.ged_model(**inputs)
138
+ predictions = torch.argmax(outputs.logits, dim=2)
139
+
140
+ tokens = self.ged_tokenizer.convert_ids_to_tokens(inputs.input_ids[0])
141
+ token_predictions = predictions[0].cpu().numpy().tolist()
142
+
143
+ error_spans = []
144
+ for i, (token, pred) in enumerate(zip(tokens, token_predictions)):
145
+ if token.startswith("##") or token in ["[CLS]", "[SEP]", "[PAD]"]:
146
+ continue
147
+ if pred != 0: # 0 is correct, 1=R, 2=M, 3=U
148
+ error_type = ["C", "R", "M", "U"][pred]
149
+ error_spans.append({"token": token, "type": error_type, "position": i})
150
+
151
+ return error_spans
152
+ except:
153
+ return []
154
+
155
+ def generate_html_analysis(self, original, corrected, error_spans):
156
+ html = f"""
157
+ <div style='font-family: Arial, sans-serif; line-height: 1.6; padding: 20px; border: 1px solid #ddd; border-radius: 8px; background-color: #f9f9f9;'>
158
+ <h3 style='color: #333; margin-top: 0;'>Grammar Analysis Results</h3>
159
+
160
+ <div style='margin: 15px 0;'>
161
+ <h4 style='color: #555;'>Original Text:</h4>
162
+ <p style='padding: 10px; background-color: #fff; border: 1px solid #ddd; border-radius: 4px;'>{original}</p>
163
+ </div>
164
+
165
+ <div style='margin: 15px 0;'>
166
+ <h4 style='color: #28a745;'>Corrected Text:</h4>
167
+ <p style='padding: 10px; background-color: #d4edda; border: 1px solid #c3e6cb; border-radius: 4px;'>{corrected}</p>
168
+ </div>
169
+
170
+ <div style='margin: 15px 0;'>
171
+ <h4 style='color: #333;'>Error Analysis:</h4>
172
+ <p style='color: #666;'>Found {len(error_spans)} potential errors</p>
173
+ </div>
174
+ </div>
175
+ """
176
+ return html
177
+
178
+ # Initialize components
179
+ init_database()
180
+ grammar_checker = SimpleGrammarChecker()
181
+
182
+ # Gradio Interface Functions
183
+ def analyze_student_writing(text, student_name, task_title="General Writing Task"):
184
+ """Analyze student writing and store in database"""
185
+ if not text.strip():
186
+ return "Please enter some text to analyze.", ""
187
+
188
+ if not student_name.strip():
189
+ return "Please enter your name.", ""
190
+
191
+ # Analyze text
192
+ corrected_text, html_analysis = grammar_checker.analyze_text(text)
193
+
194
+ # Store in database
195
+ conn = sqlite3.connect('language_app.db')
196
+ c = conn.cursor()
197
+
198
+ # Insert task if not exists
199
+ c.execute("INSERT OR IGNORE INTO tasks (title, description) VALUES (?, ?)",
200
+ (task_title, f"Writing task: {task_title}"))
201
+
202
+ c.execute("SELECT id FROM tasks WHERE title = ?", (task_title,))
203
+ task_id = c.fetchone()[0]
204
+
205
+ # Insert submission
206
+ analysis_data = {
207
+ "corrected_text": corrected_text,
208
+ "original_text": text,
209
+ "html_output": html_analysis
210
+ }
211
+
212
+ c.execute("""INSERT INTO submissions (task_id, student_name, content, analysis_result, analysis_html)
213
+ VALUES (?, ?, ?, ?, ?)""",
214
+ (task_id, student_name, text, json.dumps(analysis_data), html_analysis))
215
+
216
+ submission_id = c.lastrowid
217
+ conn.commit()
218
+ conn.close()
219
+
220
+ return corrected_text, html_analysis
221
+
222
+ def create_exercise_from_text(text, exercise_title="Grammar Exercise"):
223
+ """Create an exercise from text with errors"""
224
+ if not text.strip():
225
+ return "Please enter text to create an exercise.", ""
226
+
227
+ # Analyze text to find sentences with errors
228
+ sentences = nltk.sent_tokenize(text)
229
+ exercise_sentences = []
230
+
231
+ for sentence in sentences:
232
+ corrected, _ = grammar_checker.analyze_text(sentence)
233
+ if sentence.strip() != corrected.strip(): # Has errors
234
+ exercise_sentences.append({
235
+ "original": sentence.strip(),
236
+ "corrected": corrected.strip()
237
+ })
238
+
239
+ if not exercise_sentences:
240
+ return "No errors found in the text. Cannot create exercise.", ""
241
+
242
+ # Store exercise in database
243
+ conn = sqlite3.connect('language_app.db')
244
+ c = conn.cursor()
245
+
246
+ c.execute("""INSERT INTO exercises (title, instructions, sentences)
247
+ VALUES (?, ?, ?)""",
248
+ (exercise_title,
249
+ "Correct the grammatical errors in the following sentences:",
250
+ json.dumps(exercise_sentences)))
251
+
252
+ exercise_id = c.lastrowid
253
+ conn.commit()
254
+ conn.close()
255
+
256
+ # Generate exercise HTML
257
+ exercise_html = f"""
258
+ <div style='font-family: Arial, sans-serif; padding: 20px; border: 1px solid #ddd; border-radius: 8px;'>
259
+ <h3>{exercise_title}</h3>
260
+ <p><strong>Instructions:</strong> Correct the grammatical errors in the following sentences:</p>
261
+ <ol>
262
+ """
263
+
264
+ for i, sentence_data in enumerate(exercise_sentences, 1):
265
+ exercise_html += f"<li style='margin: 10px 0; padding: 10px; background-color: #f8f9fa; border-radius: 4px;'>{sentence_data['original']}</li>"
266
+
267
+ exercise_html += "</ol></div>"
268
+
269
+ return f"Exercise created with {len(exercise_sentences)} sentences!", exercise_html
270
+
271
+ def attempt_exercise(exercise_id, student_responses, student_name):
272
+ """Submit exercise attempt and get score"""
273
+ if not student_name.strip():
274
+ return "Please enter your name.", ""
275
+
276
+ try:
277
+ exercise_id = int(exercise_id)
278
+ except:
279
+ return "Please enter a valid exercise ID.", ""
280
+
281
+ # Get exercise from database
282
+ conn = sqlite3.connect('language_app.db')
283
+ c = conn.cursor()
284
+
285
+ c.execute("SELECT sentences FROM exercises WHERE id = ?", (exercise_id,))
286
+ result = c.fetchone()
287
+
288
+ if not result:
289
+ return "Exercise not found.", ""
290
+
291
+ exercise_sentences = json.loads(result[0])
292
+
293
+ # Parse student responses
294
+ responses = [r.strip() for r in student_responses.split('\n') if r.strip()]
295
+
296
+ if len(responses) != len(exercise_sentences):
297
+ return f"Please provide exactly {len(exercise_sentences)} responses (one per line).", ""
298
+
299
+ # Calculate score
300
+ correct_count = 0
301
+ feedback = []
302
+
303
+ for i, (sentence_data, response) in enumerate(zip(exercise_sentences, responses), 1):
304
+ correct_answer = sentence_data['corrected']
305
+ is_correct = response.lower().strip() == correct_answer.lower().strip()
306
+
307
+ if is_correct:
308
+ correct_count += 1
309
+ feedback.append(f"βœ… Sentence {i}: Correct!")
310
+ else:
311
+ feedback.append(f"❌ Sentence {i}: Your answer: '{response}' | Correct answer: '{correct_answer}'")
312
+
313
+ score = (correct_count / len(exercise_sentences)) * 100
314
+
315
+ # Store attempt
316
+ attempt_data = {
317
+ "responses": responses,
318
+ "score": score,
319
+ "feedback": feedback
320
+ }
321
+
322
+ c.execute("""INSERT INTO exercise_attempts (exercise_id, student_name, responses, score)
323
+ VALUES (?, ?, ?, ?)""",
324
+ (exercise_id, student_name, json.dumps(attempt_data), score))
325
+
326
+ conn.commit()
327
+ conn.close()
328
+
329
+ feedback_html = f"""
330
+ <div style='font-family: Arial, sans-serif; padding: 20px; border: 1px solid #ddd; border-radius: 8px;'>
331
+ <h3>Exercise Results</h3>
332
+ <p><strong>Score: {score:.1f}%</strong> ({correct_count}/{len(exercise_sentences)} correct)</p>
333
+ <div style='margin-top: 15px;'>
334
+ {'<br>'.join(feedback)}
335
+ </div>
336
+ </div>
337
+ """
338
+
339
+ return f"Score: {score:.1f}%", feedback_html
340
+
341
+ def get_student_progress(student_name):
342
+ """Get student's submission and exercise history"""
343
+ if not student_name.strip():
344
+ return "Please enter a student name."
345
+
346
+ conn = sqlite3.connect('language_app.db')
347
+ c = conn.cursor()
348
+
349
+ # Get submissions
350
+ c.execute("""SELECT s.id, s.content, s.created_at, t.title
351
+ FROM submissions s JOIN tasks t ON s.task_id = t.id
352
+ WHERE s.student_name = ? ORDER BY s.created_at DESC""", (student_name,))
353
+ submissions = c.fetchall()
354
+
355
+ # Get exercise attempts
356
+ c.execute("""SELECT ea.score, ea.created_at, e.title
357
+ FROM exercise_attempts ea JOIN exercises e ON ea.exercise_id = e.id
358
+ WHERE ea.student_name = ? ORDER BY ea.created_at DESC""", (student_name,))
359
+ attempts = c.fetchall()
360
+
361
+ conn.close()
362
+
363
+ progress_html = f"""
364
+ <div style='font-family: Arial, sans-serif; padding: 20px;'>
365
+ <h3>Progress for {student_name}</h3>
366
+
367
+ <h4>Writing Submissions ({len(submissions)})</h4>
368
+ <ul>
369
+ """
370
+
371
+ for sub in submissions:
372
+ progress_html += f"<li><strong>{sub[3]}</strong> - {sub[2][:16]} - {len(sub[1])} characters</li>"
373
+
374
+ progress_html += f"""
375
+ </ul>
376
+
377
+ <h4>Exercise Attempts ({len(attempts)})</h4>
378
+ <ul>
379
+ """
380
+
381
+ for att in attempts:
382
+ progress_html += f"<li><strong>{att[2]}</strong> - Score: {att[0]:.1f}% - {att[1][:16]}</li>"
383
+
384
+ progress_html += "</ul></div>"
385
+
386
+ return progress_html
387
+
388
+ # Create Gradio Interface
389
+ with gr.Blocks(title="Language Learning App - Grammar Checker", theme=gr.themes.Soft()) as app:
390
+ gr.Markdown("# πŸŽ“ Language Learning Application")
391
+ gr.Markdown("### AI-Powered Grammar Checking and Exercise Generation")
392
+
393
+ with gr.Tabs():
394
+ # Student Writing Analysis Tab
395
+ with gr.TabItem("πŸ“ Writing Analysis"):
396
+ gr.Markdown("## Submit Your Writing for Analysis")
397
+
398
+ with gr.Row():
399
+ with gr.Column():
400
+ student_name_input = gr.Textbox(label="Your Name", placeholder="Enter your name")
401
+ task_title_input = gr.Textbox(label="Assignment Title", value="General Writing Task")
402
+ writing_input = gr.Textbox(
403
+ label="Your Writing",
404
+ lines=8,
405
+ placeholder="Paste your writing here for grammar analysis..."
406
+ )
407
+ analyze_btn = gr.Button("Analyze Writing", variant="primary")
408
+
409
+ with gr.Column():
410
+ corrected_output = gr.Textbox(label="Corrected Text", lines=6)
411
+ analysis_output = gr.HTML(label="Detailed Analysis")
412
+
413
+ analyze_btn.click(
414
+ analyze_student_writing,
415
+ inputs=[writing_input, student_name_input, task_title_input],
416
+ outputs=[corrected_output, analysis_output]
417
+ )
418
+
419
+ # Exercise Creation Tab
420
+ with gr.TabItem("πŸ‹οΈ Exercise Creation"):
421
+ gr.Markdown("## Create Grammar Exercises")
422
+
423
+ with gr.Row():
424
+ with gr.Column():
425
+ exercise_title_input = gr.Textbox(label="Exercise Title", value="Grammar Exercise")
426
+ exercise_text_input = gr.Textbox(
427
+ label="Text with Errors",
428
+ lines=6,
429
+ placeholder="Enter text containing grammatical errors to create an exercise..."
430
+ )
431
+ create_exercise_btn = gr.Button("Create Exercise", variant="primary")
432
+
433
+ with gr.Column():
434
+ exercise_result = gr.Textbox(label="Result")
435
+ exercise_display = gr.HTML(label="Generated Exercise")
436
+
437
+ create_exercise_btn.click(
438
+ create_exercise_from_text,
439
+ inputs=[exercise_text_input, exercise_title_input],
440
+ outputs=[exercise_result, exercise_display]
441
+ )
442
+
443
+ # Exercise Attempt Tab
444
+ with gr.TabItem("✏️ Exercise Practice"):
445
+ gr.Markdown("## Practice Grammar Exercises")
446
+
447
+ with gr.Row():
448
+ with gr.Column():
449
+ exercise_id_input = gr.Textbox(label="Exercise ID", placeholder="Enter exercise ID")
450
+ student_name_exercise = gr.Textbox(label="Your Name", placeholder="Enter your name")
451
+ responses_input = gr.Textbox(
452
+ label="Your Answers",
453
+ lines=6,
454
+ placeholder="Enter your corrected sentences (one per line)..."
455
+ )
456
+ submit_exercise_btn = gr.Button("Submit Answers", variant="primary")
457
+
458
+ with gr.Column():
459
+ score_output = gr.Textbox(label="Your Score")
460
+ feedback_output = gr.HTML(label="Detailed Feedback")
461
+
462
+ submit_exercise_btn.click(
463
+ attempt_exercise,
464
+ inputs=[exercise_id_input, responses_input, student_name_exercise],
465
+ outputs=[score_output, feedback_output]
466
+ )
467
+
468
+ # Progress Tracking Tab
469
+ with gr.TabItem("πŸ“Š Student Progress"):
470
+ gr.Markdown("## View Student Progress")
471
+
472
+ with gr.Row():
473
+ with gr.Column(scale=1):
474
+ progress_student_name = gr.Textbox(label="Student Name", placeholder="Enter student name")
475
+ get_progress_btn = gr.Button("Get Progress", variant="primary")
476
+
477
+ with gr.Column(scale=2):
478
+ progress_output = gr.HTML(label="Student Progress")
479
+
480
+ get_progress_btn.click(
481
+ get_student_progress,
482
+ inputs=[progress_student_name],
483
+ outputs=[progress_output]
484
+ )
485
+
486
+ gr.Markdown("""
487
+ ---
488
+ ### How to Use:
489
+ 1. **Writing Analysis**: Submit your writing to get grammar corrections and detailed error analysis
490
+ 2. **Exercise Creation**: Teachers can create exercises from text containing errors
491
+ 3. **Exercise Practice**: Students can practice with generated exercises and get scored feedback
492
+ 4. **Progress Tracking**: View student progress across submissions and exercises
493
+
494
+ *Powered by advanced neural networks for grammar error detection and correction*
495
+ """)
496
+
497
+ if __name__ == "__main__":
498
+ app.launch()
requirements.txt ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ gradio==4.15.0
2
+ torch==2.1.0
3
+ transformers==4.36.0
4
+ nltk==3.8.1
5
+ numpy==1.24.3
6
+ sqlite3