Carlex22222 commited on
Commit
1f0256b
·
verified ·
1 Parent(s): b9c6bc6

Update aduc_framework/engineers/deformes2D_thinker.py

Browse files
aduc_framework/engineers/deformes2D_thinker.py CHANGED
@@ -2,11 +2,14 @@
2
  #
3
  # Copyright (C) 4 de Agosto de 2025 Carlos Rodrigues dos Santos
4
  #
5
- # Versão 3.0.0 (Autonomous Film Director)
6
  #
7
- # Esta classe é o cérebro criativo do framework ADUC-SDR. Ela atua como um
8
- # Diretor de Cinema Autônomo, utilizando um LLM para gerenciar o roteiro,
9
- # a direção de arte e a continuidade da produção de keyframes em tempo real.
 
 
 
10
 
11
  import logging
12
  from pathlib import Path
@@ -20,9 +23,10 @@ logger = logging.getLogger(__name__)
20
 
21
  class Deformes2DThinker:
22
  """
23
- O especialista cognitivo que atua como Diretor de Cinema Autônomo,
24
- responsável por todas as decisões criativas na geração de keyframes.
25
  """
 
26
  def _read_prompt_template(self, filename: str) -> str:
27
  """Lê um arquivo de template de prompt do diretório 'prompts'."""
28
  try:
@@ -32,19 +36,18 @@ class Deformes2DThinker:
32
  except FileNotFoundError:
33
  raise gr.Error(f"Arquivo de template de prompt não encontrado: {filename}")
34
 
 
35
  def get_directorial_decision(self, context: Dict[str, Any]) -> Dict[str, Any]:
36
  """
37
- Função principal do Diretor. Analisa o estado atual da produção, avalia
38
- o trabalho anterior e retorna a próxima ação (avançar, corrigir, improvisar).
39
  """
40
  try:
41
  template = self._read_prompt_template("autonomous_director_prompt.txt")
42
 
43
- # Serializa o contexto complexo em strings legíveis para o LLM
44
  keyframes_str = "\n".join([f"- ID {kf['id']}: {kf['prompt_keyframe']}" for kf in context.get('keyframes_gerados', [])])
45
  script_str = "\n".join([f"- Ato {i+1}: {ato}" for i, ato in enumerate(context.get('roteiro_completo', []))])
46
 
47
- # Preenche o template com todas as informações contextuais
48
  formatted_prompt = template.format(
49
  prompt_geral=context.get('prompt_geral', ''),
50
  midias_usuario=", ".join(context.get('midias_usuario', [])),
@@ -53,7 +56,6 @@ class Deformes2DThinker:
53
  keyframes_gerados=keyframes_str if keyframes_str else "Nenhuma cena filmada ainda."
54
  )
55
 
56
- # Prepara o payload para o Gemini. A imagem do último keyframe é crucial para a avaliação.
57
  prompt_parts = [formatted_prompt]
58
  keyframes_gerados = context.get('keyframes_gerados', [])
59
  if keyframes_gerados:
@@ -62,16 +64,13 @@ class Deformes2DThinker:
62
  try:
63
  prompt_parts.append(Image.open(last_keyframe_path))
64
  except FileNotFoundError:
65
- logger.warning(f"Não foi possível encontrar a imagem do último keyframe em: {last_keyframe_path}")
66
 
67
- # Chama o Gemini e espera uma decisão estruturada em JSON
68
  decision_json = gemini_manager_singleton.get_json_object(prompt_parts)
69
  return decision_json
70
 
71
  except Exception as e:
72
- logger.error(f"O Diretor Autônomo (Gemini) falhou: {e}. Acionando fallback para 'avançar'.", exc_info=True)
73
- # Fallback robusto: se o Gemini falhar, tentamos avançar com uma decisão genérica
74
- # para não interromper a produção.
75
  return self._get_fallback_decision(context)
76
 
77
  def _get_fallback_decision(self, context: Dict[str, Any]) -> Dict[str, Any]:
@@ -89,6 +88,35 @@ class Deformes2DThinker:
89
  "is_cut": False
90
  }
91
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
92
  def generate_storyboard(self, prompt: str, num_keyframes: int, ref_image_paths: List[str]) -> List[str]:
93
  """
94
  Atua como Roteirista para criar o roteiro inicial (lista de atos)
@@ -105,8 +133,9 @@ class Deformes2DThinker:
105
  storyboard = storyboard_data.get("scene_storyboard", [])
106
  if not storyboard or len(storyboard) != num_keyframes:
107
  logger.warning(f"Número de cenas gerado diferente do solicitado. Pedido: {num_keyframes}, Gerado: {len(storyboard)}")
108
- # Truncate or pad to match the requested number
109
- storyboard = (storyboard + [storyboard[-1]] * num_keyframes)[:num_keyframes]
 
110
 
111
  return storyboard
112
  except Exception as e:
 
2
  #
3
  # Copyright (C) 4 de Agosto de 2025 Carlos Rodrigues dos Santos
4
  #
5
+ # Versão 4.0.0 (Dual-Role Autonomous Director & Cinematographer)
6
  #
7
+ # Esta classe é o cérebro criativo do framework. Ela utiliza um LLM para
8
+ # desempenhar múltiplos papéis:
9
+ # 1. Roteirista: Cria a lista inicial de atos.
10
+ # 2. Diretor Autônomo: Gerencia a produção de keyframes, com poder de
11
+ # avaliar, corrigir e improvisar o roteiro.
12
+ # 3. Cineasta: Cria os prompts de movimento que conectam os keyframes.
13
 
14
  import logging
15
  from pathlib import Path
 
23
 
24
  class Deformes2DThinker:
25
  """
