File size: 4,724 Bytes
2847d0b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
#!/usr/bin/env python3
"""Select the deterministic 1000-prompt Predictor v4 training split."""

from __future__ import annotations

import argparse
import hashlib
import json
import os
import random
from pathlib import Path


ROOT = Path(__file__).resolve().parents[1]
DEFAULT_SOURCE = ROOT / "prompts" / "vidprom_filtered_extended.txt"
DEFAULT_HOLDOUT = ROOT / "prompts" / "MovieGenVideoBench_extended.txt"
DEFAULT_OUTPUT = Path(
    "/mnt/local_nvme/zoubin/cz/self_forcing_predictor_v4_1000_seed0"
)


def read_nonempty(path: Path) -> list[tuple[int, str]]:
    with path.open("r", encoding="utf-8") as handle:
        return [
            (line_number, line.strip())
            for line_number, line in enumerate(handle, start=1)
            if line.strip()
        ]


def atomic_write(path: Path, text: str) -> None:
    path.parent.mkdir(parents=True, exist_ok=True)
    temporary = path.with_name(f".{path.name}.tmp.{os.getpid()}")
    with temporary.open("w", encoding="utf-8") as handle:
        handle.write(text)
        handle.flush()
        os.fsync(handle.fileno())
    os.replace(temporary, path)


def main() -> None:
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument("--source", type=Path, default=DEFAULT_SOURCE)
    parser.add_argument("--holdout", type=Path, default=DEFAULT_HOLDOUT)
    parser.add_argument("--output_root", type=Path, default=DEFAULT_OUTPUT)
    parser.add_argument("--num_prompts", type=int, default=1000)
    parser.add_argument("--sampling_seed", type=int, default=0)
    parser.add_argument("--inference_seed", type=int, default=0)
    args = parser.parse_args()

    source = args.source.resolve()
    holdout = args.holdout.resolve()
    output_root = args.output_root.resolve()
    if args.num_prompts <= 0:
        raise ValueError("--num_prompts must be positive")
    if args.sampling_seed != 0:
        raise ValueError("the Predictor v4 split is fixed to random.Random(0)")
    if args.inference_seed != 0:
        raise ValueError("every Predictor v4 case must use inference seed 0")
    for path in (source, holdout):
        if not path.is_file():
            raise FileNotFoundError(path)

    source_rows = read_nonempty(source)
    holdout_rows = read_nonempty(holdout)
    holdout_first100 = {prompt for _, prompt in holdout_rows[:100]}
    eligible = [
        (line_number, prompt)
        for line_number, prompt in source_rows
        if prompt not in holdout_first100
    ]
    if len(eligible) < args.num_prompts:
        raise ValueError(
            f"only {len(eligible)} eligible prompts remain after holdout exclusion"
        )
    selected = random.Random(0).sample(eligible, args.num_prompts)
    cases = []
    for case_id, (source_line_number, prompt) in enumerate(selected):
        cases.append(
            {
                "case_id": case_id,
                "prompt": prompt,
                "prompt_sha256": hashlib.sha256(prompt.encode("utf-8")).hexdigest(),
                "source_line_number": source_line_number,
                "seed": 0,
            }
        )

    cases_text = "".join(
        json.dumps(item, ensure_ascii=False, sort_keys=True) + "\n"
        for item in cases
    )
    prompts_text = "".join(f"{item['prompt']}\n" for item in cases)
    config = {
        "schema_version": "self_forcing_predictor_v4_bf16_v1",
        "selection": {
            "algorithm": "random.Random(0).sample",
            "sampling_seed": 0,
            "num_prompts": args.num_prompts,
            "source": str(source),
            "source_nonempty_count": len(source_rows),
            "holdout": str(holdout),
            "holdout_nonempty_prefix_count": min(100, len(holdout_rows)),
            "holdout_exact_prompt_exclusion_count": len(holdout_first100),
            "eligible_count": len(eligible),
        },
        "inference": {
            "seed": 0,
            "reset_seed_per_case": True,
            "num_chunks": 7,
            "frames_per_chunk": 3,
            "num_steps": 4,
            "candidate_block_ids": [0, 1, 28, 29],
            "teacher_checkpoint": "checkpoints/self_forcing_dmd.pt",
            "teacher_checkpoint_key": "generator_ema",
        },
    }
    atomic_write(output_root / "cases.jsonl", cases_text)
    atomic_write(output_root / "selected_prompts.txt", prompts_text)
    atomic_write(
        output_root / "dataset_config.json",
        json.dumps(config, ensure_ascii=False, indent=2, sort_keys=True) + "\n",
    )
    print(
        f"Selected {len(cases)} prompts into {output_root}; "
        f"excluded exact matches against the first {len(holdout_rows[:100])} "
        "non-empty MovieGen prompts."
    )


if __name__ == "__main__":
    main()