yukee1992 commited on
Commit
8644d43
·
verified ·
1 Parent(s): a2d0292

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +37 -71
app.py CHANGED
@@ -24,7 +24,6 @@ import time
24
  from requests.adapters import HTTPAdapter
25
  from urllib3.util.retry import Retry
26
  from huggingface_hub import HfApi
27
- import accelerate
28
  import sys
29
  import traceback
30
 
@@ -38,7 +37,7 @@ print(f"Python version: {sys.version}")
38
  print(f"PyTorch version: {torch.__version__}")
39
  print(f"CUDA available: {torch.cuda.is_available()}")
40
 
41
- # Create diagnostic endpoint that works immediately
42
  app = FastAPI(title="Storybook Generator API")
43
 
44
  @app.get("/ping")
@@ -47,7 +46,7 @@ async def ping():
47
  return {
48
  "status": "alive",
49
  "timestamp": datetime.now().isoformat(),
50
- "message": "Basic endpoint is working"
51
  }
52
 
53
  @app.get("/debug")
@@ -73,22 +72,6 @@ app.add_middleware(
73
  allow_headers=["*"],
74
  )
75
 
76
- # =============================================
77
- # MEMORY OPTIMIZATION SETTINGS
78
- # =============================================
79
- # Check if CUDA is available and set memory optimization
80
- if torch.cuda.is_available():
81
- print("✅ CUDA available, enabling GPU optimizations")
82
- torch.backends.cuda.enable_flash_sdp(True)
83
- torch.backends.cuda.enable_mem_efficient_sdp(True)
84
- else:
85
- print("⚠️ CUDA not available, running on CPU")
86
-
87
- # Set environment variables for memory optimization
88
- os.environ["PYTORCH_CUDA_ALLOC_CONF"] = "max_split_size_mb:128"
89
- os.environ["OMP_NUM_THREADS"] = "1"
90
- os.environ["MKL_NUM_THREADS"] = "1"
91
-
92
  # =============================================
93
  # HUGGING FACE DATASET CONFIGURATION
94
  # =============================================
@@ -156,7 +139,7 @@ class MemoryStatusResponse(BaseModel):
156
  gpu_memory_cached_mb: Optional[float] = None
157
  status: str
158
 
159
- # HIGH-QUALITY MODEL SELECTION
160
  MODEL_CHOICES = {
161
  "dreamshaper-8": "lykon/dreamshaper-8",
162
  "realistic-vision": "SG161222/Realistic_Vision_V5.1",
@@ -178,7 +161,7 @@ model_lock = threading.Lock()
178
  model_loading = False
179
  model_load_error = None
180
 
181
- # MEMORY MANAGEMENT FUNCTIONS
182
  def get_memory_usage():
183
  """Get current memory usage statistics"""
184
  process = psutil.Process()
@@ -267,10 +250,10 @@ def clear_memory(clear_models=True, clear_jobs=False, clear_local_images=False,
267
  }
268
 
269
  # =============================================
270
- # MODEL LOADING WITH PROPER ERROR HANDLING
271
  # =============================================
272
  def load_model(model_name="dreamshaper-8"):
273
- """Thread-safe model loading with error handling"""
274
  global model_cache, current_model_name, current_pipe, model_loading, model_load_error
275
 
276
  with model_lock:
@@ -279,10 +262,6 @@ def load_model(model_name="dreamshaper-8"):
279
  current_model_name = model_name
280
  return current_pipe
281
 
282
- if model_loading:
283
- print(f"⏳ Model already loading, waiting...")
284
- return None
285
-
286
  model_loading = True
287
  model_load_error = None
288
 
@@ -290,29 +269,23 @@ def load_model(model_name="dreamshaper-8"):
290
  try:
291
  model_id = MODEL_CHOICES.get(model_name, "lykon/dreamshaper-8")
292
 
293
- # Load with memory optimizations
294
  pipe = StableDiffusionPipeline.from_pretrained(
295
  model_id,
296
  torch_dtype=torch.float32,
297
  safety_checker=None,
298
  requires_safety_checker=False,
299
- cache_dir="./model_cache",
300
- low_cpu_mem_usage=True,
301
- use_safetensors=True
302
  )
303
 
304
- # Use memory efficient scheduler
305
  pipe.scheduler = EulerAncestralDiscreteScheduler.from_config(pipe.scheduler.config)
306
 
307
- # Enable attention slicing
308
- pipe.enable_attention_slicing()
309
-
310
- # Enable sequential CPU offload if needed
311
- if not torch.cuda.is_available():
312
- pipe.enable_sequential_cpu_offload()
313
-
314
  pipe = pipe.to("cpu")
315
 
 
 
316
  model_cache[model_name] = pipe
317
  current_pipe = pipe
318
  current_model_name = model_name
@@ -332,12 +305,9 @@ def load_model(model_name="dreamshaper-8"):
332
  "runwayml/stable-diffusion-v1-5",
333
  torch_dtype=torch.float32,
334
  safety_checker=None,
335
- requires_safety_checker=False,
336
- low_cpu_mem_usage=True
337
  ).to("cpu")
