JaishnaCodz commited on
Commit
1d1f3c9
·
verified ·
1 Parent(s): 2ae364b

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +108 -44
app.py CHANGED
@@ -24,7 +24,6 @@ genai.configure(api_key=api_key)
24
  try:
25
  model = genai.GenerativeModel('gemini-1.5-flash')
26
  except Exception as e:
27
- # Fallback: List available models if the specified model is not found
28
  print(f"Error initializing model: {str(e)}")
29
  print("Available models:")
30
  for m in genai.list_models():
@@ -75,14 +74,12 @@ async def fetch_url_content(url):
75
  response = requests.get(url, timeout=10)
76
  response.raise_for_status()
77
  soup = BeautifulSoup(response.text, 'html.parser')
78
- # Extract text from common content tags
79
  content = ' '.join([p.get_text(strip=True) for p in soup.find_all(['p', 'article', 'div'])])
80
  return content if content else "No readable content found on the page."
81
  except Exception as e:
82
  return f"Error fetching URL: {str(e)}"
83
 
84
  async def review_blog(text_input, url_input, progress=gr.Progress()):
85
- # Determine input type based on which field is populated
86
  if text_input and not url_input:
87
  input_type = "Text"
88
  input_text = text_input
@@ -92,45 +89,37 @@ async def review_blog(text_input, url_input, progress=gr.Progress()):
92
  else:
93
  return "Review Blog", "Error: Please provide input in either the Text or URL tab, but not both.", gr.update(visible=False)
94
 
95
- # Handle empty input
96
  if not input_text:
97
  return "Review Blog", "Error: No input provided.", gr.update(visible=False)
98
 
99
- # Handle URL input
100
  if input_type == "URL":
101
  progress(0, desc="Fetching content...")
102
  input_text = await fetch_url_content(input_text)
103
  if input_text.startswith("Error"):
104
  return "Review Blog", input_text, gr.update(visible=False)
105
 
106
- # Tokenize input for analysis
107
  sentences = sent_tokenize(input_text)
108
  analysis_text = "\n".join(sentences)
109
 
110
- # Simulate progress for API call
111
  progress(0, desc="Generating report...")
112
  start_time = time.time()
113
  for i in range(1, 10):
114
- await asyncio.sleep(1) # Simulate progress every second
115
  progress(i / 10, desc=f"Generating report... ({int(i * 10)}%)")
116
- if time.time() - start_time > 30: # Timeout after 30 seconds
117
  return "Review Blog", "Error: API request timed out after 30 seconds.", gr.update(visible=False)
118
 
119
- # Query Gemini with the prompt
120
  try:
121
  response = await asyncio.to_thread(model.generate_content, PROMPT + "\n\nText to analyze:\n" + analysis_text)
122
  report = response.text.strip()
123
- # Ensure the response is markdown by removing any code fences
124
  report = re.sub(r'^markdown\n|$', '', report, flags=re.MULTILINE)
125
  except Exception as e:
126
  report = f"Error analyzing content with Gemini: {str(e)}"
127
- # Fallback: List available models for debugging
128
  print("Available models:")
129
  for m in genai.list_models():
130
  print(m.name)
131
  return "Review Blog", report, gr.update(visible=False)
132
 
133
- # Create a temporary file to store the report
134
  try:
135
  with tempfile.NamedTemporaryFile(mode='w', suffix='.md', delete=False, encoding='utf-8') as temp_file:
136
  temp_file.write(report)
@@ -140,69 +129,144 @@ async def review_blog(text_input, url_input, progress=gr.Progress()):
140
  except Exception as e:
141
  return "Review Blog", f"Error creating temporary file: {str(e)}", gr.update(visible=False)
142
 
143
- # Custom CSS for hover effect, loading state, and Inter font
144
  custom_css = """
145
  @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap');
146
  .gradio-container {
147
  font-family: 'Inter', sans-serif !important;
 
 
 
 
 
 
 
 
 
 
148
  }
149
  .review-btn {
150
- transition: all 0.3s ease;
151
- font-weight: 500;
152
- background-color: #2c3e50;
153
  color: white;
154
- border-radius: 8px;
155
- padding: 10px 20px;
 
 
 
 
156
  }
157
  .review-btn:hover {
158
- background-color: #4CAF50;
159
- color: white;
160
- transform: scale(1.05);
161
  }
162
  .review-btn:disabled {
163
- opacity: 0.7;
164
  cursor: not-allowed;
 
 
165
  }
166
  .review-btn:disabled::after {
167
  content: ' ⏳';
168
  }
169
  .tab-nav button {
170
  font-family: 'Inter', sans-serif;
171
- font-weight: 500;
 
 
 
 
 
 
 
 
 
172
  }
173
  input, textarea {
174
  font-family: 'Inter', sans-serif;
 
 
 
 
 
 
 
 
175
  }
176
  .gr-progress {
177
- background-color: #e0e0e0;
178
- border-radius: 8px;
179
  overflow: hidden;
 
180
  }
181
  .gr-progress > div {
182
- background-color: #4CAF50;
183
- height: 20px;
184
- transition: width 0.3s ease;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
185
  }
186
  """
187
 
188
- # Gradio UI with Tabs
189
  with gr.Blocks(theme=gr.themes.Monochrome(), css=custom_css) as demo:
