JaishnaCodz's picture
Update app.py
3dcaa0d verified
raw
history blame
7.61 kB
import gradio as gr
import requests
from bs4 import BeautifulSoup
from nltk import download, sent_tokenize
import google.generativeai as genai
import os
import re
import tempfile
import asyncio
import time
# Download NLTK tokenizer data
download('punkt')
# Set Gemini API key
api_key = os.environ.get("GEMINI_API_KEY")
if not api_key:
raise ValueError("GEMINI_API_KEY not found in environment variables.")
genai.configure(api_key=api_key)
try:
model = genai.GenerativeModel('gemini-1.5-flash')
except Exception as e:
print(f"Error initializing model: {e}")
print("Available models:")
for m in genai.list_models():
print(m.name)
raise
PROMPT = """
You are an AI content reviewer. Analyze the provided text for the following:
1. Grammar Issues: Identify and suggest corrections for grammatical errors.
2. Legal Policy Violations: Flag content that may violate common legal policies (e.g., copyright infringement, defamation, incitement to violence).
3. Crude/Abusive Language: Detect crude, offensive, or abusive language.
4. Sensitive Topics: Identify content related to sensitive topics such as racism, gender bias, or other forms of discrimination.
Return the results in the following markdown format:
# Blog Review Report
## Grammar Corrections
1. [Heading of issue]
- CONTENT: [Exact line or part of text with the issue]
- SUGGESTION: [Suggested correction]
- ISSUE: [Description of the issue]
[Continue numbering for additional issues or state "None detected"]
## Legal Policy Violations
- CONTENT: [Exact line or part of text with the issue]
SUGGESTION: [Suggested action or correction]
ISSUE: [Description of the legal violation]
[Or state "None detected"]
## Crude/Abusive Language
- [List instances of crude or abusive language or "None detected"]
## Sensitive Topics
- [List instances of sensitive topics or "None detected"]
"""
async def fetch_url_content(url):
try:
response = requests.get(url, timeout=10)
response.raise_for_status()
soup = BeautifulSoup(response.text, 'html.parser')
content = ' '.join([p.get_text(strip=True) for p in soup.find_all(['p', 'article', 'div'])])
return content or "No readable content found on the page."
except Exception as e:
return f"Error fetching URL: {str(e)}"
async def review_blog(text_input, url_input, progress=gr.Progress()):
if text_input and not url_input:
input_text = text_input
elif url_input and not text_input:
input_text = await fetch_url_content(url_input)
if input_text.startswith("Error"):
return "Review Blog", input_text, gr.update(visible=False)
else:
return "Review Blog", "Error: Provide either text or URL, not both.", gr.update(visible=False)
sentences = sent_tokenize(input_text)
analysis_text = "\n".join(sentences)
progress(0.2, desc="Analyzing...")
try:
response = await asyncio.to_thread(model.generate_content, PROMPT + "\n\nText to analyze:\n" + analysis_text)
report = response.text.strip()
report = re.sub(r'^markdown\n|$', '', report, flags=re.MULTILINE)
except Exception as e:
return "Review Blog", f"Error with Gemini API: {str(e)}", gr.update(visible=False)
try:
with tempfile.NamedTemporaryFile(mode='w', suffix='.md', delete=False, encoding='utf-8') as temp_file:
temp_file.write(report)
file_path = temp_file.name
progress(1.0, desc="Report Ready!")
return "Review Blog", report, gr.update(visible=True, value=file_path)
except Exception as e:
return "Review Blog", f"Error saving report: {str(e)}", gr.update(visible=False)
# ------------------ CSS ------------------ #
custom_css = """
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700&display=swap');
.gradio-container {
font-family: 'Inter', sans-serif !important;
background: linear-gradient(120deg, #e0f7fa 0%, #f9f9f9 100%);
padding: 40px;
border-radius: 20px;
box-shadow: 0 10px 40px rgba(0, 0, 0, 0.07);
}
h1, h3 {
font-weight: 700;
color: #2b6cb0;
}
input, textarea {
border: 2px solid #cbd5e0;
border-radius: 12px;
padding: 15px;
background-color: #ffffff;
font-size: 16px;
color: #2d3748;
transition: border 0.3s ease;
}
input:focus, textarea:focus {
border-color: #3182ce;
outline: none;
}
.review-btn {
background: linear-gradient(45deg, #3182ce, #63b3ed);
padding: 14px 28px;
border-radius: 12px;
font-size: 16px;
color: #fff;
font-weight: 600;
border: none;
cursor: pointer;
transition: all 0.3s ease;
}
.review-btn:hover {
transform: scale(1.04);
background: linear-gradient(45deg, #63b3ed, #3182ce);
}
.markdown-container {
background: #ffffff;
padding: 25px;
border-radius: 16px;
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.08);
margin-top: 25px;
font-size: 15px;
line-height: 1.6;
}
.download-btn {
background-color: #38a169;
color: white;
padding: 12px 20px;
border-radius: 10px;
font-weight: 600;
transition: background 0.3s ease;
}
.download-btn:hover {
background-color: #2f855a;
}
"""
# ------------------ UI ------------------ #
with gr.Blocks(css=custom_css, theme=gr.themes.Soft()) as demo:
with gr.Row():
gr.HTML("""
<div style="text-align: center; margin-bottom: 10px;">
<h1 style="color:#2b6cb0; font-size: 2.5rem;">✨ AI Blog Reviewer</h1>
<p style="font-size: 1.1rem; color: #4a5568;">
Analyze your blog for grammar, legal violations, abusive content, and more.
</p>
</div>
""")
with gr.Row(equal_height=True):
with gr.Column(scale=3):
with gr.Tabs():
with gr.TabItem("✍️ Text Input"):
text_input = gr.Textbox(
label="Paste Your Blog Content",
placeholder="Write or paste your blog text here...",
lines=12,
elem_classes=["input-text"]
)
with gr.TabItem("πŸ”— URL Input"):
url_input = gr.Textbox(
label="Enter Blog URL",
placeholder="https://example.com/blog",
lines=1,
elem_classes=["input-url"]
)
with gr.Column(scale=2):
gr.HTML("""
<div style="background: #fff; padding: 20px 25px; border-radius: 15px; box-shadow: 0 4px 14px rgba(0,0,0,0.08);">
<h3 style="color:#2b6cb0;">πŸš€ How It Works</h3>
<ul style="font-size: 15px; color: #2d3748; line-height: 1.7;">
<li>Paste blog text or a URL</li>
<li>Gemini analyzes for quality and issues</li>
<li>Download the review as Markdown</li>
</ul>
</div>
""")
status_button = gr.Button("🧠 Review Blog", elem_classes=["review-btn"])
gr.Markdown("### πŸ“„ Review Report")
with gr.Row():
with gr.Column():
report_output = gr.Markdown(elem_classes=["markdown-container"])
download_btn = gr.File(label="Download Report", visible=False, elem_classes=["download-btn"])
status_button.click(
fn=review_blog,
inputs=[text_input, url_input],
outputs=[status_button, report_output, download_btn]
)
demo.launch()