"""genconfig_to_sdcpp_args — convierte GenerationConfig a args CLI para stable-diffusion.cpp.""" from __future__ import annotations import sys import os sys.path.insert(0, os.path.dirname(__file__)) from generation_config import GenerationConfig # Mapa de SamplerName (dominio ml) a flags de sd-cli (stable-diffusion.cpp). # Referencia: https://github.com/leejet/stable-diffusion.cpp#usage _SAMPLER_MAP: dict[str, str] = { "euler": "euler", "euler_a": "euler_a", "dpm++2m": "dpmpp2m", "dpm++2m_v2": "dpmpp2mv2", "heun": "heun", "dpm2": "dpm2", "lcm": "lcm", } def genconfig_to_sdcpp_args(cfg: GenerationConfig) -> list[str]: """Convierte un GenerationConfig a la lista de args CLI para stable-diffusion.cpp. Genera los argumentos necesarios para invocar `sd` (sd-cli) de stable-diffusion.cpp. El mapa _SAMPLER_MAP traduce los SamplerName canonicos del dominio ml a los identificadores de sdcpp. Los LoRAs se pasan como repeticiones del par --lora "path:weight". Si un LoRA no tiene path definido, se omite silenciosamente. El modelo se resuelve priorizando cfg.model.path; si es None usa cfg.model.name (puede ser un nombre de hub o un path relativo segun la configuracion de sdcpp). Args: cfg: Parametros de generacion validados. Debe ser instancia de GenerationConfig. Returns: Lista de strings con los argumentos CLI en el orden esperado por sd-cli. Listo para: subprocess.run(["sd"] + args, ...) o similar. """ model_path = cfg.model.path if cfg.model.path else cfg.model.name sampler_flag = _SAMPLER_MAP.get(cfg.sampler, cfg.sampler) args: list[str] = [ "--prompt", cfg.prompt, "--negative-prompt", cfg.negative_prompt or "", "--seed", str(cfg.seed), "--steps", str(cfg.steps), "--cfg-scale", str(cfg.cfg_scale), "--sampling-method", sampler_flag, "-W", str(cfg.width), "-H", str(cfg.height), "-m", model_path, ] # Aplanar LoRAs: cada uno genera un par --lora "path:weight" for lora in cfg.loras: if lora.path: args += ["--lora", f"{lora.path}:{lora.weight}"] return args