JaishnaCodz commited on
Commit
3dcaa0d
Β·
verified Β·
1 Parent(s): 210d41a

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +93 -150
app.py CHANGED
@@ -9,28 +9,25 @@ import tempfile
9
  import asyncio
10
  import time
11
 
12
- # Download NLTK data
13
  download('punkt')
14
- download('punkt_tab')
15
 
16
- # Configure Gemini API using environment variable
17
  api_key = os.environ.get("GEMINI_API_KEY")
18
  if not api_key:
19
- raise ValueError("GEMINI_API_KEY not found in environment variables. Please set it in your environment.")
20
 
21
  genai.configure(api_key=api_key)
22
 
23
- # Use gemini-1.5-flash for faster and more accessible text analysis
24
  try:
25
  model = genai.GenerativeModel('gemini-1.5-flash')
26
  except Exception as e:
27
- print(f"Error initializing model: {str(e)}")
28
  print("Available models:")
29
  for m in genai.list_models():
30
  print(m.name)
31
- raise ValueError("Failed to initialize gemini-1.5-flash. Check available models above and update the model name.")
32
 
33
- # Prompt for Gemini to analyze text with specified output format
34
  PROMPT = """
35
  You are an AI content reviewer. Analyze the provided text for the following:
36
  1. Grammar Issues: Identify and suggest corrections for grammatical errors.
@@ -47,11 +44,6 @@ Return the results in the following markdown format:
47
  - SUGGESTION: [Suggested correction]
48
  - ISSUE: [Description of the issue]
49
 
50
- 2. [Heading of next issue]
51
- - CONTENT: [Exact line or part of text with the issue]
52
- - SUGGESTION: [Suggested correction]
53
- - ISSUE: [Description of the issue]
54
-
55
  [Continue numbering for additional issues or state "None detected"]
56
 
57
  ## Legal Policy Violations
@@ -65,8 +57,6 @@ Return the results in the following markdown format:
65
 
66
  ## Sensitive Topics
67
  - [List instances of sensitive topics or "None detected"]
68
-
69
- For each issue, provide the exact text, a suggested correction or action, and a concise explanation. Be precise and ensure the output strictly follows the specified format.
70
  """
71
 
72
  async def fetch_url_content(url):
@@ -75,202 +65,155 @@ async def fetch_url_content(url):
75
  response.raise_for_status()
76
  soup = BeautifulSoup(response.text, 'html.parser')
77
  content = ' '.join([p.get_text(strip=True) for p in soup.find_all(['p', 'article', 'div'])])
78
- return content if content else "No readable content found on the page."
79
  except Exception as e:
80
  return f"Error fetching URL: {str(e)}"
81
 
82
  async def review_blog(text_input, url_input, progress=gr.Progress()):
83
  if text_input and not url_input:
84
- input_type = "Text"
85
  input_text = text_input
86
  elif url_input and not text_input:
87
- input_type = "URL"
88
- input_text = url_input
89
- else:
90
- return "Review Blog", "Error: Please provide input in either the Text or URL tab, but not both.", gr.update(visible=False)
91
-
92
- if not input_text:
93
- return "Review Blog", "Error: No input provided.", gr.update(visible=False)
94
-
95
- if input_type == "URL":
96
- progress(0, desc="Fetching content...")
97
- input_text = await fetch_url_content(input_text)
98
  if input_text.startswith("Error"):
99
  return "Review Blog", input_text, gr.update(visible=False)
 
 
100
 
101
  sentences = sent_tokenize(input_text)
102
  analysis_text = "\n".join(sentences)
103
 
104
- progress(0, desc="Generating report...")
105
- start_time = time.time()
106
- for i in range(1, 10):
107
- await asyncio.sleep(1)
108
- progress(i / 10, desc=f"Generating report... ({int(i * 10)}%)")
109
- if time.time() - start_time > 30:
110
- return "Review Blog", "Error: API request timed out after 30 seconds.", gr.update(visible=False)
111
-
112
  try:
113
  response = await asyncio.to_thread(model.generate_content, PROMPT + "\n\nText to analyze:\n" + analysis_text)
114
  report = response.text.strip()
115
  report = re.sub(r'^markdown\n|$', '', report, flags=re.MULTILINE)
116
  except Exception as e:
117
- report = f"Error analyzing content with Gemini: {str(e)}"
118
- print("Available models:")
119
- for m in genai.list_models():
120
- print(m.name)
121
- return "Review Blog", report, gr.update(visible=False)
122
 
123
  try:
124
  with tempfile.NamedTemporaryFile(mode='w', suffix='.md', delete=False, encoding='utf-8') as temp_file:
