Spaces:
Build error
Build error
| # aduc_framework/engineers/composer.py | |
| # | |
| # Copyright (C) August 4, 2025 Carlos Rodrigues dos Santos | |
| # | |
| # Versão 1.0.0 (Conversational Execution Engine) | |
| import logging | |
| from PIL import Image | |
| from typing import List, Dict, Any, Generator | |
| import json | |
| from ..managers.llama_multimodal_manager import llama_multimodal_manager_singleton | |
| logger = logging.getLogger(__name__) | |
| # ... (função robust_json_parser aqui) ... | |
| class Composer: | |
| """ | |
| O Composer atua como o Mestre de Obras. Ele recebe um plano de execução | |
| e supervisiona o LLM para realizar cada tarefa, construindo o | |
| artefato final (o DNA de pré-produção) de forma iterativa e conversacional. | |
| """ | |
| def __init__(self): | |
| # O Composer agora carrega um "caderno de plantas" com os prompts para cada tarefa | |
| self.prompts = { | |
| "PREPROD_01_CATALOG_ASSETS": self._read_prompt_template("catalog_assets_prompt.txt"), | |
| "PREPROD_02_SCORE_ASSETS": self._read_prompt_template("score_assets_prompt.txt"), | |
| # ... e assim por diante para cada task_id do Deformes2D | |
| } | |
| def _read_prompt_template(self, filename: str) -> str: | |
| # ... (implementação para ler os arquivos de prompt) | |
| pass | |
| def _talk_to_llama(self, prompt: str, images: List[Image.Image] = None, expected_format="text") -> Any: | |
| # ... (a mesma função de wrapper de antes) | |
| pass | |
| # O PONTO DE ENTRADA PRINCIPAL DO COMPOSER | |
| def execute_plan( | |
| self, | |
| execution_plan: List[Dict[str, Any]], | |
| initial_data: Dict[str, Any] | |
| ) -> Generator[Dict[str, Any], None, Dict[str, Any]]: | |
| """ | |
| Executa um plano de trabalho tarefa por tarefa, emitindo atualizações | |
| de progresso e construindo o DNA. | |
| """ | |
| llama_multimodal_manager_singleton.reset_chat() | |
| # O DNA começa com os dados iniciais do Orquestrador | |
| dna = { | |
| "global_prompt": initial_data["global_prompt"], | |
| "initial_media_paths": initial_data["user_media_paths"], | |
| "asset_catalog": {}, | |
| "story_summary": "", | |
| "scenes": [] | |
| } | |
| user_media = [Image.open(p) for p in initial_data["user_media_paths"]] | |
| # Loop principal de execução do plano | |
| for i, task in enumerate(execution_plan): | |
| task_id = task['task_id'] | |
| description = task['description'] | |
| # --- ATUALIZAÇÃO PARA A UI --- | |
| # Emite o estado atual antes de executar a tarefa | |
| yield { | |
| "status": "progress", | |
| "stage": f"{i+1}/{len(execution_plan)}", | |
| "current_task": task_id, | |
| "message": description, | |
| "dna_snapshot": dna | |
| } | |
| # Executa a lógica específica para cada tarefa | |
| if task_id == "PREPROD_01_CATALOG_ASSETS": | |
| prompt = self.prompts[task_id].format(**task['inputs']) | |
| asset_catalog = self._talk_to_llama(prompt, user_media, expected_format="json") | |
| dna["asset_catalog"] = asset_catalog | |
| elif task_id == "PREPROD_02_SCORE_ASSETS": | |
| # A conversa continua, o Llama lembra do catálogo que acabou de criar | |
| prompt = self.prompts[task_id].format(**task['inputs']) | |
| scored_catalog = self._talk_to_llama(prompt, expected_format="json") | |
| dna["asset_catalog"] = scored_catalog | |
| # ... lógica para as outras tarefas (PREPROD_03, 04, etc.) | |
| task['status'] = 'complete' | |
| # --- FIM --- | |
| final_message = "Plano de pré-produção concluído com sucesso." | |
| logger.info(final_message) | |
| yield {"status": "complete", "message": final_message, "dna": dna} | |
| return dna | |
| # Instância Singleton | |
| composer_singleton = Composer() |