Spaces:
Build error
Build error
Update app.py
Browse files
app.py
CHANGED
|
@@ -23,6 +23,9 @@ import random
|
|
| 23 |
# External OCI API URL
|
| 24 |
OCI_API_BASE_URL = "https://yukee1992-oci-story-book.hf.space"
|
| 25 |
|
|
|
|
|
|
|
|
|
|
| 26 |
# Initialize FastAPI app
|
| 27 |
app = FastAPI(title="Storybook Generator API")
|
| 28 |
|
|
@@ -81,7 +84,7 @@ class JobStatusResponse(BaseModel):
|
|
| 81 |
created_at: float
|
| 82 |
updated_at: float
|
| 83 |
|
| 84 |
-
# HIGH-QUALITY MODEL SELECTION
|
| 85 |
MODEL_CHOICES = {
|
| 86 |
"dreamshaper-8": "lykon/dreamshaper-8", # Excellent for fantasy/artistic
|
| 87 |
"realistic-vision": "SG161222/Realistic_Vision_V5.1", # Photorealistic
|
|
@@ -127,7 +130,7 @@ def load_model(model_name="dreamshaper-8"):
|
|
| 127 |
try:
|
| 128 |
model_id = MODEL_CHOICES.get(model_name, "lykon/dreamshaper-8")
|
| 129 |
|
| 130 |
-
# HIGH-QUALITY LOADING
|
| 131 |
pipe = StableDiffusionPipeline.from_pretrained(
|
| 132 |
model_id,
|
| 133 |
torch_dtype=torch.float32,
|
|
@@ -161,7 +164,7 @@ print("π Initializing HIGH-QUALITY Storybook Generator...")
|
|
| 161 |
load_model("dreamshaper-8")
|
| 162 |
print("β
HIGH-QUALITY Model loaded and ready!")
|
| 163 |
|
| 164 |
-
# PROFESSIONAL PROMPT ENGINEERING
|
| 165 |
def enhance_prompt(prompt, style="childrens_book"):
|
| 166 |
"""Transform basic prompts into professional-grade prompts"""
|
| 167 |
|
|
@@ -309,6 +312,54 @@ def save_to_oci_via_api(image, prompt, story_title, page_number):
|
|
| 309 |
except Exception as e:
|
| 310 |
raise Exception(f"API upload failed: {str(e)}")
|
| 311 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 312 |
# JOB MANAGEMENT FUNCTIONS
|
| 313 |
def create_job(story_request: StorybookRequest) -> str:
|
| 314 |
"""Create a new job and return job ID"""
|
|
@@ -523,48 +574,10 @@ async def list_jobs():
|
|
| 523 |
}
|
| 524 |
}
|
| 525 |
|
| 526 |
-
#
|
| 527 |
def create_test_interface():
|
| 528 |
-
"""Create
|
| 529 |
|
| 530 |
-
def generate_test_image(prompt, model_choice, style_choice):
|
| 531 |
-
"""Generate a single image for testing"""
|
| 532 |
-
try:
|
| 533 |
-
if not prompt.strip():
|
| 534 |
-
return None, "β Please enter a prompt"
|
| 535 |
-
|
| 536 |
-
print(f"π¨ Generating test image with prompt: {prompt}")
|
| 537 |
-
|
| 538 |
-
# Enhance the prompt
|
| 539 |
-
enhanced_prompt, negative_prompt = enhance_prompt(prompt, style_choice)
|
| 540 |
-
|
| 541 |
-
# Generate the image
|
| 542 |
-
image = generate_high_quality_image(
|
| 543 |
-
enhanced_prompt,
|
| 544 |
-
model_choice,
|
| 545 |
-
style_choice,
|
| 546 |
-
negative_prompt
|
| 547 |
-
)
|
| 548 |
-
|
| 549 |
-
# Create a simple save (optional)
|
| 550 |
-
try:
|
| 551 |
-
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
| 552 |
-
safe_prompt = "".join(c for c in prompt[:20] if c.isalnum() or c in (' ', '-', '_')).rstrip()
|
| 553 |
-
filename = f"test_{safe_prompt}_{timestamp}.png"
|
| 554 |
-
image.save(f"/tmp/{filename}")
|
| 555 |
-
print(f"πΎ Test image saved as: {filename}")
|
| 556 |
-
except Exception as e:
|
| 557 |
-
print(f"β οΈ Could not save test image: {e}")
|
| 558 |
-
|
| 559 |
-
status_msg = f"β
Success! Generated: {prompt}\n\nEnhanced prompt: {enhanced_prompt}"
|
| 560 |
-
return image, status_msg
|
| 561 |
-
|
| 562 |
-
except Exception as e:
|
| 563 |
-
error_msg = f"β Generation failed: {str(e)}"
|
| 564 |
-
print(error_msg)
|
| 565 |
-
return None, error_msg
|
| 566 |
-
|
| 567 |
-
# Create the interface
|
| 568 |
with gr.Blocks(title="High-Quality Image Generator", theme="soft") as demo:
|
| 569 |
gr.Markdown("# π¨ High-Quality Image Generator")
|
| 570 |
gr.Markdown("Test your prompts with **studio-quality** image generation")
|
|
@@ -661,14 +674,17 @@ gradio_app = create_test_interface()
|
|
| 661 |
# Mount Gradio interface to FastAPI
|
| 662 |
@app.get("/")
|
| 663 |
async def root():
|
| 664 |
-
return {"message": "Storybook Generator API is running! Visit
|
| 665 |
|
| 666 |
-
@app.get("/
|
| 667 |
-
async def
|
| 668 |
-
"""
|
| 669 |
-
|
| 670 |
-
|
| 671 |
-
|
|
|
|
|
|
|
|
|
|
| 672 |
|
| 673 |
# For Hugging Face Spaces deployment
|
| 674 |
def get_app():
|
|
@@ -681,6 +697,7 @@ if __name__ == "__main__":
|
|
| 681 |
print("π¨ Available models:")
|
| 682 |
for model in MODEL_CHOICES:
|
| 683 |
print(f" - {model}")
|
|
|
|
| 684 |
print("π Web interface available at: http://localhost:7860")
|
| 685 |
print("π API endpoints available at: http://localhost:7860/api/")
|
| 686 |
|
|
|
|
| 23 |
# External OCI API URL
|
| 24 |
OCI_API_BASE_URL = "https://yukee1992-oci-story-book.hf.space"
|
| 25 |
|
| 26 |
+
# Create images directory if it doesn't exist
|
| 27 |
+
os.makedirs("generated_test_images", exist_ok=True)
|
| 28 |
+
|
| 29 |
# Initialize FastAPI app
|
| 30 |
app = FastAPI(title="Storybook Generator API")
|
| 31 |
|
|
|
|
| 84 |
created_at: float
|
| 85 |
updated_at: float
|
| 86 |
|
| 87 |
+
# HIGH-QUALITY MODEL SELECTION
|
| 88 |
MODEL_CHOICES = {
|
| 89 |
"dreamshaper-8": "lykon/dreamshaper-8", # Excellent for fantasy/artistic
|
| 90 |
"realistic-vision": "SG161222/Realistic_Vision_V5.1", # Photorealistic
|
|
|
|
| 130 |
try:
|
| 131 |
model_id = MODEL_CHOICES.get(model_name, "lykon/dreamshaper-8")
|
| 132 |
|
| 133 |
+
# HIGH-QUALITY LOADING
|
| 134 |
pipe = StableDiffusionPipeline.from_pretrained(
|
| 135 |
model_id,
|
| 136 |
torch_dtype=torch.float32,
|
|
|
|
| 164 |
load_model("dreamshaper-8")
|
| 165 |
print("β
HIGH-QUALITY Model loaded and ready!")
|
| 166 |
|
| 167 |
+
# PROFESSIONAL PROMPT ENGINEERING
|
| 168 |
def enhance_prompt(prompt, style="childrens_book"):
|
| 169 |
"""Transform basic prompts into professional-grade prompts"""
|
| 170 |
|
|
|
|
| 312 |
except Exception as e:
|
| 313 |
raise Exception(f"API upload failed: {str(e)}")
|
| 314 |
|
| 315 |
+
def generate_test_image(prompt, model_choice, style_choice):
|
| 316 |
+
"""Generate a single image for testing with better file management"""
|
| 317 |
+
try:
|
| 318 |
+
if not prompt.strip():
|
| 319 |
+
return None, "β Please enter a prompt"
|
| 320 |
+
|
| 321 |
+
print(f"π¨ Generating test image with prompt: {prompt}")
|
| 322 |
+
|
| 323 |
+
# Enhance the prompt
|
| 324 |
+
enhanced_prompt, negative_prompt = enhance_prompt(prompt, style_choice)
|
| 325 |
+
|
| 326 |
+
# Generate the image
|
| 327 |
+
image = generate_high_quality_image(
|
| 328 |
+
enhanced_prompt,
|
| 329 |
+
model_choice,
|
| 330 |
+
style_choice,
|
| 331 |
+
negative_prompt
|
| 332 |
+
)
|
| 333 |
+
|
| 334 |
+
# Save to accessible location
|
| 335 |
+
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
| 336 |
+
safe_prompt = "".join(c for c in prompt[:30] if c.isalnum() or c in (' ', '-', '_')).rstrip()
|
| 337 |
+
filename = f"test_{safe_prompt}_{timestamp}.png"
|
| 338 |
+
filepath = f"generated_test_images/{filename}"
|
| 339 |
+
|
| 340 |
+
try:
|
| 341 |
+
image.save(filepath)
|
| 342 |
+
save_info = f"πΎ Saved to: {filepath}"
|
| 343 |
+
print(f"β
Image saved: {filepath}")
|
| 344 |
+
except Exception as e:
|
| 345 |
+
save_info = f"β οΈ Could not save to disk: {e}"
|
| 346 |
+
print(f"β οΈ Save failed: {e}")
|
| 347 |
+
|
| 348 |
+
status_msg = f"""β
Success! Generated: {prompt}
|
| 349 |
+
|
| 350 |
+
{save_info}
|
| 351 |
+
|
| 352 |
+
π¨ Enhanced prompt: {enhanced_prompt}
|
| 353 |
+
|
| 354 |
+
π₯ Use the download button below the image to save it!"""
|
| 355 |
+
|
| 356 |
+
return image, status_msg
|
| 357 |
+
|
| 358 |
+
except Exception as e:
|
| 359 |
+
error_msg = f"β Generation failed: {str(e)}"
|
| 360 |
+
print(error_msg)
|
| 361 |
+
return None, error_msg
|
| 362 |
+
|
| 363 |
# JOB MANAGEMENT FUNCTIONS
|
| 364 |
def create_job(story_request: StorybookRequest) -> str:
|
| 365 |
"""Create a new job and return job ID"""
|
|
|
|
| 574 |
}
|
| 575 |
}
|
| 576 |
|
| 577 |
+
# GRADIO INTERFACE FOR TESTING
|
| 578 |
def create_test_interface():
|
| 579 |
+
"""Create Gradio interface for testing image generation"""
|
| 580 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 581 |
with gr.Blocks(title="High-Quality Image Generator", theme="soft") as demo:
|
| 582 |
gr.Markdown("# π¨ High-Quality Image Generator")
|
| 583 |
gr.Markdown("Test your prompts with **studio-quality** image generation")
|
|
|
|
| 674 |
# Mount Gradio interface to FastAPI
|
| 675 |
@app.get("/")
|
| 676 |
async def root():
|
| 677 |
+
return {"message": "Storybook Generator API is running! Visit the main URL for the testing interface."}
|
| 678 |
|
| 679 |
+
@app.get("/health")
|
| 680 |
+
async def health_check():
|
| 681 |
+
"""Health check endpoint"""
|
| 682 |
+
return {
|
| 683 |
+
"status": "healthy",
|
| 684 |
+
"models_loaded": list(model_cache.keys()),
|
| 685 |
+
"active_jobs": len(job_storage),
|
| 686 |
+
"memory_usage_mb": monitor_memory()
|
| 687 |
+
}
|
| 688 |
|
| 689 |
# For Hugging Face Spaces deployment
|
| 690 |
def get_app():
|
|
|
|
| 697 |
print("π¨ Available models:")
|
| 698 |
for model in MODEL_CHOICES:
|
| 699 |
print(f" - {model}")
|
| 700 |
+
print("π Images will be saved to: generated_test_images/")
|
| 701 |
print("π Web interface available at: http://localhost:7860")
|
| 702 |
print("π API endpoints available at: http://localhost:7860/api/")
|
| 703 |
|