Sam
Create yp.composer
5870d1d verified
Raw
History Blame
3.92 kB
# 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()