fix: align Qwen Image 2.1 flow schedule with official defaults (#2048)

This commit is contained in:
leejet 2026-09-25 02:43:10 +08:00 committed by GitHub
parent 1a2330de68
commit b167b942f7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -728,12 +728,20 @@ inline float flux_time_shift(float mu, float sigma, float t) {
// https://github.com/black-forest-labs/flux/blob/main/src/flux/sampling.py#L289 // https://github.com/black-forest-labs/flux/blob/main/src/flux/sampling.py#L289
struct FluxScheduler : SigmaScheduler { struct FluxScheduler : SigmaScheduler {
int image_seq_len = 0; int image_seq_len = 0;
float base_shift = 0.5f; int base_image_seq_len = 256;
float max_shift = 1.15f; int max_image_seq_len = 4096;
float base_shift = 0.5f;
float max_shift = 1.15f;
float shift_terminal = 0.0f;
explicit FluxScheduler(int image_seq_len, const char* extra_sample_args = nullptr) FluxScheduler(int image_seq_len, SDVersion version, const char* extra_sample_args = nullptr)
: image_seq_len(image_seq_len) { : image_seq_len(image_seq_len) {
if (version == VERSION_QWEN_IMAGE_2_1) {
max_image_seq_len = 8192;
max_shift = 0.9f;
shift_terminal = 0.02f;
}
parse_extra_sample_args(extra_sample_args); parse_extra_sample_args(extra_sample_args);
} }
@ -752,10 +760,8 @@ struct FluxScheduler : SigmaScheduler {
} }
float compute_mu() const { float compute_mu() const {
constexpr float base_shift_anchor = 256.0f; float m = (max_shift - base_shift) / static_cast<float>(max_image_seq_len - base_image_seq_len);
constexpr float max_shift_anchor = 4096.0f; float b = base_shift - m * static_cast<float>(base_image_seq_len);
float m = (max_shift - base_shift) / (max_shift_anchor - base_shift_anchor);
float b = base_shift - m * base_shift_anchor;
return static_cast<float>(image_seq_len) * m + b; return static_cast<float>(image_seq_len) * m + b;
} }
@ -764,7 +770,7 @@ struct FluxScheduler : SigmaScheduler {
sigmas.reserve(n + 1); sigmas.reserve(n + 1);
float mu = compute_mu(); float mu = compute_mu();
LOG_VERBOSE("Flux scheduler: image_seq_len=%d, steps=%u, mu=%.3f", image_seq_len, n, mu); LOG_VERBOSE("Flux scheduler: image_seq_len=%d, steps=%u, mu=%.3f, shift_terminal=%.3f", image_seq_len, n, mu, shift_terminal);
if (n == 0) { if (n == 0) {
sigmas.push_back(1.0f); sigmas.push_back(1.0f);
@ -780,6 +786,16 @@ struct FluxScheduler : SigmaScheduler {
} }
} }
if (shift_terminal > 0.0f && n > 1) {
// The terminal shift applies to the last model evaluation, not the final zero sigma.
float scale_factor = (1.0f - sigmas[n - 1]) / (1.0f - shift_terminal);
if (std::isfinite(scale_factor) && scale_factor > 0.0f) {
for (uint32_t i = 0; i < n; ++i) {
sigmas[i] = 1.0f - (1.0f - sigmas[i]) / scale_factor;
}
}
}
sigmas[n] = 0.0f; sigmas[n] = 0.0f;
return sigmas; return sigmas;
} }
@ -1178,7 +1194,7 @@ struct Denoiser {
} }
case FLUX_SCHEDULER: { case FLUX_SCHEDULER: {
LOG_INFO("get_sigmas with Flux scheduler"); LOG_INFO("get_sigmas with Flux scheduler");
scheduler = std::make_shared<FluxScheduler>(image_seq_len, extra_sample_args); scheduler = std::make_shared<FluxScheduler>(image_seq_len, version, extra_sample_args);
break; break;
} }
default: default: