JaishnaCodz commited on
Commit
aac72ea
Β·
verified Β·
1 Parent(s): d233c20

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +50 -143
app.py CHANGED
@@ -10,7 +10,6 @@ import asyncio
10
 
11
  # Download NLTK data
12
  download('punkt')
13
- download('punkt_tab')
14
 
15
  # Configure Gemini API using environment variable
16
  api_key = os.environ.get("GEMINI_API_KEY")
@@ -19,54 +18,29 @@ if not api_key:
19
 
20
  genai.configure(api_key=api_key)
21
 
22
- # Use gemini-1.5-flash for faster and more accessible text analysis
23
- try:
24
- model = genai.GenerativeModel('gemini-1.5-flash')
25
- except Exception as e:
26
- # Fallback: List available models if the specified model is not found
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.
37
  2. *Legal Policy Violations*: Flag content that may violate common legal policies (e.g., copyright infringement, defamation, incitement to violence).
38
  3. *Crude/Abusive Language*: Detect crude, offensive, or abusive language.
39
  4. *Sensitive Topics*: Identify content related to sensitive topics such as racism, gender bias, or other forms of discrimination.
40
-
41
  Return the results in the following markdown format:
42
  # Blog Review Report
43
-
44
  ## Grammar Corrections
45
  1. [Heading of issue]
46
  - CONTENT: [Exact line or part of text with the issue]
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
58
  - CONTENT: [Exact line or part of text with the issue]
59
  SUGGESTION: [Suggested action or correction]
60
  ISSUE: [Description of the legal violation]
61
- [Or state "None detected"]
62
-
63
  ## Crude/Abusive Language
64
  - [List instances of crude or abusive language or "None detected"]
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):
@@ -74,161 +48,94 @@ async def fetch_url_content(url):
74
  response = requests.get(url, timeout=10)
75
  response.raise_for_status()
76
  soup = BeautifulSoup(response.text, 'html.parser')
77
- # Extract text from common content tags
78
  content = ' '.join([p.get_text(strip=True) for p in soup.find_all(['p', 'article', 'div'])])
79
  return content if content else "No readable content found on the page."
80
  except Exception as e:
81
  return f"Error fetching URL: {str(e)}"
82
 
83
  async def review_blog(text_input, url_input):
84
- # Start loading effect immediately
85
- button_text = "Processing..."
86
-
87
- # Determine input type based on which field is populated
88
  if text_input and not url_input:
89
- input_type = "Text"
90
  input_text = text_input
91
  elif url_input and not text_input:
92
- input_type = "URL"
93
- input_text = url_input
 
94
  else:
95
- return "Review Blog", "Error: Please provide input in either the Text or URL tab, but not both.", gr.update(visible=False)
96
-
97
- # Handle empty input
98
- if not input_text:
99
- return "Review Blog", "Error: No input provided.", gr.update(visible=False)
100
 
101
  try:
102
- async with asyncio.timeout(30): # 30-second timeout for entire process
103
- # Handle URL input
104
- if input_type == "URL":
105
- button_text = "Fetching content..."
106
- input_text = await fetch_url_content(input_text)
107
- if input_text.startswith("Error"):
108
- return "Review Blog", input_text, gr.update(visible=False)
109
-
110
- # Tokenize input for analysis
111
- sentences = sent_tokenize(input_text)
112
- analysis_text = "\n".join(sentences)
113
-
114
- # Update button for API call
115
- button_text = "Generating report..."
116
- try:
117
- response = await asyncio.to_thread(model.generate_content, PROMPT + "\n\nText to analyze:\n" + analysis_text)
118
- report = response.text.strip()
119
- # Ensure the response is markdown by removing any code fences
120
- report = re.sub(r'^markdown\n|$', '', report, flags=re.MULTILINE)
121
- except Exception as e:
122
- report = f"Error analyzing content with Gemini: {str(e)}. Please check your API key, network connection, or model availability."
123
- # Fallback: List available models for debugging
124
- print("Available models:")
125
- for m in genai.list_models():
126
- print(m.name)
127
- return "Review Blog", report, gr.update(visible=False)
128
-
129
- # Create a temporary file to store the report
130
- try:
131
- with tempfile.NamedTemporaryFile(mode='w', suffix='.md', delete=False, encoding='utf-8') as temp_file:
132
- temp_file.write(report)
133
- temp_file_path = temp_file.name
134
- # Add note to scroll to report
135
- report = f"**Report generated, please scroll down to view.**\n\n{report}"
136
- return "Review Blog", report, gr.update(visible=True, value=temp_file_path)
137
- except Exception as e:
138
- return "Review Blog", f"Error creating temporary file: {str(e)}", gr.update(visible=False)
139
-
140
  except asyncio.TimeoutError:
