Malaji71 commited on
Commit
307a239
·
verified ·
1 Parent(s): 5b85614

Update models.py

Browse files
Files changed (1) hide show
  1. models.py +81 -221
models.py CHANGED
@@ -19,7 +19,8 @@ from utils import clean_memory, safe_execute
19
  from professional_photography import (
20
  ProfessionalPhotoAnalyzer,
21
  enhance_flux_prompt_with_professional_knowledge,
22
- professional_analyzer
 
23
  )
24
 
25
  logger = logging.getLogger(__name__)
@@ -89,183 +90,43 @@ class BagelAPIAnalyzer(BaseImageAnalyzer):
89
  logger.error(f"Fallback initialization failed: {e2}")
90
  return False
91
 
92
- def _create_professional_enhanced_prompt(self, analysis_type: str = "multimodal") -> str:
93
- """Create professionally enhanced prompt that makes BAGEL see with cinematographic eyes"""
94
-
95
- if analysis_type == "cinematic":
96
- return """You are a master cinematographer with 30+ years of experience. Analyze this image with complete professional cinematography knowledge and provide exactly two sections:
97
-
98
- 1. DESCRIPTION: Analyze what you see using professional cinematography terminology:
99
-
100
- First, identify the PHOTOGRAPHIC PLANE:
101
- - EXTREME WIDE SHOT: Subject very small in environment (establishes location)
102
- - WIDE SHOT: Full body visible with environment (subject in context)
103
- - MEDIUM SHOT: From waist up (balance subject/environment)
104
- - CLOSE-UP: Head and shoulders (emotion and expression)
105
- - EXTREME CLOSE-UP: Part of face or detail (intense emotion)
106
- - DETAIL SHOT: Specific small element (highlight aspect)
107
-
108
- Second, identify the CAMERA ANGLE:
109
- - EYE LEVEL: Camera at subject's eye level (neutral, natural perspective)
110
- - LOW ANGLE: Camera below looking up (subject appears powerful, heroic)
111
- - HIGH ANGLE: Camera above looking down (subject appears vulnerable, shows context)
112
- - DUTCH ANGLE: Camera tilted (dynamic tension, instability)
113
-
114
- Third, analyze the LIGHTING:
115
- - GOLDEN HOUR: Warm, soft, directional light (first/last hour of sun)
116
- - BLUE HOUR: Even blue light, dramatic mood (20-30 min after sunset)
117
- - NATURAL DAYLIGHT: Bright sunny conditions
118
- - SOFT NATURAL: Overcast, diffused, even light
119
- - DRAMATIC: High contrast, moody shadows
120
- - STUDIO: Controlled professional lighting
121
-
122
- Fourth, identify COMPOSITION:
123
- - RULE OF THIRDS: Key elements on intersection points
124
- - LEADING LINES: Lines guide viewer's eye to subject
125
- - SYMMETRICAL: Mirror-like balance
126
- - CENTERED: Subject in middle for impact
127
- - DEPTH LAYERS: Foreground, middle ground, background separation
128
-
129
- Now describe the scene combining all these professional elements in flowing descriptive language.
130
-
131
- 2. CAMERA_SETUP: Recommend specific professional equipment based on your analysis:
132
-
133
- For PORTRAIT scenes: Canon EOS R5, 85mm f/1.4 lens, f/2.8, ISO 200, single point AF on eyes
134
- For LANDSCAPE scenes: Phase One XT, 24-70mm f/4 lens, f/8-f/11, ISO 100, hyperfocal distance
135
- For STREET scenes: Leica M11, 35mm f/1.4 lens, f/5.6-f/8, ISO 400-1600, zone focusing
136
- For ARCHITECTURE: Canon EOS R5, 24-70mm f/2.8 lens, f/8-f/11, ISO 100, tilt-shift correction
137
- For ACTION: Sony A1, 70-200mm f/2.8 lens, f/2.8-f/4, ISO 800-3200, continuous AF tracking
138
-
139
- Apply your complete professional cinematography knowledge to see this image as a master would."""
140
-
141
- elif analysis_type == "flux_optimized":
142
- return """You are a professional cinematographer analyzing this image for photorealistic prompt generation. Use complete technical knowledge and provide exactly two sections:
143
-
144
- 1. DESCRIPTION: Technical cinematographic analysis:
145
-
146
- PHOTOGRAPHIC PLANE (choose one):
147
- - Wide shot: Full subject visible with environment
148
- - Medium shot: Waist up, balanced composition
149
- - Close-up: Head and shoulders, tight framing
150
- - Extreme close-up: Facial details or specific elements
151
- - Detail shot: Small specific elements highlighted
152
-
153
- CAMERA ANGLE (identify):
154
- - Eye level: Natural, relatable perspective
155
- - Low angle: Looking up, subject appears powerful
156
- - High angle: Looking down, shows vulnerability/context
157
- - Dutch angle: Tilted, creates dynamic tension
158
-
159
- LIGHTING TYPE (analyze):
160
- - Golden hour: Warm, soft directional light
161
- - Natural daylight: Bright outdoor conditions
162
- - Soft natural: Overcast, even diffusion
163
- - Dramatic: High contrast, moody shadows
164
- - Blue hour: Even twilight, dramatic mood
165
-
166
- COMPOSITION TECHNIQUE (apply):
167
- - Rule of thirds: Subject on intersection points
168
- - Leading lines: Elements guide eye to subject
169
- - Symmetrical: Balanced mirror composition
170
- - Centered: Subject middle for impact
171
- - Dynamic: Diagonal elements, movement
172
-
173
- Describe the scene using these professional cinematography elements in precise technical language.
174
-
175
- 2. CAMERA_SETUP: Professional equipment recommendation:
176
-
177
- PORTRAIT SETUP: Canon EOS R5 with 85mm f/1.4 lens at f/2.8, ISO 200, rule of thirds composition
178
- LANDSCAPE SETUP: Phase One XT with 24-70mm f/4 lens at f/8, ISO 100, hyperfocal distance focus
179
- STREET SETUP: Leica M11 with 35mm f/1.4 lens at f/5.6, ISO 800, zone focusing technique
180
- ARCHITECTURE SETUP: Canon EOS R5 with 24-70mm f/2.8 lens at f/11, ISO 100, perspective correction
181
- ACTION SETUP: Sony A1 with 70-200mm f/2.8 lens at f/4, ISO 1600, continuous AF tracking
182
-
183
- Choose the setup that matches your scene analysis and provide complete technical specifications."""
184
-
185
- else: # multimodal analysis
186
- return """You are a master cinematographer with decades of professional experience. Analyze this image using complete cinematography knowledge and provide exactly two sections:
187
-
188
- 1. DESCRIPTION: Professional cinematographic analysis combining:
189
-
190
- PHOTOGRAPHIC PLANES: Identify if this is a wide shot (full subject with environment), medium shot (waist up), close-up (head/shoulders), extreme close-up (facial details), or detail shot (specific elements).
191
-
192
- CAMERA ANGLES: Determine if shot from eye level (natural perspective), low angle (looking up, powerful), high angle (looking down, vulnerable), or dutch angle (tilted, dynamic).
193
-
194
- LIGHTING ANALYSIS: Analyze if this is golden hour (warm directional), natural daylight (bright outdoor), soft natural (overcast even), dramatic (high contrast), blue hour (twilight mood), or studio (controlled).
195
-
196
- COMPOSITION: Identify rule of thirds (key elements on intersections), leading lines (guiding elements), symmetrical (balanced), centered (middle impact), or dynamic (diagonal movement).
197
-
198
- Describe the complete scene using professional cinematography terminology in flowing descriptive language that captures all visual and technical elements.
199
-
200
- 2. CAMERA_SETUP: Professional equipment recommendation based on scene analysis:
201
-
202
- Choose from these professional setups:
203
- - PORTRAIT: Canon EOS R5, 85mm f/1.4 lens, f/2.8, ISO 200
204
- - LANDSCAPE: Phase One XT, 24-70mm f/4 lens, f/8, ISO 100
205
- - STREET: Leica M11, 35mm f/1.4 lens, f/5.6, ISO 800
206
- - ARCHITECTURE: Canon EOS R5, 24-70mm f/2.8 lens, f/11, ISO 100
207
- - ACTION: Sony A1, 70-200mm f/2.8 lens, f/4, ISO 1600
208
-
209
- Provide complete technical specifications matching your cinematographic analysis."""
210
-
211
- def _extract_professional_camera_setup(self, description: str) -> Optional[str]:
212
- """Extract and enhance camera setup with professional photography knowledge"""
213
  try:
