File size: 10,053 Bytes
0f2a23a
e4351cc
0f2a23a
 
db75140
0f2a23a
 
bf4908b
 
cf3f184
e4351cc
cce92ec
 
 
 
 
 
 
 
 
0f2a23a
 
e4351cc
cf3f184
bf4908b
cf3f184
 
 
0f2a23a
bf4908b
0f2a23a
 
 
79ca043
 
486bbd6
cf3f184
486bbd6
 
 
 
 
 
 
 
 
cf3f184
486bbd6
 
cf3f184
486bbd6
cf3f184
486bbd6
cf3f184
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
486bbd6
 
 
 
cf3f184
 
 
79ca043
486bbd6
 
cf3f184
 
79ca043
 
cf3f184
 
 
 
79ca043
cf3f184
 
 
486bbd6
 
 
 
 
cf3f184
 
 
 
 
 
 
 
 
 
 
 
 
486bbd6
 
 
cf3f184
 
 
 
 
 
 
 
 
 
 
 
486bbd6
 
 
 
 
cf3f184
486bbd6
cf3f184
486bbd6
cf3f184
79ca043
 
 
cf3f184
79ca043
 
cf3f184
79ca043
 
cf3f184
79ca043
 
cf3f184
79ca043
 
cf3f184
79ca043
 
cf3f184
79ca043
 
cf3f184
79ca043
cf3f184
 
79ca043
cf3f184
 
79ca043
cf3f184
79ca043
cf3f184
 
 
 
 
 
a2b6ad0
cf3f184
a2b6ad0
 
 
 
 
 
 
 
 
 
 
 
 
cf3f184
 
7c41997
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
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
import os
import gradio as gr
from transformers import pipeline
import spacy
import subprocess
import nltk
from nltk.corpus import wordnet
from spellchecker import SpellChecker
import re
import inflect

try:
    nlp = spacy.load("en_core_web_sm")
except OSError:
    print("Downloading spaCy model...")
    spacy.cli.download("en_core_web_sm")
    nlp = spacy.load("en_core_web_sm")



# Initialize the English text classification pipeline for AI detection
pipeline_en = pipeline(task="text-classification", model="Hello-SimpleAI/chatgpt-detector-roberta")

# Initialize the spell checker
spell = SpellChecker()

# Initialize the inflect engine for pluralization
inflect_engine = inflect.engine()

# Ensure necessary NLTK data is downloaded
nltk.download('wordnet')
nltk.download('omw-1.4')

# Load the SpaCy model
nlp = spacy.load("en_core_web_sm")

# Function to predict the label and score for English text (AI Detection)
def predict_en(text):
    res = pipeline_en(text)[0]
    return res['label'], res['score']

# Function to get synonyms using NLTK WordNet
def get_synonyms_nltk(word, pos):
    synsets = wordnet.synsets(word, pos=pos)
    if synsets:
        lemmas = synsets[0].lemmas()
        return [lemma.name() for lemma in lemmas if lemma.name() != word]
    return []

# Function to remove redundant and meaningless words
def remove_redundant_words(text):
    doc = nlp(text)
    meaningless_words = {"actually", "basically", "literally", "really", "very", "just"}
    filtered_text = [token.text for token in doc if token.text.lower() not in meaningless_words]
    return ' '.join(filtered_text)

# Function to capitalize the first letter of sentences and proper nouns
def capitalize_sentences_and_nouns(text):
    doc = nlp(text)
    corrected_text = []

    for sent in doc.sents:
        sentence = []
        for token in sent:
            if token.i == sent.start:  # First word of the sentence
                sentence.append(token.text.capitalize())
            elif token.pos_ == "PROPN":  # Proper noun
                sentence.append(token.text.capitalize())
            else:
                sentence.append(token.text)
        corrected_text.append(' '.join(sentence))

    return ' '.join(corrected_text)

# Function to correct tense errors in a sentence
def correct_tense_errors(text):
    doc = nlp(text)
    corrected_text = []
    for token in doc:
        if token.pos_ == "VERB" and token.dep_ in {"aux", "auxpass"}:
            lemma = wordnet.morphy(token.text, wordnet.VERB) or token.text
            corrected_text.append(lemma)
        else:
            corrected_text.append(token.text)
    return ' '.join(corrected_text)

# Function to correct singular/plural errors
def correct_singular_plural_errors(text):
    doc = nlp(text)
    corrected_text = []
    
    for token in doc:
        if token.pos_ == "NOUN":
            if token.tag_ == "NN":  # Singular noun
                if any(child.text.lower() in ['many', 'several', 'few'] for child in token.head.children):
                    corrected_text.append(inflect_engine.plural(token.lemma_))
                else:
                    corrected_text.append(token.text)
            elif token.tag_ == "NNS":  # Plural noun
                if any(child.text.lower() in ['a', 'one'] for child in token.head.children):
                    corrected_text.append(inflect_engine.singular_noun(token.text) or token.text)
                else:
                    corrected_text.append(token.text)
        else:
            corrected_text.append(token.text)
    
    return ' '.join(corrected_text)

# Function to check and correct article errors
def correct_article_errors(text):
    doc = nlp(text)
    corrected_text = []
    for token in doc:
        if token.text in ['a', 'an']:
            next_token = token.nbor(1)
            if token.text == "a" and next_token.text[0].lower() in "aeiou":
                corrected_text.append("an")
            elif token.text == "an" and next_token.text[0].lower() not in "aeiou":
                corrected_text.append("a")
            else:
                corrected_text.append(token.text)
        else:
            corrected_text.append(token.text)
    return ' '.join(corrected_text)

