Malaji71 commited on
Commit
f746366
Β·
verified Β·
1 Parent(s): d40d75f

Update utils.py

Browse files
Files changed (1) hide show
  1. utils.py +276 -97
utils.py CHANGED
@@ -1,6 +1,8 @@
1
  """
2
- Utility functions for FLUX Prompt Optimizer
3
- Clean, focused, and reusable utilities
 
 
4
  """
5
 
6
  import re
@@ -11,7 +13,7 @@ from PIL import Image
11
  import torch
12
  import numpy as np
13
 
14
- from config import PROCESSING_CONFIG, FLUX_RULES
15
 
16
  # Configure logging
17
  logging.basicConfig(level=logging.INFO)
@@ -98,16 +100,44 @@ def clean_memory() -> None:
98
  logger.warning(f"Memory cleanup failed: {e}")
99
 
100
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
101
  def apply_flux_rules(prompt: str, analysis_metadata: Optional[Dict[str, Any]] = None) -> str:
102
  """
103
- Apply Flux optimization rules to a prompt
104
 
105
  Args:
106
- prompt: Raw prompt text
107
- analysis_metadata: Optional metadata from image analysis including camera suggestions
108
 
109
  Returns:
110
- Optimized prompt following Flux rules
111
  """
112
  if not prompt or not isinstance(prompt, str):
113
  return ""