141
- return "Timeout", "Error: Process timed out after 30 seconds.", 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;600;700&display=swap');
146
  .gradio-container {
147
  font-family: 'Inter', sans-serif !important;
148
- background-color: #f9f9f9;
149
  }
150
  .review-btn {
151
  transition: all 0.3s ease;
152
- font-weight: 600;
153
- font-size: 16px;
154
- background-color: #1f2937;
155
  color: white;
156
- border-radius: 12px;
157
- padding: 12px 24px;
158
- margin-top: 10px;
159
  }
160
  .review-btn:hover {
161
- background-color: #10b981;
162
- transform: scale(1.03);
 
163
  }
164
  .review-btn:disabled {
165
- opacity: 0.6;
166
  cursor: not-allowed;
167
  }
168
- .review-btn:disabled::before {
169
- content: '';
170
- display: inline-block;
171
- width: 16px;
172
- height: 16px;
173
- border: 3px solid #fff;
174
- border-radius: 50%;
175
- border-top-color: transparent;
176
- animation: spin 1s linear infinite;
177
- margin-right: 8px;
178
- vertical-align: middle;
179
- }
180
- @keyframes spin {
181
- 0% { transform: rotate(0deg); }
182
- 100% { transform: rotate(360deg); }
183
  }
184
  input, textarea {
185
  font-family: 'Inter', sans-serif;
186
- font-size: 15px;
187
- padding: 10px;
188
- border-radius: 8px;
189
  }
190
  """
191
 
192
- with gr.Blocks(theme=gr.themes.Base(), css=custom_css) as demo:
193
- gr.Markdown("## πŸ“ AI Blog Reviewer", elem_id="title")
194
- gr.Markdown(
195
- """
196
- <div style="font-size: 16px; color: #444; line-height: 1.6;">
197
- πŸ“Œ Enter your blog text or a blog URL below.<br>
198
- βœ… The AI will check for grammar, legal issues, crude language, and sensitive content.<br>
199
- 🧾 A detailed report will be shown and available to download.
200
- </div>
201
- """,
202
- elem_id="description"
203
- )
204
 
205
  with gr.Tabs():
206
- with gr.TabItem("✍️ Text Input"):
207
- text_input = gr.Textbox(
208
- lines=10,
209
- label="Your Blog Content",
210
- placeholder="Paste your blog text here...",
211
- show_label=True
212
- )
213
- with gr.TabItem("🌐 URL Input"):
214
- url_input = gr.Textbox(
215
- lines=1,
216
- label="Blog URL",
217
- placeholder="Enter the blog URL here...",
218
- show_label=True
219
- )
220
-
221
- status_button = gr.Button(value="πŸš€ Review Blog", elem_classes=["review-btn"])
222
 
 
223
  gr.Markdown("### πŸ“„ Review Report")
224
- report_output = gr.Markdown(elem_id="report-markdown")
225
- download_btn = gr.File(label="πŸ“₯ Download Markdown Report", visible=False)
 
 
226
 
227
- # Bind button click
228
  status_button.click(
229
  fn=review_blog,
230
  inputs=[text_input, url_input],
231
- outputs=[status_button, report_output, download_btn]
232
  )
233
 
234
- demo.launch()
 
10
 
11
  # Download NLTK data
12
  download('punkt')
 
13
 
14
  # Configure Gemini API using environment variable
15
  api_key = os.environ.get("GEMINI_API_KEY")
 
18
 
19
  genai.configure(api_key=api_key)
20
 
21
+ model = genai.GenerativeModel('gemini-1.5-flash')
22
+
 
 
 
 
 
 
 
 
 
 
23
  PROMPT = """
24
  You are an AI content reviewer. Analyze the provided text for the following:
25
  1. *Grammar Issues*: Identify and suggest corrections for grammatical errors.
26
  2. *Legal Policy Violations*: Flag content that may violate common legal policies (e.g., copyright infringement, defamation, incitement to violence).
27
  3. *Crude/Abusive Language*: Detect crude, offensive, or abusive language.
28
  4. *Sensitive Topics*: Identify content related to sensitive topics such as racism, gender bias, or other forms of discrimination.
 
29
  Return the results in the following markdown format:
30
  # Blog Review Report
 
31
  ## Grammar Corrections
32
  1. [Heading of issue]
33
  - CONTENT: [Exact line or part of text with the issue]
34
  - SUGGESTION: [Suggested correction]
35
  - ISSUE: [Description of the issue]
 
 
 
 
 
 
 
 
36
  ## Legal Policy Violations
37
  - CONTENT: [Exact line or part of text with the issue]
38
  SUGGESTION: [Suggested action or correction]
39
  ISSUE: [Description of the legal violation]
 
 
40
  ## Crude/Abusive Language
41
  - [List instances of crude or abusive language or "None detected"]
 
42
  ## Sensitive Topics
