Carlexxx
feat: Implement self-contained specialist managers
99c6a62
raw
history blame
5.14 kB
# app_api.py
#
# Copyright (C) August 4, 2025 Carlos Rodrigues dos Santos
#
# Versão 3.0.0 (API Head for Aduc Framework)
#
# Este arquivo implementa um servidor de API usando FastAPI para expor as
# funcionalidades do Aduc Framework. Ele permite o controle programático
# do processo de geração de vídeo.
import yaml
import logging
import uuid
from typing import Dict
from fastapi import FastAPI, BackgroundTasks, HTTPException
# --- 1. IMPORTAÇÃO DO FRAMEWORK E SEUS TIPOS ---
import aduc_framework
from aduc_framework.types import GenerationState, PreProductionParams, ProductionParams
# --- CONFIGURAÇÃO INICIAL ---
logger = logging.getLogger(__name__)
# Cria a aplicação FastAPI
app = FastAPI(
title="ADUC-SDR Framework API",
description="API para orquestração de geração de vídeo coerente com IA.",
version="3.0.0"
)
# Carrega a configuração e inicializa uma instância SINGLETON do framework.
# O framework é pesado e deve ser carregado apenas uma vez na inicialização da API.
try:
with open("config.yaml", 'r') as f: config = yaml.safe_load(f)
WORKSPACE_DIR = config['application']['workspace_dir']
aduc = aduc_framework.create_aduc_instance(workspace_dir=WORKSPACE_DIR)
logger.info("API FastAPI inicializada e conectada ao Aduc Framework.")
except Exception as e:
logger.critical(f"ERRO CRÍTICO durante a inicialização da API: {e}", exc_info=True)
# A API não pode funcionar sem o framework, então saímos se falhar.
exit()
# --- ARMAZENAMENTO DE TAREFAS EM MEMÓRIA ---
# Em um ambiente de produção real, isso seria substituído por um banco de dados
# ou um cache como Redis para persistir o estado das tarefas.
tasks_state: Dict[str, GenerationState] = {}
# --- FUNÇÕES DE BACKGROUND ---
def run_production_in_background(task_id: str, params: ProductionParams):
"""
Função que executa a tarefa de produção demorada em segundo plano.
Ela opera na instância global 'aduc' para modificar seu estado interno.
"""
logger.info(f"Background task {task_id}: Iniciando produção de vídeo...")
try:
# A tarefa do framework modifica o estado interno da instância 'aduc'
_, _, final_state = aduc.task_produce_original_movie(params=params)
# Armazena o estado final e completo no nosso "banco de dados" de tarefas
tasks_state[task_id] = final_state
logger.info(f"Background task {task_id}: Produção de vídeo concluída com sucesso.")
except Exception as e:
logger.error(f"Background task {task_id}: Falha na produção. Erro: {e}", exc_info=True)
# Opcional: Atualizar o estado da tarefa com uma mensagem de erro.
# --- ENDPOINTS DA API ---
@app.post("/v1/pre-production", response_model=GenerationState, tags=["Workflow"])
async def start_pre_production(params: PreProductionParams):
"""
Inicia e executa a etapa de pré-produção (storyboard e keyframes).
Esta é uma chamada síncrona, pois a pré-produção é relativamente rápida.
Ela retorna o estado de geração completo após a conclusão.
"""
logger.info(f"API: Recebida solicitação de pré-produção com prompt: '{params.prompt[:30]}...'")
try:
_, _, updated_state = aduc.task_pre_production(params=params)
return updated_state
except Exception as e:
logger.error(f"API: Erro na pré-produção: {e}", exc_info=True)
raise HTTPException(status_code=500, detail=f"Erro interno durante a pré-produção: {e}")
@app.post("/v1/production", status_code=202, tags=["Workflow"])
async def start_production(params: ProductionParams, background_tasks: BackgroundTasks):
"""
Inicia a tarefa de produção de vídeo principal em segundo plano.
Esta chamada retorna imediatamente com um `task_id`. Use o endpoint
`/v1/status/{task_id}` para verificar o progresso e obter o resultado final.
"""
task_id = str(uuid.uuid4())
logger.info(f"API: Recebida solicitação de produção. Criando tarefa de background com ID: {task_id}")
# Armazena o estado atual (pré-produção) antes de iniciar a nova tarefa
tasks_state[task_id] = aduc.get_current_state()
# Adiciona a função demorada para ser executada em segundo plano
background_tasks.add_task(run_production_in_background, task_id, params)
return {"message": "Produção de vídeo iniciada em segundo plano.", "task_id": task_id}
@app.get("/v1/status/{task_id}", response_model=GenerationState, tags=["Workflow"])
async def get_task_status(task_id: str):
"""
Verifica o estado de uma tarefa de geração em andamento ou concluída.
"""
logger.info(f"API: Verificando status da tarefa {task_id}")
state = tasks_state.get(task_id)
if not state:
raise HTTPException(status_code=404, detail="ID de tarefa não encontrado.")
# Retorna o estado mais recente que temos para essa tarefa
return state
@app.get("/health", tags=["Infra"])
async def health_check():
"""
Endpoint simples para verificar se a API está online.
"""
return {"status": "ok"}