Vnmrsharma commited on
Commit
857b096
·
verified ·
1 Parent(s): d556179

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +84 -67
app.py CHANGED
@@ -20,6 +20,9 @@ dt_lock = Lock()
20
  _last_call_time = 0.0
21
 
22
  def throttle():
 
 
 
23
  global _last_call_time
24
  with dt_lock:
25
  now = time.time()
@@ -29,43 +32,28 @@ def throttle():
29
  _last_call_time = time.time()
30
 
31
  # Detailed prompt variations for different backgrounds/angles
32
- after = "..." # placeholder to show continuation; see full PROMPT_VARIATIONS in code
33
- PROMPT_VARIATIONS = [
34
- # 1: White background
35
- "Chain-of-Thought: Step 1: Carefully analyze the input image and document every single detail of the product—text, colour, material finish, branding, dimensions, and any embellishments—ensuring no detail is overlooked. Step 2: Generate a highly professional 800×800px image with a pure white background and bright natural lighting, strictly preserving the product’s text, colour, shape and finish exactly as in the original image, with zero alterations. Step 3: Rigorously verify pixel-by-pixel that the output matches the original product data 100 %, then deliver a ready-for-e-commerce upload image.",
36
- # 2: Garden background
37
- "Chain-of-Thought: Step 1: Meticulously analyze the input image and record every product detail—text, colour, material finish, branding, dimensions, texture, and any embellishments—ensuring nothing is overlooked. Step 2: Generate a highly professional 800×800px image of the product from a precise 45° top-down angle against a green garden background with even lighting, strictly preserving the product’s text, colours, shape and finish exactly as in the original image, with zero alterations. Step 3: Perform a rigorous pixel-level comparison to confirm 100 % fidelity to the original product data and deliver an e-commerce–ready image.",
38
- # 3: Modern indoor
39
- "Chain-of-Thought: Step 1: Scrutinize the input image to record every element of the product—text, colour palette, material finish, and branding—without exception. Step 2: Generate a highly professional 800×800px image from a slightly elevated angle and open lid if the product have a lid in a modern indoor setting with warm lighting, strictly preserving the product’s original text, colours and all details exactly as in the source. Step 3: Double-check at full resolution that no aspect of the product has been altered and that the image is e-commerce ready.",
40
- # 4: Spa-like setting
41
- "Chain-of-Thought: Step 1: Analyze the input image pixel-for-pixel to note every product detail—text, colour, texture, finish, branding and proportions—ensuring nothing is missed. Step 2: Generate a highly professional 800×800px image using a A serene, spa-like setting with elements of tranquility like smooth stones, bamboo, and a calming water feature, ideal for wellness or beauty products. background, with the product’s text, colours, materials and details preserved exactly as in the original. Step 3: Verify 100 % fidelity at the pixel level and confirm readiness for online catalog upload.",
42
- # 5: Vibrant outdoor
43
- "Chain-of-Thought: Step 1: Inspect the input image meticulously and record every detail—text, colour gradients, material texture, and branding—ensuring total accuracy. Step 2: Generate a highly professional 800×800px image with a vibrant outdoor background and natural sunlight, strictly preserving the product’s original text, colours, finish and all details unchanged. Step 3: Validate that the final image is flawless, matches the original exactly, and is optimized for e-commerce display.",
44
- # 6: Gradient background
45
- "Chain-of-Thought: Step 1: Review the input image thoroughly, capturing and logging every detail—text, colour accuracy, surface finish, and branding—100 % intact. Step 2: Generate a highly professional 800×800px image with a subtle gradient background and soft diffused lighting, ensuring that the product’s text, colours and all design details remain precisely as in the source. Step 3: Perform a pixel-level check to confirm no alterations and that the image meets e-commerce quality standards.",
46
- # 7: Abstract background
47
- "Chain-of-Thought: Step 1: Examine the original product image in depth, noting every detail—text, colour tones, material texture, branding logos and dimensions—with absolute precision. Step 2: Generate a highly professional 800×800px image featuring an abstract background with perfect lighting, strictly preserving the product’s text, colours and every fine detail exactly as in the original. Step 3: Verify pixel-perfect fidelity and confirm the output is upload-ready for an online store.",
48
- # 8: Lifestyle setting
49
- "Chain-of-Thought: Step 1: Scrutinize the input image in full detail, logging every aspect of the product—text, colour accuracy, branding, material texture, finish, and proportions—to guarantee total fidelity. Step 2: Generate a highly professional 800×800px image of the product placed A cozy, homely setting with a comfortable, inviting ambiance, featuring elements like soft lighting, plush textiles, and warm tones, suitable for home goods or comfort products. ensuring that the product’s text, colours, materials and every detail remain exactly as in the original image without any modification. Step 3: Validate at the pixel level that the output matches the original image perfectly and confirm readiness for online catalog upload.",
50
- ]
51
-
52
  def process_variation(variation, input_image, product_name):