214
- camera_setup = None
215
-
216
- # Extract BAGEL's camera recommendation
217
- if "CAMERA_SETUP:" in description:
218
- parts = description.split("CAMERA_SETUP:")
219
- if len(parts) > 1:
220
- camera_section = parts[1].strip()
221
- # Take the first substantial line
222
- lines = camera_section.split('\n')
223
- for line in lines:
224
- clean_line = line.strip()
225
- if len(clean_line) > 20 and not clean_line.startswith('2.'):
226
- camera_setup = clean_line
227
- break
228
-
229
- elif "2. CAMERA_SETUP" in description:
230
- parts = description.split("2. CAMERA_SETUP")
231
- if len(parts) > 1:
232
- camera_section = parts[1].strip()
233
- lines = camera_section.split('\n')
234
- for line in lines:
235
- clean_line = line.strip()
236
- if len(clean_line) > 20:
237
- camera_setup = clean_line
238
- break
239
 
240
- # Clean and format camera setup
241
- if camera_setup:
242
- return self._clean_camera_setup(camera_setup)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
243
 
244
- return None
245
 
246
  except Exception as e:
247
- logger.warning(f"Failed to extract professional camera setup: {e}")
248
- return None
 
249
 
250
- def _clean_camera_setup(self, raw_setup: str) -> str:
251
- """Clean and format camera setup"""
252
- try:
253
- # Remove common prefixes
254
- setup = re.sub(r'^(Based on.*?recommend|I would recommend|For this.*?setup)\s*:?\s*', '', raw_setup, flags=re.IGNORECASE)
255
- setup = re.sub(r'^(CAMERA_SETUP:|2\.\s*CAMERA_SETUP:?)\s*', '', setup, flags=re.IGNORECASE)
256
-
257
- # Clean up formatting
258
- setup = re.sub(r'\s+', ' ', setup).strip()
259
-
260
- # Ensure proper format
261
- if setup and not setup.lower().startswith('shot on'):
262
- setup = f"shot on {setup}"
263
-
264
- return setup
265
-
266
- except Exception as e:
267
- logger.warning(f"Camera setup cleaning failed: {e}")
268
- return raw_setup
269
 
