cyberandy's picture
Update app.py
2ab00e1 verified
raw
history blame
18.6 kB
import base64
import requests
import gradio as gr
from PIL import Image
import pillow_avif # This automatically registers AVIF support
import numpy as np
from datetime import datetime, date
import os
import json
import uuid
from http.cookies import SimpleCookie
# File to store session data
SESSION_FILE = "user_session_data.json"
# OpenAI API Key
api_key = os.getenv("OPENAI_API_KEY")
# Function to check and reset the counter if necessary for a specific user
def check_and_reset_user_counter(user_id):
all_user_data = load_user_session_data(user_id)
user_data = all_user_data[user_id]
today = str(date.today())
if user_data["last_reset_date"] != today:
user_data["last_reset_date"] = today
user_data["test_counter"] = 0
save_user_session_data(all_user_data)
return user_data["test_counter"]
def save_user_session_data(all_user_data):
with open(SESSION_FILE, 'w') as f:
json.dump(all_user_data, f)
# Function to load user session data
def load_user_session_data(user_id):
if os.path.exists(SESSION_FILE):
with open(SESSION_FILE, 'r') as f:
all_user_data = json.load(f)
else:
all_user_data = {}
if user_id not in all_user_data:
all_user_data[user_id] = {"last_reset_date": str(date.today()), "test_counter": 0}
return all_user_data
# Function to increment the counter for a specific user
def increment_user_counter(user_id):
all_user_data = load_user_session_data(user_id)
all_user_data[user_id]["test_counter"] += 1
save_user_session_data(all_user_data)
return all_user_data[user_id]["test_counter"]
# Function to get or create user ID from cookie
def get_or_create_user_id(user_id):
if not user_id:
return str(uuid.uuid4())
return user_id
# Modify the encode_image function to handle AVIF files
def encode_image(image_array):
try:
# Convert numpy array to PIL Image
img = Image.fromarray(np.uint8(image_array))
# Create a temporary file path
img_buffer = os.path.join(
"/tmp", f"temp_image_{datetime.now().strftime('%Y%m%d_%H%M%S')}.jpg"
)
# Convert to RGB mode if the image is in a different mode
if img.mode != 'RGB':
img = img.convert('RGB')
# Save as JPEG with error handling
try:
img.save(img_buffer, format="JPEG", quality=95)
except Exception as e:
print(f"Error saving image: {e}")
# If saving fails, try to convert to RGB first
img = img.convert('RGB')
img.save(img_buffer, format="JPEG", quality=95)
# Read and encode the saved image
with open(img_buffer, "rb") as image_file:
encoded_image = base64.b64encode(image_file.read()).decode("utf-8")
# Clean up temporary file
if os.path.exists(img_buffer):
os.remove(img_buffer)
return encoded_image
except Exception as e:
raise ValueError(f"Error processing image: {str(e)}")
# Function to generate product description using OpenAI API
def generate_product_description(image, description_type, custom_instruction=None):
try:
# Encode the uploaded image
base64_image = encode_image(image)
except Exception as e:
raise gr.Error(f"Error processing image: {str(e)}. Please try uploading a different image format.")
headers = {"Content-Type": "application/json", "Authorization": f"Bearer {api_key}"}
# Set the description type or custom instruction
description_prompts = {
"Short Formal πŸ“": "Based on the image, craft a concise and compelling product description that highlights key features and benefits in a formal tone.",
"Bullet Points πŸ“‹": "From the image, provide a detailed list of bullet points describing the product's features, benefits, and unique selling points.",
"Amazon Optimized πŸ›’": "Create an Amazon-style product description based on the image, including key features, benefits, relevant keywords for SEO, and a persuasive call to action.",
"Fashion πŸ‘—": "Generate a stylish and trendy product description for a fashion item shown in the image, emphasizing its design, materials, and how it fits into current fashion trends.",
"Sport πŸ€": "Using the image, develop an energetic and engaging product description for a sports-related item, highlighting its performance features and benefits for athletic activities.",
"Technical Specifications βš™οΈ": "Extract and present the product's technical specifications from the image in a clear and concise manner, suitable for tech-savvy customers.",
"SEO Optimized πŸ”": "Write an SEO-friendly product description based on the image, incorporating relevant keywords and phrases to enhance search engine visibility.",
"Social Media Style πŸ“±": "Create a catchy and engaging product description suitable for social media platforms, using the image as inspiration.",
"Luxury πŸ’Ž": "Craft an elegant and sophisticated product description for the luxury item shown in the image, emphasizing exclusivity, premium quality, and craftsmanship.",
"Kid-Friendly 🧸": "Generate a fun and appealing product description for a children's product based on the image, using language that resonates with both kids and parents.",
"Health and Beauty πŸ’„": "Develop a compelling product description for a health or beauty item shown in the image, highlighting its benefits, ingredients, and usage tips.",
"Electronic Gadgets πŸ“±": "Write a tech-focused product description for the electronic gadget in the image, focusing on its innovative features, specifications, and user advantages.",
"Eco-Friendly 🌱": "Create an eco-conscious product description for the environmentally friendly product shown in the image, emphasizing sustainability and green benefits.",
"Personalized Gifts 🎁": "Generate a heartfelt product description for the personalized gift in the image, highlighting customization options and sentimental value.",
"Seasonal Promotion πŸŽ‰": "Craft a seasonal promotional product description based on the image, incorporating festive themes and limited-time offers to encourage immediate purchase.",
"Clearance Sale 🏷️": "Write an urgent and enticing product description for the item in the image, emphasizing discounted prices and limited stock availability.",
"Cross-Selling πŸ”—": "Develop a product description that not only highlights the item in the image but also suggests complementary products, encouraging additional purchases.",
"Up-Selling ⬆️": "Create a persuasive product description that highlights premium features of the item in the image, encouraging customers to consider higher-end versions.",
"Multi-Language Support 🌍": "Provide a product description based on the image in multiple languages to cater to a diverse customer base.",
"User Testimonials ⭐": "Incorporate fictional user testimonials or reviews into the product description based on the image, adding credibility and social proof.",
"Instructional πŸ“˜": "Write a product description that includes usage instructions or assembly steps for the item shown in the image.",
"Bundle Offer πŸ“¦": "Craft a product description that promotes the item in the image as part of a bundle deal, highlighting the added value.",
"Gift Guide Entry 🎁": "Generate a product description suitable for inclusion in a gift guide, emphasizing why the item in the image makes a great gift.",
"Limited Edition πŸš€": "Create an exclusive product description for the limited-edition item shown in the image, highlighting its uniqueness and scarcity.",
"Subscription Model πŸ”„": "Write a product description that promotes the item in the image as part of a subscription service, detailing recurring benefits.",
"B2B Focused 🏒": "Develop a professional product description suitable for business-to-business contexts, emphasizing features relevant to corporate clients.",
"Alt Text Generation 🦿": "Generate concise and descriptive alt text for the image, ensuring accessibility for users with visual impairments. Focus on the image's key elements and purpose.",
}
if description_type == "Other" and custom_instruction:
instruction = custom_instruction
else:
instruction = description_prompts.get(
description_type, "Create a product description based on the image."
)
# Payload with base64 encoded image as a Data URL
payload = {
"model": "gpt-4o-mini",
"messages": [
{
"role": "user",
"content": [
{"type": "text", "text": instruction},
{
"type": "image_url",
"image_url": {"url": f"data:image/jpeg;base64,{base64_image}"},
},
],
}
],
"max_tokens": 300,
}
response = requests.post(
"https://api.openai.com/v1/chat/completions", headers=headers, json=payload
)
response_data = response.json()
# Handle errors
if response.status_code != 200:
raise ValueError(
f"OpenAI API Error: {response_data.get('error', {}).get('message', 'Unknown Error')}"
)
# Extract and return only the generated message content
return response_data["choices"][0]["message"]["content"]
# Custom CSS and JavaScript for managing user ID in local storage
custom_css = """
body {
font-family: 'Inter', sans-serif;
}
#output {
height: 500px;
overflow: auto;
border: 1px solid #ccc;
}
.redirect-message {
background-color: #f0f0f0;
border: 1px solid #ccc;
padding: 15px;
margin-top: 20px;
border-radius: 5px;
}
"""
# Initialize user ID
user_id = str(uuid.uuid4())
with gr.Blocks(css=custom_css) as demo:
gr.Markdown("<h1>WordLift Product Description Generation - [FREE]</h1>")
with gr.Tab(label="WordLift Product Description Generation"):
with gr.Row():
with gr.Column():
input_img = gr.Image(label="Input Picture", elem_classes="gr-box")
description_type = gr.Dropdown(
label="Select Description Type",
choices=[
"Short Formal πŸ“",
"Bullet Points πŸ“‹",
"Amazon Optimized πŸ›’",
"Fashion πŸ‘—",
"Sport πŸ€",
"Technical Specifications βš™οΈ",
"SEO Optimized πŸ”",
"Social Media Style πŸ“±",
"Luxury πŸ’Ž",
"Kid-Friendly 🧸",
"Health and Beauty πŸ’„",
"Electronic Gadgets πŸ“±",
"Eco-Friendly 🌱",
"Personalized Gifts 🎁",
"Seasonal Promotion πŸŽ‰",
"Clearance Sale 🏷️",
"Cross-Selling πŸ”—",
"Up-Selling ⬆️",
"Multi-Language Support 🌍",
"User Testimonials ⭐",
"Instructional πŸ“˜",
"Bundle Offer πŸ“¦",
"Gift Guide Entry 🎁",
"Limited Edition πŸš€",
"Subscription Model πŸ”„",
"B2B Focused 🏒",
"Alt Text Generation 🦿",
# "Other",
],
value="Short Formal πŸ“",
elem_classes="gr-box"
)
custom_instruction = gr.Textbox(
label="Custom Instruction (Only for 'Other')", visible=False, elem_classes="gr-box"
)
submit_btn = gr.Button(value="Submit", elem_classes="gr-box")
with gr.Column():
output_text = gr.Markdown(label="Output Text", show_copy_button=True, elem_classes="output-text")
redirect_message = gr.Markdown(visible=False, elem_classes="redirect-message")
test_counter_display = gr.Markdown(visible=True, label="Test Counter")
user_id_display = gr.Markdown(visible=False, label="User ID")
# Hidden textbox to store user ID
user_id_input = gr.Textbox(value="", visible=False)
# Toggle visibility of custom instruction based on selected type
def toggle_custom_instruction(type_selection):
return gr.update(visible=(type_selection == "Other"))
description_type.change(
toggle_custom_instruction,
inputs=[description_type],
outputs=[custom_instruction],
)
def handle_submit(image, description_type, custom_instruction, user_id):
try:
if not user_id:
user_id = str(uuid.uuid4())
check_and_reset_user_counter(user_id)
test_counter = increment_user_counter(user_id)
demo_link = "https://wordlift.io/book-a-demo/?utm_source=free-app&utm_medium=app&utm_campaign=product-description-generator"
if test_counter <= 4:
try:
result = generate_product_description(image, description_type, custom_instruction)
except gr.Error as e:
return (
str(e),
gr.update(visible=False),
gr.update(interactive=True),
f"Error occurred. You still have {4 - test_counter + 1} free test(s) remaining today.",
f"User ID: {user_id}",
user_id
)
remaining_tests = 4 - test_counter
if remaining_tests > 0:
return (
result,
gr.update(visible=False),
gr.update(interactive=True),
f"You have {remaining_tests} free test(s) remaining today.",
f"User ID: {user_id}",
user_id
)
else:
redirect_text = f"""
Thank you for trying our product description generation tool!
You've used all 4 of your free tests for today. We hope you found them helpful and insightful.
To unlock unlimited access and discover how our AI-powered solution can revolutionize your content creation process:
[Book a Personalized Demo with Our Experts]({demo_link})
During the demo, you'll get:<br>
β€’ A tailored walkthrough of our full suite of features<br>
β€’ Insights on how to optimize your specific content workflow<br>
β€’ Answers to any questions you may have about our solution<br>
We're excited to show you how we can help scale your content creation!
(Your free tests will reset tomorrow, allowing you to try 4 more if you need additional time to decide.)
"""
return (
result,
gr.update(visible=True, value=redirect_text),
gr.update(interactive=False),
"You've used all your free tests for today. We invite you to book a demo for full access!",
f"User ID: {user_id}",
user_id
)
else:
redirect_text = f"""
Thank you for your interest in our product description generation tool!
You've already used your 4 free tests for today. We hope they've given you a glimpse of how our AI can enhance your content creation.
Ready to explore the full potential of our solution?
[Book a Personalized Demo with Our Experts]({demo_link})
In this demo, you'll discover:<br>
β€’ How our AI can be customized for your specific needs<br>
β€’ Advanced features for scaling your content production using a [Product Knowledge Graph](https://wordlift.io/blog/en/product-knowledge-graph/)<br>
β€’ ROI projections based on your current content workflow<br>
Let's discuss how we can help you achieve your content goals!
(Remember, your free tests will reset tomorrow if you need more time to evaluate.)
"""
return (
"",
gr.update(visible=True, value=redirect_text),
gr.update(interactive=False),
"All free tests used. We invite you to book a demo for full access!",
f"User ID: {user_id}",
user_id
)
except Exception as e:
return (
f"An error occurred: {str(e)}",
gr.update(visible=False),
gr.update(interactive=True),
"Error processing request",
f"User ID: {user_id}",
user_id
)
# Update the outputs of the submit button click event
submit_btn.click(
handle_submit,
inputs=[input_img, description_type, custom_instruction, user_id_input],
outputs=[output_text, redirect_message, submit_btn, test_counter_display, user_id_display, user_id_input]
)
# Launch Gradio app
demo.queue(api_open=False)
demo.launch(debug=True)