unsloth/tests
Daniel Han 07272b9278
Experimental: correct varlen sample packing for hybrid linear-attention models (#7249)
* Fix text-only VLM CPT packing truncation

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* Handle streaming vision datasets in packing

* Harden multimodal packing detection

* Preserve safe packing boundaries

* Scope stream packing checks to VLMs

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* Narrow VLM packing detection

* Align packing mode and eval safety

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* Add qwen3_5/qwen3_next to PADDING_FREE_BLOCKLIST to avoid packed-sequence contamination

* Detect hybrid linear-attention models structurally instead of by name for packing guard

* Add experimental varlen packing for hybrid linear-attention models

Feed seq_idx to the causal conv and cu_seqlens to the gated-delta scan so
sample packing / padding-free reset state at sequence boundaries for hybrid
linear-attention models (Qwen3.5, Qwen3-Next). Gated behind
UNSLOTH_EXPERIMENTAL_HYBRID_PACKING and fail-closed: when the flag is off or
the accelerated kernels (causal_conv1d + fla) are unavailable, the guard keeps
these models on the padded path.

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* Harden hybrid linear-attention varlen packing shim

Make patch_hybrid_linear_attention_varlen robust across transformers 4.57.6
through 5.x and TRL 0.22.2 through 1.x, following the import_fixes.py style:

- Read UNSLOTH_EXPERIMENTAL_HYBRID_PACKING at call time so the flag takes effect
  when set after importing unsloth.
- Idempotent: repeat calls on a patched model return True without re-validating
  the wrappers or double-wrapping; signatures are checked on captured originals.
- Prefer the authoritative packed_seq_lengths (via get_packed_info_from_kwargs)
  over position_ids resets, handling pad_to_multiple_of trailing tokens.
- Suppress injection for cached forwards (use_cache / past_key_values) so
  generation and eval are left on the untouched decode path.
- Validate every gated-delta module before mutating any (transactional).
- Bind position_ids / use_cache from both positional and keyword args.
- Verify dispatch at runtime (Unsloth wraps each module forward, so the mixer
  source is not statically inspectable) and warn once if the shim is never hit.
- Emit one deduped diagnostic on each fail-closed path.

Add CPU unit tests covering the hybrid guard detection, the boundary builders,
and the shim (fail-closed, active, idempotent, cached no-op, runtime handshake).

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* Abort hybrid packing when the varlen shim is not fully dispatched

The runtime handshake used a single per-module hit flag written by both the conv
and scan wrappers, so a partial dispatch (only one kernel routed through
self.<kernel>) passed the any() check and trained on contaminated data, and a
missing dispatch only logged a warning. Track conv and scan dispatch separately,
require both on every gated-delta module on the first packed forward, and raise
before loss/backward when either is missing (the batch is already flattened, so
there is no padded recovery at that point). Also skip an empty packed_seq_lengths
before it reaches max(), and document the position_ids fallback's left-pad
assumption.

Add tests for no-dispatch and partial (conv-only / scan-only) abort, the
packed_seq_lengths preference over a competing position_ids, MRoPE 3D position
ids, and the pad_to_multiple_of trailing-segment path through the metadata builder.

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* Import the hybrid packing patch from its submodule to satisfy the import-hoist lint

* Fail closed for hybrid packing on encoder-decoder, chunked-loss, and string-name models

The varlen shim only helps decoder-only hybrid models that run their mixer
through self.<kernel> on a live nn.Module forward. Three cases slipped past
the guard:

- Encoder-decoder configs (is_encoder_decoder) reached the packing path even
  though flattening a cross-attention batch is unsound. Block them explicitly.
- TRL's chunked_nll loss (the 1.x default) calls the backbone directly and
  bypasses model.forward, so the per-instance forward wrapper that refreshes
  the varlen stash never runs. Detect that path and keep the model padded.
- A string model_name reaches the trainer before the module exists, so the
  instance shim has nothing to patch. Resolve the config up front and keep
  string hybrids on the padded path.

Adds encoder-decoder / decoder-only / chunked-loss / string-model tests.

* Harden the SFT source-injection replacements and forward auth args for string models

The wrapped-packing injection rewrote the sourced unsloth_zoo sft_prepare_dataset
with str.replace anchored on the exact 'All Unsloth Zoo code licensed under
LGPLv3' comment. str.replace never raises on a missing anchor, so a supported
newer unsloth_zoo (the dependency is only lower-bounded) that moved that header
would silently drop the setup while the truncation and pack_dataset edits still
referenced _unsloth_wrapped_packing / _inspect, raising NameError on every SFT
dataset preparation.

- Install the setup at the sft_prepare_dataset signature via re.subn (a structural
  anchor that always exists) and raise if even that is missing.
- Route the remaining edits through a _require_replace helper that fails loudly on a
  missing required anchor (or warns once for an optional one), formalizing the
  verify-then-replace idiom the DPO patchers in this file already use.
- Reuse the guarded _unsloth_pack_has_strategy at the pack_dataset call instead of
  re-calling inspect.signature(pack_dataset) unguarded, so a non-introspectable
  pack_dataset cannot crash there after the setup already handled it.
- _resolve_string_model_config now forwards token / use_auth_token / cache_dir /
  code_revision, so a private hybrid resolves its config instead of falling through
  as non-hybrid and enabling packing without the varlen shim.

Adds regression tests for the drift-resistant injection, the helper, and the
string-model auth forwarding.

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* Honor top-level SFTConfig.trust_remote_code when resolving a string model

TRL merges the top-level args.trust_remote_code into the load via
model_init_kwargs.setdefault("trust_remote_code", args.trust_remote_code) before
create_model_from_path, so a remote-code hybrid is commonly set with
SFTConfig(trust_remote_code=True) rather than inside model_init_kwargs. The config
probe only read model_init_kwargs, so AutoConfig could fail for such a model, leave
model_config None, and let the guard treat it as non-hybrid, enabling packing
without the varlen shim. Mirror TRL's setdefault (model_init_kwargs wins).

* Tighten hybrid-packing comments for concision

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

---------

Co-authored-by: alkinun <alkinunl@gmail.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Etherl <61019402+Etherll@users.noreply.github.com>
2026-07-20 00:57:02 -07:00
..
notebooks Reduce and tighten comments and docstrings across the test suite (#6429) 2026-06-18 01:07:09 -07:00
python fix(chat_templates): bind loop_messages when default_system_message is None (#7199) 2026-07-19 06:33:48 -07:00
qlora Formatting: ruff line-length 100, kwarg-spacing passes, drop blank after short local imports (#6079) 2026-06-08 04:24:13 -07:00
saving Replace standalone Studio wording with Unsloth (#7221) 2026-07-19 00:47:04 -07:00
security Harden desktop release token permissions (#7172) 2026-07-16 05:01:48 -07:00
sh Installer: preserve the previous torch release across every flavor and vendor on re-runs (#7250) 2026-07-19 07:55:06 -07:00
studio feat(studio): add UNSLOTH_LLAMA_CPP_BACKEND env var to force CPU fallback #7213 (#7228) 2026-07-20 00:33:56 -07:00
studio_setup_ps1 Make Visual Studio + CMake optional on Windows (prebuilt llama.cpp needs no build tools) (#6499) 2026-06-22 01:11:09 -07:00
utils Experimental: correct varlen sample packing for hybrid linear-attention models (#7249) 2026-07-20 00:57:02 -07:00
version_compat test(version-compat): keep GRPO fake-run logits finite on CPU (#7247) 2026-07-19 04:54:17 -07:00
vllm_compat Reduce and tighten comments and docstrings across the test suite (#6429) 2026-06-18 01:07:09 -07:00
__init__.py Qwen 3, Bug Fixes (#2445) 2025-04-30 22:38:39 -07:00
_zoo_aggressive_cuda_spoof.py Reduce and tighten comments and docstrings across the test suite (#6429) 2026-06-18 01:07:09 -07:00
_zoo_rocm_spoof.py Add RDNA 2/3/4 ROCm routing tests via a CPU-only torch spoof (#6935) 2026-07-07 04:41:37 -07:00
conftest.py Reduce and tighten comments and docstrings across the test suite (#6429) 2026-06-18 01:07:09 -07:00
run_all.sh Installer: make UV_OVERRIDE space-safe on Apple Silicon (#6503) (#6639) 2026-06-24 17:34:18 -07:00
test_attention_implementation.py fix(gpt-oss): prefer flex attention over sdpa (#5701) 2026-05-22 08:38:38 -07:00
test_attn_impl_honor_explicit.py Honor an explicit sdpa or flex_attention request when flash is disabled (#6847) 2026-07-06 05:45:45 -07:00
test_bad_mappings_redirect.py Fix BAD_MAPPINGS not redirecting the -unsloth-bnb-4bit dynamic quants (#6949) 2026-07-08 17:37:44 -03:00
test_callback_signature_drift.py Reduce and tighten comments and docstrings across the test suite (#6429) 2026-06-18 01:07:09 -07:00
test_cli_export_unpacking.py Reduce and tighten comments and docstrings across the test suite (#6429) 2026-06-18 01:07:09 -07:00
test_enforce_kwargs_spacing.py Reduce and tighten comments and docstrings across the test suite (#6429) 2026-06-18 01:07:09 -07:00
test_fast_gemv_dispatch.py Fix fast inference crash on compressed-tensors FP8 models (#7025) 2026-07-09 04:10:59 -07:00
test_fast_generate_slow_guard.py fast_generate: clear error for vLLM-style inputs when fast_inference=False (#6786) 2026-07-03 08:16:32 -07:00
test_finetune_last_n_layers.py Reduce and tighten comments and docstrings across the test suite (#6429) 2026-06-18 01:07:09 -07:00
test_fp8_device_context.py Guard FP8 Triton launches with tensor device context (#6888) 2026-07-08 18:32:51 -03:00
test_fp8_restore_dropped_scale.py Restore dropped FP8 weight_scale_inv tensors on load (#6978) 2026-07-09 06:44:44 -07:00
test_fp8_tiny_e8m0.py Handle odd shapes and non-float scales in FP8BlockQuantLinear (#6848) 2026-07-06 05:44:55 -07:00
test_fused_ce_not_return_dict_logits.py fix: use EMPTY_LOGITS on the fused-CE not-return_dict path (#2068) (#6482) 2026-06-23 01:26:55 -07:00
test_gemma4_chat_template.py Reduce and tighten comments and docstrings across the test suite (#6429) 2026-06-18 01:07:09 -07:00
test_gemma_2b_mapper_key.py Fix duplicate unsloth/gemma-2b-bnb-4bit mapper key routing the base 4bit repo to the instruct model (#6891) 2026-07-08 17:40:39 -03:00
test_generate_kwarg_gate.py Fix gpt-oss offload_embedding and generate() kwargs, and guard offload_embedding on tied/vLLM models (#6774) 2026-07-01 22:39:00 -07:00
test_get_model_name.py Fix DeepScaleR-1.5B mapper entry pointing its 16bit repo at DeepHermes-3-8B (#7088) 2026-07-14 17:56:12 -03:00
test_gradient_checkpointing_restore.py Fix TrainingArguments silently disabling unsloth gradient checkpointing (#6829) 2026-07-03 16:35:02 +01:00
test_ignored_tokenizer_casing.py Match IGNORED_TOKENIZER_NAMES case-insensitively (#6620) 2026-06-23 19:40:50 -03:00
test_import_fixes_drift.py fix: keep LoRA reloads working with PEFT 0.19 (#6748) 2026-06-30 20:26:57 +01:00
test_installer_skip_autostart.py fix(install): fail non-tauri installer errors (#7123) 2026-07-15 04:37:03 -07:00
test_loader_glob_skip.py Reduce and tighten comments and docstrings across the test suite (#6429) 2026-06-18 01:07:09 -07:00
test_missing_torchvision_vlm.py Fix misleading 'only for image models' error for Qwen3-VL when torchvision is missing (#6525) 2026-06-23 01:28:09 -07:00
test_model_registry.py fix(registry): don't register deepseek models at import time (#7227) 2026-07-19 03:37:23 -07:00
test_moe_lora_targets.py Scope MoE expert LoRA detection to actual MLP projection targets (#6849) 2026-07-06 05:45:06 -07:00
test_multi_image_grpo_chunking.py Reduce and tighten comments and docstrings across the test suite (#6429) 2026-06-18 01:07:09 -07:00
test_nvfp4_quant_load.py Reduce and tighten comments and docstrings across the test suite (#6429) 2026-06-18 01:07:09 -07:00
test_offline_loading_helpers.py Fix offline checkpoint load/export: "tokenizer is weirdly not loaded" (#6554) 2026-06-25 23:16:53 -07:00
test_offload_embedding_hooks.py Fix gpt-oss offload_embedding and generate() kwargs, and guard offload_embedding on tied/vLLM models (#6774) 2026-07-01 22:39:00 -07:00
test_offload_tied_guard.py Fix gpt-oss offload_embedding and generate() kwargs, and guard offload_embedding on tied/vLLM models (#6774) 2026-07-01 22:39:00 -07:00
test_peft_tensor_parallel_compat.py fix: keep LoRA reloads working with PEFT 0.19 (#6748) 2026-06-30 20:26:57 +01:00
test_peft_weight_converter_compat.py Formatting: ruff line-length 100, kwarg-spacing passes, drop blank after short local imports (#6079) 2026-06-08 04:24:13 -07:00
test_prefetch_snapshot_scope.py Auto Xet to HTTP download fallback in from_pretrained; share Studio's fallback via unsloth_zoo (#6638) 2026-07-06 05:13:25 -07:00
test_pretrain_compile_reset.py Add regression tests for the stray-forward compile-cache reset (#6569) 2026-06-22 07:22:47 -07:00
test_public_api_surface.py Reduce and tighten comments and docstrings across the test suite (#6429) 2026-06-18 01:07:09 -07:00
test_raw_text.py fix(dataprep): skip .jsonl lines that are valid JSON but not objects (#7195) 2026-07-18 05:54:50 -07:00
test_resolve_model_class.py Formatting: ruff line-length 100, kwarg-spacing passes, drop blank after short local imports (#6079) 2026-06-08 04:24:13 -07:00
test_studio_install_workspace_guard.py Replace standalone Studio wording with Unsloth (#7221) 2026-07-19 00:47:04 -07:00
test_studio_root_resilience.py Replace standalone Studio wording with Unsloth (#7221) 2026-07-19 00:47:04 -07:00
test_studio_shutdown_thread_wait.py Replace standalone Studio wording with Unsloth (#7221) 2026-07-19 00:47:04 -07:00
test_synthetic_chunk_data.py Fix SyntheticDataKit.chunk_data emitting chunks over max_tokens (#7073) 2026-07-12 05:06:11 -07:00
test_tool_mask_zoo_compat.py Formatting: ruff line-length 100, kwarg-spacing passes, drop blank after short local imports (#6079) 2026-06-08 04:24:13 -07:00
test_uninitialized_position_ids.py Load DeepSeek-OCR and other VLMs that register AutoModel in auto_map (#6421) 2026-06-18 07:03:43 -07:00
test_video_path_validation.py Reduce and tighten comments and docstrings across the test suite (#6429) 2026-06-18 01:07:09 -07:00
test_vllm_broken_detection.py Fix fast_inference crash on ABI-broken vLLM: probe compiled extensions, not just import vllm (#6621) 2026-06-26 22:43:36 -07:00
test_windows_rocm_bnb_version.py Reduce and tighten comments and docstrings across the test suite (#6429) 2026-06-18 01:07:09 -07:00