게임 회사가 오픈월드 하나를 만들려면 아티스트 수백 명이 몇 년을 갈아넣는다. 월드 모델은 이 파이프라인을 통째로 우회하자는 발상이다. 3D 에셋을 만들지 않고, "지금 화면 + 사용자 입력"을 조건으로 다음 화면을 생성 모델이 직접 그린다. 계속 그리면 그게 곧 플레이 가능한 세계가 된다.
AlayaWorld가 실제로 받는 입력은 세 가지다(inference/run.py 기준).
| 입력 | 파일 | 내용 |
|---|---|---|
| 첫 프레임 | <prefix>_image.png | 출발 지점 이미지 1장 (또는 _video.mp4) |
| 카메라 궤적 | <prefix>_camera.pt | dict — cam_c2w [F,4,4] 포즈 시퀀스 + intrinsic |
| 텍스트 | <prefix>_prompt.txt | 장면 설명. 중간에 교체 가능 |
출력은 mp4다. 한 번에 다 만드는 게 아니라 청크 단위로 이어붙인다: 1청크 = 레이턴트 4프레임 = 픽셀 32프레임 ≈ 24fps 기준 1.33초. 1분짜리 클립이면 약 45청크를 연달아 굴린다.
기존 게임 엔진은 미리 지어놓은 세트장이다. 카메라를 어디로 옮기든 세트는 그 자리에 있다. 월드 모델은 즉흥 연기하는 배경 화가다. 카메라가 왼쪽으로 돌면 화가가 그 자리에서 왼쪽 풍경을 그려준다. 빠르고 유연하지만, 문제는 고개를 다시 오른쪽으로 돌렸을 때 아까 그린 그림을 화가가 기억하느냐다. 기억 못 하면 "아까 있던 나무가 사라지는" 현상이 생긴다. AlayaWorld 설계의 절반이 이 기억 문제에 쓰였다.
현재(2026-07-19) 공개된 것은 추론 코드 + 병합된 가중치뿐이다. README 로드맵의 "Training code / Training data" 체크박스는 비어 있다. 재현 학습은 아직 불가능하다.
더 중요한 건 라이선스다. GitHub 페이지 배지는 Apache-2.0으로 표시되지만, 실제 LICENSE 파일 내용은 LTX-2 Community License(비-OSI, 학술·비영리 전용, 연매출 $10M 이상 기업은 Lightricks와 별도 계약 필요)다. 배지를 믿고 상업적으로 쓰면 안 된다. 반드시 LICENSE 원문을 직접 읽을 것.
솔직하게 시작하자. 별 52개, 포크 0개, 커밋 사실상 1개. 스타 수로 주목받는 저장소가 아니다. 2026-07-16에 처음 공개됐고, arXiv 논문(2607.06291)이 7월 7일에 올라와 HuggingFace Papers에서 좋아요 87을 받았다. 즉 "화제성"이 아니라 "논문 + 실행 가능한 코드 + 33GB 가중치를 한꺼번에 풀었다"는 완결성이 주목 이유다. 이 분야에서 이 세 가지를 다 공개하는 경우는 드물다.
말잔치인지 실제 구현인지는 코드를 열어보면 안다. 네 가지 모두 대응하는 파일이 있다.
| 속성 | 주장 | 실제 구현 위치 |
|---|---|---|
| Interaction | 실시간 카메라 제어 + 프롬프트 전환 | ActionAdaLNEmbedder (model_ltx_2_3.py), --skill-prompt 옵션 |
| Consistency | 롱호라이즌 기억 일관성 | history_encoder.py(시간) + spatial_cache.py(공간) 이중 메모리 |
| Stability | drift 억제 | drift된 히스토리로 학습 + error bank (학습 코드 미공개) |
| Runtime | 실시간에 근접 | DMD 증류 → sampling_steps: 4 (configs/infer.yaml) |
※ Stability의 error bank는 학습 단계의 기법이라 현재 공개된 추론 코드에서는 직접 확인할 수 없다. README 설명에만 근거한다.
프로젝트 웹페이지가 내건 숫자다. 이 중 15B는 따져볼 여지가 있다. 라이선스 문서는 "LTX-2.3-22B 베이스를 파인튜닝했다"고 명시하는데, 배포된 merged_infer.safetensors의 실제 크기는 33.6GB다. bf16(파라미터당 2바이트)으로 역산하면 약 16.8B — DiT + VAE + 커넥터 + history_encoder를 다 합친 값이니 "15B" 표기와는 얼추 맞는다.
베이스가 22B인데 배포본이 15~17B 규모인 이유(증류인지 프루닝인지 일부 모듈만 배포한 건지)를 저장소 문서는 설명하지 않는다. 추측하지 말고 미확인으로 두는 게 맞다. 오픈소스 모델을 읽을 때 이런 숫자 불일치를 발견하면, 억지로 해석하기보다 "여기는 문서가 비어있다"고 표시해두는 습관이 낫다.
저장소에도 프로젝트 페이지에도 수치 벤치마크 표가 없다. 대신 프로젝트 페이지의 "Consistency Comparisons" 섹션에서 DreaxX-World, lingBot-Fast, HY-World 1.5 세 가지와 "좌회전 → 우회전 → 뒤돌아보기" 궤적을 나란히 재생해 정성적으로 비교한다.
이 분야에서 흔한 방식이긴 하다. 영상 월드 모델의 "일관성"은 FVD 같은 지표로 잘 안 잡히기 때문에 영상을 나란히 놓고 눈으로 비교하는 관행이 있다. 다만 독자 입장에서는 "저자가 고른 궤적에서 저자가 고른 경쟁자와 비교한 결과"라는 점을 감안해서 읽어야 한다. Genie·Oasis·Matrix-Game 같은 더 알려진 모델과의 직접 비교는 자료에 없다.
playground/에 case1, case2 데모 케이스가 이미지·카메라·프롬프트 세트로 들어있고, bash inference/run.sh 한 줄이면 돈다. 논문만 내고 코드를 안 푸는, 혹은 코드만 풀고 가중치를 안 푸는 사례가 압도적으로 많은 분야에서 이건 실질적인 기여다.
AlayaWorld는 밑바닥부터 만든 모델이 아니다. 세 개의 외부 대형 모델을 조립하고, 그 사이에 자기들이 만든 메모리 모듈을 끼워넣은 구조다. 이 구성을 파악하는 게 코드 읽기의 출발점이다.
| 역할 | 모델 | 비고 |
|---|---|---|
| 영상 생성 백본 | LTX-2.3-22B (Lightricks) | DiT. 48 layer, 32 head, head_dim 128 → inner_dim 4096 |
| 텍스트 이해 | Gemma-3-12B (Google) | gemma-3-12b-it-qat-q4_0-unquantized. gated — 사전 동의 필요 |
| 깊이 추정 | Depth-Anything-3 (ByteDance) | DA3NESTED-GIANT-LARGE-1.1. 3D 공간 캐시의 핵심 |
# CUDA 12.4 wheel 인덱스에서 설치 권장
torch==2.6.0 torchvision==0.21.0 torchaudio==2.6.0
xformers==0.0.29.post2
diffusers==0.39.0 # 스케줄러/파이프라인 유틸
transformers==5.13.1 # Gemma 텍스트 인코더
peft>=0.17 # LoRA (DMD generator 가중치 병합용)
bitsandbytes>=0.45
safetensors>=0.4 einops>=0.7 numpy>=1.24,<2
opencv-python pyyaml tqdm easydict huggingface-hub
flash_alaya/ltx2/modules/attention.py는 optional import 3단 폴백을 쓴다. ① flash_attn_interface(FA3, Hopper sm_9x에서만) → ② flash_attn(FA2) → ③ 둘 다 없으면 xformers. 설정 기본값은 attention_type: flash_attention_3지만, 없어도 죽지 않고 느려질 뿐이다. 설치 난이도가 높은 의존성을 필수에서 빼고 런타임에 감지하는 건 배포 마찰을 줄이는 좋은 관행이다.
flash_alaya/utils/pipeline.py의 _renoise가 핵심 한 줄이다.
x_sigma = (1 - sigma) * x0 + sigma * eps
# 깨끗한 x0과 노이즈 eps를 sigma 비율로 직선 보간
병합 스크립트 flash_alaya/tools/merge_infer_weights.py의 주석에서 배포 가중치의 정체가 드러난다. SFT 베이스 transformer + DMD/GAN generator LoRA(타깃 선형층 480개) + history_encoder를 하나의 merged_infer.safetensors로 합친 것이다. 원본 베이스 파일명은 ltx-2.3-22b-dev.safetensors.
설정은 configs/infer.yaml 딱 하나다. 최상위 8개 섹션.
| 섹션 | 내용 |
|---|---|
run | 출력 경로 |
paths | 체크포인트 5종 경로 |
sample | 544×960 해상도, 24fps, temporal_stride 8 |
layout | sink / history / condition 레이턴트 프레임 수 |
memory | HR·LR 히스토리 압축률 |
spatial_memory | DA3 백엔드, 3D 캐시 검색 파라미터 |
control | action_scale 6개 float (카메라 6-DoF 각각의 민감도) |
validation | sampling_steps: 4, cfg_scale, ttc |
runtime | bf16, attention_type, vae_chunk_size |
※ 실제 생성 해상도는 544×960이다. 웹페이지의 "720p" 배지는 근사 표현으로 보인다(960 폭은 720p보다 낮다).
자기회귀 영상 생성이 실패하는 방식은 두 가지고, AlayaWorld는 각각에 다른 메모리를 붙였다.
파일: flash_alaya/alaya/memory/history_encoder.py
직전 프레임들을 HR(고해상)·LR(저해상) 두 갈래로 압축해 메모리 토큰을 만든다. 최근 것은 자세히, 오래된 것은 거칠게 기억하는 구조다. 해결하는 문제: 시간적 끊김 — 청크 경계에서 갑자기 물체가 튀거나 조명이 바뀌는 현상.
비유하자면 사람의 단기 기억이다. 방금 일은 선명하고, 30초 전 일은 흐릿하다.
파일: flash_alaya/alaya/memory/spatial_cache.py, flash_alaya/utils/spatial.py
생성한 프레임마다 DA3로 깊이를 추정해 3D 점군으로 쌓아둔다. 다음 청크를 만들 때는 그 점군을 새 카메라 시점으로 forward-warp(재투영)해 "이 시점에서 원래 보여야 할 모습"의 힌트를 모델에 넣어준다. 해결하는 문제: 공간적 망각 — 왼쪽 봤다가 오른쪽 봤다가 다시 왼쪽을 봤을 때 아까 그 장면이 사라지는 현상.
비유하자면 방을 돌아다니며 그린 스케치북이다. 같은 자리로 돌아오면 예전 스케치를 꺼내 참고한다.
시간 메모리만 쓰면 "방금 전"은 잘 잇지만 "1분 전 그 방"은 못 찾는다 — 슬라이딩 윈도우 밖으로 밀려났기 때문이다. 공간 메모리만 쓰면 기하는 맞지만 조명·질감이 프레임마다 튄다 — 3D 캐시는 위치 정보지 스타일 정보가 아니기 때문이다. 두 메모리는 서로 다른 실패 모드를 막는다. 하나로 합치려 하지 않고 각각의 강점에 맡긴 게 이 설계의 판단이다.
ActionAdaLNEmbedder (flash_alaya/ltx2/modules/model_ltx_2_3.py)가 담당한다. 6D 상대 포즈(평행이동 3 + 오일러각 3)를 주파수 임베딩한 뒤, AdaLN 파라미터로 변환해 정규화 레이어의 스케일·시프트에 주입한다.
즉 조건마다 주입 경로가 다르다. 텍스트는 크로스 어텐션(토큰이 많고 의미가 복잡하니까), 카메라는 AdaLN(6개 숫자니까), 공간·히스토리 메모리는 어텐션 KV로(공간 구조가 있으니까). 조건의 성격에 따라 주입 방식을 나눠 쓴 것 — 이게 이 아키텍처에서 가장 배울 만한 판단이다.
inference/run.py의 --skill-sec / --skill-prompt 옵션이다. 롤아웃 마지막 N초 구간에서만 caption을 다른 것으로 바꿔치기한다.
python -m inference.run --input playground/case1/case1 \
--skill-sec 3 --skill-prompt "a burst of flame erupts"
청크 경계마다 텍스트 조건을 새로 인코딩하기 때문에 가능한 트릭이다. "55초 지점에서 화염이 터지게 하라" 같은 연출을 넣을 수 있다는 뜻이고, 이게 "playable"이라는 표현의 실질이다.
flash_alaya/utils/cache.py. 이 프로젝트에서 가장 깔끔한 설계 판단 중 하나다.
inference/) + 두꺼운 엔진(flash_alaya/) 2층 구조① inference/run.py(입력 형식 파악) → ② configs/infer.yaml(뭘 조절할 수 있는지) → ③ flash_alaya/utils/pipeline.py(청크 루프 전체) → ④ alaya/memory/ 두 파일(이 프로젝트의 정체성) → ⑤ flash_alaya/record.md(실측 성능 로그, 중국어지만 숫자만 봐도 얻는 게 많다). ltx2/는 나중에. 남의 코드고 양이 많다.
alaya/와 ltx2/가 분리돼 있다는 사실디렉토리 경계가 곧 저작권 경계다. ltx2/는 Lightricks 코드 파생이라 LTX-2 Community License가 걸리고, alaya/는 이 팀 코드다. 남의 모델을 파인튜닝해 배포할 때 라이선스가 다른 코드를 디렉토리로 갈라놓는 것은 실무에서 반드시 따라 해야 할 습관이다.
솔직히 말하면, 이 저장소에서 월드 모델 학습을 배우기는 어렵다. 학습 코드가 없기 때문이다. 대신 33GB 모델 세 개를 한 GPU에 올려 굴리는 엔지니어링에서 배울 게 아주 많다. 다섯 가지를 뽑았다.
assign=True — 로딩 70초를 0으로flash_alaya/utils/engine.py의 fast_load_transformer:
with torch.device("meta"):
model = LTX23Model(**filtered)
...
missing, unexpected = model.load_state_dict(
converted, strict=False, assign=True
)
보통 모델을 만들면 파이썬이 모든 가중치를 난수로 채운다. 그런데 어차피 다음 줄에서 체크포인트로 전부 덮어쓸 거다. 15B 모델이면 이 헛수고가 70초다. meta 디바이스는 "모양만 있고 실제 메모리는 없는 껍데기"를 만들고, assign=True는 체크포인트 텐서를 복사하지 않고 그대로 갖다 붙인다. 이삿짐을 새 가구 사서 채운 다음 버리는 대신, 빈 방에 짐만 들이는 것.
※ 이건 AlayaWorld 전용 트릭이 아니다. PyTorch로 큰 모델을 다루면 무조건 알아야 하는 패턴이다.
tools/merge_infer_weights.py가 DiT·VAE·텍스트 프로젝션·history_encoder를 접두사(vae., history_encoder. …)로 구분해 한 파일에 합친다. 그리고 engine.setup()은 그 파일을 딱 한 번만 읽고, 각 로더가 자기 접두사 키만 필터링해 가져간다.
효과: 33GB 파일에 대한 디스크 I/O가 1회로 끝난다. 파일을 4개로 쪼개면 4번 열어야 하고, 대용량 파일에서는 이 차이가 체감된다.
history_encoder.py의 _SelfAttention3D:
t_indices = torch.arange(T * spatial, device=x.device) // spatial
causal_mask = t_indices.unsqueeze(0) <= t_indices.unsqueeze(1)
영상 토큰은 (프레임 × 공간위치)로 펼쳐져 있다. 여기서 // spatial 정수 나눗셈 한 번으로 "이 토큰이 몇 번째 프레임 소속인가"를 뽑아내고, 그걸로 마스크를 만든다. 결과: 같은 프레임 안에서는 모든 위치가 서로 다 보고, 프레임 사이에서는 미래를 못 본다. 시공간 어텐션에 인과성을 주는 가장 간결한 방법이다.
spatial_cache.py의 _safe_inv. 주석이 이 판단의 전부를 설명한다.
"""GPU의 torch.linalg.inv는 cuSOLVER를 타는데, 메모리가 빠듯하면
cusolverDnCreate(handle)가 CUSOLVER_STATUS_INTERNAL_ERROR를 던진다
(DMD가 13B 두 벌 + DA3를 동시 상주시킬 때 흔함)."""
return torch.linalg.inv(mat.float().cpu()).to(device=mat.device, dtype=mat.dtype)
4×4 카메라 행렬 역행렬은 계산량이 사실상 0이다. 그런데 GPU로 보내면 cuSOLVER 핸들 생성이라는 무거운 초기화가 딸려오고, VRAM이 빠듯하면 그게 터진다. 작고 안 중요한 연산에 큰 라이브러리를 물리면 오히려 불안정해진다는 걸 이 팀은 실패를 겪고 배운 것이다(주석의 "흔함"이 그 증거다).
pipeline.py의 _denoise_chunk에서 TTC(Test-Time Correction) 처리 방식이다. --ttc 플래그가 꺼지면 ttc_steps가 빈 frozenset()이 되어, 루프가 추가 RNG 추출도, 추가 forward도 없이 베이스라인과 완전히 동일한 코드 경로를 탄다.
실험 기능을 넣을 때 흔한 실수는 "꺼도 난수 소비 순서가 바뀌는 것"이다. 그러면 같은 seed를 줘도 결과가 달라지고, 그 순간 "이 차이가 새 기능 때문인지 난수 때문인지" 판별이 불가능해진다. off일 때 바이트 단위로 동일함을 구조적으로 보장하는 것 — 실험 코드를 짜는 사람이면 이 원칙 하나만 가져가도 본전이다.
| 기술 | 여기서 배울 것 | 실습 아이디어 |
|---|---|---|
| PyTorch 로딩 | meta device, assign=True, safetensors 병합 | 내 모델 로딩 시간 측정 후 meta 적용해 비교 |
| Flow Matching | 직선 보간 + few-step 샘플링 | MNIST에 flow matching 구현, 4 vs 50 step 비교 |
| 조건 주입 | AdaLN vs 크로스어텐션 선택 기준 | 작은 DiT에 두 방식 다 붙여 파라미터 수 비교 |
| 3D 인식 | 깊이 추정 → 점군 → forward warp | DA3로 사진 한 장을 3D 점군화 후 시점 이동 |
| 어텐션 최적화 | FA3/FA2/xformers 3단 폴백 | 세 백엔드 속도·정확도 벤치마크 |
| 분산 추론 | Ulysses Context Parallel | CP=1/2/4에서 청크 시간 측정 |
이건 미확인 사항이다. 아래 수치는 코드 주석과 파일 크기에서 역추정한 것이지 공식 스펙이 아니다. 개인 GPU로 돌려보려는 사람은 이 점을 반드시 감안할 것.
| 근거 | 위치 | 시사점 |
|---|---|---|
| "fp32 중간 피크 ~48GB, bf16 최종 ~16GB, H200 140G면 충분" | ltx2/modules/camera_control.py:795 | 개발 기준 GPU = H200(140GB) |
| "DMD 동시 상주 2벌 13B + DA3에서 흔함(cuSOLVER 오류)" | spatial_cache.py:14 | 메모리 압박이 상시였음 |
FA3 분기가 sm_9x를 명시 감지 | attention.py | Hopper(H100/H200) 우대 설계 |
| 모델 | 크기 | 비고 |
|---|---|---|
merged_infer.safetensors | 33.6 GB | HF API로 확인한 실제 바이트 |
| Gemma-3-12B | 20GB대 (bf16 추정) | gated — HF에서 라이선스 사전 동의 필요 |
| DA3NESTED-GIANT-LARGE-1.1 | 별도 | 없으면 spatial 브랜치에서 에러 |
세 모델을 동시에 GPU에 올려야 한다. 단일 GPU로 굴린다면 80GB급(A100 80G / H100 / H200)이 현실적으로 보이지만, 다시 강조하면 이건 추정이지 공식 수치가 아니다. 24GB 소비자용 GPU로는 그대로는 어렵다고 보는 게 안전하다.
# 1) PyTorch (CUDA 12.4)
pip install --index-url https://download.pytorch.org/whl/cu124 \
--extra-index-url https://pypi.org/simple \
torch==2.6.0 torchvision==0.21.0 torchaudio==2.6.0 xformers==0.0.29.post2
pip install -r requirements.txt
# 2) 본체 가중치
hf download AlayaLab/AlayaWorld merged_infer.safetensors --local-dir checkpoints
# 3) 텍스트 인코더 (gated — HF에서 먼저 동의 클릭)
hf download google/gemma-3-12b-it-qat-q4_0-unquantized \
--local-dir checkpoints/gemma-3-12b-it-qat-q4_0-unquantized
# 4) 깊이 모델 — 필수. 빠뜨리면 spatial 브랜치에서 죽는다
git clone https://github.com/ByteDance-Seed/Depth-Anything-3 checkpoints/Depth-Anything-3
pip install -e checkpoints/Depth-Anything-3
HF_HOME=checkpoints/hf_cache hf download depth-anything/DA3NESTED-GIANT-LARGE-1.1
# 단일 GPU, 번들 데모
bash inference/run.sh
# 멀티 GPU (Ulysses Context Parallel)
GPUS=4 bash inference/run.sh
# 모듈 직접 호출 + 옵션
PYTORCH_ALLOC_CONF=expandable_segments:True \
python -m inference.run --input playground/case1/case1 --seed 1234 --ttc
flash_alaya/record.md에 남아있는 실측 로그다. 청크 하나(=1.33초 분량)당:
| 단계 | 시간 | 내용 |
|---|---|---|
| denoise | ~0.84 s | flow-matching 4 step |
| spatial_ctx | ~0.59 s | 3D 캐시 → 현재 시점 warp |
| finalize | ~1.14 s | VAE 디코드 + DA3 깊이 재계산 |
| 합계 | ~2.55 s | 최적화 전 ~3.0s에서 개선 |
1청크가 1.33초 분량인데 생성에 2.55초가 걸리니 실시간의 약 1.9배 느리다. "실시간에 근접"이라는 표현은 과장은 아니지만, GPU 4장을 쓰고도 아직 실시간은 아니다는 점은 정확히 알아둘 필요가 있다. 단일 GPU 수치는 record.md에 없다(미확인).
※ 눈여겨볼 것: 가장 오래 걸리는 단계가 추론이 아니라 finalize(깊이 재계산)다. 공간 메모리를 유지하는 대가가 생성 자체보다 비싸다는 뜻이다.
playground/case1/case1_camera.pt를 torch.load로 열어 cam_c2w[F,4,4]와 intrinsic의 구조를 파악한다. 그다음 같은 형식으로 "제자리에서 360도 회전"하는 궤적을 직접 생성해본다. 회전행렬 만들기 + 동차좌표 4×4 이해가 목표다.
얻는 것: 3D 그래픽스의 camera-to-world 행렬 개념. 이건 월드 모델뿐 아니라 NeRF·3DGS·SLAM에서 전부 쓰인다.
history_encoder.py와 spatial_cache.py를 읽고, 각 메모리에 무엇이 언제 들어가고 언제 빠지는지를 직접 다이어그램으로 그린다. 특히 cache.history의 슬라이딩 윈도우 길이와 3D 캐시의 최대 크기를 코드에서 찾아낼 것.
얻는 것: 남의 코드에서 "상태의 수명주기"를 추적하는 훈련. 이게 대형 코드베이스를 읽는 핵심 기술이다.
AlayaWorld 본체는 못 돌려도 DA3는 훨씬 작다. 사진 한 장 → 깊이 추정 → 점군 변환 → 가상 카메라를 살짝 옆으로 옮겨 forward-warp해서 다시 2D로 투영한다. spatial_cache.py가 하는 일의 축소판이다.
얻는 것: 필연적으로 occlusion hole(가려졌던 부분이 드러나면서 생기는 빈 구멍)을 보게 된다. "왜 공간 캐시만으로는 부족하고 생성 모델이 필요한가"를 몸으로 이해하게 되는 게 이 과제의 진짜 목적이다.
아무 대형 모델(7B급)이나 골라 ① 평범하게 로드 ② meta device + assign=True로 로드, 두 방식의 시간과 피크 메모리를 측정해 표로 만든다. engine.py의 fast_load_transformer를 그대로 참고해도 된다.
얻는 것: 즉시 실무에 쓸 수 있는 기술. 서빙 환경에서 콜드 스타트 시간을 줄이는 표준 수법이다.
본체를 돌릴 수 있다면 가장 배울 게 많은 과제다. configs/infer.yaml의 spatial_memory를 비활성화하고 같은 궤적("좌회전 → 우회전 → 복귀")을 돌려, 공간 메모리가 있을 때와 없을 때 복귀 지점의 장면이 얼마나 달라지는지를 나란히 비교한다.
얻는 것: 논문이 주장하는 기여를 직접 검증하는 경험. ablation study를 남이 한 걸 읽는 것과 직접 돌려보는 것은 이해의 깊이가 다르다.
--skill-sec / --skill-prompt로 정해진 타이밍에 이벤트가 터지는 30초 클립을 만든다. 여러 번 프롬프트를 바꾸려면 run.py를 수정해야 한다 — 현재는 마지막 N초 한 번만 지원하기 때문이다. 다중 스위칭으로 확장하는 것 자체가 과제다.
얻는 것: 청크 경계에서 조건을 갈아끼우는 자기회귀 생성의 제어 지점을 손으로 만져보는 경험.
DDPM의 전방·역방 과정을 수식이 아니라 직관으로 잡는다. 그다음 flow matching이 "왜 더 적은 스텝으로 되는가"를 이해한다. 핵심 질문 하나: 노이즈에서 데이터로 가는 경로가 직선이면 무엇이 쉬워지는가?
실습: 2D 가우시안 혼합 분포에 flow matching을 직접 구현해 4 step vs 50 step 샘플 품질 비교. 데이터가 2D면 노트북 CPU로도 된다.
U-Net → DiT 전환이 왜 일어났는지, 그리고 조건을 넣는 세 가지 경로(크로스 어텐션 / AdaLN / 토큰 연결)의 트레이드오프를 정리한다. AlayaWorld가 세 가지를 조건 성격에 따라 나눠 쓴 이유를 설명할 수 있으면 이 주차는 성공이다.
읽을 것: DiT 논문(Peebles & Xie, 2022), 그리고 model_ltx_2_3.py의 ActionAdaLNEmbedder 실제 구현.
영상 생성이 픽셀이 아니라 레이턴트 공간에서 이뤄지는 이유. flash_alaya/ltx2/modules/vae.py의 CausalConv3d를 읽고 32× 공간 / 8× 시간 압축이 실제로 어떻게 구현되는지 본다. "causal"이 왜 필요한지(미래 프레임을 안 봐야 스트리밍이 된다)도 함께.
실습: overlap-tiling 디코딩을 직접 구현해, 겹침을 0으로 줄이면 청크 경계에 어떤 아티팩트가 생기는지 눈으로 확인.
단안 깊이 추정 → 점군 → 카메라 변환 → 재투영의 전 과정. 위 실습 과제 3이 이 주차의 중심이다. occlusion hole을 직접 만들어보는 게 핵심이다.
연결점: 여기서 NeRF·3D Gaussian Splatting으로 가지를 뻗을 수 있다. 다만 월드 모델은 명시적 3D를 보조로만 쓴다는 차이를 기억할 것.
DMD, Consistency Model, Progressive Distillation의 차이. "교사의 샘플을 따라하기 vs 교사의 분포를 따라하기"가 왜 다른 결과를 내는지가 이 주차의 핵심 개념이다. 실시간 생성 모델은 전부 이 계열 기법 위에 서 있다.
exposure bias(학습 때는 정답 히스토리, 추론 때는 자기 출력 히스토리를 본다는 불일치)와 그 완화법들. AlayaWorld의 "drift된 히스토리로 학습 + error bank"가 정확히 이 문제에 대한 답이다. 언어 모델의 teacher forcing 문제와 뿌리가 같다는 걸 연결해두면 이해가 단단해진다.
Genie / Oasis / Matrix-Game / HunyuanWorld / AlayaWorld를 입력 방식(키보드 vs 카메라 궤적), 메모리 전략, 길이, 공개 수준 네 축으로 표를 만든다. AlayaWorld가 정량 벤치마크를 안 낸 이유도 이 과정에서 스스로 판단이 설 것이다.
마무리: arXiv:2607.06291 논문을 이제 읽는다. 8주 전에 읽었으면 그림만 봤겠지만, 지금은 설계 선택 하나하나가 왜 그런지 보일 것이다.
| 용어 | 뜻 |
|---|---|
| 월드 모델 | 현재 상태 + 사용자 입력을 조건으로 다음 관측(화면)을 생성하는 모델. 3D 에셋 없이 "플레이 가능한 세계"를 만든다 |
| 자기회귀 | 앞 출력을 다시 입력으로 넣어 이어가는 방식. 길이 무제한이지만 오류가 누적됨 |
| long-horizon | 긴 시간축. 여기서는 60초 이상 안정적으로 굴리는 것 |
| drift | 자기회귀 롤아웃에서 오류가 누적돼 화면이 점점 뭉개지거나 색이 바래는 현상 |
| DiT | Diffusion Transformer. U-Net 대신 트랜스포머를 쓰는 확산 모델 백본 |
| Flow Matching | 노이즈↔데이터를 직선으로 잇고 그 속도장을 학습. 적은 스텝으로 샘플링 가능 |
| DMD | Distribution Matching Distillation. 교사 모델의 분포를 학생이 흉내내게 하는 증류. 4-step 추론의 근거 |
| AdaLN | Adaptive LayerNorm. 조건에서 정규화의 스케일·시프트를 계산해 주입. 저차원 조건에 값싸고 효과적 |
| CFG | Classifier-Free Guidance. 조건 있는 예측과 없는 예측의 차이를 증폭해 조건 따르기를 강화 |
| action-CFG | CFG를 카메라 액션 조건에 적용한 것. 카메라 지시를 더 강하게 따르게 함 |
| TTC | Pathwise Test-Time Correction (arXiv:2602.05871). 추론 중 경로를 보정해 긴 롤아웃의 외형 drift 억제 |
| sink latent | 첫 프레임 앵커. 색·톤의 기준점 역할을 해 전체가 표류하지 않게 잡아줌 |
| forward warp | 3D 점군을 새 카메라 시점의 2D 평면으로 투영하는 것 |
| occlusion hole | 재투영 시 가려져 있던 부분이 드러나며 생기는 정보 없는 빈 구멍 |
| Context Parallel | 시퀀스(토큰) 축을 여러 GPU로 쪼개는 분산 방식. 여기서는 Ulysses 방식 |
| meta device | PyTorch의 "모양만 있고 메모리는 없는" 가상 디바이스. 대형 모델 로딩 최적화의 핵심 |
| overlap-tiling | 큰 데이터를 겹치게 잘라 처리한 뒤 이어붙여 경계 아티팩트를 없애는 기법 |
| gated model | HuggingFace에서 라이선스 동의 후에만 받을 수 있는 모델. Gemma-3가 여기 해당 |