270
  def _save_temp_image(self, image: Image.Image) -> str:
271
  """Save image to temporary file for API call"""
@@ -313,29 +174,29 @@ Provide complete technical specifications matching your cinematographic analysis
313
  }
314
 
315
  try:
316
- # Use professional enhanced prompt if none provided
317
  if prompt is None:
318
- prompt = self._create_professional_enhanced_prompt("multimodal")
319
 
320
  # Save image to temporary file
321
  temp_path = self._save_temp_image(image)
322
  if not temp_path:
323
  return "Image processing failed", {"error": "Could not save image"}
324
 
325
- logger.info("Calling BAGEL API with professional cinematography prompt...")
326
 
327
- # Call BAGEL API with enhanced prompt
328
  result = self.client.predict(
329
  image=handle_file(temp_path),
330
  prompt=prompt,
331
  show_thinking=False,
332
- do_sample=False,
333
- text_temperature=0.2,
334
- max_new_tokens=512,
335
  api_name=self.api_endpoint
336
  )
337
 
338
- # Extract and process response
339
  if isinstance(result, tuple) and len(result) >= 2:
340
  description = result[1] if result[1] else result[0]
341
  else:
@@ -344,15 +205,12 @@ Provide complete technical specifications matching your cinematographic analysis
344
  if isinstance(description, str) and description.strip():
