softchart-barscript / config.json
JacobLinCool's picture
BarScript C1.3 (sc2_c1_v13_s1234_best) release package: bf16 weights, frozen serving contract, model card
09e2da6 verified
Raw
History Blame Contribute Delete
16.6 kB
{
"capabilities": {
"align": false,
"aux": true,
"axis_knobs": true,
"beat_head": true,
"complexity": false,
"ctx": false,
"dual": false,
"func_time": false,
"global_ctx": false,
"hierarchical_ctx": true,
"mask_infill": false,
"plan": false,
"sibling": false,
"slot": false,
"style": false,
"sync_token": true
},
"code": {
"git": {
"branch": null,
"commit": null,
"dirty": false
},
"module_md5": {
"src/softchart/__init__.py": "d41d8cd98f00b204e9800998ecf8427e",
"src/softchart/barscript.py": "9afc715a56ac28e9ec5675d64cd0536c",
"src/softchart/baseline.py": "875b63450c59bb62f5d50965ec7b218c",
"src/softchart/checkpoint.py": "10e215e86ac77ada9046a164bffa0644",
"src/softchart/data.py": "d0cf18237bc644f49bf2b62b9eef0ee3",
"src/softchart/evaluate.py": "72d588b7f0711dfa6d1f49b161172061",
"src/softchart/generate.py": "73b6e49b00fb60f3229c8539bc7a1029",
"src/softchart/grid.py": "eba9fddd432bee0b62ddfc13bdefc06d",
"src/softchart/hf.py": "727db85293862948587c99636ea1d1ef",
"src/softchart/meter.py": "18ccd6a003086f81276f2a916ada4c64",
"src/softchart/model.py": "eace5d89abeebf0edcf28d10b5ad3e68",
"src/softchart/preprocess.py": "b87fa0cc8af9628ae47a2fbe86de266a",
"src/softchart/proxies.py": "918c72c22d48e4ccb762e0fe814d0bfe",
"src/softchart/rhythm.py": "11cca7c58809b339f7384dcc0bf1fcaa",
"src/softchart/tja.py": "360b95e19dabe925bf8eab03fa3fd110",
"src/softchart/trace.py": "e707f7204f0d86deacca6b6325f031f1",
"src/softchart/train.py": "7f6323973c26992873717307f6652f91",
"src/softchart/vocab.py": "0f948a0efc52f5ce60e8219fcaeb136c"
},
"torch": "2.9.1+cu128"
},
"created_utc": "2026-07-26T00:17:52+00:00",
"model": {
"adapter_rank": 0,
"adapter_rank_ffn": 0,
"aux": true,
"beat": "hires",
"clean_phase": true,
"d_model": 256,
"dec_layers": 4,
"dec_share": null,
"depth_emb": false,
"dropout": 0.1,
"emb_factor": 64,
"enc_layers": 4,
"enc_share": null,
"ffn": 960,
"func_time": false,
"global_ctx": false,
"hierarchical_ctx": true,
"in_ch": 128,
"max_tgt": 960,
"nhead": 8,
"ptr": false,
"rich_section_stats": true,
"section_ffn": 512,
"section_layers": 2,
"span_duration_head": true,
"stage_emb": true,
"tempo_head": true,
"unique_layernorm": false,
"unshare_last_dec": false,
"vocab_size": 2071
},
"release_name": "sc2_c1_v13_s1234_best",
"schema_version": "softchart2_release_config_v1",
"serving": {
"bar_denom_mask": "lattice",
"bar_denoms": "supplied",
"degenerate_bar_sec": 0.25,
"family_bias": 2.0,
"family_hand_bias": 1.5,
"family_mode": "bias",
"greedy": false,
"min_onset_gap_sec": 0.02,
"motif_constraint": "auto",
"plan_temperature": null,
"span_bucket0_profile": null,
"span_min_beats": 0.3333333333333333,
"span_min_sec": 0.0833,
"temperature": 1.0,
"top_p": 0.95
},
"serving_basis": {
"bar_denom_mask": "Only consulted when bar_denoms='model'. 'lattice' = divisors of the bar's own TJA export lattice; a superset of 'div96' outside 4/4.",
"bar_denoms": "'supplied' teacher-forces the grid's per-bar denominators into every [BAR] header. It is the regime this checkpoint was TRAINED and EVALUATED under -- every published number belongs to it -- so it is the DEFAULT, and it is correct when the grid comes from a real authored/traced chart. It is the WRONG value on a synthetic uniform BPM grid: BAR_DENOM is a trained output token and the model reads a supplied denominator as a DENSITY ANNOUNCEMENT, so a forced /16 grid emits 1.69x / 1.46x / 1.30x / 1.21x the authored onsets on easy/normal/hard/oni and erases every triplet (off-/16 onsets 0 % against an authored 7.4-14.5 %). Use the 'deploy_bpm_grid' profile there. DEPLOY_GRID_FIX.md §5.2, §7; 13 songs x 4 courses, one seed.",
"degenerate_bar_sec": "Across 3 010 bars the authored side places ZERO hits in any bar shorter than 0.375 s (28 such bars, 2 songs); the shortest authored hit-bearing bar is 0.375 s. 0.25 s is the largest round threshold with zero authored counterexamples and a 1.5x margin, and it is the threshold the degenerate_bar_empty gate uses, so fix and gate cannot disagree. Blocks HITS only: authors DO route span geometry through sub-beat scaffolding measures. Source: src/softchart/generate.py DEGENERATE_BAR_SEC comment.",
"family_bias": "generate.FAMILY_BIAS. Additive logit bias toward the harder sibling's onset POSITIONS when courses are decoded as one nested difficulty family (generate_chart_family). 0 is the independent decode; 'subset' mode is the bias=infinity ablation arm.",
"family_hand_bias": "generate.FAMILY_HAND_BIAS. Additive logit bias toward the harder sibling's don/ka HAND at an inherited position. Steers type only, never position.",
"family_mode": "'bias' is the soft steering and the shipped value; 'subset' hard-restricts the easier course to the harder chart's positions and is kept for ablation only.",
"greedy": "Sampling, not argmax -- the evaluation population was produced at temperature 1.0 and every published number belongs to that decoder.",
"min_onset_gap_sec": "DEGENERACY GUARD, not a corpus percentile. Two earlier revisions (0.0395 s from a 43 387-pair subset; 0.0300 s, the 1 200-chart / 427 016-pair corpus minimum) were both wrong because a 1 000-song corpus is not the domain. The series record for two adjacent notes is 29.4118 ms (TAIKO-TONGUE-TWISTER oni, BPM 170, 48th notes, 34 hits/s); a 30 ms floor blocks the record itself. 0.020 s clears every documented chart with headroom and still blocks the observed degeneracy (six ka notes 16.7 ms apart rendering as one blob). The model's real defect on this axis is a RATE, not a value -- sub-40 ms gaps are 0.045 % of authored pairs and ~0.35 % of generated ones -- and a mask cannot fix a distribution. Source: src/softchart/generate.py MIN_ONSET_GAP_SEC comment.",
"motif_constraint": "'auto' = ON iff the checkpoint's own training cache (<cache>/<args.bs_subdir>/manifest.json) records a barscript_md5 equal to the md5 of the serving barscript.py. Only then did the gold sequences the checkpoint trained on satisfy the MOTIF hard constraint the serving FSM would apply, so only then is serving under it train/serve matched. This package records the RESOLVED value and its inputs under train_provenance.motif_constraint. Source: scripts/sc2_generate_eval.py MOTIF_AUTO_RULE (harness contract v2.1).",
"plan_temperature": "null = follow `temperature`. The four plan steps have an independent diversity knob; it was not exercised in the evaluation, so the package ships it unset rather than tuned.",
"span_bucket0_profile": "DISABLED (null) -- and this is a KNOWN GAP, not a choice on the merits. Duration bucket 0 is open at the bottom, so nothing bounds how short a span may be beyond the corpus floor and the realized length piles up on the lattice minimum; this checkpoint puts 21.2 % of its spans under 0.25 s against an authored 4.2 %. The mitigation exists in code (generate.SpanBucket0Profile / generate_song_barscript(span_bucket0_profile=...)) but NO PROFILE ARTIFACT HAS BEEN BUILT -- scripts/build_span_bucket0_profile.py has never been run on the train split, and no such file exists on the training host. Absent it the serving path is bit-identical to the shipped one. Building it is the shortest available micro-span fix.",
"span_min_beats": "Beat-relative companion to span_min_sec (1/3 quarter-note beat), so the floor survives a tempo change. Source: src/softchart/generate.py SPAN_MIN_BEATS.",
"span_min_sec": "Authored population minimum span duration; steers span closures and masks duration buckets away from lengths no author wrote. Fail-open at the mask level, counted as span_close_floor / span_floor_carry / dur_bucket_floor. Source: src/softchart/generate.py SPAN_MIN_SEC.",
"temperature": "1.0, as evaluated.",
"top_p": "0.95, as evaluated."
},
"serving_prefix_fix": "sync_token is forced ON at serving. train.py records sync_token=False, but the training prefix carries the SYNC slot, so a loader MUST set model._has_sync = True before decoding or every sync bucket reaches the decoder as the same prefix. sc2_package.load_release does this; see the SYNC note in scripts/sc2_generate_eval.py.",
"serving_profiles": {
"default": {
"overrides": {},
"when": "the supplied grid comes from a real chart trace (barscript_grid_from_trace) -- i.e. the bar denominators are the authored ones. This is the regime every published metric was measured in."
},
"deploy_bpm_grid": {
"basis": "DEPLOY_GRID_FIX.md §7, verbatim: 'Recommended now: model-emitted BAR_DENOM, masked to divisors of 96.' What it buys: note counts within 8 % of authored at every difficulty instead of 21-69 % over; the DENS plan back on the authored-grid distribution; triplets back from zero; span counts back to authored levels. What it COSTS, and this is not small: nesting coverage 0.635 / 0.706 / 0.778 against 0.835 / 0.845 / 0.866, worse on 12-13 of 13 songs, p <= .003 on all three course pairs -- the family decode's headline benefit is gone. What it does NOT fix: p90 onset offset 7-34 ms, frac_within_jnd 0.34-0.40, micro-spans 26-42 % on hard/oni. The report states the tradeoff as the finding: 'No arm here is acceptable on both axes, and that is the finding. The choice is between a chart whose difficulty is right and a chart whose difficulty ladder is nested, because one token controls both.' Evidence: 13 songs x 4 courses, one seed, this checkpoint. NOTE: DEPLOY_GRID_FIX measured this arm by runtime injection because bar_denoms='model' was then only a proposed interface; it is now implemented in generate_song_barscript, and this profile selects it directly.",
"overrides": {
"bar_denom_mask": "div96",
"bar_denoms": "model"
},
"when": "the grid is synthesized from user BPM/offset (barscript_grid_from_bpm), where every bar carries the same denominator and the model would read it as a density announcement."
}
},
"source": {
"best_val": 0.5769365892960475,
"checkpoint_file": "best.pt",
"checkpoint_select": "best",
"checkpoint_sha256": "44980bf64b1611ea73c1433c41adceff7596cfeece30dfaad5d228eae4a14e6e",
"mode": "c1",
"run_dir": "/home/jacob/softchart2/runs/sc2_c1_v13_s1234",
"seed": 1234,
"step": 96000
},
"train_provenance": {
"barscript_md5": "634e3dc3ddca8bcdceffd760e663e1b0",
"bs_subdir": "barscript",
"cache_manifest": "cache/barscript/manifest.json",
"dataset": "/home/jacob/softchart2/data/taiko-1000-parsed-clean",
"labels_version": "barscript_labels_v1",
"motif_constraint": {
"requested": "auto",
"resolved_motif_hard": false,
"serving_barscript_md5": "9afc715a56ac28e9ec5675d64cd0536c",
"source": "auto",
"train_cache_barscript_md5": "634e3dc3ddca8bcdceffd760e663e1b0",
"train_cache_built_by_serving_barscript": false,
"train_serve_matched": true
},
"revision": "b72da4616d643018e81f372cea06ce51349285e0",
"serving_barscript_md5": "9afc715a56ac28e9ec5675d64cd0536c",
"serving_barscript_path": "/home/jacob/softchart2/pkgstage/src/softchart/barscript.py",
"spec_file": "spec.json",
"spec_frozen_path": "/home/jacob/softchart2/cache/barscript_spec_frozen.json",
"spec_frozen_sha1": "cd8767684457915ece0d3d58ab80ade137ad79f5",
"spec_parameters_match_cache_manifest": true,
"spec_sha1": "cd8767684457915ece0d3d58ab80ade137ad79f5",
"spec_sha1_matches_cache_manifest_record": false,
"spec_sha1_matches_frozen_file": true,
"spec_sha1_note": "Three sha1s, and they are allowed to differ. spec_sha1 is the file shipped here; spec_frozen_sha1 is the spec artifact currently on the training host; spec_sha1_recorded_in_cache_manifest is what the cache builder recorded when the cache was built. The binding claim is spec_parameters_match_cache_manifest -- the bucket edges, motif tau and deltas shipped here are field-for-field the ones the checkpoint trained under. A sha1 mismatch means a re-serialization, not a different label contract.",
"spec_sha1_recorded_in_cache_manifest": "0893edb05b6473b983faff2aab166bcc18b4b3d6",
"train_args": {
"adapter_rank": 0,
"adapter_rank_ffn": 0,
"align": false,
"aux": true,
"axis_knobs": true,
"balance_cap": 2.5,
"balance_exclude_big": true,
"balanced": true,
"batch": 64,
"beat_all_window": false,
"beat_head": true,
"beat_hires": true,
"beat_weight": 1.0,
"bs_subdir": "barscript",
"cache": "/home/jacob/softchart2/cache",
"cal_axes": [
"big",
"span",
"density"
],
"cal_dens_margin_frac": 0.05,
"cal_margin": 0.5,
"cal_rows": 16,
"cal_weight": 0.05,
"clean_phase": true,
"complexity": false,
"cond_corrupt": 0.1,
"cond_drop": 0.15,
"ctx": false,
"d_model": 256,
"data_frac": 1.0,
"dec_layers": 4,
"dec_share": null,
"denom_augment": 0.5,
"denom_augment_mode": "lattice",
"depth_emb": false,
"distill": null,
"distill_tau": 2.0,
"distill_teacher": null,
"distill_weight": 0.5,
"dpo": null,
"dpo_beta": 0.1,
"dpo_hard": false,
"dropout": 0.1,
"dual": false,
"dual_slot_p": 0.65,
"emb_factor": 64,
"enc_layers": 4,
"enc_share": null,
"entropy_floor": 0.0,
"entropy_floor_weight": 0.1,
"ffn": 960,
"func_time": false,
"global_ctx": false,
"grammar_mask": true,
"hierarchical_ctx": true,
"importance_sampling": true,
"init_from": null,
"kd_alpha": 0.5,
"kd_tau": 2.0,
"lambda_plan": 1.0,
"lambda_type": 1.5,
"lr": 0.0005,
"lr_shared_core": 1.0,
"mask_infill": 0.0,
"max_tgt": 960,
"mode": "c1",
"nhead": 8,
"no_augment": false,
"out": "/home/jacob/softchart2/runs/sc2_c1_v13_s1234",
"plan": false,
"plan_dropout": 0.3,
"plan_jitter": 0.15,
"resume": null,
"rich_section_stats": true,
"section_ffn": 512,
"section_layers": 2,
"seed": 1234,
"sibling": false,
"slot": false,
"span_dur_weight": 1.0,
"span_duration_head": true,
"stage_emb": true,
"steps": 100000,
"style": false,
"sync_token": false,
"tempo_aug": false,
"tempo_head": true,
"tempo_weight": 0.2,
"unique_layernorm": false,
"unlikelihood_alpha": 1.0,
"unlikelihood_scope": "hits",
"unshare_last_dec": false,
"use_aug": false,
"val_every": 2000,
"warmup": 1000,
"workers": 12
}
},
"v2_flags": {
"axis_knobs": true,
"rich_section_stats": true,
"span_duration_head": true,
"stage_emb": true,
"tempo_head": true
},
"vocab": {
"checkpoint_rows": 2071,
"growth_policy": "append-only. checkpoint.expand_vocab_rows grows an older checkpoint's tok_emb (and a tied out.weight) to the current table with N(0, 0.02) rows under seed 20260725; a checkpoint with MORE rows than the runtime is refused.",
"mapping_sha256": "f139fbea1a13397015088b1ab2c33a952e97b05bb447bc86ce02f350d50dd679",
"max_tgt": 960,
"max_tgt_source": "checkpoint args",
"size": 2071,
"slots_per_4_4": 96,
"window_frames": 1728
},
"weights": {
"cast_cost": {
"float_elements": 9107291,
"max_abs_delta": 0.007111072540283203,
"max_abs_delta_relative_to_tensor_max": 0.0034862233048405743,
"max_abs_delta_tensor": "frontend.2.weight",
"note": "bfloat16 keeps 8 mantissa bits, so a cast costs up to 2^-9 relative. Training ran bf16 autocast (train.py) and inference runs bf16 autocast on CUDA (generate._autocast), so fp32 storage carried no information the forward pass could use -- the same argument the v1.5 release made and verified. It is an argument about the COMPUTE dtype, not a proof that the two checkpoints decode identically: sampling is chaotic in the logits, so individual charts can and do differ. fp32 is preserved in the source run directory."
},
"cast_from": "float32",
"dtype": "bfloat16",
"file": "model.safetensors",
"parameters": 9107291
}
}