sashtech's picture
Update app.py
353216c verified
raw
history blame
11.1 kB
import os
import gradio as gr
from transformers import pipeline
import spacy
import nltk
from nltk.corpus import wordnet
from spellchecker import SpellChecker
import re
import inflect
# Initialize components
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')
# 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)
# Enhance the spell checker function
def enhanced_spell_check(text):
words = text.split()
corrected_words = []
for word in words:
if '_' in word: # Handle cases like 'animate_being'
sub_words = word.split('_')
corrected_sub_words = [spell.correction(w) for w in sub_words]
corrected_words.append('_'.join(corrected_sub_words))
else:
corrected_word = spell.correction(word)
corrected_words.append(corrected_word if corrected_word else word)
return ' '.join(corrected_words)
# Function to correct common semantic errors
def correct_semantic_errors(text):
semantic_corrections = {
"animate_being": "animal",
"little": "smallest",
"big": "largest",
"mammalian": "mammals",
"universe": "world",
"manner": "ways",
"continue": "preserve",
"dirt": "soil",
"wellness": "health",
"modulate": "regulate",
"clime": "climate",
"function": "role",
"keeping": "maintaining",
"lend": "contribute",
"better": "improve",
"is": "s",
"wite": "write",
"alos": "also",
"ads": "as",
"dictuionatr": "dictionary",
"wors": "words"
}
words = text.split()
corrected_words = [semantic_corrections.get(word.lower(), word) for word in words]
return ' '.join(corrected_words)
# Enhance the punctuation correction function
def enhance_punctuation(text):
# Remove extra spaces before punctuation
text = re.sub(r'\s+([?.!,";:])', r'\1', text)
# Add space after punctuation if it's missing
text = re.sub(r'([?.!,";:])(\S)', r'\1 \2', text)
# Correct spacing for quotes
text = re.sub(r'\s*"\s*', '" ', text).strip()
# Ensure proper capitalization after sentence-ending punctuation
text = re.sub(r'([.!?])\s*([a-z])', lambda m: m.group(1) + ' ' + m.group(2).upper(), text)
return text
# Function to handle possessives
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 detect AI-generated content
def detect_ai(text):
label, score = predict_en(text)
return label, score
# Enhance the paraphrase_and_correct function
def paraphrase_and_correct(text):
# Apply enhanced spell checking
text = enhanced_spell_check(text)
# Correct semantic errors
text = correct_semantic_errors(text)
# Apply existing corrections
text = remove_redundant_words(text)
text = capitalize_sentences_and_nouns(text)
text = correct_tense_errors(text)
text = correct_singular_plural_errors(text)
text = correct_article_errors(text)
text = enhance_punctuation(text)
text = handle_possessives(text)
text = rephrase_with_synonyms(text)
text = correct_double_negatives(text)
text = ensure_subject_verb_agreement(text)
return text
# Gradio interface setup
def gradio_interface(text):
label, score = detect_ai(text)
corrected_text = paraphrase_and_correct(text)
return {label: score}, corrected_text
# Create Gradio interface
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()