338
 
339
- pipe.enable_attention_slicing()
340
-
341
  model_cache[model_name] = pipe
342
  current_pipe = pipe
343
  current_model_name = "sd-1.5"
@@ -443,9 +413,9 @@ def upload_image_to_hf_dataset(image, project_id, page_number, prompt, style="")
443
  print(f"❌ Failed to upload image to HF Dataset: {e}")
444
  return None
445
 
446
- # PROMPT ENGINEERING
447
  def enhance_prompt_simple(scene_visual, style="childrens_book"):
448
- """Simple prompt enhancement"""
449
 
450
  style_templates = {
451
  "childrens_book": "children's book illustration, watercolor style, soft colors, whimsical, magical, storybook art, professional illustration",
@@ -466,13 +436,16 @@ def enhance_prompt_simple(scene_visual, style="childrens_book"):
466
  return enhanced_prompt, negative_prompt
467
 
468
  # =============================================
469
- # IMAGE GENERATION
470
  # =============================================
471
  def generate_image_simple(prompt, model_choice, style, scene_number, consistency_seed=None):
472
- """Generate image with error handling"""
473
 
474
  if current_pipe is None:
475
- raise Exception("Model not loaded yet. Please wait a few seconds and try again.")
 
 
 
476
 
477
  enhanced_prompt, negative_prompt = enhance_prompt_simple(prompt, style)
478
 
@@ -484,19 +457,16 @@ def generate_image_simple(prompt, model_choice, style, scene_number, consistency
484
  try:
485
  pipe = current_pipe
486
 
487
- with torch.inference_mode():
488
- image = pipe(
489
- prompt=enhanced_prompt,
490
- negative_prompt=negative_prompt,
491
- num_inference_steps=25, # Reduced for speed
492
- guidance_scale=7.5,
493
- width=512, # Reduced for memory
494
- height=512, # Reduced for memory
495
- generator=torch.Generator(device="cpu").manual_seed(scene_seed)
496
- ).images[0]
497
-
498
- if torch.cuda.is_available():
499
- torch.cuda.empty_cache()
500
 
501
  print(f"✅ Generated image for scene {scene_number}")
502
  return image
@@ -505,7 +475,7 @@ def generate_image_simple(prompt, model_choice, style, scene_number, consistency
505
  print(f"❌ Generation failed: {str(e)}")
506
  raise
507
 
508
- # LOCAL FILE MANAGEMENT FUNCTIONS
509
  def save_image_to_local(image, prompt, style="test"):
510
  """Save image to local persistent storage"""
511
  try:
@@ -661,7 +631,7 @@ def calculate_remaining_time(job_id, progress):
661
 
662
  # BACKGROUND TASK
663
  def generate_storybook_background(job_id: str):
664
- """Background task with memory optimization"""
665
  try:
666
  if HF_TOKEN:
667
  ensure_dataset_exists()
@@ -790,12 +760,7 @@ async def root():
790
  "clear_memory": "POST /api/clear-memory",
791
  "local_images": "GET /api/local-images"
792
  },
793
- "ui": "/ui",
794
- "test_commands": {
795
- "ping": "curl -X GET https://yukee1992-Video_image_generator.hf.space/ping",
796
- "health": "curl -X GET https://yukee1992-Video_image_generator.hf.space/api/health",
797
- "generate": "curl -X POST https://yukee1992-Video_image_generator.hf.space/api/generate-storybook -H 'Content-Type: application/json' -d '{\"story_title\":\"test\",\"scenes\":[{\"visual\":\"a cat\",\"text\":\"test\"}]}'"
798
- }
799
  }
800
 
801
  @app.get("/api/health")
@@ -974,10 +939,11 @@ if __name__ == "__main__":
974
  print("📡 API endpoints:")
975
  print(" - GET /ping")
976
  print(" - GET /debug")
 
977
  print(" - GET /api/health")
978
  print(" - POST /api/generate-storybook")
979
- print(" - GET /api/job-status/{{job_id}}")
980
- print(" - GET /api/project-images/{{project_id}}")
981
  print(" - GET /api/memory-status")
982
  print(" - POST /api/clear-memory")
983
  print(" - GET /api/local-images")
 
24
  from requests.adapters import HTTPAdapter
25
  from urllib3.util.retry import Retry
26
  from huggingface_hub import HfApi
 
27
  import sys
28
  import traceback
29
 
 
37
  print(f"PyTorch version: {torch.__version__}")
38
  print(f"CUDA available: {torch.cuda.is_available()}")
39
 
40
+ # Simple diagnostic endpoint that works immediately
41
  app = FastAPI(title="Storybook Generator API")
42
 
43
  @app.get("/ping")
 
46
  return {
47
  "status": "alive",
48
  "timestamp": datetime.now().isoformat(),
49
+ "message": "API is running"
50
  }
51
 
52
  @app.get("/debug")
 
72
  allow_headers=["*"],
73
  )
