mroccuper commited on
Commit
821541f
Β·
verified Β·
1 Parent(s): fe92e03

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +185 -96
app.py CHANGED
@@ -10,49 +10,52 @@ class PRArticleGenerator:
10
  def __init__(self):
11
  self.pr_prompt = """
12
  πŸ”§ SYSTEM ROLE:
13
- You are an elite PR copywriter and strategic storyteller trusted by Forbes-level publishers, corporate PR firms, and influential entrepreneurs. Your role is to turn raw business content, personal bios, investment stories, or news leads into a **professionally polished, PR-grade article** optimized for SEO, brand perception, and online publication.
14
 
15
  🎯 OBJECTIVE:
16
- - Transform the user's input into a **trustworthy, media-ready PR article**.
17
- - Use a **neutral-positive, authoritative tone**β€”like a feature in Bloomberg, Forbes, or Business Insider.
18
- - Follow a **Rank Math-optimized structure** to improve search visibility and engagement.
19
 
20
  🧠 CONTENT STRATEGY:
21
  Mimic top-tier PR publications using this structure:
22
- 1. **Headline (`<h1>`)**: Strong, keyword-rich, and lightly sensational.
23
- 2. **Intro Paragraph**: News-style lead. Who, what, when, where, why β€” concise and compelling.
24
- 3. **Market/Impact Context**: Explain why this news matters (industry, public interest, regional economy, innovation).
25
- 4. **About the Subject**: Short professional bio (person or company) with relevant credentials.
26
- 5. **Portfolio Highlights or Track Record**: A bullet-point or paragraph list of relevant deals, actions, or achievements.
27
- 6. **Vision, Quote, or Strategy Statement**: Add a realistic, forward-looking quote or strategic comment from the figure or brand.
28
- 7. **Closing Paragraph**: Summarize the long-term significance, expected outcomes, or broader vision.
 
29
 
30
- βœ… SEO RULES (Rank Math-Ready):
31
- - Target **one primary keyword** (from the input or suggest one).
32
- - Insert the keyword in:
33
  - `<h1>` title
34
- - First 100 words
35
- - At least one `<h2>`
36
  - Last paragraph
37
- - Use semantic synonyms naturally (LSI terms).
38
- - Apply proper heading tags (`<h2>`, `<p>`, `<ul>`, `<strong>`) for WordPress.
39
- - Ensure 600+ words for standard articles (unless input is very short).
40
- - NEVER keyword-stuff. Prioritize clarity, professionalism, and semantic variation.
 
41
 
42
  🌍 TARGET AUDIENCE:
43
- - Business readers, investors, journalists, and industry stakeholders.
44
- - Tone: Strategic, editorial, and refined β€” NOT hypey or salesy.
45
 
46
  🎨 FORMATTING:
47
  - Structure article in clean **WordPress-compatible HTML**.
48
- - Use `<h2>` subheadings for each section.
49
- - Bullet lists for portfolio highlights or key achievements.
50
- - Insert **1 vision-driven quote** (real or fictional) if none provided.
 
51
  - Ready to paste into any CMS or press distribution tool.
52
  - Return ONLY the HTML content without any markdown code blocks or backticks.
53
 
54
  πŸ“₯ INPUT FORMAT:
55
- User may provide raw facts, a bio, a business update, or a rough news draft.
56
 
57
  πŸ“€ OUTPUT FORMAT:
58
  - Return a fully structured PR article with HTML formatting.
@@ -67,6 +70,7 @@ User may provide raw facts, a bio, a business update, or a rough news draft.
67
 
68
  Please transform the following content into a professional PR-style article:
69
  """
 
70
 
71
  def clean_html_output(self, text):
72
  """Remove markdown code blocks and clean HTML output"""
@@ -106,97 +110,144 @@ Please transform the following content into a professional PR-style article:
106
  # Custom PR writing metrics
107
  pr_score = self.calculate_pr_score(text, clean_text)
108
 
109
- # Normalize Flesch score to 1-10 scale
110
- readability_base = min(10, max(1, (flesch_score / 10)))
 
111
 
112
  # Combined score (60% readability, 40% PR best practices)
113
  final_score = (readability_base * 0.6) + (pr_score * 0.4)
114
 