@@ -120,23 +150,30 @@ def apply_flux_rules(prompt: str, analysis_metadata: Optional[Dict[str, Any]] =
120
  # Extract description part only (remove CAMERA_SETUP section if present)
121
  description_part = _extract_description_only(cleaned_prompt)
122
 
123
- # Check if BAGEL provided intelligent camera setup
124
  camera_config = ""
 
 
125
  if analysis_metadata and analysis_metadata.get("has_camera_suggestion") and analysis_metadata.get("camera_setup"):
126
- # Use BAGEL's intelligent camera suggestion - clean and format it properly
127
  bagel_camera = analysis_metadata["camera_setup"]
128
- camera_config = _format_bagel_camera_suggestion(bagel_camera)
129
- logger.info(f"Using BAGEL camera suggestion: {camera_config}")
 
130
  else:
131
- # Only use fallback if BAGEL didn't suggest anything
132
- camera_config = _get_fallback_camera_config(description_part.lower())
133
- logger.info("Using fallback camera configuration")
 
134
 
135
- # Add lighting enhancements if not present and not already covered by BAGEL
136
- lighting_enhancement = _get_lighting_enhancement(description_part.lower(), camera_config)
137
 
138
- # Build final prompt: Description + Camera + Lighting
139
- final_prompt = description_part + camera_config + lighting_enhancement
 
 
 
140
 
141
  # Clean up formatting
142
  final_prompt = _clean_prompt_formatting(final_prompt)
@@ -165,81 +202,133 @@ def _extract_description_only(prompt: str) -> str:
165
  # Clean up any remaining camera recommendations from the description
166
  description = re.sub(r'For this type of scene.*?shooting style would be.*?\.', '', description, flags=re.DOTALL)
167
  description = re.sub(r'I would recommend.*?aperture.*?\.', '', description, flags=re.DOTALL)
 
 
168
 
169
- # Remove numbered section residues (like "2.," at the end)
170
  description = re.sub(r'\s*\d+\.\s*,?\s*$', '', description)
171
  description = re.sub(r'\s*\d+\.\s*,?\s*', ' ', description)
172
 
173
  return description.strip()
174
 
175
 
176
- def _format_bagel_camera_suggestion(bagel_camera: str) -> str:
177
- """Format BAGEL's camera suggestion into clean FLUX format"""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
178
  try:
179
- # Clean up the BAGEL suggestion
180
  camera_text = bagel_camera.strip()
181
-
182
- # Remove "CAMERA_SETUP:" if it's still there
183
  camera_text = re.sub(r'^CAMERA_SETUP:\s*', '', camera_text)
184
 
185
- # Extract key camera info using regex patterns
186
- camera_patterns = {
187
- 'camera': r'(Canon EOS [^,]+|Sony A[^,]+|Leica [^,]+|Hasselblad [^,]+|Phase One [^,]+|Fujifilm [^,]+)',
188
- 'lens': r'(\d+mm[^,]*|[^,]*lens[^,]*)',
189
  'aperture': r'(f/[\d.]+[^,]*)'
190
  }
191
 
192
  extracted_parts = []
193
-
194
- for key, pattern in camera_patterns.items():
195
  match = re.search(pattern, camera_text, re.IGNORECASE)
196
  if match:
197
  extracted_parts.append(match.group(1).strip())
198
 
199
  if extracted_parts:
200
- # Build clean camera config
201
  camera_info = ', '.join(extracted_parts)
202
- return f", Shot on {camera_info}, professional photography"
203
- else:
204
- # Fallback: use the first part of BAGEL's suggestion
205
- first_sentence = camera_text.split('.')[0].strip()
206
- if len(first_sentence) > 10:
207
- return f", {first_sentence}, professional photography"
208
  else:
209
- return ", professional camera setup"
 
 
210
 
211
  except Exception as e:
212
- logger.warning(f"Failed to format BAGEL camera suggestion: {e}")
213
- return ", professional camera setup"
214
-
215
-
216
- def _get_fallback_camera_config(prompt_lower: str) -> str:
217
- """Get fallback camera configuration when BAGEL doesn't suggest one"""
218
- # Improved detection logic
219
- if any(word in prompt_lower for word in ['street', 'urban', 'city', 'documentary', 'crowd', 'protest']):
220
- return FLUX_RULES["camera_configs"]["street"]
221
- elif any(word in prompt_lower for word in ['portrait', 'person', 'man', 'woman', 'face']) and not any(word in prompt_lower for word in ['street', 'crowd', 'scene']):
222
- return FLUX_RULES["camera_configs"]["portrait"]
223
- elif any(word in prompt_lower for word in ['landscape', 'mountain', 'nature', 'outdoor']):
224
- return FLUX_RULES["camera_configs"]["landscape"]
 
 
 
 
 
 
 
 
225
  else:
226
  return FLUX_RULES["camera_configs"]["default"]
227
 
228
 
229
- def _get_lighting_enhancement(prompt_lower: str, camera_config: str) -> str:
230
- """Determine appropriate lighting enhancement"""
231
- # Don't add lighting if already mentioned in prompt or camera config
232
- if 'lighting' in prompt_lower or 'lighting' in camera_config.lower():
233
  return ""
234
 
235
- if 'dramatic' in prompt_lower or 'chaos' in prompt_lower or 'fire' in prompt_lower:
 
 
 
 
 
 
 
 
236
  return FLUX_RULES["lighting_enhancements"]["dramatic"]
237
- elif 'portrait' in camera_config.lower():
238
- return FLUX_RULES["lighting_enhancements"]["portrait"]
239
  else:
240
  return FLUX_RULES["lighting_enhancements"]["default"]
241
 
242
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
243
  def _clean_prompt_formatting(prompt: str) -> str:
244
  """Clean up prompt formatting"""
245
  if not prompt:
@@ -264,64 +353,118 @@ def _clean_prompt_formatting(prompt: str) -> str:
264
 
265
  def calculate_prompt_score(prompt: str, analysis_data: Optional[Dict[str, Any]] = None) -> Tuple[int, Dict[str, int]]:
266
  """
267
- Calculate quality score for a prompt
268
 
269
  Args:
270
  prompt: The prompt to score
271
- analysis_data: Optional analysis data to enhance scoring
272
 
273
  Returns:
274
  Tuple of (total_score, breakdown_dict)
275
  """
276
  if not prompt:
277
- return 0, {"prompt_quality": 0, "technical_details": 0, "artistic_value": 0, "flux_optimization": 0}
278
 
279
  breakdown = {}
280
 
281
- # Prompt quality score (0-30 points)
282
- length_score = min(20, len(prompt) // 8) # Reward decent length
283
- detail_score = min(10, len(prompt.split(',')) * 2) # Reward detail
284
- breakdown["prompt_quality"] = length_score + detail_score
285
 
286
- # Technical details score (0-25 points) - Enhanced for BAGEL camera suggestions
287
  tech_score = 0
288
- tech_keywords = ['shot on', 'lens', 'photography', 'lighting', 'camera']
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
289
  for keyword in tech_keywords:
290
  if keyword in prompt.lower():
291
- tech_score += 5
292
 
293
- # Bonus points for BAGEL camera suggestions
294
  if analysis_data and analysis_data.get("has_camera_suggestion"):
295
- tech_score += 10 # Higher bonus for intelligent camera selection
296
 
297
  breakdown["technical_details"] = min(25, tech_score)
298
 
299
- # Artistic value score (0-25 points)
300
- art_keywords = ['masterful', 'professional', 'cinematic', 'dramatic', 'beautiful']
301
- art_score = sum(5 for keyword in art_keywords if keyword in prompt.lower())
302
- breakdown["artistic_value"] = min(25, art_score)
303
 
304
- # Flux optimization score (0-20 points)
305
- flux_score = 0
 
306
 
307
- # Check for camera configuration (prefer BAGEL over fallback)
308
- if analysis_data and analysis_data.get("has_camera_suggestion"):
309
- flux_score += 15 # Higher score for BAGEL suggestions
310
- elif any(camera in prompt for camera in FLUX_RULES["camera_configs"].values()):
311
- flux_score += 10 # Lower score for fallback
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
312
 
313
- # Check for lighting configuration
314
  if any(lighting in prompt for lighting in FLUX_RULES["lighting_enhancements"].values()):
315
- flux_score += 5
316
 
317
- breakdown["flux_optimization"] = flux_score
 
 
 
 
318
 
319
- # Calculate total
320
  total_score = sum(breakdown.values())
321
 
322
  return total_score, breakdown
323
 
324
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
325
  def get_score_grade(score: int) -> Dict[str, str]:
326
  """
327
  Get grade information for a score
@@ -344,31 +487,35 @@ def get_score_grade(score: int) -> Dict[str, str]:
344
 
345
  def format_analysis_report(analysis_data: Dict[str, Any], processing_time: float) -> str:
346
  """
347
- Format analysis data into a readable report
348
 
349
  Args:
350
- analysis_data: Analysis results
351
  processing_time: Time taken for processing
352
 
353
  Returns:
354
  Formatted markdown report
355
  """
356
- model_used = analysis_data.get("model_used", "Unknown")
357
  prompt_length = len(analysis_data.get("prompt", ""))
 
 
358
 
359
- report = f"""**πŸš€ FLUX OPTIMIZATION COMPLETE**
360
  **Model:** {model_used} β€’ **Time:** {processing_time:.1f}s β€’ **Length:** {prompt_length} chars
361
 
362
- **πŸ“Š ANALYSIS SUMMARY:**
363
- {analysis_data.get("summary", "Analysis completed successfully")}
 
364
 
365
  **🎯 OPTIMIZATIONS APPLIED:**
366
- βœ… Flux camera configuration
367
- βœ… Professional lighting setup
368
- βœ… Technical photography details
369
- βœ… Artistic enhancement keywords
 
370
 
371
- **⚑ Powered by Frame 0 Laboratory for MIA**"""
372
 
373
  return report
374
 
@@ -410,6 +557,35 @@ def truncate_text(text: str, max_length: int = 100) -> str:
410
  return text[:max_length-3] + "..."
411
 
412
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
413
  # Export main functions
414
  __all__ = [
415
  "setup_logging",
@@ -418,8 +594,11 @@ __all__ = [
418
  "clean_memory",
419
  "apply_flux_rules",
420
  "calculate_prompt_score",
 
421
  "get_score_grade",
422
  "format_analysis_report",
423
  "safe_execute",
424
- "truncate_text"
 
 
425
  ]
 
1
  """
2
+ Utility functions for Phramer AI
3
+ By Pariente AI, for MIA TV Series
4
+
5
+ Enhanced with professional cinematography knowledge and multi-engine optimization
6
  """
7
 
8
  import re
 
13
  import torch
14
  import numpy as np
15
 
16
+ from config import PROCESSING_CONFIG, FLUX_RULES, PROFESSIONAL_PHOTOGRAPHY_CONFIG
17
 
18
  # Configure logging
19
  logging.basicConfig(level=logging.INFO)
 
100
  logger.warning(f"Memory cleanup failed: {e}")
101
 
102
 
103
+ def detect_scene_type_from_analysis(analysis_metadata: Dict[str, Any]) -> str:
104
+ """Detect scene type from BAGEL analysis metadata"""
105
+ try:
106
+ # Check if BAGEL provided scene detection
107
+ if "scene_type" in analysis_metadata:
108
+ return analysis_metadata["scene_type"]
109
+
110
+ # Check camera setup for scene hints
111
+ camera_setup = analysis_metadata.get("camera_setup", "").lower()
112
+
113
+ if any(term in camera_setup for term in ["portrait", "85mm", "135mm"]):
114
+ return "portrait"
115
+ elif any(term in camera_setup for term in ["landscape", "wide", "24mm", "phase one"]):
116
+ return "landscape"
117
+ elif any(term in camera_setup for term in ["street", "35mm", "documentary", "leica"]):
118
+ return "street"
119
+ elif any(term in camera_setup for term in ["cinema", "arri", "red", "anamorphic"]):
120
+ return "cinematic"
121
+ elif any(term in camera_setup for term in ["architecture", "building", "tilt"]):
122
+ return "architectural"
123
+
124
+ return "default"
125
+
126
+ except Exception as e:
127
+ logger.warning(f"Scene type detection failed: {e}")
128
+ return "default"
129
+
130
+
131
  def apply_flux_rules(prompt: str, analysis_metadata: Optional[Dict[str, Any]] = None) -> str:
132
  """
133
+ Apply enhanced prompt optimization rules for multi-engine compatibility
134
 
135
  Args:
136
+ prompt: Raw prompt text from BAGEL analysis
137
+ analysis_metadata: Enhanced metadata with cinematography suggestions
138
 
139
  Returns:
140
+ Optimized prompt for Flux, Midjourney, and other generative engines
141
  """
142
  if not prompt or not isinstance(prompt, str):
143
  return ""
 
150
  # Extract description part only (remove CAMERA_SETUP section if present)
151
  description_part = _extract_description_only(cleaned_prompt)
152
 
153
+ # Check if BAGEL provided intelligent camera setup with cinematography context
154
  camera_config = ""
155
+ scene_type = "default"
156
+
157
  if analysis_metadata and analysis_metadata.get("has_camera_suggestion") and analysis_metadata.get("camera_setup"):
158
+ # Use BAGEL's intelligent camera suggestion - enhanced with cinematography knowledge
159
  bagel_camera = analysis_metadata["camera_setup"]
160
+ scene_type = detect_scene_type_from_analysis(analysis_metadata)
161
+ camera_config = _format_professional_camera_suggestion(bagel_camera, scene_type)
162
+ logger.info(f"Using BAGEL cinematography suggestion: {camera_config}")
163
  else:
164
+ # Enhanced fallback with professional cinematography knowledge
165
+ scene_type = _detect_scene_from_description(description_part.lower())
166
+ camera_config = _get_enhanced_camera_config(scene_type, description_part.lower())
167
+ logger.info(f"Using enhanced cinematography configuration for {scene_type}")
168
 
169
+ # Add enhanced lighting with cinematography principles
170
+ lighting_enhancement = _get_cinematography_lighting_enhancement(description_part.lower(), camera_config, scene_type)
171
 
172
+ # Add style enhancement for multi-engine compatibility
173
+ style_enhancement = _get_style_enhancement(scene_type, description_part.lower())
174
+
175
+ # Build final prompt: Description + Camera + Lighting + Style
176
+ final_prompt = description_part + camera_config + lighting_enhancement + style_enhancement
177
 
178
  # Clean up formatting
179
  final_prompt = _clean_prompt_formatting(final_prompt)
 
202
  # Clean up any remaining camera recommendations from the description
203
  description = re.sub(r'For this type of scene.*?shooting style would be.*?\.', '', description, flags=re.DOTALL)
204
  description = re.sub(r'I would recommend.*?aperture.*?\.', '', description, flags=re.DOTALL)
205
+ description = re.sub(r'Professional Context:.*?\.', '', description, flags=re.DOTALL)
206
+ description = re.sub(r'Cinematography context:.*?\.', '', description, flags=re.DOTALL)
207
 
208
+ # Remove numbered section residues
209
  description = re.sub(r'\s*\d+\.\s*,?\s*$', '', description)
210
  description = re.sub(r'\s*\d+\.\s*,?\s*', ' ', description)
211
 
212
  return description.strip()
213
 
214
 
215
+ def _detect_scene_from_description(description_lower: str) -> str:
216
+ """Enhanced scene detection from description with cinematography knowledge"""
217
+ scene_keywords = PROFESSIONAL_PHOTOGRAPHY_CONFIG.get("scene_detection_keywords", {})
218
+
219
+ # Score each scene type
220
+ scene_scores = {}
221
+ for scene_type, keywords in scene_keywords.items():
222
+ score = sum(1 for keyword in keywords if keyword in description_lower)
223
+ if score > 0:
224
+ scene_scores[scene_type] = score
225
+
226
+ # Additional cinematography-specific detection
227
+ if any(term in description_lower for term in ["film", "movie", "cinematic", "dramatic lighting", "anamorphic"]):
228
+ scene_scores["cinematic"] = scene_scores.get("cinematic", 0) + 2
229
+
230
+ if any(term in description_lower for term in ["studio", "controlled lighting", "professional portrait"]):
231
+ scene_scores["portrait"] = scene_scores.get("portrait", 0) + 2
232
+
233
+ # Return highest scoring scene type
234
+ if scene_scores:
235
+ return max(scene_scores.items(), key=lambda x: x[1])[0]
236
+ else:
237
+ return "default"
238
+
239
+
240
+ def _format_professional_camera_suggestion(bagel_camera: str, scene_type: str) -> str:
241
+ """Format BAGEL's camera suggestion with enhanced cinematography knowledge"""
242
  try:
 
243
  camera_text = bagel_camera.strip()
 
 
244
  camera_text = re.sub(r'^CAMERA_SETUP:\s*', '', camera_text)
245
 
246
+ # Enhanced extraction patterns for cinema equipment
247
+ cinema_patterns = {
248
+ 'camera': r'(ARRI [^,]+|RED [^,]+|Canon EOS [^,]+|Sony A[^,]+|Leica [^,]+|Hasselblad [^,]+|Phase One [^,]+)',
249
+ 'lens': r'(\d+mm[^,]*(?:anamorphic)?[^,]*|[^,]*(?:anamorphic|telephoto|wide-angle)[^,]*)',
250
  'aperture': r'(f/[\d.]+[^,]*)'
251
  }
252
 
253
  extracted_parts = []
254
+ for key, pattern in cinema_patterns.items():
 
255
  match = re.search(pattern, camera_text, re.IGNORECASE)
256
  if match:
257
  extracted_parts.append(match.group(1).strip())
258
 
259
  if extracted_parts:
 
260
  camera_info = ', '.join(extracted_parts)
261
+ # Add scene-specific enhancement
262
+ if scene_type == "cinematic":
263
+ return f", Shot on {camera_info}, cinematic photography"
264
+ elif scene_type == "portrait":
265
+ return f", Shot on {camera_info}, professional portrait photography"
 
266
  else:
267
+ return f", Shot on {camera_info}, professional photography"
268
+ else:
269
+ return _get_enhanced_camera_config(scene_type, camera_text.lower())
270
 
271
  except Exception as e:
272
+ logger.warning(f"Failed to format professional camera suggestion: {e}")
273
+ return _get_enhanced_camera_config(scene_type, "")
274
+
275
+
276
+ def _get_enhanced_camera_config(scene_type: str, description_lower: str) -> str:
277
+ """Get enhanced camera configuration with cinematography knowledge"""
278
+ # Enhanced camera configurations with cinema equipment
279
+ enhanced_configs = {
280
+ "cinematic": ", Shot on ARRI Alexa LF, 35mm anamorphic lens, cinematic photography",
281
+ "portrait": ", Shot on Canon EOS R5, 85mm f/1.4 lens at f/2.8, professional portrait photography",
282
+ "landscape": ", Shot on Phase One XT, 24-70mm f/4 lens at f/8, epic landscape photography",
283
+ "street": ", Shot on Leica M11, 35mm f/1.4 lens at f/2.8, documentary street photography",
284
+ "architectural": ", Shot on Canon EOS R5, 24-70mm f/2.8 lens at f/8, architectural photography",
285
+ "commercial": ", Shot on Hasselblad X2D 100C, 90mm f/2.5 lens, commercial photography"
286
+ }
287
+
288
+ # Use enhanced config if available, otherwise fall back to FLUX_RULES
289
+ if scene_type in enhanced_configs:
290
+ return enhanced_configs[scene_type]
291
+ elif scene_type in FLUX_RULES["camera_configs"]:
292
+ return FLUX_RULES["camera_configs"][scene_type]
293
  else:
294
  return FLUX_RULES["camera_configs"]["default"]
295
 
296
 
297
+ def _get_cinematography_lighting_enhancement(description_lower: str, camera_config: str, scene_type: str) -> str:
298
+ """Enhanced lighting with cinematography principles"""
299
+ # Don't add lighting if already mentioned
300
+ if any(term in description_lower for term in ["lighting", "lit", "illuminated"]) or 'lighting' in camera_config.lower():
301
  return ""
302
 
303
+ # Enhanced lighting based on scene type and cinematography knowledge
304
+ if scene_type == "cinematic":
305
+ if any(term in description_lower for term in ["dramatic", "moody", "dark"]):
306
+ return ", dramatic cinematic lighting with practical lights"
307
+ else:
308
+ return ", professional cinematic lighting"
309
+ elif scene_type == "portrait":
310
+ return ", professional studio lighting with subtle rim light"
311
+ elif "dramatic" in description_lower or "chaos" in description_lower:
312
  return FLUX_RULES["lighting_enhancements"]["dramatic"]
 
 
313
  else:
314
  return FLUX_RULES["lighting_enhancements"]["default"]
315
 
316
 
317
+ def _get_style_enhancement(scene_type: str, description_lower: str) -> str:
318
+ """Get style enhancement for multi-engine compatibility"""
319
+ style_enhancements = FLUX_RULES.get("style_enhancements", {})
320
+
321
+ if scene_type == "cinematic":
322
+ if "film grain" not in description_lower:
323
+ return ", " + style_enhancements.get("cinematic", "cinematic composition, film grain")
324
+ elif scene_type in ["portrait", "commercial"]:
325
+ return ", " + style_enhancements.get("photorealistic", "photorealistic, ultra-detailed")
326
+ elif "editorial" in description_lower:
327
+ return ", " + style_enhancements.get("editorial", "editorial photography style")
328
+
329
+ return ""
330
+
331
+
332
  def _clean_prompt_formatting(prompt: str) -> str:
333
  """Clean up prompt formatting"""
334
  if not prompt:
 
353
 
354
  def calculate_prompt_score(prompt: str, analysis_data: Optional[Dict[str, Any]] = None) -> Tuple[int, Dict[str, int]]:
355
  """
356
+ Calculate enhanced quality score with professional cinematography criteria
357
 
358
  Args:
359
  prompt: The prompt to score
360
+ analysis_data: Enhanced analysis data with cinematography context
361
 
362
  Returns:
363
  Tuple of (total_score, breakdown_dict)
364
  """
365
  if not prompt:
366
+ return 0, {"prompt_quality": 0, "technical_details": 0, "professional_cinematography": 0, "multi_engine_optimization": 0}
367
 
368
  breakdown = {}
369
 
370
+ # Enhanced Prompt Quality (0-25 points)
371
+ length_score = min(15, len(prompt) // 10) # Reward appropriate length
372
+ detail_score = min(10, len(prompt.split(',')) * 1.5) # Reward structured detail
373
+ breakdown["prompt_quality"] = int(length_score + detail_score)
374
 
375
+ # Technical Details with Cinematography Focus (0-25 points)
376
  tech_score = 0
377
+
378
+ # Cinema equipment (higher scores for professional gear)
379
+ cinema_equipment = ['ARRI', 'RED', 'Canon EOS R', 'Sony A1', 'Leica', 'Hasselblad', 'Phase One']
380
+ for equipment in cinema_equipment:
381
+ if equipment.lower() in prompt.lower():
382
+ tech_score += 6
383
+ break
384
+
385
+ # Lens specifications
386
+ if re.search(r'\d+mm.*f/[\d.]+', prompt):
387
+ tech_score += 5
388
+
389
+ # Anamorphic and specialized lenses
390
+ if 'anamorphic' in prompt.lower():
391
+ tech_score += 4
392
+
393
+ # Professional terminology
394
+ tech_keywords = ['shot on', 'lens', 'photography', 'lighting', 'cinematic']
395
  for keyword in tech_keywords:
396
  if keyword in prompt.lower():
397
+ tech_score += 2
398
 
399
+ # Bonus for BAGEL cinematography suggestions
400
  if analysis_data and analysis_data.get("has_camera_suggestion"):
401
+ tech_score += 8
402
 
403
  breakdown["technical_details"] = min(25, tech_score)
404
 
405
+ # Professional Cinematography (0-25 points) - NEW CATEGORY
406
+ cinema_score = 0
 
 
407
 
408
+ # Professional lighting techniques
409
+ lighting_terms = ['cinematic lighting', 'dramatic lighting', 'studio lighting', 'rim light', 'practical lights']
410
+ cinema_score += sum(3 for term in lighting_terms if term in prompt.lower())
411
 
412
+ # Composition techniques
413
+ composition_terms = ['composition', 'framing', 'depth of field', 'bokeh', 'rule of thirds']
414
+ cinema_score += sum(2 for term in composition_terms if term in prompt.lower())
415
+
416
+ # Cinematography style elements
417
+ style_terms = ['film grain', 'anamorphic', 'telephoto compression', 'wide-angle']
418
+ cinema_score += sum(3 for term in style_terms if term in prompt.lower())
419
+
420
+ # Professional context bonus
421
+ if analysis_data and analysis_data.get("cinematography_context_applied"):
422
+ cinema_score += 5
423
+
424
+ breakdown["professional_cinematography"] = min(25, cinema_score)
425
+
426
+ # Multi-Engine Optimization (0-25 points)
427
+ optimization_score = 0
428
+
429
+ # Check for multi-engine compatible elements
430
+ multi_engine_terms = ['photorealistic', 'ultra-detailed', 'professional photography', 'cinematic']
431
+ optimization_score += sum(3 for term in multi_engine_terms if term in prompt.lower())
432
+
433
+ # Technical specifications for generation
434
+ if any(camera in prompt for camera in FLUX_RULES["camera_configs"].values()):
435
+ optimization_score += 5
436
 
437
+ # Lighting configuration
438
  if any(lighting in prompt for lighting in FLUX_RULES["lighting_enhancements"].values()):
439
+ optimization_score += 4
440
 
441
+ # Style enhancements
442
+ if any(style in prompt for style in FLUX_RULES.get("style_enhancements", {}).values()):
443
+ optimization_score += 3
444
+
445
+ breakdown["multi_engine_optimization"] = min(25, optimization_score)
446
 
447
+ # Calculate total with enhanced weighting
448
  total_score = sum(breakdown.values())
449
 
450
  return total_score, breakdown
451
 
452
 
453
+ def calculate_professional_enhanced_score(prompt: str, analysis_data: Optional[Dict[str, Any]] = None) -> Tuple[int, Dict[str, int]]:
454
+ """
455
+ Enhanced scoring with professional cinematography criteria
456
+
457
+ Args:
458
+ prompt: The prompt to score
459
+ analysis_data: Analysis data with cinematography context
460
+
461
+ Returns:
462
+ Tuple of (total_score, breakdown_dict)
463
+ """
464
+ # Use the enhanced scoring system
465
+ return calculate_prompt_score(prompt, analysis_data)
466
+
467
+
468
  def get_score_grade(score: int) -> Dict[str, str]:
469
  """
470
  Get grade information for a score
 
487
 
488
  def format_analysis_report(analysis_data: Dict[str, Any], processing_time: float) -> str:
489
  """
490
+ Format analysis data into a readable report with cinematography insights
491
 
492
  Args:
493
+ analysis_data: Analysis results with cinematography context
494
  processing_time: Time taken for processing
495
 
496
  Returns:
497
  Formatted markdown report
498
  """
499
+ model_used = analysis_data.get("model", "Unknown")
500
  prompt_length = len(analysis_data.get("prompt", ""))
501
+ has_cinema_context = analysis_data.get("cinematography_context_applied", False)
502
+ scene_type = analysis_data.get("scene_type", "general")
503
 
504
+ report = f"""**🎬 PHRAMER AI ANALYSIS COMPLETE**
505
  **Model:** {model_used} β€’ **Time:** {processing_time:.1f}s β€’ **Length:** {prompt_length} chars
506
 
507
+ **πŸ“Š CINEMATOGRAPHY ANALYSIS:**
508
+ **Scene Type:** {scene_type.replace('_', ' ').title()}
509
+ **Professional Context:** {'βœ… Applied' if has_cinema_context else '❌ Not Applied'}
510
 
511
  **🎯 OPTIMIZATIONS APPLIED:**
512
+ βœ… Professional camera configuration
513
+ βœ… Cinematography lighting setup
514
+ βœ… Technical specifications
515
+ βœ… Multi-engine compatibility
516
+ βœ… Cinema-quality enhancement
517
 
518
+ **⚑ Powered by Pariente AI for MIA TV Series**"""
519
 
520
  return report
521
 
 
557
  return text[:max_length-3] + "..."
558
 
559
 
560
+ def enhance_prompt_with_cinematography_knowledge(original_prompt: str, scene_type: str = "default") -> str:
561
+ """
562
+ Enhance prompt with professional cinematography knowledge
563
+
564
+ Args:
565
+ original_prompt: Base prompt text
566
+ scene_type: Detected scene type
567
+
568
+ Returns:
569
+ Enhanced prompt with cinematography context
570
+ """
571
+ try:
572
+ # Import here to avoid circular imports
573
+ from professional_photography import enhance_flux_prompt_with_professional_knowledge
574
+
575
+ # Apply professional cinematography enhancement
576
+ enhanced = enhance_flux_prompt_with_professional_knowledge(original_prompt)
577
+
578
+ logger.info(f"Enhanced prompt with cinematography knowledge for {scene_type} scene")
579
+ return enhanced
580
+
581
+ except ImportError:
582
+ logger.warning("Professional photography module not available")
583
+ return original_prompt
584
+ except Exception as e:
585
+ logger.warning(f"Cinematography enhancement failed: {e}")
586
+ return original_prompt
587
+
588
+
589
  # Export main functions
590
  __all__ = [
591
  "setup_logging",
 
594
  "clean_memory",
595
  "apply_flux_rules",
596
  "calculate_prompt_score",
597
+ "calculate_professional_enhanced_score",
598
  "get_score_grade",
599
  "format_analysis_report",
600
  "safe_execute",
601
+ "truncate_text",
602
+ "enhance_prompt_with_cinematography_knowledge",
603
+ "detect_scene_type_from_analysis"
604
  ]