Creative-Design / app.py
openfree's picture
Update app.py
6367647 verified
raw
history blame
17.1 kB
import gradio as gr
import replicate
import os
from PIL import Image
import requests
from io import BytesIO
import time
import tempfile
import base64
import json
# Set up API keys from environment variables
os.environ['REPLICATE_API_TOKEN'] = os.getenv('REPLICATE_API_TOKEN')
FIREWORKS_API_KEY = os.getenv('FIREWORKS_API_KEY', '')
def enhance_prompt_with_team(user_input):
"""
Enhanced prompt generation using team collaboration approach:
Director -> Engineer (with web search) -> Designer
"""
if not FIREWORKS_API_KEY:
return user_input
try:
url = "https://api.fireworks.ai/inference/v1/chat/completions"
# Team collaboration system prompt
system_prompt = """You are a product design team consisting of three roles working in sequence:
## TEAM COLLABORATION PROCESS:
### 1. DIRECTOR (Creative Vision Leader)
The Director analyzes the user's input and establishes:
- Core product category and target market
- Key functional requirements
- Design philosophy and brand positioning
- Initial design direction and constraints
- Questions for the engineering team
### 2. ENGINEER (Technical Feasibility Expert)
The Engineer responds to the Director's vision by:
- Researching current technologies and materials
- Identifying manufacturing possibilities
- Suggesting innovative technical features
- Evaluating feasibility of proposed concepts
- Providing data on similar successful products
- Recommending technical specifications
### 3. DESIGNER (Visual Design Specialist)
The Designer synthesizes all inputs to create the final prompt:
- Translating technical specs into visual language
- Adding aesthetic details and finishing touches
- Specifying materials, textures, and colors
- Defining the rendering style
- Creating the complete visual description
## OUTPUT FORMAT:
Structure the team discussion as follows:
**DIRECTOR'S VISION:**
[Director's analysis and initial direction]
**ENGINEER'S TECHNICAL ASSESSMENT:**
[Research findings and technical recommendations]
**DIRECTOR'S REFINEMENT:**
[Approval/modification of engineering inputs]
**DESIGNER'S FINAL PROMPT:**
[Complete product design prompt with all visual details]
Focus exclusively on PHYSICAL PRODUCT DESIGN - no services, apps, or abstract concepts.
Examples: furniture, electronics, vehicles, appliances, tools, wearables, etc."""
# Create the collaborative dialogue
user_prompt = f"""Create a product design for: {user_input}
Execute the full team collaboration process:
1. Director establishes the vision
2. Engineer researches and provides technical input (simulate web research findings)
3. Director refines based on engineering feedback
4. Designer creates the final detailed visual prompt
Remember: Focus ONLY on physical product design."""
payload = {
"model": "accounts/fireworks/models/qwen3-235b-a22b-instruct-2507",
"max_tokens": 800,
"top_p": 0.9,
"top_k": 40,
"presence_penalty": 0.3,
"frequency_penalty": 0.2,
"temperature": 0.8,
"messages": [
{
"role": "system",
"content": system_prompt
},
{
"role": "user",
"content": user_prompt
}
]
}
headers = {
"Accept": "application/json",
"Content-Type": "application/json",
"Authorization": f"Bearer {FIREWORKS_API_KEY}"
}
response = requests.post(url, headers=headers, data=json.dumps(payload), timeout=15)
if response.status_code == 200:
result = response.json()
enhanced = result.get('choices', [{}])[0].get('message', {}).get('content', '')
if enhanced:
# Extract only the designer's final prompt from the response
if "DESIGNER'S FINAL PROMPT:" in enhanced:
parts = enhanced.split("DESIGNER'S FINAL PROMPT:")
if len(parts) > 1:
return parts[1].strip()
return enhanced
return user_input
except Exception as e:
print(f"Team collaboration error: {str(e)}")
return user_input
def upload_image_to_hosting(image):
"""
Upload image to multiple hosting services with fallback
"""
# Method 1: Try imgbb.com
try:
buffered = BytesIO()
image.save(buffered, format="PNG")
buffered.seek(0)
img_base64 = base64.b64encode(buffered.getvalue()).decode()
response = requests.post(
"https://api.imgbb.com/1/upload",
data={
'key': '6d207e02198a847aa98d0a2a901485a5',
'image': img_base64,
}
)
if response.status_code == 200:
data = response.json()
if data.get('success'):
return data['data']['url']
except:
pass
# Method 2: Try 0x0.st
try:
buffered = BytesIO()
image.save(buffered, format="PNG")
buffered.seek(0)
files = {'file': ('image.png', buffered, 'image/png')}
response = requests.post("https://0x0.st", files=files)
if response.status_code == 200:
return response.text.strip()
except:
pass
# Method 3: Fallback to base64
buffered = BytesIO()
image.save(buffered, format="PNG")
buffered.seek(0)
img_base64 = base64.b64encode(buffered.getvalue()).decode()
return f"data:image/png;base64,{img_base64}"
def process_product_design(prompt, enhance_prompt_flag, image1, image2=None):
"""
Process product design with team collaboration approach
"""
if not os.getenv('REPLICATE_API_TOKEN'):
return None, prompt, "Please set REPLICATE_API_TOKEN", ""
try:
# Store team discussion for display
team_discussion = ""
# Enhance prompt with team collaboration if requested
final_prompt = prompt
if enhance_prompt_flag:
# This will contain the full team discussion
full_response = enhance_prompt_with_team(prompt)
final_prompt = full_response
# Store the discussion for display
team_discussion = f"🎬 **Director → Engineer → Designer Collaboration**\n\n{full_response}"
# Prepare input for model
model_input = {
"prompt": final_prompt
}
# Add style reference images if provided
if image1 or image2:
image_urls = []
if image1:
url1 = upload_image_to_hosting(image1)
image_urls.append(url1)
if image2:
url2 = upload_image_to_hosting(image2)
image_urls.append(url2)
model_input["image_input"] = image_urls
status_msg = "🏭 Product design generated with style references!"
else:
status_msg = "🏭 Product design generated from concept!"
# Run model
output = replicate.run(
"google/nano-banana",
input=model_input
)
if output is None:
return None, final_prompt, "No output received", team_discussion
# Get the generated image
try:
if hasattr(output, 'read'):
img_data = output.read()
img = Image.open(BytesIO(img_data))
return img, final_prompt, status_msg, team_discussion
except:
pass
try:
if hasattr(output, 'url'):
output_url = output.url()
response = requests.get(output_url, timeout=30)
if response.status_code == 200:
img = Image.open(BytesIO(response.content))
return img, final_prompt, status_msg, team_discussion
except:
pass
output_url = None
if isinstance(output, str):
output_url = output
elif isinstance(output, list) and len(output) > 0:
output_url = output[0]
if output_url:
response = requests.get(output_url, timeout=30)
if response.status_code == 200:
img = Image.open(BytesIO(response.content))
return img, final_prompt, status_msg, team_discussion
return None, final_prompt, "Could not process output", team_discussion
except Exception as e:
error_msg = str(e)
if "image_input" in error_msg.lower():
return None, prompt, "Note: Model may require at least one image.", ""
return None, prompt, f"Error: {error_msg[:100]}", ""
# Enhanced CSS for Product Design focus
css = """
.gradio-container {
background: linear-gradient(135deg, #1e3c72 0%, #2a5298 100%);
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
min-height: 100vh;
}
.header-container {
background: linear-gradient(135deg, #434343 0%, #000000 100%);
padding: 2.5rem;
border-radius: 24px;
margin-bottom: 2.5rem;
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.4);
}
.logo-text {
font-size: 3.5rem;
font-weight: 900;
color: white;
text-align: center;
margin: 0;
letter-spacing: -2px;
text-shadow: 2px 2px 4px rgba(0,0,0,0.5);
}
.subtitle {
color: #e0e0e0;
text-align: center;
font-size: 1.2rem;
margin-top: 0.5rem;
font-weight: 300;
}
.mode-indicator {
background: rgba(255, 255, 255, 0.1);
backdrop-filter: blur(10px);
border-radius: 12px;
padding: 0.8rem 1.5rem;
margin-top: 1rem;
text-align: center;
font-weight: 600;
color: #ffd700;
border: 1px solid rgba(255, 215, 0, 0.3);
}
.main-content {
background: rgba(255, 255, 255, 0.98);
backdrop-filter: blur(20px);
border-radius: 24px;
padding: 2.5rem;
box-shadow: 0 10px 40px rgba(0, 0, 0, 0.2);
}
.gr-button-primary {
background: linear-gradient(135deg, #434343 0%, #000000 100%) !important;
border: 2px solid #ffd700 !important;
color: white !important;
font-weight: 700 !important;
font-size: 1.1rem !important;
padding: 1.2rem 2rem !important;
border-radius: 14px !important;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1) !important;
text-transform: uppercase;
letter-spacing: 1px;
width: 100%;
margin-top: 1rem !important;
}
.gr-button-primary:hover {
transform: translateY(-3px) !important;
box-shadow: 0 15px 40px rgba(255, 215, 0, 0.3) !important;
background: linear-gradient(135deg, #ffd700 0%, #ffed4e 100%) !important;
color: #000 !important;
}
.gr-input, .gr-textarea {
background: #ffffff !important;
border: 2px solid #d0d0d0 !important;
border-radius: 12px !important;
color: #2d3436 !important;
font-size: 1rem !important;
padding: 0.8rem 1rem !important;
}
.gr-input:focus, .gr-textarea:focus {
border-color: #434343 !important;
box-shadow: 0 0 0 4px rgba(67, 67, 67, 0.1) !important;
}
.team-discussion {
background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
border-radius: 12px;
padding: 1.5rem;
margin-top: 1rem;
border-left: 4px solid #434343;
font-family: 'Monaco', 'Courier New', monospace;
font-size: 0.9rem;
max-height: 400px;
overflow-y: auto;
}
.info-box {
background: linear-gradient(135deg, #ffd700 0%, #ffed4e 100%);
border-radius: 12px;
padding: 1rem;
margin-bottom: 1rem;
border-left: 4px solid #000;
color: #000;
font-weight: 500;
}
.enhanced-prompt-box {
background: #f0f0f0;
border-radius: 12px;
padding: 1rem;
margin-top: 1rem;
border-left: 4px solid #ffd700;
}
footer {
display: none !important;
}
"""
with gr.Blocks(css=css, theme=gr.themes.Base()) as demo:
with gr.Column(elem_classes="header-container"):
gr.HTML("""
<h1 class="logo-text">🏭 PRODUCT DESIGN STUDIO</h1>
<p class="subtitle">AI-Powered Industrial & Product Design System</p>
<div class="mode-indicator">
👥 Team Collaboration: Director → Engineer → Designer
</div>
""")
with gr.Column(elem_classes="main-content"):
# Info box
gr.HTML("""
<div class="info-box">
<strong>🎯 Professional Product Design Process:</strong><br>
• <b>Director:</b> Establishes design vision and requirements<br>
• <b>Engineer:</b> Researches technology and feasibility<br>
• <b>Designer:</b> Creates detailed visual specifications<br>
• Focus: Physical products only (electronics, furniture, vehicles, tools, etc.)
</div>
""")
with gr.Row(equal_height=True):
# Left Column - Inputs
with gr.Column(scale=1):
prompt = gr.Textbox(
label="Product Concept",
placeholder="Examples: 'ergonomic office chair', 'smart home speaker', 'electric bicycle', 'modular kitchen appliance'...",
lines=3,
value="professional mechanical keyboard",
elem_classes="prompt-input"
)
enhance_prompt_checkbox = gr.Checkbox(
label="👥 Enable Team Collaboration (Director + Engineer + Designer)",
value=True,
info="Activates multi-role design process with technical research"
)
with gr.Row(equal_height=True):
image1 = gr.Image(
label="Style/Material Reference 1",
type="pil",
height=200,
elem_classes="image-container"
)
image2 = gr.Image(
label="Style/Material Reference 2",
type="pil",
height=200,
elem_classes="image-container"
)
generate_btn = gr.Button(
"Generate Product Design 🏭",
variant="primary",
size="lg"
)
# Right Column - Output
with gr.Column(scale=1):
output_image = gr.Image(
label="Product Design Visualization",
type="pil",
height=420,
elem_classes="image-container"
)
enhanced_prompt_display = gr.Textbox(
label="Final Design Specifications",
interactive=False,
lines=4,
elem_classes="enhanced-prompt-box",
visible=True,
value="Design specifications will appear here..."
)
status = gr.Textbox(
label="Status",
interactive=False,
lines=1,
elem_classes="status-text",
value="Ready to design products..."
)
# Team Discussion Display
with gr.Row():
team_discussion_display = gr.Markdown(
label="Team Collaboration Process",
value="",
elem_classes="team-discussion"
)
# Event handler
generate_btn.click(
fn=process_product_design,
inputs=[prompt, enhance_prompt_checkbox, image1, image2],
outputs=[output_image, enhanced_prompt_display, status, team_discussion_display]
)
# Product Design Examples
gr.Examples(
examples=[
["ergonomic gaming mouse", True, None, None],
["portable coffee maker", True, None, None],
["modular storage system", True, None, None],
["smart bicycle helmet", True, None, None],
["industrial power tool", True, None, None],
["luxury watch design", True, None, None],
["compact home gym equipment", True, None, None],
["sustainable packaging solution", True, None, None],
["professional camera lens", True, None, None],
["electric vehicle charging station", True, None, None],
],
inputs=[prompt, enhance_prompt_checkbox, image1, image2],
label="Product Design Examples (Team will collaborate on these concepts)"
)
# Launch
if __name__ == "__main__":
demo.launch(
share=True,
server_name="0.0.0.0",
server_port=7860
)