53
  # Throttle to respect API rate limit
54
  throttle()
 
 
55
  text_input = (
56
  f"Hi, this is a picture of a product. The name of the product is {product_name}.",
57
  variation
58
  )
 
 
59
  response = client.models.generate_content(
60
  model=univin_model,
61
  contents=[text_input, input_image],
62
  config=types.GenerateContentConfig(response_modalities=['Text', 'Image'])
63
  )
 
64
  # Extract generated image bytes
65
  for part in response.candidates[0].content.parts:
66
  if part.inline_data is not None:
67
  img = Image.open(BytesIO(part.inline_data.data))
68
- # Save to temp file
69
  with tempfile.NamedTemporaryFile(delete=False, suffix=".png") as tmp:
70
  img.save(tmp, format="PNG")
71
  return tmp.name
@@ -73,57 +61,86 @@ def process_variation(variation, input_image, product_name):
73
 
74
 
75
  def generate_images(input_image, product_name):
 
 
 
76
  with concurrent.futures.ThreadPoolExecutor() as executor:
77
  futures = [
78
  executor.submit(process_variation, var, input_image, product_name)
79
  for var in PROMPT_VARIATIONS
80
  ]
81
- # Collect successful outputs
82
- return [f.result() for f in futures if f.result() is not None]
83
 
84
- # Gradio UI setup
85
- custom_css = """
86
- #generate-button {
87
- background-color: #4A90E2;
88
- color: white;
89
- border-radius: 8px;
90
- padding: 12px 24px;
91
- font-size: 16px;
92
- margin-top: 10px;
93
- }
94
- #gallery .gallery-item {
95
- border-radius: 12px;
96
- box-shadow: 0 4px 6px rgba(0,0,0,0.1);
97
- transition: transform 0.2s ease;
98
- }
99
- #gallery .gallery-item:hover {
100
- transform: scale(1.05);
101
- }
102
- #input-row {
103
- gap: 20px;
104
- align-items: start;
105
- }
106
- """
 
107
 
108
- demo = gr.Blocks(css=custom_css, theme=gr.themes.Soft())
109
- with demo:
110
- gr.Markdown("""
111
- ## 🎨 Uni-Imaginator (Rate-Limited)
112
- **Create professional, e-commerce–ready product images effortlessly—now respecting API rate limits.**
113
- """)
114
- with gr.Row(elem_id="input-row"):
115
- with gr.Column(scale=1):
116
- input_image = gr.Image(type="pil", label="Upload Product Image", elem_id="upload-img")
117
- product_name = gr.Textbox(label="Product Name", placeholder="Enter your product's name here", elem_id="product-name")
118
- generate_button = gr.Button("Generate Images", variant="primary", elem_id="generate-button")
119
- with gr.Column(scale=1):
120
- gr.Markdown("""
121
- **How to Use:**
122
- 1. Upload a clear photo of your product.
123
- 2. Enter the product name.
124
- 3. Click **Generate Images** and wait a few moments while images are processed within rate limits.
125
- """)
126
- gallery = gr.Gallery(label="Generated Images", elem_id="gallery", columns=4, object_fit="contain", height="auto", show_label=False)
127
- generate_button.click(fn=generate_images, inputs=[input_image, product_name], outputs=gallery)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
128
 
129
- demo.launch()
 
 
 
20
  _last_call_time = 0.0
21
 
22
  def throttle():
23
+ """
24
+ Ensures there's at least CALL_INTERVAL seconds between API calls.
25
+ """
26
  global _last_call_time