74
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
75
  # =============================================
76
  # HUGGING FACE DATASET CONFIGURATION
77
  # =============================================
 
139
  gpu_memory_cached_mb: Optional[float] = None
140
  status: str
141
 
142
+ # HIGH-QUALITY MODEL SELECTION - SAME AS WORKING VERSION
143
  MODEL_CHOICES = {
144
  "dreamshaper-8": "lykon/dreamshaper-8",
145
  "realistic-vision": "SG161222/Realistic_Vision_V5.1",
 
161
  model_loading = False
162
  model_load_error = None
163
 
164
+ # MEMORY MANAGEMENT FUNCTIONS - FROM WORKING VERSION
165
  def get_memory_usage():
166
  """Get current memory usage statistics"""
167
  process = psutil.Process()
 
250
  }
251
 
252
  # =============================================
253
+ # SIMPLIFIED MODEL LOADING - EXACTLY LIKE WORKING VERSION
254
  # =============================================
255
  def load_model(model_name="dreamshaper-8"):
256
+ """Thread-safe model loading - simplified like working version"""
257
  global model_cache, current_model_name, current_pipe, model_loading, model_load_error
258
 
259
  with model_lock:
 
262
  current_model_name = model_name
263
  return current_pipe
264
 
 
 
 
 
265
  model_loading = True
266
  model_load_error = None
267
 
 
269
  try:
270
  model_id = MODEL_CHOICES.get(model_name, "lykon/dreamshaper-8")
271
 
272
+ # Load model - exactly like your working version
273
  pipe = StableDiffusionPipeline.from_pretrained(
274
  model_id,
275
  torch_dtype=torch.float32,
276
  safety_checker=None,
277
  requires_safety_checker=False,
278
+ cache_dir="./model_cache"
 
 
279
  )
280
 
281
+ # Use the same scheduler as working version
282
  pipe.scheduler = EulerAncestralDiscreteScheduler.from_config(pipe.scheduler.config)
283
 
284
+ # Move to CPU - like working version
 
 
 
 
 
 
285
  pipe = pipe.to("cpu")
286
 
287
+ # NO additional optimizations - exactly like working version
288
+
289
  model_cache[model_name] = pipe
290
  current_pipe = pipe
291
  current_model_name = model_name
 
305
  "runwayml/stable-diffusion-v1-5",
306
  torch_dtype=torch.float32,
307
  safety_checker=None,
308
+ requires_safety_checker=False
 
309
  ).to("cpu")
310
 
 
 
311
  model_cache[model_name] = pipe
312
  current_pipe = pipe
313
  current_model_name = "sd-1.5"
 
413
  print(f"❌ Failed to upload image to HF Dataset: {e}")
414
  return None
415
 
416
+ # PROMPT ENGINEERING - FROM WORKING VERSION
417
  def enhance_prompt_simple(scene_visual, style="childrens_book"):
418
+ """Simple prompt enhancement - uses only the provided visual prompt with style"""
419
 
420
  style_templates = {
421
  "childrens_book": "children's book illustration, watercolor style, soft colors, whimsical, magical, storybook art, professional illustration",
 
436
  return enhanced_prompt, negative_prompt
437
 
438
  # =============================================
439
+ # IMAGE GENERATION - EXACTLY LIKE WORKING VERSION
440
  # =============================================
441
  def generate_image_simple(prompt, model_choice, style, scene_number, consistency_seed=None):
442
+ """Generate image - exactly like working version"""
443
 
444
  if current_pipe is None:
445
+ if model_loading:
446
+ raise Exception("Model is still loading. Please wait a few seconds and try again.")
447
+ else:
448
+ raise Exception(f"Model failed to load: {model_load_error}")
449
 
450
  enhanced_prompt, negative_prompt = enhance_prompt_simple(prompt, style)
451
 
 
457
  try:
458
  pipe = current_pipe
459
 
460
+ # Use full quality settings like working version
461
+ image = pipe(
462
+ prompt=enhanced_prompt,
463
+ negative_prompt=negative_prompt,
464
+ num_inference_steps=35,
465
+ guidance_scale=7.5,
466
+ width=768,
467
+ height=1024,
468
+ generator=torch.Generator(device="cpu").manual_seed(scene_seed)
469
+ ).images[0]
 
 
 
470
 
471
  print(f"✅ Generated image for scene {scene_number}")
472
  return image
 
475
  print(f"❌ Generation failed: {str(e)}")
476
  raise
477
 
478
+ # LOCAL FILE MANAGEMENT FUNCTIONS - FROM WORKING VERSION
479
  def save_image_to_local(image, prompt, style="test"):
480
  """Save image to local persistent storage"""
481
  try:
 
631
 
632
  # BACKGROUND TASK
633
  def generate_storybook_background(job_id: str):
634
+ """Background task to generate storybook"""
635
  try:
636
  if HF_TOKEN:
637
  ensure_dataset_exists()
 
760
  "clear_memory": "POST /api/clear-memory",
761
  "local_images": "GET /api/local-images"
762
  },
763
+ "ui": "/ui"
 
 
 
 
 
764
  }
765
 
766
  @app.get("/api/health")
 
939
  print("📡 API endpoints:")
940
  print(" - GET /ping")
941
  print(" - GET /debug")
942
+ print(" - GET /")
943
  print(" - GET /api/health")
944
  print(" - POST /api/generate-storybook")
945
+ print(" - GET /api/job-status/{job_id}")
946
+ print(" - GET /api/project-images/{project_id}")
947
  print(" - GET /api/memory-status")
948
  print(" - POST /api/clear-memory")
949
  print(" - GET /api/local-images")