345
  description = description.strip()
346
 
347
- # Extract professional camera setup
348
- camera_setup = self._extract_professional_camera_setup(description)
349
- if camera_setup:
350
- metadata["camera_setup"] = camera_setup
351
  metadata["has_camera_suggestion"] = True
352
- logger.info(f"Professional camera setup extracted: {camera_setup}")
353
  else:
354
  metadata["has_camera_suggestion"] = False
355
- logger.info("No camera setup found in BAGEL response")
356
 
357
  # Mark as cinematography enhanced
358
  metadata["cinematography_context_applied"] = True
@@ -367,7 +225,7 @@ Provide complete technical specifications matching your cinematographic analysis
367
  "analysis_type": "professional_enhanced"
368
  })
369
 
370
- logger.info(f"BAGEL Professional analysis complete: {len(description)} chars, Camera: {metadata.get('has_camera_suggestion', False)}")
371
  return description, metadata
372
 
373
  except Exception as e:
@@ -380,17 +238,17 @@ Provide complete technical specifications matching your cinematographic analysis
380
 
381
  def analyze_for_cinematic_prompt(self, image: Image.Image) -> Tuple[str, Dict[str, Any]]:
382
  """Analyze image specifically for cinematic/MIA TV Series prompt generation"""
383
- cinematic_prompt = self._create_professional_enhanced_prompt("cinematic")
384
  return self.analyze_image(image, cinematic_prompt)
385
 
386
  def analyze_for_flux_with_professional_context(self, image: Image.Image) -> Tuple[str, Dict[str, Any]]:
387
  """Analyze image for FLUX with enhanced professional cinematography context"""
388
- flux_prompt = self._create_professional_enhanced_prompt("flux_optimized")
389
  return self.analyze_image(image, flux_prompt)
390
 
391
  def analyze_for_multiengine_prompt(self, image: Image.Image) -> Tuple[str, Dict[str, Any]]:
392
  """Analyze image for multi-engine compatibility (Flux, Midjourney, etc.)"""
393
- multiengine_prompt = self._create_professional_enhanced_prompt("multimodal")
394
  return self.analyze_image(image, multiengine_prompt)
395
 
396
  def cleanup(self) -> None:
@@ -405,7 +263,7 @@ Provide complete technical specifications matching your cinematographic analysis
405
 
406
 
407
  class FallbackAnalyzer(BaseImageAnalyzer):
408
- """Enhanced fallback analyzer with basic professional cinematography principles"""
409
 
410
  def __init__(self):
411
  super().__init__()
@@ -417,43 +275,45 @@ class FallbackAnalyzer(BaseImageAnalyzer):
417
  return True
418
 
419
  def analyze_image(self, image: Image.Image) -> Tuple[str, Dict[str, Any]]:
420
- """Provide enhanced image description with cinematography context"""
421
  try:
422
  width, height = image.size
423
- mode = image.mode
424
  aspect_ratio = width / height
425
 
426
- # Enhanced scene detection with cinematographic analysis
427
- if aspect_ratio > 1.5:
428
- orientation = "landscape"
429
- scene_type = "landscape"
430
- plane = "Wide shot"
431
- camera_suggestion = "Phase One XT with 24-70mm f/4 lens, f/8, ISO 100"
432
- elif aspect_ratio < 0.75:
433
- orientation = "portrait"
434
- scene_type = "portrait_studio"
435
- plane = "Close-up"
436
- camera_suggestion = "Canon EOS R5 with 85mm f/1.4 lens, f/2.8, ISO 200"
437
- else:
438
- orientation = "square"
439
- scene_type = "general"
440
- plane = "Medium shot"
441
- camera_suggestion = "Canon EOS R6 with 50mm f/1.8 lens, f/4, ISO 400"
442
 
