Instructions to use vidfom/Ltx-3 with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- llama-cpp-python
How to use vidfom/Ltx-3 with llama-cpp-python:
# !pip install llama-cpp-python from llama_cpp import Llama llm = Llama.from_pretrained( repo_id="vidfom/Ltx-3", filename="ComfyUI/models/text_encoders/gemma-3-12b-it-qat-UD-Q4_K_XL.gguf", )
llm.create_chat_completion( messages = "No input example has been defined for this model task." )
- Notebooks
- Google Colab
- Kaggle
- Local Apps
- llama.cpp
How to use vidfom/Ltx-3 with llama.cpp:
Install from brew
brew install llama.cpp # Start a local OpenAI-compatible server with a web UI: llama-server -hf vidfom/Ltx-3:UD-Q4_K_XL # Run inference directly in the terminal: llama-cli -hf vidfom/Ltx-3:UD-Q4_K_XL
Install from WinGet (Windows)
winget install llama.cpp # Start a local OpenAI-compatible server with a web UI: llama-server -hf vidfom/Ltx-3:UD-Q4_K_XL # Run inference directly in the terminal: llama-cli -hf vidfom/Ltx-3:UD-Q4_K_XL
Use pre-built binary
# Download pre-built binary from: # https://github.com/ggerganov/llama.cpp/releases # Start a local OpenAI-compatible server with a web UI: ./llama-server -hf vidfom/Ltx-3:UD-Q4_K_XL # Run inference directly in the terminal: ./llama-cli -hf vidfom/Ltx-3:UD-Q4_K_XL
Build from source code
git clone https://github.com/ggerganov/llama.cpp.git cd llama.cpp cmake -B build cmake --build build -j --target llama-server llama-cli # Start a local OpenAI-compatible server with a web UI: ./build/bin/llama-server -hf vidfom/Ltx-3:UD-Q4_K_XL # Run inference directly in the terminal: ./build/bin/llama-cli -hf vidfom/Ltx-3:UD-Q4_K_XL
Use Docker
docker model run hf.co/vidfom/Ltx-3:UD-Q4_K_XL
- LM Studio
- Jan
- Ollama
How to use vidfom/Ltx-3 with Ollama:
ollama run hf.co/vidfom/Ltx-3:UD-Q4_K_XL
- Unsloth Studio new
How to use vidfom/Ltx-3 with Unsloth Studio:
Install Unsloth Studio (macOS, Linux, WSL)
curl -fsSL https://unsloth.ai/install.sh | sh # Run unsloth studio unsloth studio -H 0.0.0.0 -p 8888 # Then open http://localhost:8888 in your browser # Search for vidfom/Ltx-3 to start chatting
Install Unsloth Studio (Windows)
irm https://unsloth.ai/install.ps1 | iex # Run unsloth studio unsloth studio -H 0.0.0.0 -p 8888 # Then open http://localhost:8888 in your browser # Search for vidfom/Ltx-3 to start chatting
Using HuggingFace Spaces for Unsloth
# No setup required # Open https://huggingface.co/spaces/unsloth/studio in your browser # Search for vidfom/Ltx-3 to start chatting
- Docker Model Runner
How to use vidfom/Ltx-3 with Docker Model Runner:
docker model run hf.co/vidfom/Ltx-3:UD-Q4_K_XL
- Lemonade
How to use vidfom/Ltx-3 with Lemonade:
Pull the model
# Download Lemonade from https://lemonade-server.ai/ lemonade pull vidfom/Ltx-3:UD-Q4_K_XL
Run and chat with the model
lemonade run user.Ltx-3-UD-Q4_K_XL
List all available models
lemonade list
| import torch | |
| from .imagefunc import AnyType, log, extract_all_numbers_from_str | |
| any = AnyType("*") | |
| class SeedNode: | |
| def __init__(self): | |
| pass | |
| def INPUT_TYPES(self): | |
| return {"required": { | |
| "seed":("INT", {"default": 0, "min": 0, "max": 1e18, "step": 1}), | |
| },} | |
| RETURN_TYPES = ("INT",) | |
| RETURN_NAMES = ("seed",) | |
| FUNCTION = 'seed_node' | |
| CATEGORY = '😺dzNodes/LayerUtility/Data' | |
| def seed_node(self, seed): | |
| return (seed,) | |
| class BooleanOperator: | |
| def __init__(self): | |
| pass | |
| def INPUT_TYPES(self): | |
| operator_list = ["==", "!=", ">", "<", ">=", "<=", "and", "or", "xor", "not(a)", "min", "max"] | |
| return {"required": { | |
| "a": (any, ), | |
| "b": (any, ), | |
| "operator": (operator_list,), | |
| },} | |
| RETURN_TYPES = ("BOOLEAN",) | |
| RETURN_NAMES = ("output",) | |
| FUNCTION = 'bool_operator_node' | |
| CATEGORY = '😺dzNodes/LayerUtility/Data' | |
| def bool_operator_node(self, a, b, operator): | |
| ret_value = False | |
| if operator == "==": | |
| ret_value = a == b | |
| if operator == "!=": | |
| ret_value = a != b | |
| if operator == ">": | |
| ret_value = a > b | |
| if operator == "<": | |
| ret_value = a < b | |
| if operator == ">=": | |
| ret_value = a >= b | |
| if operator == "<=": | |
| ret_value = a <= b | |
| if operator == "and": | |
| ret_value = a and b | |
| if operator == "or": | |
| ret_value = a or b | |
| if operator == "xor": | |
| ret_value = not(a == b) | |
| if operator == "not(a)": | |
| ret_value = not a | |
| if operator == "min": | |
| ret_value = min(a, b) | |
| if operator == "max": | |
| ret_value = max(a, b) | |
| return (ret_value,) | |
| class BooleanOperatorV2: | |
| def __init__(self): | |
| pass | |
| def INPUT_TYPES(self): | |
| operator_list = ["==", "!=", ">", "<", ">=", "<=", "and", "or", "xor", "not(a)", "min", "max"] | |
| return { | |
| "required": | |
| { | |
| "a_value": ("STRING", {"default": "", "multiline": False}), | |
| "b_value": ("STRING", {"default": "", "multiline": False}), | |
| "operator": (operator_list,), | |
| }, | |
| "optional": { | |
| "a": (any,), | |
| "b": (any,), | |
| } | |
| } | |
| RETURN_TYPES = ("BOOLEAN", "STRING",) | |
| RETURN_NAMES = ("output", "string",) | |
| FUNCTION = 'bool_operator_node_v2' | |
| CATEGORY = '😺dzNodes/LayerUtility/Data' | |
| def bool_operator_node_v2(self, a_value, b_value, operator, a = None, b = None): | |
| if a is None: | |
| if a_value != "": | |
| _numbers = extract_all_numbers_from_str(a_value, checkint=True) | |
| if len(_numbers) > 0: | |
| a = _numbers[0] | |
| else: | |
| a = 0 | |
| else: | |
| a = 0 | |
| if b is None: | |
| if b_value != "": | |
| _numbers = extract_all_numbers_from_str(b_value, checkint=True) | |
| if len(_numbers) > 0: | |
| b = _numbers[0] | |
| else: | |
| b = 0 | |
| else: | |
| b = 0 | |
| ret_value = False | |
| if operator == "==": | |
| ret_value = a == b | |
| if operator == "!=": | |
| ret_value = a != b | |
| if operator == ">": | |
| ret_value = a > b | |
| if operator == "<": | |
| ret_value = a < b | |
| if operator == ">=": | |
| ret_value = a >= b | |
| if operator == "<=": | |
| ret_value = a <= b | |
| if operator == "and": | |
| ret_value = a and b | |
| if operator == "or": | |
| ret_value = a or b | |
| if operator == "xor": | |
| ret_value = not(a == b) | |
| if operator == "not(a)": | |
| ret_value = not a | |
| if operator == "min": | |
| ret_value = min(a, b) | |
| if operator == "max": | |
| ret_value = max(a, b) | |
| return (ret_value, str(ret_value)) | |
| class NumberCalculator: | |
| def __init__(self): | |
| pass | |
| def INPUT_TYPES(self): | |
| operator_list = ["+", "-", "*", "/", "**", "//", "%", "nth_root", "min", "max"] | |
| return {"required": { | |
| "a": (any, {}), | |
| "b": (any, {}), | |
| "operator": (operator_list,), | |
| },} | |
| RETURN_TYPES = ("INT", "FLOAT",) | |
| RETURN_NAMES = ("int", "float",) | |
| FUNCTION = 'number_calculator_node' | |
| CATEGORY = '😺dzNodes/LayerUtility/Data' | |
| def number_calculator_node(self, a, b, operator): | |
| ret_value = 0 | |
| if operator == "+": | |
| ret_value = a + b | |
| if operator == "-": | |
| ret_value = a - b | |
| if operator == "*": | |
| ret_value = a * b | |
| if operator == "**": | |
| ret_value = a ** b | |
| if operator == "%": | |
| ret_value = a % b | |
| if operator == "nth_root": | |
| ret_value = a ** (1/b) | |
| if operator == "min": | |
| ret_value = min(a, b) | |
| if operator == "max": | |
| ret_value = max(a, b) | |
| if operator == "/": | |
| if b != 0: | |
| ret_value = a / b | |
| else: | |
| ret_value = 0 | |
| if operator == "//": | |
| if b != 0: | |
| ret_value = a // b | |
| else: | |
| ret_value = 0 | |
| return (int(ret_value), float(ret_value),) | |
| class NumberCalculatorV2: | |
| def __init__(self): | |
| pass | |
| def INPUT_TYPES(self): | |
| operator_list = ["+", "-", "*", "/", "**", "//", "%" , "nth_root", "min", "max"] | |
| return { | |
| "required": | |
| { | |
| "a_value": ("STRING", {"default": "", "multiline": False}), | |
| "b_value": ("STRING", {"default": "", "multiline": False}), | |
| "operator": (operator_list,), | |
| }, | |
| "optional": { | |
| "a": (any,), | |
| "b": (any,), | |
| } | |
| } | |
| RETURN_TYPES = ("INT", "FLOAT", "STRING",) | |
| RETURN_NAMES = ("int", "float", "string",) | |
| FUNCTION = 'number_calculator_node_v2' | |
| CATEGORY = '😺dzNodes/LayerUtility/Data' | |
| def number_calculator_node_v2(self, a_value, b_value, operator, a = None, b = None): | |
| if a is None: | |
| if a_value != "": | |
| _numbers = extract_all_numbers_from_str(a_value, checkint=True) | |
| if len(_numbers) > 0: | |
| a = _numbers[0] | |
| else: | |
| a = 0 | |
| else: | |
| a = 0 | |
| if b is None: | |
| if b_value != "": | |
| _numbers = extract_all_numbers_from_str(b_value, checkint=True) | |
| if len(_numbers) > 0: | |
| b = _numbers[0] | |
| else: | |
| b = 0 | |
| else: | |
| b = 0 | |
| ret_value = 0 | |
| if operator == "+": | |
| ret_value = a + b | |
| if operator == "-": | |
| ret_value = a - b | |
| if operator == "*": | |
| ret_value = a * b | |
| if operator == "**": | |
| ret_value = a ** b | |
| if operator == "%": | |
| ret_value = a % b | |
| if operator == "nth_root": | |
| ret_value = a ** (1/b) | |
| if operator == "min": | |
| ret_value = min(a, b) | |
| if operator == "max": | |
| ret_value = max(a, b) | |
| if operator == "/": | |
| if b != 0: | |
| ret_value = a / b | |
| else: | |
| ret_value = 0 | |
| if operator == "//": | |
| if b != 0: | |
| ret_value = a // b | |
| else: | |
| ret_value = 0 | |
| return (int(ret_value), float(ret_value), str(ret_value)) | |
| class StringCondition: | |
| def __init__(self): | |
| pass | |
| def INPUT_TYPES(self): | |
| string_condition_list = ["include", "exclude", "equal"] | |
| return {"required": { | |
| "text": ("STRING", {"multiline": False}), | |
| "condition": (string_condition_list,), | |
| "sub_string": ("STRING", {"multiline": False}), | |
| },} | |
| RETURN_TYPES = ("BOOLEAN", "STRING",) | |
| RETURN_NAMES = ("output", "string",) | |
| FUNCTION = 'string_condition' | |
| CATEGORY = '😺dzNodes/LayerUtility/Data' | |
| def string_condition(self, text, condition, sub_string): | |
| ret = False | |
| if condition == "include": | |
| ret = sub_string in text | |
| if condition == "exclude": | |
| ret = sub_string not in text | |
| if condition == "equal": | |
| ret = text == sub_string | |
| return (ret, str(ret)) | |
| class TextBoxNode: | |
| def __init__(self): | |
| pass | |
| def INPUT_TYPES(self): | |
| return {"required": { | |
| "text": ("STRING", {"multiline": True}), | |
| },} | |
| RETURN_TYPES = ("STRING",) | |
| RETURN_NAMES = ("text",) | |
| FUNCTION = 'text_box_node' | |
| CATEGORY = '😺dzNodes/LayerUtility/Data' | |
| def text_box_node(self, text): | |
| return (text,) | |
| class StringNode: | |
| def __init__(self): | |
| pass | |
| def INPUT_TYPES(self): | |
| return {"required": { | |
| "string": ("STRING", {"multiline": False}), | |
| },} | |
| RETURN_TYPES = ("STRING",) | |
| RETURN_NAMES = ("string",) | |
| FUNCTION = 'string_node' | |
| CATEGORY = '😺dzNodes/LayerUtility/Data' | |
| def string_node(self, string): | |
| return (string,) | |
| class IntegerNode: | |
| def __init__(self): | |
| pass | |
| def INPUT_TYPES(self): | |
| return {"required": { | |
| "int_value":("INT", {"default": 0, "min": -1e18, "max": 1e18, "step": 1}), | |
| },} | |
| RETURN_TYPES = ("INT", "STRING",) | |
| RETURN_NAMES = ("int", "string",) | |
| FUNCTION = 'integer_node' | |
| CATEGORY = '😺dzNodes/LayerUtility/Data' | |
| def integer_node(self, int_value): | |
| return (int(int_value), str(int_value)) | |
| class FloatNode: | |
| def __init__(self): | |
| pass | |
| def INPUT_TYPES(self): | |
| return {"required": { | |
| "float_value": ("FLOAT", {"default": 0, "min": -1e18, "max": 1e18, "step": 0.00001}), | |
| },} | |
| RETURN_TYPES = ("FLOAT", "STRING",) | |
| RETURN_NAMES = ("float", "string",) | |
| FUNCTION = 'float_node' | |
| CATEGORY = '😺dzNodes/LayerUtility/Data' | |
| def float_node(self, float_value): | |
| return (float_value, str(float_value)) | |
| class BooleanNode: | |
| def __init__(self): | |
| pass | |
| def INPUT_TYPES(self): | |
| return {"required": { | |
| "bool_value": ("BOOLEAN", {"default": False}), | |
| },} | |
| RETURN_TYPES = ("BOOLEAN", "STRING",) | |
| RETURN_NAMES = ("boolean", "string",) | |
| FUNCTION = 'boolean_node' | |
| CATEGORY = '😺dzNodes/LayerUtility/Data' | |
| def boolean_node(self, bool_value): | |
| return (bool_value, str(bool_value)) | |
| class IfExecute: | |
| def INPUT_TYPES(s): | |
| return { | |
| "required": { | |
| "if_condition": (any,), | |
| "when_TRUE": (any,), | |
| "when_FALSE": (any,), | |
| }, | |
| } | |
| RETURN_TYPES = (any,) | |
| RETURN_NAMES = ("?",) | |
| FUNCTION = "if_execute" | |
| CATEGORY = '😺dzNodes/LayerUtility/Data' | |
| def if_execute(self, if_condition, when_TRUE, when_FALSE): | |
| return (when_TRUE if if_condition else when_FALSE,) | |
| class SwitchCaseNode: | |
| def INPUT_TYPES(s): | |
| return { | |
| "required": { | |
| "switch_condition": ("STRING", {"default": "", "multiline": False}), | |
| "case_1": ("STRING", {"default": "", "multiline": False}), | |
| "case_2": ("STRING", {"default": "", "multiline": False}), | |
| "case_3": ("STRING", {"default": "", "multiline": False}), | |
| "input_default": (any,), | |
| }, | |
| "optional": { | |
| "input_1": (any,), | |
| "input_2": (any,), | |
| "input_3": (any,), | |
| } | |
| } | |
| RETURN_TYPES = (any,) | |
| RETURN_NAMES = ("?",) | |
| FUNCTION = "switch_case" | |
| CATEGORY = '😺dzNodes/LayerUtility/Data' | |
| def switch_case(self, switch_condition, case_1, case_2, case_3, input_default, input_1=None, input_2=None, input_3=None): | |
| output=input_default | |
| if switch_condition == case_1 and input_1 is not None: | |
| output=input_1 | |
| elif switch_condition == case_2 and input_2 is not None: | |
| output=input_2 | |
| elif switch_condition == case_3 and input_3 is not None: | |
| output=input_3 | |
| return (output,) | |
| class QueueStopNode(): | |
| def __init__(self): | |
| pass | |
| def INPUT_TYPES(self): | |
| mode_list = ["stop", "continue"] | |
| return { | |
| "required": { | |
| "any": (any, ), | |
| "mode": (mode_list,), | |
| "stop": ("BOOLEAN", {"default": True}), | |
| }, | |
| } | |
| RETURN_TYPES = (any,) | |
| RETURN_NAMES = ("any",) | |
| FUNCTION = 'stop_node' | |
| CATEGORY = '😺dzNodes/LayerUtility/SystemIO' | |
| def stop_node(self, any, mode,stop): | |
| if mode == "stop": | |
| if stop: | |
| log(f"Queue stopped, it was terminated by node.", "error") | |
| from comfy.model_management import InterruptProcessingException | |
| raise InterruptProcessingException() | |
| return (any,) | |
| class LS_ImageBatchToMultiList: | |
| def __init__(self): | |
| self.NODE_NAME = 'ImageBatchToList' | |
| def INPUT_TYPES(s): | |
| return { | |
| "required": { | |
| "image": ("IMAGE",), | |
| "batch_size": ("INT", { | |
| "default": 6, | |
| "min": 1, | |
| "max": 64, | |
| "step": 1 | |
| }), | |
| } | |
| } | |
| RETURN_TYPES = ("IMAGE",) | |
| RETURN_NAMES = ("image", ) | |
| OUTPUT_IS_LIST = (True,) | |
| FUNCTION = "image_batch_to_multi_list" | |
| CATEGORY = '😺dzNodes/LayerUtility/Data' | |
| def image_batch_to_multi_list(self, image, batch_size): | |
| """ | |
| image: [B, H, W, C] | |
| 输出: list of IMAGE batch,每个 batch 大小 <= batch_size | |
| """ | |
| B = image.shape[0] | |
| out = [] | |
| sizes = [] | |
| for i in range(0, B, batch_size): | |
| batch = image[i:i + batch_size] | |
| out.append(batch) | |
| sizes.append(batch.shape[0]) | |
| log(f"{self.NODE_NAME}: Convert a batch of {B} images to {sizes}.", message_type='finish') | |
| return (out,) | |
| class LS_MultiImageListToBatch: | |
| def __init__(self): | |
| self.NODE_NAME = 'ImageListToBatch' | |
| def INPUT_TYPES(s): | |
| return { | |
| "required": { | |
| "image": ("IMAGE",), | |
| } | |
| } | |
| RETURN_TYPES = ("IMAGE",) | |
| RETURN_NAMES = ("image", ) | |
| INPUT_IS_LIST = True | |
| FUNCTION = "multi_image_list_to_batch" | |
| CATEGORY = '😺dzNodes/LayerUtility/Data' | |
| def multi_image_list_to_batch(self, image): | |
| """ | |
| image: list of IMAGE batch | |
| 每个元素 shape 为 [Bi, Hi, Wi, C] | |
| 输出: 单一 IMAGE batch [sum(Bi), H, W, C] | |
| """ | |
| # 以第一个 batch 的第一张图作为基准尺寸 | |
| base_h, base_w = image[0].shape[1:3] | |
| out = [] | |
| sizes = [] | |
| for batch in image: | |
| # batch: [B, H, W, C] | |
| if batch.shape[1:3] != (base_h, base_w): | |
| # 转成 [B, C, H, W] | |
| batch = batch.permute(0, 3, 1, 2) | |
| batch = comfy.utils.common_upscale( | |
| batch, | |
| base_w, | |
| base_h, | |
| upscale_method="bicubic", | |
| crop="center" | |
| ) | |
| # 转回 [B, H, W, C] | |
| batch = batch.permute(0, 2, 3, 1) | |
| sizes.append(batch.shape[0]) | |
| out.append(batch) | |
| # 沿 batch 维拼接 | |
| out = torch.cat(out, dim=0) | |
| log(f"{self.NODE_NAME}: Convert {sizes} list(s) to a batch of {out.shape[0]} images.", message_type='finish') | |
| return (out,) | |
| NODE_CLASS_MAPPINGS = { | |
| "LayerUtility: QueueStop": QueueStopNode, | |
| "LayerUtility: SwitchCase": SwitchCaseNode, | |
| "LayerUtility: If ": IfExecute, | |
| "LayerUtility: StringCondition": StringCondition, | |
| "LayerUtility: BooleanOperator": BooleanOperator, | |
| "LayerUtility: NumberCalculator": NumberCalculator, | |
| "LayerUtility: BooleanOperatorV2": BooleanOperatorV2, | |
| "LayerUtility: NumberCalculatorV2": NumberCalculatorV2, | |
| "LayerUtility: TextBox": TextBoxNode, | |
| "LayerUtility: String": StringNode, | |
| "LayerUtility: Integer": IntegerNode, | |
| "LayerUtility: Float": FloatNode, | |
| "LayerUtility: Boolean": BooleanNode, | |
| "LayerUtility: Seed": SeedNode, | |
| "LayerUtility: ImageBatchToList": LS_ImageBatchToMultiList, | |
| "LayerUtility: ImageListToBatch": LS_MultiImageListToBatch, | |
| } | |
| NODE_DISPLAY_NAME_MAPPINGS = { | |
| "LayerUtility: QueueStop": "LayerUtility: Queue Stop", | |
| "LayerUtility: SwitchCase": "LayerUtility: Switch Case", | |
| "LayerUtility: If ": "LayerUtility: If", | |
| "LayerUtility: StringCondition": "LayerUtility: String Condition", | |
| "LayerUtility: BooleanOperator": "LayerUtility: Boolean Operator", | |
| "LayerUtility: NumberCalculator": "LayerUtility: Number Calculator", | |
| "LayerUtility: BooleanOperatorV2": "LayerUtility: Boolean Operator V2", | |
| "LayerUtility: NumberCalculatorV2": "LayerUtility: Number Calculator V2", | |
| "LayerUtility: TextBox": "LayerUtility: TextBox", | |
| "LayerUtility: String": "LayerUtility: String", | |
| "LayerUtility: Integer": "LayerUtility: Integer", | |
| "LayerUtility: Float": "LayerUtility: Float", | |
| "LayerUtility: Boolean": "LayerUtility: Boolean", | |
| "LayerUtility: Seed": "LayerUtility: Seed", | |
| "LayerUtility: ImageBatchToList": "LayerUtility: Image Batch To List(Multi)", | |
| "LayerUtility: ImageListToBatch": "LayerUtility: Image List To Batch(Multi)", | |
| } |