125
  temp_file.write(report)
126
- temp_file_path = temp_file.name
127
- progress(1.0, desc="Report generated!")
128
- return "Review Blog", report, gr.update(visible=True, value=temp_file_path)
129
  except Exception as e:
130
- return "Review Blog", f"Error creating temporary file: {str(e)}", gr.update(visible=False)
131
 
132
- # Enhanced custom CSS for a more attractive and user-friendly UI
133
  custom_css = """
134
- @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap');
 
135
  .gradio-container {
136
  font-family: 'Inter', sans-serif !important;
137
- background: linear-gradient(135deg, #f0f4f8 0%, #d9e2ec 100%);
138
- padding: 30px;
139
- border-radius: 15px;
140
- box-shadow: 0 6px 25px rgba(0, 0, 0, 0.15);
141
- color: #2d3748;
142
  }
 
143
  h1, h3 {
144
- color: #2b6cb0;
145
- text-align: center;
146
  font-weight: 700;
147
- margin-bottom: 15px;
148
- text-shadow: 1px 1px 3px rgba(0, 0, 0, 0.1);
149
- }
150
- .review-btn {
151
- background: linear-gradient(45deg, #4a90e2, #63b3ed);
152
- color: white;
153
- font-weight: 600;
154
- border: none;
155
- border-radius: 12px;
156
- padding: 14px 28px;
157
- transition: all 0.3s ease;
158
- box-shadow: 0 4px 12px rgba(74, 144, 226, 0.3);
159
- cursor: pointer;
160
- }
161
- .review-btn:hover {
162
- background: linear-gradient(45deg, #63b3ed, #4a90e2);
163
- transform: translateY(-3px);
164
- box-shadow: 0 6px 15px rgba(74, 144, 226, 0.4);
165
- }
166
- .review-btn:disabled {
167
- opacity: 0.7;
168
- cursor: not-allowed;
169
- transform: none;
170
- box-shadow: none;
171
- }
172
- .review-btn:disabled::after {
173
- content: ' ⏳';
174
- }
175
- .tab-nav button {
176
- font-family: 'Inter', sans-serif;
177
- font-weight: 600;
178
- background: #edf2f7;
179
- color: #2d3748;
180
- border-radius: 10px 10px 0 0;
181
- padding: 12px 24px;
182
- transition: all 0.2s ease;
183
- border: 1px solid #e2e8f0;
184
- }
185
- .tab-nav button:hover {
186
- background: #4a90e2;
187
- color: white;
188
- border-color: #4a90e2;
189
  }
 
190
  input, textarea {
191
- font-family: 'Inter', sans-serif;
192
- border: 2px solid #e2e8f0;
193
- border-radius: 10px;
194
- padding: 12px;
195
- background: #ffffff;
196
- box-shadow: 0 2px 6px rgba(0, 0, 0, 0.05);
197
- color: #2d3748;
198
  font-size: 16px;
 
 
199
  }
200
- .gr-textbox textarea {
201
- resize: vertical;
202
- min-height: 150px;
 
203
  }
204
- .gr-progress {
205
- background: #edf2f7;
 
 
206
  border-radius: 12px;
207
- overflow: hidden;
208
- height: 30px;
 
 
 
 
209
  }
210
- .gr-progress > div {
211
- background: linear-gradient(90deg, #48bb78, #38a169);
212
- height: 100%;
213
- transition: width 0.5s ease;
214
  }
 
215
  .markdown-container {
216
  background: #ffffff;
217
- border-radius: 12px;
218
  padding: 25px;
219
- box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
220
- margin-top: 20px;
221
- color: #2d3748;
 
 
222
  }
 
223
  .download-btn {
224
- background: #48bb78;
225
  color: white;
 
226
  border-radius: 10px;
227
- padding: 12px 24px;
228
  font-weight: 600;
229
- transition: all 0.3s ease;
230
- cursor: pointer;
231
  }
 
232
  .download-btn:hover {
233
- background: #38a169;
234
- transform: translateY(-3px);
235
  }
236
  """
237
 
238
- # Gradio UI with enhanced layout
239
- with gr.Blocks(theme=gr.themes.Monochrome(), css=custom_css) as demo:
240
- gr.Markdown(
241
- """
242
- # πŸ“ AI Blog Reviewer
243
- Easily analyze your blog for grammar, legal issues, crude language, and sensitive topics.
244
- """
245
- )
246
  with gr.Row():
247
- with gr.Column(scale=2):
 
 
 
 
 
 
 
 
 
 
248
  with gr.Tabs():