190
- gr.Markdown("# 📝 AI Blog Reviewer")
191
- gr.Markdown("Enter blog text or a URL to review for grammar, legal issues, crude language, and sensitive topics. The report is generated in markdown format.")
192
-
193
- with gr.Tabs():
194
- with gr.TabItem("Text"):
195
- text_input = gr.Textbox(lines=8, label="Blog Content", placeholder="Paste your blog text here...")
196
- with gr.TabItem("URL"):
197
- url_input = gr.Textbox(lines=1, label="Blog URL", placeholder="Enter the blog URL here...")
198
-
199
- status_button = gr.Button(value="Review Blog", elem_classes=["review-btn"])
200
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
201
  gr.Markdown("### 📄 Review Report")
202
- report_output = gr.Markdown()
203
- download_btn = gr.File(label="Download Report", visible=False)
 
 
204
 
205
- # Bind the review button to process inputs
206
  status_button.click(
207
  fn=review_blog,
208
  inputs=[text_input, url_input],
 
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():
 
74
  response = requests.get(url, timeout=10)
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
 
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)
 
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 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, #f5f7fa 0%, #c3cfe2 100%);
138
+ padding: 20px;
139
+ border-radius: 12px;
140
+ box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
141
+ }
142
+ h1, h3 {
143
+ color: #1a3c34;
144
+ text-align: center;
145
+ font-weight: 700;
146
+ margin-bottom: 10px;
147
  }
148
  .review-btn {
149
+ background: linear-gradient(45deg, #2c3e50, #3498db);
 
 
150
  color: white;
151
+ font-weight: 600;
152
+ border: none;
153
+ border-radius: 10px;
154
+ padding: 12px 24px;
155
+ transition: all 0.3s ease;
156
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
157
  }
158
  .review-btn:hover {
159
+ background: linear-gradient(45deg, #3498db, #2c3e50);
160
+ transform: translateY(-2px);
161
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
162
  }
163
  .review-btn:disabled {
164
+ opacity: 0.6;
165
  cursor: not-allowed;
166
+ transform: none;
167
+ box-shadow: none;
168
  }
169
  .review-btn:disabled::after {
170
  content: ' ⏳';
171
  }
172
  .tab-nav button {
173
  font-family: 'Inter', sans-serif;
174
+ font-weight: 600;
175
+ background: #ffffff;
176
+ color: #2c3e50;
177
+ border-radius: 8px 8px 0 0;
178
+ padding: 10px 20px;
179
+ transition: all 0.2s ease;
180
+ }
181
+ .tab-nav button:hover {
182
+ background: #3498db;
183
+ color: white;
184
  }
185
  input, textarea {
186
  font-family: 'Inter', sans-serif;
187
+ border: 1px solid #d1d5db;
188
+ border-radius: 8px;
189
+ padding: 10px;
190
+ background: #ffffff;
191
+ box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1);
192
+ }
193
+ .gr-textbox textarea {
194
+ resize: vertical;
195
  }
196
  .gr-progress {
197
+ background: #e2e8f0;
198
+ border-radius: 10px;
199
  overflow: hidden;
200
+ height: 24px;
201
  }
202
  .gr-progress > div {
203
+ background: linear-gradient(90deg, #34c759, #4CAF50);
204
+ height: 100%;
205
+ transition: width 0.4s ease-in-out;
206
+ }
207
+ .markdown-container {
208
+ background: #ffffff;
209
+ border-radius: 8px;
210
+ padding: 20px;
211
+ box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
212
+ margin-top: 20px;
213
+ }
214
+ .download-btn {
215
+ background: #4CAF50;
216
+ color: white;
217
+ border-radius: 8px;
218
+ padding: 10px 20px;
219
+ font-weight: 500;
220
+ transition: all 0.3s ease;
221
+ }
222
+ .download-btn:hover {
223
+ background: #45a049;
224
+ transform: translateY(-2px);
225
  }
226
  """
227
 
228
+ # Gradio UI with enhanced layout
229
  with gr.Blocks(theme=gr.themes.Monochrome(), css=custom_css) as demo:
230
+ gr.Markdown(
231
+ """
232
+ # 📝 AI Blog Reviewer
233
+ Analyze your blog content for grammar, legal issues, crude language, and sensitive topics with ease.
234
+ """
235
+ )
236
+ with gr.Row():
237
+ with gr.Column(scale=2):
238
+ with gr.Tabs():
239
+ with gr.TabItem("Text Input"):
240
+ text_input = gr.Textbox(
241
+ lines=10,
242
+ label="Paste Your Blog Content",
243
+ placeholder="Enter your blog text here...",
244
+ elem_classes=["input-text"]
245
+ )
246
+ with gr.TabItem("URL Input"):
247
+ url_input = gr.Textbox(
248
+ lines=1,
249
+ label="Enter Blog URL",
250
+ placeholder="https://example.com/blog",
251
+ elem_classes=["input-url"]
252
+ )
253
+ with gr.Column(scale=1):
254
+ gr.Markdown(
255
+ """
256
+ ### How It Works
257
+ 1. **Input**: Paste blog text or provide a URL.
258
+ 2. **Analysis**: Our AI reviews for grammar, legal issues, and more.
259
+ 3. **Report**: Get a detailed markdown report with suggestions.
260
+ """
261
+ )
262
+ status_button = gr.Button("Review Blog", elem_classes=["review-btn"])
263
+
264
  gr.Markdown("### 📄 Review Report")
265
+ with gr.Row():
266
+ with gr.Column():
267
+ report_output = gr.Markdown(elem_classes=["markdown-container"])
268
+ download_btn = gr.File(label="Download Report as Markdown", visible=False, elem_classes=["download-btn"])
269
 
 
270
  status_button.click(
271
  fn=review_blog,
272
  inputs=[text_input, url_input],