115
- return round(final_score, 1), self.get_improvement_suggestions(flesch_score, avg_sentence_length, syllable_count, text)
116
 
117
  except Exception as e:
118
  return 5.0, f"Error calculating readability: {str(e)}"
119
 
120
  def calculate_pr_score(self, html_text, clean_text):
121
- """Calculate score based on PR writing best practices"""
122
  score = 0
123
- max_score = 10
124
 
125
- # Check for proper HTML structure (H1, H2 tags)
126
- if re.search(r'<h1>', html_text, re.IGNORECASE):
127
- score += 1.5
128
- if re.search(r'<h2>', html_text, re.IGNORECASE):
 
129
  score += 1.5
130
-
131
- # Check for bullet points/lists
132
- if re.search(r'<ul>|<ol>', html_text, re.IGNORECASE):
133
- score += 1
134
-
135
- # Check for strong/bold text
136
- if re.search(r'<strong>|<b>', html_text, re.IGNORECASE):
137
  score += 1
138
-
139
- # Check word count (600+ words is ideal for PR)
 
 
 
 
140
  word_count = len(clean_text.split())
141
- if word_count >= 600:
142
  score += 2
143
- elif word_count >= 400:
144
  score += 1.5
145
- elif word_count >= 200:
146
  score += 1
147
 
148
- # Check for quotes (professional credibility)
149
- if '"' in clean_text and clean_text.count('"') >= 2:
 
150
  score += 1
 
 
151
 
152
- # Check for numbers/statistics (authority building)
153
- if re.search(r'\d+%|\$\d+|[\d,]+\s*(million|billion|thousand)', clean_text):
154
- score += 1.5
155
-
156
- # Check for professional language patterns
157
- professional_indicators = ['according to', 'announced', 'reported', 'confirmed', 'revealed']
158
- if any(indicator in clean_text.lower() for indicator in professional_indicators):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
159
  score += 0.5
160
 
161
  return min(max_score, score)
162
 
163
- def get_improvement_suggestions(self, flesch_score, avg_sentence_length, syllable_count, html_text):
164
- """Generate specific improvement suggestions"""
165
  suggestions = []
166
 
167
- if flesch_score < 50:
168
- suggestions.append("β€’ Simplify complex sentences - aim for 15-20 words per sentence")
169
- if avg_sentence_length > 25:
170
- suggestions.append("β€’ Break down long sentences for better readability")
171
- if syllable_count > 1.8:
172
- suggestions.append("β€’ Use simpler words where possible without losing professionalism")
173
- if not re.search(r'<h2>', html_text, re.IGNORECASE):
174
- suggestions.append("β€’ Add more H2 subheadings to improve structure and SEO")
 
 
 
 
175
  if not re.search(r'<ul>|<ol>', html_text, re.IGNORECASE):
176
- suggestions.append("β€’ Include bullet points or lists for better scannability")
177
- if len(html_text.split()) < 600:
178
- suggestions.append("β€’ Expand content to reach 600+ words for better SEO performance")
179
- if html_text.count('"') < 2:
180
- suggestions.append("β€’ Add relevant quotes to increase credibility and engagement")
181
- if not re.search(r'\d+%|\$\d+|[\d,]+', html_text):
182
- suggestions.append("β€’ Include specific numbers, statistics, or financial data for authority")
 
 
183
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
184
  if not suggestions:
185
- suggestions.append("β€’ Excellent! Your content meets PR writing best practices.")
186
 
187
  return "\n".join(suggestions)
188
 
189
  def generate_article(self, api_key, content, max_length=None):
190
  """Generate PR-style article using Gemini API"""
191
  if not api_key.strip():
192
- return "❌ Error: Please enter your Gemini API key", "", None
193
 
194
  if not content.strip():
195
- return "❌ Error: Please enter content to transform", "", None
196
 
197
  model, error = self.setup_gemini(api_key)
198
  if error:
199
- return f"❌ {error}", "", None
200
 
201
  try:
202
  # Generate article
@@ -204,11 +255,25 @@ Please transform the following content into a professional PR-style article:
204
  response = model.generate_content(full_prompt)
205
 
206
  if not response.text:
207
- return "❌ Error: No response generated from API", "", None
208
 
