Spaces:
Running
Running
import gradio as gr | |
from transformers import pipeline | |
from newspaper import Article | |
import nltk | |
from nltk.tokenize import sent_tokenize | |
import re | |
# Download punkt tokenizer | |
nltk.download("punkt") | |
# Load Hugging Face pipelines | |
grammar_corrector = pipeline("text2text-generation", model="pszemraj/flan-t5-base-grammar-synthesis") | |
toxicity_detector = pipeline("text-classification", model="unitary/toxic-bert") | |
# Utility: extract blog text from URL | |
def extract_text(input_type, text_input, url_input): | |
if input_type == "Text": | |
return text_input | |
elif input_type == "URL": | |
try: | |
article = Article(url_input) | |
article.download() | |
article.parse() | |
return article.text | |
except Exception as e: | |
return f"Error extracting article: {str(e)}" | |
return "" | |
# Highlight grammar & sensitive content | |
def highlight_text(text, grammar_sentences, toxic_sentences): | |
for s in grammar_sentences: | |
text = text.replace(s, f"<span style='background-color: yellow'>{s}</span>") | |
for s in toxic_sentences: | |
text = text.replace(s, f"<span style='background-color: red'>{s}</span>") | |
return text | |
# Main blog review function | |
def review_blog(input_type, text_input, url_input): | |
text = extract_text(input_type, text_input, url_input) | |
if not text or text.startswith("Error"): | |
return text, "", [] | |
sentences = sent_tokenize(text) | |
grammar_issues = [] | |
toxic_issues = [] | |
suggestions = [] | |
for sent in sentences: | |
# Check grammar by comparing original and corrected | |
corrected = grammar_corrector(sent, max_length=128, do_sample=False)[0]['generated_text'] | |
if corrected.strip() != sent.strip(): | |
grammar_issues.append(sent) | |
suggestions.append(f"Grammar: Replace '{sent}' β '{corrected}'") | |
# Check for toxicity | |
result = toxicity_detector(sent) | |
if result[0]['label'] == 'toxic' and result[0]['score'] > 0.7: | |
toxic_issues.append(sent) | |
suggestions.append(f"Toxicity: Rephrase '{sent}' (score: {result[0]['score']:.2f})") | |
highlighted = highlight_text(text, grammar_issues, toxic_issues) | |
sug_text = "\n".join(f"{i+1}. {s}" for i, s in enumerate(suggestions)) | |
return highlighted, sug_text, suggestions | |
# Apply approved suggestions | |
def apply_changes(original_text, suggestions, indices): | |
try: | |
indices = [int(i.strip()) - 1 for i in indices.split(",") if i.strip().isdigit()] | |
sentences = sent_tokenize(original_text) | |
for i in indices: | |
if i < len(suggestions): | |
match = re.search(r"'(.*?)'\s*β\s*'(.*?)'", suggestions[i]) | |
if match: | |
old = match.group(1) | |
new = match.group(2) | |
original_text = original_text.replace(old, new) | |
return original_text | |
except Exception as e: | |
return f"Error applying changes: {str(e)}" | |
# Gradio UI | |
with gr.Blocks(theme=gr.themes.Soft()) as demo: | |
gr.Markdown("## β¨ Blog Content Reviewer (LLM-powered)") | |
gr.Markdown("Paste blog content or a blog URL. AI will detect grammar issues & sensitive content.") | |
input_type = gr.Radio(["Text", "URL"], value="Text", label="Input Type") | |
text_input = gr.Textbox(label="Blog Text", lines=10, visible=True) | |
url_input = gr.Textbox(label="Blog URL", visible=False) | |
input_type.change(lambda t: {text_input: gr.update(visible=t=="Text"), | |
url_input: gr.update(visible=t=="URL")}, | |
input_type, [text_input, url_input]) | |
review_button = gr.Button("Review") | |
highlighted_output = gr.HTML() | |
suggestions_output = gr.Textbox(label="Suggestions", lines=10) | |
approve_input = gr.Textbox(label="Approve Suggestions (e.g., 1,2)") | |
apply_button = gr.Button("Apply Changes") | |
final_text = gr.Textbox(label="Final Output", lines=10) | |
suggestions_state = gr.State() | |
review_button.click( | |
fn=review_blog, | |
inputs=[input_type, text_input, url_input], | |
outputs=[highlighted_output, suggestions_output, suggestions_state] | |
) | |
apply_button.click( | |
fn=apply_changes, | |
inputs=[text_input, suggestions_state, approve_input], | |
outputs=[final_text] | |
) | |
demo.launch() | |