remiai3 commited on
Commit
e6892ca
·
verified ·
1 Parent(s): 1f936b2

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +43 -21
app.py CHANGED
@@ -1,6 +1,6 @@
1
  from flask import Flask, request, jsonify
2
  from flask_cors import CORS
3
- from diffusers import StableDiffusionPipeline, StableDiffusionXLPipeline, DPMSolverMultistepScheduler
4
  import torch
5
  import os
6
  from PIL import Image
@@ -8,6 +8,7 @@ import base64
8
  import time
9
  import logging
10
  from huggingface_hub import list_repo_files
 
11
 
12
  # Disable GPU detection (remove these lines if GPU is available)
13
  os.environ["CUDA_VISIBLE_DEVICES"] = ""
@@ -22,21 +23,22 @@ CORS(app)
22
  logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s')
23
  logger = logging.getLogger(__name__)
24
 
25
- # Log device in use
26
  logger.info(f"Device in use: {torch.device('cpu')}")
 
27
 
28
  # Model cache
29
  model_cache = {}
30
  model_paths = {
31
- "ssd-1b": "segmind/SSD-1B", # Use segmind/SSD-1B for testing
32
  "sd-v1-5": "remiai3/stable-diffusion-v1-5"
33
  }
34
 
35
- # Image ratio to dimensions (optimized for CPU)
36
  ratio_to_dims = {
37
- "1:1": (256, 256),
38
- "3:4": (192, 256),
39
- "16:9": (256, 144)
40
  }
41
 
42
  def load_model(model_id):
@@ -57,7 +59,9 @@ def load_model(model_id):
57
  use_safetensors=True,
58
  low_cpu_mem_usage=True
59
  )
60
- pipe.scheduler = DPMSolverMultistepScheduler.from_config(pipe.scheduler.config)
 
 
61
  pipe.enable_attention_slicing()
62
  pipe.to(torch.device("cpu")) # Change to "cuda" if GPU is available
63
  model_cache[model_id] = pipe
@@ -83,11 +87,15 @@ def generate():
83
  prompt = data.get('prompt', '')
84
  ratio = data.get('ratio', '1:1')
85
  num_images = min(int(data.get('num_images', 1)), 4)
86
- guidance_scale = float(data.get('guidance_scale', 7.5))
 
 
 
87
 
88
  if not prompt:
89
  return jsonify({"error": "Prompt is required"}), 400
90
-
 
91
  if model_id == 'ssd-1b' and num_images > 1:
92
  return jsonify({"error": "SSD-1B allows only 1 image per generation"}), 400
93
  if model_id == 'ssd-1b' and ratio != '1:1':
@@ -95,21 +103,34 @@ def generate():
95
  if model_id == 'sd-v1-5' and len(prompt.split()) > 77:
96
  return jsonify({"error": "Prompt exceeds 77 tokens for Stable Diffusion v1.5"}), 400
97
 
98
- width, height = ratio_to_dims.get(ratio, (256, 256))
 
 
 
 
 
 
99
  pipe = load_model(model_id)
100
  pipe.to(torch.device("cpu")) # Change to "cuda" if GPU is available
101
 
102
  images = []
103
- num_inference_steps = 20 if model_id == 'ssd-1b' else 30
104
- for _ in range(num_images):
105
- image = pipe(
106
- prompt=prompt,
107
- height=height,
108
- width=width,
109
- num_inference_steps=num_inference_steps,
110
- guidance_scale=guidance_scale
111
- ).images[0]
112
- images.append(image)
 
 
 
 
 
 
 
113
 
114
  output_dir = "outputs"
115
  os.makedirs(output_dir, exist_ok=True)
@@ -122,6 +143,7 @@ def generate():
122
  image_urls.append(f"data:image/png;base64,{img_data}")
123
  os.remove(img_path)
124
 
 
125
  return jsonify({"images": image_urls})
126
 
127
  except Exception as e:
 
1
  from flask import Flask, request, jsonify
2
  from flask_cors import CORS
3
+ from diffusers import StableDiffusionPipeline, StableDiffusionXLPipeline, UniPCMultistepScheduler
4
  import torch
5
  import os
6
  from PIL import Image
 
8
  import time
9
  import logging
10
  from huggingface_hub import list_repo_files
11
+ import psutil
12
 
13
  # Disable GPU detection (remove these lines if GPU is available)
14
  os.environ["CUDA_VISIBLE_DEVICES"] = ""
 
23
  logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s')
