Malaji71 commited on
Commit
b2d5c27
·
verified ·
1 Parent(s): 6be61fc

Upload 6 files

Browse files
interfaz_sara_directo_ui.py CHANGED
@@ -7,10 +7,10 @@
7
  # ✅ Event handlers solo para sistema técnico
8
 
9
  import gradio as gr
10
- from sara_v3_interfaz_core import sara_optimized
11
 
12
  # Importar funciones core SOLO GEN-4
13
  from interfaz_sara_directo_core import (
 
14
  analyze_image_step1,
15
  generate_prompts_step2,
16
  update_system_info,
 
7
  # ✅ Event handlers solo para sistema técnico
8
 
9
  import gradio as gr
 
10
 
11
  # Importar funciones core SOLO GEN-4
12
  from interfaz_sara_directo_core import (
13
+ sara_optimized,
14
  analyze_image_step1,
15
  generate_prompts_step2,
16
  update_system_info,
sara_v3_parte_4_gen4_carga.py CHANGED
@@ -1,7 +1,7 @@
1
- # PARTE 4-GEN4 CARGA: MOTOR PRINCIPAL SARA TÉCNICO CON PARSER ARREGLADO
2
  # Sistema completo de carga y gestión del modelo Gen-4 con parser corregido
3
  # Usa HuggingFaceH4/zephyr-7b-beta con reglas inteligentes y extracción optimizada
4
- # ARREGLADO: Parser menos restrictivo, extracción mejorada, un prompt por nivel
5
 
6
  import time
7
  import re
@@ -117,8 +117,8 @@ def generate_technical_prompts_gen4(image_description: str, user_idea: str = "")
117
  # Log de la respuesta raw para debug
118
  sara_v3_state.logger.info(f"🔍 Respuesta Gen-4 raw: {generated_text[:200]}...")
119
 
120
- # Parsear prompts técnicos con extracción mejorada
121
- prompts = _parse_technical_response_optimized(generated_text)
122
 
123
  generation_time = time.time() - start_time
124
 
@@ -144,220 +144,267 @@ def generate_technical_prompts_gen4(image_description: str, user_idea: str = "")
144
  'method': 'fallback_technical'
145
  }
146
 
147
- def _parse_technical_response_optimized(response: str) -> dict:
148
  """
149
- Parser OPTIMIZADO para respuestas técnicas Gen-4
150
- ARREGLADO: Menos restrictivo, mejor extracción, un prompt por nivel
151
  """
152
 
153
  if not response.strip():
154
  sara_v3_state.logger.warning("⚠️ Respuesta vacía de Gen-4")
155
  return _generate_fallback_prompts_from_empty()
156
 
157
- sara_v3_state.logger.info("📝 Parseando respuesta Gen-4 con extracción optimizada...")
158
 
159
- # Limpiar respuesta completa primero
160
- cleaned_response = _clean_full_response(response)
161
 
162
- # Estrategia 1: Dividir por párrafos dobles
163
- sections = [s.strip() for s in cleaned_response.split('\n\n') if s.strip() and len(s.strip()) > 20]
164
-
165
- # Estrategia 2: Si no hay párrafos, dividir por líneas
166
- if len(sections) < 2:
167
- lines = [l.strip() for l in cleaned_response.split('\n') if l.strip() and len(l.strip()) > 20]
168
- sections = lines
169
 
170
- # Estrategia 3: Si aún no hay suficiente, dividir por puntos
171
- if len(sections) < 2:
172
- sentences = [s.strip() + '.' for s in cleaned_response.split('.') if s.strip() and len(s.strip()) > 20]
173
- sections = sentences
174
-
175
- # Limpiar y validar cada sección
176
- valid_prompts = []
177
  for section in sections:
178
- cleaned_section = _clean_prompt_aggressive(section)
179
- if _is_valid_prompt_relaxed(cleaned_section):
180
- valid_prompts.append(cleaned_section)
181
 
182
- sara_v3_state.logger.info(f"🧹 Extraídos {len(valid_prompts)} prompts válidos de {len(sections)} secciones")
183
 
184
- # Asignar prompts a niveles - UN PROMPT POR NIVEL
185
  levels = ['basic', 'intermediate', 'advanced', 'experimental']
186
  final_prompts = {}
187
 
188
  for i, level in enumerate(levels):
189
- if i < len(valid_prompts):
190
- # Usar prompt extraído
191
- final_prompts[level] = valid_prompts[i]
192
  else:
193
- # Generar prompt faltante basado en los existentes
194
- final_prompts[level] = _generate_level_prompt(level, valid_prompts, cleaned_response)
195
 
196
- # Log final para debug
197
  for level, prompt in final_prompts.items():
198
  sara_v3_state.logger.info(f"📝 {level.upper()}: {prompt[:60]}...")
199
 
200
  return final_prompts
201
 
202
- def _clean_full_response(response: str) -> str:
203
- """Limpieza inicial de la respuesta completa"""
204
-
205
- # Remover texto introductorio común
206
- intro_patterns = [
207
- r'^Based on.*?here are.*?:',
208
- r'^Here are.*?prompts.*?:',
209
- r'^.*?Generate.*?prompts.*?:',
210
- r'^.*?four prompts.*?:',
211
- r'^.*?increasing complexity.*?:'
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
212
  ]
213
 
214
- for pattern in intro_patterns:
 
 
 
215
  response = re.sub(pattern, '', response, flags=re.IGNORECASE | re.MULTILINE)
216
 
217
- # Limpiar saltos de línea excesivos
218
  response = re.sub(r'\n{3,}', '\n\n', response)
 
219
  response = response.strip()
220
 
 
 
221
  return response
222
 
223
- def _clean_prompt_aggressive(text: str) -> str:
224
  """
225
- Limpieza AGRESIVA pero inteligente de prompts individuales
226
- ARREGLADO: Menos destructiva, preserva contenido válido
227
  """
228
 
229
- if not text or len(text) < 10:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
230
  return ""
231
 
232
  original_text = text
233
 
234
- # Remover etiquetas obvias pero conservar contenido
235
- patterns_to_remove = [
236
- r'^\d+\.\s*', # "1. "
237
- r'^Basic:\s*', # "Basic: "
238
- r'^Intermediate:\s*', # "Intermediate: "
239
- r'^Advanced:\s*', # "Advanced: "
240
- r'^Experimental:\s*', # "Experimental: "
241
- r'^Prompt\s*\d+:\s*', # "Prompt 1: "
242
- r'^Level\s*\d+:\s*', # "Level 1: "
243
- r'^[\-\*\•]\s*', # "- ", "* ", "• "
 
 
 
 
 
244
  ]
245
 
246
- for pattern in patterns_to_remove:
 
247
  text = re.sub(pattern, '', text, flags=re.IGNORECASE)
248
 
249
- # Limpiar comillas mal formadas
250
- text = re.sub(r'^["\']|["\']$', '', text)
251
- text = re.sub(r'["\']([^"\']*)["\']', r'\1', text)
252
-
253
- # Normalizar espacios
254
  text = re.sub(r'\s+', ' ', text)
255
  text = text.strip()
256
 
257
- # Si se vació demasiado, intentar extracción suave
258
- if len(text) < 15 and len(original_text) > 30:
 
 
 
 
 
 
 
 
 
259
  # Buscar contenido después de dos puntos
260
  if ':' in original_text:
261
  parts = original_text.split(':', 1)
262
- if len(parts) > 1 and len(parts[1].strip()) > 15:
263
  text = parts[1].strip()
264
  text = re.sub(r'^["\'\s]+|["\'\s]+$', '', text)
265
-
266
- # Asegurar capitalización y terminación
267
- if text and len(text) > 10:
268
- if not text[0].isupper():
269
- text = text[0].upper() + text[1:]
270
-
271
- if not text.endswith(('.', '!', '?')):
272
- text += '.'
273
 
274
  return text.strip()
275
 
276
- def _is_valid_prompt_relaxed(text: str) -> bool:
277
  """
278
- Validación RELAJADA de prompts - ARREGLADO: Menos restrictiva
279
  """
280
 
281
- if not text or len(text) < 10:
282
  return False
283
 
284
- # Patrones que definitivamente NO son prompts (muy restrictivo)
285
- definitely_invalid = [
286
- r'^(Here are|Based on|Generate|Create)',
287
- r'^(BASIC|INTERMEDIATE|ADVANCED|EXPERIMENTAL)[:]\s*$',
288
- r'^\d+\.\s*$',
289
- r'^[Pp]rompt\s*\d+\s*[:]\s*$'
 
290
  ]
291
 
292
- for pattern in definitely_invalid:
293
- if re.match(pattern, text, re.IGNORECASE):
294
  return False
295
 
296
- # Debe tener al menos UNA palabra clave de video IA (muy permisivo)
297
  video_keywords = [
298
  'camera', 'shot', 'movement', 'lighting', 'frame', 'focus',
299
  'moves', 'tracks', 'follows', 'reveals', 'transitions',
300
- 'smoothly', 'slowly', 'gently', 'steadily', 'woman', 'man',
301
- 'person', 'subject', 'dolly', 'crane', 'steadicam', 'time-lapse',
302
- 'cinematic', 'dramatic', 'golden', 'natural', 'professional'
303
  ]
304
 
305
  text_lower = text.lower()
306
- keyword_count = sum(1 for keyword in video_keywords if keyword in text_lower)
307
-
308
- # Muy permisivo: solo necesita 1 palabra clave
309
- has_keywords = keyword_count >= 1
310
-
311
- # Debe tener longitud razonable
312
- reasonable_length = 10 <= len(text) <= 1000
313
 
314
- # Debe tener al menos 3 palabras
315
- has_words = len(text.split()) >= 3
316
-
317
- return has_keywords and reasonable_length and has_words
318
 
319
- def _generate_level_prompt(level: str, existing_prompts: list, original_response: str) -> str:
320
  """
321
- Generar prompt para nivel específico basado en prompts existentes
322
- ARREGLADO: Mejor integración con prompts reales extraídos
323
  """
324
 
325
- # Si hay prompts existentes, usar como base
 
 
 
 
 
 
 
 
 
 
 
326
  if existing_prompts:
327
  base_prompt = existing_prompts[0]
328
 
329
- # Extraer elementos del prompt base
330
  base_lower = base_prompt.lower()
331
-
332
  if 'woman' in base_lower:
333
- subject = "Woman"
334
  elif 'man' in base_lower:
335
- subject = "Man"
336
  elif 'person' in base_lower:
337
- subject = "Person"
338
  else:
339
- subject = "Subject"
340
-
341
- # Generar prompts escalados basados en el contenido real
342
- level_templates = {
343
- 'basic': f"Camera tracks {subject.lower()} with steady movement, natural lighting creates professional framing.",
344
-
345
- 'intermediate': f"Steadicam follows {subject.lower()} with controlled precision, enhanced lighting creates cinematic depth and visual storytelling.",
346
-
347
- 'advanced': f"Sophisticated crane shot reveals {subject.lower()} through complex staging techniques, dramatic lighting transitions with color grading create compelling visual narrative using advanced cinematographic elements.",
348
-
349
- 'experimental': f"Time-lapse sequences transform conventional reality as {subject.lower()} transcends physical boundaries through innovative camera approaches and experimental lighting techniques."
350
- }
351
 
352
- return level_templates.get(level, base_prompt)
 
 
 
353
 
354
- # Fallback si no hay prompts válidos extraídos
355
- return f"Camera moves smoothly while subject performs natural movement, professional lighting creates cinematic atmosphere."
356
 
357
  def _generate_fallback_prompts_from_empty() -> dict:
358
- """Generar prompts cuando la respuesta está completamente vacía"""
359
 
360
- sara_v3_state.logger.warning("⚠️ Generando prompts desde respuesta vacía")
361
 
362
  return {
363
  'basic': "Camera tracks steadily while subject moves naturally, professional lighting creates clean visual foundation.",
@@ -367,7 +414,7 @@ def _generate_fallback_prompts_from_empty() -> dict:
367
  }
368
 
369
  def _generate_technical_fallback_gen4(image_description: str, user_idea: str = "") -> dict:
370
- """Fallback técnico mejorado para Gen-4"""
371
 
372
  sara_v3_state.logger.info("🔄 Generando fallback técnico Gen-4...")
373
 
@@ -387,7 +434,6 @@ def _generate_technical_fallback_gen4(image_description: str, user_idea: str = "
387
 
388
  # Procesar e integrar user_idea si existe
389
  if user_idea.strip():
390
- # Limpiar user_idea
391
  clean_idea = user_idea.strip()
392
 
393
  # Remover artículos en español
@@ -406,9 +452,7 @@ def _generate_technical_fallback_gen4(image_description: str, user_idea: str = "
406
  'se acerca': 'approaches',
407
  'lentamente': 'slowly',
408
  'rápidamente': 'quickly',
409
- 'suavemente': 'gently',
410
- 'movimiento': 'movement',
411
- 'iluminación': 'lighting'
412
  }
413
 
414
  for spanish, english in translation_map.items():
@@ -418,7 +462,7 @@ def _generate_technical_fallback_gen4(image_description: str, user_idea: str = "
418
  else:
419
  action_base = "moves naturally"
420
 
421
- # Generar prompts técnicos mejorados con integración real
422
  return {
423
  'basic': f"{subject} {action_base} while camera tracks steadily, {clean_description}, professional lighting setup creates clean visual foundation.",
424
 
@@ -464,7 +508,7 @@ def get_gen4_info() -> dict:
464
  info = {
465
  'status': get_gen4_status(),
466
  'model': 'HuggingFaceH4/zephyr-7b-beta',
467
- 'system': 'Reglas Inteligentes + Parser Optimizado'
468
  }
469
 
470
  if hasattr(sara_v3_state, 'gen4_load_time'):
@@ -479,35 +523,9 @@ def get_gen4_info() -> dict:
479
 
480
  return info
481
 
482
- # Función principal para integración con sistema existente
483
- def integrate_gen4_with_existing_system():
484
- """Integrar Gen-4 con sistema SARA existente sin romper compatibilidad"""
485
-
486
- sara_v3_state.logger.info("🔗 Integrando Gen-4 con sistema existente...")
487
-
488
- # Verificar que sistema actual esté disponible
489
- try:
490
- from sara_v3_parte_4 import is_sara_ready
491
-
492
- if is_sara_ready():
493
- sara_v3_state.logger.info("✅ Sistema poético SARA-v2 disponible")
494
- else:
495
- sara_v3_state.logger.info("⚠️ Sistema poético no disponible")
496
- except ImportError:
497
- sara_v3_state.logger.info("⚠️ Sistema poético no disponible")
498
-
499
- if is_gen4_ready():
500
- sara_v3_state.logger.info("✅ Sistema técnico Gen-4 disponible")
501
- else:
502
- sara_v3_state.logger.info("⚠️ Sistema técnico no disponible")
503
-
504
- # Marcar integración completada
505
- sara_v3_state.dual_system_ready = True
506
- sara_v3_state.logger.info("🎯 Sistema dual SARA disponible: Poético + Técnico")
507
-
508
  if __name__ == "__main__":
509
- # Test del sistema Gen-4
510
- print("🧪 Probando carga SARA Gen-4...")
511
 
512
  success = load_sara_gen4_complete()
513
 
@@ -524,25 +542,23 @@ if __name__ == "__main__":
524
  if test_result['success']:
525
  print("🎬 Test generación exitoso:")
526
  for level, prompt in test_result['prompts'].items():
527
- print(f" {level.upper()}: {prompt[:60]}...")
528
  else:
529
  print(f"❌ Test generación falló: {test_result['error']}")
530
  else:
531
  print("❌ Error cargando Gen-4")
532
 
533
- print("✅ Test Gen-4 completado")
534
 
535
- # FINAL SARA V3 PARTE 4-GEN4 CARGA: PARSER COMPLETAMENTE ARREGLADO
536
  #
537
  # CORRECCIONES IMPLEMENTADAS:
538
- # ✅ _parse_technical_response_optimized() - Parser completamente reescrito
539
- # ✅ _clean_prompt_aggressive() - Limpieza menos destructiva
540
- # ✅ _is_valid_prompt_relaxed() - Validación mucho menos restrictiva
541
- # ✅ _generate_level_prompt() - Generación mejorada basada en contenido real
542
- # ✅ _clean_full_response() - Limpieza inicial de respuesta completa
543
- # ✅ _generate_fallback_prompts_from_empty() - Manejo de respuestas vacías
544
- # ✅ _generate_technical_fallback_gen4() - Fallback mejorado con traducción
545
- # ✅ Logging de debug para diagnosticar problemas de parsing
546
- # ✅ Estrategias múltiples de extracción (párrafos, líneas, oraciones)
547
- # ✅ Un prompt limpio por nivel garantizado
548
- # ✅ Preservación de contenido válido durante limpieza
 
1
+ # PARTE COMPLETA: SARA V3 PARTE 4-GEN4 CARGA - PARSER COMPLETAMENTE ARREGLADO
2
  # Sistema completo de carga y gestión del modelo Gen-4 con parser corregido
3
  # Usa HuggingFaceH4/zephyr-7b-beta con reglas inteligentes y extracción optimizada
4
+ # ARREGLADO: Parser agresivo que ELIMINA todas las etiquetas técnicas
5
 
6
  import time
7
  import re
 
117
  # Log de la respuesta raw para debug
118
  sara_v3_state.logger.info(f"🔍 Respuesta Gen-4 raw: {generated_text[:200]}...")
119
 
120
+ # Parsear prompts técnicos con extracción SUPER AGRESIVA
121
+ prompts = _parse_technical_response_super_aggressive(generated_text)
122
 
123
  generation_time = time.time() - start_time
124
 
 
144
  'method': 'fallback_technical'
145
  }
146
 
147
+ def _parse_technical_response_super_aggressive(response: str) -> dict:
148
  """
149
+ Parser SUPER AGRESIVO para respuestas técnicas Gen-4
150
+ ARREGLADO: Elimina TODAS las etiquetas técnicas automáticamente
151
  """
152
 
153
  if not response.strip():
154
  sara_v3_state.logger.warning("⚠️ Respuesta vacía de Gen-4")
155
  return _generate_fallback_prompts_from_empty()
156
 
157
+ sara_v3_state.logger.info("📝 Parseando respuesta Gen-4 con LIMPIEZA SUPER AGRESIVA...")
158
 
159
+ # PASO 1: Limpiar respuesta completa de etiquetas obvias
160
+ cleaned_response = _super_aggressive_cleaning(response)
161
 
162
+ # PASO 2: Dividir en secciones
163
+ sections = _extract_sections_multiple_strategies(cleaned_response)
 
 
 
 
 
164
 
165
+ # PASO 3: Limpiar cada sección individualmente y ELIMINAR ETIQUETAS
166
+ clean_prompts = []
 
 
 
 
 
167
  for section in sections:
168
+ cleaned_prompt = _eliminate_all_technical_labels(section)
169
+ if _is_valid_clean_prompt(cleaned_prompt):
170
+ clean_prompts.append(cleaned_prompt)
171
 
172
+ sara_v3_state.logger.info(f"🧹 Extraídos {len(clean_prompts)} prompts LIMPIOS de {len(sections)} secciones")
173
 
174
+ # PASO 4: Asignar a niveles - UN PROMPT LIMPIO POR NIVEL
175
  levels = ['basic', 'intermediate', 'advanced', 'experimental']
176
  final_prompts = {}
177
 
178
  for i, level in enumerate(levels):
179
+ if i < len(clean_prompts):
180
+ # Usar prompt limpio extraído
181
+ final_prompts[level] = clean_prompts[i]
182
  else:
183
+ # Generar prompt faltante sin etiquetas
184
+ final_prompts[level] = _generate_clean_level_prompt(level, clean_prompts, cleaned_response)
185
 
186
+ # Log final para verificar limpieza
187
  for level, prompt in final_prompts.items():
188
  sara_v3_state.logger.info(f"📝 {level.upper()}: {prompt[:60]}...")
189
 
190
  return final_prompts
191
 
192
+ def _super_aggressive_cleaning(response: str) -> str:
193
+ """
194
+ Limpieza SUPER AGRESIVA de etiquetas técnicas de la respuesta completa
195
+ ARREGLADO: Elimina TODO lo que parezca etiqueta técnica
196
+ """
197
+
198
+ # Lista completa de patrones a eliminar AGRESIVAMENTE
199
+ aggressive_patterns = [
200
+ # Patrones específicos que vimos en los logs
201
+ r'Prompt\s*\d+\s*\([^)]+\):\s*', # "Prompt 1 (Basic): "
202
+ r'Prompt\s*\d+\s*\(.*?\):\s*', # "Prompt 1 (cualquier cosa): "
203
+ r'Prompt\s*\d+:\s*', # "Prompt 1: "
204
+
205
+ # Patrones generales de etiquetas
206
+ r'^\d+\.\s*', # "1. "
207
+ r'^Basic:\s*', # "Basic: "
208
+ r'^Intermediate:\s*', # "Intermediate: "
209
+ r'^Advanced:\s*', # "Advanced: "
210
+ r'^Experimental:\s*', # "Experimental: "
211
+ r'^Level\s*\d+:\s*', # "Level 1: "
212
+ r'^[\-\*\•]\s*', # "- ", "* ", "• "
213
+
214
+ # Patrones más agresivos
215
+ r'Based on.*?here are.*?:', # Textos introductorios
216
+ r'Here are.*?prompts.*?:', # "Here are the prompts:"
217
+ r'Generate.*?prompts.*?:', # "Generate 4 prompts:"
218
+ r'.*?four prompts.*?:', # "Here are four prompts:"
219
+ r'.*?increasing complexity.*?:', # "with increasing complexity:"
220
+
221
+ # Eliminar numeración al inicio
222
+ r'^\s*\d+\)\s*', # "1) "
223
+ r'^\s*\(\d+\)\s*', # "(1) "
224
+
225
+ # Eliminar comillas mal formadas
226
+ r'^["\']|["\']$', # Comillas al inicio/final
227
  ]
228
 
229
+ original_response = response
230
+
231
+ # Aplicar todos los patrones de limpieza
232
+ for pattern in aggressive_patterns:
233
  response = re.sub(pattern, '', response, flags=re.IGNORECASE | re.MULTILINE)
234
 
235
+ # Limpiar espacios múltiples y saltos de línea excesivos
236
  response = re.sub(r'\n{3,}', '\n\n', response)
237
+ response = re.sub(r'\s+', ' ', response)
238
  response = response.strip()
239
 
240
+ sara_v3_state.logger.info(f"🧹 Limpieza agresiva: {len(original_response)} → {len(response)} caracteres")
241
+
242
  return response
243
 
244
+ def _extract_sections_multiple_strategies(text: str) -> list:
245
  """
246
+ Extraer secciones usando múltiples estrategias
 
247
  """
248
 
249
+ # Estrategia 1: Dividir por párrafos dobles
250
+ sections = [s.strip() for s in text.split('\n\n') if s.strip() and len(s.strip()) > 15]
251
+
252
+ if len(sections) >= 4:
253
+ return sections[:4] # Tomar los primeros 4
254
+
255
+ # Estrategia 2: Dividir por líneas individuales
256
+ if len(sections) < 4:
257
+ lines = [l.strip() for l in text.split('\n') if l.strip() and len(l.strip()) > 15]
258
+ if len(lines) >= 4:
259
+ return lines[:4]
260
+ sections.extend(lines)
261
+
262
+ # Estrategia 3: Dividir por puntos
263
+ if len(sections) < 4:
264
+ sentences = [s.strip() + '.' for s in text.split('.') if s.strip() and len(s.strip()) > 15]
265
+ sections.extend(sentences)
266
+
267
+ # Retornar al menos 4 secciones (rellenar si es necesario)
268
+ while len(sections) < 4:
269
+ sections.append("Camera moves smoothly while subject performs natural action, professional lighting creates cinematic atmosphere.")
270
+
271
+ return sections[:4]
272
+
273
+ def _eliminate_all_technical_labels(text: str) -> str:
274
+ """
275
+ Eliminar TODAS las etiquetas técnicas de un prompt individual
276
+ ARREGLADO: Más agresivo con la limpieza
277
+ """
278
+
279
+ if not text or len(text) < 5:
280
  return ""
281
 
282
  original_text = text
283
 
284
+ # Patrones específicos para eliminar etiquetas restantes
285
+ label_elimination_patterns = [
286
+ r'^Prompt\s*\d+\s*\([^)]+\):\s*', # "Prompt 1 (Basic): "
287
+ r'^Prompt\s*\d+\s*\(.*?\):\s*', # "Prompt 1 (...): "
288
+ r'^Prompt\s*\d+:\s*', # "Prompt 1: "
289
+ r'^\d+\.\s*Basic:\s*', # "1. Basic: "
290
+ r'^\d+\.\s*Intermediate:\s*', # "2. Intermediate: "
291
+ r'^\d+\.\s*Advanced:\s*', # "3. Advanced: "
292
+ r'^\d+\.\s*Experimental:\s*', # "4. Experimental: "
293
+ r'^Basic\s*Level:\s*', # "Basic Level: "
294
+ r'^Intermediate\s*Level:\s*', # "Intermediate Level: "
295
+ r'^Advanced\s*Level:\s*', # "Advanced Level: "
296
+ r'^Experimental\s*Level:\s*', # "Experimental Level: "
297
+ r'^\d+\.\s*', # "1. ", "2. ", etc.
298
+ r'^[\-\*\•]\s*', # "- ", "* ", "• "
299
  ]
300
 
301
+ # Aplicar limpieza de etiquetas
302
+ for pattern in label_elimination_patterns:
303
  text = re.sub(pattern, '', text, flags=re.IGNORECASE)
304
 
305
+ # Limpiar comillas y espacios
306
+ text = re.sub(r'^["\'\s]+|["\'\s]+$', '', text)
 
 
 
307
  text = re.sub(r'\s+', ' ', text)
308
  text = text.strip()
309
 
310
+ # Asegurar capitalización y terminación
311
+ if text and len(text) > 5:
312
+ # Capitalizar primera letra
313
+ text = text[0].upper() + text[1:] if len(text) > 1 else text.upper()
314
+
315
+ # Asegurar terminación con punto
316
+ if not text.endswith(('.', '!', '?')):
317
+ text += '.'
318
+
319
+ # Si se vació demasiado, intentar recuperar contenido útil
320
+ if len(text) < 10 and len(original_text) > 20:
321
  # Buscar contenido después de dos puntos
322
  if ':' in original_text:
323
  parts = original_text.split(':', 1)
324
+ if len(parts) > 1 and len(parts[1].strip()) > 10:
325
  text = parts[1].strip()
326
  text = re.sub(r'^["\'\s]+|["\'\s]+$', '', text)
327
+ if text and not text.endswith(('.', '!', '?')):
328
+ text += '.'
 
 
 
 
 
 
329
 
330
  return text.strip()
331
 
332
+ def _is_valid_clean_prompt(text: str) -> bool:
333
  """
334
+ Validación PERMISIVA de prompts limpios
335
  """
336
 
337
+ if not text or len(text) < 8:
338
  return False
339
 
340
+ # NO debe contener etiquetas técnicas residuales
341
+ bad_patterns = [
342
+ r'Prompt\s*\d+',
343
+ r'Basic:|Intermediate:|Advanced:|Experimental:',
344
+ r'Level\s*\d+',
345
+ r'^\d+\.',
346
+ r'^[\-\*\•]'
347
  ]
348
 
349
+ for pattern in bad_patterns:
350
+ if re.search(pattern, text, re.IGNORECASE):
351
  return False
352
 
353
+ # Debe tener al menos alguna palabra relacionada con video
354
  video_keywords = [
355
  'camera', 'shot', 'movement', 'lighting', 'frame', 'focus',
356
  'moves', 'tracks', 'follows', 'reveals', 'transitions',
357
+ 'smoothly', 'slowly', 'gently', 'steadily', 'subject',
358
+ 'cinematic', 'dramatic', 'natural', 'professional'
 
359
  ]
360
 
361
  text_lower = text.lower()
362
+ has_video_keyword = any(keyword in text_lower for keyword in video_keywords)
 
 
 
 
 
 
363
 
364
+ return has_video_keyword and len(text.split()) >= 5
 
 
 
365
 
366
+ def _generate_clean_level_prompt(level: str, existing_prompts: list, original_response: str) -> str:
367
  """
368
+ Generar prompt limpio para nivel específico SIN etiquetas técnicas
 
369
  """
370
 
371
+ # Templates limpios sin etiquetas
372
+ clean_templates = {
373
+ 'basic': "Camera tracks steadily while subject moves naturally, professional lighting creates clean visual foundation.",
374
+
375
+ 'intermediate': "Steadicam follows subject with controlled movement, enhanced lighting creates cinematic depth and atmospheric storytelling.",
376
+
377
+ 'advanced': "Sophisticated camera work employs complex staging techniques, dramatic lighting transitions with color grading create compelling visual narrative using advanced cinematographic elements.",
378
+
379
+ 'experimental': "Time-lapse sequences transform conventional reality through innovative camera approaches, experimental lighting techniques create transcendent visual poetry."
380
+ }
381
+
382
+ # Si hay prompts existentes, intentar extrapolar el contenido
383
  if existing_prompts:
384
  base_prompt = existing_prompts[0]
385
 
386
+ # Extraer sujeto del prompt base
387
  base_lower = base_prompt.lower()
 
388
  if 'woman' in base_lower:
389
+ subject = "woman"
390
  elif 'man' in base_lower:
391
+ subject = "man"
392
  elif 'person' in base_lower:
393
+ subject = "person"
394
  else:
395
+ subject = "subject"
 
 
 
 
 
 
 
 
 
 
 
396
 
397
+ # Personalizar template con el sujeto
398
+ template = clean_templates.get(level, clean_templates['basic'])
399
+ personalized = template.replace('subject', subject)
400
+ return personalized
401
 
402
+ return clean_templates.get(level, clean_templates['basic'])
 
403
 
404
  def _generate_fallback_prompts_from_empty() -> dict:
405
+ """Generar prompts limpios cuando la respuesta está vacía"""
406
 
407
+ sara_v3_state.logger.warning("⚠️ Generando prompts limpios desde respuesta vacía")
408
 
409
  return {
410
  'basic': "Camera tracks steadily while subject moves naturally, professional lighting creates clean visual foundation.",
 
414
  }
415
 
416
  def _generate_technical_fallback_gen4(image_description: str, user_idea: str = "") -> dict:
417
+ """Fallback técnico mejorado para Gen-4 SIN etiquetas"""
418
 
419
  sara_v3_state.logger.info("🔄 Generando fallback técnico Gen-4...")
420
 
 
434
 
435
  # Procesar e integrar user_idea si existe
436
  if user_idea.strip():
 
437
  clean_idea = user_idea.strip()
438
 
439
  # Remover artículos en español
 
452
  'se acerca': 'approaches',
453
  'lentamente': 'slowly',
454
  'rápidamente': 'quickly',
455
+ 'suavemente': 'gently'
 
 
456
  }
457
 
458
  for spanish, english in translation_map.items():
 
462
  else:
463
  action_base = "moves naturally"
464
 
465
+ # Generar prompts técnicos LIMPIOS sin etiquetas
466
  return {
467
  'basic': f"{subject} {action_base} while camera tracks steadily, {clean_description}, professional lighting setup creates clean visual foundation.",
468
 
 
508
  info = {
509
  'status': get_gen4_status(),
510
  'model': 'HuggingFaceH4/zephyr-7b-beta',
511
+ 'system': 'Reglas Inteligentes + Parser SUPER AGRESIVO'
512
  }
513
 
514
  if hasattr(sara_v3_state, 'gen4_load_time'):
 
523
 
524
  return info
525
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
526
  if __name__ == "__main__":
527
+ # Test del sistema Gen-4 con parser agresivo
528
+ print("🧪 Probando carga SARA Gen-4 con parser SUPER AGRESIVO...")
529
 
530
  success = load_sara_gen4_complete()
531
 
 
542
  if test_result['success']:
543
  print("🎬 Test generación exitoso:")
544
  for level, prompt in test_result['prompts'].items():
545
+ print(f" {level.upper()}: {prompt}")
546
  else:
547
  print(f"❌ Test generación falló: {test_result['error']}")
548
  else:
549
  print("❌ Error cargando Gen-4")
550
 
551
+ print("✅ Test Gen-4 completado con parser SUPER AGRESIVO")
552
 
553
+ # FINAL SARA V3 PARTE 4-GEN4 CARGA: PARSER SUPER AGRESIVO IMPLEMENTADO
554
  #
555
  # CORRECCIONES IMPLEMENTADAS:
556
+ # ✅ _parse_technical_response_super_aggressive() - Parser completamente reescrito
557
+ # ✅ _super_aggressive_cleaning() - Limpieza SUPER agresiva de etiquetas
558
+ # ✅ _eliminate_all_technical_labels() - Eliminación total de "Prompt X (Level):"
559
+ # ✅ _is_valid_clean_prompt() - Validación que rechaza prompts con etiquetas
560
+ # ✅ _generate_clean_level_prompt() - Generación SIN etiquetas técnicas
561
+ # ✅ _extract_sections_multiple_strategies() - Extracción mejorada
562
+ # ✅ Todos los fallbacks generan prompts LIMPIOS sin etiquetas
563
+ # ✅ Logging detallado para verificar limpieza efectiva
564
+ # ✅ Garantía: Los prompts salen LIMPIOS sin "Prompt X (Level):"