Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -10,7 +10,7 @@ def fetch_article_content(url):
|
|
| 10 |
response = requests.get(url, headers=headers, timeout=8)
|
| 11 |
response.raise_for_status()
|
| 12 |
soup = BeautifulSoup(response.text, 'html.parser')
|
| 13 |
-
|
| 14 |
# Extract first 8 paragraphs
|
| 15 |
paragraphs = soup.find_all('p')[:8]
|
| 16 |
content = ' '.join([p.get_text(strip=True) for p in paragraphs])
|
|
@@ -24,64 +24,65 @@ def generate_platform_post(article_text, api_key):
|
|
| 24 |
# Configure Gemini with user's API key
|
| 25 |
genai.configure(api_key=api_key)
|
| 26 |
model = genai.GenerativeModel('gemini-1.5-pro')
|
| 27 |
-
|
| 28 |
prompt = f"""
|
| 29 |
Create a Reddit/Quora-style post from this article:
|
| 30 |
-
|
| 31 |
{article_text}
|
| 32 |
-
|
| 33 |
Output format:
|
| 34 |
Title: [short title]
|
| 35 |
Post: [clean HTML with 1 image tag + alt text]
|
| 36 |
-
|
| 37 |
Requirements:
|
| 38 |
- Title < 100 characters
|
| 39 |
- Include <img> with descriptive alt text
|
| 40 |
- Minimal styling
|
| 41 |
- Mobile-friendly
|
| 42 |
"""
|
| 43 |
-
|
| 44 |
-
response = model.generate_content(prompt, timeout=15)
|
| 45 |
return parse_gemini_response(response.text)
|
| 46 |
except Exception as e:
|
| 47 |
-
return
|
| 48 |
|
| 49 |
def parse_gemini_response(response):
|
| 50 |
-
"""Robust response parsing"""
|
| 51 |
try:
|
| 52 |
title = response.split("Title:")[1].split("Post:")[0].strip()[:100]
|
| 53 |
content = response.split("Post:")[1].strip()
|
|
|
|
| 54 |
except:
|
| 55 |
-
|
| 56 |
-
content = "<p>Failed to parse AI response</p>"
|
| 57 |
-
|
| 58 |
-
return {"title": title, "content": content}
|
| 59 |
|
| 60 |
def process_url(url, api_key):
|
| 61 |
"""Main processing pipeline with status updates"""
|
| 62 |
if not api_key or len(api_key.strip()) < 30:
|
| 63 |
-
yield
|
| 64 |
return
|
| 65 |
-
|
| 66 |
if not url.startswith("http"):
|
| 67 |
-
yield
|
| 68 |
return
|
| 69 |
-
|
| 70 |
-
yield
|
| 71 |
-
|
| 72 |
article_text = fetch_article_content(url)
|
| 73 |
if article_text.startswith("FETCH_ERROR:"):
|
| 74 |
-
yield
|
| 75 |
return
|
| 76 |
-
|
| 77 |
-
yield
|
| 78 |
-
|
| 79 |
result = generate_platform_post(article_text, api_key)
|
| 80 |
-
yield result
|
| 81 |
|
| 82 |
# Create Gradio interface
|
| 83 |
url_input = gr.Textbox(label="Article URL", placeholder="https://example.com/article...")
|
| 84 |
-
api_key_input = gr.Textbox(
|
|
|
|
|
|
|
|
|
|
|
|
|
| 85 |
|
| 86 |
title_output = gr.Textbox(label="Generated Title")
|
| 87 |
content_output = gr.HTML(label="Formatted Post")
|
|
@@ -94,7 +95,7 @@ app = gr.Interface(
|
|
| 94 |
gr.HTML(label="Formatted Post")
|
| 95 |
],
|
| 96 |
examples=[
|
| 97 |
-
["https://google.com
|
| 98 |
],
|
| 99 |
title="Article to Reddit/Quora Post Converter",
|
| 100 |
description="Convert news articles into optimized posts with AI-generated formatting and image descriptions",
|
|
|
|
| 10 |
response = requests.get(url, headers=headers, timeout=8)
|
| 11 |
response.raise_for_status()
|
| 12 |
soup = BeautifulSoup(response.text, 'html.parser')
|
| 13 |
+
|
| 14 |
# Extract first 8 paragraphs
|
| 15 |
paragraphs = soup.find_all('p')[:8]
|
| 16 |
content = ' '.join([p.get_text(strip=True) for p in paragraphs])
|
|
|
|
| 24 |
# Configure Gemini with user's API key
|
| 25 |
genai.configure(api_key=api_key)
|
| 26 |
model = genai.GenerativeModel('gemini-1.5-pro')
|
| 27 |
+
|
| 28 |
prompt = f"""
|
| 29 |
Create a Reddit/Quora-style post from this article:
|
| 30 |
+
|
| 31 |
{article_text}
|
| 32 |
+
|
| 33 |
Output format:
|
| 34 |
Title: [short title]
|
| 35 |
Post: [clean HTML with 1 image tag + alt text]
|
| 36 |
+
|
| 37 |
Requirements:
|
| 38 |
- Title < 100 characters
|
| 39 |
- Include <img> with descriptive alt text
|
| 40 |
- Minimal styling
|
| 41 |
- Mobile-friendly
|
| 42 |
"""
|
| 43 |
+
response = model.generate_content(prompt) # Removed invalid timeout
|
|
|
|
| 44 |
return parse_gemini_response(response.text)
|
| 45 |
except Exception as e:
|
| 46 |
+
return ("AI ERROR", f"<p>API Error: {str(e)}</p>")
|
| 47 |
|
| 48 |
def parse_gemini_response(response):
|
| 49 |
+
"""Robust response parsing – returns two values (title, content)"""
|
| 50 |
try:
|
| 51 |
title = response.split("Title:")[1].split("Post:")[0].strip()[:100]
|
| 52 |
content = response.split("Post:")[1].strip()
|
| 53 |
+
return title, content
|
| 54 |
except:
|
| 55 |
+
return ("Formatting Error", "<p>Failed to parse AI response</p>")
|
|
|
|
|
|
|
|
|
|
| 56 |
|
| 57 |
def process_url(url, api_key):
|
| 58 |
"""Main processing pipeline with status updates"""
|
| 59 |
if not api_key or len(api_key.strip()) < 30:
|
| 60 |
+
yield ("API Key Required", "<p>Please enter your Gemini API key above</p>")
|
| 61 |
return
|
| 62 |
+
|
| 63 |
if not url.startswith("http"):
|
| 64 |
+
yield ("Invalid URL", "<p>Please enter a valid article URL</p>")
|
| 65 |
return
|
| 66 |
+
|
| 67 |
+
yield ("Fetching Article...", "<p>Connecting to URL...</p>")
|
| 68 |
+
|
| 69 |
article_text = fetch_article_content(url)
|
| 70 |
if article_text.startswith("FETCH_ERROR:"):
|
| 71 |
+
yield ("Fetch Failed", f"<p>{article_text.replace('FETCH_ERROR: ', '')}</p>")
|
| 72 |
return
|
| 73 |
+
|
| 74 |
+
yield ("Generating Post...", "<p>Creating content with Gemini...</p>")
|
| 75 |
+
|
| 76 |
result = generate_platform_post(article_text, api_key)
|
| 77 |
+
yield result # This will now return (title, content)
|
| 78 |
|
| 79 |
# Create Gradio interface
|
| 80 |
url_input = gr.Textbox(label="Article URL", placeholder="https://example.com/article...")
|
| 81 |
+
api_key_input = gr.Textbox(
|
| 82 |
+
label="Gemini API Key",
|
| 83 |
+
placeholder="AIzaXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
|
| 84 |
+
type="password"
|
| 85 |
+
)
|
| 86 |
|
| 87 |
title_output = gr.Textbox(label="Generated Title")
|
| 88 |
content_output = gr.HTML(label="Formatted Post")
|
|
|
|
| 95 |
gr.HTML(label="Formatted Post")
|
| 96 |
],
|
| 97 |
examples=[
|
| 98 |
+
["https://google.com", "AIzaXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"]
|
| 99 |
],
|
| 100 |
title="Article to Reddit/Quora Post Converter",
|
| 101 |
description="Convert news articles into optimized posts with AI-generated formatting and image descriptions",
|