209
  # Clean the HTML output to remove markdown code blocks
210
  article_html = self.clean_html_output(response.text.strip())
211
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
212
  # Create downloadable file
213
  timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
214
  filename = f"pr_article_{timestamp}.html"
@@ -235,12 +300,12 @@ Please transform the following content into a professional PR-style article:
235
  </html>""")
236
  temp_file.close()
237
 
238
- success_msg = f"βœ… Article generated successfully!"
239
 
240
- return success_msg, article_html, temp_file.name
241
 
242
  except Exception as e:
243
- return f"❌ Generation Error: {str(e)}", "", None
244
 
245
  def create_interface():
246
  generator = PRArticleGenerator()
@@ -255,17 +320,29 @@ def create_interface():
255
  padding: 10px;
256
  border-radius: 5px;
257
  margin: 10px 0;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
258
  }
259
- .error { color: #e74c3c; }
260
- .success { color: #27ae60; }
261
- .warning { color: #f39c12; }
262
  """
263
 
264
- with gr.Blocks(css=css, title="PR Article Generator", theme=gr.themes.Soft()) as interface:
265
  gr.HTML("""
266
  <div class="header">
267
  <h1>🎯 Elite PR Article Generator</h1>
268
- <p>Transform any content into professional PR-style articles optimized for SEO and media consumption</p>
269
  </div>
270
  """)
271
 
@@ -282,19 +359,19 @@ def create_interface():
282
 
283
  content_input = gr.Textbox(
284
  label="πŸ“„ Content to Transform",
285
- placeholder="Paste your raw content, news, facts, or story here...\n\nExample:\n- Company announcement\n- Business news\n- Achievement story\n- Product launch details\n- Executive biography",
286
  lines=15,
287
  max_lines=20
288
  )
289
 
290
  generate_btn = gr.Button(
291
- "πŸš€ Generate PR Article",
292
  variant="primary",
293
  size="lg"
294
  )
295
 
296
  with gr.Column(scale=1):
297
- gr.HTML("<h3>πŸ“Š Output & Status</h3>")
298
 
299
  status_output = gr.Textbox(
300
  label="πŸ“‹ Status",
@@ -302,6 +379,18 @@ def create_interface():
302
  interactive=False
303
  )
304
 
 
 
 
 
 
 
 
 
 
 
 
 
