Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -9,6 +9,10 @@ from datetime import datetime
|
|
| 9 |
import re
|
| 10 |
import tempfile
|
| 11 |
import time
|
|
|
|
|
|
|
|
|
|
|
|
|
| 12 |
|
| 13 |
# Try to import your existing OCI connector for direct access
|
| 14 |
try:
|
|
@@ -17,7 +21,7 @@ try:
|
|
| 17 |
print("β
Direct OCI access available - using existing OCI connector")
|
| 18 |
except ImportError:
|
| 19 |
DIRECT_OCI_ACCESS = False
|
| 20 |
-
print("β οΈ Direct OCI access not available - using API endpoint")
|
| 21 |
|
| 22 |
# Initialize the Stable Diffusion model
|
| 23 |
def load_model():
|
|
@@ -109,31 +113,22 @@ def save_to_oci_direct(image, prompt):
|
|
| 109 |
return f"β Direct upload failed: {str(e)}"
|
| 110 |
|
| 111 |
def save_to_oci_via_api(image, prompt):
|
| 112 |
-
"""Save image using the OCI API endpoint
|
| 113 |
try:
|
| 114 |
# Convert image to bytes
|
| 115 |
img_bytes = io.BytesIO()
|
| 116 |
image.save(img_bytes, format='PNG')
|
| 117 |
img_data = img_bytes.getvalue()
|
| 118 |
-
img_bytes.seek(0)
|
| 119 |
|
| 120 |
# Create filename
|
| 121 |
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
| 122 |
safe_prompt = "".join(c for c in prompt[:30] if c.isalnum() or c in (' ', '-', '_')).rstrip()
|
| 123 |
filename = f"story_{timestamp}_{safe_prompt}.png"
|
| 124 |
|
| 125 |
-
# Use
|
| 126 |
-
api_url = "/api/upload"
|
| 127 |
-
|
| 128 |
-
# For Hugging Face deployment, use absolute URL if needed
|
| 129 |
-
try:
|
| 130 |
-
space_name = os.environ.get('SPACE_NAME', 'yukee1992-oci-story-book')
|
| 131 |
-
if 'HF_SPACE_ID' in os.environ:
|
| 132 |
-
api_url = f"https://{space_name}.hf.space/api/upload"
|
| 133 |
-
except:
|
| 134 |
-
pass
|
| 135 |
|
| 136 |
-
print(f"π Calling OCI API: {api_url}")
|
| 137 |
|
| 138 |
# Prepare form data for API request
|
| 139 |
files = {
|
|
@@ -149,14 +144,62 @@ def save_to_oci_via_api(image, prompt):
|
|
| 149 |
response = requests.post(api_url, files=files, data=data, timeout=30)
|
| 150 |
|
| 151 |
print(f"π¨ API Response: {response.status_code}")
|
|
|
|
|
|
|
| 152 |
|
| 153 |
if response.status_code == 200:
|
| 154 |
result = response.json()
|
| 155 |
if result['status'] == 'success':
|
| 156 |
-
|
| 157 |
-
|
| 158 |
-
|
| 159 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 160 |
else:
|
| 161 |
return f"β API Error: {result.get('message', 'Unknown error')}"
|
| 162 |
else:
|
|
@@ -175,7 +218,13 @@ def save_to_oci(image, prompt):
|
|
| 175 |
if DIRECT_OCI_ACCESS:
|
| 176 |
return save_to_oci_direct(image, prompt)
|
| 177 |
else:
|
| 178 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 179 |
|
| 180 |
def generate_storybook_image(prompt):
|
| 181 |
"""Generate an image from text prompt and save to OCI"""
|
|
@@ -213,6 +262,42 @@ def generate_storybook_image(prompt):
|
|
| 213 |
print(f"Traceback: {traceback.format_exc()}")
|
| 214 |
return None, error_msg
|
| 215 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 216 |
# Create the Gradio interface
|
| 217 |
with gr.Blocks(title="Children's Book Illustrator", theme="soft") as demo:
|
| 218 |
gr.Markdown("# π Children's Book Illustrator")
|
|
@@ -233,44 +318,16 @@ with gr.Blocks(title="Children's Book Illustrator", theme="soft") as demo:
|
|
| 233 |
|
| 234 |
# Debug section
|
| 235 |
with gr.Accordion("π§ Debug Information", open=False):
|
| 236 |
-
gr.Markdown("""
|
| 237 |
**Current Configuration:**
|
| 238 |
-
- OCI Access: **{
|
|
|
|
| 239 |
- Model: Stable Diffusion v1.5
|
| 240 |
- Storage Path: `storybook-generator/childrens-books/`
|
| 241 |
-
"""
|
| 242 |
|
| 243 |
debug_btn = gr.Button("π Check OCI Connection", variant="secondary")
|
| 244 |
-
debug_output = gr.Textbox(label="Debug Info", interactive=False, lines=
|
| 245 |
-
|
| 246 |
-
def check_oci_connection():
|
| 247 |
-
"""Check OCI connection status"""
|
| 248 |
-
try:
|
| 249 |
-
if DIRECT_OCI_ACCESS:
|
| 250 |
-
# Test direct OCI connection
|
| 251 |
-
namespace = oci_connector.config.get('namespace', 'Not set')
|
| 252 |
-
bucket = oci_connector.config.get('bucket_name', 'Not set')
|
| 253 |
-
client_status = "β
Connected" if oci_connector.client else "β Disconnected"
|
| 254 |
-
|
| 255 |
-
return f"""**Direct OCI Connection:**
|
| 256 |
-
- Client: {client_status}
|
| 257 |
-
- Namespace: {namespace}
|
| 258 |
-
- Bucket: {bucket}
|
| 259 |
-
- Initialization Error: {oci_connector.initialization_error or 'None'}"""
|
| 260 |
-
else:
|
| 261 |
-
# Test API connection
|
| 262 |
-
try:
|
| 263 |
-
api_url = "/api/health"
|
| 264 |
-
response = requests.get(api_url, timeout=10)
|
| 265 |
-
if response.status_code == 200:
|
| 266 |
-
return "β
API Connection: Healthy"
|
| 267 |
-
else:
|
| 268 |
-
return f"β API Connection: HTTP {response.status_code}"
|
| 269 |
-
except Exception as e:
|
| 270 |
-
return f"β API Connection: {str(e)}"
|
| 271 |
-
|
| 272 |
-
except Exception as e:
|
| 273 |
-
return f"β Connection check failed: {str(e)}"
|
| 274 |
|
| 275 |
# Connect buttons to functions
|
| 276 |
generate_btn.click(
|
|
@@ -291,5 +348,6 @@ def get_app():
|
|
| 291 |
|
| 292 |
if __name__ == "__main__":
|
| 293 |
print("π Starting Children's Book Illustrator...")
|
| 294 |
-
print(f"π¦ OCI Access: {'Direct' if DIRECT_OCI_ACCESS else 'API'}")
|
|
|
|
| 295 |
demo.launch(server_name="0.0.0.0", server_port=7860)
|
|
|
|
| 9 |
import re
|
| 10 |
import tempfile
|
| 11 |
import time
|
| 12 |
+
import base64
|
| 13 |
+
|
| 14 |
+
# External OCI API URL - THIS IS THE KEY FIX
|
| 15 |
+
OCI_API_BASE_URL = "https://yukee1992-oci-video-storage.hf.space"
|
| 16 |
|
| 17 |
# Try to import your existing OCI connector for direct access
|
| 18 |
try:
|
|
|
|
| 21 |
print("β
Direct OCI access available - using existing OCI connector")
|
| 22 |
except ImportError:
|
| 23 |
DIRECT_OCI_ACCESS = False
|
| 24 |
+
print("β οΈ Direct OCI access not available - using external API endpoint")
|
| 25 |
|
| 26 |
# Initialize the Stable Diffusion model
|
| 27 |
def load_model():
|
|
|
|
| 113 |
return f"β Direct upload failed: {str(e)}"
|
| 114 |
|
| 115 |
def save_to_oci_via_api(image, prompt):
|
| 116 |
+
"""Save image using the EXTERNAL OCI API endpoint"""
|
| 117 |
try:
|
| 118 |
# Convert image to bytes
|
| 119 |
img_bytes = io.BytesIO()
|
| 120 |
image.save(img_bytes, format='PNG')
|
| 121 |
img_data = img_bytes.getvalue()
|
|
|
|
| 122 |
|
| 123 |
# Create filename
|
| 124 |
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
| 125 |
safe_prompt = "".join(c for c in prompt[:30] if c.isalnum() or c in (' ', '-', '_')).rstrip()
|
| 126 |
filename = f"story_{timestamp}_{safe_prompt}.png"
|
| 127 |
|
| 128 |
+
# Use the EXTERNAL API URL - THIS IS THE FIX
|
| 129 |
+
api_url = f"{OCI_API_BASE_URL}/api/upload"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 130 |
|
| 131 |
+
print(f"π Calling EXTERNAL OCI API: {api_url}")
|
| 132 |
|
| 133 |
# Prepare form data for API request
|
| 134 |
files = {
|
|
|
|
| 144 |
response = requests.post(api_url, files=files, data=data, timeout=30)
|
| 145 |
|
| 146 |
print(f"π¨ API Response: {response.status_code}")
|
| 147 |
+
if response.text:
|
| 148 |
+
print(f"π¨ API Response Text: {response.text[:200]}...")
|
| 149 |
|
| 150 |
if response.status_code == 200:
|
| 151 |
result = response.json()
|
| 152 |
if result['status'] == 'success':
|
| 153 |
+
return f"β
{result['message']}"
|
| 154 |
+
else:
|
| 155 |
+
return f"β API Error: {result.get('message', 'Unknown error')}"
|
| 156 |
+
else:
|
| 157 |
+
return f"β HTTP Error: {response.status_code} - {response.text}"
|
| 158 |
+
|
| 159 |
+
except requests.exceptions.Timeout:
|
| 160 |
+
return "β API call timed out (30s)"
|
| 161 |
+
except requests.exceptions.ConnectionError:
|
| 162 |
+
return "β Cannot connect to OCI API"
|
| 163 |
+
except Exception as e:
|
| 164 |
+
return f"β API upload failed: {str(e)}"
|
| 165 |
+
|
| 166 |
+
def save_to_oci_via_api_text(image, prompt):
|
| 167 |
+
"""Alternative: Save image using the external OCI API text endpoint"""
|
| 168 |
+
try:
|
| 169 |
+
# Convert image to base64
|
| 170 |
+
img_bytes = io.BytesIO()
|
| 171 |
+
image.save(img_bytes, format='PNG')
|
| 172 |
+
img_base64 = base64.b64encode(img_bytes.getvalue()).decode('utf-8')
|
| 173 |
+
|
| 174 |
+
# Create filename
|
| 175 |
+
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
| 176 |
+
safe_prompt = "".join(c for c in prompt[:30] if c.isalnum() or c in (' ', '-', '_')).rstrip()
|
| 177 |
+
filename = f"story_{timestamp}_{safe_prompt}.png"
|
| 178 |
+
|
| 179 |
+
# Use the EXTERNAL API text endpoint
|
| 180 |
+
api_url = f"{OCI_API_BASE_URL}/api/upload-text"
|
| 181 |
+
|
| 182 |
+
print(f"π Calling EXTERNAL OCI API (text): {api_url}")
|
| 183 |
+
|
| 184 |
+
# Prepare data for text endpoint
|
| 185 |
+
data = {
|
| 186 |
+
'project_id': 'storybook-generator',
|
| 187 |
+
'subfolder': 'childrens-books',
|
| 188 |
+
'filename': filename,
|
| 189 |
+
'content': img_base64 # Base64 encoded image
|
| 190 |
+
}
|
| 191 |
+
|
| 192 |
+
# Make the API request with timeout
|
| 193 |
+
response = requests.post(api_url, data=data, timeout=30)
|
| 194 |
+
|
| 195 |
+
print(f"π¨ API Response: {response.status_code}")
|
| 196 |
+
if response.text:
|
| 197 |
+
print(f"π¨ API Response Text: {response.text[:200]}...")
|
| 198 |
+
|
| 199 |
+
if response.status_code == 200:
|
| 200 |
+
result = response.json()
|
| 201 |
+
if result['status'] == 'success':
|
| 202 |
+
return f"β
{result['message']}"
|
| 203 |
else:
|
| 204 |
return f"β API Error: {result.get('message', 'Unknown error')}"
|
| 205 |
else:
|
|
|
|
| 218 |
if DIRECT_OCI_ACCESS:
|
| 219 |
return save_to_oci_direct(image, prompt)
|
| 220 |
else:
|
| 221 |
+
# Try regular upload first, fallback to text upload if needed
|
| 222 |
+
result = save_to_oci_via_api(image, prompt)
|
| 223 |
+
if "β" in result and "upload-text" not in result:
|
| 224 |
+
# If regular upload fails, try text endpoint
|
| 225 |
+
print("π Regular upload failed, trying text endpoint...")
|
| 226 |
+
return save_to_oci_via_api_text(image, prompt)
|
| 227 |
+
return result
|
| 228 |
|
| 229 |
def generate_storybook_image(prompt):
|
| 230 |
"""Generate an image from text prompt and save to OCI"""
|
|
|
|
| 262 |
print(f"Traceback: {traceback.format_exc()}")
|
| 263 |
return None, error_msg
|
| 264 |
|
| 265 |
+
def check_oci_connection():
|
| 266 |
+
"""Check OCI connection status"""
|
| 267 |
+
try:
|
| 268 |
+
if DIRECT_OCI_ACCESS:
|
| 269 |
+
# Test direct OCI connection
|
| 270 |
+
namespace = oci_connector.config.get('namespace', 'Not set')
|
| 271 |
+
bucket = oci_connector.config.get('bucket_name', 'Not set')
|
| 272 |
+
client_status = "β
Connected" if oci_connector.client else "β Disconnected"
|
| 273 |
+
|
| 274 |
+
return f"""**Direct OCI Connection:**
|
| 275 |
+
- Client: {client_status}
|
| 276 |
+
- Namespace: {namespace}
|
| 277 |
+
- Bucket: {bucket}
|
| 278 |
+
- Initialization Error: {oci_connector.initialization_error or 'None'}"""
|
| 279 |
+
else:
|
| 280 |
+
# Test EXTERNAL API connection
|
| 281 |
+
try:
|
| 282 |
+
api_url = f"{OCI_API_BASE_URL}/api/health"
|
| 283 |
+
print(f"π Testing EXTERNAL API: {api_url}")
|
| 284 |
+
|
| 285 |
+
response = requests.get(api_url, timeout=10)
|
| 286 |
+
if response.status_code == 200:
|
| 287 |
+
result = response.json()
|
| 288 |
+
return f"β
EXTERNAL API Connection: Healthy - {result.get('status', 'No status')}"
|
| 289 |
+
else:
|
| 290 |
+
return f"β EXTERNAL API Connection: HTTP {response.status_code} - {response.text}"
|
| 291 |
+
except requests.exceptions.ConnectionError:
|
| 292 |
+
return "β EXTERNAL API Connection: Cannot connect (ConnectionError)"
|
| 293 |
+
except requests.exceptions.Timeout:
|
| 294 |
+
return "β EXTERNAL API Connection: Timeout after 10 seconds"
|
| 295 |
+
except Exception as e:
|
| 296 |
+
return f"β EXTERNAL API Connection Error: {str(e)}"
|
| 297 |
+
|
| 298 |
+
except Exception as e:
|
| 299 |
+
return f"β Connection check failed: {str(e)}"
|
| 300 |
+
|
| 301 |
# Create the Gradio interface
|
| 302 |
with gr.Blocks(title="Children's Book Illustrator", theme="soft") as demo:
|
| 303 |
gr.Markdown("# π Children's Book Illustrator")
|
|
|
|
| 318 |
|
| 319 |
# Debug section
|
| 320 |
with gr.Accordion("π§ Debug Information", open=False):
|
| 321 |
+
gr.Markdown(f"""
|
| 322 |
**Current Configuration:**
|
| 323 |
+
- OCI Access: **{'Direct' if DIRECT_OCI_ACCESS else 'External API'}**
|
| 324 |
+
- API URL: {OCI_API_BASE_URL}
|
| 325 |
- Model: Stable Diffusion v1.5
|
| 326 |
- Storage Path: `storybook-generator/childrens-books/`
|
| 327 |
+
""")
|
| 328 |
|
| 329 |
debug_btn = gr.Button("π Check OCI Connection", variant="secondary")
|
| 330 |
+
debug_output = gr.Textbox(label="Debug Info", interactive=False, lines=8)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 331 |
|
| 332 |
# Connect buttons to functions
|
| 333 |
generate_btn.click(
|
|
|
|
| 348 |
|
| 349 |
if __name__ == "__main__":
|
| 350 |
print("π Starting Children's Book Illustrator...")
|
| 351 |
+
print(f"π¦ OCI Access: {'Direct' if DIRECT_OCI_ACCESS else 'External API'}")
|
| 352 |
+
print(f"π API URL: {OCI_API_BASE_URL}")
|
| 353 |
demo.launch(server_name="0.0.0.0", server_port=7860)
|