File size: 8,661 Bytes
00c7b31 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 | # CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## What this repo is
Echo-Memory is the release code for a paper that runs a **controlled study of memory mechanisms in action-conditioned video world models**. Every experiment shares the same Wan 2.1 1.3B DiT backbone and the same two-chunk training/eval setup; only the *memory pathway* changes between rows. The goal is to compare how four memory families (Context, Compression, Spatial, State-Space) preserve scene identity/layout/viewpoint when a generated trajectory leaves a view and later revisits it.
This is a **public release of a larger internal codebase**. Private benchmark launchers, cluster submit files, logs, generated outputs, and machine-local absolute paths have been intentionally removed. Do not reintroduce them (see Public-repo constraints below).
## Environment & required variables
```bash
conda env create -f environment.yml && conda activate echo-memory
pip install -r requirements.txt
```
Almost every script is path-portable via environment variables:
```bash
export WAN_BASE_MODEL=/path/to/Wan2.1-T2V-1.3B # must contain diffusion_pytorch_model.safetensors, models_t5_umt5-xxl-enc-bf16.pth, Wan2.1_VAE.pth
export DATASET_BASE_PATH=data/Context-as-Memory-Dataset # training/eval pool root (code default if unset)
export PYTHONPATH=$PWD:${PYTHONPATH:-}
export CKPT=./ckpts/<row_id>/epoch-0.safetensors # for eval/inference
export OUTPUT_BASE_ROOT=$PWD/outputs # training output root (optional)
```
**Critical convention:** the `CKPT` path must keep the row folder name (e.g. `spatial_mem/`, `context_k20/`). `env/memory_baseline_runtime.py` and `inference/unified_inference.py` infer the memory profile (which flags to set) by matching substrings in that path. Renaming the folder breaks memory selection.
## Common commands
**Run a single test** (tests are standalone scripts, not pytest β there is no pytest config):
```bash
PYTHONPATH=. python3 tests/test_context_chunk_utils.py
PYTHONPATH=. python3 tests/test_framepack_memory_align.py
PYTHONPATH=. python3 tests/test_two_chunk_anchor_readout.py
```
These check memory/context plumbing (context-frame selection, FramePack alignment, two-chunk anchor read-out).
**Train** a memory row (run from repo root; uses `accelerate launch src/model_training/train.py` under the hood):
```bash
bash train/memory_baselines_basic/run_spatial_memory_baseline.sh # spatial / SSM / compression rows
bash train/context_learning/run_pre_qkv_ctx20.sh # raw-context K=1/5/20 rows
bash train/dynamic_spatialvid/run_dyn_spatial_mem.sh # SpatialVID dynamic pool rows
```
**Inference** (single-chunk generation, any memory family):
```bash
python inference/unified_inference.py --ckpt $CKPT --memory_type auto \
--context_image assets/opendomain_revisit/1774363417.png \
--action_path env/action_rotation_left_45.json \
--prompt "A toy bear on a table" --output_path output.mp4
```
`--memory_type auto` detects the family from the ckpt path; see `python inference/unified_inference.py --help` for the full list.
**Evaluate** (in-domain replay/revisit; requires the static pool):
```bash
bash eval/v2/run_basic_replay_gt.sh # fast single-video GT fidelity check (~5 min)
bash eval/v2/run_static_consistency_loop_and_revisit.sh # full paper eval bundle (loop closure + revisit)
PHASE=stage1 OOD_DIR=assets/opendomain_revisit bash eval/v2/revisit_suite/run_one_click_revisit_eval.sh
```
Outputs go to `${CKPT_DIR}/evals_v2/`.
## Architecture: the big picture
**Layered structure** (each layer reads from the one below):
- `train/`, `inference/`, `eval/` β **bash launchers** that set flags and call into the Python entrypoints. The paper's experiment matrix lives here as a set of `run_*.sh` scripts, one per memory row. They are the canonical, reproducible interface β prefer editing/extending an existing launcher over writing new Python entrypoints.
- `src/model_training/train.py` β the single training entrypoint. All memory mechanisms are toggled by command-line flags (`--use_spatial_memory`, `--use_framepack_memory`, `--use_block_wise_ssm`, `--context_memory_frames`, etc.), so the same script trains every row. It writes the active memory config into the pipeline.
- `inference/unified_inference.py` + `env/loop_utils.py` β load a checkpoint, reconstruct the matching memory module (inferring structure from checkpoint key names / weight shapes), and run generation.
- `diffsynth/` β a **vendored DiffSynth model stack** (Wan + many other diffusion model families). The Echo-Memory-specific code is concentrated in:
- `diffsynth/models/memory/` β the four memory families: `spatial_grid_memory.py`, `framepack_length.py`, `framepack_weight.py`, `block_wise_ssm.py` (paper-aligned recurrent SSM), `videossm_hybrid.py` (legacy temporal-conv baseline).
- `diffsynth/pipelines/wan_video_new.py` β the action-conditioned Wan pipeline; the raw-context and FramePack read-out paths live here.
- `diffsynth/models/wan_video_*.py` β DiT, VAE, text/image encoders, camera/motion controllers.
- `src/model_training/context_chunk_utils.py`, `context_retrieval.py`, etc. β context-frame selection and multi-chunk sampling helpers (the logic the tests cover).
- `env/` β runtime glue: `memory_baseline_runtime.py` (CKPT path β memory flags), `loop_utils.py` (pipeline + checkpoint loading), action JSONs, replay-loop driver.
### The two-chunk paradigm (central to the whole repo)
All memory baselines are trained and evaluated in a **two-chunk** setup that simulates the revisit scenario:
- **Chunk 1 (context):** a clean reference segment, VAE-encoded, with matched camera RT actions. Concatenated at the suffix position (`CONTEXT_POSITION=suffix`).
- **Chunk 2 (target):** the noisy segment the model learns to denoise. It can only access chunk-1 information *through the memory mechanism* β this is what forces the memory pathway to do work, and what evaluation later probes.
The ablations are designed to change **only** the memory read/write pathway while keeping backbone, action conditioning, resolution (640Γ352), chunk length (81 frames), and training schedule fixed. See `doc/memory_mechanisms.md` for the authoritative paper-row β code-path β training-script mapping.
### Memory rows at a glance
| Family | Rows | Code path |
| --- | --- | --- |
| Raw context | `context_k1/k5/k20` | `wan_video_new.py` context latent path |
| Compression | `framepack_weight`, `framepack_len_r2/r4`, `framepack_hybrid_*` | `memory/framepack_{weight,length}.py` |
| Spatial | `spatial_mem`, `spatial_inject_none/concat_text/cross_attn_readout` | `memory/spatial_grid_memory.py` (same storage, different read-out) |
| State-space | `block_wise_ssm` (paper), `videossm_hybrid` (legacy) | `memory/block_wise_ssm.py`, `memory/videossm_hybrid.py` |
### Two dataset pools (same on-disk layout)
`DATASET_BASE_PATH` points at one of two interchangeable pools, each with `frames/ jsons/ overlap_labels/ metadata_full.csv [latents/]`:
- **Static in-domain pool** β `data/Context-as-Memory-Dataset` (default). Used for all in-domain training and eval.
- **Dynamic training pool** β `data/dynamic-spatialvid-motion60/mixed` (SpatialVID subset). Training + inference only; dynamic eval is TODO.
Metadata is regenerated with `scripts/run_generate_metadata.sh`; optional latent precompute with `scripts/run_precompute_ctx_target_latents.sh`.
## Public-repo constraints (the codebase is split public/private)
- **No machine-local absolute paths** (e.g. `/pfs/β¦`, cluster paths) in any committed file β use env vars with sensible defaults.
- **No checkpoint-upload scripts, internal benchmark names, or cluster submit files.** `scripts/upload_hf_checkpoints.sh` and related are gitignored; do not add them.
- In public-facing markdown use the released pool names ("static in-domain pool", "dynamic training pool"), not internal codenames.
- `data/`, `outputs/`, `logs/`, `wandb/`, `checkpoints/`, and binary weights are gitignored. Versioned binaries are limited to README/site visual assets under `assets/` and `docs/`.
- Keep diffs minimal and match the existing bash/Python patterns in `train/` and `eval/v2/`.
## Cursor skills
Maintainer workflows are documented as Cursor skills in `.cursor/skills/` (`echo-memory-train`, `echo-memory-eval`, `echo-memory-release`, `echo-memory-agent`) and in `doc/DEVELOPER.md`. Consult `doc/memory_mechanisms.md`, `doc/checkpoints.md`, and `doc/dataset_preprocessing.md` for row/checkpoint/dataset details.
|