305
  download_file = gr.File(
306
  label="πŸ“₯ Download HTML Article",
307
  interactive=False
@@ -319,16 +408,16 @@ def create_interface():
319
  generate_btn.click(
320
  fn=generator.generate_article,
321
  inputs=[api_key_input, content_input],
322
- outputs=[status_output, article_output, download_file]
323
  )
324
 
325
  # Add examples
326
  gr.HTML("""
327
- <div style="margin-top: 30px; padding: 20px;border-radius: 10px;">
328
  <h3>πŸ’‘ Example Input Content:</h3>
329
- <p><strong>Business Acquisition:</strong> "Tech entrepreneur John Smith announced the acquisition of downtown office building for $15M. Smith, who previously founded two successful startups, plans to convert the space into a modern co-working hub."</p>
330
- <p><strong>Product Launch:</strong> "AI company releases new software that reduces processing time by 60%. The tool has been tested by 500+ businesses with positive results."</p>
331
- <p><strong>Executive Profile:</strong> "Sarah Johnson, CEO of GreenTech Solutions, graduated from MIT and led three successful IPOs. Her company just secured $50M in Series B funding."</p>
332
  </div>
333
  """)
334
 
@@ -345,5 +434,5 @@ if __name__ == "__main__":
345
 
346
  app = create_interface()
347
  app.launch(
348
-
349
- )
 
10
  def __init__(self):
11
  self.pr_prompt = """
12
  πŸ”§ SYSTEM ROLE:
13
+ You are an elite PR copywriter and strategic storyteller, trusted by Forbes-level publishers, corporate PR firms, and influential entrepreneurs. Your role is to transform raw business content, personal bios, investment stories, or news leads into a **professionally polished, elite-grade PR article** optimized for SEO, brand perception, and high-impact online publication.
14
 
15
  🎯 OBJECTIVE:
16
+ - Transform the user's input into a **trustworthy, media-ready PR article with strategic depth and journalistic integrity**.
17
+ - Use a **neutral-positive, authoritative, and sophisticated tone**β€”like a feature in Bloomberg, Forbes, or Business Insider.
18
+ - Follow a **Rank Math-optimized structure** to improve search visibility and engagement, ensuring narrative flow and impactful messaging.
19
 
20
  🧠 CONTENT STRATEGY:
21
  Mimic top-tier PR publications using this structure:
22
+ 1. **Headline (`<h1>`)**: Strong, keyword-rich, highly engaging, and precisely reflects the core news, aiming for virality without sensationalism.
23
+ 2. **Intro Paragraph**: News-style lead. Who, what, when, where, why β€” concise, compelling, and immediately establishes the article's significance.
24
+ 3. **Market/Impact Context (`<h2>`)**: Provide a robust analysis of the market landscape, competitive positioning, and the long-term implications of this news. Connect the development to broader industry trends or societal shifts, illustrating its strategic importance and why it truly matters.
25
+ 4. **About the Subject (`<h2>`)**: Craft a compelling narrative around the individual or company, emphasizing their unique vision, core values, and the distinctive philosophy driving their success. Go beyond mere credentials to illustrate their leadership impact and market influence.
26
+ 5. **Portfolio Highlights or Track Record (`<h2>`)**: A concise bullet-point or paragraph list of relevant, high-impact deals, significant actions, or verifiable achievements that underscore credibility and success. Quantify where possible.
27
+ 6. **Vision, Quote, or Strategy Statement (`<h2>`)**: Generate a visionary, impactful quote that not only articulates future plans but also conveys the underlying philosophy, strategic foresight, and commitment to long-term value creation. The quote should resonate with investors and industry leaders.
28
+ 7. **Key Differentiators/Unique Value Proposition (`<h2>` - Optional but Recommended if applicable):** Briefly articulate what truly sets the subject or company apart – be it their innovative technology, groundbreaking business model, distinctive cultural approach, or specialized market niche.
29
+ 8. **Closing Paragraph (`<h2>`)**: Conclude with a powerful summary that underscores the enduring significance of the announcement, reinforcing the company's trajectory, its commitment to innovation, and its anticipated long-term impact on the industry or broader ecosystem. This should be a memorable final statement.
30
 
31
+ βœ… SEO RULES (Rank Math-Ready & Elite Optimization):
32
+ - Target **one primary keyword** (from the input or suggest one, ensuring it's highly relevant).
33
+ - Insert the keyword strategically and naturally in:
34
  - `<h1>` title
35
+ - First 100 words (prominently)
36
+ - At least one `<h2>` subheading
37
  - Last paragraph
38
+ - Aim for a natural keyword density (approx. 0.5-1.5%).
39
+ - Use semantic synonyms and Latent Semantic Indexing (LSI) terms naturally throughout the text.
40
+ - Apply proper heading tags (`<h2>`, `<p>`, `<ul>`, `<strong>`) for optimal WordPress compatibility and readability.
41
+ - Ensure 600+ words for standard articles (unless the input content is extremely brief), prioritizing depth over brevity.
42
+ - NEVER keyword-stuff. Prioritize clarity, professionalism, semantic variation, and reader value over keyword density.
43
 
44
  🌍 TARGET AUDIENCE:
45
+ - Sophisticated business readers, institutional investors, top-tier journalists, industry analysts, and strategic stakeholders.
46
+ - Tone: Strategic, editorial, refined, and highly credible β€” absolutely NOT hypey, salesy, or overly promotional. Maintain a detached, objective yet positive journalistic voice.
47
 
48
  🎨 FORMATTING:
49
  - Structure article in clean **WordPress-compatible HTML**.
50
+ - Use `<h2>` subheadings for each primary section as outlined above.
51
+ - Employ bullet lists (`<ul>` or `<ol>`) for portfolio highlights or key achievements for easy scannability.
52
+ - Insert **1 to 2 vision-driven, high-quality quotes** (real or fictional if not provided, ensuring they sound authentic to a CEO/leader).
53
+ - Ensure readability for a broad, intelligent audience.
54
  - Ready to paste into any CMS or press distribution tool.
55
  - Return ONLY the HTML content without any markdown code blocks or backticks.
56
 
57
  πŸ“₯ INPUT FORMAT:
58
+ User may provide raw facts, a detailed bio, a business update, or a rough news draft. The AI should infer the central narrative and elaborate it into a full PR article.
59
 
60
  πŸ“€ OUTPUT FORMAT:
61
  - Return a fully structured PR article with HTML formatting.
 
70
 
71
  Please transform the following content into a professional PR-style article:
72
  """
73
+ self.target_keyword = None # To store the extracted keyword for scoring
74
 
75
  def clean_html_output(self, text):
76
  """Remove markdown code blocks and clean HTML output"""
 
110
  # Custom PR writing metrics
111
  pr_score = self.calculate_pr_score(text, clean_text)
112
 
113
+ # Normalize Flesch score to 1-10 scale (Flesch maxes around 120, typical good is 60-70)
114
+ # A score of 60-70 is generally good for PR; scale 30-70 roughly to 0-10
115
+ readability_base = max(0, min(10, (flesch_score - 30) / 4))
116
 
117
  # Combined score (60% readability, 40% PR best practices)
118
  final_score = (readability_base * 0.6) + (pr_score * 0.4)
119
 
120
+ return round(final_score, 1), self.get_improvement_suggestions(flesch_score, avg_sentence_length, syllable_count, text, clean_text)
121
 
122
  except Exception as e:
123
  return 5.0, f"Error calculating readability: {str(e)}"
124
 
125
  def calculate_pr_score(self, html_text, clean_text):
126
+ """Calculate score based on PR writing best practices for Elite PR"""
127
  score = 0
128
+ max_score = 10 # Total points available for PR best practices
129
 
130
+ # 1. HTML Structure & Formatting (Max 3 points)
131
+ if re.search(r'<h1>', html_text, re.IGNORECASE): # H1 presence
132
+ score += 0.5
133
+ h2_count = len(re.findall(r'<h2>', html_text, re.IGNORECASE))
134
+ if h2_count >= 6: # At least 6 H2s for detailed elite structure (including SEO Metadata)
135
  score += 1.5
136
+ elif h2_count >= 4:
 
 
 
 
 
 
137
  score += 1
138
+ if re.search(r'<ul>|<ol>', html_text, re.IGNORECASE): # Lists for scannability
139
+ score += 0.5
140
+ if re.search(r'<strong>|<b>', html_text, re.IGNORECASE): # Strong text for emphasis
141
+ score += 0.5
142
+
143
+ # 2. Content Depth & Word Count (Max 2 points)
144
  word_count = len(clean_text.split())
145
+ if word_count >= 800: # Elite articles often longer for depth
146
  score += 2
147
+ elif word_count >= 600:
148
  score += 1.5
149
+ elif word_count >= 400:
150
  score += 1
151
 
152
+ # 3. Credibility & Authority (Max 2 points)
153
+ # Check for quotes (professional credibility) - aim for 2+ distinct quotes
154
+ if clean_text.count('"') >= 4: # At least two full quotes (4 quote marks)
155
  score += 1
156
+ elif clean_text.count('"') >= 2:
157
+ score += 0.5
158
 
159
+ # Check for numbers/statistics/financial data (authority building)
160
+ # Looks for percentages, dollar amounts, and large number terms
161
+ if re.search(r'\d+%|\$\s*\d+(?:,\d{3})*(?:\.\d{2})?|[\d,]+\s*(?:million|billion|thousand|trillion)\b', clean_text, re.IGNORECASE):
162
+ score += 1
163
+
164
+ # 4. Keyword Integration (Max 1.5 points)
165
+ if self.target_keyword:
166
+ keyword_lower = self.target_keyword.lower()
167
+ # Check H1
168
+ if re.search(r'<h1>.*?'+re.escape(keyword_lower)+'.*?</h1>', html_text, re.IGNORECASE):
169
+ score += 0.5
170
+ # Check first 200 words
171
+ if keyword_lower in clean_text[:200].lower():
172
+ score += 0.5
173
+ # Check last 200 words
174
+ if keyword_lower in clean_text[-200:].lower():
175
+ score += 0.5
176
+
177
+ # 5. Tone & Professionalism (Max 1 point)
178
+ # Check for absence of hype words (negative scoring for presence)
179
+ hype_words = ['unbelievable', 'game-changing', 'revolutionary', 'groundbreaking', 'amazing', 'stunning', 'incredible', 'breakthrough']
180
+ if not any(word in clean_text.lower() for word in hype_words):
181
+ score += 0.5 # Reward for mature tone
182
+
183
+ # Check for presence of strategic/journalistic language
184
+ strategic_indicators = ['strategic', 'implications', 'visionary', 'innovation', 'leadership', 'market dynamics', 'ecosystem', 'trajectory', 'future-forward', 'robust analysis', 'pivotal moment', 'transformative', 'significant investment']
185
+ if sum(1 for indicator in strategic_indicators if indicator in clean_text.lower()) >= 5: # At least 5 strategic terms
186
  score += 0.5
187
 
188
  return min(max_score, score)
189
 
190
+ def get_improvement_suggestions(self, flesch_score, avg_sentence_length, syllable_count, html_text, clean_text):
191
+ """Generate specific improvement suggestions for Elite PR"""
192
  suggestions = []
193
 
194
+ # Readability suggestions
195
+ if flesch_score < 60: # Aim for 60-70 for good readability
196
+ suggestions.append("β€’ Improve Flesch Reading Ease: Simplify sentence structures, reduce jargon, and break down complex ideas. Aim for a score of 60-70.")
197
+ if avg_sentence_length > 22: # Keep sentences concise for impact
198
+ suggestions.append("β€’ Reduce average sentence length to enhance flow and clarity. Aim for 18-22 words per sentence.")
199
+ if syllable_count > 1.6: # Use more common words
200
+ suggestions.append("β€’ Opt for more accessible vocabulary where appropriate, without sacrificing professionalism.")
201
+
202
+ # Structure & Content suggestions
203
+ h2_count = len(re.findall(r'<h2>', html_text, re.IGNORECASE))
204
+ if h2_count < 6: # Including SEO Metadata, we expect around 6-8 H2s
205
+ suggestions.append(f"β€’ Incorporate more descriptive H2 subheadings (currently {h2_count}) to segment the article and improve SEO/scannability. Aim for 6-8 sections.")
206
  if not re.search(r'<ul>|<ol>', html_text, re.IGNORECASE):
207
+ suggestions.append("β€’ Utilize bullet points or numbered lists to highlight key achievements, making content more digestible.")
208
+ if len(clean_text.split()) < 600:
209
+ suggestions.append("β€’ Expand the article's content to reach at least 600-800 words for comprehensive coverage and better SEO depth.")
210
+
211
+ # Credibility & Impact suggestions
212
+ if clean_text.count('"') < 4: # Less than two full quotes
213
+ suggestions.append("β€’ Include at least two insightful and forward-looking quotes to enhance credibility and provide a strong leadership voice.")
214
+ if not re.search(r'\d+%|\$\s*\d+(?:,\d{3})*(?:\.\d{2})?|[\d,]+\s*(?:million|billion|thousand|trillion)\b', clean_text, re.IGNORECASE):
215
+ suggestions.append("β€’ Integrate specific metrics, financial figures, or quantifiable achievements to add authority and impact.")
216
 
217
+ # SEO & Tone suggestions
218
+ if self.target_keyword:
219
+ keyword_lower = self.target_keyword.lower()
220
+ if not re.search(r'<h1>.*?'+re.escape(keyword_lower)+'.*?</h1>', html_text, re.IGNORECASE):
221
+ suggestions.append(f"β€’ Ensure the target keyword '{self.target_keyword}' is present in the H1 title for optimal SEO.")
222
+ if keyword_lower not in clean_text[:200].lower():
223
+ suggestions.append(f"β€’ Place the target keyword '{self.target_keyword}' within the first 200 words of the article.")
224
+ if keyword_lower not in clean_text[-200:].lower():
225
+ suggestions.append(f"β€’ Include the target keyword '{self.target_keyword}' in the concluding paragraph.")
226
+
227
+ hype_words = ['unbelievable', 'game-changing', 'revolutionary', 'groundbreaking', 'amazing', 'stunning', 'incredible', 'breakthrough']
228
+ if any(word in clean_text.lower() for word in hype_words):
229
+ suggestions.append("β€’ Review language for overly promotional or 'hypey' terms. Elite PR uses a more measured, authoritative tone.")
230
+
231
+ strategic_indicators = ['strategic', 'implications', 'visionary', 'innovation', 'leadership', 'market dynamics', 'ecosystem', 'trajectory', 'future-forward', 'robust analysis', 'pivotal moment', 'transformative', 'significant investment']
232
+ if sum(1 for indicator in strategic_indicators if indicator in clean_text.lower()) < 5:
233
+ suggestions.append("β€’ Incorporate more strategic and analytical language to convey depth, expertise, and a broader market perspective.")
234
+
235
  if not suggestions:
236
+ suggestions.append("β€’ Your article is exceptionally well-crafted, adhering to elite PR standards! No major improvements suggested.")
237
 
238
  return "\n".join(suggestions)
239
 
240
  def generate_article(self, api_key, content, max_length=None):
241
  """Generate PR-style article using Gemini API"""
242
  if not api_key.strip():
243
+ return "❌ Error: Please enter your Gemini API key", "", None, "", ""
244
 
245
  if not content.strip():
246
+ return "❌ Error: Please enter content to transform", "", None, "", ""
247
 
248
  model, error = self.setup_gemini(api_key)
249
  if error:
250
+ return f"❌ {error}", "", None, "", ""
251
 
252
  try:
253
  # Generate article
 
255
  response = model.generate_content(full_prompt)
256
 
257
  if not response.text:
258
+ return "❌ Error: No response generated from API", "", None, "", ""
259
 
260
  # Clean the HTML output to remove markdown code blocks
261
  article_html = self.clean_html_output(response.text.strip())
262
 
263
+ # Extract SEO metadata to pass to readability score
264
+ # Regex to find the target keyword within the SEO Metadata list
265
+ target_keyword_match = re.search(r'<li><strong>Target Keyword:</strong>\s*(.*?)</li>', article_html, re.IGNORECASE)
266
+
267
+ # Store target keyword for scoring
268
+ self.target_keyword = target_keyword_match.group(1).strip() if target_keyword_match else None
269
+
270
+ # Calculate readability and suggestions
271
+ readability_score, suggestions = self.calculate_readability_score(article_html)
272
+
273
+ # Prepare readability display
274
+ score_color = "error" if readability_score < 6.0 else ("warning" if readability_score < 8.0 else "success")
275
+ readability_display = f"<div class='score-display {score_color}'>Elite PR Score: {readability_score}/10</div>"
276
+
277
  # Create downloadable file
278
  timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
279
  filename = f"pr_article_{timestamp}.html"
 
300
  </html>""")
301
  temp_file.close()
302
 
303
+ success_msg = f"βœ… Article generated successfully! See Elite PR Score and suggestions below."
304
 
305
+ return success_msg, article_html, temp_file.name, readability_display, suggestions
306
 
307
  except Exception as e:
308
+ return f"❌ Generation Error: {str(e)}", "", None, "", ""
309
 
310
  def create_interface():
311
  generator = PRArticleGenerator()
 
320
  padding: 10px;
321
  border-radius: 5px;
322
  margin: 10px 0;
323
+ text-align: center;
324
+ }
325
+ .error { background-color: #fcecec; color: #e74c3c; border: 1px solid #e74c3c; }
326
+ .success { background-color: #e8fce8; color: #27ae60; border: 1px solid #27ae60; }
327
+ .warning { background-color: #fff9e6; color: #f39c12; border: 1px solid #f39c12; }
328
+ .suggestions-box {
329
+ background-color: #f8f8f8;
330
+ border: 1px solid #ddd;
331
+ padding: 15px;
332
+ border-radius: 8px;
333
+ margin-top: 20px;
334
+ }
335
+ .suggestions-box h3 {
336
+ color: #34495e;
337
+ margin-top: 0;
338
  }
 
 
 
339
  """
340
 
341
+ with gr.Blocks(css=css, title="Elite PR Article Generator", theme=gr.themes.Soft()) as interface:
342
  gr.HTML("""
343
  <div class="header">
344
  <h1>🎯 Elite PR Article Generator</h1>
345
+ <p>Transform any content into professional, high-impact PR-style articles optimized for SEO and top-tier media consumption.</p>
346
  </div>
347
  """)
348
 
 
359
 
360
  content_input = gr.Textbox(
361
  label="πŸ“„ Content to Transform",
362
+ placeholder="Paste your raw content, news, facts, or story here...\n\nExample:\n- Company announcement detailing a funding round, acquisition, or strategic partnership.\n- In-depth executive biography highlighting leadership philosophy and career milestones.\n- Detailed product launch outlining market problem, solution, and future roadmap.\n- Business news covering a major achievement or industry impact.",
363
  lines=15,
364
  max_lines=20
365
  )
366
 
367
  generate_btn = gr.Button(
368
+ "πŸš€ Generate Elite PR Article",
369
  variant="primary",
370
  size="lg"
371
  )
372
 
373
  with gr.Column(scale=1):
374
+ gr.HTML("<h3>πŸ“Š Output & Performance</h3>")
375
 
376
  status_output = gr.Textbox(
377
  label="πŸ“‹ Status",
 
379
  interactive=False
380
  )
381
 
382
+ readability_score_output = gr.HTML(
383
+ value="", # Placeholder for the score display
384
+ label="Elite PR Score"
385
+ )
386
+
387
+ suggestions_output = gr.Textbox(
388
+ label="πŸ’‘ Improvement Suggestions",
389
+ lines=8,
390
+ interactive=False,
391
+ elem_classes="suggestions-box"
392
+ )
393
+
394
  download_file = gr.File(
395
  label="πŸ“₯ Download HTML Article",
396
  interactive=False
 
408
  generate_btn.click(
409
  fn=generator.generate_article,
410
  inputs=[api_key_input, content_input],
411
+ outputs=[status_output, article_output, download_file, readability_score_output, suggestions_output]
412
  )
413
 
414
  # Add examples
415
  gr.HTML("""
416
+ <div style="margin-top: 30px; padding: 20px; border-radius: 10px;">
417
  <h3>πŸ’‘ Example Input Content:</h3>
418
+ <p><strong>Business Acquisition:</strong> "Global tech leader InnovateCo today announced its strategic acquisition of cutting-edge AI startup, Nexus Solutions, for $150 million in cash. The acquisition aims to integrate Nexus's patented machine learning algorithms into InnovateCo's enterprise software suite, enhancing predictive analytics capabilities for Fortune 500 clients. InnovateCo CEO, Dr. Anya Sharma, stated, 'This acquisition is a pivotal moment for us, accelerating our AI roadmap and solidifying our leadership in intelligent automation.' Nexus Solutions, founded by visionary AI engineer Mark Chen, is renowned for its breakthroughs in unsupervised learning and has consistently been recognized for its innovation in the AI landscape."</p>
419
+ <p><strong>Product Launch:</strong> "Sustainable Energy Corp. unveils 'EcoGrid Pro,' a revolutionary smart grid management software designed to optimize renewable energy distribution by 40%. The system leverages AI to predict energy demand fluctuations and seamlessly integrate solar and wind power into existing grids. Early pilot programs with major utility providers in California and Germany demonstrated a 25% reduction in energy waste. CEO Elena Petrova highlights, 'EcoGrid Pro isn't just a product; it's a commitment to a more resilient and sustainable energy future.' The company plans a global rollout in Q3 2025."</p>
420
+ <p><strong>Executive Profile:</strong> "Dr. David Kim, newly appointed Chief Innovation Officer at BioSynth Labs, brings over two decades of experience in pharmaceutical R&D, including leading three blockbuster drug development programs at PharmaGiant Inc. A graduate of Stanford University with a Ph.D. in Molecular Biology, Dr. Kim is known for his pioneering work in CRISPR gene-editing technologies. His vision for BioSynth Labs focuses on accelerating therapeutic breakthroughs for neurodegenerative diseases and establishing new industry benchmarks for drug discovery. He believes, 'True innovation stems from a relentless pursuit of curiosity and a collaborative spirit to challenge existing paradigms.'"</p>
421
  </div>
422
  """)
423
 
 
434
 
435
  app = create_interface()
436
  app.launch(
437
+ # You can add launch parameters here, e.g., share=True for a public link
438
+ )