443
- # Generate professional cinematographic description
444
- description = f"{plane} composition with balanced framing and professional execution, natural lighting with good contrast, rule of thirds composition, suitable for high-quality reproduction across multiple generative platforms"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
445
 
446
  metadata = {
447
  "model": "Professional-Fallback",
448
  "device": "cpu",
449
  "confidence": 0.7,
450
  "image_size": f"{width}x{height}",
451
- "color_mode": mode,
452
- "orientation": orientation,
453
  "aspect_ratio": round(aspect_ratio, 2),
454
- "scene_type": scene_type,
455
  "has_camera_suggestion": True,
456
- "camera_setup": f"shot on {camera_suggestion}",
457
  "professional_enhancement": True,
458
  "cinematography_context_applied": True
459
  }
@@ -462,7 +322,7 @@ class FallbackAnalyzer(BaseImageAnalyzer):
462
 
463
  except Exception as e:
464
  logger.error(f"Professional fallback analysis failed: {e}")
465
- return "Professional cinematographic analysis with technical excellence", {
466
  "error": str(e),
467
  "model": "Professional-Fallback"
468
  }
@@ -511,15 +371,15 @@ class ModelManager:
511
  if success and result[1].get("error") is None:
512
  return result
513
  else:
514
- # Enhanced fallback with cinematography context
515
- logger.warning(f"Primary model failed, using cinematography-enhanced fallback: {result}")
516
  fallback_analyzer = self.get_analyzer("fallback")
517
  fallback_success, fallback_result = safe_execute(fallback_analyzer.analyze_image, image)
518
 
519
  if fallback_success:
520
  return fallback_result
521
  else:
522
- return "All cinematography analyzers failed", {"error": "Complete analysis failure"}
523
 
524
  def cleanup_all(self) -> None:
525
  """Clean up all model resources"""
@@ -527,10 +387,10 @@ class ModelManager:
527
  analyzer.cleanup()
528
  self.analyzers.clear()
529
  clean_memory()
530
- logger.info("All cinematography analyzers cleaned up")
531
 
532
 
533
- # Global model manager instance with cinematography enhancement
534
  model_manager = ModelManager(preferred_model="bagel-professional")
535
 
536
 
 
19
  from professional_photography import (
20
  ProfessionalPhotoAnalyzer,
21
  enhance_flux_prompt_with_professional_knowledge,
22
+ professional_analyzer,
23
+ export_professional_prompt_enhancement
24
  )
25
 
26
  logger = logging.getLogger(__name__)
 
90
  logger.error(f"Fallback initialization failed: {e2}")
91
  return False
92
 
93
+ def _get_professional_prompt(self, analysis_type: str = "multimodal") -> str:
94
+ """Get professional prompt created by professional_photography.py"""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
95
  try:
96
+ # Let professional_photography.py create the complete prompt with full knowledge base
97
+ enhanced_context = self.professional_analyzer.generate_enhanced_context("")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
98
 
99
+ if analysis_type == "cinematic":
100
+ # Use the professional analyzer to format cinematic prompt
101
+ prompt = self.professional_analyzer.format_bagel_enhancement_prompt(
102
+ base_prompt="Analyze this image with complete professional cinematography expertise for cinema-quality generation.",
103
+ enhanced_context=enhanced_context
104
+ )
105
+ elif analysis_type == "flux_optimized":
106
+ # Use the professional analyzer to format FLUX prompt
107
+ prompt = self.professional_analyzer.format_bagel_enhancement_prompt(
108
+ base_prompt="Analyze this image with complete professional photography knowledge for photorealistic prompt generation.",
109
+ enhanced_context=enhanced_context
110
+ )
111
+ else:
112
+ # Use the professional analyzer to format multimodal prompt
113
+ prompt = self.professional_analyzer.format_bagel_enhancement_prompt(
114
+ base_prompt="Analyze this image with complete professional cinematography knowledge for multi-engine prompt generation.",
115
+ enhanced_context=enhanced_context
116
+ )
117
 