26
+ O especialista cognitivo que atua como a inteligência criativa central,
27
+ desempenhando os papéis de Roteirista, Diretor Autônomo e Cineasta.
28
  """
29
+
30
  def _read_prompt_template(self, filename: str) -> str:
31
  """Lê um arquivo de template de prompt do diretório 'prompts'."""
32
  try:
 
36
  except FileNotFoundError:
37
  raise gr.Error(f"Arquivo de template de prompt não encontrado: {filename}")
38
 
39
+ # --- PAPEL 1: DIRETOR AUTÔNOMO (Para Deformes3D) ---
40
  def get_directorial_decision(self, context: Dict[str, Any]) -> Dict[str, Any]:
41
  """
42
+ Função principal do Diretor. Analisa o estado da produção e retorna a
43
+ próxima ação (avançar, corrigir, improvisar) para a criação de KEYFRAMES.
44
  """
45
  try:
46
  template = self._read_prompt_template("autonomous_director_prompt.txt")
47
 
 
48
  keyframes_str = "\n".join([f"- ID {kf['id']}: {kf['prompt_keyframe']}" for kf in context.get('keyframes_gerados', [])])
49
  script_str = "\n".join([f"- Ato {i+1}: {ato}" for i, ato in enumerate(context.get('roteiro_completo', []))])
50
 
 
51
  formatted_prompt = template.format(
52
  prompt_geral=context.get('prompt_geral', ''),
53
  midias_usuario=", ".join(context.get('midias_usuario', [])),
 
56
  keyframes_gerados=keyframes_str if keyframes_str else "Nenhuma cena filmada ainda."
57
  )
58
 
 
59
  prompt_parts = [formatted_prompt]
60
  keyframes_gerados = context.get('keyframes_gerados', [])
61
  if keyframes_gerados:
 
64
  try:
65
  prompt_parts.append(Image.open(last_keyframe_path))
66
  except FileNotFoundError:
67
+ logger.warning(f"Não foi possível encontrar a imagem do último keyframe: {last_keyframe_path}")
68
 
 
69
  decision_json = gemini_manager_singleton.get_json_object(prompt_parts)
70
  return decision_json
71
 
72
  except Exception as e:
73
+ logger.error(f"O Diretor Autônomo (Gemini) falhou: {e}. Acionando fallback.", exc_info=True)
 
 
74
  return self._get_fallback_decision(context)
75
 
76
  def _get_fallback_decision(self, context: Dict[str, Any]) -> Dict[str, Any]:
 
88
  "is_cut": False
89
  }
90
 
91
+ # --- PAPEL 2: CINEASTA (Para Deformes4D) ---
92
+ def get_motion_decision(self, start_kf: Dict, end_kf: Dict, motion_history: str) -> str:
93
+ """
94
+ Atua como Cineasta para decidir o melhor `motion_prompt` que conecta
95
+ dois keyframes existentes, criando o MOVIMENTO.
96
+ """
97
+ try:
98
+ template = self._read_prompt_template("motion_director_prompt.txt")
99
+
100
+ formatted_prompt = template.format(
101
+ cena_atual_desc=start_kf.get('prompt_keyframe', 'início da cena'),
102
+ cena_futura_desc=end_kf.get('prompt_keyframe', 'fim da cena'),
103
+ historico_movimento=motion_history
104
+ )
105
+
106
+ prompt_parts = [
107
+ formatted_prompt,
108
+ "IMAGEM ATUAL:", Image.open(start_kf['caminho_pixel']),
109
+ "IMAGEM FUTURA:", Image.open(end_kf['caminho_pixel'])
110
+ ]
111
+
112
+ motion_prompt = gemini_manager_singleton.get_raw_text(prompt_parts)
113
+ return motion_prompt.strip().replace("`", "").replace("\"", "")
114
+
115
+ except Exception as e:
116
+ logger.error(f"O Cineasta (Gemini) falhou ao criar motion_prompt: {e}. Usando fallback.", exc_info=True)
117
+ return f"Uma transição cinematográfica suave de '{start_kf.get('prompt_keyframe', 'cena anterior')}' para '{end_kf.get('prompt_keyframe', 'próxima cena')}'."
118
+
119
+ # --- PAPEL 3: ROTEIRISTA (Para Orquestrador) ---
120
  def generate_storyboard(self, prompt: str, num_keyframes: int, ref_image_paths: List[str]) -> List[str]:
121
  """
122
  Atua como Roteirista para criar o roteiro inicial (lista de atos)
 
133
  storyboard = storyboard_data.get("scene_storyboard", [])
134
  if not storyboard or len(storyboard) != num_keyframes:
135
  logger.warning(f"Número de cenas gerado diferente do solicitado. Pedido: {num_keyframes}, Gerado: {len(storyboard)}")
136
+ # Garante que a lista tenha o tamanho exato solicitado
137
+ default_scene = storyboard[-1] if storyboard else "Cena de continuação."
138
+ storyboard = (storyboard + [default_scene] * num_keyframes)[:num_keyframes]
139
 
140
  return storyboard
141
  except Exception as e: