Spaces:
Running
Running
File size: 7,610 Bytes
768c740 7d19342 b8a6b71 7d19342 6784902 20bfd0b 56f7cbb 3dcaa0d b8a6b71 7d19342 3dcaa0d 7d19342 3dcaa0d 20bfd0b 7d19342 20bfd0b 3dcaa0d 20bfd0b 3dcaa0d 20bfd0b 7d19342 20bfd0b 7d19342 20bfd0b 7d19342 20bfd0b 7d19342 20bfd0b 7d19342 3dcaa0d 7d19342 b8a6b71 20bfd0b 3dcaa0d 7d19342 20bfd0b 3dcaa0d 768c740 7d19342 768c740 3dcaa0d 7d19342 20bfd0b 7d19342 20bfd0b 7d19342 3dcaa0d 768c740 20bfd0b 3dcaa0d 20bfd0b 3dcaa0d 20bfd0b 3dcaa0d 20bfd0b 3dcaa0d 20bfd0b 3dcaa0d 1d1f3c9 3dcaa0d 1d1f3c9 3dcaa0d 20bfd0b 3dcaa0d 20bfd0b 3dcaa0d 210d41a 3dcaa0d 1d1f3c9 3dcaa0d 20bfd0b 3dcaa0d 210d41a 3dcaa0d 20bfd0b 3dcaa0d 1d1f3c9 3dcaa0d 1d1f3c9 210d41a 3dcaa0d 1d1f3c9 3dcaa0d 1d1f3c9 3dcaa0d 1d1f3c9 3dcaa0d 210d41a 3dcaa0d 1d1f3c9 3dcaa0d 1d1f3c9 3dcaa0d 20bfd0b b8a6b71 3dcaa0d 1d1f3c9 3dcaa0d 1d1f3c9 3dcaa0d 1d1f3c9 3dcaa0d 1d1f3c9 3dcaa0d 1d1f3c9 3dcaa0d 1d1f3c9 3dcaa0d 7d19342 1d1f3c9 210d41a 7d19342 20bfd0b 7d19342 768c740 3dcaa0d |
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 |
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()
|