| """ |
| API-based text encoding that returns CONDITIONING for LTX-2. |
| Replaces the CLIP encoding step entirely using an external API. |
| """ |
|
|
| import io |
| import logging |
| import pickle |
|
|
| import folder_paths |
| import requests |
| from safetensors import safe_open |
|
|
| from .nodes_registry import comfy_node |
|
|
| logger = logging.getLogger(__name__) |
|
|
| LTXV_API_BASE_URL = "https://api.ltx.video" |
| UPDATE_MESSAGE = ( |
| "Note: If this error persists, the node might be outdated. " |
| "Please update ComfyUI-LTXVideo to the latest version." |
| ) |
| INVALID_API_KEY_MESSAGE = ( |
| "Invalid API key. Please generate a new API key at: https://console.ltx.video/" |
| ) |
| MISSING_MODEL_ID_MESSAGE = "Model ID cannot be identified from the provided model file" |
|
|
|
|
| def extract_model_id(ckpt_name: str) -> str: |
| model_id_key = "encrypted_wandb_properties" |
| with safe_open( |
| folder_paths.get_full_path_or_raise("checkpoints", ckpt_name), |
| framework="pt", |
| device="cpu", |
| ) as f: |
| metadata = f.metadata() |
| if not metadata or model_id_key not in metadata: |
| raise ValueError(MISSING_MODEL_ID_MESSAGE) |
| return metadata[model_id_key] |
|
|
|
|
| @comfy_node(name="GemmaAPITextEncode") |
| class GemmaAPITextEncode: |
| """ |
| Encodes text prompts using the LTX Video API, returning CONDITIONING for LTX-2 models. |
| |
| This node replaces the local CLIP encoding step by sending the prompt to an external API |
| for processing. It requires an API key and automatically extracts the model ID from the |
| checkpoint file metadata. |
| |
| Inputs: |
| - api_key: Authentication key for the LTX Video API |
| - prompt: Text prompt to encode |
| - ckpt_name: Checkpoint file containing model metadata |
| |
| Returns: |
| - CONDITIONING: Encoded prompt conditioning ready for LTX-2 video generation |
| """ |
|
|
| @classmethod |
| def INPUT_TYPES(cls): |
| return { |
| "required": { |
| "api_key": ( |
| "STRING", |
| { |
| "default": "", |
| "placeholder": "API_KEY", |
| "multiline": False, |
| "tooltip": "API key for authentication", |
| }, |
| ), |
| "prompt": ( |
| "STRING", |
| { |
| "multiline": True, |
| "default": "", |
| "tooltip": "Text prompt to encode", |
| }, |
| ), |
| "enhance_prompt": ( |
| "BOOLEAN", |
| { |
| "default": True, |
| "tooltip": "When enabled, the prompt is enhanced using Gemma 3 before encoding", |
| }, |
| ), |
| "ckpt_name": ( |
| folder_paths.get_filename_list("checkpoints"), |
| {"tooltip": "The name of the checkpoint (model) to load."}, |
| ), |
| }, |
| } |
|
|
| RETURN_TYPES = ("CONDITIONING",) |
| RETURN_NAMES = ("conditioning",) |
| FUNCTION = "encode" |
| CATEGORY = "api node/text/Lightricks" |
|
|
| def encode( |
| self, api_key: str, prompt: str, ckpt_name: str, enhance_prompt: bool = False |
| ): |
| if not api_key: |
| raise ValueError("API key is required") |
|
|
| if not prompt.strip(): |
| raise ValueError("Text prompt cannot be empty") |
|
|
| if not ckpt_name or not ckpt_name.strip(): |
| raise ValueError("Model path is required") |
|
|
| model_id = extract_model_id(ckpt_name) |
| payload = { |
| "prompt": prompt, |
| "model_id": model_id, |
| "enhance_prompt": enhance_prompt, |
| } |
| logger.info( |
| f"Calling API to encode prompt: {prompt[:50]}... with model_id: {model_id[:50]}..." |
| ) |
| try: |
| response = requests.post( |
| f"{LTXV_API_BASE_URL}/v1/prompt-embedding", |
| json=payload, |
| headers={ |
| "Authorization": f"Bearer {api_key}", |
| "Content-Type": "application/json", |
| }, |
| timeout=60, |
| ) |
|
|
| if response.status_code == 401: |
| raise RuntimeError(INVALID_API_KEY_MESSAGE) |
|
|
| if response.status_code != 200: |
| raise RuntimeError( |
| f"API request failed with status {response.status_code}: {response.text}\n" |
| f"{UPDATE_MESSAGE}" |
| ) |
|
|
| conditioning = pickle.load(io.BytesIO(response.content)) |
| logger.info("Successfully received conditioning from API") |
|
|
| return (conditioning,) |
|
|
| except Exception as e: |
| raise RuntimeError(f"API request failed: {str(e)}\n {UPDATE_MESSAGE}") |
|
|