mroccuper commited on
Commit
498b1f8
·
verified ·
1 Parent(s): 244c047

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +86 -228
app.py CHANGED
@@ -1,241 +1,99 @@
1
  import gradio as gr
2
- import os
3
- import google.generativeai as genai
4
  from bs4 import BeautifulSoup
5
- import datetime
6
- import re
7
- import html
8
 
9
- # Function to extract text from HTML
10
- def extract_text_from_html(html_content):
11
- soup = BeautifulSoup(html_content, 'html.parser')
12
- # Remove script and style elements
13
- for script in soup(["script", "style"]):
14
- script.extract()
15
-
16
- # Get text
17
- text = soup.get_text(separator='\n')
18
-
19
- # Remove extra whitespace
20
- lines = (line.strip() for line in text.splitlines())
21
- chunks = (phrase.strip() for line in lines for phrase in line.split(" "))
22
- text = '\n'.join(chunk for chunk in chunks if chunk)
23
-
 
 
 
24
  return text
25
 
26
- # Generate post using Gemini API
27
- def generate_post(api_key, html_content, platform, styles, emotional_tone):
28
- genai.configure(api_key=api_key)
29
- model = genai.GenerativeModel('gemini-1.5-pro')
30
-
31
- # Extract text from HTML
32
- content_text = extract_text_from_html(html_content)
33
-
34
- # Create a summary first (this helps control the context length)
35
- summary_prompt = f"""
36
- You are an expert content summarizer specializing in fermentation topics.
37
- Please create a concise summary of the following content, focusing on the main points,
38
- techniques, and unique aspects of the fermentation process described:
39
-
40
- {content_text[:8000]} # Limiting to first 8000 chars for summary
41
- """
42
-
43
- summary_response = model.generate_content(summary_prompt)
44
- summary = summary_response.text
45
-
46
- # Prepare style instructions
47
- style_instruction = ", ".join(styles)
48
- if emotional_tone:
49
- style_instruction += f" with a {emotional_tone} emotional tone"
50
-
51
- # Platform-specific formatting
52
- if platform == "Reddit":
53
- platform_instruction = "Format this as a Reddit post with a catchy title, engaging introduction, clear sections, and end with a question to encourage comments."
54
- else: # Quora
55
- platform_instruction = "Format this as a Quora answer that demonstrates expertise, provides personal experience, includes detailed steps, and shows passion for fermentation."
56
-
57
- # Main generation prompt
58
- prompt = f"""
59
- You are an expert content creator specializing in fermentation topics.
60
-
61
- Create a {platform} post about fermentation based on the following content summary.
62
- Use a {style_instruction} writing style.
63
-
64
- Write the post as if you have personally tried or experienced this fermentation technique/recipe.
65
- Include sensory details (how it looked, tasted, smelled), challenges you faced, and results.
66
-
67
- The post should feel authentic, like it's written by a real fermentation enthusiast sharing their experience, not like marketing material.
68
-
69
- Content summary to base the post on:
70
- {summary}
71
-
72
- Special instructions:
73
- 1. {platform_instruction}
74
- 2. Include a compelling title
75
- 3. Be specific and detailed about the fermentation process
76
- 4. Use conversational language that would engage the {platform} community
77
- 5. End with a question or call for the community to share their experiences
78
-
79
- Structure the response with:
80
- TITLE: [Your generated title]
81
-
82
- [The body of your post]
83
- """
84
-
85
- response = model.generate_content(prompt)
86
- return response.text
87
 
88
- # Function to extract title and body from generated content
89
- def extract_title_and_body(generated_text):
90
- # Find the title
91
- title_match = re.search(r'TITLE:\s*(.*?)(?:\n\n|\n|$)', generated_text)
92
- title = title_match.group(1) if title_match else "Generated Post"
93
-
94
- # Remove the title part to get the body
95
- body = re.sub(r'TITLE:\s*.*?(?:\n\n|\n|$)', '', generated_text, count=1, flags=re.DOTALL).strip()
96
-
97
- return title, body
98
 
99
- # Create formatted HTML for download
100
- def create_html_output(title, body):
101
- return f"""<!DOCTYPE html>
102
- <html>
103
- <head>
104
- <title>{html.escape(title)}</title>
105
- <meta charset="UTF-8">
106
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
107
- <style>
108
- body {{ font-family: Arial, sans-serif; line-height: 1.6; max-width: 800px; margin: 0 auto; padding: 20px; }}
109
- h1 {{ color: #333; }}
110
- .post-body {{ margin-top: 20px; }}
111
- .post-meta {{ color: #666; font-size: 0.9em; margin-bottom: 20px; }}
112
- </style>
113
- </head>
114
- <body>
115
- <h1>{html.escape(title)}</h1>
116
- <div class="post-meta">Generated on {datetime.datetime.now().strftime('%Y-%m-%d')} for {html.escape(platform_choice)}</div>
117
- <div class="post-body">
118
- {body.replace('\n', '<br>')}
119
- </div>
120
- </body>
121
- </html>
122
  """
