Skip to content

MOSS-Image: extra sample args to window or disable the block-22 negative-branch skip - #40

Merged
danielhanchen merged 3 commits into
masterfrom
moss-uncond-skip-window
Oct 30, 2026
Merged

danielhanchen merged 3 commits into
masterfrom
moss-uncond-skip-window

Conversation

@danielhanchen

@danielhanchen danielhanchen commented Oct 30, 2026 •

Copy link
Copy Markdown
Member

Based on master (d331c66, #34). One source change, no ggml patch.

Problem

MOSS-Image always drops transformer block 22 from the negative (unconditional) pass, on every step (moss_skip_layers = {22} for VERSION_MOSS_IMAGE in src/pipeline/diffusion_engine.cpp, from upstream's MOSS-Image support). The reference workflows for these checkpoints do it per checkpoint instead:

checkpoint reference workflow
MOSS-Image-SFT no negative-branch skip
MOSS-Image-Base block 22 while sigma-percent is in [0, 0.5], then off (shift 5: sigma >= 0.833, steps 0-12 of 25)

The existing skip-layer guidance options cannot express either: --slg-scale > 0 adds a third, skipped positive pass, and slg_uncond only skips inside its window while the MOSS code still forces block 22 outside it.

Fix

Three new --extra-sample-args keys, read in src/runtime/guidance.{h,cpp} and applied where the MOSS negative pass picks its skip layers:

key default meaning
moss_uncond_skip true false runs the negative pass with no skipped block
moss_uncond_skip_start 0 first sigma-percent (inclusive) at which block 22 is skipped
moss_uncond_skip_end 1 last sigma-percent (inclusive) at which block 22 is skipped

The window uses the schedule's own shift (--flow-shift is respected). With none of the keys set, the old code path runs unchanged. Invalid values are warned about and ignored. At each window edge the step caches (EasyCache / UCache / CacheDIT) drop their cached negative prediction and Spectrum clears its history, since both would otherwise reuse outputs computed with the other skip set. Each sampling run logs MOSS uncond skip: K of N steps, and -v logs one line per skipped step.

Studio will send moss_uncond_skip=false for SFT and moss_uncond_skip_start=0,moss_uncond_skip_end=0.5 for Base, matching the diffusers path in unslothai/unsloth#16127.

Results

MOSS-Image-Base-Q4_K_M.gguf, Linux x86_64 CPU, 256x256, 25 steps, euler. Builds use the same flags as the release job; pixels compared after decoding (the PNG metadata differs only in the build name).

case result
unmodified d331c66 rebuilt vs the pinned release master-982-0518b34-ud331c66 pixel-identical (A/A)
this branch, no new key pixel-identical to the pinned release
this branch, explicit window 0..1 pixel-identical to the default
this branch, moss_uncond_skip=false 0 of 25 negative passes skip block 22
this branch, window 0..0.5 13 of 25 (steps 0-12, sigma 1.0000 to 0.8336)
pinned release given the new keys keys ignored, pixel-identical to the same binary without them
sd-cli vs sd-server pixel-identical for the default, SFT and Base cases
EasyCache, window 0..0.5 the first negative pass after the edge is recomputed
Spectrum, no new key pixel-identical before and after the edge reset
Spectrum, window 0..0.5 history reset at step 14; prediction resumes at 16 instead of 15

The default, SFT and Base renders all differ from each other, so the new path runs.

Not proven

  • Only Linux x86_64 CPU was built and run; CUDA, Vulkan, Metal, Windows and aarch64 were not.
  • Only euler was checked. On samplers that call the model more than once per step, the summary counts model calls.

…ive-branch skip

moss_uncond_skip=false turns the built-in uncond skip off; moss_uncond_skip_start /
moss_uncond_skip_end bound it in sigma-percent of the shifted flow schedule
(ComfyUI percent_to_sigma, inclusive). Without these keys every step skips block 22
as before. Logs the number of skipped negative passes per sampling run.
@danielhanchen danielhanchen self-assigned this Oct 30, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 572baeeb78

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/pipeline/diffusion_engine.cpp Outdated
Comment on lines +2936 to +2938
} else if (version == VERSION_MOSS_IMAGE && moss_uncond_skip.enabled &&
(!moss_uncond_skip.windowed() ||
(sigma >= moss_skip_sigma_low && sigma <= moss_skip_sigma_high))) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Invalidate negative-branch caches when the skip window changes

When MOSS sampling uses EasyCache or CacheDIT and a cache hit coincides with entering or leaving the new window, the negative prediction can still come from the previous skip configuration. run_condition() calls step_cache.before_condition() before executing the model, and these caches key entries only by the condition pointer, so changing uncond_skip_layers does not invalidate the cached &uncond result. Consequently, a prediction computed without block 22 can continue to be reused outside the requested window, or vice versa, altering CFG results. Track changes to the effective skip configuration and invalidate the negative-condition cache before its next lookup.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch, this is real. The step caches key the cached prediction on the condition pointer alone, so at the window edge a reused negative pass could carry the result from the other skip set. 5c4248e tracks the effective negative-branch skip per pass and drops the cached uncond entry whenever it flips, so the first pass after the edge is recomputed. Verified with EasyCache on MOSS Base at 25 steps: steps 3 to 13 reuse the cached uncond, step 14 recomputes it even though EasyCache reuses that step, and the default path without the new keys is still pixel-identical to the current prebuilt. Studio never enables an sd.cpp step cache, so this only matters when someone passes --cache-mode by hand.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 30, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-30T16:10:49.992188Z 892e800 Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

…p set changes

EasyCache / UCache / CacheDIT key a condition's cached output by its pointer only, so at
the moss_uncond_skip window edge a reused &uncond diff could come from the other skip
configuration. Track the effective negative-branch skip per pass and invalidate &uncond in
the step cache when it flips. Only runs with a window set; the default path is unchanged.
Verbose logs say whether each windowed MOSS uncond pass was computed or served from cache.
@danielhanchen

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5c4248e21b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/pipeline/diffusion_engine.cpp Resolved
@danielhanchen

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. 🎉

Reviewed commit: 892e8005f2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@danielhanchen
danielhanchen merged commit aba3a1c into master Oct 30, 2026
8 checks passed
meefs pushed a commit to meefs/unsloth that referenced this pull request Oct 31, 2026
…ch skip (unslothai#16255)

## Summary

unslothai#16127 made the diffusers MOSS-Image path skip transformer block 22 on
the negative pass per checkpoint, as the reference workflows do: never
for MOSS-Image-SFT, and only while sigma-percent is in [0, 0.5] for
MOSS-Image-Base. The GGUF path runs stable-diffusion.cpp, which still
skips block 22 on every step for both checkpoints.

unslothai/stable-diffusion.cpp#40 added sample args that express the
per-checkpoint rule. This sends them from Studio and pins the prebuilt
that reads them.

The pinned release, `master-982-0518b34-uaba3a1c`, is published on
unslothai/stable-diffusion.cpp; the 7 asset names
`test_sd_cpp_vulkan_cpu_torch.py` lists are all in it.

## Change

- `sd_cpp_args.moss_uncond_skip_sample_args`: `moss_uncond_skip=false`
for SFT, `moss_uncond_skip_start=0,moss_uncond_skip_end=0.5` for Base.
Base is detected from the repo id, folder or GGUF filename (separators
folded). `UNSLOTH_MOSS_REFERENCE_SKIP=0` sends nothing, which is the
binary's every-step default.
- `sd_cpp_backend`: MOSS-Image requests carry it, as
`sample_params.extra_sample_args` on the server path and
`--extra-sample-args` on the CLI path. Other families send nothing.
- `install_sd_cpp_prebuilt.DEFAULT_TAG`: `master-982-0518b34-ud331c66`
-> `master-982-0518b34-uaba3a1c`. Same upstream base (master-982); the
new build adds only unslothai#40. The tests that name the pin are updated.

A build without the keys ignores them, so an older install keeps today's
behaviour until it updates.

## Results

`MOSS-Image-Base-Q4_K_M.gguf`, Linux x86_64 CPU, 256x256, 25 steps,
`euler`, the release's own `sd-cli`:

| case | negative passes that skip block 22 |
|---|---|
| new pin, no keys | 25 of 25; PNG byte-identical to the current pin |
| new pin, SFT (`moss_uncond_skip=false`) | 0 of 25 |
| new pin, Base (window `0..0.5`) | 13 of 25 (steps 1-13) |
| current pin given the keys | keys ignored; identical to the same
binary without them |

The server path, driven through this branch's `build_img_gen_request`
and `SdCppServer`, gives the same counts: 25, 0 and 13 of 25.

## Tests

- `test_sd_cpp_moss_uncond_skip.py` (new): Base / SFT detection across
repo ids, folders and GGUF names, the env kill switch, the server
request field, the CLI flag, and that other families send nothing.
- `test_sd_cpp_moss_uncond_skip.py`, `test_sd_cpp_args.py`,
`test_sd_cpp_install_verify.py`, `test_sd_cpp_vulkan_cpu_torch.py`,
`test_diffusion_more_families.py`: 310 passed.

## Not proven

- Only the Linux x86_64 CPU bundle was run. The CUDA, Vulkan, Metal,
Windows and aarch64 bundles were built by the release job but not
rendered.
- The MOSS-Image-SFT GGUF was not rendered on the GGUF path; its 0-of-25
count comes from the Base GGUF given the SFT keys.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant