Skip to content

feat(lora): per LoRA-model configurable weight range#9154

Open
lstein wants to merge 5 commits into
mainfrom
feat/lora-weight-range
Open

feat(lora): per LoRA-model configurable weight range#9154
lstein wants to merge 5 commits into
mainfrom
feat/lora-weight-range

Conversation

@lstein
Copy link
Copy Markdown
Collaborator

@lstein lstein commented May 11, 2026

Summary

  • The LoRA weight slider was previously hard-coded to a -1.0..+2.0 range. Slider-style LoRAs that operate at larger scales (e.g. -10..+10) couldn't be driven to their useful values from the UI.
  • This PR adds optional weight_min and weight_max fields to LoraModelDefaultSettings, exposes them in the model edit panel as toggleable spinners (alongside a re-labeled "Starting Weight" spinner), and makes the canvas LoRA card's slider honor whatever range the user saved on the model. The previous -1..+2 hard cap on weight is removed.

Setting the min and max weights from within the Model Manager:

image

The LoRA slider with custom min and max ranges

image

Changes

  • Backend (invokeai/backend/model_manager/configs/lora.py): LoraModelDefaultSettings gains weight_min and weight_max (both optional, default None); a model validator rejects weight_min >= weight_max. Removed the ge=-1, le=2 constraint on weight.
  • Model edit panel: Three spinners in a single row — Starting Weight / Min Weight / Max Weight — each independently toggleable. Client-side validation surfaces a toast if min >= max before the PATCH.
  • LoRA card (canvas): Slider/number-input bounds are pulled from loraConfig.default_settings.weight_min/max, falling back to the global defaults (-1..+2 slider, -10..+10 number input).
  • State: Relaxed the zLoRA.weight zod schema from .gte(-10).lte(10) to plain z.number() so persisted values within a user-set wide range aren't rejected on rehydration.
  • Regenerated services/api/schema.ts; added en locale strings.

Test plan

  • Edit a LoRA, set Min Weight = -10 and Max Weight = 10, save; reopen the panel and confirm values persist.
  • Try saving Min >= Max and confirm the toast prevents the request.
  • Add the LoRA to a generation and verify the canvas slider now spans the saved range.
  • Edit a LoRA and leave min/max disabled; confirm the canvas slider falls back to -1..+2.
  • pnpm lint:tsc, pnpm lint:eslint, pnpm lint:prettier, pnpm lint:knip, pnpm lint:dpdm
  • pnpm test:no-watch (1097 passed)
  • pytest tests/app/routers/test_model_manager.py tests/backend/model_manager/configs/ (45 passed)

🤖 Generated with Claude Code

Adds optional `weight_min` and `weight_max` to the LoRA model's default
settings so slider LoRAs that operate at non-standard scales (e.g.
-10..+10) can be tuned without bumping into the previously hard-coded
-1..+2 slider range. The model edit panel exposes them alongside the
starting weight, and the LoRA card slider in the canvas honors whatever
range the user saved on the model.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@github-actions github-actions Bot added python PRs that change python files backend PRs that change backend files frontend PRs that change frontend files labels May 11, 2026
@lstein lstein added the 6.14.x label May 11, 2026
@lstein lstein moved this to 6.14.x Theme: LIBRARY UPDATES in Invoke - Community Roadmap May 11, 2026
@lstein lstein changed the title feat(lora): per-model configurable weight range feat(lora): per LoRA-model configurable weight range May 11, 2026
Copy link
Copy Markdown
Collaborator

@JPPhoto JPPhoto left a comment

