yukee1992 commited on
Commit
8eed004
Β·
verified Β·
1 Parent(s): 000b832

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +312 -1
app.py CHANGED
@@ -973,4 +973,315 @@ def create_gradio_interface():
973
 
974
  except Exception as e:
975
  error_msg = f"❌ Generation failed: {str(e)}"
976
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
973
 
974
  except Exception as e:
975
  error_msg = f"❌ Generation failed: {str(e)}"
976
+ print(error_msg)
977
+ return None, error_msg, None
978
+
979
+ with gr.Blocks(title="Premium Children's Book Illustrator with Dynamic Character Consistency", theme="soft") as demo:
980
+ gr.Markdown("# 🎨 Premium Children's Book Illustrator")
981
+ gr.Markdown("Generate **studio-quality** storybook images with **dynamic character consistency**")
982
+
983
+ # Storage info display
984
+ storage_info = gr.Textbox(
985
+ label="πŸ“Š Local Storage Information",
986
+ interactive=False,
987
+ lines=2
988
+ )
989
+
990
+ def update_storage_info():
991
+ info = get_local_storage_info()
992
+ if "error" not in info:
993
+ return f"πŸ“ Local Storage: {info['total_files']} images, {info['total_size_mb']} MB used"
994
+ return "πŸ“ Local Storage: Unable to calculate"
995
+
996
+ with gr.Row():
997
+ with gr.Column(scale=1):
998
+ gr.Markdown("### 🎯 Quality Settings")
999
+
1000
+ model_dropdown = gr.Dropdown(
1001
+ label="AI Model",
1002
+ choices=list(MODEL_CHOICES.keys()),
1003
+ value="dreamshaper-8"
1004
+ )
1005
+
1006
+ style_dropdown = gr.Dropdown(
1007
+ label="Art Style",
1008
+ choices=["childrens_book", "realistic", "fantasy", "anime"],
1009
+ value="childrens_book"
1010
+ )
1011
+
1012
+ # Dynamic character input for testing
1013
+ character_names_input = gr.Textbox(
1014
+ label="Character Names (comma-separated)",
1015
+ placeholder="Enter character names: Sparkle the Star Cat, Benny the Bunny, Tilly the Turtle",
1016
+ info="Enter character names to test consistency features",
1017
+ lines=2
1018
+ )
1019
+
1020
+ prompt_input = gr.Textbox(
1021
+ label="Scene Description",
1022
+ placeholder="Describe your scene with character interactions...\nExample: Sparkle the Star Cat chasing butterflies while Benny the Bunny watches",
1023
+ lines=3
1024
+ )
1025
+
1026
+ generate_btn = gr.Button("✨ Generate Premium Image", variant="primary")
1027
+
1028
+ # Current image management
1029
+ current_file_path = gr.State()
1030
+ delete_btn = gr.Button("πŸ—‘οΈ Delete This Image", variant="stop")
1031
+ delete_status = gr.Textbox(label="Delete Status", interactive=False, lines=2)
1032
+
1033
+ gr.Markdown("### πŸ“š API Usage for n8n")
1034
+ gr.Markdown("""
1035
+ **For complete storybooks (OCI bucket):**
1036
+ - Endpoint: `POST /api/generate-storybook`
1037
+ - Input: `story_title`, `scenes[]`, `characters[]`
1038
+ - Output: Saves to OCI bucket with dynamic character consistency
1039
+ """)
1040
+
1041
+ with gr.Column(scale=2):
1042
+ image_output = gr.Image(label="Generated Image", height=500, show_download_button=True)
1043
+ status_output = gr.Textbox(label="Status", interactive=False, lines=4)
1044
+
1045
+ # Dynamic character guidance section
1046
+ with gr.Accordion("πŸ‘₯ Dynamic Character Guidance", open=False):
1047
+ gr.Markdown("""
1048
+ ### How to Use Dynamic Characters from n8n:
1049
+
1050
+ **n8n Payload Structure:**
1051
+ ```json
1052
+ {
1053
+ "story_title": "Your Story Title",
1054
+ "characters": [
1055
+ {
1056
+ "name": "Character Name",
1057
+ "description": "Character description...",
1058
+ "visual_prompt": "Detailed visual description", // Optional
1059
+ "key_features": ["feature1", "feature2"] // Optional
1060
+ }
1061
+ ],
1062
+ "scenes": [
1063
+ {
1064
+ "visual": "Scene description with characters...",
1065
+ "text": "Scene text...",
1066
+ "characters_present": ["Character Name"] // Optional
1067
+ }
1068
+ ]
1069
+ }
1070
+ ```
1071
+
1072
+ **Features:**
1073
+ - βœ… Dynamic character processing from n8n
1074
+ - βœ… Automatic visual prompt generation
1075
+ - βœ… Key feature extraction
1076
+ - βœ… Cross-scene consistency
1077
+ - βœ… Flexible character numbers and types
1078
+ """)
1079
+
1080
+ # Examples section
1081
+ with gr.Accordion("πŸ’‘ Prompt Examples & Tips", open=False):
1082
+ gr.Markdown("""
1083
+ ## 🎨 Professional Prompt Examples with Dynamic Characters:
1084
+
1085
+ **Best Results with Dynamic Characters:**
1086
+ - "Sparkle the Star Cat chasing butterflies in a sunny meadow"
1087
+ - "Benny the Bunny and Tilly the Turtle having a picnic"
1088
+ - "Multiple characters discovering a magical portal together"
1089
+
1090
+ ## ⚑ Dynamic Character Consistency Tips:
1091
+ 1. **Always mention character names** in your prompts
1092
+ 2. **n8n will send character details** automatically
1093
+ 3. **The system processes any number** of characters dynamically
1094
+ 4. **Consistency is maintained** across all scenes automatically
1095
+ """)
1096
+
1097
+ # Local file management section
1098
+ with gr.Accordion("πŸ“ Manage Local Test Images", open=True):
1099
+ gr.Markdown("### Locally Saved Images")
1100
+
1101
+ with gr.Row():
1102
+ refresh_btn = gr.Button("πŸ”„ Refresh List")
1103
+ clear_all_btn = gr.Button("πŸ—‘οΈ Clear All Images", variant="stop")
1104
+
1105
+ file_gallery = gr.Gallery(
1106
+ label="Local Images",
1107
+ show_label=True,
1108
+ elem_id="gallery",
1109
+ columns=4,
1110
+ height="auto"
1111
+ )
1112
+
1113
+ clear_status = gr.Textbox(label="Clear Status", interactive=False)
1114
+
1115
+ # Debug section
1116
+ with gr.Accordion("πŸ”§ Advanced Settings", open=False):
1117
+ debug_btn = gr.Button("πŸ”„ Check System Status", variant="secondary")
1118
+ debug_output = gr.Textbox(label="System Info", interactive=False, lines=4)
1119
+
1120
+ def check_system_status():
1121
+ """Check system status"""
1122
+ active_jobs = len(job_storage)
1123
+ return f"""**System Status:**
1124
+ - Model: {current_model_name}
1125
+ - Dynamic Character Processing: βœ… Enabled
1126
+ - Fallback Templates: {len(FALLBACK_CHARACTER_TEMPLATES)} available
1127
+ - OCI API: {OCI_API_BASE_URL}
1128
+ - Local Storage: {get_local_storage_info().get('total_files', 0)} images
1129
+ - Active Jobs: {active_jobs}
1130
+ - Ready for dynamic character consistency generation!"""
1131
+
1132
+ # Connect buttons to functions
1133
+ generate_btn.click(
1134
+ fn=generate_test_image_with_characters,
1135
+ inputs=[prompt_input, model_dropdown, style_dropdown, character_names_input],
1136
+ outputs=[image_output, status_output, current_file_path]
1137
+ ).then(
1138
+ fn=refresh_local_images,
1139
+ outputs=file_gallery
1140
+ ).then(
1141
+ fn=update_storage_info,
1142
+ outputs=storage_info
1143
+ )
1144
+
1145
+ delete_btn.click(
1146
+ fn=delete_current_image,
1147
+ inputs=current_file_path,
1148
+ outputs=[delete_status, image_output, status_output, file_gallery]
1149
+ ).then(
1150
+ fn=update_storage_info,
1151
+ outputs=storage_info
1152
+ )
1153
+
1154
+ refresh_btn.click(
1155
+ fn=refresh_local_images,
1156
+ outputs=file_gallery
1157
+ ).then(
1158
+ fn=update_storage_info,
1159
+ outputs=storage_info
1160
+ )
1161
+
1162
+ clear_all_btn.click(
1163
+ fn=clear_all_images,
1164
+ outputs=[clear_status, file_gallery]
1165
+ ).then(
1166
+ fn=update_storage_info,
1167
+ outputs=storage_info
1168
+ )
1169
+
1170
+ debug_btn.click(
1171
+ fn=check_system_status,
1172
+ inputs=None,
1173
+ outputs=debug_output
1174
+ )
1175
+
1176
+ # Initialize on load
1177
+ demo.load(fn=refresh_local_images, outputs=file_gallery)
1178
+ demo.load(fn=update_storage_info, outputs=storage_info)
1179
+
1180
+ return demo
1181
+
1182
+ # Create enhanced Gradio app
1183
+ demo = create_gradio_interface()
1184
+
1185
+ # Enhanced root endpoint that explains the API structure
1186
+ @app.get("/")
1187
+ async def root():
1188
+ return {
1189
+ "message": "Storybook Generator API with Dynamic Character Consistency is running!",
1190
+ "api_endpoints": {
1191
+ "health_check": "GET /api/health",
1192
+ "generate_storybook": "POST /api/generate-storybook",
1193
+ "check_job_status": "GET /api/job-status/{job_id}",
1194
+ "local_images": "GET /api/local-images"
1195
+ },
1196
+ "features": {
1197
+ "dynamic_characters": "βœ… Enabled",
1198
+ "character_consistency": "βœ… Enabled",
1199
+ "flexible_storytelling": "βœ… Enabled",
1200
+ "n8n_integration": "βœ… Enabled"
1201
+ },
1202
+ "web_interface": "GET /ui",
1203
+ "note": "Use API endpoints for programmatic access with dynamic characters from n8n"
1204
+ }
1205
+
1206
+ # Add a simple test endpoint
1207
+ @app.get("/api/test")
1208
+ async def test_endpoint():
1209
+ return {
1210
+ "status": "success",
1211
+ "message": "API with dynamic character consistency is working correctly",
1212
+ "dynamic_processing": "βœ… Enabled",
1213
+ "fallback_templates": len(FALLBACK_CHARACTER_TEMPLATES),
1214
+ "timestamp": datetime.now().isoformat()
1215
+ }
1216
+
1217
+ # For Hugging Face Spaces deployment
1218
+ def get_app():
1219
+ return app
1220
+
1221
+ if __name__ == "__main__":
1222
+ import uvicorn
1223
+ import os
1224
+
1225
+ # Check if we're running on Hugging Face Spaces
1226
+ HF_SPACE = os.environ.get('SPACE_ID') is not None
1227
+
1228
+ if HF_SPACE:
1229
+ print("πŸš€ Running on Hugging Face Spaces - Integrated Mode")
1230
+ print("πŸ“š API endpoints available at: /api/*")
1231
+ print("🎨 Web interface available at: /ui")
1232
+ print("πŸ‘₯ Dynamic character consistency features enabled")
1233
+ print("πŸ”Œ Both API and UI running on same port")
1234
+
1235
+ # Mount Gradio without reassigning app
1236
+ gr.mount_gradio_app(app, demo, path="/ui")
1237
+
1238
+ # Run the combined app
1239
+ uvicorn.run(
1240
+ app,
1241
+ host="0.0.0.0",
1242
+ port=7860,
1243
+ log_level="info"
1244
+ )
1245
+ else:
1246
+ # Local development - run separate servers
1247
+ print("πŸš€ Running locally - Separate API and UI servers")
1248
+ print("πŸ“š API endpoints: http://localhost:8000/api/*")
1249
+ print("🎨 Web interface: http://localhost:7860/ui")
1250
+ print("πŸ‘₯ Dynamic character consistency features enabled")
1251
+
1252
+ def run_fastapi():
1253
+ """Run FastAPI on port 8000 for API calls"""
1254
+ uvicorn.run(
1255
+ app,
1256
+ host="0.0.0.0",
1257
+ port=8000,
1258
+ log_level="info",
1259
+ access_log=False
1260
+ )
1261
+
1262
+ def run_gradio():
1263
+ """Run Gradio on port 7860 for web interface"""
1264
+ demo.launch(
1265
+ server_name="0.0.0.0",
1266
+ server_port=7860,
1267
+ share=False,
1268
+ show_error=True,
1269
+ quiet=True
1270
+ )
1271
+
1272
+ # Start both servers in separate threads
1273
+ api_thread = threading.Thread(target=run_fastapi, daemon=True)
1274
+ ui_thread = threading.Thread(target=run_gradio, daemon=True)
1275
+
1276
+ api_thread.start()
1277
+ print("βœ… FastAPI server started on port 8000")
1278
+
1279
+ ui_thread.start()
1280
+ print("βœ… Gradio server started on port 7860")
1281
+
1282
+ # Keep the main thread alive
1283
+ try:
1284
+ while True:
1285
+ time.sleep(1)
1286
+ except KeyboardInterrupt:
1287
+ print("πŸ›‘ Shutting down servers...")