27
  with dt_lock:
28
  now = time.time()
 
32
  _last_call_time = time.time()
33
 
34
  # Detailed prompt variations for different backgrounds/angles
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35
  def process_variation(variation, input_image, product_name):
36
  # Throttle to respect API rate limit
37
  throttle()
38
+
39
+ # Build text + image input
40
  text_input = (
41
  f"Hi, this is a picture of a product. The name of the product is {product_name}.",
42
  variation
43
  )
44
+
45
+ # Call the GenAI API
46
  response = client.models.generate_content(
47
  model=univin_model,
48
  contents=[text_input, input_image],
49
  config=types.GenerateContentConfig(response_modalities=['Text', 'Image'])
50
  )
51
+
52
  # Extract generated image bytes
53
  for part in response.candidates[0].content.parts:
54
  if part.inline_data is not None:
55
  img = Image.open(BytesIO(part.inline_data.data))
56
+ # Save to temp file and return its path
57
  with tempfile.NamedTemporaryFile(delete=False, suffix=".png") as tmp:
58
  img.save(tmp, format="PNG")
59
  return tmp.name
 
61
 
62
 
63
  def generate_images(input_image, product_name):
64
+ """
65
+ Generate one image per prompt variation in parallel, respecting rate limits.
66
+ """
67
  with concurrent.futures.ThreadPoolExecutor() as executor:
68
  futures = [
69
  executor.submit(process_variation, var, input_image, product_name)
70
  for var in PROMPT_VARIATIONS
71
  ]
72
+ return [f.result() for f in futures if f.result()]
 
73
 
74
+ # Gradio UI setup with custom styling
75
+ def build_interface():
76
+ custom_css = """
77
+ #generate-button {
78
+ background-color: #4A90E2;
79
+ color: white;
80
+ border-radius: 8px;
81
+ padding: 12px 24px;
82
+ font-size: 16px;
83
+ margin-top: 10px;
84
+ }
85
+ #gallery .gallery-item {
86
+ border-radius: 12px;
87
+ box-shadow: 0 4px 6px rgba(0,0,0,0.1);
88
+ transition: transform 0.2s ease;
89
+ }
90
+ #gallery .gallery-item:hover {
91
+ transform: scale(1.05);
92
+ }
93
+ #input-row {
94
+ gap: 20px;
95
+ align-items: start;
96
+ }
97
+ """
98
 
99
+ demo = gr.Blocks(css=custom_css, theme=gr.themes.Soft())
100
+ with demo:
101
+ gr.Markdown(
102
+ """
103
+ ## 🎨 Uni-Imaginator (Rate-Limited)
104
+ **Create professional, e-commerce–ready product images effortlessly—now respecting API rate limits.**
105
+ """
106
+ )
107
+ with gr.Row(elem_id="input-row"):
108
+ with gr.Column(scale=1):
109
+ input_image = gr.Image(
110
+ type="pil", label="Upload Product Image", elem_id="upload-img"
111
+ )
112
+ product_name = gr.Textbox(
113
+ label="Product Name",
114
+ placeholder="Enter your product's name here",
115
+ elem_id="product-name"
116
+ )
117
+ generate_button = gr.Button(
118
+ "Generate Images", variant="primary", elem_id="generate-button"
119
+ )
120
+ with gr.Column(scale=1):
121
+ gr.Markdown(
122
+ """
123
+ **How to Use:**
124
+ 1. Upload a clear photo of your product.
125
+ 2. Enter the product name.
126
+ 3. Click **Generate Images** and wait a few moments while images are processed within rate limits.
127
+ """
128
+ )
129
+ gallery = gr.Gallery(
130
+ label="Generated Images",
131
+ elem_id="gallery",
132
+ columns=4,
133
+ object_fit="contain",
134
+ height="auto",
135
+ show_label=False
136
+ )
137
+ generate_button.click(
138
+ fn=generate_images,
139
+ inputs=[input_image, product_name],
140
+ outputs=gallery
141
+ )
142
+ return demo
143
 
144
+ # Launch the app with SSR and async queue disabled to prevent file timeouts
145
+ demo_app = build_interface()
146
+ demo_app.launch(ssr=False, enable_queue=False)