conecta-primo-gpu / modelos /escolha.py
ConectaPrimoAI's picture
Upload folder using huggingface_hub
64e1ec4 verified
Raw History Blame Contribute Delete
3.51 kB
# -*- coding: utf-8 -*-
"""QUAL MÓDULO ATENDE CADA TIPO — num lugar só, para o worker e o Space.
POR QUE ISTO EXISTE. Havia duas tabelas com a mesma decisão: o `_MODULOS` do
`gerenciador.py` (worker CUDA) e o `_MODULOS` do `nucleo.py` (Space ZeroGPU).
Enquanto cada tipo tinha um módulo só, elas eram iguais por sorte. No dia em
que a imagem passou a ter DOIS módulos possíveis — Z-Image e Qwen-Image,
escolhidos pelo `IMAGE_MODEL` —, duas tabelas viraram duas respostas para a
mesma pergunta, e a que fica para trás é sempre a que ninguém olha. É o
defeito mais caro desta casa, e ele já cobrou a peneira do navegador, os dois
renderizadores de resumo do estudo e as duas regras de imagem no chat.
A REGRA DE SEMPRE VALE AQUI: a ORDEM é nossa, quem diz o que EXISTE é a
conta — ou, neste caso, a variável. O que está escrito abaixo são MARCAS DE
FAMÍLIA (`qwen-image`, `z-image`), nunca um id completo: um `Qwen-Image-2512`
publicado amanhã cai sozinho no módulo certo, sem ninguém tocar no arquivo.
Lista de ids escrita à mão já mordeu este projeto cinco vezes.
E O DESCONHECIDO TEM DONO. Um id que não bate com marca nenhuma vai para o
módulo PADRÃO do tipo, em vez de virar `None`: devolver nada aqui apagaria a
geração inteira por causa de um nome que ninguém previu — e o pior desfecho de
um palpite é uma imagem com a calibragem errada, que ainda é uma imagem.
"""
from __future__ import annotations
import os
from typing import Dict, List, Tuple
# Marca da família -> nome do módulo dentro de `modelos/`. A ordem importa:
# a primeira marca que aparecer no id ganha.
_FAMILIAS_IMAGEM: List[Tuple[str, str]] = [
("qwen-image", "qwen_image"),
("z-image", "z_image"),
]
_FAMILIAS_VIDEO: List[Tuple[str, str]] = [
("ltx", "ltx"),
("wan", "wan22"),
]
# O padrão de cada tipo quando o id não bate com marca nenhuma.
_PADRAO = {"image": "qwen_image", "speech": "qwen3_tts", "voice": "qwen3_tts",
"music": "ace_step", "video": "wan22"}
_VARIAVEL = {"image": "IMAGE_MODEL", "speech": "TTS_MODEL",
"voice": "TTS_MODEL", "music": "MUSIC_MODEL",
"video": "VIDEO_MODEL"}
_POR_TIPO: Dict[str, List[Tuple[str, str]]] = {
"image": _FAMILIAS_IMAGEM,
"video": _FAMILIAS_VIDEO,
}
def nome_do_modulo(tipo: str, modelo: str = "") -> str:
"""O nome do módulo que atende este tipo, pela FAMÍLIA do id configurado.
`modelo` vazio faz a função ler a variável de ambiente do tipo — é como os
dois consumidores a chamam. Passar o id à mão existe para o teste, que
precisa medir a escolha sem mexer no ambiente do processo.
"""
tipo = (tipo or "").strip().lower()
id_modelo = (modelo or os.getenv(_VARIAVEL.get(tipo, ""), "")).strip().lower()
for marca, modulo in _POR_TIPO.get(tipo, []):
if marca in id_modelo:
return modulo
return _PADRAO.get(tipo, "")
def modulo_de(tipo: str):
"""O módulo em si, importado na hora.
O import é TARDIO de propósito, e é a regra do `modelos/__init__.py`: o
worker sobe e responde `/health` sem torch instalado, e o peso de um
modelo só entra quando um job pede. Importar os dois módulos de imagem no
topo obrigaria o processo a resolver as dependências dos DOIS para atender
um pedido de voz.
"""
nome = nome_do_modulo(tipo)
if not nome:
return None
from importlib import import_module
return import_module(f".{nome}", package=__package__)