249
- with gr.TabItem("Text Input"):
250
  text_input = gr.Textbox(
251
- lines=10,
252
  label="Paste Your Blog Content",
253
- placeholder="Enter your blog text here...",
 
254
  elem_classes=["input-text"]
255
  )
256
- with gr.TabItem("URL Input"):
257
  url_input = gr.Textbox(
258
- lines=1,
259
  label="Enter Blog URL",
260
  placeholder="https://example.com/blog",
 
261
  elem_classes=["input-url"]
262
  )
263
- with gr.Column(scale=1):
264
- gr.Markdown(
265
- """
266
- ### How It Works
267
- 1. **Input**: Paste text or provide a URL.
268
- 2. **Analysis**: AI checks grammar, legal issues, and more.
269
- 3. **Report**: Download a detailed markdown report.
270
- """
271
- )
272
- status_button = gr.Button("Review Blog", elem_classes=["review-btn"])
273
-
 
 
274
  gr.Markdown("### πŸ“„ Review Report")
275
  with gr.Row():
276
  with gr.Column():
@@ -283,4 +226,4 @@ with gr.Blocks(theme=gr.themes.Monochrome(), css=custom_css) as demo:
283
  outputs=[status_button, report_output, download_btn]
284
  )
285
 
286
- demo.launch()
 
9
  import asyncio
10
  import time
11
 
12
+ # Download NLTK tokenizer data
13
  download('punkt')
 
14
 
15
+ # Set Gemini API key
16
  api_key = os.environ.get("GEMINI_API_KEY")
17
  if not api_key:
18
+ raise ValueError("GEMINI_API_KEY not found in environment variables.")
19
 
20
  genai.configure(api_key=api_key)
21
 
 
22
  try:
23
  model = genai.GenerativeModel('gemini-1.5-flash')
24
  except Exception as e:
25
+ print(f"Error initializing model: {e}")
26
  print("Available models:")
27
  for m in genai.list_models():
28
  print(m.name)
29
+ raise
30
 
 
31
  PROMPT = """
32
  You are an AI content reviewer. Analyze the provided text for the following:
33
  1. Grammar Issues: Identify and suggest corrections for grammatical errors.
 
44
  - SUGGESTION: [Suggested correction]
45
  - ISSUE: [Description of the issue]
46
 
 
 
 
 
 
47
  [Continue numbering for additional issues or state "None detected"]
48
 
49
  ## Legal Policy Violations
 
57
 
58
  ## Sensitive Topics
59
  - [List instances of sensitive topics or "None detected"]
 
 
60
  """
61
 
62
  async def fetch_url_content(url):
 
65
  response.raise_for_status()
66
  soup = BeautifulSoup(response.text, 'html.parser')
67
  content = ' '.join([p.get_text(strip=True) for p in soup.find_all(['p', 'article', 'div'])])
68
+ return content or "No readable content found on the page."
69
  except Exception as e:
70
  return f"Error fetching URL: {str(e)}"
71
 
72
  async def review_blog(text_input, url_input, progress=gr.Progress()):
73
  if text_input and not url_input:
 
74
  input_text = text_input
75
  elif url_input and not text_input:
76
+ input_text = await fetch_url_content(url_input)
 
 
 
 
 
 
 
 
 
 
77
  if input_text.startswith("Error"):
78
  return "Review Blog", input_text, gr.update(visible=False)
79
+ else:
80
+ return "Review Blog", "Error: Provide either text or URL, not both.", gr.update(visible=False)
81
 
82
  sentences = sent_tokenize(input_text)
83
  analysis_text = "\n".join(sentences)
84
 
85
+ progress(0.2, desc="Analyzing...")
 
 
 
 
 
 
 
86
  try:
87
  response = await asyncio.to_thread(model.generate_content, PROMPT + "\n\nText to analyze:\n" + analysis_text)
88
  report = response.text.strip()
89
  report = re.sub(r'^markdown\n|$', '', report, flags=re.MULTILINE)
90
  except Exception as e:
91
+ return "Review Blog", f"Error with Gemini API: {str(e)}", gr.update(visible=False)
 
 
 
 
92
 
93
  try:
94
  with tempfile.NamedTemporaryFile(mode='w', suffix='.md', delete=False, encoding='utf-8') as temp_file:
95
  temp_file.write(report)
96
+ file_path = temp_file.name
97
+ progress(1.0, desc="Report Ready!")
98
+ return "Review Blog", report, gr.update(visible=True, value=file_path)
99
  except Exception as e:
100
+ return "Review Blog", f"Error saving report: {str(e)}", gr.update(visible=False)
101
 