118
+ return prompt
119
 
120
  except Exception as e:
121
+ logger.warning(f"Professional prompt generation failed: {e}")
122
+ # Fallback to basic professional prompt
123
+ return """Analyze this image using complete professional cinematography expertise. Provide exactly two sections:
124
 
125
+ 1. DESCRIPTION: Complete professional visual analysis using your full cinematography knowledge - identify the photographic plane (wide shot, close-up, medium shot), camera angle (eye level, low angle, high angle), lighting type (golden hour, natural daylight, dramatic), and composition technique (rule of thirds, leading lines, symmetrical). Describe the specific subject, action, and context in detail.
126
+
127
+ 2. CAMERA_SETUP: Recommend specific professional equipment based on your scene analysis - camera body, lens specifications, aperture settings, ISO, and any special techniques.
128
+
129
+ Apply your complete professional cinematography knowledge."""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
130
 
131
  def _save_temp_image(self, image: Image.Image) -> str:
132
  """Save image to temporary file for API call"""
 
174
  }
175
 
176
  try:
177
+ # Use professional prompt created by professional_photography.py
178
  if prompt is None:
179
+ prompt = self._get_professional_prompt("multimodal")
180
 
181
  # Save image to temporary file
182
  temp_path = self._save_temp_image(image)
183
  if not temp_path:
184
  return "Image processing failed", {"error": "Could not save image"}
185
 
186
+ logger.info("Calling BAGEL API with professional_photography.py prompt...")
187
 
188
+ # Call BAGEL API with professional prompt - let it do its work
189
  result = self.client.predict(
190
  image=handle_file(temp_path),
191
  prompt=prompt,
192
  show_thinking=False,
193
+ do_sample=True, # Allow creativity
194
+ text_temperature=0.7, # Higher temperature for richer descriptions
195
+ max_new_tokens=1024, # More tokens for detailed analysis
196
  api_name=self.api_endpoint
197
  )
198
 
199
+ # Extract response without filtering
200
  if isinstance(result, tuple) and len(result) >= 2:
201
  description = result[1] if result[1] else result[0]
202
  else:
 
205
  if isinstance(description, str) and description.strip():
206
  description = description.strip()
207
 
208
+ # Extract camera setup if present
209
+ if "CAMERA_SETUP:" in description or "2. CAMERA_SETUP" in description:
 
 
210
  metadata["has_camera_suggestion"] = True
211
+ logger.info("BAGEL provided camera setup recommendation")
212
  else:
213
  metadata["has_camera_suggestion"] = False
 
214
 
215
  # Mark as cinematography enhanced
216
  metadata["cinematography_context_applied"] = True
 
225
  "analysis_type": "professional_enhanced"
226
  })
227
 
228
+ logger.info(f"BAGEL Professional analysis complete: {len(description)} chars")
229
  return description, metadata
230
 
231
  except Exception as e:
 
238
 
239
  def analyze_for_cinematic_prompt(self, image: Image.Image) -> Tuple[str, Dict[str, Any]]:
240
  """Analyze image specifically for cinematic/MIA TV Series prompt generation"""
241
+ cinematic_prompt = self._get_professional_prompt("cinematic")
242
  return self.analyze_image(image, cinematic_prompt)
243
 
244
  def analyze_for_flux_with_professional_context(self, image: Image.Image) -> Tuple[str, Dict[str, Any]]:
245
  """Analyze image for FLUX with enhanced professional cinematography context"""
246
+ flux_prompt = self._get_professional_prompt("flux_optimized")
247
  return self.analyze_image(image, flux_prompt)
248
 
