Download code/tests/test_p2cot_seams.py from maxpicy/mamba-cot-tts: direct link, hf CLI and curl.
- Browser
- Download file 9.27 kB
-
https://huggingface.co/maxpicy/mamba-cot-tts/resolve/main/code/tests/test_p2cot_seams.py
- Command line
-
hf download hf://maxpicy/mamba-cot-tts/code/tests/test_p2cot_seams.py
-
curl -L -o test_p2cot_seams.py https://huggingface.co/maxpicy/mamba-cot-tts/resolve/main/code/tests/test_p2cot_seams.py
9.27 kB
| # test_p2cot_seams.py: The plan tier's cross-file contracts. | |
| import json | |
| import os | |
| import subprocess | |
| import sys | |
| 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)) | |
| PROBE = r''' | |
| import json, sys, tempfile | |
| from pathlib import Path | |
| REPO = Path(sys.argv[1]) | |
| sys.path.insert(0, str(REPO)); sys.path.insert(0, str(REPO / "scripts")) | |
| out = {} | |
| try: | |
| import torch | |
| from tokenizer import load_base_tokenizer, expand_tokenizer, TokenRegistry | |
| import plan_extract as PX | |
| import plan_adherence as PA | |
| import delay_dataset as DD | |
| import model as M | |
| import train as TR | |
| tok = load_base_tokenizer() | |
| expand_tokenizer(tok) | |
| reg = TokenRegistry(tok) | |
| except Exception as e: # offline / missing cache | |
| print(json.dumps({"unavailable": f"{type(e).__name__}: {e}"})) | |
| raise SystemExit(0) | |
| # A plan with a deliberately UNVOICED middle word and both extreme bins. | |
| WORDS = [ | |
| {"word": "alpha", "pitch_bin": 3, "dur_bin": 4, "energy_bin": 2, "dur_frames": 7}, | |
| {"word": "sss", "pitch_bin": PX.PITCH_UNVOICED_BIN, | |
| "dur_bin": 1, "energy_bin": 0, "dur_frames": 3}, | |
| {"word": "omega", "pitch_bin": 15, "dur_bin": 9, "energy_bin": 7, "dur_frames": 11}, | |
| ] | |
| T = sum(w["dur_frames"] for w in WORDS) | |
| # ---- S1: extractor string -> tokenizer ids, one id per symbol -------------- | |
| plan_str = PX.plan_to_tokens(WORDS, wrap=True) | |
| ids = tok.encode(plan_str, add_special_tokens=False) | |
| n_symbols = 2 + sum(1 + (0 if w["pitch_bin"] == PX.PITCH_UNVOICED_BIN else 1) + 2 | |
| for w in WORDS) | |
| out["extractor_string"] = plan_str | |
| out["n_ids"] = len(ids) | |
| out["n_symbols"] = n_symbols | |
| out["ids_are_plan_block"] = all(reg.is_plan_token(int(i)) for i in ids) | |
| # ---- S1/S2: dataset-emitted ids -> extractor parser ------------------------ | |
| row = {"prompt": "alpha sss omega", | |
| "speech_tokens": [5] * T, | |
| "residual_codes": [[7] * T for _ in range(DD.NUM_LEVELS - 1)], | |
| "speaker_id": 1, | |
| "plan": {"words": WORDS, "ok": True, "coverage": 1.0}} | |
| p = Path(tempfile.mkdtemp()) / "rows.jsonl" | |
| p.write_text(json.dumps(row) + "\n" + json.dumps(row) + "\n", encoding="utf-8") | |
| ds = DD.DelayMimiDataset(str(p), tok, reg, max_seq_len=512, stage=2, | |
| aligned=True, cot_mode="plan", audio_continue_weight=1.0) | |
| item = ds[0] | |
| seq = item["input_ids"].tolist() | |
| plan_pos = [i for i, t in enumerate(seq) if reg.is_plan_token(t)] | |
| dataset_str = "".join(tok.convert_ids_to_tokens([seq[i] for i in plan_pos])) | |
| out["dataset_string"] = dataset_str | |
| out["dataset_string_matches_extractor"] = (dataset_str == plan_str) | |
| out["parsed_back"] = PX.tokens_to_plan(dataset_str) | |
| # ---- S3: collator slots -> train adapter -> injector bins ------------------ | |
| batch = DD.DelayCollator(pad_token_id=0)([ds[0], ds[1]]) | |
| out["collator_plan_keys"] = sorted(k for k in batch if k.startswith("plan_")) | |
| bins = TR.plan_bins_from_slots(batch["input_ids"], batch["plan_slots"], reg) | |
| out["bins"] = bins.tolist() | |
| inj = M.PlanInjector(d_model=16, n_pitch_bins=len(reg.pitch_ids), | |
| n_duration_bins=len(reg.duration_ids), | |
| n_energy_bins=len(reg.energy_ids), d_plan=8, | |
| scaffold_dropout=0.0) | |
| out["injector_accepts_batch"] = tuple( | |
| inj(bins, batch["plan_schedule"]).shape) == (2, len(seq), 16) | |
| # ---- S4: the two schedule builders ---------------------------------------- | |
| durs = [w["dur_frames"] for w in WORDS] | |
| a0 = int(item["audio_start"]) | |
| ds_sched = item["plan_schedule"].tolist() | |
| m_sched = M.build_plan_schedule([durs], a0, T, seq_len=len(seq))[0].tolist() | |
| # plan_lookahead=1: the dataset places frame t one position EARLIER than | |
| # model.build_plan_schedule does, because the input at p predicts the code at | |
| # p+1. Shift by exactly that one position and the two must be identical. | |
| shifted = [-1] * len(seq) | |
| for t in range(T): | |
| shifted[a0 + t - 1] = m_sched[a0 + t] | |
| out["schedules_agree_modulo_lookahead"] = (shifted == ds_sched) | |
| out["dataset_schedule_head"] = ds_sched[a0 - 2:a0 + 4] | |
| out["model_schedule_head"] = m_sched[a0 - 2:a0 + 4] | |
| # ---- S2/S5: PAS against the extractor's own output ------------------------- | |
| try: | |
| out["pas_on_quantised_output"] = PA.pas(WORDS, WORDS)["pas"] | |
| except Exception as e: | |
| out["pas_on_quantised_output"] = f"RAISED {type(e).__name__}: {e}" | |
| out["plan_extract_has_contract"] = { | |
| n: hasattr(PX, n) for n in ("parse_plan_string", "extract_plan_words")} | |
| try: | |
| sg = PA.score_generation("g.wav", plan_str, "alpha sss omega", | |
| extract_fn=lambda w, t, **k: PX.parse_plan_string(plan_str)) | |
| out["score_generation_self_pas"] = sg["pas"]["pas"] | |
| except Exception as e: | |
| out["score_generation_self_pas"] = f"RAISED {type(e).__name__}: {e}" | |
| print(json.dumps(out)) | |
| ''' | |
| def seams(): | |
| env = dict(os.environ) | |
| env["MVC_ENABLE_PLAN_TOKENS"] = "1" | |
| env["MVC_NUM_SPEECH_TOKENS"] = "1024" | |
| env["MVC_NUM_CODEC_LEVELS"] = "10" | |
| env["HF_HUB_OFFLINE"] = env.get("HF_HUB_OFFLINE", "1") | |
| proc = subprocess.run([sys.executable, "-c", PROBE, str(REPO_ROOT)], | |
| capture_output=True, text=True, env=env, timeout=900) | |
| if proc.returncode != 0: | |
| pytest.fail(f"seam probe crashed:\n{proc.stdout}\n{proc.stderr}") | |
| line = proc.stdout.strip().splitlines()[-1] | |
| data = json.loads(line) | |
| if "unavailable" in data: | |
| pytest.skip(f"real tokenizer unavailable: {data['unavailable']}") | |
| return data | |
| def test_plan_symbols_cost_exactly_one_token_id_each(seams): | |
| assert seams["n_ids"] == seams["n_symbols"], seams["extractor_string"] | |
| assert seams["ids_are_plan_block"], "a plan symbol tokenized outside the plan block" | |
| def test_dataset_emits_exactly_the_string_the_extractor_writes(seams): | |
| assert seams["dataset_string_matches_extractor"], ( | |
| f"dataset: {seams['dataset_string']!r}\n" | |
| f"extractor: {seams['extractor_string']!r}") | |
| def test_extractor_parser_recovers_the_dataset_program(seams): | |
| expect = [{"pitch_bin": 3, "dur_bin": 4, "energy_bin": 2}, | |
| {"pitch_bin": 16, "dur_bin": 1, "energy_bin": 0}, | |
| {"pitch_bin": 15, "dur_bin": 9, "energy_bin": 7}] | |
| assert seams["parsed_back"] == expect | |
| def test_collator_emits_the_channels_the_train_loop_reads(seams): | |
| assert seams["collator_plan_keys"] == [ | |
| "plan_durations", "plan_lengths", "plan_schedule", "plan_slots"] | |
| def test_slots_decode_back_to_the_sidecar_bins(seams): | |
| expect_row = [[3, 4, 2], [-1, 1, 0], [15, 9, 7]] | |
| assert seams["bins"] == [expect_row, expect_row] | |
| def test_injector_consumes_the_collated_batch_unchanged(seams): | |
| assert seams["injector_accepts_batch"] | |
| def test_pas_accepts_the_extractors_unvoiced_sentinel(seams): | |
| assert seams["pas_on_quantised_output"] == 1.0, seams["pas_on_quantised_output"] | |
| def test_training_and_decode_schedules_agree_modulo_the_lookahead(seams): | |
| assert seams["schedules_agree_modulo_lookahead"], ( | |
| f"dataset {seams['dataset_schedule_head']} vs " | |
| f"model {seams['model_schedule_head']}") | |
| def test_plan_extract_exposes_the_entry_points_pas_resolves(seams): | |
| assert seams["plan_extract_has_contract"] == { | |
| "parse_plan_string": True, "extract_plan_words": True} | |
| def test_score_generation_runs_through_the_real_parser(seams): | |
| assert seams["score_generation_self_pas"] == 1.0, seams["score_generation_self_pas"] | |
| def test_trailing_zero_duration_word_is_never_scheduled(): | |
| torch = pytest.importorskip("torch") | |
| from model import build_plan_schedule | |
| got = build_plan_schedule([[4, 0]], 0, 6)[0].tolist() | |
| assert got == [0, 0, 0, 0, 0, 0], got | |
| got = build_plan_schedule([[3, 2, 0, 0]], 0, 8)[0].tolist() | |
| assert got == [0, 0, 0, 1, 1, 1, 1, 1], got | |
| got = build_plan_schedule([[0, 0]], 0, 3)[0].tolist() | |
| assert got == [-1, -1, -1], got | |
| def test_documented_known_answers_still_hold(): | |
| pytest.importorskip("torch") | |
| from model import build_plan_schedule | |
| assert build_plan_schedule([[2, 3]], 0, 5)[0].tolist() == [0, 0, 1, 1, 1] | |
| assert build_plan_schedule([[2, 2]], 0, 6)[0].tolist() == [0, 0, 1, 1, 1, 1] | |
| assert build_plan_schedule([[3, 0, 2]], 0, 7)[0].tolist() == [0, 0, 0, 2, 2, 2, 2] | |
| assert build_plan_schedule([[4]], 2, 3, 7)[0].tolist() == [-1, -1, 0, 0, 0, -1, -1] | |
| def test_gate_off_leaves_no_plan_vocabulary(): | |
| import config | |
| import importlib | |
| importlib.reload(config) | |
| assert config.ENABLE_PLAN_TOKENS is False | |
| assert config.get_control_tokens() == [ | |
| config.USER_PROMPT_TOKEN, config.THINK_START_TOKEN, config.THINK_END_TOKEN, | |
| config.AUDIO_START_TOKEN, config.AUDIO_END_TOKEN, config.SPEAKER_TOKEN, | |
| ] + config.EMOTION_TAGS + config.PROSODY_TAGS | |
| def test_plan_extract_token_surface_matches_config_vocabulary(): | |
| sys.path.insert(0, str(REPO_ROOT / "scripts")) | |
| import plan_extract as PX | |
| assert PX.verify_config_vocab() == "ok" | |