JaishnaCodz commited on
Commit
7acb803
·
verified ·
1 Parent(s): 8595ae6

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +191 -81
app.py CHANGED
@@ -6,106 +6,216 @@ import google.generativeai as genai
6
  import os
7
  import re
8
  import tempfile
 
9
 
10
- # Download NLTK tokenizer data
11
  download('punkt')
 
12
 
13
- # Set your Gemini API key
14
  api_key = os.environ.get("GEMINI_API_KEY")
15
  if not api_key:
16
- raise ValueError("GEMINI_API_KEY not found in environment variables")
17
 
18
  genai.configure(api_key=api_key)
19
- model = genai.GenerativeModel("gemini-pro")
20
 
21
- # Helper functions
22
- def extract_text_from_url(url):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
  try:
24
  response = requests.get(url, timeout=10)
25
- soup = BeautifulSoup(response.text, "html.parser")
26
-
27
- for script in soup(["script", "style", "header", "footer", "nav"]):
28
- script.decompose()
29
-
30
- paragraphs = soup.find_all("p")
31
- blog_text = "\n".join(p.get_text() for p in paragraphs if len(p.get_text()) > 40)
32
-
33
- return blog_text.strip()
34
  except Exception as e:
35
- return f"Error extracting content: {str(e)}"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
36
 
37
- def review_blog(blog_text):
38
- prompt = f"""
39
- You are a professional AI blog reviewer and sensitive content analyst.
40
 
41
- Carefully analyze the following blog content for:
42
- 1. Grammar, spelling, and clarity improvements
43
- 2. Crude, harsh, or unprofessional language
44
- 3. Sensitive, biased, offensive, or policy-violating content
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
45
 
46
- Provide detailed suggestions and highlight what should be improved.
 
 
 
47
 
48
- BLOG:
49
- \"\"\"
50
- {blog_text}
51
- \"\"\"
52
- """
53
- response = model.generate_content(prompt)
54
- return response.text
55
 
56
- def process_input(text_input, url_input):
57
- if url_input:
58
- blog_content = extract_text_from_url(url_input)
59
- else:
60
- blog_content = text_input
61
-
62
- if not blog_content or blog_content.strip() == "":
63
- return "Please provide blog content or a valid URL.", None
64
-
65
- analysis = review_blog(blog_content)
66
-
67
- # Create a temporary file with the markdown review
68
- with tempfile.NamedTemporaryFile(mode="w", delete=False, suffix=".md") as tmp_file:
69
- tmp_file.write(analysis)
70
- file_path = tmp_file.name
71
-
72
- return analysis, file_path
73
-
74
- # Gradio UI
75
- with gr.Blocks(theme=gr.themes.Soft()) as demo:
76
- gr.Markdown("# 🧠 AI Blog Reviewer")
77
- gr.Markdown("Review blogs for grammar, clarity, and policy issues using Gemini AI.")
78
-
79
- with gr.Row(equal_height=True):
80
- with gr.Column(scale=3):
81
- with gr.Tabs():
82
- with gr.TabItem("✍️ Text Input"):
83
- text_input = gr.Textbox(
84
- label="Paste Your Blog Content",
85
- placeholder="Write or paste your blog text here...",
86
- lines=12
87
- )
88
- with gr.TabItem("🔗 URL Input"):
89
- url_input = gr.Textbox(
90
- label="Enter Blog URL",
91
- placeholder="https://example.com/blog"
92
- )
93
- with gr.Column(scale=2):
94
- gr.Markdown("""
95
- ### 🚀 How It Works
96
- 1. **Input**: Paste your blog text or provide a blog URL
97
- 2. **Analysis**: Gemini AI checks for grammar, legal violations, and sensitive content
98
- 3. **Report**: Instantly download a structured Markdown review
99
- """)
100
- status_button = gr.Button("🧠 Review Blog")
101
-
102
- output_text = gr.Textbox(label="Review Summary", lines=20)
103
- download_button = gr.File(label="Download Markdown Review")
104
 
 
 
 
 
 
105
  status_button.click(
106
- fn=process_input,
107
  inputs=[text_input, url_input],
108
- outputs=[output_text, download_button]
109
  )
110
 
111
  demo.launch()
 
 
 
 
 
 
6
  import os
7
  import re
8
  import tempfile
9
+ 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")
17
  if not api_key:
18
+ raise ValueError("GEMINI_API_KEY not found in environment variables. Please set it in your environment.")
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):
73
  try:
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;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
+ position: relative;
157
+ }
158
+ .review-btn:hover {
159
+ background-color: #4CAF50;
160
+ color: white;
161
+ transform: scale(1.05);
162
+ }
163
+ .review-btn:disabled {
164
+ opacity: 0.7;
165
+ cursor: not-allowed;
166
+ }
167
+ .review-btn:disabled::before {
168
+ content: '';
169
+ display: inline-block;
170
+ width: 16px;
171
+ height: 16px;
172
+ border: 2px solid #fff;
173
+ border-radius: 50%;
174
+ border-top-color: transparent;
175
+ animation: spin 1s linear infinite;
176
+ margin-right: 8px;
177
+ vertical-align: middle;
178
+ }
179
+ @keyframes spin {
180
+ 0% { transform: rotate(0deg); }
181
+ 100% { transform: rotate(360deg); }
182
+ }
183
+ .tab-nav button {
184
+ font-family: 'Inter', sans-serif;
185
+ font-weight: 500;
186
+ }
187
+ input, textarea {
188
+ font-family: 'Inter', sans-serif;
189
+ }
190
+ """
191
 
192
+ # Gradio UI with Tabs
193
+ with gr.Blocks(theme=gr.themes.Monochrome(), css=custom_css) as demo:
194
+ gr.Markdown("# 📝 AI Blog Reviewer")
195
+ 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.")
196
 
197
+ with gr.Tabs():
198
+ with gr.TabItem("Text"):
199
+ text_input = gr.Textbox(lines=8, label="Blog Content", placeholder="Paste your blog text here...")
200
+ with gr.TabItem("URL"):
201
+ url_input = gr.Textbox(lines=1, label="Blog URL", placeholder="Enter the blog URL here...")
 
 
202
 
203
+ status_button = gr.Button(value="Review Blog", elem_classes=["review-btn"])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
204
 
205
+ gr.Markdown("### 📄 Review Report")
206
+ report_output = gr.Markdown()
207
+ download_btn = gr.File(label="Download Report", visible=False)
208
+
209
+ # Bind the review button to process inputs
210
  status_button.click(
211
+ fn=review_blog,
212
  inputs=[text_input, url_input],
213
+ outputs=[status_button, report_output, download_btn]
214
  )
215
 
216
  demo.launch()
217
+
218
+
219
+ Explain me line by line
220
+ Literally line by line
221
+ Think I'm s beginner,, new to ai, coding n all n explain