Choose a reason for hiding this comment

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

  • invokeai/frontend/web/src/features/modelManagerV2/subpanels/ModelPanel/LoRAModelDefaultSettings/LoRAModelDefaultSettings.tsx:45: partial LoRA range defaults are validated only when both weightMin and weightMax are enabled, and the backend mirrors that at invokeai/backend/model_manager/configs/lora.py:49. Saving only weight_min=3 is accepted, but LoRACard falls back to sliderMax=2 at invokeai/frontend/web/src/features/lora/components/LoRACard.tsx:61 and then renders a slider with min={3} and max={2} at invokeai/frontend/web/src/features/lora/components/LoRACard.tsx:95. The same failure happens with only weight_max <= -1. This persists an invalid model setting that can break or misrender the LoRA weight control. To expose this issue, add a test that saves only weight_min above the default max, or only weight_max below the default min, and asserts the API or UI rejects it before persistence.

  • invokeai/frontend/web/src/features/modelManagerV2/subpanels/ModelPanel/LoRAModelDefaultSettings/LoRAModelDefaultSettings.tsx:58: the submitted weight is never validated against the effective slider range before being saved. The model form computes effective bounds in DefaultWeight.tsx, but onSubmit still accepts any enabled weight and the backend removed the old ge=-1, le=2 constraint at invokeai/backend/model_manager/configs/lora.py:42. A model can therefore persist default_settings={ weight: 10, weight_min: -1, weight_max: 2 }; adding that LoRA uses the out-of-range default at invokeai/frontend/web/src/features/controlLayers/store/lorasSlice.ts:41, while LoRACard renders a slider limited to -1..2 at invokeai/frontend/web/src/features/lora/components/LoRACard.tsx:95. To expose this issue, add a test that saves a starting weight outside the enabled/effective min/max and asserts it is rejected or the saved range is expanded consistently.

Address review feedback on partial-bound and weight-out-of-range cases:

- Backend LoraModelDefaultSettings now computes an effective slider range
  using frontend-matching defaults (-1, 2) when one bound is unset, and
  rejects saves where effective_min >= effective_max or where the starting
  weight falls outside that range. Previously, saving only weight_min=3
  (or weight_max<=-1) was accepted and produced an inverted slider in
  LoRACard, and weight=10 with bounds [-1, 2] was persisted unchanged.
- Mirror the same checks in LoRAModelDefaultSettings.tsx onSubmit so
  invalid configurations are surfaced inline before the API call.
- Add backend tests covering partial bounds and out-of-range weight.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@lstein
Copy link
Copy Markdown
Collaborator Author

lstein commented May 14, 2026

Thanks for the careful review @JPPhoto — both findings are real bugs. Fixed in c976a53.

Backend (invokeai/backend/model_manager/configs/lora.py)

LoraModelDefaultSettings now computes an effective slider range by falling back to module-level constants _DEFAULT_LORA_WEIGHT_SLIDER_MIN = -1.0 / _DEFAULT_LORA_WEIGHT_SLIDER_MAX = 2.0 (mirroring the frontend's DEFAULT_LORA_WEIGHT_CONFIG) when one bound is unset, and rejects:

  • effective_min >= effective_max — covers your weight_min=3 (only) and weight_max<=-1 (only) cases.
  • weight outside [effective_min, effective_max] — covers weight=10 with bounds [-1, 2].

Frontend (LoRAModelDefaultSettings.tsx)

Mirrored both checks in onSubmit using the same DEFAULT_LORA_WEIGHT_CONFIG constants, so users get an inline error toast before the API call rather than relying on the backend.

Tests (tests/backend/model_manager/configs/test_lora_default_settings.py)

Added 17 cases against LoraModelDefaultSettings directly, including the ones you suggested:

  • test_rejects_only_weight_min_above_default_maxweight_min=3, no weight_max.
  • test_rejects_only_weight_max_below_default_minweight_max=-2, no weight_min.
  • test_rejects_weight_above_explicit_effective_rangeweight=10 with [-1, 2].
  • Plus symmetric cases for weight below range, weight outside partial bounds, inclusive boundary acceptance, etc.

All 17 pass.

@github-actions github-actions Bot added the python-tests PRs that change python tests label May 14, 2026
@JPPhoto
Copy link
Copy Markdown
Collaborator

JPPhoto commented May 14, 2026

This addressed the problems! It looks like you need to run ruff checks/fixes, plus openapi.json is stale and needs to be regenerated (followed by make frontend-typegen):

python scripts/generate_openapi_schema.py > invokeai/frontend/web/openapi.json

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

6.14.x backend PRs that change backend files frontend PRs that change frontend files python PRs that change python files python-tests PRs that change python tests

Projects

Status: 6.14.x Theme: USER EXPERIENCE

Development

Successfully merging this pull request may close these issues.

2 participants