123
 
124
- # Function to handle file upload and process request
125
- def process_upload(html_file, api_key, platform_choice, humanized, friendly, storytelling, emotional_tone):
 
 
 
 
 
 
 
 
 
 
 
 
 
126
  try:
127
- # Check if API key is provided
128
- if not api_key.strip():
129
- return "Please enter your Gemini API key", None, None, None, None
130
-
131
- # Read file content
132
- html_content = html_file.decode('utf-8')
133
-
134
- # Collect selected styles
135
- styles = []
136
- if humanized:
137
- styles.append("humanized")
138
- if friendly:
139
- styles.append("friendly")
140
- if storytelling:
141
- styles.append("personal storytelling")
142
-
143
- # Generate post
144
- generated_post = generate_post(api_key, html_content, platform_choice, styles, emotional_tone)
145
-
146
- # Extract title and body
147
- title, body = extract_title_and_body(generated_post)
148
-
149
- # Create formatted outputs for download
150
- html_output = create_html_output(title, body)
151
- text_output = f"{title}\n\n{body}"
152
-
153
- return f"## {title}\n\n{body}", title, body, html_output, text_output
154
-
155
- except Exception as e:
156
- return f"Error: {str(e)}", None, None, None, None
157
 
158
- # Define the Gradio interface
159
- with gr.Blocks(title="Fermentation Content Generator") as app:
160
- gr.Markdown("# 🧪 Fermentation Content Generator for Reddit & Quora")
161
- gr.Markdown("Upload your fermentation content HTML file and generate engaging posts optimized for Reddit or Quora.")
162
-
163
  with gr.Row():
164
- with gr.Column(scale=1):
165
- # Input section
166
- gr.Markdown("### 1. Configure Your Post")
167
-
168
- api_key = gr.Textbox(label="Gemini API Key", placeholder="Enter your API key", type="password")
169
-
170
- html_file = gr.File(label="Upload HTML Content", file_types=[".html", ".htm"])
171
-
172
- platform_choice = gr.Radio(
173
- label="Choose Platform",
174
- choices=["Reddit", "Quora"],
175
- value="Reddit"
176
- )
177
-
178
- with gr.Accordion("Style Options"):
179
- gr.Markdown("Select the writing style:")
180
- with gr.Row():
181
- humanized = gr.Checkbox(label="Humanized", value=True)
182
- friendly = gr.Checkbox(label="Friendly", value=True)
183
- storytelling = gr.Checkbox(label="Personal/Storytelling", value=True)
184
-
185
- emotional_tone = gr.Dropdown(
186
- label="Emotional Tone",
187
- choices=["Curious", "Enthusiastic", "Skeptical", "Inspiring", "Helpful", "None"],
188
- value="Enthusiastic"
189
- )
190
-
191
- generate_btn = gr.Button("Generate Post", variant="primary")
192
-
193
- with gr.Column(scale=2):
194
- # Output section
195
- gr.Markdown("### 2. Generated Post Preview")
196
-
197
- output = gr.Markdown(label="Generated Post")
198
-
199
- with gr.Accordion("Post Details", open=False):
200
- title_output = gr.Textbox(label="Title")
201
- body_output = gr.Textbox(label="Body", lines=10)
202
-
203
- with gr.Row():
204
- html_download = gr.File(label="Download as HTML")
205
- text_download = gr.File(label="Download as Text")
206
-
207
- # Process when button is clicked
208
- generate_btn.click(
209
- fn=process_upload,
210
- inputs=[html_file, api_key, platform_choice, humanized, friendly, storytelling, emotional_tone],
211
- outputs=[output, title_output, body_output, html_download, text_download]
212
- )
213
-
214
- # Examples and tips
215
- with gr.Accordion("Tips & Examples", open=False):
216
- gr.Markdown("""
217
- ### Tips for Best Results
218
-
219
- 1. **Content Quality**: Ensure your HTML file contains comprehensive information about the fermentation process.
220
- 2. **File Size**: For optimal results, keep your HTML file under 100KB.
221
- 3. **Style Selection**: Experiment with different style combinations to find what works best for your target audience.
222
- 4. **Emotional Tones**:
223
- - **Curious**: Good for experimental fermentation techniques
224
- - **Enthusiastic**: Works well for successful recipes and projects
225
- - **Skeptical**: Useful for discussing common myths or challenges
226
- - **Inspiring**: Great for showcasing transformative projects or health benefits
227
- - **Helpful**: Best for educational content and guides
228
-
229
- ### Example Content
230
-
231
- Your HTML content should ideally include:
232
- - Detailed fermentation process
233
- - Ingredients and equipment used
234
- - Timeline and observations
235
- - Results and flavor notes
236
- - Any troubleshooting tips
237
- """)
238
 