249
  def analyze_for_multiengine_prompt(self, image: Image.Image) -> Tuple[str, Dict[str, Any]]:
250
  """Analyze image for multi-engine compatibility (Flux, Midjourney, etc.)"""
251
+ multiengine_prompt = self._get_professional_prompt("multimodal")
252
  return self.analyze_image(image, multiengine_prompt)
253
 
254
  def cleanup(self) -> None:
 
263
 
264
 
265
  class FallbackAnalyzer(BaseImageAnalyzer):
266
+ """Enhanced fallback analyzer using professional_photography.py knowledge"""
267
 
268
  def __init__(self):
269
  super().__init__()
 
275
  return True
276
 
277
  def analyze_image(self, image: Image.Image) -> Tuple[str, Dict[str, Any]]:
278
+ """Provide enhanced image description using professional_photography.py"""
279
  try:
280
  width, height = image.size
 
281
  aspect_ratio = width / height
282
 
283
+ # Use professional_photography.py to analyze basic image properties
284
+ basic_description = f"Professional photograph with {width}x{height} resolution, aspect ratio {aspect_ratio:.2f}"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
285
 
286
+ # Let professional_photography.py enhance this
287
+ try:
288
+ enhancement_result = export_professional_prompt_enhancement(
289
+ bagel_output=basic_description,
290
+ bagel_metadata={"image_size": f"{width}x{height}", "aspect_ratio": aspect_ratio}
291
+ )
292
+
293
+ description = enhancement_result["enhanced_prompt"]
294
+ camera_setup = enhancement_result["metadata"].get("technical_context", "")
295
+
296
+ except Exception as e:
297
+ logger.warning(f"Professional enhancement failed in fallback: {e}")
298
+ # Basic fallback
299
+ if aspect_ratio > 1.5:
300
+ description = "Wide shot composition with natural lighting and balanced framing"
301
+ camera_setup = "shot on Phase One XT, 24-70mm f/4 lens, ISO 100"
302
+ elif aspect_ratio < 0.75:
303
+ description = "Portrait composition with professional lighting and sharp focus"
304
+ camera_setup = "shot on Canon EOS R5, 85mm f/1.4 lens, ISO 200"
305
+ else:
306
+ description = "Balanced composition with professional execution"
307
+ camera_setup = "shot on Canon EOS R6, 50mm f/1.8 lens, ISO 400"
308
 
309
  metadata = {
310
  "model": "Professional-Fallback",
311
  "device": "cpu",
312
  "confidence": 0.7,
313
  "image_size": f"{width}x{height}",
 
 
314
  "aspect_ratio": round(aspect_ratio, 2),
 
315
  "has_camera_suggestion": True,
316
+ "camera_setup": camera_setup,
317
  "professional_enhancement": True,
318
  "cinematography_context_applied": True
319
  }
 
322
 
323
  except Exception as e:
324
  logger.error(f"Professional fallback analysis failed: {e}")
325
+ return "Professional cinematographic analysis", {
326
  "error": str(e),
327
  "model": "Professional-Fallback"
328
  }
 
371
  if success and result[1].get("error") is None:
372
  return result
373
  else:
374
+ # Fallback with professional_photography.py
375
+ logger.warning(f"Primary model failed, using professional fallback")
376
  fallback_analyzer = self.get_analyzer("fallback")
377
  fallback_success, fallback_result = safe_execute(fallback_analyzer.analyze_image, image)
378
 
379
  if fallback_success:
380
  return fallback_result
381
  else:
382
+ return "All analyzers failed", {"error": "Complete analysis failure"}
383
 
384
  def cleanup_all(self) -> None:
385
  """Clean up all model resources"""
 
387
  analyzer.cleanup()
388
  self.analyzers.clear()
389
  clean_memory()
390
+ logger.info("All analyzers cleaned up")
391
 
392
 
393
+ # Global model manager instance
394
  model_manager = ModelManager(preferred_model="bagel-professional")
395
 
396