From afa6b6512567dc9964294a1cec8601e1b505802e Mon Sep 17 00:00:00 2001 From: BP <11394934+benjipeng@users.noreply.github.com> Date: Fri, 14 Aug 2026 15:21:33 -0400 Subject: [PATCH 1/2] fix(lito): embed TRELLIS decoder in runtime bundles --- src/mlx_spatial/lito_assets.py | 42 ++++++------------------- src/mlx_spatial/lito_quantization.py | 46 ++++++++++++++++++++++++++-- src/mlx_spatial/lito_real_backend.py | 20 +++++++----- tests/test_lito_assets.py | 15 ++++----- tests/test_lito_cli.py | 6 ++-- tests/test_lito_inference.py | 4 +-- tests/test_lito_quantization.py | 40 ++++++++++++++++++++++++ tests/test_lito_real_backend.py | 20 ++++++++---- 8 files changed, 134 insertions(+), 59 deletions(-) diff --git a/src/mlx_spatial/lito_assets.py b/src/mlx_spatial/lito_assets.py index 7ef5da8..4b5b24e 100644 --- a/src/mlx_spatial/lito_assets.py +++ b/src/mlx_spatial/lito_assets.py @@ -19,7 +19,7 @@ LITO_RAW_DEFAULT_ROOT = "weights/lito-raw" LITO_DEFAULT_ROOT = "weights/lito-research-mlx" LITO_TRELLIS_REPO_ID = "microsoft/TRELLIS-image-large" -LITO_TRELLIS_DEFAULT_ROOT = "weights/trellis2/microsoft/TRELLIS-image-large" +LITO_TRELLIS_BUNDLE_PATH = Path("dependencies/trellis") LITO_COMPONENT_GROUPS = ( "tokenizer", "image_conditioner", @@ -34,6 +34,10 @@ "ckpts/ss_dec_conv3d_16l8_fp16.json", "ckpts/ss_dec_conv3d_16l8_fp16.safetensors", ) +LITO_TRELLIS_METADATA_FILES = ( + "LICENSE", + "SOURCE.json", +) LITO_MODEL_LICENSE = "Apple Machine Learning Research Model License Agreement" LITO_SAMPLE_LICENSE = "CC BY-NC-ND 4.0" @@ -64,12 +68,12 @@ def validate( checkpoint_paths = tuple(root_path / relative_path for _, _, relative_path in LITO_DEFAULT_CHECKPOINTS) runtime_dependency_paths: tuple[Path, ...] = () if include_runtime_dependencies: - trellis_root = _resolve_validation_trellis_root(root_path) + trellis_root = lito_trellis_root(root_path) runtime_dependency_paths = tuple(trellis_root / relative_path for relative_path in LITO_TRELLIS_REQUIRED_FILES) present: list[str] = [] missing: list[str] = [] for path in (*checkpoint_paths, *runtime_dependency_paths): - relative = _runtime_report_path(root_path, path) + relative = _relative_report_path(root_path, path) if path.is_file(): present.append(relative) else: @@ -210,36 +214,10 @@ def _relative_report_path(root: Path, path: Path) -> str: return path.as_posix() -def lito_trellis_root_candidates(root: str | Path = LITO_DEFAULT_ROOT) -> tuple[Path, ...]: - """Return the supported TRELLIS decoder roots for a LiTo weights root.""" - - root_path = Path(root) - candidates = ( - root_path.parent / "trellis2" / "microsoft" / "TRELLIS-image-large", - Path(LITO_TRELLIS_DEFAULT_ROOT), - ) - unique: list[Path] = [] - for candidate in candidates: - if candidate not in unique: - unique.append(candidate) - return tuple(unique) - - -def _resolve_validation_trellis_root(root: Path) -> Path: - candidates = lito_trellis_root_candidates(root) - for candidate in candidates: - if all((candidate / relative_path).is_file() for relative_path in LITO_TRELLIS_REQUIRED_FILES): - return candidate - return candidates[0] - +def lito_trellis_root(root: str | Path = LITO_DEFAULT_ROOT) -> Path: + """Return the bundle-local TRELLIS decoder root for LiTo inference.""" -def _runtime_report_path(root: Path, path: Path) -> str: - if path in tuple(root / relative_path for _, _, relative_path in LITO_DEFAULT_CHECKPOINTS): - return _relative_report_path(root, path) - try: - return path.relative_to(root.parent).as_posix() - except ValueError: - return path.as_posix() + return Path(root) / LITO_TRELLIS_BUNDLE_PATH def _normalize_prefixes(prefixes: Iterable[str] | None) -> tuple[str, ...] | None: diff --git a/src/mlx_spatial/lito_quantization.py b/src/mlx_spatial/lito_quantization.py index 57b34fe..0f55b1a 100644 --- a/src/mlx_spatial/lito_quantization.py +++ b/src/mlx_spatial/lito_quantization.py @@ -6,12 +6,18 @@ import json import math import re +import shutil from dataclasses import dataclass from pathlib import Path from typing import Any, Mapping, Sequence import mlx.core as mx +from .lito_assets import ( + LITO_TRELLIS_BUNDLE_PATH, + LITO_TRELLIS_METADATA_FILES, + LITO_TRELLIS_REQUIRED_FILES, +) from .safetensors_io import ( SafetensorHeader, inspect_safetensors, @@ -386,6 +392,7 @@ def quantize_lito_weights( _validate_quantization_options(bits, group_size) if source.resolve() == output.resolve(): raise ValueError("LiTo quantization output root must differ from the full-precision source root") + dependency_pairs = _lito_bundle_dependency_pairs(source, output, overwrite=overwrite) for relative_path in LITO_QUANTIZED_CHECKPOINTS: source_path = source / relative_path output_path = output / relative_path @@ -393,7 +400,7 @@ def quantize_lito_weights( raise FileNotFoundError(f"LiTo source checkpoint not found: {source_path}") if output_path.exists() and not overwrite: raise FileExistsError(f"LiTo quantization output already exists: {output_path}") - return tuple( + results = tuple( quantize_lito_checkpoint( source / relative_path, output / relative_path, @@ -403,6 +410,8 @@ def quantize_lito_weights( ) for relative_path in LITO_QUANTIZED_CHECKPOINTS ) + _copy_lito_bundle_dependencies(dependency_pairs) + return results def prune_lito_checkpoint( @@ -472,6 +481,7 @@ def prune_lito_weights( source = Path(source_root) output = Path(output_root) + dependency_pairs = _lito_bundle_dependency_pairs(source, output, overwrite=overwrite) for relative_path in LITO_QUANTIZED_CHECKPOINTS: source_path = source / relative_path output_path = output / relative_path @@ -481,7 +491,7 @@ def prune_lito_weights( raise ValueError(f"full-precision LiTo pruning does not accept a quantized source: {source_path}") if output_path.exists() and not overwrite: raise FileExistsError(f"LiTo runtime checkpoint output already exists: {output_path}") - return tuple( + results = tuple( prune_lito_checkpoint( source / relative_path, output / relative_path, @@ -489,6 +499,38 @@ def prune_lito_weights( ) for relative_path in LITO_QUANTIZED_CHECKPOINTS ) + _copy_lito_bundle_dependencies(dependency_pairs) + return results + + +def _lito_bundle_dependency_pairs( + source: Path, + output: Path, + *, + overwrite: bool, +) -> tuple[tuple[Path, Path], ...]: + relative_paths = tuple( + LITO_TRELLIS_BUNDLE_PATH / relative_path + for relative_path in (*LITO_TRELLIS_REQUIRED_FILES, *LITO_TRELLIS_METADATA_FILES) + ) + missing = [source / relative_path for relative_path in relative_paths if not (source / relative_path).is_file()] + if missing: + raise FileNotFoundError(f"LiTo source bundle is missing embedded dependency: {missing[0]}") + if source.resolve() == output.resolve(): + return () + + pairs = tuple((source / relative_path, output / relative_path) for relative_path in relative_paths) + if not overwrite: + existing = [destination for _, destination in pairs if destination.exists()] + if existing: + raise FileExistsError(f"LiTo bundle dependency output already exists: {existing[0]}") + return pairs + + +def _copy_lito_bundle_dependencies(pairs: tuple[tuple[Path, Path], ...]) -> None: + for source, destination in pairs: + destination.parent.mkdir(parents=True, exist_ok=True) + shutil.copy2(source, destination) def _validate_quantization_options(bits: int, group_size: int) -> None: diff --git a/src/mlx_spatial/lito_real_backend.py b/src/mlx_spatial/lito_real_backend.py index 6ef22a7..3f5cc16 100644 --- a/src/mlx_spatial/lito_real_backend.py +++ b/src/mlx_spatial/lito_real_backend.py @@ -17,7 +17,7 @@ import mlx.nn as nn import numpy as np -from .lito_assets import LITO_TRELLIS_REQUIRED_FILES, lito_trellis_root_candidates +from .lito_assets import LITO_TRELLIS_REQUIRED_FILES, lito_trellis_root from .lito_quantization import ( LitoQuantizedMatrix, inspect_logical_lito_safetensors, @@ -2622,12 +2622,18 @@ def _validate_request(request: LitoRealGenerateRequest) -> None: def _resolve_lito_trellis_root(config: LitoRealBackendConfig) -> Path: - candidates = lito_trellis_root_candidates(config.weights_root) - for candidate in candidates: - if (candidate / _TRELLIS_SS_DECODER_CHECKPOINT).is_file() and (candidate / _TRELLIS_SS_DECODER_CONFIG).is_file(): - return candidate - searched = ", ".join(str(path) for path in candidates) - raise LitoBackendUnavailable(f"TRELLIS sparse-structure decoder weights are required for LiTo init coords; searched {searched}") + root = lito_trellis_root(config.weights_root) + missing = [ + path + for path in (_TRELLIS_SS_DECODER_CONFIG, _TRELLIS_SS_DECODER_CHECKPOINT) + if not (root / path).is_file() + ] + if missing: + relative = ", ".join(str(path) for path in missing) + raise LitoBackendUnavailable( + f"LiTo bundle is missing embedded TRELLIS sparse-structure decoder files under {root}: {relative}" + ) + return root def _as_numpy(value: Any, name: str) -> np.ndarray: diff --git a/tests/test_lito_assets.py b/tests/test_lito_assets.py index 799367e..723c589 100644 --- a/tests/test_lito_assets.py +++ b/tests/test_lito_assets.py @@ -6,6 +6,7 @@ from mlx_spatial.lito_assets import ( LITO_DEFAULT_CHECKPOINTS, LITO_REPO_ID, + LITO_TRELLIS_BUNDLE_PATH, LITO_TRELLIS_REQUIRED_FILES, convert, download_command, @@ -34,7 +35,7 @@ def _write_lito_fixture(root): def test_validate_layout_passes_on_downloaded_weights(tmp_path): root = tmp_path / "lito-research-mlx" _write_lito_fixture(root) - _write_trellis_fixture(tmp_path / "trellis2/microsoft/TRELLIS-image-large") + _write_trellis_fixture(root / LITO_TRELLIS_BUNDLE_PATH) validation = validate(root) @@ -43,22 +44,22 @@ def test_validate_layout_passes_on_downloaded_weights(tmp_path): assert validation.present == ( "tokenizer/lito_new.safetensors", "image_to_3d/lito_dit_rgba.safetensors", - "trellis2/microsoft/TRELLIS-image-large/ckpts/ss_dec_conv3d_16l8_fp16.json", - "trellis2/microsoft/TRELLIS-image-large/ckpts/ss_dec_conv3d_16l8_fp16.safetensors", + "dependencies/trellis/ckpts/ss_dec_conv3d_16l8_fp16.json", + "dependencies/trellis/ckpts/ss_dec_conv3d_16l8_fp16.safetensors", ) -def test_validate_reports_missing_trellis_runtime_dependency(tmp_path, monkeypatch): - monkeypatch.chdir(tmp_path) +def test_validate_reports_missing_bundle_local_trellis_runtime_dependency(tmp_path): root = tmp_path / "lito-research-mlx" _write_lito_fixture(root) + _write_trellis_fixture(tmp_path / "trellis2/microsoft/TRELLIS-image-large") validation = validate(root) assert not validation.ready assert validation.missing == ( - "trellis2/microsoft/TRELLIS-image-large/ckpts/ss_dec_conv3d_16l8_fp16.json", - "trellis2/microsoft/TRELLIS-image-large/ckpts/ss_dec_conv3d_16l8_fp16.safetensors", + "dependencies/trellis/ckpts/ss_dec_conv3d_16l8_fp16.json", + "dependencies/trellis/ckpts/ss_dec_conv3d_16l8_fp16.safetensors", ) diff --git a/tests/test_lito_cli.py b/tests/test_lito_cli.py index 032cac1..737bd6b 100644 --- a/tests/test_lito_cli.py +++ b/tests/test_lito_cli.py @@ -11,7 +11,7 @@ from tests.safetensors_test_utils import save_file from mlx_spatial.lito import main as lito_main -from mlx_spatial.lito_assets import LITO_TRELLIS_REQUIRED_FILES +from mlx_spatial.lito_assets import LITO_TRELLIS_BUNDLE_PATH, LITO_TRELLIS_REQUIRED_FILES from mlx_spatial.lito_inference import LitoGenerationResult @@ -26,7 +26,7 @@ def test_pyproject_exposes_lito_script_entry(): def test_cli_validate_returns_zero_on_valid_weights(tmp_path, capsys): root = _write_valid_weights(tmp_path / "weights") - _write_trellis_runtime_assets(tmp_path / "trellis2/microsoft/TRELLIS-image-large") + _write_trellis_runtime_assets(root / LITO_TRELLIS_BUNDLE_PATH) assert lito_main(["validate", str(root)]) == 0 output = capsys.readouterr().out @@ -266,7 +266,7 @@ def test_cli_generate_fails_closed_without_smoke_flag(tmp_path, capsys): def test_cli_generate_rejects_placeholder_weights_without_smoke_flag(tmp_path, capsys): root = _write_valid_weights(tmp_path / "weights") - _write_trellis_runtime_assets(tmp_path / "trellis2/microsoft/TRELLIS-image-large") + _write_trellis_runtime_assets(root / LITO_TRELLIS_BUNDLE_PATH) image = _write_synthetic_image(tmp_path / "input.png") output = tmp_path / "test.ply" diff --git a/tests/test_lito_inference.py b/tests/test_lito_inference.py index 0f06615..5fcff13 100644 --- a/tests/test_lito_inference.py +++ b/tests/test_lito_inference.py @@ -10,7 +10,7 @@ from tests.safetensors_test_utils import load_file from mlx_spatial.lito import LitoInferencePipeline -from mlx_spatial.lito_assets import LITO_TRELLIS_REQUIRED_FILES +from mlx_spatial.lito_assets import LITO_TRELLIS_BUNDLE_PATH, LITO_TRELLIS_REQUIRED_FILES from mlx_spatial.lito_inference import ( LITO_RECOMMENDED_CFG_SCALE, LITO_RECOMMENDED_NUM_STEPS, @@ -199,7 +199,7 @@ def test_generate_rejects_placeholder_weight_files_by_default(tmp_path): root = tmp_path / "weights" (root / "tokenizer").mkdir(parents=True) (root / "image_to_3d").mkdir(parents=True) - _write_trellis_runtime_assets(tmp_path / "trellis2/microsoft/TRELLIS-image-large") + _write_trellis_runtime_assets(root / LITO_TRELLIS_BUNDLE_PATH) save_file({"tokenizer.weight": np.ones((1,), dtype=np.float32)}, root / "tokenizer" / "lito_new.safetensors") save_file( {"dit.weight": np.ones((1,), dtype=np.float32)}, diff --git a/tests/test_lito_quantization.py b/tests/test_lito_quantization.py index 55c6120..dafb983 100644 --- a/tests/test_lito_quantization.py +++ b/tests/test_lito_quantization.py @@ -15,9 +15,15 @@ load_logical_lito_safetensors, prune_lito_checkpoint, quantize_lito_checkpoint, + quantize_lito_weights, read_lito_quantization_spec, should_quantize_lito_tensor, ) +from mlx_spatial.lito_assets import ( + LITO_TRELLIS_BUNDLE_PATH, + LITO_TRELLIS_METADATA_FILES, + LITO_TRELLIS_REQUIRED_FILES, +) from mlx_spatial.safetensors_io import inspect_safetensors, read_safetensors_metadata, save_safetensors @@ -161,6 +167,40 @@ def test_quantized_checkpoint_round_trip_executes_packed_affine_matmul(tmp_path) np.testing.assert_allclose(np.asarray(actual), np.asarray(expected), rtol=2e-2, atol=2e-2) +def test_quantize_lito_weights_copies_embedded_trellis_dependency(tmp_path): + source = tmp_path / "full" + output = tmp_path / "int8" + tensors_by_path = { + "image_to_3d/lito_dit_rgba.safetensors": { + "velocity_estimator_ema.module.blocks.0.attn.linear_qkv.weight": np.ones( + (64, 64), dtype=np.float32 + ) + }, + "tokenizer/lito_new.safetensors": { + "gs_decoder.perceiver.blocks.0.ca_layer.linear_q.weight": np.ones( + (64, 64), dtype=np.float32 + ) + }, + } + for relative_path, tensors in tensors_by_path.items(): + checkpoint = source / relative_path + checkpoint.parent.mkdir(parents=True, exist_ok=True) + save_safetensors(checkpoint, tensors) + + dependency_files = (*LITO_TRELLIS_REQUIRED_FILES, *LITO_TRELLIS_METADATA_FILES) + for index, relative_path in enumerate(dependency_files): + path = source / LITO_TRELLIS_BUNDLE_PATH / relative_path + path.parent.mkdir(parents=True, exist_ok=True) + path.write_bytes(f"dependency-{index}".encode("utf-8")) + + quantize_lito_weights(source, output) + + for relative_path in dependency_files: + source_path = source / LITO_TRELLIS_BUNDLE_PATH / relative_path + output_path = output / LITO_TRELLIS_BUNDLE_PATH / relative_path + assert output_path.read_bytes() == source_path.read_bytes() + + def test_gaussian_loader_splits_packed_fused_swiglu_rows(tmp_path): from mlx_spatial.lito_real_backend import load_lito_gaussian_decoder_weight_arrays diff --git a/tests/test_lito_real_backend.py b/tests/test_lito_real_backend.py index a888c1c..235726d 100644 --- a/tests/test_lito_real_backend.py +++ b/tests/test_lito_real_backend.py @@ -12,7 +12,7 @@ from tests.safetensors_test_utils import save_file from mlx_spatial.lito import LitoInferencePipeline -from mlx_spatial.lito_assets import LITO_TRELLIS_REQUIRED_FILES +from mlx_spatial.lito_assets import LITO_TRELLIS_BUNDLE_PATH, LITO_TRELLIS_REQUIRED_FILES from mlx_spatial.lito_inference import LITO_REAL_TENSOR_SENTINELS @@ -766,13 +766,19 @@ def test_real_voxel_decoder_lowres_latent_runs_from_loaded_checkpoint_weights(): @pytest.mark.skipif( not ( Path(__file__).resolve().parents[1] - / "weights/trellis2/microsoft/TRELLIS-image-large/ckpts/ss_dec_conv3d_16l8_fp16.safetensors" + / "weights/lito-research-mlx" + / LITO_TRELLIS_BUNDLE_PATH + / "ckpts/ss_dec_conv3d_16l8_fp16.safetensors" ).is_file(), reason="TRELLIS sparse-structure decoder weights absent", ) def test_real_trellis_sparse_structure_decoder_logits_run_from_local_mlx_weights(): backend = importlib.import_module("mlx_spatial.lito_real_backend") - root = Path(__file__).resolve().parents[1] / "weights/trellis2/microsoft/TRELLIS-image-large" + root = ( + Path(__file__).resolve().parents[1] + / "weights/lito-research-mlx" + / LITO_TRELLIS_BUNDLE_PATH + ) ss_latent = np.zeros((1, 8, 16, 16, 16), dtype=np.float32) logits = backend.decode_lito_trellis_sparse_structure_logits(ss_latent, trellis_root=root) @@ -792,7 +798,9 @@ def test_real_trellis_sparse_structure_decoder_logits_run_from_local_mlx_weights ).is_file() or not ( Path(__file__).resolve().parents[1] - / "weights/trellis2/microsoft/TRELLIS-image-large/ckpts/ss_dec_conv3d_16l8_fp16.safetensors" + / "weights/lito-research-mlx" + / LITO_TRELLIS_BUNDLE_PATH + / "ckpts/ss_dec_conv3d_16l8_fp16.safetensors" ).is_file(), reason="LiTo or TRELLIS sparse-structure decoder weights absent", ) @@ -800,7 +808,7 @@ def test_real_init_coord_generation_from_latents_runs_with_local_mlx_weights(): backend = importlib.import_module("mlx_spatial.lito_real_backend") repo = Path(__file__).resolve().parents[1] lito_root = repo / "weights/lito-research-mlx" - trellis_root = repo / "weights/trellis2/microsoft/TRELLIS-image-large" + trellis_root = lito_root / LITO_TRELLIS_BUNDLE_PATH voxel_weights = backend.load_lito_voxel_decoder_weight_arrays(lito_root) latent_tokens = np.zeros((1, 2, 32), dtype=np.float32) @@ -1185,7 +1193,7 @@ def _write_fake_lito_weights(root: Path) -> Path: path = root / relative_path path.parent.mkdir(parents=True, exist_ok=True) save_file(tensors, path) - trellis_root = root.parent / "trellis2" / "microsoft" / "TRELLIS-image-large" + trellis_root = root / LITO_TRELLIS_BUNDLE_PATH for relative_path in LITO_TRELLIS_REQUIRED_FILES: path = trellis_root / relative_path path.parent.mkdir(parents=True, exist_ok=True) From b0bab77fad7d2438f758750d2fc3bc9ea93133cc Mon Sep 17 00:00:00 2001 From: BP <11394934+benjipeng@users.noreply.github.com> Date: Fri, 14 Aug 2026 15:24:12 -0400 Subject: [PATCH 2/2] docs(lito): document self-contained runtime bundles --- README.md | 4 - docs/lito.md | 25 ++-- docs/model-publishing.md | 5 + .../lito-research-mlx-8bit/LICENSE_MODEL | 88 +++++++++++++ model-cards/lito-research-mlx-8bit/README.md | 121 ++++++++++++++++++ .../dependencies/trellis/LICENSE | 21 +++ .../dependencies/trellis/SOURCE.json | 15 +++ model-cards/lito-research-mlx/README.md | 82 +++++++----- .../dependencies/trellis/LICENSE | 21 +++ .../dependencies/trellis/SOURCE.json | 15 +++ scripts/README.md | 8 +- 11 files changed, 352 insertions(+), 53 deletions(-) create mode 100644 model-cards/lito-research-mlx-8bit/LICENSE_MODEL create mode 100644 model-cards/lito-research-mlx-8bit/README.md create mode 100644 model-cards/lito-research-mlx-8bit/dependencies/trellis/LICENSE create mode 100644 model-cards/lito-research-mlx-8bit/dependencies/trellis/SOURCE.json create mode 100644 model-cards/lito-research-mlx/dependencies/trellis/LICENSE create mode 100644 model-cards/lito-research-mlx/dependencies/trellis/SOURCE.json diff --git a/README.md b/README.md index 3ef8ae4..0025589 100644 --- a/README.md +++ b/README.md @@ -103,10 +103,6 @@ uv run hf download appautomaton/sam-3d-objects-mlx --local-dir weights/sam-3d-ob uv run mlx-spatial-sam3d validate weights/sam-3d-objects-mlx uv run hf download appautomaton/lito-research-mlx --local-dir weights/lito-research-mlx -uv run hf download microsoft/TRELLIS-image-large \ - ckpts/ss_dec_conv3d_16l8_fp16.json \ - ckpts/ss_dec_conv3d_16l8_fp16.safetensors \ - --local-dir weights/trellis2/microsoft/TRELLIS-image-large uv run mlx-spatial-lito validate weights/lito-research-mlx ``` diff --git a/docs/lito.md b/docs/lito.md index 6f10b71..b86743d 100644 --- a/docs/lito.md +++ b/docs/lito.md @@ -21,10 +21,6 @@ Recommended runtime bundle: ```bash uv run hf download appautomaton/lito-research-mlx \ --local-dir weights/lito-research-mlx -uv run hf download microsoft/TRELLIS-image-large \ - ckpts/ss_dec_conv3d_16l8_fp16.json \ - ckpts/ss_dec_conv3d_16l8_fp16.safetensors \ - --local-dir weights/trellis2/microsoft/TRELLIS-image-large uv run mlx-spatial-lito validate weights/lito-research-mlx uv run mlx-spatial-lito inspect weights/lito-research-mlx --limit 10 ``` @@ -34,16 +30,19 @@ Expected converted layout: ```text weights/lito-research-mlx/tokenizer/lito_new.safetensors weights/lito-research-mlx/image_to_3d/lito_dit_rgba.safetensors -weights/trellis2/microsoft/TRELLIS-image-large/ckpts/ss_dec_conv3d_16l8_fp16.json -weights/trellis2/microsoft/TRELLIS-image-large/ckpts/ss_dec_conv3d_16l8_fp16.safetensors +weights/lito-research-mlx/dependencies/trellis/LICENSE +weights/lito-research-mlx/dependencies/trellis/SOURCE.json +weights/lito-research-mlx/dependencies/trellis/ckpts/ss_dec_conv3d_16l8_fp16.json +weights/lito-research-mlx/dependencies/trellis/ckpts/ss_dec_conv3d_16l8_fp16.safetensors ``` -The first two files are the LiTo bundle. The final two are the sparse-structure -decoder used to convert LiTo voxel latents into Gaussian initialization -coordinates. They come from `microsoft/TRELLIS-image-large`, not from the -`microsoft/TRELLIS.2-4B` bundle used by the separate TRELLIS.2 pipeline. -`mlx-spatial-lito validate` checks all four runtime files; `inspect` reads only -the two LiTo safetensors. +The embedded sparse-structure decoder converts LiTo voxel latents into Gaussian +initialization coordinates. It is the exact checkpoint from +`microsoft/TRELLIS-image-large` revision +`25e0d31ffbebe4b5a97464dd851910efc3002d96`, not a dependency on the separate +TRELLIS.2 pipeline. `mlx-spatial-lito validate` requires the bundle-local +decoder and never searches an external TRELLIS root. `inspect` reads only the +two LiTo safetensors. Maintainers can print Apple CDN download commands and convert local `.ckpt` files: @@ -85,6 +84,8 @@ checkpoint records the exact policy, logical tensor shapes, bit width, group size, and affine mode in safetensors metadata. The normal LiTo loader detects that metadata and executes packed matrices directly with MLX quantized matrix multiplication; no Torch or intermediate dequantized checkpoint is involved. +The root-level quantizer copies the embedded TRELLIS decoder and its provenance +files into the output bundle unchanged. Pass the new root to inference exactly as you would the full-precision root: diff --git a/docs/model-publishing.md b/docs/model-publishing.md index 7f75f52..265f848 100644 --- a/docs/model-publishing.md +++ b/docs/model-publishing.md @@ -42,9 +42,14 @@ The tracked model-card source lives under: ```text model-cards/lito-research-mlx/ +model-cards/lito-research-mlx-8bit/ ``` LiTo is research-only and non-commercial under Apple's model license. The model repository must include `LICENSE_MODEL`, identify the safetensors files as an unofficial converted derivative, and avoid language that implies Apple endorsement. +Both LiTo variants must embed the required Microsoft TRELLIS sparse-structure +decoder under `dependencies/trellis/`, together with its MIT license and an +immutable source manifest. Published LiTo bundles must not depend on a sibling +TRELLIS checkout. ## What The Model Card Should Contain diff --git a/model-cards/lito-research-mlx-8bit/LICENSE_MODEL b/model-cards/lito-research-mlx-8bit/LICENSE_MODEL new file mode 100644 index 0000000..813ad18 --- /dev/null +++ b/model-cards/lito-research-mlx-8bit/LICENSE_MODEL @@ -0,0 +1,88 @@ +Disclaimer: IMPORTANT: This Apple Machine Learning Research Model is +specifically developed and released by Apple Inc. ("Apple") for the sole purpose +of scientific research of artificial intelligence and machine-learning +technology. “Apple Machine Learning Research Model” means the model, including +but not limited to algorithms, formulas, trained model weights, parameters, +configurations, checkpoints, and any related materials (including +documentation). + +This Apple Machine Learning Research Model is provided to You by +Apple in consideration of your agreement to the following terms, and your use, +modification, creation of Model Derivatives, and or redistribution of the Apple +Machine Learning Research Model constitutes acceptance of this Agreement. If You +do not agree with these terms, please do not use, modify, create Model +Derivatives of, or distribute this Apple Machine Learning Research Model or +Model Derivatives. + +* License Scope: In consideration of your agreement to abide by the following + terms, and subject to these terms, Apple hereby grants you a personal, + non-exclusive, worldwide, non-transferable, royalty-free, revocable, and + limited license, to use, copy, modify, distribute, and create Model + Derivatives (defined below) of the Apple Machine Learning Research Model + exclusively for Research Purposes. You agree that any Model Derivatives You + may create or that may be created for You will be limited to Research Purposes + as well. “Research Purposes” means non-commercial scientific research and + academic development activities, such as experimentation, analysis, testing + conducted by You with the sole intent to advance scientific knowledge and + research. “Research Purposes” does not include any commercial exploitation, + product development or use in any commercial product or service. + +* Distribution of Apple Machine Learning Research Model and Model Derivatives: + If you choose to redistribute Apple Machine Learning Research Model or its + Model Derivatives, you must provide a copy of this Agreement to such third + party, and ensure that the following attribution notice be provided: “Apple + Machine Learning Research Model is licensed under the Apple Machine Learning + Research Model License Agreement.” Additionally, all Model Derivatives must + clearly be identified as such, including disclosure of modifications and + changes made to the Apple Machine Learning Research Model. The name, + trademarks, service marks or logos of Apple may not be used to endorse or + promote Model Derivatives or the relationship between You and Apple. “Model + Derivatives” means any models or any other artifacts created by modifications, + improvements, adaptations, alterations to the architecture, algorithm or + training processes of the Apple Machine Learning Research Model, or by any + retraining, fine-tuning of the Apple Machine Learning Research Model. + +* No Other License: Except as expressly stated in this notice, no other rights + or licenses, express or implied, are granted by Apple herein, including but + not limited to any patent, trademark, and similar intellectual property rights + worldwide that may be infringed by the Apple Machine Learning Research Model, + the Model Derivatives or by other works in which the Apple Machine Learning + Research Model may be incorporated. + +* Compliance with Laws: Your use of Apple Machine Learning Research Model must + be in compliance with all applicable laws and regulations. + +* Term and Termination: The term of this Agreement will begin upon your + acceptance of this Agreement or use of the Apple Machine Learning Research + Model and will continue until terminated in accordance with the following + terms. Apple may terminate this Agreement at any time if You are in breach of + any term or condition of this Agreement. Upon termination of this Agreement, + You must cease to use all Apple Machine Learning Research Models and Model + Derivatives and permanently delete any copy thereof. Sections 3, 6 and 7 will + survive termination. + +* Disclaimer and Limitation of Liability: This Apple Machine Learning Research + Model and any outputs generated by the Apple Machine Learning Research Model + are provided on an “AS IS” basis. APPLE MAKES NO WARRANTIES, EXPRESS OR + IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, + REGARDING THE APPLE MACHINE LEARNING RESEARCH MODEL OR OUTPUTS GENERATED BY + THE APPLE MACHINE LEARNING RESEARCH MODEL. You are solely responsible for + determining the appropriateness of using or redistributing the Apple Machine + Learning Research Model and any outputs of the Apple Machine Learning Research + Model and assume any risks associated with Your use of the Apple Machine + Learning Research Model and any output and results. IN NO EVENT SHALL APPLE BE + LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING + IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF + THE APPLE MACHINE LEARNING RESEARCH MODEL AND ANY OUTPUTS OF THE APPLE MACHINE + LEARNING RESEARCH MODEL, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, + TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS + BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +* Governing Law: This Agreement will be governed by and construed under the laws + of the State of California without regard to its choice of law principles. The + Convention on Contracts for the International Sale of Goods shall not apply to + the Agreement except that the arbitration clause and any arbitration hereunder + shall be governed by the Federal Arbitration Act, Chapters 1 and 2. + +Copyright (C) 2026 Apple Inc. All Rights Reserved. diff --git a/model-cards/lito-research-mlx-8bit/README.md b/model-cards/lito-research-mlx-8bit/README.md new file mode 100644 index 0000000..d387bf7 --- /dev/null +++ b/model-cards/lito-research-mlx-8bit/README.md @@ -0,0 +1,121 @@ +--- +license: other +license_name: apple-machine-learning-research-model-license-agreement +license_link: https://github.com/apple/ml-lito/blob/main/LICENSE_MODEL +library_name: mlx +pipeline_tag: image-to-3d +base_model: + - appautomaton/lito-research-mlx +tags: + - mlx + - apple-silicon + - safetensors + - image-to-3d + - gaussian-splatting + - 3dgs + - 8-bit + - affine-quantization + - runtime-only + - research-only + - non-commercial +--- + +# LiTo Runtime 8-bit Affine for `mlx-spatial` + +A self-contained LiTo inference bundle with selective affine INT8 weights for +Apple Silicon. Accuracy-sensitive boundaries remain in FP32. This is an +unofficial derivative for non-commercial research use, not an Apple release. + +## Use + +```bash +pip install \ + "mlx-spatial @ git+https://github.com/appautomaton/mlx-spatial.git@afa6b6512567dc9964294a1cec8601e1b505802e" + +hf download appautomaton/lito-research-mlx-8bit \ + --local-dir weights/lito-research-mlx-8bit + +mlx-spatial-lito validate weights/lito-research-mlx-8bit + +mlx-spatial-lito generate inputs/lito/object-rgba.png \ + --weights-root weights/lito-research-mlx-8bit \ + --output outputs/lito/object-8bit.ply \ + --format ply \ + --num-steps 20 \ + --cfg-scale 3.0 \ + --print-metrics +``` + +The output is a 3D Gaussian Splat PLY, not a triangle mesh. A clean RGBA +foreground matte is strongly recommended. + +## Bundle + +| File | Logical tensors | Quantized matrices | Bytes | +| --- | ---: | ---: | ---: | +| `image_to_3d/lito_dit_rgba.safetensors` | 1,016 | 224 | 2,004,347,727 | +| `tokenizer/lito_new.safetensors` | 467 | 124 | 168,537,103 | +| `dependencies/trellis/ckpts/ss_dec_conv3d_16l8_fp16.safetensors` | 74 | 0 | 147,591,972 | +| **Runtime weights** | **1,557** | **348** | **2,320,476,802** | + +The bundle also includes the decoder config, Microsoft MIT license, and an +immutable source manifest under `dependencies/trellis/`. + +The LiTo quantization scheme is affine 8-bit with group size 64. Packed weights +are stored as `uint32` with FP32 scales and biases and execute directly through +`mx.quantized_matmul`. Internal attention and MLP matrices in the EMA DiT, +Gaussian decoder, and voxel decoder are quantized. The image conditioner, +convolutions, embeddings, normalizations, boundary projections, and output +heads remain FP32. + +## Embedded TRELLIS Decoder + +LiTo uses the TRELLIS sparse-structure decoder to convert voxel latents into +Gaussian initialization coordinates. This bundle embeds the exact checkpoint +from `microsoft/TRELLIS-image-large` revision +`25e0d31ffbebe4b5a97464dd851910efc3002d96`: + +```text +dependencies/trellis/LICENSE +dependencies/trellis/SOURCE.json +dependencies/trellis/ckpts/ss_dec_conv3d_16l8_fp16.json +dependencies/trellis/ckpts/ss_dec_conv3d_16l8_fp16.safetensors +``` + +The decoder safetensors SHA-256 is +`1c76d4a40519aa2d711cc263a8404105231ac26db31d946bed48b84fee79009a`. +The runtime does not search a separate TRELLIS checkout. + +## Verification + +- Both checkpoints pass `mlx-spatial-lito validate`. +- Architecture inspection recovers 28 DiT blocks, 6 Gaussian Perceiver blocks, + and 4 voxel decoder blocks. +- Real-weight Linear probes measured `0.51%–0.61%` relative RMSE and cosine + similarity above `0.99998` against FP32. +- An uncapped 20-step run produced 557,568 finite Gaussians in 2 minutes + 39.76 seconds, with 11.60 GiB peak active MLX memory. +- A separate bundle-local 20-step validation produced 8,192 finite Gaussians + after explicitly capping occupied cells for packaging verification. + +These figures are one local Apple Silicon observation, not a general benchmark +or an official quality-equivalence claim. + +## Limitations and Licenses + +- Inference only; training and mesh-specific modules are intentionally absent. +- Quantization can change generation details relative to FP32. +- Single-view reconstruction cannot determine unseen geometry with certainty. +- Commercial use is not permitted by Apple's model license. + +LiTo weights are covered by the bundled `LICENSE_MODEL`. The embedded TRELLIS +decoder is covered by the MIT License under `dependencies/trellis/LICENSE`. + +> Apple Machine Learning Research Model is licensed under the Apple Machine Learning Research Model License Agreement. + +## Links + +- [FP32 runtime variant](https://huggingface.co/appautomaton/lito-research-mlx) +- [`appautomaton/mlx-spatial`](https://github.com/appautomaton/mlx-spatial) +- [Apple LiTo project](https://apple.github.io/ml-lito/) +- [Apple LiTo source](https://github.com/apple/ml-lito) diff --git a/model-cards/lito-research-mlx-8bit/dependencies/trellis/LICENSE b/model-cards/lito-research-mlx-8bit/dependencies/trellis/LICENSE new file mode 100644 index 0000000..22aed37 --- /dev/null +++ b/model-cards/lito-research-mlx-8bit/dependencies/trellis/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) Microsoft Corporation. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/model-cards/lito-research-mlx-8bit/dependencies/trellis/SOURCE.json b/model-cards/lito-research-mlx-8bit/dependencies/trellis/SOURCE.json new file mode 100644 index 0000000..0d17155 --- /dev/null +++ b/model-cards/lito-research-mlx-8bit/dependencies/trellis/SOURCE.json @@ -0,0 +1,15 @@ +{ + "files": { + "ckpts/ss_dec_conv3d_16l8_fp16.json": { + "bytes": 245, + "sha256": "646781293f1cda74720de85d1cef50a957fb4aebd9a4bd014e454e32f2330ac5" + }, + "ckpts/ss_dec_conv3d_16l8_fp16.safetensors": { + "bytes": 147591972, + "sha256": "1c76d4a40519aa2d711cc263a8404105231ac26db31d946bed48b84fee79009a" + } + }, + "license": "MIT", + "repo_id": "microsoft/TRELLIS-image-large", + "revision": "25e0d31ffbebe4b5a97464dd851910efc3002d96" +} diff --git a/model-cards/lito-research-mlx/README.md b/model-cards/lito-research-mlx/README.md index 8a7e0d3..b52adea 100644 --- a/model-cards/lito-research-mlx/README.md +++ b/model-cards/lito-research-mlx/README.md @@ -10,37 +10,39 @@ tags: - image-to-3d - gaussian-splatting - 3dgs + - fp32 + - runtime-only - research-only - non-commercial base_model: - apple/ml-lito --- -# LiTo Research MLX for mlx-spatial +# LiTo Runtime FP32 for `mlx-spatial` Run Apple's LiTo image-to-3D Gaussian Splat model on Apple Silicon through `mlx-spatial`, using MLX-ready safetensors instead of local `.ckpt` conversion. -This bundle is for researchers who want a practical Mac-native LiTo inference path: download the weights, point `mlx-spatial-lito` at them, and generate a 3D Gaussian Splat PLY from an input image. No CUDA is required. +This runtime-pruned bundle is for researchers who want a practical Mac-native +LiTo inference path: download one repository and generate a 3D Gaussian Splat +PLY from an input image. No CUDA is required. ## Quick Start: Image to 3DGS on Apple Silicon Install `mlx-spatial`: ```bash -pip install mlx-spatial==0.0.3 +pip install \ + "mlx-spatial @ git+https://github.com/appautomaton/mlx-spatial.git@afa6b6512567dc9964294a1cec8601e1b505802e" ``` -This model card targets `mlx-spatial` 0.0.3. +This model card requires the bundle-local LiTo dependency layout introduced by +the immutable runtime commit above. Download this model bundle: ```bash hf download appautomaton/lito-research-mlx \ --local-dir weights/lito-research-mlx -hf download microsoft/TRELLIS-image-large \ - ckpts/ss_dec_conv3d_16l8_fp16.json \ - ckpts/ss_dec_conv3d_16l8_fp16.safetensors \ - --local-dir weights/trellis2/microsoft/TRELLIS-image-large ``` Validate the local layout: @@ -64,32 +66,32 @@ The output is a 3D Gaussian Splat PLY, not a mesh. Use a 3DGS-aware viewer such ## What This Model Bundle Provides -This Hugging Face repository contains the LiTo-specific safetensors expected by `mlx-spatial`: +This Hugging Face repository is a self-contained LiTo runtime bundle for +`mlx-spatial`: ```text tokenizer/lito_new.safetensors image_to_3d/lito_dit_rgba.safetensors +dependencies/trellis/LICENSE +dependencies/trellis/SOURCE.json +dependencies/trellis/ckpts/ss_dec_conv3d_16l8_fp16.json +dependencies/trellis/ckpts/ss_dec_conv3d_16l8_fp16.safetensors ``` -It also includes lightweight conversion metadata: - -```text -tokenizer/conversion_metadata/lito_new.yaml -image_to_3d/conversion_metadata/lito_dit_rgba.yaml -``` - -End-to-end LiTo generation also needs these two files from the separate -`microsoft/TRELLIS-image-large` repository: - -```text -weights/trellis2/microsoft/TRELLIS-image-large/ckpts/ss_dec_conv3d_16l8_fp16.json -weights/trellis2/microsoft/TRELLIS-image-large/ckpts/ss_dec_conv3d_16l8_fp16.safetensors -``` - -They are not part of the newer `microsoft/TRELLIS.2-4B` bundle and are not -included in this LiTo repository. `mlx-spatial-lito validate` checks both the -LiTo checkpoints and this runtime decoder dependency; `inspect` reads only the -LiTo safetensors. +The embedded decoder is the exact 147,591,972-byte checkpoint from +`microsoft/TRELLIS-image-large` revision +`25e0d31ffbebe4b5a97464dd851910efc3002d96`, with SHA-256 +`1c76d4a40519aa2d711cc263a8404105231ac26db31d946bed48b84fee79009a`. +It converts LiTo voxel latents into Gaussian initialization coordinates. +`mlx-spatial-lito validate` requires this bundle-local decoder and does not +search a separate TRELLIS checkout. + +| File | Logical tensors | Bytes | +| --- | ---: | ---: | +| `image_to_3d/lito_dit_rgba.safetensors` | 1,016 | 3,713,563,945 | +| `tokenizer/lito_new.safetensors` | 467 | 521,201,761 | +| `dependencies/trellis/ckpts/ss_dec_conv3d_16l8_fp16.safetensors` | 74 | 147,591,972 | +| **Runtime weights** | **1,557** | **4,382,357,678** | ## Best For @@ -108,9 +110,24 @@ LiTo safetensors. ## Conversion Details -The files in this repository were converted from Apple's original `.ckpt` checkpoints to safetensors for local MLX loading. The conversion changes storage format and local layout only. - -No training, fine-tuning, quantization, pruning, or tensor-value modification was applied. +The LiTo files were converted from Apple's original `.ckpt` checkpoints to +safetensors and pruned to the modules read by the main inference path. The +bundle retains the EMA velocity estimator, DINO/RGBA image conditioner, +Gaussian decoder, and voxel decoder. It removes the non-EMA training copy, +duplicate tokenizer, mesh/fpoint/LPIPS modules, and training-only decoders. +Retained tensor values, shapes, and dtypes are unchanged; no retained LiTo +tensor is quantized. The embedded TRELLIS decoder is redistributed unchanged +from the immutable Microsoft source revision recorded above. + +## Verification + +- Both checkpoints and the embedded decoder pass `mlx-spatial-lito validate`. +- Architecture inspection recovers 28 DiT blocks, 6 Gaussian Perceiver blocks, + and 4 voxel decoder blocks. +- The bundle exposes 1,483 LiTo logical inference tensors. +- A bundle-local 20-step runtime validation produced 8,192 finite Gaussians + after explicitly capping occupied cells for packaging verification. This is + not an uncapped quality benchmark. ## Project Links @@ -136,3 +153,6 @@ This repository is not an Apple release and is not endorsed by Apple. Redistribu Required attribution notice: > Apple Machine Learning Research Model is licensed under the Apple Machine Learning Research Model License Agreement. + +The embedded TRELLIS dependency is licensed under the MIT License. Its license +copy and immutable source metadata are included under `dependencies/trellis/`. diff --git a/model-cards/lito-research-mlx/dependencies/trellis/LICENSE b/model-cards/lito-research-mlx/dependencies/trellis/LICENSE new file mode 100644 index 0000000..22aed37 --- /dev/null +++ b/model-cards/lito-research-mlx/dependencies/trellis/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) Microsoft Corporation. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/model-cards/lito-research-mlx/dependencies/trellis/SOURCE.json b/model-cards/lito-research-mlx/dependencies/trellis/SOURCE.json new file mode 100644 index 0000000..0d17155 --- /dev/null +++ b/model-cards/lito-research-mlx/dependencies/trellis/SOURCE.json @@ -0,0 +1,15 @@ +{ + "files": { + "ckpts/ss_dec_conv3d_16l8_fp16.json": { + "bytes": 245, + "sha256": "646781293f1cda74720de85d1cef50a957fb4aebd9a4bd014e454e32f2330ac5" + }, + "ckpts/ss_dec_conv3d_16l8_fp16.safetensors": { + "bytes": 147591972, + "sha256": "1c76d4a40519aa2d711cc263a8404105231ac26db31d946bed48b84fee79009a" + } + }, + "license": "MIT", + "repo_id": "microsoft/TRELLIS-image-large", + "revision": "25e0d31ffbebe4b5a97464dd851910efc3002d96" +} diff --git a/scripts/README.md b/scripts/README.md index 2ab6855..cda7e1d 100644 --- a/scripts/README.md +++ b/scripts/README.md @@ -151,16 +151,12 @@ do not infer reference equivalence from the existence of a GLB. See ### LiTo -LiTo needs both the converted LiTo bundle and the TRELLIS sparse-structure -decoder used for initialization coordinates: +The LiTo bundle includes the TRELLIS sparse-structure decoder used for +initialization coordinates: ```bash uv run hf download appautomaton/lito-research-mlx \ --local-dir weights/lito-research-mlx -uv run hf download microsoft/TRELLIS-image-large \ - ckpts/ss_dec_conv3d_16l8_fp16.json \ - ckpts/ss_dec_conv3d_16l8_fp16.safetensors \ - --local-dir weights/trellis2/microsoft/TRELLIS-image-large uv run mlx-spatial-lito validate weights/lito-research-mlx uv run python scripts/lito/generate.py inputs/lito/sample.png \ --weights-root weights/lito-research-mlx \