-
Notifications
You must be signed in to change notification settings - Fork 2.8k
feat(z-image): add Seed Variance Enhancer node and Linear UI integration #8753
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Pfannkuchensack
merged 10 commits into
invoke-ai:main
from
Pfannkuchensack:feature/z-image-seed-variance-enhancer
Jan 12, 2026
Merged
Changes from 6 commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
27ffefc
feat(z-image): add Seed Variance Enhancer node and Linear UI integration
Pfannkuchensack 2174ac0
Merge branch 'main' into feature/z-image-seed-variance-enhancer
Pfannkuchensack 3efd7b2
chore: ruff and typegen fix
Pfannkuchensack d49524d
chore: ruff and typegen fix
Pfannkuchensack c17f2b0
Revise seedVarianceStrength explanation
Pfannkuchensack 9d768dd
Merge branch 'main' into feature/z-image-seed-variance-enhancer
Pfannkuchensack 2fb02b4
Update description for seedVarianceStrength
Pfannkuchensack f85bbc4
Merge branch 'main' into feature/z-image-seed-variance-enhancer
Pfannkuchensack 5c8d03e
fix(z-image): correct noise range comment from [-1, 1] to [-1, 1)
Pfannkuchensack 1500f09
Merge branch 'feature/z-image-seed-variance-enhancer' of https://gith…
Pfannkuchensack File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
110 changes: 110 additions & 0 deletions
110
invokeai/app/invocations/z_image_seed_variance_enhancer.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,110 @@ | ||
| import torch | ||
|
|
||
| from invokeai.app.invocations.baseinvocation import BaseInvocation, Classification, invocation | ||
| from invokeai.app.invocations.fields import ( | ||
| FieldDescriptions, | ||
| Input, | ||
| InputField, | ||
| ZImageConditioningField, | ||
| ) | ||
| from invokeai.app.invocations.primitives import ZImageConditioningOutput | ||
| from invokeai.app.services.shared.invocation_context import InvocationContext | ||
| from invokeai.backend.stable_diffusion.diffusion.conditioning_data import ( | ||
| ConditioningFieldData, | ||
| ZImageConditioningInfo, | ||
| ) | ||
|
|
||
|
|
||
| @invocation( | ||
| "z_image_seed_variance_enhancer", | ||
| title="Seed Variance Enhancer - Z-Image", | ||
| tags=["conditioning", "z-image", "variance", "seed"], | ||
| category="conditioning", | ||
| version="1.0.0", | ||
| classification=Classification.Prototype, | ||
| ) | ||
| class ZImageSeedVarianceEnhancerInvocation(BaseInvocation): | ||
| """Adds seed-based noise to Z-Image conditioning to increase variance between seeds. | ||
| Z-Image-Turbo can produce relatively similar images with different seeds, | ||
| making it harder to explore variations of a prompt. This node implements | ||
| reproducible, seed-based noise injection into text embeddings to increase | ||
| visual variation while maintaining reproducibility. | ||
| The noise strength is auto-calibrated relative to the embedding's standard | ||
| deviation, ensuring consistent results across different prompts. | ||
| """ | ||
|
|
||
| conditioning: ZImageConditioningField = InputField( | ||
| description=FieldDescriptions.cond, | ||
| input=Input.Connection, | ||
| title="Conditioning", | ||
| ) | ||
| seed: int = InputField( | ||
| default=0, | ||
| ge=0, | ||
| description="Seed for reproducible noise generation. Different seeds produce different noise patterns.", | ||
| ) | ||
| strength: float = InputField( | ||
| default=0.1, | ||
| ge=0.0, | ||
| le=2.0, | ||
| description="Noise strength as multiplier of embedding std. 0=off, 0.1=subtle, 0.5=strong.", | ||
| ) | ||
| randomize_percent: float = InputField( | ||
| default=50.0, | ||
| ge=1.0, | ||
| le=100.0, | ||
| description="Percentage of embedding values to add noise to (1-100). Lower values create more selective noise patterns.", | ||
| ) | ||
|
|
||
| @torch.no_grad() | ||
| def invoke(self, context: InvocationContext) -> ZImageConditioningOutput: | ||
| # Load conditioning data | ||
| cond_data = context.conditioning.load(self.conditioning.conditioning_name) | ||
| assert len(cond_data.conditionings) == 1, "Expected exactly one conditioning tensor" | ||
| z_image_conditioning = cond_data.conditionings[0] | ||
| assert isinstance(z_image_conditioning, ZImageConditioningInfo), "Expected ZImageConditioningInfo" | ||
|
|
||
| # Early return if strength is zero (no modification needed) | ||
| if self.strength == 0: | ||
| return ZImageConditioningOutput(conditioning=self.conditioning) | ||
|
|
||
| # Clone embeddings to avoid modifying the original | ||
| prompt_embeds = z_image_conditioning.prompt_embeds.clone() | ||
|
|
||
| # Calculate actual noise strength based on embedding statistics | ||
| # This auto-calibration ensures consistent results across different prompts | ||
| embed_std = torch.std(prompt_embeds).item() | ||
| actual_strength = self.strength * embed_std | ||
|
|
||
| # Generate deterministic noise using the seed | ||
| generator = torch.Generator(device=prompt_embeds.device) | ||
| generator.manual_seed(self.seed) | ||
| noise = torch.rand( | ||
| prompt_embeds.shape, generator=generator, device=prompt_embeds.device, dtype=prompt_embeds.dtype | ||
| ) | ||
| noise = noise * 2 - 1 # Scale to [-1, 1] | ||
| noise = noise * actual_strength | ||
|
|
||
| # Create selective mask for noise application | ||
| generator.manual_seed(self.seed + 1) | ||
| noise_mask = torch.bernoulli( | ||
| torch.ones_like(prompt_embeds) * (self.randomize_percent / 100.0), | ||
| generator=generator, | ||
| ).bool() | ||
|
|
||
| # Apply noise only to masked positions | ||
| prompt_embeds = prompt_embeds + (noise * noise_mask) | ||
|
|
||
| # Save modified conditioning | ||
| new_conditioning = ZImageConditioningInfo(prompt_embeds=prompt_embeds) | ||
| conditioning_data = ConditioningFieldData(conditionings=[new_conditioning]) | ||
| conditioning_name = context.conditioning.save(conditioning_data) | ||
|
|
||
| return ZImageConditioningOutput( | ||
| conditioning=ZImageConditioningField( | ||
| conditioning_name=conditioning_name, | ||
| mask=self.conditioning.mask, | ||
| ) | ||
| ) | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.