24
  logger = logging.getLogger(__name__)
25
 
26
+ # Log device and memory info
27
  logger.info(f"Device in use: {torch.device('cpu')}")
28
+ logger.info(f"Available memory: {psutil.virtual_memory().available / (1024 ** 3):.2f} GB")
29
 
30
  # Model cache
31
  model_cache = {}
32
  model_paths = {
33
+ "ssd-1b": "segmind/SSD-1B", # Using segmind/SSD-1B for testing
34
  "sd-v1-5": "remiai3/stable-diffusion-v1-5"
35
  }
36
 
37
+ # Image ratio to dimensions (optimized for CPU, multiple of 8)
38
  ratio_to_dims = {
39
+ "1:1": (512, 512), # Default for SSD-1B
40
+ "3:4": (384, 512),
41
+ "16:9": (512, 288)
42
  }
43
 
44
  def load_model(model_id):
 
59
  use_safetensors=True,
60
  low_cpu_mem_usage=True
61
  )
62
+ # Use UniPCMultistepScheduler for SSD-1B, DPMSolver for SD-v1-5
63
+ scheduler = UniPCMultistepScheduler.from_config(pipe.scheduler.config) if model_id == "ssd-1b" else DPMSolverMultistepScheduler.from_config(pipe.scheduler.config)
64
+ pipe.scheduler = scheduler
65
  pipe.enable_attention_slicing()
66
  pipe.to(torch.device("cpu")) # Change to "cuda" if GPU is available
67
  model_cache[model_id] = pipe
 
87
  prompt = data.get('prompt', '')
88
  ratio = data.get('ratio', '1:1')
89
  num_images = min(int(data.get('num_images', 1)), 4)
90
+ guidance_scale = float(min(max(data.get('guidance_scale', 7.5), 1.0), 20.0)) # Clamp guidance scale
91
+
92
+ # Log input parameters
93
+ logger.info(f"Generating with model: {model_id}, prompt: {prompt}, ratio: {ratio}, num_images: {num_images}, guidance_scale: {guidance_scale}")
94
 
95
  if not prompt:
96
  return jsonify({"error": "Prompt is required"}), 400
97
+ if len(prompt) > 512:
98
+ return jsonify({"error": "Prompt is too long (max 512 characters)"}), 400
99
  if model_id == 'ssd-1b' and num_images > 1:
100
  return jsonify({"error": "SSD-1B allows only 1 image per generation"}), 400
101
  if model_id == 'ssd-1b' and ratio != '1:1':
 
103
  if model_id == 'sd-v1-5' and len(prompt.split()) > 77:
104
  return jsonify({"error": "Prompt exceeds 77 tokens for Stable Diffusion v1.5"}), 400
105
 
106
+ width, height = ratio_to_dims.get(ratio, (512, 512))
107
+ if width % 8 != 0 or height % 8 != 0:
108
+ return jsonify({"error": "Width and height must be multiples of 8"}), 400
109
+
110
+ # Log memory before generation
111
+ logger.info(f"Memory before generation: {psutil.virtual_memory().available / (1024 ** 3):.2f} GB")
112
+
113
  pipe = load_model(model_id)
114
  pipe.to(torch.device("cpu")) # Change to "cuda" if GPU is available
115
 
116
  images = []
117
+ num_inference_steps = 30 if model_id == 'ssd-1b' else 40 # Unified steps for stability
118
+ try:
119
+ for _ in range(num_images):
120
+ image = pipe(
121
+ prompt=prompt,
122
+ height=height,
123
+ width=width,
124
+ num_inference_steps=num_inference_steps,
125
+ guidance_scale=guidance_scale
126
+ ).images[0]
127
+ images.append(image)
128
+ except IndexError as e:
129
+ logger.error(f"IndexError during generation: {str(e)}")
130
+ return jsonify({"error": f"Generation failed due to invalid index access: {str(e)}"}), 500
131
+ except Exception as e:
132
+ logger.error(f"Unexpected error during generation: {str(e)}")
133
+ return jsonify({"error": f"Generation failed: {str(e)}"}), 500
134
 
135
  output_dir = "outputs"
136
  os.makedirs(output_dir, exist_ok=True)
 
143
  image_urls.append(f"data:image/png;base64,{img_data}")
144
  os.remove(img_path)
145
 
146
+ logger.info(f"Generation successful, returning {len(image_urls)} images")
147
  return jsonify({"images": image_urls})
148
 
149
  except Exception as e: