Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -48,18 +48,14 @@ Use these specific keywords in your listing: {keywords}
|
|
48 |
|
49 |
Respond ONLY with a JSON object in this format:
|
50 |
{{
|
51 |
-
"title": "
|
52 |
-
"brand_name": "Brand name
|
53 |
-
"bullet_point_1": "
|
54 |
-
"bullet_point_2": "
|
55 |
-
"suggested_keywords": "
|
56 |
}}
|
57 |
|
58 |
-
|
59 |
-
- Title: Exactly 60 characters
|
60 |
-
- Brand Name: Between 34-50 characters
|
61 |
-
- Bullet Point 1: Between 240-256 characters
|
62 |
-
- Bullet Point 2: Between 240-256 characters"""
|
63 |
|
64 |
return combined_prompt
|
65 |
|
@@ -84,126 +80,146 @@ All titles must be exactly 60 characters and brand names between 34-50 character
|
|
84 |
Respond ONLY with a JSON object in this format:
|
85 |
{{
|
86 |
"title_variations": [
|
87 |
-
"Title variation 1
|
88 |
-
"Title variation 2
|
89 |
-
"Title variation 3
|
90 |
],
|
91 |
"brand_name_variations": [
|
92 |
-
"Brand name variation 1
|
93 |
-
"Brand name variation 2
|
94 |
-
"Brand name variation 3
|
95 |
]
|
96 |
-
}}
|
|
|
|
|
97 |
|
98 |
return combined_prompt
|
99 |
|
100 |
def generate_amazon_listing(api_key, quote, niche, target, keywords):
|
101 |
"""Generate Amazon listing using Gemini API."""
|
|
|
|
|
|
|
|
|
|
|
|
|
102 |
try:
|
103 |
# Configure the Gemini API with the provided key
|
104 |
genai.configure(api_key=api_key)
|
105 |
-
model = genai.GenerativeModel('gemini-1.5-pro')
|
106 |
-
|
107 |
-
# Generate the main listing
|
108 |
-
prompt = generate_prompt(quote, niche, target, keywords)
|
109 |
|
110 |
-
|
111 |
-
|
|
|
112 |
generation_config={
|
113 |
-
"temperature": 0.3,
|
114 |
"top_p": 0.8,
|
115 |
-
"max_output_tokens":
|
116 |
}
|
117 |
)
|
118 |
|
119 |
-
#
|
120 |
-
|
121 |
-
|
122 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
123 |
json_str = match.group(0)
|
124 |
try:
|
125 |
result = json.loads(json_str)
|
|
|
|
|
126 |
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
147 |
|
148 |
-
|
149 |
-
|
150 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
151 |
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
variations_prompt = generate_multiple_variations_prompt(quote, niche, target, keywords)
|
159 |
-
response_var = model.generate_content(
|
160 |
-
variations_prompt,
|
161 |
-
generation_config={
|
162 |
-
"temperature": 0.4, # Lower temperature for more focused results
|
163 |
-
"top_p": 0.8,
|
164 |
-
"max_output_tokens": 2048
|
165 |
-
}
|
166 |
-
)
|
167 |
-
|
168 |
-
# Extract JSON from the variations response
|
169 |
-
response_var_text = response_var.text
|
170 |
-
match_var = re.search(r'{.*}', response_var_text, re.DOTALL)
|
171 |
-
if match_var:
|
172 |
-
json_str_var = match_var.group(0)
|
173 |
-
try:
|
174 |
-
variations = json.loads(json_str_var)
|
175 |
-
except json.JSONDecodeError:
|
176 |
-
variations = {
|
177 |
-
"title_variations": ["Error generating variations"],
|
178 |
-
"brand_name_variations": ["Error generating variations"]
|
179 |
-
}
|
180 |
-
else:
|
181 |
-
variations = {
|
182 |
-
"title_variations": ["Error generating variations"],
|
183 |
-
"brand_name_variations": ["Error generating variations"]
|
184 |
-
}
|
185 |
-
|
186 |
-
# Format main output
|
187 |
-
main_output = format_output(
|
188 |
-
result.get("title", "Error generating title"),
|
189 |
-
result.get("brand_name", "Error generating brand name"),
|
190 |
-
result.get("bullet_point_1", "Error generating bullet point 1"),
|
191 |
-
result.get("bullet_point_2", "Error generating bullet point 2"),
|
192 |
-
result.get("suggested_keywords", "Error generating suggested keywords")
|
193 |
-
)
|
194 |
-
|
195 |
-
# Format variations output
|
196 |
-
variations_output = "ADDITIONAL VARIATIONS:\n\n"
|
197 |
-
variations_output += "Title Variations:\n"
|
198 |
-
for i, var in enumerate(variations.get("title_variations", []), 1):
|
199 |
-
variations_output += f"{i}. {var} ({count_characters(var)}/60 characters)\n"
|
200 |
-
|
201 |
-
variations_output += "\nBrand Name Variations:\n"
|
202 |
-
for i, var in enumerate(variations.get("brand_name_variations", []), 1):
|
203 |
-
variations_output += f"{i}. {var} ({count_characters(var)}/50 characters)\n"
|
204 |
-
|
205 |
-
return main_output + "\n\n" + variations_output
|
206 |
-
|
207 |
except Exception as e:
|
208 |
return f"Error: {str(e)}"
|
209 |
|
@@ -216,19 +232,34 @@ def create_interface():
|
|
216 |
with gr.Row():
|
217 |
with gr.Column():
|
218 |
api_key = gr.Textbox(label="Gemini API Key", placeholder="Enter your Gemini API key", type="password")
|
219 |
-
quote = gr.Textbox(label="Quote/Design/Idea", placeholder="Enter the quote or design idea")
|
220 |
-
niche = gr.Textbox(label="Holiday/Event", placeholder="Enter the holiday or event (e.g., St Patrick's Day)")
|
221 |
-
target = gr.Textbox(label="Target Audience", placeholder="Teacher, Mom, Dad, etc.")
|
222 |
-
keywords = gr.Textbox(label="Target Keywords", placeholder="Enter keywords separated by commas", lines=5)
|
223 |
submit_btn = gr.Button("Generate Amazon Listing", variant="primary")
|
224 |
|
225 |
with gr.Column():
|
|
|
226 |
output = gr.Textbox(label="Generated Amazon Listing", lines=25)
|
227 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
228 |
submit_btn.click(
|
229 |
-
fn=
|
230 |
inputs=[api_key, quote, niche, target, keywords],
|
231 |
-
outputs=output
|
|
|
232 |
)
|
233 |
|
234 |
gr.Markdown("## Example Input")
|
@@ -241,6 +272,13 @@ Keywords: lucky, teacher, rainbow, st, patricks, day, t-shirt, patrick's, outfit
|
|
241 |
```
|
242 |
''')
|
243 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
244 |
return app
|
245 |
|
246 |
# Create and launch the app
|
|
|
48 |
|
49 |
Respond ONLY with a JSON object in this format:
|
50 |
{{
|
51 |
+
"title": "The title with exactly 60 characters",
|
52 |
+
"brand_name": "Brand name between 34-50 characters",
|
53 |
+
"bullet_point_1": "First bullet point between 240-256 characters that focuses on the design and theme",
|
54 |
+
"bullet_point_2": "Second bullet point between 240-256 characters that focuses on the design and theme",
|
55 |
+
"suggested_keywords": "5 additional keywords separated by commas"
|
56 |
}}
|
57 |
|
58 |
+
REMINDER: Make sure to count the characters carefully. Title should be EXACTLY 60 characters. Bullet points should be between 240-256 characters."""
|
|
|
|
|
|
|
|
|
59 |
|
60 |
return combined_prompt
|
61 |
|
|
|
80 |
Respond ONLY with a JSON object in this format:
|
81 |
{{
|
82 |
"title_variations": [
|
83 |
+
"Title variation 1 - exactly 60 characters, count carefully",
|
84 |
+
"Title variation 2 - exactly 60 characters, count carefully",
|
85 |
+
"Title variation 3 - exactly 60 characters, count carefully"
|
86 |
],
|
87 |
"brand_name_variations": [
|
88 |
+
"Brand name variation 1 (34-50 characters)",
|
89 |
+
"Brand name variation 2 (34-50 characters)",
|
90 |
+
"Brand name variation 3 (34-50 characters)"
|
91 |
]
|
92 |
+
}}
|
93 |
+
|
94 |
+
REMINDER: Make sure each title is EXACTLY 60 characters. Count carefully!"""
|
95 |
|
96 |
return combined_prompt
|
97 |
|
98 |
def generate_amazon_listing(api_key, quote, niche, target, keywords):
|
99 |
"""Generate Amazon listing using Gemini API."""
|
100 |
+
# Input validation
|
101 |
+
if not api_key:
|
102 |
+
return "Error: Please enter a valid Gemini API key"
|
103 |
+
if not quote or not niche or not target:
|
104 |
+
return "Error: Please fill in all required fields (Quote, Holiday/Event, and Target Audience)"
|
105 |
+
|
106 |
try:
|
107 |
# Configure the Gemini API with the provided key
|
108 |
genai.configure(api_key=api_key)
|
|
|
|
|
|
|
|
|
109 |
|
110 |
+
# Create model with optimized settings
|
111 |
+
model = genai.GenerativeModel(
|
112 |
+
'gemini-1.5-pro',
|
113 |
generation_config={
|
114 |
+
"temperature": 0.3,
|
115 |
"top_p": 0.8,
|
116 |
+
"max_output_tokens": 1024, # Reduced for faster response
|
117 |
}
|
118 |
)
|
119 |
|
120 |
+
# Generate the main listing
|
121 |
+
prompt = generate_prompt(quote, niche, target, keywords)
|
122 |
+
|
123 |
+
try:
|
124 |
+
# First try to get just the main listing for faster response
|
125 |
+
response = model.generate_content(prompt)
|
126 |
+
|
127 |
+
# Extract JSON from the response
|
128 |
+
response_text = response.text
|
129 |
+
match = re.search(r'{.*}', response_text, re.DOTALL)
|
130 |
+
if not match:
|
131 |
+
return "Error: Could not extract JSON from Gemini API response. Please try again."
|
132 |
+
|
133 |
json_str = match.group(0)
|
134 |
try:
|
135 |
result = json.loads(json_str)
|
136 |
+
except json.JSONDecodeError:
|
137 |
+
return "Error parsing JSON response from Gemini API. Please try again."
|
138 |
|
139 |
+
# Validate that the output actually matches the input criteria
|
140 |
+
title = result.get("title", "")
|
141 |
+
if not (quote.lower() in title.lower() or
|
142 |
+
niche.lower() in title.lower() or
|
143 |
+
any(t.lower() in title.lower() for t in target.lower().split(','))):
|
144 |
+
return f"Error: Generated title doesn't match the requested theme: '{quote}', '{niche}', or '{target}'. Please try again."
|
145 |
+
|
146 |
+
# Validate bullet point lengths
|
147 |
+
bullet1 = result.get("bullet_point_1", "")
|
148 |
+
bullet2 = result.get("bullet_point_2", "")
|
149 |
+
|
150 |
+
if len(bullet1) < 240 or len(bullet1) > 256:
|
151 |
+
return f"Error: Bullet point 1 length ({len(bullet1)}) is not between 240-256 characters. Please try again."
|
152 |
+
|
153 |
+
if len(bullet2) < 240 or len(bullet2) > 256:
|
154 |
+
return f"Error: Bullet point 2 length ({len(bullet2)}) is not between 240-256 characters. Please try again."
|
155 |
+
|
156 |
+
# Check for generic content in bullet points
|
157 |
+
generic_phrases = ["premium quality", "high-quality materials", "soft feel", "long-lasting wear",
|
158 |
+
"comfortable and stylish", "perfect gift", "great gift"]
|
159 |
+
|
160 |
+
for phrase in generic_phrases:
|
161 |
+
if phrase in bullet1.lower() or phrase in bullet2.lower():
|
162 |
+
return f"Error: Generated bullet points contain generic phrase '{phrase}'. Please try again."
|
163 |
+
|
164 |
+
# Format main output first - so we have something to show quickly
|
165 |
+
main_output = format_output(
|
166 |
+
result.get("title", "Error generating title"),
|
167 |
+
result.get("brand_name", "Error generating brand name"),
|
168 |
+
result.get("bullet_point_1", "Error generating bullet point 1"),
|
169 |
+
result.get("bullet_point_2", "Error generating bullet point 2"),
|
170 |
+
result.get("suggested_keywords", "Error generating suggested keywords")
|
171 |
+
)
|
172 |
+
|
173 |
+
# Now try to get variations in a separate call
|
174 |
+
try:
|
175 |
+
variations_prompt = generate_multiple_variations_prompt(quote, niche, target, keywords)
|
176 |
+
response_var = model.generate_content(
|
177 |
+
variations_prompt,
|
178 |
+
generation_config={
|
179 |
+
"temperature": 0.4,
|
180 |
+
"top_p": 0.8,
|
181 |
+
"max_output_tokens": 1024
|
182 |
+
}
|
183 |
+
)
|
184 |
|
185 |
+
# Extract JSON from the variations response
|
186 |
+
response_var_text = response_var.text
|
187 |
+
match_var = re.search(r'{.*}', response_var_text, re.DOTALL)
|
188 |
+
if match_var:
|
189 |
+
json_str_var = match_var.group(0)
|
190 |
+
try:
|
191 |
+
variations = json.loads(json_str_var)
|
192 |
+
|
193 |
+
# Format variations output
|
194 |
+
variations_output = "\n\nADDITIONAL VARIATIONS:\n\n"
|
195 |
+
variations_output += "Title Variations:\n"
|
196 |
+
for i, var in enumerate(variations.get("title_variations", []), 1):
|
197 |
+
variations_output += f"{i}. {var} ({count_characters(var)}/60 characters)\n"
|
198 |
+
|
199 |
+
variations_output += "\nBrand Name Variations:\n"
|
200 |
+
for i, var in enumerate(variations.get("brand_name_variations", []), 1):
|
201 |
+
variations_output += f"{i}. {var} ({count_characters(var)}/50 characters)\n"
|
202 |
+
|
203 |
+
# Combine main output with variations
|
204 |
+
return main_output + variations_output
|
205 |
+
|
206 |
+
except json.JSONDecodeError:
|
207 |
+
# Return just the main output if we can't parse variations
|
208 |
+
return main_output + "\n\n(Could not generate variations)"
|
209 |
+
else:
|
210 |
+
# Return just the main output if we can't extract JSON for variations
|
211 |
+
return main_output + "\n\n(Could not generate variations)"
|
212 |
+
|
213 |
+
except Exception as var_error:
|
214 |
+
# Return just the main output if variations fail
|
215 |
+
return main_output + f"\n\n(Could not generate variations: {str(var_error)})"
|
216 |
|
217 |
+
except genai.types.generation_types.BlockedPromptException as e:
|
218 |
+
return f"Error: The prompt was blocked by Gemini API safety filters. Please modify your input and try again."
|
219 |
+
|
220 |
+
except Exception as e:
|
221 |
+
return f"Error generating main listing: {str(e)}"
|
222 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
223 |
except Exception as e:
|
224 |
return f"Error: {str(e)}"
|
225 |
|
|
|
232 |
with gr.Row():
|
233 |
with gr.Column():
|
234 |
api_key = gr.Textbox(label="Gemini API Key", placeholder="Enter your Gemini API key", type="password")
|
235 |
+
quote = gr.Textbox(label="Quote/Design/Idea", placeholder="Enter the quote or design idea", value="")
|
236 |
+
niche = gr.Textbox(label="Holiday/Event", placeholder="Enter the holiday or event (e.g., St Patrick's Day)", value="")
|
237 |
+
target = gr.Textbox(label="Target Audience", placeholder="Teacher, Mom, Dad, etc.", value="")
|
238 |
+
keywords = gr.Textbox(label="Target Keywords", placeholder="Enter keywords separated by commas", lines=5, value="")
|
239 |
submit_btn = gr.Button("Generate Amazon Listing", variant="primary")
|
240 |
|
241 |
with gr.Column():
|
242 |
+
status = gr.Textbox(label="Status", value="Ready to generate listing", interactive=False)
|
243 |
output = gr.Textbox(label="Generated Amazon Listing", lines=25)
|
244 |
|
245 |
+
def on_submit(api_key, quote, niche, target, keywords):
|
246 |
+
# Update status first
|
247 |
+
yield "Generating listing... Please wait.", output.value
|
248 |
+
|
249 |
+
# Generate the listing
|
250 |
+
result = generate_amazon_listing(api_key, quote, niche, target, keywords)
|
251 |
+
|
252 |
+
# Update status with completion message
|
253 |
+
if "Error" in result:
|
254 |
+
yield "Error occurred. See details below.", result
|
255 |
+
else:
|
256 |
+
yield "Listing generated successfully!", result
|
257 |
+
|
258 |
submit_btn.click(
|
259 |
+
fn=on_submit,
|
260 |
inputs=[api_key, quote, niche, target, keywords],
|
261 |
+
outputs=[status, output],
|
262 |
+
show_progress="minimal"
|
263 |
)
|
264 |
|
265 |
gr.Markdown("## Example Input")
|
|
|
272 |
```
|
273 |
''')
|
274 |
|
275 |
+
gr.Markdown("""
|
276 |
+
## Troubleshooting Tips
|
277 |
+
- If you experience timeouts, try using shorter, more specific inputs
|
278 |
+
- Make sure your Gemini API key is valid and has sufficient quota
|
279 |
+
- The app will prioritize showing the main listing first, then try to generate variations
|
280 |
+
""")
|
281 |
+
|
282 |
return app
|
283 |
|
284 |
# Create and launch the app
|