43
  - [List instances of sensitive topics or "None detected"]
 
 
44
  """
45
 
46
  async def fetch_url_content(url):
 
48
  response = requests.get(url, timeout=10)
49
  response.raise_for_status()
50
  soup = BeautifulSoup(response.text, 'html.parser')
 
51
  content = ' '.join([p.get_text(strip=True) for p in soup.find_all(['p', 'article', 'div'])])
52
  return content if content else "No readable content found on the page."
53
  except Exception as e:
54
  return f"Error fetching URL: {str(e)}"
55
 
56
  async def review_blog(text_input, url_input):
 
 
 
 
57
  if text_input and not url_input:
 
58
  input_text = text_input
59
  elif url_input and not text_input:
60
+ input_text = await fetch_url_content(url_input)
61
+ if input_text.startswith("Error"):
62
+ return "Review Blog", input_text, gr.update(visible=False), ""
63
  else:
64
+ return "Review Blog", "Error: Please provide input in either the Text or URL tab, but not both.", gr.update(visible=False), ""
 
 
 
 
65
 
66
  try:
67
+ sentences = sent_tokenize(input_text)
68
+ analysis_text = "\n".join(sentences)
69
+ response = await asyncio.to_thread(model.generate_content, PROMPT + "\n\nText to analyze:\n" + analysis_text)
70
+ report = response.text.strip()
71
+
72
+ suggestions = re.findall(r'- CONTENT: (.*?)\n\s*SUGGESTION: (.*?)\n\s*ISSUE: (.*?)\n', report, re.DOTALL)
73
+ highlighted = input_text
74
+ for content, suggestion, issue in suggestions:
75
+ highlighted = highlighted.replace(content, f'<span style="background-color: #ffcccc;" title="{issue} | Suggested: {suggestion}">{content}</span>')
76
+
77
+ with tempfile.NamedTemporaryFile(mode='w', suffix='.md', delete=False, encoding='utf-8') as temp_file:
78
+ temp_file.write(report)
79
+ temp_file_path = temp_file.name
80
+
81
+ report = f"**Report generated, please scroll down to view.**\n\n{report}"
82
+ return "Review Blog", report, gr.update(visible=True, value=temp_file_path), highlighted
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
83
  except asyncio.TimeoutError:
84
+ return "Timeout", "Error: Process timed out after 30 seconds.", gr.update(visible=False), ""
85
 
 
86
  custom_css = """
87
+ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap');
88
  .gradio-container {
89
  font-family: 'Inter', sans-serif !important;
 
90
  }
91
  .review-btn {
92
  transition: all 0.3s ease;
93
+ font-weight: 500;
94
+ background-color: #2c3e50;
 
95
  color: white;
96
+ border-radius: 8px;
97
+ padding: 10px 20px;
98
+ position: relative;
99
  }
100
  .review-btn:hover {
101
+ background-color: #4CAF50;
102
+ color: white;
103
+ transform: scale(1.05);
104
  }
105
  .review-btn:disabled {
106
+ opacity: 0.7;
107
  cursor: not-allowed;
108
  }
109
+ .tab-nav button {
110
+ font-family: 'Inter', sans-serif;
111
+ font-weight: 500;
 
 
 
 
 
 
 
 
 
 
 
 
112
  }
113
  input, textarea {
114
  font-family: 'Inter', sans-serif;
 
 
 
115
  }
116
  """
117
 
118
+ with gr.Blocks(theme=gr.themes.Monochrome(), css=custom_css) as demo:
119
+ gr.Markdown("# πŸ“ AI Blog Reviewer")
120
+ gr.Markdown("Enter blog text or a URL to review. Issues will be highlighted in the content and summarized in a downloadable report.")
 
 
 
 
 
 
 
 
 
121
 
122
  with gr.Tabs():
123
+ with gr.TabItem("Text"):
124
+ text_input = gr.Textbox(lines=8, label="Blog Content", placeholder="Paste your blog text here...")
125
+ with gr.TabItem("URL"):
126
+ url_input = gr.Textbox(lines=1, label="Blog URL", placeholder="Enter the blog URL here...")
 
 
 
 
 
 
 
 
 
 
 
 
127
 
128
+ status_button = gr.Button(value="Review Blog", elem_classes=["review-btn"])
129
  gr.Markdown("### πŸ“„ Review Report")
130
+ report_output = gr.Markdown()
131
+ download_btn = gr.File(label="Download Report", visible=False)
132
+ gr.Markdown("### πŸ” Highlighted Blog Content")
133
+ highlighted_text = gr.HTML()
134
 
 
135
  status_button.click(
136
  fn=review_blog,
137
  inputs=[text_input, url_input],
138
+ outputs=[status_button, report_output, download_btn, highlighted_text]
139
  )
140
 
141
+ demo.launch()