14 KiB
Per-layer parameter rules for merge, extraction, and resize
1. Summary and initial scope
Add one multiline configurator node that supplies optional per-layer numeric overrides to existing nodes. Matching layers receive the explicitly assigned values; unassigned parameters and unmatched layers retain the main node’s settings. Existing exclusions, inclusion filters, discard rules, mismatch handling, and safety guards remain authoritative.
The initial implementation covers these 39 nodes:
| Family | Included variants | Count |
|---|---|---|
| Standard mergers | Two- and three-input checkpoint, diffusion-model, text-encoder, LoRA, and embedding mergers | 10 |
| Extraction | Fixed, Ratio, Quantile, Knee, and Frobenius for LoRA, DoRA, learned DoRA, text-encoder LoRA, and text-encoder DoRA | 25 |
| LoRA resize | Fixed, Ratio, Frobenius, and Cumulative | 4 |
Do not expand this implementation to CWB configuration, weighted multi-LoRA merging, LoRA application, Lodestone, optimizer settings, iteration counts, seeds, device selection, dtype selection, or new normalization behavior. These remain post-implementation considerations.
No changes are made during planning. After approval and execution is enabled, the first implementation action is to save this entire approved plan verbatim to plans/per-layer-parameter-rules.md. Commit that planning document before editing implementation files. Commit the completed feature after verification.
Preserve the pre-existing analysis/report edits currently outside the filter commit.
2. Public interface, syntax, and bindings
Configurator and connection
Implement LayerParameterConfiguration, displayed as Layer Parameter Configuration, in a new nodes/layer_parameters.py module.
Its inputs are:
| Input | Type | Default | Meaning |
|---|---|---|---|
rules |
Multiline string | Empty | One pattern-and-assignment rule per line |
glob_patterns |
Boolean | False | False uses regex substring search; True uses glob substring matching |
Its outputs are:
| Output | Type | Meaning |
|---|---|---|
layer_parameters |
io.Custom("MODELUTILS_LAYER_PARAMETERS") |
Immutable, parsed rules |
documentation |
String | Syntax, bindings, supported nodes, fallback behavior, errors, and examples |
This follows the existing io.Custom(...) configurator/socket mechanism already used by CWB. No frontend extension or dynamic socket-type changes are needed.
Append an optional layer_parameters input to each supported receiver. Append layer_parameters=None to its execution interface and forward it by keyword. Preserve every existing input identifier, widget order, output, and default.
An unconnected input or an empty rule set leaves the operation unchanged.
Rule grammar
Accept the following forms:
(blocks\.4[589]\.attn\.qkv_proj) a:0.5 b:0.25 c:0.75 d:1.0
(blocks\.4[589]\.attn\.qkv_proj) alpha:0.5, beta:0.25, gamma:0.75, delta:1.0
(blocks\.4[589]\.attn\.qkv_proj) a:64, b:32, c:0.99, d:0.0
(blocks\.4[589]\.attn\.qkv_proj) max_rank:128 min_rank:1 target:0.9
Rules:
- Require a parenthesized pattern followed by at least one
name:valueassignment. - Accept whitespace, commas, or a mixture between assignments, including whitespace around colons.
- Preserve the pattern’s backslashes, internal whitespace, nested groups, and character classes.
- Accept signed decimal and scientific-notation numeric values. Reject nonfinite values.
- Ignore blank lines and whole-line comments whose first nonwhitespace character is
#. Do not support inline comments. - Reject empty patterns, missing values, trailing garbage, duplicate assignments, and invalid regex.
- Use
re.searchfor regex matching. For glob matching, use case-sensitivefnmatchcasewith surrounding wildcards to provide substring matching. - Keep configurator pattern syntax independent of the main node’s existing exclusion-filter syntax.
Short aliases and full parameter names may be mixed. Two aliases assigning the same parameter on one line are an error, even when their values agree.
Binding tables
The shared binding definitions must generate both receiver tooltips and configurator documentation, preventing the two from drifting.
Standard merge coefficients
Bindings remain stable across calculation modes:
| Short name | Full name |
|---|---|
a |
alpha |
b |
beta |
c or g |
gamma |
d |
delta |
e |
epsilon |
f or z |
zeta |
Accept only coefficients actually used by the selected calculation mode:
| Calculation mode | Supported coefficients |
|---|---|
| Weight-Sum; Train-Difference | alpha |
| Add-Difference; Power-Up (DARE) | alpha, beta |
| Comparative-Interpolation; Add-Dissimilarities; SVD LoRA Extraction; Enhanced Auto Interp; Weight-Sum Cutoff; Power-Up (DARE+TIES) | alpha, beta, gamma |
| Extract-Features; Enhanced Man Interp; Power-Up Enhanced (DARE) | alpha, beta, gamma, delta |
| Power-Up Enhanced (DARE+TIES) | beta, gamma, delta, epsilon, zeta |
Reject assignments to ignored coefficients rather than pretend they affect the selected mode. Seeds remain main-node settings.
Extraction
Use the same bindings across LoRA, DoRA, learned DoRA, and both text-encoder extraction families:
| Method | a |
b |
c |
d |
e |
f |
|---|---|---|---|---|---|---|
| Fixed | linear_dim | conv_dim | clamp_quantile | min_diff | — | — |
| Ratio | linear_ratio | conv_ratio | clamp_quantile | min_diff | linear_max_rank | conv_max_rank |
| Quantile | linear_quantile | conv_quantile | clamp_quantile | min_diff | linear_max_rank | conv_max_rank |
| Frobenius | linear_target | conv_target | clamp_quantile | min_diff | linear_max_rank | conv_max_rank |
| Knee | linear_max_rank | conv_max_rank | clamp_quantile | min_diff | — | — |
Knee method selection, probe offsets, SVD iterations, chunking controls, and learned-DoRA optimization settings remain on the receiving node.
LoRA resize
| Method | a |
b |
c |
|---|---|---|---|
| Fixed | new_rank | — | — |
| Ratio | max_rank | ratio | — |
| Frobenius | max_rank | min_rank | target |
| Cumulative | max_rank | target | — |
Value validation
Inherit values from the receiving node—not hardcoded configurator defaults.
For supplied overrides:
- Extraction dimensions and rank caps are integral values in
[1, 16384]; ratios are[1, 100]; quantile/Frobenius targets are[0, 1];clamp_quantileis[0.5, 1];min_diffis[0, 1]. - Resize ranks are integral values in
[1, 3072]; ratios are[1, 100]; targets are[0.1, 1]. - Validate resolved Frobenius resize
min_rank <= max_rank, including values inherited from the main node. - Standard merge coefficients retain existing widget bounds. Where a coefficient represents a quantile or probability, validate
[0, 1]; generic SVD rank coefficients must also be positive integral values. - Do not silently truncate fractional ranks or repair invalid assignments. Retain existing mathematical rank caps imposed by tensor dimensions.
3. Matching and implementation data flow
Matching contract
For ordinary model merging and extraction, match the receiving operation’s target tensor names.
For LoRA inputs, match the normalized logical layer name after the existing parsing and normalization path. Do not match factor or alpha suffixes independently.
Use the established dotted naming produced by extraction and existing reference mapping. Preserve internal identifiers such as qkv_proj. Do not introduce underscore normalization as the new public convention, rewrite regex punctuation, or redesign model-format conversion.
Retain the existing unresolved flattened-name fallback when no reference mapping exists. Documentation must distinguish this fallback from the normal dotted path. A dotted rule that cannot match the resulting normalized input names produces the ordinary unmatched-rule error; do not silently reinterpret it.
A single rule matching multiple keys belonging to one logical LoRA layer counts as one match. That layer receives one parameter set shared by its factors.
Strict errors and fallback
Validate all rules before opening the output writer or beginning tensor streaming:
- Parse syntax and compile patterns once in the configurator.
- At each receiver, resolve aliases and reject unsupported parameters.
- Use header/key information to identify target layers and their existing normalized names.
- Detect matching rules per logical layer.
- Reject multiple matching rule lines for any one layer—even if their assignments concern different parameters.
- Reject any rule line matching no target layer.
- Combine the single matching rule with main-node values and validate the resulting parameters.
Errors identify the receiving node, configuration line number, pattern, and affected layer or parameter. Overlap errors include every conflicting line number.
Determine name matches before existing exclusions so an explicitly excluded layer is not falsely reported as nonexistent. Overrides never reactivate an excluded, discarded, guarded, or otherwise unprocessable layer.
Shared implementation
Keep parsing, immutable rule records, binding definitions, and matching/error handling in the new shared module.
Store only lightweight per-layer assignments and resolved scalar parameters. Do not store tensors, mutate the shared configuration payload, or modify global/main-node parameter dictionaries between layers.
Register the configurator through the existing extension node list. Do not add dependencies.
Standard merger integration
In MergerLogic.execute_merge:
- Prepare the rule-to-layer mapping alongside existing header-based work planning.
- For LoRA mode, use parsed logical groups to assign the same override to their factor keys; retain existing merge and alpha-normalization behavior.
- Immediately before
calc_mode_class.create_recipe, construct a layer-local parameter dictionary containing the base settings plus that layer’s overrides. - Keep tensor references and preloaded-source data local to the current work unit.
- Do not mutate
recipe_paramswith overrides that could affect later layers.
Do not change recipe formulas, calculation-mode selection, or source-loading behavior.
Extraction integration
Thread the optional rules through all 25 node entry points into the four extraction backends.
Prepare resolved parameters before streaming, then use them in each backend’s _process_layer before min_diff testing and SVD selection.
Specific requirements:
- Fixed-rank overrides update both the requested dimension and corresponding maximum-rank argument; otherwise the original cap would negate an increased rank.
- Adaptive overrides update the existing linear/conv method parameter and rank cap without altering method selection or probe settings.
- Normal execution, CPU retry, and chunked fallback use the same resolved layer values.
- Extend the existing chunked extraction helpers with a trailing
clamp_quantileargument and pass the effective value through. These helpers currently omit it when calling_svd_extract_linear; text-encoder extraction shares the SVD helper. - Perform configuration validation outside broad extraction exception handlers so a configuration error cannot become a silently skipped layer.
Do not alter SVD, chunk recombination, learned optimization, or tensor-lifecycle algorithms.
Resize integration
Attach resolved rank/target values to the existing logical-layer work units.
When calling _resize_lora_factors, translate the public bindings into the existing arguments:
- Fixed
new_rank→new_rank. - Adaptive
max_rank→new_rank. - Ratio/target →
dynamic_param. - Frobenius
min_rank→min_rank.
Leave dynamic_method on the main node. Preserve whole-layer factor handling, alpha behavior, passthrough data, low-bit handling, dtype selection, and CPU fallback.
4. Verification and delivery
Extend the repository-owned test selector with focused rule-parser and integration coverage. Map the new production module explicitly; do not rely solely on the broad repository-contract group.
Required tests:
- Both delimiter styles, mixed short/full names, scientific notation, nested regex groups, CRLF, blank lines, and comments.
- Invalid syntax, invalid regex, unsupported parameters, duplicate aliases, nonfinite values, fractional ranks, and invalid resolved rank bounds.
- Overlapping rules fail with layer and line numbers; unmatched rules fail before streaming or writing.
- Partial assignments inherit remaining main-node values. Unmatched layers retain main-node behavior.
- Existing include/exclude/discard and safety paths remain authoritative.
- LoRA matching uses normalized logical names, preserves internal underscores, and assigns one configuration to paired factors.
- All 39 receiver schemas append the optional socket without moving existing controls; every execution wrapper forwards it correctly.
- Standard merge outputs reflect different coefficients on different layers, without leaking overrides to later layers.
- Every extraction family uses the requested per-layer rank, clamp, and
min_diff; cover adaptive methods, CPU retry, and forced chunk fallback. - All four resize variants use their resolved rank/target values, including inherited
min_rankvalidation. - Absent or empty configuration preserves existing behavior.
- Configuration failures preserve any existing destination file.
Use small deterministic tensors and existing I/O fixtures. Do not run model inference or add unrelated performance, architecture, or normalization test projects.
Run focused groups during development, --changed after accumulated changes, and the required full gate before the feature commit. Run changed-file lint, compilation, and git diff --check; distinguish pre-existing lint findings from new ones.
Deliver the saved approved plan, implementation, generated binding documentation/tooltips, regression tests, and a verified feature commit. Leave unrelated analysis/report edits untouched.