Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -19,6 +19,9 @@ import uuid
|
|
| 19 |
import hashlib
|
| 20 |
from enum import Enum
|
| 21 |
import random
|
|
|
|
|
|
|
|
|
|
| 22 |
|
| 23 |
# External OCI API URL - YOUR BUCKET SAVING API
|
| 24 |
OCI_API_BASE_URL = "https://yukee1992-oci-story-book.hf.space"
|
|
@@ -490,7 +493,7 @@ def refresh_local_images():
|
|
| 490 |
|
| 491 |
# OCI BUCKET FUNCTIONS
|
| 492 |
def save_to_oci_bucket(image, text_content, story_title, page_number, file_type="image"):
|
| 493 |
-
"""Save both images and text to OCI bucket via your OCI API"""
|
| 494 |
try:
|
| 495 |
if file_type == "image":
|
| 496 |
# Convert image to bytes
|
|
@@ -513,7 +516,20 @@ def save_to_oci_bucket(image, text_content, story_title, page_number, file_type=
|
|
| 513 |
'subfolder': f'stories/{story_title}'
|
| 514 |
}
|
| 515 |
|
| 516 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 517 |
|
| 518 |
print(f"π¨ OCI API Response: {response.status_code}")
|
| 519 |
|
|
@@ -708,37 +724,64 @@ def generate_storybook_background(job_id: str):
|
|
| 708 |
story_request.consistency_seed
|
| 709 |
)
|
| 710 |
|
| 711 |
-
#
|
| 712 |
-
|
| 713 |
-
|
| 714 |
-
"", # No text for image
|
| 715 |
-
story_request.story_title,
|
| 716 |
-
i + 1,
|
| 717 |
-
"image"
|
| 718 |
-
)
|
| 719 |
-
|
| 720 |
-
# Save TEXT to OCI bucket
|
| 721 |
-
text_url = save_to_oci_bucket(
|
| 722 |
-
None, # No image for text
|
| 723 |
-
scene.text,
|
| 724 |
-
story_request.story_title,
|
| 725 |
-
i + 1,
|
| 726 |
-
"text"
|
| 727 |
-
)
|
| 728 |
-
|
| 729 |
-
# Store page data
|
| 730 |
-
page_data = {
|
| 731 |
-
"page_number": i + 1,
|
| 732 |
-
"image_url": image_url,
|
| 733 |
-
"text_url": text_url,
|
| 734 |
-
"text_content": scene.text,
|
| 735 |
-
"visual_description": scene.visual,
|
| 736 |
-
"characters_present": characters_present,
|
| 737 |
-
"prompt_used": f"Dynamic consistent generation with {len(characters_present)} characters"
|
| 738 |
-
}
|
| 739 |
-
generated_pages.append(page_data)
|
| 740 |
|
| 741 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 742 |
|
| 743 |
except Exception as e:
|
| 744 |
error_msg = f"Failed to generate page {i+1}: {str(e)}"
|
|
@@ -749,6 +792,10 @@ def generate_storybook_background(job_id: str):
|
|
| 749 |
# Complete the job
|
| 750 |
generation_time = time.time() - start_time
|
| 751 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 752 |
result = {
|
| 753 |
"story_title": story_request.story_title,
|
| 754 |
"total_pages": total_scenes,
|
|
@@ -763,19 +810,28 @@ def generate_storybook_background(job_id: str):
|
|
| 763 |
"file_structure": {
|
| 764 |
"images": [f"page_{i+1:03d}.png" for i in range(total_scenes)],
|
| 765 |
"texts": [f"page_{i+1:03d}.txt" for i in range(total_scenes)]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 766 |
}
|
| 767 |
}
|
| 768 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 769 |
update_job_status(
|
| 770 |
job_id,
|
| 771 |
JobStatus.COMPLETED,
|
| 772 |
100,
|
| 773 |
-
|
| 774 |
result
|
| 775 |
)
|
| 776 |
|
| 777 |
print(f"π DYNAMIC Storybook generation finished for job {job_id}")
|
| 778 |
-
print(f"π
|
| 779 |
print(f"π₯ Dynamic character consistency maintained for {len(story_request.characters)} characters across {total_scenes} scenes")
|
| 780 |
|
| 781 |
except Exception as e:
|
|
|
|
| 19 |
import hashlib
|
| 20 |
from enum import Enum
|
| 21 |
import random
|
| 22 |
+
import time
|
| 23 |
+
from requests.adapters import HTTPAdapter
|
| 24 |
+
from urllib3.util.retry import Retry
|
| 25 |
|
| 26 |
# External OCI API URL - YOUR BUCKET SAVING API
|
| 27 |
OCI_API_BASE_URL = "https://yukee1992-oci-story-book.hf.space"
|
|
|
|
| 493 |
|
| 494 |
# OCI BUCKET FUNCTIONS
|
| 495 |
def save_to_oci_bucket(image, text_content, story_title, page_number, file_type="image"):
|
| 496 |
+
"""Save both images and text to OCI bucket via your OCI API with retry logic"""
|
| 497 |
try:
|
| 498 |
if file_type == "image":
|
| 499 |
# Convert image to bytes
|
|
|
|
| 516 |
'subfolder': f'stories/{story_title}'
|
| 517 |
}
|
| 518 |
|
| 519 |
+
# Create session with retry strategy
|
| 520 |
+
session = requests.Session()
|
| 521 |
+
retry_strategy = Retry(
|
| 522 |
+
total=3, # Retry 3 times
|
| 523 |
+
status_forcelist=[429, 500, 502, 503, 504], # Retry on these status codes
|
| 524 |
+
method_whitelist=["POST"], # Only retry on POST requests
|
| 525 |
+
backoff_factor=1 # Wait 1, 2, 4 seconds between retries
|
| 526 |
+
)
|
| 527 |
+
adapter = HTTPAdapter(max_retries=retry_strategy)
|
| 528 |
+
session.mount("http://", adapter)
|
| 529 |
+
session.mount("https://", adapter)
|
| 530 |
+
|
| 531 |
+
# INCREASED TIMEOUT WITH RETRY LOGIC
|
| 532 |
+
response = session.post(api_url, files=files, data=data, timeout=60)
|
| 533 |
|
| 534 |
print(f"π¨ OCI API Response: {response.status_code}")
|
| 535 |
|
|
|
|
| 724 |
story_request.consistency_seed
|
| 725 |
)
|
| 726 |
|
| 727 |
+
# ADD LOCAL FALLBACK SAVE
|
| 728 |
+
local_filepath, local_filename = save_image_to_local(image, scene.visual, story_request.style)
|
| 729 |
+
print(f"πΎ Image saved locally as backup: {local_filename}")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 730 |
|
| 731 |
+
try:
|
| 732 |
+
# Save IMAGE to OCI bucket
|
| 733 |
+
image_url = save_to_oci_bucket(
|
| 734 |
+
image,
|
| 735 |
+
"", # No text for image
|
| 736 |
+
story_request.story_title,
|
| 737 |
+
i + 1,
|
| 738 |
+
"image"
|
| 739 |
+
)
|
| 740 |
+
|
| 741 |
+
# Save TEXT to OCI bucket
|
| 742 |
+
text_url = save_to_oci_bucket(
|
| 743 |
+
None, # No image for text
|
| 744 |
+
scene.text,
|
| 745 |
+
story_request.story_title,
|
| 746 |
+
i + 1,
|
| 747 |
+
"text"
|
| 748 |
+
)
|
| 749 |
+
|
| 750 |
+
# Store page data
|
| 751 |
+
page_data = {
|
| 752 |
+
"page_number": i + 1,
|
| 753 |
+
"image_url": image_url,
|
| 754 |
+
"text_url": text_url,
|
| 755 |
+
"text_content": scene.text,
|
| 756 |
+
"visual_description": scene.visual,
|
| 757 |
+
"characters_present": characters_present,
|
| 758 |
+
"prompt_used": f"Dynamic consistent generation with {len(characters_present)} characters",
|
| 759 |
+
"local_backup_path": local_filepath # Store local path as backup
|
| 760 |
+
}
|
| 761 |
+
generated_pages.append(page_data)
|
| 762 |
+
|
| 763 |
+
print(f"β
Page {i+1} completed - Characters: {characters_present}")
|
| 764 |
+
|
| 765 |
+
except Exception as upload_error:
|
| 766 |
+
# If OCI upload fails, use local file as fallback
|
| 767 |
+
error_msg = f"OCI upload failed for page {i+1}, using local backup: {str(upload_error)}"
|
| 768 |
+
print(f"β οΈ {error_msg}")
|
| 769 |
+
|
| 770 |
+
page_data = {
|
| 771 |
+
"page_number": i + 1,
|
| 772 |
+
"image_url": f"local://{local_filepath}", # Mark as local file
|
| 773 |
+
"text_url": f"local://text_content_{i+1}",
|
| 774 |
+
"text_content": scene.text,
|
| 775 |
+
"visual_description": scene.visual,
|
| 776 |
+
"characters_present": characters_present,
|
| 777 |
+
"prompt_used": f"Dynamic consistent generation with {len(characters_present)} characters",
|
| 778 |
+
"local_backup_path": local_filepath,
|
| 779 |
+
"upload_error": str(upload_error)
|
| 780 |
+
}
|
| 781 |
+
generated_pages.append(page_data)
|
| 782 |
+
|
| 783 |
+
# Continue with next page instead of failing completely
|
| 784 |
+
continue
|
| 785 |
|
| 786 |
except Exception as e:
|
| 787 |
error_msg = f"Failed to generate page {i+1}: {str(e)}"
|
|
|
|
| 792 |
# Complete the job
|
| 793 |
generation_time = time.time() - start_time
|
| 794 |
|
| 795 |
+
# Count successful OCI uploads vs local fallbacks
|
| 796 |
+
oci_success_count = sum(1 for page in generated_pages if not page.get("upload_error"))
|
| 797 |
+
local_fallback_count = sum(1 for page in generated_pages if page.get("upload_error"))
|
| 798 |
+
|
| 799 |
result = {
|
| 800 |
"story_title": story_request.story_title,
|
| 801 |
"total_pages": total_scenes,
|
|
|
|
| 810 |
"file_structure": {
|
| 811 |
"images": [f"page_{i+1:03d}.png" for i in range(total_scenes)],
|
| 812 |
"texts": [f"page_{i+1:03d}.txt" for i in range(total_scenes)]
|
| 813 |
+
},
|
| 814 |
+
"upload_summary": {
|
| 815 |
+
"oci_successful": oci_success_count,
|
| 816 |
+
"local_fallback": local_fallback_count,
|
| 817 |
+
"total_attempted": total_scenes
|
| 818 |
}
|
| 819 |
}
|
| 820 |
|
| 821 |
+
status_message = f"π Storybook completed! {len(generated_pages)} pages with {len(story_request.characters)} dynamic characters created in {generation_time:.2f}s."
|
| 822 |
+
if local_fallback_count > 0:
|
| 823 |
+
status_message += f" {local_fallback_count} pages saved locally due to OCI upload issues."
|
| 824 |
+
|
| 825 |
update_job_status(
|
| 826 |
job_id,
|
| 827 |
JobStatus.COMPLETED,
|
| 828 |
100,
|
| 829 |
+
status_message,
|
| 830 |
result
|
| 831 |
)
|
| 832 |
|
| 833 |
print(f"π DYNAMIC Storybook generation finished for job {job_id}")
|
| 834 |
+
print(f"π OCI Uploads: {oci_success_count} successful, {local_fallback_count} local fallbacks")
|
| 835 |
print(f"π₯ Dynamic character consistency maintained for {len(story_request.characters)} characters across {total_scenes} scenes")
|
| 836 |
|
| 837 |
except Exception as e:
|