Enhance: generate 32-bit seeds

SeedVR2VideoUpscaler (the new Sharpen / Rescue templates) rejects seeds
above 2^32 - 1 at validation, and the 52-bit seeds made every job fail with
"Value ... bigger than max of 4294967295: seed". 32 bits is still plenty of
variety for the Fibo templates.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Cameron CordesandClaude Opus 5.5 committed 2026-11-01 18:24:36 -05:00
1 parent ce101a3b2c
commit 096ddfe24e
2 files changed
+20 -5

No files matched your search

+2 -4
View File
@@ -16,7 +16,7 @@ use serde::{Deserialize, Serialize};
use super::comfy::{ApproveError, ComfyClient, ComfyError, HistoryEntry, Staged, SubmitError}; use super::comfy::{ApproveError, ComfyClient, ComfyError, HistoryEntry, Staged, SubmitError};
use super::config::{EnhanceConfig, Loaded, PromptMode}; use super::config::{EnhanceConfig, Loaded, PromptMode};
use super::path_map::PathMap; use super::path_map::PathMap;
use super::template::Template; use super::template::{Template, random_seed};
use crate::database::enhance_dao::{ use crate::database::enhance_dao::{
EnhanceJobDao, EnhanceJobRow, JobUpdate, RecentPrompt, STATUS_APPROVED, STATUS_EXPIRED, EnhanceJobDao, EnhanceJobRow, JobUpdate, RecentPrompt, STATUS_APPROVED, STATUS_EXPIRED,
STATUS_FAILED, STATUS_QUEUED, STATUS_READY, STATUS_RUNNING, STATUS_UNAVAILABLE, STATUS_FAILED, STATUS_QUEUED, STATUS_READY, STATUS_RUNNING, STATUS_UNAVAILABLE,
@@ -314,9 +314,7 @@ impl EnhanceService {
None => None, None => None,
}; };
let filled = template let filled = template
.fill(&source, prompt, reference_path.as_deref(), &mut || { .fill(&source, prompt, reference_path.as_deref(), &mut random_seed)
rand::random::<u64>() >> 12
})
.map_err(|e| EnhanceError::BadRequest(e.0))?; .map_err(|e| EnhanceError::BadRequest(e.0))?;
if !self.probe_now().await { if !self.probe_now().await {
+18 -1
View File
@@ -285,6 +285,13 @@ fn links_to(v: &Value, id: &str) -> bool {
matches!(v.as_array().map(Vec::as_slice), Some([Value::String(s), Value::Number(_)]) if s == id) matches!(v.as_array().map(Vec::as_slice), Some([Value::String(s), Value::Number(_)]) if s == id)
} }
/// A fresh seed for one job. 32 bits: some nodes cap their seed there
/// (SeedVR2VideoUpscaler's max is 2^32 - 1), and it's plenty of variety for
/// the ones that take 64.
pub fn random_seed() -> u64 {
u64::from(rand::random::<u32>())
}
fn is_seed_input(key: &str) -> bool { fn is_seed_input(key: &str) -> bool {
key == "seed" || key == "noise_seed" || key.ends_with(".seed") key == "seed" || key == "noise_seed" || key.ends_with(".seed")
} }
@@ -401,12 +408,22 @@ mod tests {
assert!(a > 1000 && b > 1000 && a != b); assert!(a > 1000 && b > 1000 && a != b);
assert_ne!(a, 774744764437710); assert_ne!(a, 774744764437710);
// Two fills with a real RNG differ. // Two fills with a real RNG differ.
let mut rng = || rand::random::<u64>() >> 12; let mut rng = random_seed;
let x = t.fill("p", None, None, &mut rng).unwrap(); let x = t.fill("p", None, None, &mut rng).unwrap();
let y = t.fill("p", None, None, &mut rng).unwrap(); let y = t.fill("p", None, None, &mut rng).unwrap();
assert_ne!(input(&x.prompt, "5", "seed"), input(&y.prompt, "5", "seed")); assert_ne!(input(&x.prompt, "5", "seed"), input(&y.prompt, "5", "seed"));
} }
#[test]
fn random_seeds_fit_seedvr2s_u32_limit() {
// SeedVR2VideoUpscaler rejects seeds above 2^32 - 1 at validation.
let t = load(RESTORE, PromptMode::Append).unwrap();
for _ in 0..200 {
let f = t.fill("p", None, None, &mut random_seed).unwrap();
assert!(input(&f.prompt, "5", "seed").as_u64().unwrap() <= u64::from(u32::MAX));
}
}
#[test] #[test]
fn force_approval_even_if_the_export_had_it_off() { fn force_approval_even_if_the_export_had_it_off() {
let off = RESTORE.replace("\"require_approval\": true", "\"require_approval\": false"); let off = RESTORE.replace("\"require_approval\": true", "\"require_approval\": false");