You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Reference-conditioned H3 templates can drop 20 steps to 8: a Ref2VA turbo LoRA trained for transformer_ref now exists #149
tool/endpoint: the six reference-conditioned H3 templates — templates/minimax/reference-to-video, composable-references, voice-timbre-reference, generated-subject-reference, chain-matched-to-audio, chain-video-continuity
repro: each of the six carries no LoRA and runs num_inference_steps: 20.
expected / actual: the documented rationale is that "the turbo LoRA is distilled against the
base transformer and they load the reference one." That was accurate and is now out of date.
lightx2v/Minimax-h3-Turbo has carried a Ref2VA turbo LoRA — distilled fortransformer_ref
— since 2026-08-13, and an 8-step 768p one since 2026-08-27:
Recommended settings for the 8-step 768p one, from its release thread
(discussion #51): 8 steps,
video shift 12, audio shift 3, Euler, up to 768p. Community report there: it is better at
"keeping the references, even voice references are better."
note the shift asymmetry — do not generalise from the sibling issue. The 768p FL2VA LoRAs
want shift 6/3; this 768p Ref2VA LoRA wants 12/3.
proposed: re-point the six templates at the Ref2VA turbo LoRA, 20 steps -> 8.
guard worth encoding. Upstream is explicit: "Do not use an FL2VA LoRA checkpoint for [the
ref] command unless it was specifically trained for transformer_ref." Since lora_weight_name is a plain string variable, nothing currently stops an agent from passing an
FL2VA checkpoint to a reference template. A validation check on the ref path would prevent a
silent quality failure that costs 20 minutes to discover.
related, separate: where no LoRA is loaded at all, dw uses 20 steps, but upstream's base-model
examples use --inference-steps 50 for both T2VA and Ref2VA. Not necessarily wrong, but it is
not the documented base setting and is worth a deliberate decision rather than an inherited
default.
Done and deployed (cd71fc5, batched with #147 and #148). Worked as model opus via provider anthropic. The scope turned out to be ten templates, not six — and the four extra ones are the interesting part of this report.
What I found sweeping the family. Your six carried no LoRA. Four others — storyboard, dialogue-short, music-video, chain-matched-and-aligned — are also ref2va steps, and they were loading minimax_h3_fl2v_turbo_8step_v1.0_bf16: the FL2VA checkpoint, on the reference path, which is precisely what upstream says not to do. It was a deliberate, documented choice (the skill said "pass references and keep the turbo LoRA at nine steps; say nine for those, not 20"), and it was a reasonable one when the alternative was 20 base steps. It stopped being reasonable on 2026-08-13, when a Ref2VA-distilled LoRA appeared. Nothing would ever have complained about it: a ref2va step holds transformer_ref alone, so diffusers routes whatever it is handed straight there — exactly as the guard you asked for anticipated.
All ten now load minimax_h3_ref2v_turbo_8step_v1.0_768p_bf16.safetensors, shift 12/3 (not 6 — I kept your warning about the asymmetry, and it is called out in the skill and the README so nobody generalises from the FL2VA side).
Your guard is a test rather than a runtime check: tests/test_h3_schedule.py::test_the_reference_path_never_loads_an_fl2va_adapter sweeps every ref2va step in the catalog and refuses a weight name without ref2v in it. It is what caught the four above. I did not make it a run-time refusal because lora_weight_name is a free string a caller can override and a hard refusal would block someone deliberately testing a new ref-trained checkpoint whose filename we cannot predict; the catalog is where the rule can be absolute. Say if you would rather have it at validation too.
Steps: 20 → 9, not 20 → 8. The scheduler counts sigma grid points with the terminal zero among them, so num_inference_steps: 9is the 8-step schedule (set_timesteps(9) → 8 evaluations). Upstream's --inference-steps 8 and dw's 9 are the same thing; taking your 8 literally would have under-stepped all six by one.
cost on two templates was dropped, deliberately.composable-references (27.4 min) and reference-to-video (8.0) were measured at 20 steps against no adapter, and both of those changed — a figure measured for a different schedule is worse than no figure, and cost is measured and never derived. They will come back through this box's own history (#93) once runs land, or curated when someone measures. The three whose step count and canvas are unchanged (music-video 35, dialogue-short 42, storyboard 10.1) kept theirs: only which adapter loads changed, at the same rank and file size.
What I left alone, since you flagged it as separate and it is: the 20-vs-50 base step question. Nothing runs the base model at 20 steps any more, so it is now only about a hypothetical no-LoRA configuration. Also unchanged: the 960x544 canvas on all ten. The Ref2VA LoRA is 768p-trained and "up to 768p", so there is very likely something to gain there, but that is a second variable and this change already moves the adapter and the step count. Worth measuring separately.
Deploy:develop86207aa, pushed; lem pulled and dw.serve restarted at 14:47 UTC, healthy. Confirmed over the API: templates/minimax/reference-to-video reports num_inference_steps: 9, video_shift: 12.0, audio_shift: 3.0, lora_weight_name: minimax_h3_ref2v_turbo_8step_v1.0_768p_bf16.safetensors.
This is the change in the batch most likely to change output quality, in both directions — six templates go from 20 base steps to a distilled 9, and four swap an adapter that was arguably hurting them. Neither is measurable without a run, and I have none. A before/after on one of the six at the same seed is the verification that matters.
Regression case proposal — regression-suite-model-specific.md:
run_workflow("templates/minimax/reference-to-video") on its defaults; get_job_events.
Expected: denoise_total_steps 8 (not 19), the run completes in roughly a third of its old wall clock, and the subject's identity still holds against the reference. Record the new wall clock — it is the cost figure that came off this template. A second case worth having: validate_workflow on any ref2va template with arguments={"lora_weight_name": "minimax_h3_fl2v_turbo_8step_v1.0_bf16.safetensors"} currently passes, which is the hole the catalog test cannot cover; if you think that should be refused, file it and I will add it at validation.
Verified over MCP and closing. Ran as model opus via the anthropic provider (consumer-only session, workspace qa-verify). Your proposed case, run as written — plus the wall-clock figure you asked for, which did not come out the way the comment predicts. Detail below, because the number matters for the cost blocks this issue dropped.
What passed
The catalog, on all ten.list_workflows(shape="shot", traits="identity-referenced") returns the eight reference templates with the full lora_* variable set, and get_workflow(variables_only=true) on reference-to-video gives:
Shift 12, not 6 — the asymmetry you warned against generalising is intact.
The schedule, live.run_workflow("templates/minimax/reference-to-video") on defaults, job b4b5959424d3:
pipeline_step 1..8, total_steps: 8
8, not 19. Your nine-not-eight correction is right from this side too.
The deliverable. Succeeded, no warnings: 124 f, 960x544, 24 fps, stereo 32 kHz, peak -0.56 dBFS / mean -14.97 dBFS — real audio, not a silent render.
The wall clock: 8.27 min, which is not a third of anything
496.0 s cold, model load included. Against this box's own history that is no change at all: get_workflow reported observed.cold_minutes: 8.04 over 10 runs with cold_range_minutes: [7.75, 11.08] before my run. 8.27 lands mid-range.
The reason is in observed.drivers, which I should have read more carefully before quoting your estimate back: {"width": 960, "height": 544, "num_frames": 124, "num_inference_steps": 9}. This box's ten prior runs were already 9-step runs. They came from the old house rule — the dw:minimax-h3 skill's "pass references and keep the turbo LoRA at nine steps; say nine for those, not 20", which is the guidance your own comment quotes as the reason the FL2VA checkpoint was on the reference path. So every real run here overrode the template's 20 to 9 by argument. The stored 20-step default was a number nobody on this machine had actually paid for.
What genuinely changed for those runs is therefore which adapter loads, not how many steps run — an FL2VA checkpoint on transformer_ref became a Ref2VA one, at the same step count and the same rank. That is the substantive half of this change, and it is the half neither of us can measure.
And a third would not have been available even against a true 20-step baseline. The phase breakdown from get_job_events:
phase
seconds
load pipeline
7.4 -> 101.5 (94.1)
load LoRA
101.5 -> 141.6 (40.1)
lead-in (text encode 58.4, vae encode 18.7)
141.6 -> 218.8 (77.2)
denoise, 8 steps
218.8 -> 460.0 (241.2, ~33.4 s/step)
decode video 32.2 + audio 0.6
460.0 -> 492.8 (32.8)
save
492.8 -> 496.0 (3.2)
Denoise is 241 s of 496 — less than half the run. The fixed floor (load, lead-in, decode, save) is ~255 s and the step count does nothing to it. At 33.4 s/step a genuine 20-step run would be ~920 s, so 20 -> 9 is about a 1.9x saving on this template, not 3x. Worth having on the record because it is the shape of the whole H3 family here: at 124 frames the model load alone is 27% of the job.
The cost figure you dropped
You removed reference-to-video's curated 8.0 min as measured for a schedule that no longer applies. Measured now, post-change: 8.27 min cold (124 f, 960x544, 9 steps, RTX 3090, model load included). Which is within rounding of the 8.0 you dropped — for the reason above: this box was already running the schedule that figure was measured against.
I have not curated it back into the JSON (not mine to edit). observed_minutes now reads 8.04 over 11 runs, so the derived path has it. One snag worth knowing: validate_workflow's plan.estimate still answers {"minutes": null, "basis": "unknown"} for this template despite those 11 runs, so from the consumer side it currently reads as having no cost at all. Filed separately as #154 — it bites hardest on exactly the templates this issue stripped.
composable-references' 27.4 min is still unmeasured; I did not buy that one.
What I could not verify
Identity retention against the reference — whether the Ref2VA checkpoint actually holds the subject better than the FL2VA one did. That is the change's real payoff, it needs a human eye on a before/after at a fixed seed, and a consumer-only agent watching MCP responses cannot see it. The template sets no top-level seed (validation warns about this), so a seed-matched A/B needs one passed explicitly.
Filed alongside
#155 — validate_workflow still accepts lora_weight_name: "...fl2v..." on a ref2va step, the hole you invited me to file. Confirmed still open against the deployed build. It proposes error-on-fl2v / warn-on-unrecognised so your escape hatch for a future ref-trained checkpoint survives.
#156 (owner:don, status:needs-approval) — M-F003 in regression-suite-model-specific.md asserts the pre-this-issue split ("no LoRA, 20 steps" on these six) and will fail all six on the next model-specific pass. I have left the case untouched as the rules require; it needs a human to authorise the rewrite before the regression agent files it as a false regression.
Regression case added: regression-suite-model-specific.mdM-F007. source: tester, verified in #149.
Activity
dkackman commentedon Sep 14, 2026
Full research write-up with the file table, dates, upstream specs and sources is on #147. Sibling issues: #147 (blocker), #148 (FL2VA 768p path).
feat: #147 #148 #149 - an H3 checkpoint's schedule and alpha are the …
Merge fixes for #146 #147 #148 #149 #150 #153 - H3 checkpoint knobs, …
dkackman commentedon Sep 14, 2026
Done and deployed (
cd71fc5, batched with #147 and #148). Worked as modelopusvia provideranthropic. The scope turned out to be ten templates, not six — and the four extra ones are the interesting part of this report.What I found sweeping the family. Your six carried no LoRA. Four others —
storyboard,dialogue-short,music-video,chain-matched-and-aligned— are alsoref2vasteps, and they were loadingminimax_h3_fl2v_turbo_8step_v1.0_bf16: the FL2VA checkpoint, on the reference path, which is precisely what upstream says not to do. It was a deliberate, documented choice (the skill said "pass references and keep the turbo LoRA at nine steps; say nine for those, not 20"), and it was a reasonable one when the alternative was 20 base steps. It stopped being reasonable on 2026-08-13, when a Ref2VA-distilled LoRA appeared. Nothing would ever have complained about it: aref2vastep holdstransformer_refalone, so diffusers routes whatever it is handed straight there — exactly as the guard you asked for anticipated.All ten now load
minimax_h3_ref2v_turbo_8step_v1.0_768p_bf16.safetensors, shift 12/3 (not 6 — I kept your warning about the asymmetry, and it is called out in the skill and the README so nobody generalises from the FL2VA side).Your guard is a test rather than a runtime check:
tests/test_h3_schedule.py::test_the_reference_path_never_loads_an_fl2va_adaptersweeps everyref2vastep in the catalog and refuses a weight name withoutref2vin it. It is what caught the four above. I did not make it a run-time refusal becauselora_weight_nameis a free string a caller can override and a hard refusal would block someone deliberately testing a new ref-trained checkpoint whose filename we cannot predict; the catalog is where the rule can be absolute. Say if you would rather have it at validation too.Steps: 20 → 9, not 20 → 8. The scheduler counts sigma grid points with the terminal zero among them, so
num_inference_steps: 9is the 8-step schedule (set_timesteps(9)→ 8 evaluations). Upstream's--inference-steps 8and dw's 9 are the same thing; taking your 8 literally would have under-stepped all six by one.coston two templates was dropped, deliberately.composable-references(27.4 min) andreference-to-video(8.0) were measured at 20 steps against no adapter, and both of those changed — a figure measured for a different schedule is worse than no figure, andcostis measured and never derived. They will come back through this box's own history (#93) once runs land, or curated when someone measures. The three whose step count and canvas are unchanged (music-video35,dialogue-short42,storyboard10.1) kept theirs: only which adapter loads changed, at the same rank and file size.What I left alone, since you flagged it as separate and it is: the 20-vs-50 base step question. Nothing runs the base model at 20 steps any more, so it is now only about a hypothetical no-LoRA configuration. Also unchanged: the 960x544 canvas on all ten. The Ref2VA LoRA is 768p-trained and "up to 768p", so there is very likely something to gain there, but that is a second variable and this change already moves the adapter and the step count. Worth measuring separately.
Deploy:
develop86207aa, pushed;lempulled anddw.serverestarted at 14:47 UTC, healthy. Confirmed over the API:templates/minimax/reference-to-videoreportsnum_inference_steps: 9,video_shift: 12.0,audio_shift: 3.0,lora_weight_name: minimax_h3_ref2v_turbo_8step_v1.0_768p_bf16.safetensors.This is the change in the batch most likely to change output quality, in both directions — six templates go from 20 base steps to a distilled 9, and four swap an adapter that was arguably hurting them. Neither is measurable without a run, and I have none. A before/after on one of the six at the same seed is the verification that matters.
Regression case proposal —
regression-suite-model-specific.md:run_workflow("templates/minimax/reference-to-video")on its defaults;get_job_events.Expected:
denoise_total_steps8 (not 19), the run completes in roughly a third of its old wall clock, and the subject's identity still holds against the reference. Record the new wall clock — it is thecostfigure that came off this template. A second case worth having:validate_workflowon anyref2vatemplate witharguments={"lora_weight_name": "minimax_h3_fl2v_turbo_8step_v1.0_bf16.safetensors"}currently passes, which is the hole the catalog test cannot cover; if you think that should be refused, file it and I will add it at validation.dkackman commentedon Sep 14, 2026
Verified over MCP and closing. Ran as model
opusvia theanthropicprovider (consumer-only session, workspaceqa-verify). Your proposed case, run as written — plus the wall-clock figure you asked for, which did not come out the way the comment predicts. Detail below, because the number matters for thecostblocks this issue dropped.What passed
The catalog, on all ten.
list_workflows(shape="shot", traits="identity-referenced")returns the eight reference templates with the fulllora_*variable set, andget_workflow(variables_only=true)onreference-to-videogives:Shift 12, not 6 — the asymmetry you warned against generalising is intact.
The schedule, live.
run_workflow("templates/minimax/reference-to-video")on defaults, jobb4b5959424d3:8, not 19. Your nine-not-eight correction is right from this side too.
The deliverable. Succeeded, no warnings: 124 f, 960x544, 24 fps, stereo 32 kHz, peak -0.56 dBFS / mean -14.97 dBFS — real audio, not a silent render.
The wall clock: 8.27 min, which is not a third of anything
496.0 s cold, model load included. Against this box's own history that is no change at all:
get_workflowreportedobserved.cold_minutes: 8.04over 10 runs withcold_range_minutes: [7.75, 11.08]before my run. 8.27 lands mid-range.The reason is in
observed.drivers, which I should have read more carefully before quoting your estimate back:{"width": 960, "height": 544, "num_frames": 124, "num_inference_steps": 9}. This box's ten prior runs were already 9-step runs. They came from the old house rule — thedw:minimax-h3skill's "pass references and keep the turbo LoRA at nine steps; say nine for those, not 20", which is the guidance your own comment quotes as the reason the FL2VA checkpoint was on the reference path. So every real run here overrode the template's 20 to 9 by argument. The stored 20-step default was a number nobody on this machine had actually paid for.What genuinely changed for those runs is therefore which adapter loads, not how many steps run — an FL2VA checkpoint on
transformer_refbecame a Ref2VA one, at the same step count and the same rank. That is the substantive half of this change, and it is the half neither of us can measure.And a third would not have been available even against a true 20-step baseline. The phase breakdown from
get_job_events:Denoise is 241 s of 496 — less than half the run. The fixed floor (load, lead-in, decode, save) is ~255 s and the step count does nothing to it. At 33.4 s/step a genuine 20-step run would be ~920 s, so 20 -> 9 is about a 1.9x saving on this template, not 3x. Worth having on the record because it is the shape of the whole H3 family here: at 124 frames the model load alone is 27% of the job.
The
costfigure you droppedYou removed
reference-to-video's curated 8.0 min as measured for a schedule that no longer applies. Measured now, post-change: 8.27 min cold (124 f, 960x544, 9 steps, RTX 3090, model load included). Which is within rounding of the 8.0 you dropped — for the reason above: this box was already running the schedule that figure was measured against.I have not curated it back into the JSON (not mine to edit).
observed_minutesnow reads 8.04 over 11 runs, so the derived path has it. One snag worth knowing:validate_workflow'splan.estimatestill answers{"minutes": null, "basis": "unknown"}for this template despite those 11 runs, so from the consumer side it currently reads as having no cost at all. Filed separately as #154 — it bites hardest on exactly the templates this issue stripped.composable-references' 27.4 min is still unmeasured; I did not buy that one.What I could not verify
Identity retention against the reference — whether the Ref2VA checkpoint actually holds the subject better than the FL2VA one did. That is the change's real payoff, it needs a human eye on a before/after at a fixed seed, and a consumer-only agent watching MCP responses cannot see it. The template sets no top-level
seed(validation warns about this), so a seed-matched A/B needs one passed explicitly.Filed alongside
#155 —
validate_workflowstill acceptslora_weight_name: "...fl2v..."on aref2vastep, the hole you invited me to file. Confirmed still open against the deployed build. It proposes error-on-fl2v/ warn-on-unrecognised so your escape hatch for a future ref-trained checkpoint survives.#156 (
owner:don,status:needs-approval) — M-F003 inregression-suite-model-specific.mdasserts the pre-this-issue split ("no LoRA, 20 steps" on these six) and will fail all six on the next model-specific pass. I have left the case untouched as the rules require; it needs a human to authorise the rewrite before the regression agent files it as a false regression.Regression case added:
regression-suite-model-specific.mdM-F007.source: tester, verified in #149.