Test-time search at 63% of the cost: explore every candidate under caching, commit only the winner at full compute.
Paper (arXiv, coming soon) · Project page · Blog
- Ranking survives caching: median Spearman rho is 0.905, with 72% top-1 agreement on VBench.
- Ranking failures are self-limiting because they concentrate where candidates are nearly tied.
- Explore cheap plus commit full retains 94.7% of the best-of-8 gain at 63% of the cost.
- CachedSearch works with any published cache engine and transfers across six models in four families.
Generate every candidate with a training-free cache enabled.
Score the cached drafts with the verifier used by the search procedure.
Select the seed with the highest draft score.
Regenerate only that seed at full compute.
Return the full-compute video, so caching affects selection but not delivery quality.
drafts = [cached_generate(prompt, seed) for seed in seeds]
winner = seeds[argmax(verifier(video, prompt) for video in drafts)]
return full_generate(prompt, winner)
What search buys. "Robot dancing in Times Square": an unlucky seed on the left, the seed CachedSearch selected on the right. The unlucky sample misses the scene entirely. Both are delivered at full compute, so search only chooses between them. This is a selected example; the aggregate effect is in the capture and regret numbers.
Why the ranking survives. The same seed at full compute and under caching. The cached draft is roughly twice as cheap and is what the verifier ranks; the content it ranks on is preserved.
The honest edge. At an aggressive threshold, keeping the cached draft instead of recommitting dampens motion. This is why commit is the default.
These are the backbones we measured. The recommended threshold is the most aggressive setting that still keeps at least 85% of search's gain, taken from the calibration sweep; capture and speedup are reported at that setting.
| Model | Params | Family | Recommended tau |
Gain capture | Exploration speedup |
|---|---|---|---|---|---|
| Wan2.1-T2V-1.3B | 1.3B | Wan | 0.20 | 88.3% | 2.41x |
| Wan2.1-T2V-14B | 14B | Wan | 0.10 | 87.5% | 2.05x |
| Wan2.2-TI2V-5B | 5B | Wan | 0.10 | 86.0% | 2.05x |
| CogVideoX-5B | 5B | CogVideoX | 0.05 | 85.9% | 1.78x |
| HunyuanVideo | 13B | HunyuanVideo | 0.05 | 85.1% | 1.77x |
| LTX-Video | 2B | LTX | 0.02 | 79.6% | 1.71x |
CachedSearch is not limited to these models. It is a training-free wrapper around generation, so it applies to any diffusion or flow-matching video model whose sampler is deterministic in the seed, which covers essentially every current open text-to-video pipeline. These six are simply the ones where we measured the numbers ourselves, across four architecture families and a 1.3B to 14B size range.
For a model that is not listed, run the calibration script once
(examples/calibrate_new_model.py, about
two GPU-hours) and use the threshold it recommends. Fidelity tracks
architecture family rather than parameter count, so a threshold calibrated on
one member of a family transfers to its other sizes: Wan2.1-14B behaves like
Wan2.1-1.3B, while off-family ports need their own value. LTX-Video is the
honest boundary case in our set. No threshold we measured reached 85% capture,
which is exactly the situation the calibration is meant to reveal before you
deploy rather than after.
CachedSearch is a wrapper around generation, not a new model. If you already run best-of-N search (or you generate a few candidates and pick one by hand), you can adopt it in three steps.
1. Install and import.
pip install -r requirements.txtfrom cachedsearch import cached_search2. Replace your search loop. Wherever you generate N candidates and keep
the best, call cached_search instead. It takes any diffusers video pipeline.
The verifier defaults to ImageReward averaged over 8 frames, the scorer behind
every number in the paper; pass verifier=your_scorer (any callable taking
frames and a prompt and returning a float, higher is better) to use your own.
result = cached_search(
pipe, # your diffusers video pipeline
"a red fox running through deep snow",
n=8, # search width
tau=0.10, # caching threshold (see step 3 for other models)
mode="commit", # regenerate the winner at full compute
) # verifier defaults to ImageReward
result.video # delivered video: a genuine full-compute sample
result.seed # the seed that won
result.total_seconds # about 63% of what full best-of-8 costsInternally this generates all N candidates with caching on, scores the cheap drafts, then regenerates only the winning seed with caching off. Because the sampler is seed-deterministic, the delivered video is bit-identical to what full-compute search would have returned whenever both pick the same seed: caching changes which candidate you select, never the quality of what ships.
A runnable end-to-end script is in examples/run_wan.py.
3. Calibrate tau if your model is not Wan. The threshold is the one
model-specific number. Fidelity tracks architecture family rather than
parameter count, so calibrate once per family and reuse it across sizes.
python examples/calibrate_new_model.py --model <hf-id> --prompts your_prompts.txtThis runs the paper's protocol in miniature (25 prompts, both compute levels) in roughly two GPU-hours and prints the largest threshold that still retains 90% of search's gain. Starting points we measured: Wan family 0.10, CogVideoX 0.05, HunyuanVideo 0.05, LTX-Video 0.02. Do not copy a threshold across families; an over-driven threshold silently degrades selection.
| Situation | Setting |
|---|---|
| Default, quality matters | mode="commit", tau=0.10 (Wan) |
| Fidelity first, some speed given up | swap in a milder engine (TeaCache) or lower tau |
| Maximum savings, motion not critical | mode="keep" at tau<=0.10; expect mild motion dampening |
| Fixed budget, want more quality | keep the budget, raise n: capture rises with width |
| New architecture | calibrate first, never copy constants |
Yes. CachedSearch only changes how exploration rollouts are computed, so it sits underneath the rest of the stack: any published training-free cache works as the engine (we measured PAB, CFG-Cache, TeaCache, and EasyCache on one frontier), any verifier works, and pruning-based search composes multiplicatively (we measured 3.11x exploration speedup when stacked with mid-trajectory pruning).
Each row uses the listed cache as the exploration engine at search width 8. Cost includes the full-compute commit.
| Exploration engine | Gain capture | Cost |
|---|---|---|
| No caching | 100.0% | 621 s |
| PAB | 99.5% | 493 s |
| FasterCache CFG-Cache | 99.6% | 465 s |
| TeaCache | 93.2% | 365 s |
| EasyCache | 90.1% | 346 s |
At similar exploration cost, caching retains 90.1% of search gain, while 25-step truncation retains 72.6%.
# one experiment arm (your prompt list x 8 seeds, full and cached rollouts)
python code/experiments/b1_gate.py --prompts your_prompts.txt \
--variants full,cached --tau 0.10 --tag v0
# regenerate every figure from the score records
python code/paper_figs/make_figs.py
python code/paper_figs/make_fig_hero.pyGeneration needs a CUDA GPU with enough memory for your backbone (we used
NVIDIA GH200). Set CACHEDSEARCH_RESULTS to choose where records are written.
cachedsearch/ the drop-in API (cached_search, calibrate_tau)
examples/ runnable scripts: search on Wan, calibrate a new model
code/videogen1/ caching wrapper and generation helpers
code/experiments/ experiment runners used for the paper
code/paper_figs/ figure and table generation from score records
results/ per-candidate score records (added on release)
assets/ logo and figures
We sincerely thank the authors and open-source teams whose models, acceleration methods, evaluators, and benchmarks made this work possible: Wan2.1, CogVideoX, HunyuanVideo, LTX-Video, TeaCache, PAB and VideoSys, FasterCache, EasyCache, ImageReward, VideoScore, and VBench. Their public releases made it possible to study cached exploration across a broad and reproducible video generation ecosystem.
@article{saini2026cachedsearch,
title = {CachedSearch: Training-Free Cached Exploration for Test-Time Search in Video Diffusion},
author = {Saini, Shreshth and Birkbeck, Neil and Wang, Yilin and Adsumilli, Balu and Bovik, Alan C.},
year = {2026},
note = {arXiv id TBD}
}The code and release materials are available under the MIT License.