239
- # Launch the app
240
- if __name__ == "__main__":
241
- app.launch(share=True)
 
 
1
  import gradio as gr
 
 
2
  from bs4 import BeautifulSoup
3
+ import json
4
+ import requests
 
5
 
6
+ # ---------------------------
7
+ # Gemini API Setup (User will insert their own key manually)
8
+ # ---------------------------
9
+ GEMINI_API_KEY = "YOUR_GEMINI_API_KEY_HERE" # Replace manually
10
+ GEMINI_API_URL = "https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-pro:generateContent"
11
+
12
+ # ---------------------------
13
+ # Tone Options
14
+ # ---------------------------
15
+ TONE_OPTIONS = ["Friendly", "Humanized", "Engaging", "Funny", "Emotional"]
16
+
17
+ # ---------------------------
18
+ # Function to extract main content from HTML
19
+ # ---------------------------
20
+ def extract_main_content(html_file):
21
+ soup = BeautifulSoup(html_file, "html.parser")
22
+ article = soup.find("article") or soup.body
23
+ text = article.get_text(separator="\n", strip=True) if article else ""
24
  return text
25
 
26
+ # ---------------------------
27
+ # Prompt builder
28
+ # ---------------------------
29
+ def build_prompt(text, tones, platform):
30
+ tone_str = ", ".join(tones)
31
+ return f"""
32
+ You are a skilled content writer. Based on the content below, generate a post for {platform}.
33
+ The post should feel like someone sharing a personal experience or story related to the topic.
34
+ Make it {tone_str.lower()}, natural, and relatable. Include a catchy title to hook readers, and a body that encourages responses.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35
 
36
+ ---
37
+ {text}
38
+ ---
 
 
 
 
 
 
 
39
 
40
+ Return in this format:
41
+ Title: <catchy title>
42
+ Body:
43
+ <post body text>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
44
  """
45
 
46
+ # ---------------------------
47
+ # Function to call Gemini
48
+ # ---------------------------
49
+ def generate_post(text, tones, platform):
50
+ headers = {"Content-Type": "application/json"}
51
+ prompt = build_prompt(text, tones, platform)
52
+ data = {
53
+ "contents": [{"parts": [{"text": prompt}]}]
54
+ }
55
+ response = requests.post(
56
+ f"{GEMINI_API_URL}?key={GEMINI_API_KEY}",
57
+ headers=headers,
58
+ data=json.dumps(data)
59
+ )
60
+ result = response.json()
61
  try:
62
+ return result["candidates"][0]["content"]["parts"][0]["text"]
63
+ except:
64
+ return "Error generating content. Check your API key or prompt."
65
+
66
+ # ---------------------------
67
+ # Gradio UI
68
+ # ---------------------------
69
+ def app_interface(html_file, tones, platform_choice):
70
+ if not html_file:
71
+ return "Please upload an HTML blog post."
72
+
73
+ html_content = html_file.read().decode("utf-8")
74
+ main_text = extract_main_content(html_content)
75
+ if not main_text:
76
+ return "Couldn't extract content from file. Ensure it's a valid HTML blog post."
77
+
78
+ output = generate_post(main_text, tones, platform_choice)
79
+ return output
80
+
81
+ # Gradio Blocks UI
82
+ with gr.Blocks() as demo:
83
+ gr.Markdown("# Reddit & Quora Post Generator 🧠")
84
+ gr.Markdown("Upload your HTML blog post and get ready-to-publish content for Reddit or Quora, written in a human, friendly tone.")
 
 
 
 
 
 
 
85
 
 
 
 
 
 
86
  with gr.Row():
87
+ html_input = gr.File(label="Upload HTML Blog Post", file_types=[".html"])
88
+
89
+ tone_checkboxes = gr.CheckboxGroup(label="Choose Tones", choices=TONE_OPTIONS, value=["Friendly", "Humanized"])
90
+ platform_radio = gr.Radio(label="Target Platform", choices=["Reddit", "Quora"], value="Reddit")
91
+ generate_button = gr.Button("Generate Post")
92
+ output_box = gr.Textbox(label="Generated Post", lines=20, interactive=True)
93
+
94
+ generate_button.click(app_interface, inputs=[html_input, tone_checkboxes, platform_radio], outputs=output_box)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
95
 
96
+ # ---------------------------
97
+ # Launch App
98
+ # ---------------------------
99
+ demo.launch()