# Function to get the correct synonym while maintaining verb form
def replace_with_synonym(token):
    pos = None
    if token.pos_ == "VERB":
        pos = wordnet.VERB
    elif token.pos_ == "NOUN":
        pos = wordnet.NOUN
    elif token.pos_ == "ADJ":
        pos = wordnet.ADJ
    elif token.pos_ == "ADV":
        pos = wordnet.ADV
    
    synonyms = get_synonyms_nltk(token.lemma_, pos)
    
    if synonyms:
        synonym = synonyms[0]
        if token.tag_ == "VBG":  # Present participle (e.g., running)
            synonym = synonym + 'ing'
        elif token.tag_ == "VBD" or token.tag_ == "VBN":  # Past tense or past participle
            synonym = synonym + 'ed'
        elif token.tag_ == "VBZ":  # Third-person singular present
            synonym = synonym + 's'
        return synonym
    return token.text

# Function to check for and avoid double negatives
def correct_double_negatives(text):
    doc = nlp(text)
    corrected_text = []
    for token in doc:
        if token.text.lower() == "not" and any(child.text.lower() == "never" for child in token.head.children):
            corrected_text.append("always")
        else:
            corrected_text.append(token.text)
    return ' '.join(corrected_text)

# Function to ensure subject-verb agreement
def ensure_subject_verb_agreement(text):
    doc = nlp(text)
    corrected_text = []
    for token in doc:
        if token.dep_ == "nsubj" and token.head.pos_ == "VERB":
            if token.tag_ == "NN" and token.head.tag_ != "VBZ":  # Singular noun, should use singular verb
                corrected_text.append(token.head.lemma_ + "s")
            elif token.tag_ == "NNS" and token.head.tag_ == "VBZ":  # Plural noun, should not use singular verb
                corrected_text.append(token.head.lemma_)
        corrected_text.append(token.text)
    return ' '.join(corrected_text)

# Function to correct spelling errors
def correct_spelling(text):
    words = text.split()
    corrected_words = []
    for word in words:
        corrected_word = spell.correction(word)
        corrected_words.append(corrected_word if corrected_word else word)
    return ' '.join(corrected_words)

# Function to correct punctuation issues
def correct_punctuation(text):
    text = re.sub(r'\s+([?.!,";:])', r'\1', text)
    text = re.sub(r'([?.!,";:])\s+', r'\1 ', text)
    return text

# Function to ensure correct handling of possessive forms
def handle_possessives(text):
    text = re.sub(r"\b(\w+)'s\b", r"\1's", text)
    return text

# Function to rephrase text and replace words with their synonyms while maintaining form
def rephrase_with_synonyms(text):
    doc = nlp(text)
    rephrased_text = []

    for token in doc:
        if token.pos_ == "NOUN" and token.text.lower() == "earth":
            rephrased_text.append("Earth")
            continue
        
        pos_tag = None
        if token.pos_ == "NOUN":
            pos_tag = wordnet.NOUN
        elif token.pos_ == "VERB":
            pos_tag = wordnet.VERB
        elif token.pos_ == "ADJ":
            pos_tag = wordnet.ADJ
        elif token.pos_ == "ADV":
            pos_tag = wordnet.ADV
        
        if pos_tag:
            synonyms = get_synonyms_nltk(token.lemma_, pos_tag)
            if synonyms:
                synonym = synonyms[0]  # Just using the first synonym for simplicity
                if token.pos_ == "VERB":
                    if token.tag_ == "VBG":  # Present participle (e.g., running)
                        synonym = synonym + 'ing'
                    elif token.tag_ == "VBD" or token.tag_ == "VBN":  # Past tense or past participle
                        synonym = synonym + 'ed'
                    elif token.tag_ == "VBZ":  # Third-person singular present
                        synonym = synonym + 's'
                rephrased_text.append(synonym)
            else:
                rephrased_text.append(token.text)
        else:
            rephrased_text.append(token.text)

    return ' '.join(rephrased_text)

# Function to paraphrase and correct grammar with enhanced accuracy
def paraphrase_and_correct(text):
    # Remove meaningless or redundant words first
    cleaned_text = remove_redundant_words(text)
    
    # Capitalize sentences and proper nouns
    cleaned_text = capitalize_sentences_and_nouns(cleaned_text)

    # Correct tense errors
    cleaned_text = correct_tense_errors(cleaned_text)

    # Correct singular/plural errors
    cleaned_text = correct_singular_plural_errors(cleaned_text)

    # Correct article errors
    cleaned_text = correct_article_errors(cleaned_text)

    # Correct spelling
    cleaned_text = correct_spelling(cleaned_text)

    # Correct punctuation issues
    cleaned_text = correct_punctuation(cleaned_text)

    # Handle possessives
    cleaned_text = handle_possessives(cleaned_text)

    # Replace words with synonyms
    cleaned_text = rephrase_with_synonyms(cleaned_text)

    # Correct double negatives
    cleaned_text = correct_double_negatives(cleaned_text)

    # Ensure subject-verb agreement
    cleaned_text = ensure_subject_verb_agreement(cleaned_text)

    return cleaned_text

# Function to detect AI-generated content
def detect_ai(text):
    label, score = predict_en(text)
    return label, score
def gradio_interface(text):
    label, score = detect_ai(text)
    corrected_text = paraphrase_and_correct(text)
    return {label: score}, corrected_text

# Modify the Gradio interface setup
iface = gr.Interface(
    fn=gradio_interface,
    inputs=gr.Textbox(lines=5, placeholder="Enter text here..."),
    outputs=[
        gr.Label(num_top_classes=1),
        gr.Textbox(label="Corrected Text")
    ],
    title="AI Detection and Grammar Correction",
    description="Detect AI-generated content and correct grammar issues."
)

# Launch the app
iface.launch()