Download code/tests/test_plan_dataset.py from maxpicy/mamba-cot-tts: direct link, hf CLI and curl.
- Browser
- Download file 27.2 kB
-
https://huggingface.co/maxpicy/mamba-cot-tts/resolve/main/code/tests/test_plan_dataset.py
- Command line
-
hf download hf://maxpicy/mamba-cot-tts/code/tests/test_plan_dataset.py
-
curl -L -o test_plan_dataset.py https://huggingface.co/maxpicy/mamba-cot-tts/resolve/main/code/tests/test_plan_dataset.py
27.2 kB
| # test_plan_dataset.py: The three think-block tiers in the dataset. | |
| import json | |
| import os | |
| import subprocess | |
| import sys | |
| import zlib | |
| from pathlib import Path | |
| import pytest | |
| REPO_ROOT = Path(__file__).resolve().parents[1] | |
| if str(REPO_ROOT) not in sys.path: | |
| sys.path.insert(0, str(REPO_ROOT)) | |
| torch = pytest.importorskip("torch") | |
| class FakeTokenizer: | |
| UNK_ID = 0 | |
| UNK_TOKEN = "<|endoftext|>" | |
| TEXT_BASE = 1000 | |
| def __init__(self, tokens, base_vocab: int = 50277): | |
| self._token_to_id = {self.UNK_TOKEN: self.UNK_ID} | |
| self._id_to_token = {self.UNK_ID: self.UNK_TOKEN} | |
| for offset, token in enumerate(tokens): | |
| token_id = base_vocab + offset | |
| self._token_to_id[token] = token_id | |
| self._id_to_token[token_id] = token | |
| def __len__(self): | |
| return max(self._id_to_token) + 1 | |
| def convert_tokens_to_ids(self, tokens): | |
| if isinstance(tokens, str): | |
| return self._token_to_id.get(tokens, self.UNK_ID) | |
| return [self._token_to_id.get(t, self.UNK_ID) for t in tokens] | |
| def convert_ids_to_tokens(self, ids): | |
| if isinstance(ids, int): | |
| return self._id_to_token.get(ids) | |
| return [self._id_to_token.get(i) for i in ids] | |
| def encode(self, text, add_special_tokens=False): | |
| return [self.TEXT_BASE + (zlib.crc32(w.encode()) % 4096) | |
| for w in text.split()] | |
| def fake_registry(): | |
| import tokenizer as tok | |
| return tok.TokenRegistry(FakeTokenizer(tok.get_all_new_tokens())) | |
| PROMPT = "alpha beta gamma delta" | |
| REASONING = "Say it warmly and slow down at the end." | |
| PLAN_WORDS = [ | |
| {"word": "alpha", "pitch_bin": 3, "dur_bin": 1, "energy_bin": 0, "dur_frames": 2}, | |
| {"word": "beta", "pitch_bin": None, "dur_bin": 4, "energy_bin": 7, "dur_frames": 4}, | |
| {"word": "gamma", "pitch_bin": 15, "dur_bin": 9, "energy_bin": 3, "dur_frames": 6}, | |
| ] | |
| SUM_D = 12 | |
| def _row(n_frames, *, plan=None, reasoning=REASONING, tags=True, prompt=PROMPT): | |
| from delay_dataset import NUM_LEVELS | |
| row = { | |
| "prompt": prompt, | |
| "reasoning": reasoning, | |
| "speaker_id": 3, | |
| "speech_tokens": list(range(n_frames)), | |
| "residual_codes": [[(k + 1) % 900 for _ in range(n_frames)] | |
| for k in range(NUM_LEVELS - 1)], | |
| } | |
| if tags: | |
| row.update({"emotion_label": "joyful", "pace": "fast", "pitch": "high"}) | |
| if plan is not None: | |
| row["plan"] = plan | |
| return row | |
| def write_corpus(path, rows): | |
| Path(path).write_text("\n".join(json.dumps(r) for r in rows), encoding="utf-8") | |
| return str(path) | |
| def make_dataset(path, registry, cot_mode, **kw): | |
| from delay_dataset import DelayMimiDataset | |
| import tokenizer as tok | |
| kw.setdefault("max_seq_len", 2048) | |
| kw.setdefault("aligned", True) | |
| kw.setdefault("stage", "auto") | |
| kw.setdefault("lazy", False) | |
| return DelayMimiDataset(data_path=path, tokenizer=registry.tokenizer, | |
| registry=registry, cot_mode=cot_mode, **kw) | |
| def expected_legacy_ids(reg, tok_, think_text, n_frames, aligned=True, n_levels=None): | |
| from delay_dataset import NUM_LEVELS | |
| n_levels = NUM_LEVELS if n_levels is None else n_levels | |
| stagger = 0 if aligned else n_levels - 1 | |
| span = n_frames + stagger | |
| think = ([reg.think_start_id] + tok_.encode(think_text) + [reg.think_end_id] | |
| if think_text else []) | |
| return ([reg.bos_id, reg.user_prompt_id] + tok_.encode(PROMPT) + think | |
| + [reg.audio_start_id] + [reg.audio_start_id] * span | |
| + [reg.audio_end_id, reg.eos_id]) | |
| def probe(tmpdir) -> dict: | |
| import config | |
| from delay_dataset import DelayMimiDataset, NO_WORD | |
| tmpdir = Path(tmpdir) | |
| reg = fake_registry() | |
| tok_ = reg.tokenizer | |
| rows = [ | |
| _row(SUM_D, plan=list(PLAN_WORDS)), | |
| _row(SUM_D), | |
| _row(2 * SUM_D, plan=list(PLAN_WORDS)), | |
| ] | |
| path = write_corpus(tmpdir / "plan.jsonl", rows) | |
| out = { | |
| "plan_start_id": reg.plan_start_id, | |
| "plan_end_id": reg.plan_end_id, | |
| "plan_word_sep_id": reg.plan_word_sep_id, | |
| "think_start_id": reg.think_start_id, | |
| "think_end_id": reg.think_end_id, | |
| "audio_start_id": reg.audio_start_id, | |
| "audio_end_id": reg.audio_end_id, | |
| "bos_id": reg.bos_id, | |
| "eos_id": reg.eos_id, | |
| "pitch_ids": [reg.pitch_bin_to_id(b) for b in range(config.PITCH_BINS)], | |
| "duration_ids": [reg.duration_bin_to_id(b) for b in range(config.DURATION_BINS)], | |
| "energy_ids": [reg.energy_bin_to_id(b) for b in range(config.ENERGY_BINS)], | |
| "prompt_ids": tok_.encode(PROMPT), | |
| "reasoning_ids": tok_.encode(REASONING), | |
| "tag_ids": tok_.encode("EMO=joyful PACE=fast PITCH=high"), | |
| "tag_ids_after_prose": tok_.encode(" EMO=joyful PACE=fast PITCH=high"), | |
| "no_word": NO_WORD, | |
| } | |
| def dump(ds, i): | |
| item = ds[i] | |
| d = {k: (v.tolist() if torch.is_tensor(v) else v) for k, v in item.items()} | |
| return d | |
| for mode in ("prose", "tags", "none", "plan", "tags+plan", "full"): | |
| ds = make_dataset(path, reg, mode) | |
| out[f"items_{mode}"] = [dump(ds, i) for i in range(len(ds))] | |
| out[f"counters_{mode}"] = { | |
| "seen": ds.n_rows_seen, "missing": ds.n_rows_missing_plan, | |
| "rejected": ds.n_rows_plan_rejected, | |
| "truncated": ds.n_rows_plan_truncated, | |
| "prose_dropped": ds.n_rows_reasoning_dropped, | |
| } | |
| out[f"audit_{mode}"] = ds.plan_audit | |
| ds_pack = make_dataset(path, reg, "plan", plan_schedule_mode="pack") | |
| out["items_plan_pack"] = [dump(ds_pack, i) for i in range(len(ds_pack))] | |
| ds_la0 = make_dataset(path, reg, "plan", plan_lookahead=0) | |
| out["item_plan_lookahead0"] = dump(ds_la0, 0) | |
| ds_w = make_dataset(path, reg, "full", reasoning_weight=0.3, tag_weight=1.0, | |
| plan_weight=2.0) | |
| out["item_full_weighted"] = dump(ds_w, 0) | |
| from delay_dataset import DelayCollator | |
| ds_plan = make_dataset(path, reg, "plan") | |
| batch = DelayCollator(pad_token_id=reg.pad_id)([ds_plan[0], ds_plan[1], ds_plan[2]]) | |
| out["batch_keys"] = sorted(batch.keys()) | |
| out["batch"] = {k: batch[k].tolist() for k in | |
| ("plan_schedule", "plan_slots", "plan_durations", "plan_lengths")} | |
| ds_none = make_dataset(path, reg, "none") | |
| out["batch_keys_plainarm"] = sorted( | |
| DelayCollator(pad_token_id=reg.pad_id)([ds_none[0], ds_none[1]]).keys()) | |
| tight = make_dataset(path, reg, "full", max_seq_len=40) | |
| out["item_tight"] = dump(tight, 0) | |
| out["counters_tight"] = {"prose_dropped": tight.n_rows_reasoning_dropped, | |
| "truncated": tight.n_rows_plan_truncated} | |
| tighter = make_dataset(path, reg, "full", max_seq_len=20) | |
| out["item_tighter"] = dump(tighter, 0) | |
| out["counters_tighter"] = {"truncated": tighter.n_rows_plan_truncated} | |
| rej = write_corpus(tmpdir / "rej.jsonl", [ | |
| _row(SUM_D, plan={"words": list(PLAN_WORDS), "ok": False}), | |
| _row(SUM_D, plan=list(PLAN_WORDS)), | |
| ]) | |
| ds_rej = make_dataset(rej, reg, "plan") | |
| out["rejected_audit"] = ds_rej.plan_audit | |
| out["rejected_item0_schedule"] = dump(ds_rej, 0)["plan_schedule"] | |
| out["rejected_counters"] = {"rejected": ds_rej.n_rows_plan_rejected, | |
| "missing": ds_rej.n_rows_missing_plan} | |
| noplan = write_corpus(tmpdir / "noplan.jsonl", [_row(SUM_D), _row(SUM_D)]) | |
| out["err_zero_coverage"] = _err(make_dataset, noplan, reg, "plan") | |
| out["err_stage1_plan_arm"] = _err(lambda: make_dataset(path, reg, "plan", stage=1)) | |
| out["err_min_coverage"] = _err( | |
| lambda: make_dataset(path, reg, "plan", min_plan_coverage=0.95)) | |
| bad_bin = write_corpus(tmpdir / "badbin.jsonl", [ | |
| _row(SUM_D, plan=[{"pitch_bin": 3, "dur_bin": 99, "energy_bin": 0, | |
| "dur_frames": 2}])]) | |
| out["err_bad_dur_bin"] = _err(lambda: make_dataset(bad_bin, reg, "plan")[0]) | |
| no_frames = write_corpus(tmpdir / "nodur.jsonl", [ | |
| _row(SUM_D, plan=[{"pitch_bin": 3, "dur_bin": 1, "energy_bin": 0}])]) | |
| out["err_no_dur_frames"] = _err(lambda: make_dataset(no_frames, reg, "plan")[0]) | |
| out["err_no_dur_frames_msg"] = _msg(lambda: make_dataset(no_frames, reg, "plan")[0]) | |
| dur_s = write_corpus(tmpdir / "durs.jsonl", [ | |
| _row(SUM_D, plan=[{"pitch_bin": 3, "dur_bin": 1, "energy_bin": 0, | |
| "dur_s": 0.5}])]) | |
| out["dur_s_frames"] = dump(make_dataset(dur_s, reg, "plan"), 0)["plan_durations"] | |
| out["legacy_expected_prose"] = expected_legacy_ids( | |
| reg, tok_, REASONING, SUM_D) | |
| out["legacy_expected_tags"] = expected_legacy_ids( | |
| reg, tok_, "EMO=joyful PACE=fast PITCH=high", SUM_D) | |
| out["legacy_expected_none"] = expected_legacy_ids(reg, tok_, "", SUM_D) | |
| return out | |
| def _err(fn, *args): | |
| try: | |
| fn(*args) | |
| except Exception as exc: | |
| return type(exc).__name__ | |
| return None | |
| def _msg(fn, *args): | |
| try: | |
| fn(*args) | |
| except Exception as exc: | |
| return str(exc) | |
| return "" | |
| _CACHE: dict = {} | |
| def _run_probe(**env_extra) -> dict: | |
| key = tuple(sorted(env_extra.items())) | |
| if key in _CACHE: | |
| return _CACHE[key] | |
| env = dict(os.environ) | |
| env.update(env_extra) | |
| env["PYTHONPATH"] = str(REPO_ROOT) + os.pathsep + env.get("PYTHONPATH", "") | |
| proc = subprocess.run( | |
| [sys.executable, str(Path(__file__).resolve())], | |
| capture_output=True, text=True, cwd=str(REPO_ROOT), env=env) | |
| assert proc.returncode == 0, ( | |
| f"probe subprocess failed (env={env_extra}):\n" | |
| f"{proc.stdout[-2000:]}\n{proc.stderr[-4000:]}") | |
| result = json.loads(proc.stdout.strip().splitlines()[-1]) | |
| _CACHE[key] = result | |
| return result | |
| def on() -> dict: | |
| return _run_probe(MVC_ENABLE_PLAN_TOKENS="1", MVC_NUM_SPEECH_TOKENS="64") | |
| def reg(): | |
| import config | |
| if config.ENABLE_PLAN_TOKENS: | |
| pytest.skip("suite is running with MVC_ENABLE_PLAN_TOKENS=1; gate-off N/A") | |
| return fake_registry() | |
| def corpus(tmp_path): | |
| return write_corpus(tmp_path / "legacy.jsonl", | |
| [_row(SUM_D), _row(SUM_D, reasoning="")]) | |
| class TestLegacyUnchanged: | |
| def test_sequence_is_the_hand_written_answer(self, corpus, reg, mode, think_text): | |
| ds = make_dataset(corpus, reg, mode) | |
| got = ds[0]["input_ids"].tolist() | |
| assert got == expected_legacy_ids(reg, reg.tokenizer, think_text, SUM_D) | |
| def test_none_emits_no_think_block_at_all(self, corpus, reg): | |
| ids = make_dataset(corpus, reg, "none")[0]["input_ids"].tolist() | |
| assert reg.think_start_id not in ids | |
| assert reg.think_end_id not in ids | |
| def test_stage1_row_in_auto_mode_still_gets_no_think(self, corpus, reg): | |
| ids = make_dataset(corpus, reg, "prose")[1]["input_ids"].tolist() | |
| assert reg.think_start_id not in ids | |
| def test_legacy_loss_weights_unchanged(self, corpus, reg): | |
| item = make_dataset(corpus, reg, "prose", reasoning_weight=0.3)[0] | |
| w = item["loss_weights"].tolist() | |
| n_prompt = len(reg.tokenizer.encode(PROMPT)) | |
| lo = 2 + n_prompt | |
| hi = lo + 1 + len(reg.tokenizer.encode(REASONING)) + 1 | |
| assert w[lo:hi] == pytest.approx([0.3] * (hi - lo)) | |
| assert set(w[:lo]) == {1.0} and set(w[hi:]) == {1.0} | |
| def test_no_plan_keys_leak_into_a_legacy_batch(self, corpus, reg): | |
| from delay_dataset import DelayCollator | |
| ds = make_dataset(corpus, reg, "prose") | |
| batch = DelayCollator(pad_token_id=reg.pad_id)([ds[0], ds[1]]) | |
| assert not [k for k in batch if k.startswith("plan_")] | |
| assert set(batch) == {"input_ids", "labels", "codes", "attention_mask", | |
| "loss_weights", "speaker_ids"} | |
| def test_item_exposes_plan_fields_as_none(self, corpus, reg): | |
| item = make_dataset(corpus, reg, "prose")[0] | |
| assert item["plan_schedule"] is None | |
| assert item["plan_slots"] is None | |
| assert item["plan_durations"] is None | |
| class TestGateOffRefusesPlanArms: | |
| def test_plan_mode_without_the_vocabulary_is_fatal(self, corpus, reg, mode): | |
| with pytest.raises(RuntimeError, match="MVC_ENABLE_PLAN_TOKENS"): | |
| make_dataset(corpus, reg, mode) | |
| def test_unknown_cot_mode_still_rejected(self, corpus, reg): | |
| with pytest.raises(AssertionError): | |
| make_dataset(corpus, reg, "plann") | |
| class TestSchedule: | |
| def test_stretch_tiles_the_span_exactly(self): | |
| from delay_dataset import build_plan_schedule | |
| assert build_plan_schedule([2, 4, 6], 12) == ( | |
| [0] * 2 + [1] * 4 + [2] * 6) | |
| def test_stretch_dilates_proportionally(self): | |
| from delay_dataset import build_plan_schedule | |
| assert build_plan_schedule([2, 4, 6], 24) == ( | |
| [0] * 4 + [1] * 8 + [2] * 12) | |
| def test_stretch_covers_every_frame_and_every_word(self): | |
| from delay_dataset import build_plan_schedule | |
| sched = build_plan_schedule([3, 1, 7, 2], 37) | |
| assert -1 not in sched and len(sched) == 37 | |
| assert sorted(set(sched)) == [0, 1, 2, 3] | |
| assert sched == sorted(sched) | |
| def test_pack_is_reproducible_from_the_plan_alone(self): | |
| from delay_dataset import build_plan_schedule, NO_WORD | |
| assert build_plan_schedule([2, 4, 6], 24, "pack") == ( | |
| [0] * 2 + [1] * 4 + [2] * 6 + [NO_WORD] * 12) | |
| def test_pack_clips_at_the_span_without_wrapping(self): | |
| from delay_dataset import build_plan_schedule | |
| assert build_plan_schedule([2, 4, 6], 5, "pack") == [0, 0, 1, 1, 1] | |
| def test_more_words_than_frames_does_not_crash(self): | |
| from delay_dataset import build_plan_schedule | |
| sched = build_plan_schedule([1, 1, 1, 1], 2) | |
| assert len(sched) == 2 and sched == sorted(sched) | |
| def test_empty_and_zero_cases(self): | |
| from delay_dataset import build_plan_schedule, NO_WORD | |
| assert build_plan_schedule([], 3) == [NO_WORD] * 3 | |
| assert build_plan_schedule([1, 2], 0) == [] | |
| def test_degenerate_durations_raise(self): | |
| from delay_dataset import build_plan_schedule | |
| with pytest.raises(ValueError): | |
| build_plan_schedule([0, 0], 10) | |
| with pytest.raises(ValueError): | |
| build_plan_schedule([1, -2], 10) | |
| def test_unknown_mode_raises(self): | |
| from delay_dataset import build_plan_schedule | |
| with pytest.raises(ValueError, match="schedule mode"): | |
| build_plan_schedule([1], 1, "squash") | |
| class TestWordNormalisation: | |
| def _norm(self, words): | |
| from delay_dataset import normalise_plan_words | |
| return normalise_plan_words(words, n_pitch_bins=16, n_duration_bins=16, | |
| n_energy_bins=8) | |
| def test_unvoiced_sentinel_becomes_none(self): | |
| out = self._norm([{"pitch_bin": 16, "dur_bin": 0, "energy_bin": 0, | |
| "dur_frames": 3}]) | |
| assert out[0]["pitch_bin"] is None | |
| def test_out_of_range_bins_raise_with_coordinates(self): | |
| from delay_dataset import normalise_plan_words | |
| with pytest.raises(ValueError, match="word 1"): | |
| normalise_plan_words( | |
| [{"pitch_bin": 0, "dur_bin": 0, "energy_bin": 0, "dur_frames": 1}, | |
| {"pitch_bin": 0, "dur_bin": 0, "energy_bin": 9, "dur_frames": 1}], | |
| n_pitch_bins=16, n_duration_bins=16, n_energy_bins=8) | |
| def test_pitch_above_the_sentinel_raises(self): | |
| with pytest.raises(ValueError, match="pitch_bin"): | |
| self._norm([{"pitch_bin": 17, "dur_bin": 0, "energy_bin": 0, | |
| "dur_frames": 1}]) | |
| def test_seconds_are_converted_at_the_declared_frame_rate(self): | |
| from delay_dataset import normalise_plan_words | |
| out = normalise_plan_words( | |
| [{"pitch_bin": 0, "dur_bin": 0, "energy_bin": 0, "dur_s": 0.5}], | |
| n_pitch_bins=16, n_duration_bins=16, n_energy_bins=8, frame_rate=20.0) | |
| assert out[0]["dur_frames"] == 10 | |
| def _plan_span(on, item): | |
| ids = item["input_ids"] | |
| return ids.index(on["plan_start_id"]), ids.index(on["plan_end_id"]) + 1 | |
| class TestPlanAssembly: | |
| def test_legacy_arms_are_unchanged_with_the_gate_on(self, on): | |
| assert on["items_prose"][0]["input_ids"] == on["legacy_expected_prose"] | |
| assert on["items_tags"][0]["input_ids"] == on["legacy_expected_tags"] | |
| assert on["items_none"][0]["input_ids"] == on["legacy_expected_none"] | |
| def test_plan_block_is_exactly_the_program(self, on): | |
| item = on["items_plan"][0] | |
| lo, hi = _plan_span(on, item) | |
| expected = ( | |
| [on["plan_start_id"]] | |
| + [on["plan_word_sep_id"], on["pitch_ids"][3], | |
| on["duration_ids"][1], on["energy_ids"][0]] | |
| + [on["plan_word_sep_id"], on["duration_ids"][4], on["energy_ids"][7]] | |
| + [on["plan_word_sep_id"], on["pitch_ids"][15], | |
| on["duration_ids"][9], on["energy_ids"][3]] | |
| + [on["plan_end_id"]]) | |
| assert item["input_ids"][lo:hi] == expected | |
| def test_plan_only_arm_carries_no_prose_and_no_tags(self, on): | |
| item = on["items_plan"][0] | |
| ids = item["input_ids"] | |
| i = ids.index(on["think_start_id"]) | |
| assert ids[i + 1] == on["plan_start_id"] | |
| assert ids[ids.index(on["plan_end_id"]) + 1] == on["think_end_id"] | |
| for tid in on["reasoning_ids"] + on["tag_ids"]: | |
| assert tid not in ids | |
| def test_tier_order_is_prose_then_tags_then_plan(self, on): | |
| ids = on["items_full"][0]["input_ids"] | |
| i_think = ids.index(on["think_start_id"]) | |
| i_prose = ids.index(on["reasoning_ids"][0]) | |
| i_tags = ids.index(on["tag_ids_after_prose"][0]) | |
| i_plan = ids.index(on["plan_start_id"]) | |
| i_end = ids.index(on["think_end_id"]) | |
| assert i_think < i_prose < i_tags < i_plan < i_end | |
| def test_tags_plus_plan_has_no_prose(self, on): | |
| ids = on["items_tags+plan"][0]["input_ids"] | |
| assert ids[ids.index(on["think_start_id"]) + 1] == on["tag_ids"][0] | |
| for tid in on["reasoning_ids"]: | |
| assert tid not in ids | |
| def test_audio_content_is_identical_across_arms(self, on): | |
| base = on["items_none"][0]["codes"] | |
| for mode in ("prose", "tags", "plan", "tags+plan", "full"): | |
| item = on[f"items_{mode}"][0] | |
| codes = [c for c in item["codes"] if c[0] != -1] | |
| assert codes == [c for c in base if c[0] != -1], mode | |
| class TestPerTierLossWeights: | |
| def test_each_tier_lands_on_exactly_its_own_positions(self, on): | |
| item = on["item_full_weighted"] | |
| w = item["loss_weights"] | |
| ids = item["input_ids"] | |
| lo = ids.index(on["think_start_id"]) | |
| n_prose = len(on["reasoning_ids"]) | |
| n_tags = len(on["tag_ids_after_prose"]) | |
| p_lo, p_hi = _plan_span(on, item) | |
| assert w[lo] == pytest.approx(0.3) | |
| assert w[lo + 1: lo + 1 + n_prose] == pytest.approx([0.3] * n_prose) | |
| assert w[lo + 1 + n_prose: p_lo] == [1.0] * n_tags | |
| assert w[p_lo:p_hi] == [2.0] * (p_hi - p_lo) | |
| assert w[p_hi] == pytest.approx(0.3) | |
| assert set(w[:lo]) == {1.0} and set(w[p_hi + 1:]) == {1.0} | |
| def test_tag_weight_defaults_to_the_reasoning_weight(self, on): | |
| item = on["items_tags"][0] | |
| w = item["loss_weights"] | |
| lo = item["input_ids"].index(on["think_start_id"]) | |
| n = 1 + len(on["tag_ids"]) + 1 | |
| assert w[lo:lo + n] == pytest.approx([0.3] * n) | |
| def test_plan_tokens_are_supervised_targets(self, on): | |
| item = on["items_plan"][0] | |
| lo, hi = _plan_span(on, item) | |
| assert item["labels"][lo:hi] == item["input_ids"][lo:hi] | |
| class TestScheduleAlignment: | |
| def test_position_to_word_map_is_exact(self, on): | |
| item = on["items_plan"][0] | |
| sched = item["plan_schedule"] | |
| a0 = item["audio_start"] | |
| expected_frames = [0] * 2 + [1] * 4 + [2] * 6 | |
| for t, word in enumerate(expected_frames): | |
| assert sched[a0 + t - 1] == word, f"frame {t}" | |
| assert set(sched[: a0 - 1]) == {on["no_word"]} | |
| assert set(sched[a0 + len(expected_frames) - 1:]) == {on["no_word"]} | |
| def test_frame_zero_is_scheduled_on_the_audio_token(self, on): | |
| item = on["items_plan"][0] | |
| a0 = item["audio_start"] | |
| assert item["input_ids"][a0 - 1] == on["audio_start_id"] | |
| assert item["plan_schedule"][a0 - 1] == 0 | |
| def test_lookahead_zero_shifts_by_exactly_one(self, on): | |
| shifted = on["item_plan_lookahead0"]["plan_schedule"] | |
| base = on["items_plan"][0]["plan_schedule"] | |
| assert shifted[1:] == base[:-1] | |
| def test_stretch_dilates_when_the_clip_is_longer_than_the_program(self, on): | |
| item = on["items_plan"][2] | |
| a0 = item["audio_start"] | |
| expected = [0] * 4 + [1] * 8 + [2] * 12 | |
| assert item["plan_schedule"][a0 - 1: a0 - 1 + 24] == expected | |
| def test_pack_leaves_the_tail_unscheduled(self, on): | |
| item = on["items_plan_pack"][2] | |
| a0 = item["audio_start"] | |
| expected = [0] * 2 + [1] * 4 + [2] * 6 + [on["no_word"]] * 12 | |
| assert item["plan_schedule"][a0 - 1: a0 - 1 + 24] == expected | |
| def test_slots_point_at_the_words_own_plan_tokens(self, on): | |
| item = on["items_plan"][0] | |
| ids = item["input_ids"] | |
| slots = item["plan_slots"] | |
| assert [ids[s[0]] for s in slots if s[0] != -1] == [ | |
| on["pitch_ids"][3], on["pitch_ids"][15]] | |
| assert slots[1][0] == -1 | |
| assert [ids[s[1]] for s in slots] == [on["duration_ids"][b] | |
| for b in (1, 4, 9)] | |
| assert [ids[s[2]] for s in slots] == [on["energy_ids"][b] | |
| for b in (0, 7, 3)] | |
| def test_durations_match_the_sidecar(self, on): | |
| assert on["items_plan"][0]["plan_durations"] == [2, 4, 6] | |
| def test_seconds_fall_back_at_the_declared_frame_rate(self, on): | |
| assert on["dur_s_frames"] == [11] | |
| class TestMissingPlansAreVisible: | |
| def test_a_plan_less_row_degrades_to_the_stage1_layout(self, on): | |
| item = on["items_plan"][1] | |
| assert on["think_start_id"] not in item["input_ids"] | |
| assert item["plan_schedule"] is None | |
| assert item["plan_slots"] is None | |
| def test_the_degradation_is_counted(self, on): | |
| assert on["counters_plan"]["missing"] == 1 | |
| assert on["counters_plan"]["seen"] == 3 | |
| def test_construction_audits_coverage(self, on): | |
| audit = on["audit_plan"] | |
| assert audit["scanned"] == 3 and audit["with_plan"] == 2 | |
| assert abs(audit["coverage"] - 2 / 3) < 1e-9 | |
| assert audit["mean_words"] == 3.0 | |
| assert audit["sampled"] is False | |
| def test_legacy_arms_run_no_audit(self, on): | |
| for mode in ("prose", "tags", "none"): | |
| assert on[f"audit_{mode}"] is None | |
| def test_a_corpus_with_no_plans_at_all_is_fatal(self, on): | |
| assert on["err_zero_coverage"] == "RuntimeError" | |
| def test_min_coverage_is_enforceable(self, on): | |
| assert on["err_min_coverage"] == "RuntimeError" | |
| def test_a_plan_arm_pinned_to_stage_1_is_fatal(self, on): | |
| assert on["err_stage1_plan_arm"] == "ValueError" | |
| def test_a_rejected_sidecar_is_dropped_not_used(self, on): | |
| assert on["rejected_item0_schedule"] is None | |
| assert on["rejected_counters"]["rejected"] == 1 | |
| assert on["rejected_audit"]["rejected"] == 1 | |
| assert on["rejected_audit"]["with_plan"] == 1 | |
| def test_malformed_plans_raise_loudly(self, on): | |
| assert on["err_bad_dur_bin"] == "ValueError" | |
| assert on["err_no_dur_frames"] == "ValueError" | |
| assert "dur_frames" in on["err_no_dur_frames_msg"] | |
| assert "plan_extract" in on["err_no_dur_frames_msg"] | |
| class TestTruncationPolicy: | |
| def test_reasoning_goes_first(self, on): | |
| item = on["item_tight"] | |
| ids = item["input_ids"] | |
| assert on["plan_start_id"] in ids, "the plan was dropped before the prose" | |
| for tid in on["reasoning_ids"]: | |
| assert tid not in ids | |
| assert on["counters_tight"]["prose_dropped"] == 1 | |
| def test_the_window_is_respected(self, on): | |
| assert len(on["item_tight"]["input_ids"]) <= 40 | |
| assert len(on["item_tighter"]["input_ids"]) <= 20 | |
| def test_a_words_program_is_never_split(self, on): | |
| item = on["item_tighter"] | |
| ids = item["input_ids"] | |
| lo, hi = _plan_span(on, item) | |
| body = ids[lo + 1: hi - 1] | |
| assert body, "the whole program vanished" | |
| assert body[0] == on["plan_word_sep_id"] | |
| groups, cur = [], [] | |
| for tid in body: | |
| if tid == on["plan_word_sep_id"]: | |
| if cur: | |
| groups.append(cur) | |
| cur = [] | |
| else: | |
| cur.append(tid) | |
| groups.append(cur) | |
| for g in groups: | |
| assert len(g) in (2, 3), f"partial word {g}" | |
| assert g[-2] in on["duration_ids"] and g[-1] in on["energy_ids"] | |
| if len(g) == 3: | |
| assert g[0] in on["pitch_ids"] | |
| def test_truncation_is_counted(self, on): | |
| assert on["counters_tighter"]["truncated"] >= 1 | |
| def test_the_schedule_still_covers_only_surviving_words(self, on): | |
| item = on["item_tighter"] | |
| n_words = len(item["plan_slots"]) | |
| assert max(item["plan_schedule"]) < n_words | |
| assert len(item["plan_durations"]) == n_words | |
| class TestCollator: | |
| def test_plan_keys_appear_only_when_a_plan_is_present(self, on): | |
| assert not [k for k in on["batch_keys_plainarm"] if k.startswith("plan_")] | |
| for key in ("plan_schedule", "plan_slots", "plan_durations", "plan_lengths"): | |
| assert key in on["batch_keys"] | |
| def test_padding_never_looks_like_word_zero(self, on): | |
| sched = on["batch"]["plan_schedule"] | |
| assert len(set(len(r) for r in sched)) == 1, "ragged batch" | |
| assert set(sched[1]) == {-1}, "the plan-less row must be all NO_WORD" | |
| assert sched[0][-1] == -1 | |
| def test_slots_and_durations_pad_correctly(self, on): | |
| slots = on["batch"]["plan_slots"] | |
| durations = on["batch"]["plan_durations"] | |
| lengths = on["batch"]["plan_lengths"] | |
| assert lengths == [3, 0, 3] | |
| assert slots[1] == [[-1, -1, -1]] * 3 | |
| assert durations[1] == [0, 0, 0] | |
| assert durations[0] == [2, 4, 6] | |
| assert sum(durations[1]) == 0 | |
| def test_schedule_rows_align_with_the_padded_input(self, on): | |
| sched = on["batch"]["plan_schedule"] | |
| item0 = on["items_plan"][0] | |
| a0 = item0["audio_start"] | |
| assert sched[0][a0 - 1] == 0 | |
| assert sched[0][: a0 - 1] == [-1] * (a0 - 1) | |
| if __name__ == "__main__": | |
| import tempfile | |
| with tempfile.TemporaryDirectory() as td: | |
| print(json.dumps(probe(td))) | |