Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -1,82 +1,92 @@
|
|
1 |
-
# app.py
|
2 |
import gradio as gr
|
3 |
import requests
|
4 |
from bs4 import BeautifulSoup
|
5 |
import google.generativeai as genai
|
6 |
import os
|
|
|
7 |
|
8 |
# Configure Gemini API
|
9 |
GEMINI_API_KEY = os.getenv("GEMINI_API_KEY")
|
|
|
|
|
|
|
10 |
genai.configure(api_key=GEMINI_API_KEY)
|
11 |
|
12 |
def fetch_article_content(url):
|
13 |
-
"""Fetch article content
|
14 |
try:
|
15 |
headers = {'User-Agent': 'Mozilla/5.0'}
|
16 |
-
response = requests.get(url, headers=headers, timeout=
|
17 |
response.raise_for_status()
|
18 |
soup = BeautifulSoup(response.text, 'html.parser')
|
19 |
-
|
20 |
# Extract text from <p> tags
|
21 |
-
paragraphs = soup.find_all('p')
|
22 |
content = ' '.join([p.get_text(strip=True) for p in paragraphs])
|
23 |
-
return content
|
24 |
except Exception as e:
|
25 |
return f"Error fetching article: {str(e)}"
|
26 |
|
27 |
def generate_platform_post(article_text):
|
28 |
-
"""Generate optimized post using Gemini API"""
|
29 |
try:
|
30 |
model = genai.GenerativeModel('gemini-1.5-pro')
|
31 |
|
32 |
prompt = f"""
|
33 |
-
|
34 |
-
1. A compelling title (max 100 characters)
|
35 |
-
2. An optimized post in HTML format for Reddit/Quora
|
36 |
-
3. Include an image tag with descriptive alt text
|
37 |
|
38 |
Article content:
|
39 |
-
{article_text
|
40 |
|
41 |
-
|
42 |
-
[
|
43 |
-
[
|
44 |
|
45 |
Requirements:
|
46 |
-
-
|
47 |
-
-
|
48 |
-
-
|
49 |
-
-
|
|
|
50 |
"""
|
51 |
|
|
|
|
|
52 |
response = model.generate_content(prompt)
|
|
|
|
|
53 |
return parse_gemini_response(response.text)
|
54 |
except Exception as e:
|
55 |
-
return {"title": "
|
56 |
|
57 |
def parse_gemini_response(response):
|
58 |
-
"""
|
59 |
try:
|
60 |
-
title = response.split("
|
61 |
-
content = response.split("
|
62 |
except:
|
63 |
title = "Content Generation Error"
|
64 |
-
content = "<p>Failed to parse response
|
65 |
|
66 |
return {"title": title, "content": content}
|
67 |
|
68 |
def process_url(url):
|
69 |
-
"""Main processing pipeline"""
|
|
|
|
|
70 |
article_text = fetch_article_content(url)
|
71 |
if article_text.startswith("Error"):
|
72 |
-
|
|
|
73 |
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
|
|
|
|
78 |
title_output = gr.Textbox(label="Generated Title")
|
79 |
-
content_output = gr.HTML(label="
|
80 |
|
81 |
app = gr.Interface(
|
82 |
fn=process_url,
|
@@ -86,10 +96,12 @@ app = gr.Interface(
|
|
86 |
gr.HTML(label="Formatted Post")
|
87 |
],
|
88 |
examples=[
|
89 |
-
["https://
|
90 |
],
|
91 |
title="Article to Reddit/Quora Post Converter",
|
92 |
-
description="Convert news articles into optimized
|
|
|
|
|
93 |
)
|
94 |
|
95 |
if __name__ == "__main__":
|
|
|
|
|
1 |
import gradio as gr
|
2 |
import requests
|
3 |
from bs4 import BeautifulSoup
|
4 |
import google.generativeai as genai
|
5 |
import os
|
6 |
+
import time
|
7 |
|
8 |
# Configure Gemini API
|
9 |
GEMINI_API_KEY = os.getenv("GEMINI_API_KEY")
|
10 |
+
if not GEMINI_API_KEY:
|
11 |
+
raise ValueError("GEMINI_API_KEY not found in environment variables")
|
12 |
+
|
13 |
genai.configure(api_key=GEMINI_API_KEY)
|
14 |
|
15 |
def fetch_article_content(url):
|
16 |
+
"""Fetch article content with timeout and fallback"""
|
17 |
try:
|
18 |
headers = {'User-Agent': 'Mozilla/5.0'}
|
19 |
+
response = requests.get(url, headers=headers, timeout=8) # 8s timeout
|
20 |
response.raise_for_status()
|
21 |
soup = BeautifulSoup(response.text, 'html.parser')
|
22 |
+
|
23 |
# Extract text from <p> tags
|
24 |
+
paragraphs = soup.find_all('p')[:10] # Limit to 10 paragraphs
|
25 |
content = ' '.join([p.get_text(strip=True) for p in paragraphs])
|
26 |
+
return content[:2000] # Limit to 2000 chars for prompt safety
|
27 |
except Exception as e:
|
28 |
return f"Error fetching article: {str(e)}"
|
29 |
|
30 |
def generate_platform_post(article_text):
|
31 |
+
"""Generate optimized post using Gemini API with timeout"""
|
32 |
try:
|
33 |
model = genai.GenerativeModel('gemini-1.5-pro')
|
34 |
|
35 |
prompt = f"""
|
36 |
+
Convert this article into a short, engaging post suitable for Reddit or Quora.
|
|
|
|
|
|
|
37 |
|
38 |
Article content:
|
39 |
+
{article_text}
|
40 |
|
41 |
+
Output format:
|
42 |
+
Title: [short title]
|
43 |
+
Post: [clean HTML with paragraphs and one image tag]
|
44 |
|
45 |
Requirements:
|
46 |
+
- Keep title under 100 characters
|
47 |
+
- Include one <img> tag with alt text
|
48 |
+
- Use minimal styling
|
49 |
+
- Mobile-friendly
|
50 |
+
- No markdown
|
51 |
"""
|
52 |
|
53 |
+
# Timeout mechanism
|
54 |
+
start_time = time.time()
|
55 |
response = model.generate_content(prompt)
|
56 |
+
print(f"AI Response received in {time.time()-start_time:.2f} seconds")
|
57 |
+
|
58 |
return parse_gemini_response(response.text)
|
59 |
except Exception as e:
|
60 |
+
return {"title": "Generation Failed", "content": f"<p>AI Error: {str(e)}</p>"}
|
61 |
|
62 |
def parse_gemini_response(response):
|
63 |
+
"""Robust parsing with fallbacks"""
|
64 |
try:
|
65 |
+
title = response.split("Title:")[1].split("Post:")[0].strip()[:100]
|
66 |
+
content = response.split("Post:")[1].strip()
|
67 |
except:
|
68 |
title = "Content Generation Error"
|
69 |
+
content = "<p>Failed to parse AI response</p>"
|
70 |
|
71 |
return {"title": title, "content": content}
|
72 |
|
73 |
def process_url(url):
|
74 |
+
"""Main processing pipeline with status updates"""
|
75 |
+
yield {"title": "Fetching Article...", "content": "<p>Connecting to URL...</p>"}
|
76 |
+
|
77 |
article_text = fetch_article_content(url)
|
78 |
if article_text.startswith("Error"):
|
79 |
+
yield {"title": "Fetch Error", "content": f"<p>{article_text}</p>"}
|
80 |
+
return
|
81 |
|
82 |
+
yield {"title": "Generating Post...", "content": "<p>Creating content with AI...</p>"}
|
83 |
+
|
84 |
+
result = generate_platform_post(article_text)
|
85 |
+
yield result
|
86 |
+
# Gradio Interface
|
87 |
+
url_input = gr.Textbox(label="Article URL", placeholder="https://example.com/article...", lines=1)
|
88 |
title_output = gr.Textbox(label="Generated Title")
|
89 |
+
content_output = gr.HTML(label="Formatted Post")
|
90 |
|
91 |
app = gr.Interface(
|
92 |
fn=process_url,
|
|
|
96 |
gr.HTML(label="Formatted Post")
|
97 |
],
|
98 |
examples=[
|
99 |
+
["https://example.com/sample-article"]
|
100 |
],
|
101 |
title="Article to Reddit/Quora Post Converter",
|
102 |
+
description="Convert news articles into optimized posts with AI-generated formatting and image descriptions",
|
103 |
+
allow_flagging="never",
|
104 |
+
live=False
|
105 |
)
|
106 |
|
107 |
if __name__ == "__main__":
|