102
+ # ------------------ CSS ------------------ #
103
  custom_css = """
104
+ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700&display=swap');
105
+
106
  .gradio-container {
107
  font-family: 'Inter', sans-serif !important;
108
+ background: linear-gradient(120deg, #e0f7fa 0%, #f9f9f9 100%);
109
+ padding: 40px;
110
+ border-radius: 20px;
111
+ box-shadow: 0 10px 40px rgba(0, 0, 0, 0.07);
 
112
  }
113
+
114
  h1, h3 {
 
 
115
  font-weight: 700;
116
+ color: #2b6cb0;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
117
  }
118
+
119
  input, textarea {
120
+ border: 2px solid #cbd5e0;
121
+ border-radius: 12px;
122
+ padding: 15px;
123
+ background-color: #ffffff;
 
 
 
124
  font-size: 16px;
125
+ color: #2d3748;
126
+ transition: border 0.3s ease;
127
  }
128
+
129
+ input:focus, textarea:focus {
130
+ border-color: #3182ce;
131
+ outline: none;
132
  }
133
+
134
+ .review-btn {
135
+ background: linear-gradient(45deg, #3182ce, #63b3ed);
136
+ padding: 14px 28px;
137
  border-radius: 12px;
138
+ font-size: 16px;
139
+ color: #fff;
140
+ font-weight: 600;
141
+ border: none;
142
+ cursor: pointer;
143
+ transition: all 0.3s ease;
144
  }
145
+
146
+ .review-btn:hover {
147
+ transform: scale(1.04);
148
+ background: linear-gradient(45deg, #63b3ed, #3182ce);
149
  }
150
+
151
  .markdown-container {
152
  background: #ffffff;
 
153
  padding: 25px;
154
+ border-radius: 16px;
155
+ box-shadow: 0 8px 24px rgba(0, 0, 0, 0.08);
156
+ margin-top: 25px;
157
+ font-size: 15px;
158
+ line-height: 1.6;
159
  }
160
+
161
  .download-btn {
162
+ background-color: #38a169;
163
  color: white;
164
+ padding: 12px 20px;
165
  border-radius: 10px;
 
166
  font-weight: 600;
167
+ transition: background 0.3s ease;
 
168
  }
169
+
170
  .download-btn:hover {
171
+ background-color: #2f855a;
 
172
  }
173
  """
174
 
175
+ # ------------------ UI ------------------ #
176
+ with gr.Blocks(css=custom_css, theme=gr.themes.Soft()) as demo:
 
 
 
 
 
 
177
  with gr.Row():
178
+ gr.HTML("""
179
+ <div style="text-align: center; margin-bottom: 10px;">
180
+ <h1 style="color:#2b6cb0; font-size: 2.5rem;">✨ AI Blog Reviewer</h1>
181
+ <p style="font-size: 1.1rem; color: #4a5568;">
182
+ Analyze your blog for grammar, legal violations, abusive content, and more.
183
+ </p>
184
+ </div>
185
+ """)
186
+
187
+ with gr.Row(equal_height=True):
188
+ with gr.Column(scale=3):
189
  with gr.Tabs():
190
+ with gr.TabItem("✍️ Text Input"):
191
  text_input = gr.Textbox(
 
192
  label="Paste Your Blog Content",
193
+ placeholder="Write or paste your blog text here...",
194
+ lines=12,
195
  elem_classes=["input-text"]
196
  )
197
+ with gr.TabItem("πŸ”— URL Input"):
198
  url_input = gr.Textbox(
 
199
  label="Enter Blog URL",
200
  placeholder="https://example.com/blog",
201
+ lines=1,
202
  elem_classes=["input-url"]
203
  )
204
+ with gr.Column(scale=2):
205
+ gr.HTML("""
206
+ <div style="background: #fff; padding: 20px 25px; border-radius: 15px; box-shadow: 0 4px 14px rgba(0,0,0,0.08);">
207
+ <h3 style="color:#2b6cb0;">πŸš€ How It Works</h3>
208
+ <ul style="font-size: 15px; color: #2d3748; line-height: 1.7;">
209
+ <li>Paste blog text or a URL</li>
210
+ <li>Gemini analyzes for quality and issues</li>
211
+ <li>Download the review as Markdown</li>
212
+ </ul>
213
+ </div>
214
+ """)
215
+ status_button = gr.Button("🧠 Review Blog", elem_classes=["review-btn"])
216
+
217
  gr.Markdown("### πŸ“„ Review Report")
218
  with gr.Row():
219
  with gr.Column():
 
226
  outputs=[status_button, report_output, download_btn]
227
  )
228
 
229
+ demo.launch()