Compare commits

..

354 Commits

Author SHA1 Message Date
Brandon Rising
99146be670 Next: Remove deprecated app.on_event usage in api runner 2024-02-29 13:29:01 -05:00
psychedelicious
4426c1de5a chore: ruff 2024-02-29 13:29:01 -05:00
blessedcoolant
2a579ba953 fix: Assertion issue with SDXL Compel 2024-02-29 13:29:01 -05:00
Brandon Rising
95875c6827 Fix merge with next 2024-02-29 13:29:01 -05:00
Brandon Rising
2df7db7e49 Switch absolute path to as_posix in _walk_directory 2024-02-29 13:29:01 -05:00
Brandon Rising
1b839cd26d Ruff checks 2024-02-29 13:29:01 -05:00
Brandon Rising
d370e1fd6f Fix directory called on _walk_directory 2024-02-29 13:29:01 -05:00
Brandon Rising
b13d11eaac Switch ModelSearch from os.walk to os.scandir 2024-02-29 13:29:01 -05:00
Brandon Rising
35dfad7318 Ruff format 2024-02-29 13:29:01 -05:00
Brandon Rising
92a7c1eec5 Ruff check 2024-02-29 13:29:01 -05:00
Brandon Rising
2a6722bb6c Extract TI loading logic into util, disallow it from ever failing a generation 2024-02-29 13:29:01 -05:00
Brandon Rising
9a1e55a305 Fix one last reference to the uncasted model 2024-02-29 13:29:01 -05:00
Brandon Rising
4c9dc7f845 Allow TIs to be either a key or a name in the prompt during our transition to using keys 2024-02-29 13:29:01 -05:00
Lincoln Stein
2da03bebaa handle change to Civitai metadata schema for commercial usage 2024-02-29 13:29:01 -05:00
Jennifer Player
1d5f7acf96 updated to use new import model mutation 2024-02-29 13:29:01 -05:00
psychedelicious
4c787f879d fix(ui): merge conflict 2024-02-29 13:29:01 -05:00
psychedelicious
f400867b9e chore(ui): bump deps
The only major version is `query-string`. The breaking change for it is dropping support for old versions of node. Not a problem for us.
2024-02-29 13:29:01 -05:00
psychedelicious
44b285637a ci: change frontend check to dpdm 2024-02-29 13:29:01 -05:00
psychedelicious
9c589b4449 feat(ui): move from madge to dpdm for circular dependencies 2024-02-29 13:29:01 -05:00
psychedelicious
f8375a9f72 tidy(ui): fix circular dependencies in listeners 2024-02-29 13:29:01 -05:00
psychedelicious
e4be78c256 tidy: remove some traces of ONNX 2024-02-29 13:29:01 -05:00
psychedelicious
3b725126fc chore(ui): typegen, update knip config
Knip should never touch the autogenerated types
2024-02-29 13:29:01 -05:00
psychedelicious
ac012a07a2 chore(ui): update pnpm-lock.yaml
Forgot to run `pnpm i` earlier after removing packages.
2024-02-29 13:29:01 -05:00
psychedelicious
2699755c6e ci: add knip to ui check workflow 2024-02-29 13:29:01 -05:00
psychedelicious
0c2b7b0e0f feat(ui): configure knip 2024-02-29 13:29:01 -05:00
psychedelicious
4a506eb0a7 tidy(ui): clean up unused code 6
unused files
2024-02-29 13:29:01 -05:00
psychedelicious
d435a479f1 tidy(ui): clean up unused code 5
variables, types and schemas
2024-02-29 13:29:01 -05:00
psychedelicious
e38427d5a1 tidy(ui): clean up unused code 4
variables, types and schemas
2024-02-29 13:29:01 -05:00
psychedelicious
a106c1126c tidy(ui): clean up unused code 3
variables, types and schemas
2024-02-29 13:29:01 -05:00
psychedelicious
bca1737b9c tidy(ui): clean up unused code 2
types and schemas
2024-02-29 13:29:00 -05:00
psychedelicious
9db4d9b0c0 feat(mm): add log stmt for download complete event 2024-02-29 13:29:00 -05:00
psychedelicious
929b353305 fix(ui): model install progress sets total bytes correctly 2024-02-29 13:29:00 -05:00
psychedelicious
67f40a3b26 chore(ui): lint 2024-02-29 13:29:00 -05:00
psychedelicious
732a1f135d fix(ui): fix remaining TS issues 2024-02-29 13:29:00 -05:00
psychedelicious
3001b146b1 fix(ui): fix up MM queries & types (wip) 2024-02-29 13:29:00 -05:00
psychedelicious
4a048dd0d4 tidy(api): remove non-heuristic install route 2024-02-29 13:29:00 -05:00
psychedelicious
b38080336d tidy(mm): remove ONNX from AnyModelConfig 2024-02-29 13:29:00 -05:00
psychedelicious
45546fdcea tidy(ui): clean up unused code 1
- Only export when necessary
- Remove totally usused functions, variables, state, etc
- Remove unused packages
2024-02-29 13:29:00 -05:00
psychedelicious
5e83fc8ac7 feat(ui): add knip + minimal config
https://knip.dev/

Replaces `unimported`
2024-02-29 13:29:00 -05:00
psychedelicious
04024fe479 fix(ui): fix missing component import 2024-02-29 13:29:00 -05:00
blessedcoolant
0722eb132d ui: split the canvas mask blur and edge size setting 2024-02-29 13:29:00 -05:00
Jennifer Player
120988b5f3 added add all button to scan models 2024-02-29 13:29:00 -05:00
psychedelicious
76e21fe607 feat(ui): create metadata types for control adapters
These are the same as the existing control adapter types, but the model field is non-nullable, simplifying handling of these objects.
2024-02-29 13:29:00 -05:00
psychedelicious
769ddc0024 fix(ui): model metadata handlers use model identifiers, not configs
Model metadata includes the main model, VAE and refiner model.

These used full model configs, as returned by the server, as their metadata type.

LoRA and control adapter metadata only use the metadata identifier.

This created a difference in handling. After parsing a model/vae/refiner, we have its name and can display it. But for LoRAs and control adapters, we only have the model key and must query for the full model config to get the name.

This change makes main model/vae/refiner metadata only have the model key, like LoRAs and control adapters.

The render function is now async so fetching can occur within it. All metadata fields with models now only contain the identifier, and fetch the model name to render their values.
2024-02-29 13:29:00 -05:00
psychedelicious
4833f9c736 fix(ui): CanvasPasteBack types 2024-02-29 13:29:00 -05:00
psychedelicious
68f9ce5e2d tidy(ui): remove unused metadata schemas 2024-02-29 13:29:00 -05:00
psychedelicious
ac200ab79d feat(nodes): update LoRAMetadataItem model
LoRA model now at under `model` not `lora.
2024-02-29 13:29:00 -05:00
psychedelicious
38cf809cb0 tidy(ui): tidy model identifier logic
- Move some files around
- Use util to extract key and base from model config
2024-02-29 13:29:00 -05:00
psychedelicious
d069f21d97 feat(ui): optimize model query caching
When we retrieve a list of models, upsert that data into the `getModelConfig` and `getModelConfigByAttrs` query caches.

With this change, calls to those two queries are almost always going to be free, because their caches will already have all models in them. The exception is queries for models that no longer exist.
2024-02-29 13:29:00 -05:00
psychedelicious
7d23120c2e fix(ui): fix lora metadata item type 2024-02-29 13:29:00 -05:00
psychedelicious
3b9b11e94b fix(ui): fix node type 2024-02-29 13:29:00 -05:00
psychedelicious
cd0699ada4 feat(ui): add transformation to width/height parameter schemas to round to multiple of 8
This allows image dimensions that are not multiples of 8 to still be recalled with best effort.
2024-02-29 13:29:00 -05:00
psychedelicious
8938765fb6 fix(ui): fix lora metadata rendering 2024-02-29 13:29:00 -05:00
psychedelicious
5b1fe4511e fix(ui): fix type issues related to change in LoRA type 2024-02-29 13:29:00 -05:00
psychedelicious
6a2ae5caa4 feat(ui): migrate all metadata recall logic to new system 2024-02-29 13:29:00 -05:00
psychedelicious
0cb2579109 fix(ui): use id for component key in control adapter components 2024-02-29 13:29:00 -05:00
psychedelicious
c6a95eb9ac feat(ui): no JSX in metadata handlers 2024-02-29 13:29:00 -05:00
psychedelicious
caa05864f8 feat(ui): refactor metadata handling (again)
Add concepts for metadata handlers. Handlers include parsers, recallers and validators for different metadata types:
- Parsers parse a raw metadata object of any shape to a structured object.
- Recallers load the parsed metadata into state. Recallers are optional, as some metadata types don't need to be loaded into state.
- Validators provide an additional layer of validation before recalling the metadata. This is needed because a metadata object may be valid, but not able to be recalled due to some other requirement, like base model compatibility. Validators are optional.

Sometimes metadata is not a single object but a list of items - like LoRAs. Metadata handlers may implement an optional set of "item" handlers which operate on individual items in the list.

Parsers and validators are async to allow fetching additional data, like a model config. Recallers are synchronous.

The these handlers are composed into a public API, exported as a `handlers` object. Besides the handlers functions, a metadata handler set includes:
- A function to get the label of the metadata type.
- An optional function to render the value of the metadata type.
- An optional function to render the _item_ value of the metadata type.
2024-02-29 13:29:00 -05:00
psychedelicious
f24b3c64d3 build(ui): do not fail build on eslint error in dev mode 2024-02-29 13:29:00 -05:00
psychedelicious
70d7b1c756 chore(ui): typegen 2024-02-29 13:29:00 -05:00
psychedelicious
92abcaedcf feat(api): add MM get_by_attrs route
Gets the first model that matches the given name, base and type. Raises 404 if there isn't one.

This will be used for backwards compatibility with old metadata.
2024-02-29 13:29:00 -05:00
Mary Hipp
2eb9d66ef0 undo 2024-02-29 13:29:00 -05:00
Mary Hipp
d893cb954a fix literal strings in MM UI 2024-02-29 13:29:00 -05:00
Mary Hipp
9a6c2089bf fix TI appearing as key in prompt 2024-02-29 13:29:00 -05:00
Mary Hipp
52d0f9c52f fix base model grouping in combobox 2024-02-29 13:29:00 -05:00
psychedelicious
638322e89f fix(mm): fix ModelCacheBase method name 2024-02-29 13:29:00 -05:00
psychedelicious
bc7572797c chore: ruff 2024-02-29 13:29:00 -05:00
Lincoln Stein
2463710497 recover gracefuly from GPU out of memory errors (next version) 2024-02-29 13:29:00 -05:00
Lincoln Stein
3be3bba007 clear out VRAM when an OOM occurs 2024-02-29 13:29:00 -05:00
psychedelicious
8dc33e60a7 feat(ui): bulk download click to download 2024-02-29 13:29:00 -05:00
psychedelicious
bde752bc02 fix(ui): fix node types for canvas graphs 2024-02-29 13:29:00 -05:00
psychedelicious
8f7b1f5068 chore(ui): typegen 2024-02-29 13:29:00 -05:00
psychedelicious
38afb918ad tidy(nodes): rename canvas paste back 2024-02-29 13:29:00 -05:00
blessedcoolant
5ca01bfad4 fix: outpaint result not getting pasted back correctly 2024-02-29 13:29:00 -05:00
blessedcoolant
c9f73c3340 fix: lint errors 2024-02-29 13:29:00 -05:00
blessedcoolant
6df606ac2a canvas: improve paste back (or try to) 2024-02-29 13:29:00 -05:00
blessedcoolant
ba3cf1d873 wip(ui): Replace 2 Layer Coherence pass with Gradient Mask 2024-02-29 13:28:58 -05:00
psychedelicious
1e52a1507b chore: ruff 2024-02-29 13:28:22 -05:00
psychedelicious
d52c956441 fix(ui): fix merge issue 2024-02-29 13:28:22 -05:00
psychedelicious
3130b3db64 fix(ui): use new scan_folder response instead of hook to determine if models are installed already 2024-02-29 13:28:22 -05:00
psychedelicious
8848443eff chore(ui): typegen 2024-02-29 13:28:22 -05:00
psychedelicious
acedc6d127 feat(mm): add logic to scan_folder route to check if a model is already installed
This was done in the frontend before but it's something the backend should handle.

The logic compares the found model paths to the path and source of all installed models. It excludes core models.
2024-02-29 13:28:22 -05:00
psychedelicious
6d78276049 chore(ui): lint 2024-02-29 13:28:22 -05:00
psychedelicious
858300030c build(ui): restore i18n eslint rule 2024-02-29 13:28:22 -05:00
psychedelicious
bcc02c5902 chore: ruff 2024-02-29 13:28:22 -05:00
psychedelicious
92f42dfb2a fix(ui): fix metadata route 2024-02-29 13:28:22 -05:00
psychedelicious
8b18c0d273 chore(ui): typegen 2024-02-29 13:28:22 -05:00
psychedelicious
35c9a29722 feat(api): mm metadata route "meta" -> "metadata" 2024-02-29 13:28:22 -05:00
Mary Hipp
8deca6c9e6 lint fix 2024-02-29 13:28:22 -05:00
Mary Hipp
5a8550d2dd updated translations 2024-02-29 13:28:22 -05:00
maryhipp
866ba7974b fix convert endpoint logic 2024-02-29 13:28:22 -05:00
Mary Hipp
7119a5b88f clean up old model manager components and endpoints 2024-02-29 13:28:22 -05:00
Mary Hipp
af9a62d224 add model convert to checkpoint main models 2024-02-29 13:28:22 -05:00
Mary Hipp
dd9b139e38 fix logic to see if scanned models are already installed, style tweaks 2024-02-29 13:28:22 -05:00
maryhipp
0c0da5480b add error_reason to ModelInstallJob 2024-02-29 13:28:22 -05:00
Mary Hipp
d802900abe add error_reason to UI if import fails 2024-02-29 13:28:22 -05:00
Mary Hipp
34b9ab3674 fix types for ImportQueue, add QuickAdd for scan models 2024-02-29 13:28:22 -05:00
Jennifer Player
7f56e84a8d refactored and fixed issues with advanced import form 2024-02-29 13:28:22 -05:00
psychedelicious
170d9bca98 fix(ui): misc MM cleanup 2024-02-29 13:28:22 -05:00
psychedelicious
84ddad4ea2 chore(ui): temp disable eslint i18 rule 2024-02-29 13:28:22 -05:00
psychedelicious
4854aa8dc2 fix(ui): fix ImportMainModelResponse type 2024-02-29 13:28:22 -05:00
psychedelicious
4afb6b8b0a fix(ui): simplify model install event listeners 2024-02-29 13:28:22 -05:00
psychedelicious
5baa79c903 fix(ui): fix model install event types 2024-02-29 13:28:22 -05:00
Jennifer Player
2db252af31 added advanced import forms, not fully working yet 2024-02-29 13:28:22 -05:00
Mary Hipp
ccdb89534a get positioning/scrolling working for scan results list 2024-02-29 13:28:22 -05:00
Mary Hipp
c23dcc3e77 basic scan working and renders results 2024-02-29 13:28:22 -05:00
Mary Hipp
a9b1f4b8c6 add scan model endpoint, break add model into tabs 2024-02-29 13:28:22 -05:00
Mary Hipp
0030606d99 update metadata endpoint 2024-02-29 13:28:22 -05:00
maryhipp
58ce98101b allow metadata-less models to be used for GET metadata endpoint 2024-02-29 13:28:22 -05:00
Jennifer Player
66df96e425 added status to import queue model 2024-02-29 13:28:22 -05:00
Jennifer Player
eec5f6fb44 delete model imports and prune all finished, update state with socket messages 2024-02-29 13:28:22 -05:00
Mary Hipp
913cfc9583 fix sync model endpoint 2024-02-29 13:28:22 -05:00
Mary Hipp
8185225937 form error handling 2024-02-29 13:28:22 -05:00
Mary Hipp
78365e2c61 finish model update 2024-02-29 13:28:22 -05:00
Jennifer Player
8aafa873ef added socket listeners, added more info to ui 2024-02-29 13:28:22 -05:00
Mary Hipp
52bbd3b5ec edit view for model, depending on type and valid values 2024-02-29 13:28:21 -05:00
Mary Hipp
da6c4bf493 hook up Add Model button 2024-02-29 13:28:21 -05:00
Mary Hipp
f1e21bc9a9 single model view 2024-02-29 13:28:21 -05:00
Jennifer Player
c99eaee6f3 added import model form and importqueue 2024-02-29 13:28:21 -05:00
Mary Hipp
c2fca07c8e model list, filtering, searching 2024-02-29 13:28:21 -05:00
Mary Hipp
49c68a16c2 workspace for mary and jenn 2024-02-29 13:28:21 -05:00
Mary Hipp
3d977def53 get old UI working somewhat with new endpoints 2024-02-29 13:28:21 -05:00
Brandon Rising
70570b7213 Allow passing in key on register 2024-02-29 13:28:21 -05:00
Brandon Rising
957ff8a17e Remove passing keys in on register 2024-02-29 13:28:21 -05:00
Brandon Rising
c32eb17d73 Run ruff 2024-02-29 13:28:21 -05:00
Brandon Rising
57b288e57b Allow users to run model manager without cuda 2024-02-29 13:28:21 -05:00
psychedelicious
4c06132fc6 fix(ui): roll back utility-types
It's `Required` util does not distribute over unions as expected. Also we have `ts-toolbelt` already for some utils.
2024-02-29 13:28:21 -05:00
psychedelicious
9b23820717 feat(ui): refactor metadata handling
Refactor of metadata recall handling. This is in preparation for a backwards compatibility layer for models.

- Create helpers to fetch a model outside react (e.g. not in a hook)
- Created helpers to parse model metadata
- Renamed a lot of types that were confusing and/or had naming collisions
2024-02-29 13:28:21 -05:00
psychedelicious
c323179854 chore(ui): typegen 2024-02-29 13:28:21 -05:00
psychedelicious
a0a143f495 fix(nodes): make fields on ModelConfigBase required
The setup of `ModelConfigBase` means autogenerated types have critical fields flagged as nullable (like `key` and `base`). Need to manually flag them as required.
2024-02-29 13:28:21 -05:00
psychedelicious
ae43e91caa feat(ui): replace type-fest with utility-types
- The new package has more useful types
- Only used `JsonObject` from `type-fest`; added an implementation of that type
2024-02-29 13:28:21 -05:00
Lincoln Stein
adab454c51 several small model install enhancements
- Support extended HF repoid syntax in TUI. This allows
  installation of subfolders and safetensors files, as in
  `XpucT/Deliberate::Deliberate_v5.safetensors`

- Add `error` and `error_traceback` properties to the install
  job objects.

- Rename the `heuristic_import` route to `heuristic_install`.

- Fix the example `config` input in the `heuristic_install` route.
2024-02-29 13:28:21 -05:00
Lincoln Stein
6f27a1ba8c use official Deliberate download repo 2024-02-29 13:28:21 -05:00
Lincoln Stein
dd7fc680bf fix repo-id for the Deliberate v5 model
prevent lora and embedding file suffixes from being stripped during installation

apply psychedelicious patch to get compel to load proper TI embedding
2024-02-29 13:28:21 -05:00
Lincoln Stein
3312dcc58f remove startup dependency on legacy models.yaml file 2024-02-29 13:28:21 -05:00
dunkeroni
c60cfdb285 chore: typing 2024-02-29 13:28:21 -05:00
dunkeroni
83984b92db chore: typing fix 2024-02-29 13:28:21 -05:00
dunkeroni
dcca220885 feat(nodes): added gradient mask node 2024-02-29 13:28:21 -05:00
Brandon Rising
550f6cb437 Run ruff 2024-02-29 13:28:21 -05:00
Mary Hipp
e18763438b rename endpoint for scanning 2024-02-29 13:28:21 -05:00
Brandon Rising
e731645f0e Create /search endpoint, update model object structure in scan model page 2024-02-29 13:28:21 -05:00
psychedelicious
15ce8e35c7 chore(ui): bump deps
Notable updates:
- Minor version of RTK includes customizable selectors for RTK Query, so we can remove the patch that was added to ensure only the LRU memoize function was used for perf reasons. Updated to use the LRU memoize function.
- Major version of react-resizable-panels. No breaking changes, works great, and you can now resize all panels when dragging at the intersection point of panels. Cool!
- Minor (?) version of nanostores. `action` API is removed, we were using it in one spot. Fixed.
- @invoke-ai/eslint-config-react has all deps bumped and now has its dependent plugins/configs listed as normal dependencies (as opposed to peer deps). This means we can remove those packages from explicit dev deps.
2024-02-29 13:28:21 -05:00
psychedelicious
8d6d03bd04 tidy(ui): remove debugging stmt 2024-02-29 13:28:21 -05:00
psychedelicious
64c1ce895c fix(ui): handle new model format for metadata 2024-02-29 13:28:21 -05:00
psychedelicious
1ced80d492 fix(ui): use model names in badges 2024-02-29 13:28:21 -05:00
psychedelicious
6577250523 fix(nodes): fix TI loading 2024-02-29 13:28:21 -05:00
psychedelicious
068886a70c fix(ui): fix package build 2024-02-29 13:28:21 -05:00
psychedelicious
3a97f6e38e feat(ui): do not subscribe to bulk download sio room if baseUrl is set 2024-02-29 13:28:21 -05:00
psychedelicious
85dae6ad1e feat(ui): revise bulk download listeners
- Use a single listener for all of the to keep them in one spot
- Use the bulk download item name as a toast id so we can update the existing toasts
- Update handling to work with other environments
- Move all bulk download handling from components to listener
2024-02-29 13:28:21 -05:00
psychedelicious
ffef5c65bb chore(ui): typegen 2024-02-29 13:28:21 -05:00
psychedelicious
f74e352f96 feat(bulk_download): update response model, messages 2024-02-29 13:28:21 -05:00
Stefan Tobler
6a6958f19b implementing download for bulk_download events 2024-02-29 13:28:21 -05:00
Stefan Tobler
6828962c05 setting up event listeners for bulk download socket 2024-02-29 13:28:21 -05:00
psychedelicious
c7ed5606bd test: clean up & fix tests
- Deduplicate the mock invocation services. This is possible now that the import order issue is resolved.
- Merge `DummyEventService` into `TestEventService` and update all tests to use `TestEventService`.
2024-02-29 13:28:21 -05:00
psychedelicious
fff5d12648 tidy(bulk_download): don't store events service separately
Using the invoker object directly leaves no ambiguity as to what `_events_bus` actually is.
2024-02-29 13:28:21 -05:00
psychedelicious
dabb5e2cf4 tidy(bulk_download): do not rely on pagination API to get all images for board
We can get all images for the board as a list of image names, then pass that to `_image_handler` to get the DTOs, decoupling from the pagination API.
2024-02-29 13:28:21 -05:00
psychedelicious
8927620c2d tidy(bulk_download): nit - use or as a coalescing operator
Just a bit cleaner.
2024-02-29 13:28:21 -05:00
psychedelicious
8244733145 tidy(bulk_download): use single underscore for private attrs
Double underscores are used in the app but it doesn't actually do or convey anything that single underscores don't already do. Considered unpythonic except for actual dunder/magic methods.
2024-02-29 13:28:21 -05:00
psychedelicious
ac25ad0b67 tidy(bulk_download): remove class-level attr annotations
These can be misleading as they shadow actual assigned class attributes. This pattern is in the rest of the app but it shouldn't be.
2024-02-29 13:28:21 -05:00
psychedelicious
8abb57eedb tidy(bulk_download): remove extraneous abstract methods
`start`, `stop` and `__init__` are not required in implementations of an ABC or service.
2024-02-29 13:28:21 -05:00
psychedelicious
b7f152b45a tidy(bulk_download): clean up comments 2024-02-29 13:28:21 -05:00
Stefan Tobler
28ae16001e adding bulk_download_item_name to socket events 2024-02-29 13:28:21 -05:00
Stefan Tobler
6468b044d8 refactoring handlers to do null check 2024-02-29 13:28:21 -05:00
Stefan Tobler
ec129662a6 removing dependency on an output folder, embrace python temp folder for bulk download 2024-02-29 13:28:21 -05:00
Stefan Tobler
024b4580a7 relocating event_service fixture due to import ordering 2024-02-29 13:28:21 -05:00
Stefan Tobler
ba28709f2d moving the responsibility of cleaning up board names to the service not the route 2024-02-29 13:28:21 -05:00
Stefan Tobler
3c881d5b1a updating imports to satisfy ruff 2024-02-29 13:28:21 -05:00
Stefan Tobler
bb40196a17 using temp directory for downloads 2024-02-29 13:28:21 -05:00
Stefan Tobler
b1301e1cbc returning the bulk_download_item_name on response for possible polling 2024-02-29 13:28:21 -05:00
Stefan Tobler
67df224df4 narrowing bulk_download stop service scope 2024-02-29 13:28:21 -05:00
Stefan Tobler
8102decfb9 adding test coverage for new bulk download routes 2024-02-29 13:28:21 -05:00
Stefan Tobler
4dfa1e3d03 cleaning up bulk download zip after the response is complete 2024-02-29 13:28:21 -05:00
Stefan Tobler
ca1c96e8f5 replacing import removed during rebase 2024-02-29 13:28:21 -05:00
Stefan Tobler
45f2370375 97% test coverage on bulk_download 2024-02-29 13:28:21 -05:00
Stefan Tobler
37e80f62b3 refactoring bulk_download to be better managed 2024-02-29 13:28:21 -05:00
Stefan Tobler
72429b1760 refactoring dummy event service, DRY principal; adding bulk_download_event to existing invoker tests 2024-02-29 13:28:21 -05:00
Stefan Tobler
c2b12f8849 refactoring bulkdownload to consider image category 2024-02-29 13:28:21 -05:00
Stefan Tobler
1e00b9760a fixing issue where default board did not return images 2024-02-29 13:28:21 -05:00
Stefan Tobler
c4cdaaf4dd using the board name to download boards 2024-02-29 13:28:21 -05:00
Stefan Tobler
9c61a40659 reworking some of the logic to use a default room, adding endpoint to download file on complete 2024-02-29 13:28:21 -05:00
Stefan Tobler
cacd0b9c4e linted and styling 2024-02-29 13:28:21 -05:00
Stefan Tobler
2dd67c3b71 implementation of bulkdownload background task 2024-02-29 13:28:21 -05:00
Stefan Tobler
cf6eb1394a adding socket events for bulk download 2024-02-29 13:28:21 -05:00
Stefan Tobler
aba9cd3f9a groundwork for the bulk_download_service 2024-02-29 13:28:21 -05:00
psychedelicious
f81388508f fix(ui): get workflow editor model selects working 2024-02-29 13:28:21 -05:00
psychedelicious
abe2055bbb fix(ui): get refiner model select working 2024-02-29 13:28:21 -05:00
psychedelicious
7dab32138c fix(ui): get vae model select working 2024-02-29 13:28:21 -05:00
psychedelicious
d6c9360fa3 fix(ui): get embedding select working 2024-02-29 13:28:20 -05:00
psychedelicious
ff53d828ce fix(ui): get lora select working 2024-02-29 13:28:20 -05:00
psychedelicious
0212d4f4a2 chore(ui): bump @invoke-ai/ui-library 2024-02-29 13:28:20 -05:00
psychedelicious
8db5aa626f fix(ui): fix low-hanging fruit types 2024-02-29 13:28:20 -05:00
Lincoln Stein
6e52d9bbce Add a few convenience targets to Makefile
- "test" to run pytests
- "frontend-install" to reinstall pnpm's node modeuls
2024-02-29 13:28:20 -05:00
psychedelicious
03db2cba6c chore(nodes): update TODO comment 2024-02-29 13:28:20 -05:00
psychedelicious
9ea8c2af54 tidy(nodes): clean up profiler/stats in processor, better comments 2024-02-29 13:28:20 -05:00
psychedelicious
37b8d59347 fix(nodes): fix typing on stats service context manager 2024-02-29 13:28:20 -05:00
psychedelicious
18e1fe83d5 fix(nodes): fix model load events
was accessing incorrect properties in event data
2024-02-29 13:28:20 -05:00
psychedelicious
198ed222c4 feat(nodes): making invocation class var in processor 2024-02-29 13:28:20 -05:00
psychedelicious
62199b0fb1 feat(nodes): improved error messages in processor 2024-02-29 13:28:20 -05:00
psychedelicious
bdb843a6fb feat(nodes): make processor thread limit and polling interval configurable 2024-02-29 13:28:20 -05:00
psychedelicious
817cc616ce tests(nodes): fix tests following removal of services 2024-02-29 13:28:20 -05:00
psychedelicious
d37840712b chore(nodes): better comments for invocation context 2024-02-29 13:28:20 -05:00
psychedelicious
5c4779907f chore(nodes): "context_data" -> "data"
Changed within InvocationContext, for brevity.
2024-02-29 13:28:20 -05:00
psychedelicious
8870e0f8f2 refactor(nodes): move is_canceled to context.util 2024-02-29 13:28:20 -05:00
psychedelicious
d35f986351 feat(nodes): add whole queue_item to InvocationContextData
No reason to not have the whole thing in there.
2024-02-29 13:28:20 -05:00
psychedelicious
fafaa09f5e tidy(nodes): remove extraneous comments 2024-02-29 13:28:20 -05:00
psychedelicious
03c5de78e1 feat(nodes): better invocation error messages 2024-02-29 13:28:20 -05:00
psychedelicious
e85634742e chore(nodes): add comments for cancel state 2024-02-29 13:28:20 -05:00
psychedelicious
b4a120af42 feat(nodes): promote is_canceled to public node API 2024-02-29 13:28:20 -05:00
psychedelicious
276a95ae8e refactor(nodes): merge processors
Consolidate graph processing logic into session processor.

With graphs as the unit of work, and the session queue distributing graphs, we no longer need the invocation queue or processor.

Instead, the session processor dequeues the next session and processes it in a simple loop, greatly simplifying the app.

- Remove `graph_execution_manager` service.
- Remove `queue` (invocation queue) service.
- Remove `processor` (invocation processor) service.
- Remove queue-related logic from `Invoker`. It now only starts and stops the services, providing them with access to other services.
- Remove unused `invocation_retrieval_error` and `session_retrieval_error` events, these are no longer needed.
- Clean up stats service now that it is less coupled to the rest of the app.
- Refactor cancellation logic - cancellations now originate from session queue (i.e. HTTP cancel endpoint) and are emitted as events. Processor gets the events and sets the canceled event. Access to this event is provided to the invocation context for e.g. the step callback.
- Remove `sessions` router; it provided access to `graph_executions` but that no longer exists.
2024-02-29 13:28:20 -05:00
psychedelicious
69a176be92 tidy(nodes): remove commented tests 2024-02-29 13:28:20 -05:00
psychedelicious
d4a7f55c72 chore(ui): typegen 2024-02-29 13:28:20 -05:00
psychedelicious
0977a5e4aa tidy(nodes): remove no-op model_config
Because we now customize the JSON Schema creation for GraphExecutionState, the model_config did nothing.
2024-02-29 13:28:20 -05:00
psychedelicious
b711c46fa4 tidy(nodes): remove LibraryGraphs
The workflow library supersedes this unused feature.
2024-02-29 13:28:20 -05:00
psychedelicious
fb0fe06135 tidy(nodes): move node tests to parent dir
Thanks to the resolution of the import vs union issue, we can put tests anywhere.
2024-02-29 13:28:20 -05:00
psychedelicious
ab83fb2cea tidy(nodes): remove GraphInvocation
`GraphInvocation` is a node that can contain a whole graph. It is removed for a number of reasons:

1. This feature was unused (the UI doesn't support it) and there is no plan for it to be used.

The use-case it served is known in other node execution engines as "node groups" or "blocks" - a self-contained group of nodes, which has group inputs and outputs. This is a planned feature that will be handled client-side.

2. It adds substantial complexity to the graph processing logic. It's probably not enough to have a measurable performance impact but it does make it harder to work in the graph logic.

3. It allows for graphs to be recursive, and the improved invocations union handling does not play well with it. Actually, it works fine within `graph.py` but not in the tests for some reason. I do not understand why. There's probably a workaround, but I took this as encouragement to remove `GraphInvocation` from the app since we don't use it.
2024-02-29 13:28:20 -05:00
psychedelicious
d7adab89bd fix(nodes): fix OpenAPI schema generation
The change to `Graph.nodes` and `GraphExecutionState.results` validation requires some fanagling to get the OpenAPI schema generation to work. See new comments for a details.
2024-02-29 13:28:20 -05:00
psychedelicious
0ad904d2b3 feat(nodes): JIT graph nodes validation
We use pydantic to validate a union of valid invocations when instantiating a graph.

Previously, we constructed the union while creating the `Graph` class. This introduces a dependency on the order of imports.

For example, consider a setup where we have 3 invocations in the app:

- Python executes the module where `FirstInvocation` is defined, registering `FirstInvocation`.
- Python executes the module where `SecondInvocation` is defined, registering `SecondInvocation`.
- Python executes the module where `Graph` is defined. A union of invocations is created and used to define the `Graph.nodes` field. The union contains `FirstInvocation` and `SecondInvocation`.
- Python executes the module where `ThirdInvocation` is defined, registering `ThirdInvocation`.
- A graph is created that includes `ThirdInvocation`. Pydantic validates the graph using the union, which does not know about `ThirdInvocation`, raising a `ValidationError` about an unknown invocation type.

This scenario has been particularly problematic in tests, where we may create invocations dynamically. The test files have to be structured in such a way that the imports happen in the right order. It's a major pain.

This PR refactors the validation of graph nodes to resolve this issue:

- `BaseInvocation` gets a new method `get_typeadapter`. This builds a pydantic `TypeAdapter` for the union of all registered invocations, caching it after the first call.
- `Graph.nodes`'s type is widened to `dict[str, BaseInvocation]`. This actually is a nice bonus, because we get better type hints whenever we reference `some_graph.nodes`.
- A "plain" field validator takes over the validation logic for `Graph.nodes`. "Plain" validators totally override pydantic's own validation logic. The validator grabs the `TypeAdapter` from `BaseInvocation`, then validates each node with it. The validation is identical to the previous implementation - we get the same errors.

`BaseInvocationOutput` gets the same treatment.
2024-02-29 13:28:20 -05:00
Lincoln Stein
75aa93fabb remove errant def that was crashing invokeai-configure 2024-02-29 13:28:20 -05:00
dunkeroni
0bd0cfc025 one more redundant RGB convert removed 2024-02-29 13:28:20 -05:00
dunkeroni
9c2dd21256 chore: ruff formatting 2024-02-29 13:28:20 -05:00
dunkeroni
4b33589def chore(invocations): remove redundant RGB conversions 2024-02-29 13:28:20 -05:00
dunkeroni
3e5a91e3bf chore(invocations): use IMAGE_MODES constant literal 2024-02-29 13:28:20 -05:00
dunkeroni
2dd2f19b46 fix: removed custom module 2024-02-29 13:28:20 -05:00
dunkeroni
5e14c90f94 fix(nodes): canny preprocessor uses RGBA again 2024-02-29 13:28:20 -05:00
dunkeroni
d17a0779cc feat(nodes): format option for get_image method
Also default CNet preprocessors to "RGB"
2024-02-29 13:28:20 -05:00
blessedcoolant
ee2ef470a7 fix: Alpha channel causing issue with DW Processor 2024-02-29 13:28:20 -05:00
psychedelicious
4191ca1a46 final tidying before marking PR as ready for review
- Replace AnyModelLoader with ModelLoaderRegistry
- Fix type check errors in multiple files
- Remove apparently unneeded `get_model_config_enum()` method from model manager
- Remove last vestiges of old model manager
- Updated tests and documentation

resolve conflict with seamless.py
2024-02-29 13:28:20 -05:00
Lincoln Stein
ab46865e5b Tidy names and locations of modules
- Rename old "model_management" directory to "model_management_OLD" in order to catch
  dangling references to original model manager.
- Caught and fixed most dangling references (still checking)
- Rename lora, textual_inversion and model_patcher modules
- Introduce a RawModel base class to simplfy the Union returned by the
  model loaders.
- Tidy up the model manager 2-related tests. Add useful fixtures, and
  a finalizer to the queue and installer fixtures that will stop the
  services and release threads.
2024-02-29 13:28:20 -05:00
Lincoln Stein
3c1b0d01ac Fix issues identified during PR review by RyanjDick and brandonrising
- ModelMetadataStoreService is now injected into ModelRecordStoreService
  (these two services are really joined at the hip, and should someday be merged)
- ModelRecordStoreService is now injected into ModelManagerService
- Reduced timeout value for the various installer and download wait*() methods
- Introduced a Mock modelmanager for testing
- Removed bare print() statement with _logger in the install helper backend.
- Removed unused code from model loader init file
- Made `locker` a private variable in the `LoadedModel` object.
- Fixed up model merge frontend (will be deprecated anyway!)
2024-02-29 13:28:20 -05:00
psychedelicious
8a8e862a5f chore(ui): lint 2024-02-29 13:28:20 -05:00
psychedelicious
ed860ae851 feat(ui): fix main model & control adapter model selects 2024-02-29 13:28:18 -05:00
psychedelicious
eb27951b8c refactor(ui): url builders for each router
The MM2 router is at `api/v2/models`. URL builder utils make this a bit easier to manage.
2024-02-29 13:21:15 -05:00
psychedelicious
527f76250a feat(ui): update model identifier to be key (wip)
- Update most model identifiers to be `{key: string}` instead of name/base/type. Doesn't change the model select components yet.
- Update model _parameters_, stored in redux, to be `{key: string, base: BaseModel}` - we need to store the base model to be able to check model compatibility. May want to store the whole config? Not sure...
2024-02-29 13:16:37 -05:00
psychedelicious
c53d73ddfa fix(nodes): fix t2i adapter model loading 2024-02-29 13:16:37 -05:00
psychedelicious
2d953fe0cc fix(ui): update model types 2024-02-29 13:16:37 -05:00
psychedelicious
c6be4f5b9f tests(ui): add type tests 2024-02-29 13:16:37 -05:00
psychedelicious
ac1382abed tests(ui): enable vitest type testing
This is useful for the zod schemas and types we have created to match the backend.
2024-02-29 13:16:37 -05:00
psychedelicious
f0dcd70515 chore(ui): typegen 2024-02-29 13:16:37 -05:00
psychedelicious
87b0f7d04a feat(ui): export components type 2024-02-29 13:16:37 -05:00
psychedelicious
535350ebce fix(ui): fix type issues 2024-02-29 13:16:37 -05:00
psychedelicious
5873900410 chore: lint 2024-02-29 13:16:37 -05:00
psychedelicious
0f335bef5a chore: ruff 2024-02-29 13:16:37 -05:00
psychedelicious
8958e820c8 feat(nodes): update invocation context for mm2, update nodes model usage 2024-02-29 13:16:37 -05:00
Brandon Rising
7a36cd2832 Raise InvalidModelConfigException when unable to detect load class in ModelLoader 2024-02-29 13:16:37 -05:00
Brandon Rising
5728da5132 Update _get_hf_load_class to support clipvision models 2024-02-29 13:16:37 -05:00
Brandon Rising
aa5d124d70 References to context.services.model_manager.store.get_model can only accept keys, remove invalid assertion 2024-02-29 13:16:37 -05:00
Brandon Rising
5cc73ec5dd Remove references to model_records service, change submodel property on ModelInfo to submodel_type to support new params in model manager 2024-02-29 13:16:37 -05:00
Lincoln Stein
ad9f8542f2 improve swagger documentation 2024-02-29 13:16:37 -05:00
Lincoln Stein
1d95fe6116 fix a number of typechecking errors 2024-02-29 13:16:37 -05:00
Lincoln Stein
6e91d5baaf add route for model conversion from safetensors to diffusers
- Begin to add SwaggerUI documentation for AnyModelConfig and other
  discriminated Unions.
2024-02-29 13:16:37 -05:00
Lincoln Stein
93fb2d1a55 add a JIT download_and_cache() call to the model installer 2024-02-29 13:16:37 -05:00
Lincoln Stein
195768c9ee add back the heuristic_import() method and extend repo_ids to arbitrary file paths 2024-02-29 13:16:37 -05:00
Lincoln Stein
d56337f2d8 make model manager v2 ready for PR review
- Replace legacy model manager service with the v2 manager.

- Update invocations to use new load interface.

- Fixed many but not all type checking errors in the invocations. Most
  were unrelated to model manager

- Updated routes. All the new routes live under the route tag
  `model_manager_v2`. To avoid confusion with the old routes,
  they have the URL prefix `/api/v2/models`. The old routes
  have been de-registered.

- Added a pytest for the loader.

- Updated documentation in contributing/MODEL_MANAGER.md
2024-02-29 13:16:37 -05:00
Lincoln Stein
721ff58e44 consolidate model manager parts into a single class 2024-02-29 13:16:37 -05:00
Lincoln Stein
8f1b7355df probe for required encoder for IPAdapters and add to config 2024-02-29 13:16:37 -05:00
Lincoln Stein
dbd2f8dc5f fix invokeai_configure script to work with new mm; rename CLIs 2024-02-29 13:16:37 -05:00
Lincoln Stein
49df4fa120 BREAKING CHANGES: invocations now require model key, not base/type/name
- Implement new model loader and modify invocations and embeddings

- Finish implementation loaders for all models currently supported by
  InvokeAI.

- Move lora, textual_inversion, and model patching support into
  backend/embeddings.

- Restore support for model cache statistics collection (a little ugly,
  needs work).

- Fixed up invocations that load and patch models.

- Move seamless and silencewarnings utils into better location
2024-02-29 13:16:37 -05:00
Lincoln Stein
92843d55eb Multiple refinements on loaders:
- Cache stat collection enabled.
- Implemented ONNX loading.
- Add ability to specify the repo version variant in installer CLI.
- If caller asks for a repo version that doesn't exist, will fall back
  to empty version rather than raising an error.
2024-02-29 13:16:37 -05:00
Lincoln Stein
fdbd288956 added textual inversion and lora loaders 2024-02-29 13:16:36 -05:00
Lincoln Stein
c0dabb5255 loaders for main, controlnet, ip-adapter, clipvision and t2i 2024-02-29 13:16:36 -05:00
Lincoln Stein
e242fe41f2 model loading and conversion implemented for vaes 2024-02-29 13:16:36 -05:00
Lincoln Stein
231c12fd1e add ram cache module and support files 2024-02-29 13:16:36 -05:00
Lincoln Stein
66e2d1b346 add concept of repo variant 2024-02-29 13:16:36 -05:00
psychedelicious
55147fbb7e tests(ui): add parseFieldType.test.ts 2024-02-29 13:16:36 -05:00
psychedelicious
c99e264bde feat(ui): add more types of FieldParseError
Unfortunately you cannot test for both a specific type of error and match its message. Splitting the error classes makes it easier to test expected error conditions.
2024-02-29 13:16:36 -05:00
psychedelicious
62c3687a9a feat(ui): add vitest
- Add vitest.
- Consolidate vite configs into single file (easier to config everything based on env for testing)
2024-02-29 13:16:36 -05:00
psychedelicious
c7f1fad398 feat(ui): workflow schema v3 (WIP)
The changes aim to deduplicate data between workflows and node templates, decoupling workflows from internal implementation details. A good amount of data that was needlessly duplicated from the node template to the workflow is removed.

These changes substantially reduce the file size of workflows (and therefore the images with embedded workflows):

- Default T2I SD1.5 workflow JSON is reduced from 23.7kb (798 lines) to 10.9kb (407 lines).
- Default tiled upscale workflow JSON is reduced from 102.7kb (3341 lines) to 51.9kb (1774 lines).

The trade-off is that we need to reference node templates to get things like the field type and other things. In practice, this is a non-issue, because we need a node template to do anything with a node anyways.

- Field types are not included in the workflow. They are always pulled from the node templates.

The field type is now properly an internal implementation detail and we can change it as needed. Previously this would require a migration for the workflow itself. With the v3 schema, the structure of a field type is an internal implementation detail that we are free to change as we see fit.

- Workflow nodes no long have an `outputs` property and there is no longer such a thing as a `FieldOutputInstance`. These are only on the templates.

These were never referenced at a time when we didn't also have the templates available, and there'd be no reason to do so.

- Node width and height are no longer stored in the node.

These weren't used. Also, per https://reactflow.dev/api-reference/types/node, we shouldn't be programmatically changing these properties. A future enhancement can properly add node resizing.

- `nodeTemplates` slice is merged back into `nodesSlice` as `nodes.templates`. Turns out it's just a hassle having these separate in separate slices.

- Workflow migration logic updated to support the new schema. V1 workflows migrate all the way to v3 now.

- Changes throughout the nodes code to accommodate the above changes.
2024-02-29 13:16:36 -05:00
psychedelicious
0540e6fb0d chore(ui): regen types 2024-02-29 13:16:36 -05:00
psychedelicious
179aa1de63 feat(nodes): add more missing exports to invocation_api
Crawled through a few custom nodes to figure out what I had missed.
2024-02-29 13:16:36 -05:00
psychedelicious
acc50d9bd2 chore(nodes): "SAMPLER_NAME_VALUES" -> "SCHEDULER_NAME_VALUES"
This was named inaccurately.
2024-02-29 13:16:36 -05:00
psychedelicious
54d92cb246 chore(nodes): remove deprecation logic for nodes API 2024-02-29 13:16:36 -05:00
psychedelicious
17ed6cc82f chore(nodes): export model-related objects from invocation_api 2024-02-29 13:16:36 -05:00
psychedelicious
5927ab9c36 chore(backend): rename ModelInfo -> LoadedModelInfo
We have two different classes named `ModelInfo` which might need to be used by API consumers. We need to export both but have to deal with this naming collision.

The `ModelInfo` I've renamed here is the one that is returned when a model is loaded. It's the object least likely to be used by API consumers.
2024-02-29 13:16:36 -05:00
psychedelicious
08636e42af feat(nodes): use LATENT_SCALE_FACTOR in primitives.py, noise.py
- LatentsOutput.build
- NoiseOutput.build
- Noise.width, Noise.height multiple_of
2024-02-29 13:16:36 -05:00
psychedelicious
2d74a39810 feat(nodes): extract LATENT_SCALE_FACTOR to constants.py 2024-02-29 13:16:36 -05:00
psychedelicious
bcc57dc886 feat(nodes): use TemporaryDirectory to handle ephemeral storage in ObjectSerializerDisk
Replace `delete_on_startup: bool` & associated logic with `ephemeral: bool` and `TemporaryDirectory`.

The temp dir is created inside of `output_dir`. For example, if `output_dir` is `invokeai/outputs/tensors/`, then the temp dir might be `invokeai/outputs/tensors/tmpvj35ht7b/`.

The temp dir is cleaned up when the service is stopped, or when it is GC'd if not properly stopped.

In the event of a catastrophic crash where the temp files are not cleaned up, the user can delete the tempdir themselves.

This situation may not occur in normal use, but if you kill the process, python cannot clean up the temp dir itself. This includes running the app in a debugger and killing the debugger process - something I do relatively often.

Tests updated.
2024-02-29 13:16:36 -05:00
psychedelicious
cda9ab7933 tests: test ObjectSerializerDisk class name extraction 2024-02-29 13:16:36 -05:00
psychedelicious
dc003a4bac chore(nodes): update ObjectSerializerForwardCache docstring 2024-02-29 13:16:36 -05:00
psychedelicious
e464804696 chore(nodes): fix pyright ignore 2024-02-29 13:16:36 -05:00
psychedelicious
6b5f01ed3f tidy(nodes): "latents" -> "obj" 2024-02-29 13:16:36 -05:00
psychedelicious
c05c3e5a7b tidy(nodes): do not store unnecessarily store invoker 2024-02-29 13:16:36 -05:00
psychedelicious
d202243c62 feat(nodes): make delete on startup configurable for obj serializer
- The default is to not delete on startup - feels safer.
- The two services using this class _do_ delete on startup.
- The class has "ephemeral" removed from its name.
- Tests & app updated for this change.
2024-02-29 13:16:36 -05:00
psychedelicious
7e04f2bff9 fix(nodes): use metadata/board_id if provided by user, overriding WithMetadata/WithBoard-provided values 2024-02-29 13:16:36 -05:00
psychedelicious
0282f477b6 tidy(nodes): clarify comment 2024-02-29 13:16:36 -05:00
psychedelicious
9983eddc01 Revert "feat(nodes): use LATENT_SCALE_FACTOR const in tensor output builders"
This reverts commit ef18fc546560277302f3886e456da9a47e8edce0.
2024-02-29 13:16:36 -05:00
psychedelicious
b62be80762 feat(nodes): use LATENT_SCALE_FACTOR const in tensor output builders 2024-02-29 13:16:36 -05:00
psychedelicious
62db617b41 tests: fix broken tests 2024-02-29 13:16:36 -05:00
psychedelicious
6905f18c08 tidy(nodes): minor spelling correction 2024-02-29 13:16:36 -05:00
psychedelicious
62bbfa7b5a tests: add object serializer tests
These test both object serializer and its forward cache implementation.
2024-02-29 13:16:36 -05:00
psychedelicious
27d7a1731b feat(nodes): allow _delete_all in obj serializer to be called at any time
`_delete_all` logged how many items it deleted, and had to be called _after_ service start bc it needed access to logger.

Move the logger call to the startup method and return the the deleted stats from `_delete_all`. This lets `_delete_all` be called at any time.
2024-02-29 13:16:36 -05:00
psychedelicious
787510a65b tidy(nodes): remove object serializer on_saved
It's unused.
2024-02-29 13:16:36 -05:00
psychedelicious
d9dc5d58be revert(nodes): revert making tensors/conditioning use item storage
Turns out they are just different enough in purpose that the implementations would be rather unintuitive. I've made a separate ObjectSerializer service to handle tensors and conditioning.

Refined the class a bit too.
2024-02-29 13:16:36 -05:00
psychedelicious
614f0e8086 feat(nodes): support custom exception in ephemeral disk storage 2024-02-29 13:16:36 -05:00
psychedelicious
723009e163 feat(nodes): support custom save and load functions in ItemStorageEphemeralDisk 2024-02-29 13:16:36 -05:00
psychedelicious
abdc87d5fc feat(nodes): create helper function to generate the item ID 2024-02-29 13:16:36 -05:00
psychedelicious
7cb8e29726 feat(nodes): use ItemStorageABC for tensors and conditioning
Turns out `ItemStorageABC` was almost identical to `PickleStorageBase`. Instead of maintaining separate classes, we can use `ItemStorageABC` for both.

There's only one change needed - the `ItemStorageABC.set` method must return the newly stored item's ID. This allows us to let the service handle the responsibility of naming the item, but still create the requisite output objects during node execution.

The naming implementation is improved here. It extracts the name of the generic and appends a UUID to that string when saving items.
2024-02-29 13:16:36 -05:00
psychedelicious
f593959bea tidy(nodes): do not refer to files as latents in PickleStorageTorch (again) 2024-02-29 13:16:36 -05:00
psychedelicious
c7218dc130 feat(nodes): ItemStorageABC typevar no longer bound to pydantic.BaseModel
This bound is totally unnecessary. There's no requirement for any implementation of `ItemStorageABC` to work only on pydantic models.
2024-02-29 13:16:36 -05:00
psychedelicious
ebc3a24d0d fix(nodes): add super init to PickleStorageTorch 2024-02-29 13:16:36 -05:00
psychedelicious
315681b491 tidy(nodes): do not refer to files as latents in PickleStorageTorch 2024-02-29 13:16:36 -05:00
psychedelicious
0c149cbd3b feat(nodes): replace latents service with tensors and conditioning services
- New generic class `PickleStorageBase`, implements the same API as `LatentsStorageBase`, use for storing non-serializable data via pickling
- Implementation `PickleStorageTorch` uses `torch.save` and `torch.load`, same as `LatentsStorageDisk`
- Add `tensors: PickleStorageBase[torch.Tensor]` to `InvocationServices`
- Add `conditioning: PickleStorageBase[ConditioningFieldData]` to `InvocationServices`
- Remove `latents` service and all `LatentsStorage` classes
- Update `InvocationContext` and all usage of old `latents` service to use the new services/context wrapper methods
2024-02-29 13:16:36 -05:00
psychedelicious
3563d4ecf7 tidy(nodes): delete onnx.py
It doesn't work and keeping it updated to prevent the app from starting was getting tedious. Deleted.
2024-02-29 13:16:36 -05:00
psychedelicious
c4ea96dec2 fix(nodes): rearrange fields.py to avoid needing forward refs 2024-02-29 13:16:36 -05:00
psychedelicious
06d0232841 tidy(nodes): remove unnecessary, shadowing class attr declarations 2024-02-29 13:16:36 -05:00
psychedelicious
bb8c71f706 feat(ui): revise graphs to not use LinearUIOutputInvocation
See this comment for context: https://github.com/invoke-ai/InvokeAI/pull/5491#discussion_r1480760629

- Remove this now-unnecessary node from all graphs
- Update graphs' terminal image-outputting nodes' `is_intermediate` and `board` fields appropriately
- Add util function to prepare the `board` field, tidy the utils
- Update `socketInvocationComplete` listener to work correctly with this change

I've manually tested all graph permutations that were changed (I think this is all...) to ensure images go to the gallery as expected:
- ad-hoc upscaling
- t2i w/ sd1.5
- t2i w/ sd1.5 & hrf
- t2i w/ sdxl
- t2i w/ sdxl + refiner
- i2i w/ sd1.5
- i2i w/ sdxl
- i2i w/ sdxl + refiner
- canvas t2i w/ sd1.5
- canvas t2i w/ sdxl
- canvas t2i w/ sdxl + refiner
- canvas i2i w/ sd1.5
- canvas i2i w/ sdxl
- canvas i2i w/ sdxl + refiner
- canvas inpaint w/ sd1.5
- canvas inpaint w/ sdxl
- canvas inpaint w/ sdxl + refiner
- canvas outpaint w/ sd1.5
- canvas outpaint w/ sdxl
- canvas outpaint w/ sdxl + refiner
2024-02-29 13:16:36 -05:00
psychedelicious
c16f77bb23 chore(ui): regen types 2024-02-29 13:16:36 -05:00
psychedelicious
1e4b953ccd feat(nodes): add WithBoard field helper class
This class works the same way as `WithMetadata` - it simply adds a `board` field to the node. The context wrapper function is able to pull the board id from this. This allows image-outputting nodes to get a board field "for free", and have their outputs automatically saved to it.

This is a breaking change for node authors who may have a field called `board`, because it makes `board` a reserved field name. I'll look into how to avoid this - maybe by naming this invoke-managed field `_board` to avoid collisions?

Supporting changes:
- `WithBoard` is added to all image-outputting nodes, giving them the ability to save to board.
- Unused, duplicate `WithMetadata` and `WithWorkflow` classes are deleted from `baseinvocation.py`. The "real" versions are in `fields.py`.
- Remove `LinearUIOutputInvocation`. Now that all nodes that output images also have a `board` field by default, this node is no longer necessary. See comment here for context: https://github.com/invoke-ai/InvokeAI/pull/5491#discussion_r1480760629
- Without `LinearUIOutputInvocation`, the `ImagesInferface.update` method is no longer needed, and removed.

Note: This commit does not bump all node versions. I will ensure that is done correctly before merging the PR of which this commit is a part.

Note: A followup commit will implement the frontend changes to support this change.
2024-02-29 13:16:36 -05:00
psychedelicious
d6ce901ad2 remove unused configdict import 2024-02-29 13:16:36 -05:00
psychedelicious
060038a8c0 fix(ui): remove original l2i node in HRF graph 2024-02-29 13:16:36 -05:00
psychedelicious
e38d275e20 fix(nodes): do not freeze or cache config in context wrapper
- The config is already cached by the config class's `get_config()` method.
- The config mutates itself in its `root_path` property getter. Freezing the class makes any attempt to grab a path from the config error. Unfortunately this means we cannot easily freeze the class without fiddling with the inner workings of `InvokeAIAppConfig`, which is outside the scope here.
2024-02-29 13:16:36 -05:00
psychedelicious
3fea7a6f00 feat(nodes): context.data -> context._data 2024-02-29 13:16:36 -05:00
psychedelicious
57ae23b222 feat(nodes): context.__services -> context._services 2024-02-29 13:16:36 -05:00
psychedelicious
10a4f1df8a feat(nodes): cache invocation interface config 2024-02-29 13:16:36 -05:00
psychedelicious
0fde0d1ff7 feat(nodes): do not hide services in invocation context interfaces 2024-02-29 13:16:36 -05:00
psychedelicious
0ff466ebc4 fix(nodes): restore missing context type annotations 2024-02-29 13:16:36 -05:00
psychedelicious
c3bfb4a38f tests(nodes): fix mock InvocationContext 2024-02-29 13:16:36 -05:00
psychedelicious
a976130899 chore(nodes): add comments for ConfigInterface 2024-02-29 13:16:36 -05:00
psychedelicious
fcfc0c9a94 feat(nodes): export more things from `invocation_api" 2024-02-29 13:16:36 -05:00
psychedelicious
42c99efddf feat(nodes): add boards interface to invocation context 2024-02-29 13:16:36 -05:00
psychedelicious
87d28b2519 fix(nodes): restore type annotations for InvocationContext 2024-02-29 13:16:36 -05:00
psychedelicious
e600f495a2 feat(nodes): do not freeze InvocationContextData, prevents it from being subclassesd 2024-02-29 13:16:36 -05:00
psychedelicious
e4bf66ef5b feat: tweak pyright config 2024-02-29 13:16:36 -05:00
psychedelicious
4e266e7466 feat(nodes): create invocation_api.py
This is the public API for invocations.

Everything a custom node might need should be re-exported from this file.
2024-02-29 13:16:36 -05:00
psychedelicious
26b17d778d feat(nodes): move ConditioningFieldData to conditioning_data.py 2024-02-29 13:16:35 -05:00
psychedelicious
1ca6c0798f tests: fix missing arg for InvocationContext 2024-02-29 13:16:35 -05:00
psychedelicious
2515a2dffd feat(nodes): restore previous invocation context methods with deprecation warnings 2024-02-29 13:16:35 -05:00
psychedelicious
cc4a4f1275 chore: ruff 2024-02-29 13:16:35 -05:00
psychedelicious
c58951dfcc feat(nodes): tidy invocation_context.py, improve comments 2024-02-29 13:16:35 -05:00
psychedelicious
8dc1207790 tests: fix tests for new invocation context 2024-02-29 13:16:35 -05:00
psychedelicious
248176604f docs: update INVOCATIONS.md 2024-02-29 13:16:35 -05:00
psychedelicious
2254a0c078 feat(nodes): update all invocations to use new invocation context
Update all invocations to use the new context. The changes are all fairly simple, but there are a lot of them.

Supporting minor changes:
- Patch bump for all nodes that use the context
- Update invocation processor to provide new context
- Minor change to `EventServiceBase` to accept a node's ID instead of the dict version of a node
- Minor change to `ModelManagerService` to support the new wrapped context
- Fanagling of imports to avoid circular dependencies
2024-02-29 13:16:35 -05:00
psychedelicious
ff30ec4746 feat: add pyright config
I was having issues with mypy bother over- and under-reporting certain problems. I've added a pyright config.
2024-02-29 13:16:35 -05:00
psychedelicious
7657c361a3 feat(nodes): restricts invocation context power
Creates a low-power `InvocationContext` with simplified methods and data.

See `invocation_context.py` for detailed comments.
2024-02-29 13:16:35 -05:00
psychedelicious
c3f0d2e273 tidy(nodes): move all field things to fields.py
Unfortunately, this is necessary to prevent circular imports at runtime.
2024-02-29 13:16:35 -05:00
Васянатор
63ab5ff5a2 translationBot(ui): update translation (Russian)
Currently translated at 98.3% (1398 of 1422 strings)

Co-authored-by: Васянатор <ilabulanov339@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/ru/
Translation: InvokeAI/Web UI
2024-02-29 23:27:36 +11:00
Samantha Morello
9a8a9c5848 translationBot(ui): update translation (Italian)
Currently translated at 98.0% (1441 of 1470 strings)

Co-authored-by: Samantha Morello <tildsart@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/it/
Translation: InvokeAI/Web UI
2024-02-29 23:27:36 +11:00
Alexander Eichhorn
1a3ffb6e94 translationBot(ui): update translation (German)
Currently translated at 80.4% (1183 of 1470 strings)

Co-authored-by: Alexander Eichhorn <pfannkuchensack@einfach-doof.de>
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/de/
Translation: InvokeAI/Web UI
2024-02-29 23:27:36 +11:00
skunkworxdark
3a09bceea4 Update communityNodes.md
Updated description of metadata nodes
2024-02-26 14:20:09 -05:00
Riccardo Giovanetti
2ec6b51d8b translationBot(ui): update translation (Italian)
Currently translated at 97.2% (1430 of 1470 strings)

Co-authored-by: Riccardo Giovanetti <riccardo.giovanetti@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/it/
Translation: InvokeAI/Web UI
2024-02-26 17:41:00 +11:00
B N
34b0ea20dc translationBot(ui): update translation (German)
Currently translated at 80.3% (1181 of 1470 strings)

translationBot(ui): update translation (German)

Currently translated at 80.1% (1178 of 1470 strings)

Co-authored-by: B N <berndnieschalk@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/de/
Translation: InvokeAI/Web UI
2024-02-26 17:41:00 +11:00
Alexander Eichhorn
9986fce1a6 translationBot(ui): update translation (German)
Currently translated at 80.0% (1176 of 1470 strings)

Co-authored-by: Alexander Eichhorn <pfannkuchensack@einfach-doof.de>
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/de/
Translation: InvokeAI/Web UI
2024-02-23 07:57:15 +11:00
Riccardo Giovanetti
228f1d7f62 translationBot(ui): update translation (Italian)
Currently translated at 95.6% (1406 of 1470 strings)

translationBot(ui): update translation (Italian)

Currently translated at 93.9% (1381 of 1470 strings)

Co-authored-by: Riccardo Giovanetti <riccardo.giovanetti@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/it/
Translation: InvokeAI/Web UI
2024-02-23 07:57:15 +11:00
B N
01a6378dc1 translationBot(ui): update translation (German)
Currently translated at 78.8% (1159 of 1470 strings)

Co-authored-by: B N <berndnieschalk@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/de/
Translation: InvokeAI/Web UI
2024-02-23 07:57:15 +11:00
Hosted Weblate
e01769294f translationBot(ui): update translation files
Updated by "Cleanup translation files" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/
Translation: InvokeAI/Web UI
2024-02-20 22:33:03 +11:00
chainchompa
16aa261e28 updated tooltip popovers (#5751)
## What type of PR is this? (check all applicable)

- [ ] Refactor
- [ ] Feature
- [ ] Bug Fix
- [X] Optimization
- [ ] Documentation Update
- [ ] Community Node Submission


## Have you discussed this change with the InvokeAI team?
- [X] Yes
- [ ] No, because:

      
## Have you updated all relevant documentation?
- [ ] Yes
- [ ] No


## Description
Added new tooltip popovers and updated copy of existing ones

## Related Tickets & Documents

<!--
For pull requests that relate or close an issue, please include them
below. 

For example having the text: "closes #1234" would connect the current
pull
request to issue 1234.  And when we merge the pull request, Github will
automatically close the issue.
-->

- Related Issue #
- Closes #

## QA Instructions, Screenshots, Recordings

<!-- 
Please provide steps on how to test changes, any hardware or 
software specifications as well as any other pertinent information. 
-->

## Merge Plan

<!--
A merge plan describes how this PR should be handled after it is
approved.

Example merge plans:
- "This PR can be merged when approved"
- "This must be squash-merged when approved"
- "DO NOT MERGE - I will rebase and tidy commits before merging"
- "#dev-chat on discord needs to be advised of this change when it is
merged"

A merge plan is particularly important for large PRs or PRs that touch
the
database in any way.
-->

## Added/updated tests?

- [ ] Yes
- [ ] No : _please replace this line with details on why tests
      have not been included_

## [optional] Are there any post deployment tasks we need to perform?
2024-02-19 13:12:47 -05:00
chainchompa
1dabf18d14 Merge branch 'main' into chainchompa/tooltip-popovers 2024-02-19 13:04:15 -05:00
Jennifer Player
115d92b1ae updated copy 2024-02-19 12:50:35 -05:00
Jennifer Player
f0d4c71960 updated tooltip popovers 2024-02-19 12:50:11 -05:00
gogurtenjoyer
3e48edda6f add latent-upscale to communityNodes.md (#5728)
Adds the 'latent upscale' community node
2024-02-19 16:53:35 +00:00
Riccardo Giovanetti
716b584f03 translationBot(ui): update translation (Italian)
Currently translated at 97.1% (1384 of 1424 strings)

Co-authored-by: Riccardo Giovanetti <riccardo.giovanetti@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/it/
Translation: InvokeAI/Web UI
2024-02-19 08:18:33 +11:00
B N
d43b843c23 translationBot(ui): update translation (German)
Currently translated at 80.2% (1143 of 1424 strings)

Co-authored-by: B N <berndnieschalk@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/de/
Translation: InvokeAI/Web UI
2024-02-18 01:47:01 +11:00
psychedelicious
f36b5990ed fix(ui): do not provide auth headers for openapi.json 2024-02-15 10:38:26 -05:00
Millun Atluri
5706237ec7 {release} 3.7.0 (#5727)
## What type of PR is this? (check all applicable)

Release - Invoke 3.7.0

## Have you discussed this change with the InvokeAI team?
- [X] Yes
- [ ] No, because:

      
## Have you updated all relevant documentation?
- [X] Yes
- [ ] No


## Description
Invoke 3.7.0 Release

## QA Instructions, Screenshots, Recordings
Test Installer: 

[InvokeAI-installer-v3.7.0.zip](https://github.com/invoke-ai/InvokeAI/files/14298200/InvokeAI-installer-v3.7.0.zip)

<!-- 
Please provide steps on how to test changes, any hardware or 
software specifications as well as any other pertinent information. 
-->

## Merge Plan
Merge once approved
<!--
A merge plan describes how this PR should be handled after it is
approved.

Example merge plans:
- "This PR can be merged when approved"
- "This must be squash-merged when approved"
- "DO NOT MERGE - I will rebase and tidy commits before merging"
- "#dev-chat on discord needs to be advised of this change when it is
merged"

A merge plan is particularly important for large PRs or PRs that touch
the
database in any way.
-->

## Added/updated tests?

- [ ] Yes
- [X] No : _please replace this line with details on why tests
      have not been included_

## [optional] Are there any post deployment tasks we need to perform?
1. Release on PyPi
2. Release on GitHub
3. Announce on Discord
2024-02-15 07:59:20 -07:00
Millun Atluri
163b22a7b3 {release} 3.7.0 2024-02-15 07:34:31 -07:00
37 changed files with 845 additions and 303 deletions

View File

@@ -32,6 +32,7 @@ To use a community workflow, download the the `.json` node graph file and load i
+ [Image to Character Art Image Nodes](#image-to-character-art-image-nodes)
+ [Image Picker](#image-picker)
+ [Image Resize Plus](#image-resize-plus)
+ [Latent Upscale](#latent-upscale)
+ [Load Video Frame](#load-video-frame)
+ [Make 3D](#make-3d)
+ [Mask Operations](#mask-operations)
@@ -290,6 +291,13 @@ View:
</br><img src="https://raw.githubusercontent.com/VeyDlin/image-resize-plus-node/master/.readme/node.png" width="500" />
--------------------------------
### Latent Upscale
**Description:** This node uses a small (~2.4mb) model to upscale the latents used in a Stable Diffusion 1.5 or Stable Diffusion XL image generation, rather than the typical interpolation method, avoiding the traditional downsides of the latent upscale technique.
**Node Link:** [https://github.com/gogurtenjoyer/latent-upscale](https://github.com/gogurtenjoyer/latent-upscale)
--------------------------------
### Load Video Frame
@@ -346,12 +354,21 @@ See full docs here: https://github.com/skunkworxdark/Prompt-tools-nodes/edit/mai
**Description:** A set of nodes for Metadata. Collect Metadata from within an `iterate` node & extract metadata from an image.
- `Metadata Item Linked` - Allows collecting of metadata while within an iterate node with no need for a collect node or conversion to metadata node.
- `Metadata From Image` - Provides Metadata from an image.
- `Metadata To String` - Extracts a String value of a label from metadata.
- `Metadata To Integer` - Extracts an Integer value of a label from metadata.
- `Metadata To Float` - Extracts a Float value of a label from metadata.
- `Metadata To Scheduler` - Extracts a Scheduler value of a label from metadata.
- `Metadata Item Linked` - Allows collecting of metadata while within an iterate node with no need for a collect node or conversion to metadata node
- `Metadata From Image` - Provides Metadata from an image
- `Metadata To String` - Extracts a String value of a label from metadata
- `Metadata To Integer` - Extracts an Integer value of a label from metadata
- `Metadata To Float` - Extracts a Float value of a label from metadata
- `Metadata To Scheduler` - Extracts a Scheduler value of a label from metadata
- `Metadata To Bool` - Extracts Bool types from metadata
- `Metadata To Model` - Extracts model types from metadata
- `Metadata To SDXL Model` - Extracts SDXL model types from metadata
- `Metadata To LoRAs` - Extracts Loras from metadata.
- `Metadata To SDXL LoRAs` - Extracts SDXL Loras from metadata
- `Metadata To ControlNets` - Extracts ControNets from metadata
- `Metadata To IP-Adapters` - Extracts IP-Adapters from metadata
- `Metadata To T2I-Adapters` - Extracts T2I-Adapters from metadata
- `Denoise Latents + Metadata` - This is an inherited version of the existing `Denoise Latents` node but with a metadata input and output.
**Node Link:** https://github.com/skunkworxdark/metadata-linked-nodes

View File

@@ -2,6 +2,7 @@
# which are imported/used before parse_args() is called will get the default config values instead of the
# values from the command line or config file.
import sys
from contextlib import asynccontextmanager
from invokeai.app.api.no_cache_staticfiles import NoCacheStaticFiles
from invokeai.version.invokeai_version import __version__
@@ -71,9 +72,25 @@ logger = InvokeAILogger.get_logger(config=app_config)
mimetypes.add_type("application/javascript", ".js")
mimetypes.add_type("text/css", ".css")
@asynccontextmanager
async def lifespan(app: FastAPI):
# Add startup event to load dependencies
ApiDependencies.initialize(config=app_config, event_handler_id=event_handler_id, logger=logger)
yield
# Shut down threads
ApiDependencies.shutdown()
# Create the app
# TODO: create this all in a method so configuration/etc. can be passed in?
app = FastAPI(title="Invoke - Community Edition", docs_url=None, redoc_url=None, separate_input_output_schemas=False)
app = FastAPI(
title="Invoke - Community Edition",
docs_url=None,
redoc_url=None,
separate_input_output_schemas=False,
lifespan=lifespan,
)
# Add event handler
event_handler_id: int = id(app)
@@ -96,18 +113,6 @@ app.add_middleware(
app.add_middleware(GZipMiddleware, minimum_size=1000)
# Add startup event to load dependencies
@app.on_event("startup")
async def startup_event() -> None:
ApiDependencies.initialize(config=app_config, event_handler_id=event_handler_id, logger=logger)
# Shut down threads
@app.on_event("shutdown")
async def shutdown_event() -> None:
ApiDependencies.shutdown()
# Include all routers
app.include_router(utilities.utilities_router, prefix="/api")
app.include_router(model_manager.model_manager_router, prefix="/api")

View File

@@ -1,17 +1,11 @@
from typing import Iterator, List, Optional, Tuple, Union
from typing import Iterator, List, Optional, Tuple, Union, cast
import torch
from compel import Compel, ReturnedEmbeddingsType
from compel.prompt_parser import Blend, Conjunction, CrossAttentionControlSubstitute, FlattenedPrompt, Fragment
from transformers import CLIPTextModel, CLIPTokenizer
from transformers import CLIPTextModel, CLIPTextModelWithProjection, CLIPTokenizer
from invokeai.app.invocations.fields import (
FieldDescriptions,
Input,
InputField,
OutputField,
UIComponent,
)
from invokeai.app.invocations.fields import FieldDescriptions, Input, InputField, OutputField, UIComponent
from invokeai.app.invocations.primitives import ConditioningOutput
from invokeai.app.services.shared.invocation_context import InvocationContext
from invokeai.app.util.ti_utils import generate_ti_list
@@ -25,12 +19,7 @@ from invokeai.backend.stable_diffusion.diffusion.conditioning_data import (
)
from invokeai.backend.util.devices import torch_dtype
from .baseinvocation import (
BaseInvocation,
BaseInvocationOutput,
invocation,
invocation_output,
)
from .baseinvocation import BaseInvocation, BaseInvocationOutput, invocation, invocation_output
from .model import ClipField
# unconditioned: Optional[torch.Tensor]
@@ -149,7 +138,7 @@ class SDXLPromptInvocationBase:
assert isinstance(tokenizer_model, CLIPTokenizer)
text_encoder_info = context.models.load(**clip_field.text_encoder.model_dump())
text_encoder_model = text_encoder_info.model
assert isinstance(text_encoder_model, CLIPTextModel)
assert isinstance(text_encoder_model, (CLIPTextModel, CLIPTextModelWithProjection))
# return zero on empty
if prompt == "" and zero_on_empty:
@@ -196,7 +185,8 @@ class SDXLPromptInvocationBase:
# Apply CLIP Skip after LoRA to prevent LoRA application from failing on skipped layers.
ModelPatcher.apply_clip_skip(text_encoder_model, clip_field.skipped_layers),
):
assert isinstance(text_encoder, CLIPTextModel)
assert isinstance(text_encoder, (CLIPTextModel, CLIPTextModelWithProjection))
text_encoder = cast(CLIPTextModel, text_encoder)
compel = Compel(
tokenizer=tokenizer,
text_encoder=text_encoder,

View File

@@ -228,16 +228,10 @@ class DownloadQueueService(DownloadQueueServiceBase):
except (OSError, HTTPError) as excp:
job.error_type = excp.__class__.__name__ + f"({str(excp)})"
job.error = traceback.format_exc()
try:
self._signal_job_error(job, excp)
except:
pass
self._signal_job_error(job, excp)
except DownloadJobCancelledException:
try:
self._signal_job_cancelled(job)
self._cleanup_cancelled_job(job)
except:
pass
self._signal_job_cancelled(job)
self._cleanup_cancelled_job(job)
finally:
job.job_ended = get_iso_timestamp()

View File

@@ -28,6 +28,7 @@ from typing import Callable, Optional, Set, Union
from pydantic import BaseModel, Field
from invokeai.app.services.config import InvokeAIAppConfig
from invokeai.backend.util.logging import InvokeAILogger
default_logger: Logger = InvokeAILogger.get_logger()
@@ -117,13 +118,10 @@ class ModelSearch(ModelSearchBase):
"""
models_found: Set[Path] = Field(default_factory=set)
scanned_dirs: Set[Path] = Field(default_factory=set)
pruned_paths: Set[Path] = Field(default_factory=set)
config: InvokeAIAppConfig = InvokeAIAppConfig.get_config()
def search_started(self) -> None:
self.models_found = set()
self.scanned_dirs = set()
self.pruned_paths = set()
if self.on_search_started:
self.on_search_started(self._directory)
@@ -139,53 +137,53 @@ class ModelSearch(ModelSearchBase):
def search(self, directory: Union[Path, str]) -> Set[Path]:
self._directory = Path(directory)
if not self._directory.is_absolute():
self._directory = self.config.models_path / self._directory
self.stats = SearchStats() # zero out
self.search_started() # This will initialize _models_found to empty
self._walk_directory(directory)
self._walk_directory(self._directory)
self.search_completed()
return self.models_found
def _walk_directory(self, path: Union[Path, str]) -> None:
for root, dirs, files in os.walk(path, followlinks=True):
# don't descend into directories that start with a "."
# to avoid the Mac .DS_STORE issue.
if str(Path(root).name).startswith("."):
self.pruned_paths.add(Path(root))
if any(Path(root).is_relative_to(x) for x in self.pruned_paths):
continue
def _walk_directory(self, path: Union[Path, str], max_depth: int = 20) -> None:
absolute_path = Path(path)
if (
len(absolute_path.parts) - len(self._directory.parts) > max_depth
or not absolute_path.exists()
or absolute_path.parent in self.models_found
):
return
entries = os.scandir(absolute_path.as_posix())
entries = [entry for entry in entries if not entry.name.startswith(".")]
dirs = [entry for entry in entries if entry.is_dir()]
file_names = [entry.name for entry in entries if entry.is_file()]
if any(
x in file_names
for x in [
"config.json",
"model_index.json",
"learned_embeds.bin",
"pytorch_lora_weights.bin",
"image_encoder.txt",
]
):
try:
self.model_found(absolute_path)
return
except KeyboardInterrupt:
raise
except Exception as e:
self.logger.warning(str(e))
return
self.stats.items_scanned += len(dirs) + len(files)
for d in dirs:
path = Path(root) / d
if path.parent in self.scanned_dirs:
self.scanned_dirs.add(path)
continue
if any(
(path / x).exists()
for x in [
"config.json",
"model_index.json",
"learned_embeds.bin",
"pytorch_lora_weights.bin",
"image_encoder.txt",
]
):
self.scanned_dirs.add(path)
try:
self.model_found(path)
except KeyboardInterrupt:
raise
except Exception as e:
self.logger.warning(str(e))
for n in file_names:
if n.endswith((".ckpt", ".bin", ".pth", ".safetensors", ".pt")):
try:
self.model_found(absolute_path / n)
except KeyboardInterrupt:
raise
except Exception as e:
self.logger.warning(str(e))
for f in files:
path = Path(root) / f
if path.parent in self.scanned_dirs:
continue
if path.suffix in {".ckpt", ".bin", ".pth", ".safetensors", ".pt"}:
try:
self.model_found(path)
except KeyboardInterrupt:
raise
except Exception as e:
self.logger.warning(str(e))
for d in dirs:
self._walk_directory(absolute_path / d)

View File

@@ -4,12 +4,12 @@ from __future__ import annotations
import pickle
from contextlib import contextmanager
from typing import Any, Dict, Iterator, List, Optional, Tuple
from typing import Any, Dict, Iterator, List, Optional, Tuple, Union
import numpy as np
import torch
from diffusers import OnnxRuntimeModel, UNet2DConditionModel
from transformers import CLIPTextModel, CLIPTokenizer
from transformers import CLIPTextModel, CLIPTextModelWithProjection, CLIPTokenizer
from invokeai.app.shared.models import FreeUConfig
from invokeai.backend.model_manager import AnyModel
@@ -168,7 +168,7 @@ class ModelPatcher:
def apply_ti(
cls,
tokenizer: CLIPTokenizer,
text_encoder: CLIPTextModel,
text_encoder: Union[CLIPTextModel, CLIPTextModelWithProjection],
ti_list: List[Tuple[str, TextualInversionModelRaw]],
) -> Iterator[Tuple[CLIPTokenizer, TextualInversionManager]]:
init_tokens_count = None
@@ -265,7 +265,7 @@ class ModelPatcher:
@contextmanager
def apply_clip_skip(
cls,
text_encoder: CLIPTextModel,
text_encoder: Union[CLIPTextModel, CLIPTextModelWithProjection],
clip_skip: int,
) -> None:
skipped_layers = []

View File

@@ -81,7 +81,7 @@
"outputs": "Ausgabe",
"data": "Daten",
"safetensors": "Safe-Tensors",
"outpaint": "Ausmalen",
"outpaint": "Outpaint (Außen ausmalen)",
"details": "Details",
"format": "Format",
"unknown": "Unbekannt",
@@ -110,17 +110,18 @@
"nextPage": "Nächste Seite",
"unknownError": "Unbekannter Fehler",
"unsaved": "Nicht gespeichert",
"aboutDesc": "Verwenden Sie Invoke für die Arbeit? Dann siehe hier:",
"aboutDesc": "Verwenden Sie Invoke für die Arbeit? Siehe hier:",
"localSystem": "Lokales System",
"orderBy": "Ordnen nach",
"saveAs": "Speicher als",
"saveAs": "Speichern als",
"updated": "Aktualisiert",
"copy": "Kopieren",
"aboutHeading": "Nutzen Sie Ihre kreative Energie"
"aboutHeading": "Nutzen Sie Ihre kreative Energie",
"toResolve": "Lösen"
},
"gallery": {
"generations": "Erzeugungen",
"showGenerations": "Zeige Erzeugnisse",
"showGenerations": "Zeige Ergebnisse",
"uploads": "Uploads",
"showUploads": "Zeige Uploads",
"galleryImageSize": "Bildgröße",
@@ -150,9 +151,9 @@
"problemDeletingImagesDesc": "Ein oder mehrere Bilder konnten nicht gelöscht werden",
"starImage": "Bild markieren",
"assets": "Ressourcen",
"unstarImage": "Markierung Entfernen",
"unstarImage": "Markierung entfernen",
"image": "Bild",
"deleteSelection": "Lösche markierte",
"deleteSelection": "Lösche Auswahl",
"dropToUpload": "$t(gallery.drop) zum hochladen",
"dropOrUpload": "$t(gallery.drop) oder hochladen",
"drop": "Ablegen",
@@ -590,10 +591,21 @@
"general": "Allgemein",
"hiresStrength": "High Res Stärke",
"hidePreview": "Verstecke Vorschau",
"showPreview": "Zeige Vorschau"
"showPreview": "Zeige Vorschau",
"aspect": "Seitenverhältnis",
"aspectRatio": "Seitenverhältnis",
"scheduler": "Planer",
"aspectRatioFree": "Frei",
"setToOptimalSizeTooLarge": "$t(parameters.setToOptimalSize) (kann zu groß sein)",
"lockAspectRatio": "Seitenverhältnis sperren",
"swapDimensions": "Seitenverhältnis umkehren",
"setToOptimalSize": "Optimiere Größe für Modell",
"useSize": "Maße übernehmen",
"remixImage": "Remix des Bilds erstellen",
"imageActions": "Weitere Bildaktionen"
},
"settings": {
"displayInProgress": "Bilder in Bearbeitung anzeigen",
"displayInProgress": "Zwischenbilder anzeigen",
"saveSteps": "Speichern der Bilder alle n Schritte",
"confirmOnDelete": "Bestätigen beim Löschen",
"displayHelpIcons": "Hilfesymbole anzeigen",
@@ -606,7 +618,34 @@
"useSlidersForAll": "Schieberegler für alle Optionen verwenden",
"showAdvancedOptions": "Erweiterte Optionen anzeigen",
"alternateCanvasLayout": "Alternatives Leinwand-Layout",
"clearIntermediatesDesc1": "Das Löschen der Zwischenprodukte setzt Leinwand und ControlNet zurück."
"clearIntermediatesDesc1": "Das Löschen der Zwischenbilder setzt Leinwand und ControlNet zurück.",
"favoriteSchedulers": "Lieblings-Planer",
"favoriteSchedulersPlaceholder": "Keine Planer favorisiert",
"generation": "Erzeugung",
"enableInformationalPopovers": "Info-Popouts anzeigen",
"shouldLogToConsole": "Konsole loggen",
"showProgressInViewer": "Zwischenbilder im Viewer anzeigen",
"clearIntermediatesDesc3": "Ihre Bilder werden nicht gelöscht.",
"clearIntermediatesWithCount_one": "Lösche {{count}} Zwischenbilder",
"clearIntermediatesWithCount_other": "Lösche {{count}} Zwischenbilder",
"reloadingIn": "Neuladen in",
"enableNodesEditor": "Nodes Editor aktivieren",
"autoChangeDimensions": "Breite/Höhe auf Modellstandard setzen",
"experimental": "Experimentell",
"intermediatesCleared_one": "{{count}} Zwischenbilder gelöscht",
"intermediatesCleared_other": "{{count}} Zwischenbilder gelöscht",
"enableInvisibleWatermark": "Unsichtbares Wasserzeichen aktivieren",
"general": "Allgemein",
"consoleLogLevel": "Protokollierungsstufe",
"clearIntermediatesDisabled": "Warteschlange muss leer sein, um Zwischenbilder zu löschen",
"developer": "Entwickler",
"antialiasProgressImages": "Zwischenbilder mit Anti-Alias",
"beta": "Beta",
"ui": "Benutzeroberfläche",
"clearIntermediatesDesc2": "Zwischenbilder sind Nebenprodukte der Erstellung. Sie zu löschen macht Festplattenspeicher frei.",
"clearIntermediates": "Zwischenbilder löschen",
"intermediatesClearedFailed": "Problem beim Löschen der Zwischenbilder",
"enableNSFWChecker": "Auf unangemessene Inhalte prüfen"
},
"toast": {
"tempFoldersEmptied": "Temp-Ordner geleert",
@@ -651,7 +690,9 @@
"problemCopyingCanvas": "Problem beim Kopieren der Leinwand",
"problemCopyingCanvasDesc": "Kann Basis-Layer nicht exportieren",
"problemDownloadingCanvas": "Problem beim Herunterladen der Leinwand",
"setAsCanvasInitialImage": "Als Ausgangsbild gesetzt"
"setAsCanvasInitialImage": "Als Ausgangsbild gesetzt",
"addedToBoard": "Dem Board hinzugefügt",
"loadedWithWarnings": "Workflow mit Warnungen geladen"
},
"tooltip": {
"feature": {
@@ -733,23 +774,23 @@
"accessibility": {
"modelSelect": "Modell-Auswahl",
"uploadImage": "Bild hochladen",
"previousImage": "Voriges Bild",
"previousImage": "Vorheriges Bild",
"useThisParameter": "Benutze diesen Parameter",
"copyMetadataJson": "Kopiere Metadaten JSON",
"copyMetadataJson": "Kopiere JSON-Metadaten",
"zoomIn": "Vergrößern",
"rotateClockwise": "Im Uhrzeigersinn drehen",
"flipHorizontally": "Horizontal drehen",
"flipVertically": "Vertikal drehen",
"modifyConfig": "Optionen einstellen",
"toggleAutoscroll": "Auroscroll ein/ausschalten",
"toggleLogViewer": "Log Betrachter ein/ausschalten",
"toggleLogViewer": "Log-Betrachter ein/ausschalten",
"showOptionsPanel": "Seitenpanel anzeigen",
"reset": "Zurücksetzten",
"nextImage": "Nächstes Bild",
"zoomOut": "Verkleinern",
"rotateCounterClockwise": "Gegen den Uhrzeigersinn drehen",
"showGalleryPanel": "Galeriefenster anzeigen",
"exitViewer": "Betrachten beenden",
"showGalleryPanel": "Galerie-Panel anzeigen",
"exitViewer": "Betrachter beenden",
"menu": "Menü",
"loadMore": "Mehr laden",
"invokeProgressBar": "Invoke Fortschrittsanzeige",
@@ -759,7 +800,7 @@
"about": "Über"
},
"boards": {
"autoAddBoard": "Automatisches Hinzufügen zum Ordner",
"autoAddBoard": "Automatisches Hinzufügen zum Board",
"topMessage": "Dieser Ordner enthält Bilder die in den folgenden Funktionen verwendet werden:",
"move": "Bewegen",
"menuItemAutoAdd": "Auto-Hinzufügen zu diesem Ordner",
@@ -768,13 +809,13 @@
"noMatching": "Keine passenden Ordner",
"selectBoard": "Ordner aussuchen",
"cancel": "Abbrechen",
"addBoard": "Ordner hinzufügen",
"addBoard": "Board hinzufügen",
"uncategorized": "Ohne Kategorie",
"downloadBoard": "Ordner runterladen",
"changeBoard": "Ordner wechseln",
"loading": "Laden...",
"clearSearch": "Suche leeren",
"bottomMessage": "Durch das Löschen dieses Ordners und seiner Bilder werden alle Funktionen zurückgesetzt, die sie derzeit verwenden.",
"bottomMessage": "Löschen des Boards und seiner Bilder setzt alle Funktionen zurück, die sie gerade verwenden.",
"deleteBoardOnly": "Nur Ordner löschen",
"deleteBoard": "Löschen Ordner",
"deleteBoardAndImages": "Löschen Ordner und Bilder",
@@ -820,7 +861,7 @@
"colorMap": "Farbe",
"lowThreshold": "Niedrige Schwelle",
"highThreshold": "Hohe Schwelle",
"toggleControlNet": "Schalten ControlNet um",
"toggleControlNet": "Dieses ControlNet ein- oder ausschalten",
"delete": "Löschen",
"controlAdapter_one": "Control Adapter",
"controlAdapter_other": "Control Adapter",
@@ -865,18 +906,23 @@
"maxFaces": "Maximale Anzahl Gesichter",
"resizeSimple": "Größe ändern (einfach)",
"large": "Groß",
"modelSize": "Modell Größe",
"modelSize": "Modellgröße",
"small": "Klein",
"base": "Basis",
"depthAnything": "Depth Anything / \"Tiefe irgendwas\"",
"depthAnythingDescription": "Erstellung einer Tiefenkarte mit der Depth Anything-Technik"
"depthAnything": "Depth Anything",
"depthAnythingDescription": "Erstellung einer Tiefenkarte mit der Depth-Anything-Technik",
"face": "Gesicht",
"body": "Körper",
"hands": "Hände",
"dwOpenpose": "DW Openpose",
"dwOpenposeDescription": "Posenschätzung mit DW Openpose"
},
"queue": {
"status": "Status",
"cancelTooltip": "Aktuellen Aufgabe abbrechen",
"queueEmpty": "Warteschlange leer",
"in_progress": "In Arbeit",
"queueFront": "An den Anfang der Warteschlange tun",
"queueFront": "Am Anfang der Warteschlange einreihen",
"completed": "Fertig",
"queueBack": "In die Warteschlange",
"clearFailed": "Probleme beim leeren der Warteschlange",
@@ -904,7 +950,7 @@
"batchValues": "Stapel Werte",
"queueCountPrediction": "{{promptsCount}} Prompts × {{iterations}} Iterationen -> {{count}} Generationen",
"queuedCount": "{{pending}} wartenden Elemente",
"clearQueueAlertDialog": "Die Warteschlange leeren, stoppt den aktuellen Prozess und leert die Warteschlange komplett.",
"clearQueueAlertDialog": "\"Die Warteschlange leeren\" stoppt den aktuellen Prozess und leert die Warteschlange komplett.",
"completedIn": "Fertig in",
"cancelBatchSucceeded": "Stapel abgebrochen",
"cancelBatch": "Stapel stoppen",
@@ -913,20 +959,20 @@
"cancelBatchFailed": "Problem beim Abbruch vom Stapel",
"clearQueueAlertDialog2": "Warteschlange wirklich leeren?",
"pruneSucceeded": "{{item_count}} abgeschlossene Elemente aus der Warteschlange entfernt",
"pauseSucceeded": "Prozessor angehalten",
"pauseSucceeded": "Prozess angehalten",
"cancelFailed": "Problem beim Stornieren des Auftrags",
"pauseFailed": "Problem beim Anhalten des Prozessors",
"pauseFailed": "Problem beim Anhalten des Prozesses",
"front": "Vorne",
"pruneTooltip": "Bereinigen Sie {{item_count}} abgeschlossene Aufträge",
"resumeFailed": "Problem beim wieder aufnehmen von Prozessor",
"resumeFailed": "Problem beim Fortsetzen des Prozesses",
"pruneFailed": "Problem beim leeren der Warteschlange",
"pauseTooltip": "Pause von Prozessor",
"pauseTooltip": "Prozess anhalten",
"back": "Hinten",
"resumeSucceeded": "Prozessor wieder aufgenommen",
"resumeTooltip": "Prozessor wieder aufnehmen",
"resumeSucceeded": "Prozess wird fortgesetzt",
"resumeTooltip": "Prozess wieder aufnehmen",
"time": "Zeit",
"batchQueuedDesc_one": "{{count}} Eintrag ans {{direction}} der Wartschlange hinzugefügt",
"batchQueuedDesc_other": "{{count}} Einträge ans {{direction}} der Wartschlange hinzugefügt",
"batchQueuedDesc_one": "{{count}} Eintrag an {{direction}} der Wartschlange hinzugefügt",
"batchQueuedDesc_other": "{{count}} Einträge an {{direction}} der Wartschlange hinzugefügt",
"openQueue": "Warteschlange öffnen",
"batchFailedToQueue": "Fehler beim Einreihen in die Stapelverarbeitung",
"batchFieldValues": "Stapelverarbeitungswerte",
@@ -961,11 +1007,12 @@
"workflow": "Workflow",
"scheduler": "Planer",
"noRecallParameters": "Es wurden keine Parameter zum Abrufen gefunden",
"recallParameters": "Parameter wiederherstellen"
"recallParameters": "Parameter wiederherstellen",
"cfgRescaleMultiplier": "$t(parameters.cfgRescaleMultiplier)"
},
"popovers": {
"noiseUseCPU": {
"heading": "Nutze Prozessor rauschen",
"heading": "Nutze CPU-Rauschen",
"paragraphs": [
"Entscheidet, ob auf der CPU oder GPU Rauschen erzeugt wird.",
"Mit aktiviertem CPU-Rauschen wird ein bestimmter Seedwert das gleiche Bild auf jeder Maschine erzeugen.",
@@ -975,8 +1022,7 @@
"paramModel": {
"heading": "Modell",
"paragraphs": [
"Modell für die Entrauschungsschritte.",
"Verschiedene Modelle werden in der Regel so trainiert, dass sie sich auf die Erzeugung bestimmter Ästhetik und/oder Inhalte spezialisiert."
"Modell für die Entrauschungsschritte."
]
},
"paramIterations": {
@@ -1084,12 +1130,23 @@
"Wie stark wird das ControlNet das generierte Bild beeinflussen wird."
],
"heading": "Einfluss"
},
"paramScheduler": {
"paragraphs": [
"\"Planer\" definiert, wie iterativ Rauschen zu einem Bild hinzugefügt wird, oder wie ein Sample bei der Ausgabe eines Modells aktualisiert wird."
],
"heading": "Planer"
},
"imageFit": {
"paragraphs": [
"Reduziert das Ausgangsbild auf die Breite und Höhe des Ausgangsbildes. Empfohlen zu aktivieren."
]
}
},
"ui": {
"lockRatio": "Verhältnis sperren",
"hideProgressImages": "Verstecke Prozess Bild",
"showProgressImages": "Zeige Prozess Bild",
"hideProgressImages": "Fortschrittsbilder verbergen",
"showProgressImages": "Fortschrittsbilder anzeigen",
"swapSizes": "Tausche Größen"
},
"invocationCache": {
@@ -1287,7 +1344,19 @@
"vaeFieldDescription": "VAE Submodell.",
"unknownInput": "Unbekannte Eingabe: {{name}}",
"unknownNodeType": "Unbekannter Knotentyp",
"float": "Kommazahlen"
"float": "Kommazahlen",
"latentsPolymorphic": "Latents Polymorph",
"integerPolymorphicDescription": "Eine Sammlung von ganzen Zahlen.",
"integerPolymorphic": "Ganze Zahl Polymorph",
"ipAdapterPolymorphic": "IP-Adapter Polymorph",
"floatPolymorphic": "Fließkommazahl Polymorph",
"enumDescription": "Aufzählungen sind Werte, die eine von mehreren Optionen sein können.",
"floatCollection": "Fließkommazahl Sammlung",
"enum": "Aufzählung",
"floatPolymorphicDescription": "Eine Sammlung von Fließkommazahlen",
"fullyContainNodes": "Vollständig ausgewählte Nodes auswählen",
"editMode": "Im Workflow-Editor bearbeiten",
"floatCollectionDescription": "Eine Sammlung von Fließkommazahlen"
},
"hrf": {
"enableHrf": "Korrektur für hohe Auflösungen",
@@ -1336,12 +1405,12 @@
},
"control": {
"title": "Kontrolle",
"controlAdaptersTab": "Kontroll Adapter",
"ipTab": "Bild Beschreibung"
"controlAdaptersTab": "Kontroll-Adapter",
"ipTab": "Bild-Prompts"
},
"compositing": {
"coherenceTab": "Kohärenzpass",
"infillTab": "Füllung",
"infillTab": "Füllung / Infill",
"title": "Compositing"
}
},
@@ -1379,5 +1448,15 @@
},
"app": {
"storeNotInitialized": "App-Store ist nicht initialisiert"
},
"sdxl": {
"concatPromptStyle": "Verknüpfen von Prompt & Stil",
"scheduler": "Planer",
"steps": "Schritte",
"useRefiner": "Refiner verwenden",
"selectAModel": "Modell auswählen"
},
"dynamicPrompts": {
"showDynamicPrompts": "Dynamische Prompts anzeigen"
}
}

View File

@@ -1456,9 +1456,8 @@
"clipSkip": {
"heading": "CLIP Skip",
"paragraphs": [
"Choose how many layers of the CLIP model to skip.",
"Some models work better with certain CLIP Skip settings.",
"A higher value typically results in a less detailed image."
"How many layers of the CLIP model to skip.",
"Certain models are better suited to be used with CLIP Skip."
]
},
"paramNegativeConditioning": {
@@ -1478,7 +1477,8 @@
"paramScheduler": {
"heading": "Scheduler",
"paragraphs": [
"Scheduler defines how to iteratively add noise to an image or how to update a sample based on a model's output."
"Scheduler used during the generation process.",
"Each scheduler defines how to iteratively add noise to an image or how to update a sample based on a model's output."
]
},
"compositingMaskBlur": {
@@ -1495,7 +1495,15 @@
},
"compositingCoherenceMode": {
"heading": "Mode",
"paragraphs": ["The mode of the Coherence Pass."]
"paragraphs": ["Method used to create a coherent image with the newly generated masked area."]
},
"compositingCoherenceSteps": {
"heading": "Steps",
"paragraphs": ["Number of steps in the Coherence Pass.", "Similar to Generation Steps."]
},
"compositingStrength": {
"heading": "Strength",
"paragraphs": ["Amount of noise added for the Coherence Pass.", "Similar to Denoising Strength."]
},
"compositingCoherenceEdgeSize": {
"heading": "Edge Size",
@@ -1512,30 +1520,38 @@
"heading": "Mask Adjustments",
"paragraphs": ["Adjust the mask."]
},
"controlNetBeginEnd": {
"heading": "Begin / End Step Percentage",
"paragraphs": [
"Which steps of the denoising process will have the ControlNet applied.",
"ControlNets applied at the beginning of the process guide composition, and ControlNets applied at the end guide details."
]
},
"controlNetControlMode": {
"heading": "Control Mode",
"paragraphs": ["Lends more weight to either the prompt or ControlNet."]
},
"controlNetResizeMode": {
"heading": "Resize Mode",
"paragraphs": ["How the ControlNet image will be fit to the image output size."]
},
"controlNet": {
"heading": "ControlNet",
"paragraphs": [
"ControlNets provide guidance to the generation process, helping create images with controlled composition, structure, or style, depending on the model selected."
]
},
"controlNetBeginEnd": {
"heading": "Begin / End Step Percentage",
"paragraphs": [
"The part of the of the denoising process that will have the Control Adapter applied.",
"Generally, Control Adapters applied at the start of the process guide composition, and Control Adapters applied at the end guide details."
]
},
"controlNetControlMode": {
"heading": "Control Mode",
"paragraphs": ["Lend more weight to either the prompt or ControlNet."]
},
"controlNetProcessor": {
"heading": "Processor",
"paragraphs": [
"Method of processing the input image to guide the generation process. Different processors will providedifferent effects or styles in your generated images."
]
},
"controlNetResizeMode": {
"heading": "Resize Mode",
"paragraphs": ["Method to fit Control Adapter's input image size to the output generation size."]
},
"controlNetWeight": {
"heading": "Weight",
"paragraphs": ["How strongly the ControlNet will impact the generated image."]
"paragraphs": [
"Weight of the Control Adapter. Higher weight will lead to larger impacts on the final image."
]
},
"dynamicPrompts": {
"heading": "Dynamic Prompts",
@@ -1558,13 +1574,23 @@
"Per Image will use a unique seed for each image. This provides more variation."
]
},
"imageFit": {
"heading": "Fit Initial Image to Output Size",
"paragraphs": [
"Resizes the initial image to the width and height of the output image. Recommended to enable."
]
},
"infillMethod": {
"heading": "Infill Method",
"paragraphs": ["Method to infill the selected area."]
"paragraphs": ["Method of infilling during the Outpainting or Inpainting process."]
},
"lora": {
"heading": "LoRA Weight",
"paragraphs": ["Higher LoRA weight will lead to larger impacts on the final image."]
"heading": "LoRA",
"paragraphs": ["Lightweight models that are used in conjunction with base models."]
},
"loraWeight": {
"heading": "Weight",
"paragraphs": ["Weight of the LoRA. Higher weight will lead to larger impacts on the final image."]
},
"noiseUseCPU": {
"heading": "Use CPU Noise",
@@ -1574,14 +1600,25 @@
"There is no performance impact to enabling CPU Noise."
]
},
"paramAspect": {
"heading": "Aspect",
"paragraphs": [
"Aspect ratio of the generated image. Changing the ratio will update the Width and Height accordingly.",
"“Optimize” will set the Width and Height to optimal dimensions for the chosen model."
]
},
"paramCFGScale": {
"heading": "CFG Scale",
"paragraphs": ["Controls how much your prompt influences the generation process."]
"paragraphs": [
"Controls how much the prompt influences the generation process.",
"High CFG Scale values can result in over-saturation and distorted generation results. "
]
},
"paramCFGRescaleMultiplier": {
"heading": "CFG Rescale Multiplier",
"paragraphs": [
"Rescale multiplier for CFG guidance, used for models trained using zero-terminal SNR (ztsnr). Suggested value 0.7."
"Rescale multiplier for CFG guidance, used for models trained using zero-terminal SNR (ztsnr).",
"Suggested value of 0.7 for these models."
]
},
"paramDenoisingStrength": {
@@ -1591,6 +1628,16 @@
"0 will result in an identical image, while 1 will result in a completely new image."
]
},
"paramHeight": {
"heading": "Height",
"paragraphs": ["Height of the generated image. Must be a multiple of 8."]
},
"paramHrf": {
"heading": "Enable High Resolution Fix",
"paragraphs": [
"Generate high quality images at a larger resolution than optimal for the model. Generally used to prevent duplication in the generated image."
]
},
"paramIterations": {
"heading": "Iterations",
"paragraphs": [
@@ -1601,8 +1648,7 @@
"paramModel": {
"heading": "Model",
"paragraphs": [
"Model used for the denoising steps.",
"Different models are typically trained to specialize in producing particular aesthetic results and content."
"Model used for generation. Different models are trained to specialize in producing different aesthetic results and content."
]
},
"paramRatio": {
@@ -1616,7 +1662,7 @@
"heading": "Seed",
"paragraphs": [
"Controls the starting noise used for generation.",
"Disable “Random Seed” to produce identical results with the same generation settings."
"Disable the “Random” option to produce identical results with the same generation settings."
]
},
"paramSteps": {
@@ -1626,6 +1672,10 @@
"Higher step counts will typically create better images but will require more generation time."
]
},
"paramUpscaleMethod": {
"heading": "Upscale Method",
"paragraphs": ["Method used to upscale the image for High Resolution Fix."]
},
"paramVAE": {
"heading": "VAE",
"paragraphs": ["Model used for translating AI output into the final image."]
@@ -1633,14 +1683,82 @@
"paramVAEPrecision": {
"heading": "VAE Precision",
"paragraphs": [
"The precision used during VAE encoding and decoding. FP16/half precision is more efficient, at the expense of minor image variations."
"The precision used during VAE encoding and decoding.",
"Fp16/Half precision is more efficient, at the expense of minor image variations."
]
},
"paramWidth": {
"heading": "Width",
"paragraphs": ["Width of the generated image. Must be a multiple of 8."]
},
"patchmatchDownScaleSize": {
"heading": "Downscale",
"paragraphs": [
"How much downscaling occurs before infilling.",
"Higher downscaling will improve performance and reduce quality."
]
},
"refinerModel": {
"heading": "Refiner Model",
"paragraphs": [
"Model used during the refiner portion of the generation process.",
"Similar to the Generation Model."
]
},
"refinerPositiveAestheticScore": {
"heading": "Positive Aesthetic Score",
"paragraphs": [
"Weight generations to be more similar to images with a high aesthetic score, based on the training data."
]
},
"refinerNegativeAestheticScore": {
"heading": "Negative Aesthetic Score",
"paragraphs": [
"Weight generations to be more similar to images with a low aesthetic score, based on the training data."
]
},
"refinerScheduler": {
"heading": "Scheduler",
"paragraphs": [
"Scheduler used during the refiner portion of the generation process.",
"Similar to the Generation Scheduler."
]
},
"refinerStart": {
"heading": "Refiner Start",
"paragraphs": [
"Where in the generation process the refiner will start to be used.",
"0 means the refiner will be used for the entire generation process, 0.8 means the refiner will be used for the last 20% of the generation process."
]
},
"refinerSteps": {
"heading": "Steps",
"paragraphs": [
"Number of steps that will be performed during the refiner portion of the generation process.",
"Similar to the Generation Steps."
]
},
"refinerCfgScale": {
"heading": "CFG Scale",
"paragraphs": [
"Controls how much the prompt influences the generation process.",
"Similar to the Generation CFG Scale."
]
},
"scaleBeforeProcessing": {
"heading": "Scale Before Processing",
"paragraphs": [
"Scales the selected area to the size best suited for the model before the image generation process."
"“Auto” scales the selected area to the size best suited for the model before the image generation process.",
"“Manual” allows you to choose the width and height the selected area will be scaled to before the image generation process."
]
},
"seamlessTilingXAxis": {
"heading": "Seamless Tiling X Axis",
"paragraphs": ["Seamlessly tile an image along the horizontal axis."]
},
"seamlessTilingYAxis": {
"heading": "Seamless Tiling Y Axis",
"paragraphs": ["Seamlessly tile an image along the vertical axis."]
}
},
"ui": {

View File

@@ -47,7 +47,7 @@
"statusModelConverted": "Modello Convertito",
"statusConvertingModel": "Conversione Modello",
"loading": "Caricamento in corso",
"loadingInvokeAI": "Caricamento Invoke AI",
"loadingInvokeAI": "Caricamento di Invoke AI",
"postprocessing": "Post Elaborazione",
"txt2img": "Testo a Immagine",
"accept": "Accetta",
@@ -61,7 +61,7 @@
"imagePrompt": "Prompt Immagine",
"darkMode": "Modalità scura",
"batch": "Gestione Lotto",
"modelManager": "Gestore modello",
"modelManager": "Gestore Modelli",
"communityLabel": "Comunità",
"nodeEditor": "Editor dei nodi",
"statusProcessing": "Elaborazione in corso",
@@ -81,7 +81,7 @@
"error": "Errore",
"installed": "Installato",
"template": "Schema",
"outputs": "Uscite",
"outputs": "Risultati",
"data": "Dati",
"somethingWentWrong": "Qualcosa è andato storto",
"copyError": "$t(gallery.copy) Errore",
@@ -93,7 +93,7 @@
"created": "Creato",
"prevPage": "Pagina precedente",
"delete": "Elimina",
"orderBy": "Ordinato per",
"orderBy": "Ordina per",
"nextPage": "Pagina successiva",
"saveAs": "Salva come",
"unsaved": "Non salvato",
@@ -109,7 +109,12 @@
"green": "Verde",
"blue": "Blu",
"alpha": "Alfa",
"copy": "Copia"
"copy": "Copia",
"on": "Attivato",
"checkpoint": "Checkpoint",
"safetensors": "Safetensors",
"ai": "ia",
"file": "File"
},
"gallery": {
"generations": "Generazioni",
@@ -934,7 +939,7 @@
"executionStateCompleted": "Completato",
"boardFieldDescription": "Una bacheca della galleria",
"addNodeToolTip": "Aggiungi nodo (Shift+A, Space)",
"sDXLRefinerModelField": "Modello Refiner",
"sDXLRefinerModelField": "Modello Affinatore",
"problemReadingMetadata": "Problema durante la lettura dei metadati dall'immagine",
"colorCodeEdgesHelp": "Bordi con codice colore in base ai campi collegati",
"animatedEdges": "Bordi animati",
@@ -1138,7 +1143,11 @@
"unsupportedAnyOfLength": "unione di troppi elementi ({{count}})",
"clearWorkflowDesc": "Cancellare questo flusso di lavoro e avviarne uno nuovo?",
"clearWorkflow": "Cancella il flusso di lavoro",
"clearWorkflowDesc2": "Il tuo flusso di lavoro attuale presenta modifiche non salvate."
"clearWorkflowDesc2": "Il tuo flusso di lavoro attuale presenta modifiche non salvate.",
"viewMode": "Utilizzare nella vista lineare",
"reorderLinearView": "Riordina la vista lineare",
"editMode": "Modifica nell'editor del flusso di lavoro",
"resetToDefaultValue": "Ripristina il valore predefinito"
},
"boards": {
"autoAddBoard": "Aggiungi automaticamente bacheca",
@@ -1241,7 +1250,16 @@
"large": "Grande",
"small": "Piccolo",
"depthAnythingDescription": "Generazione di mappe di profondità utilizzando la tecnica Depth Anything",
"modelSize": "Dimensioni del modello"
"modelSize": "Dimensioni del modello",
"dwOpenposeDescription": "Stima della posa umana utilizzando DW Openpose",
"face": "Viso",
"body": "Corpo",
"hands": "Mani",
"lineartAnime": "Linea Anime",
"base": "Base",
"lineart": "Linea",
"controlnet": "$t(controlnet.controlAdapter_one) #{{number}} ($t(common.controlNet))",
"mediapipeFace": "Mediapipe Volto"
},
"queue": {
"queueFront": "Aggiungi all'inizio della coda",
@@ -1321,7 +1339,7 @@
"noModelsAvailable": "Nessun modello disponibile",
"selectModel": "Seleziona un modello",
"selectLoRA": "Seleziona un LoRA",
"noRefinerModelsInstalled": "Nessun modello SDXL Refiner installato",
"noRefinerModelsInstalled": "Nessun modello affinatore SDXL installato",
"noLoRAsInstalled": "Nessun LoRA installato",
"esrganModel": "Modello ESRGAN",
"addLora": "Aggiungi LoRA",
@@ -1371,7 +1389,8 @@
"popovers": {
"paramScheduler": {
"paragraphs": [
"Il campionatore definisce come aggiungere in modo iterativo il rumore a un'immagine o come aggiornare un campione in base all'output di un modello."
"Il campionatore utilizzato durante il processo di generazione.",
"Ciascun campionatore definisce come aggiungere in modo iterativo il rumore a un'immagine o come aggiornare un campione in base all'output di un modello."
],
"heading": "Campionatore"
},
@@ -1384,8 +1403,8 @@
"compositingCoherenceSteps": {
"heading": "Passi",
"paragraphs": [
"Numero di passi di riduzione del rumore utilizzati nel Passaggio di Coerenza.",
"Uguale al parametro principale Passi."
"Numero di passi utilizzati nel Passaggio di Coerenza.",
"Simile ai passi di generazione."
]
},
"compositingBlur": {
@@ -1397,14 +1416,13 @@
"compositingCoherenceMode": {
"heading": "Modalità",
"paragraphs": [
"La modalità del Passaggio di Coerenza."
"Metodo utilizzato per creare un'immagine coerente con l'area mascherata appena generata."
]
},
"clipSkip": {
"paragraphs": [
"Scegli quanti livelli del modello CLIP saltare.",
"Alcuni modelli funzionano meglio con determinate impostazioni di CLIP Skip.",
"Un valore più alto in genere produce un'immagine meno dettagliata."
"Alcuni modelli funzionano meglio con determinate impostazioni di CLIP Skip."
]
},
"compositingCoherencePass": {
@@ -1416,8 +1434,8 @@
"compositingStrength": {
"heading": "Forza",
"paragraphs": [
"Intensità di riduzione del rumore per il passaggio di coerenza.",
"Uguale al parametro intensità di riduzione del rumore da immagine a immagine."
"Quantità di rumore aggiunta per il Passaggio di Coerenza.",
"Simile alla forza di riduzione del rumore."
]
},
"paramNegativeConditioning": {
@@ -1443,8 +1461,8 @@
"controlNetBeginEnd": {
"heading": "Percentuale passi Inizio / Fine",
"paragraphs": [
"A quali passi del processo di rimozione del rumore verrà applicato ControlNet.",
"I ControlNet applicati all'inizio del processo guidano la composizione, mentre i ControlNet applicati alla fine guidano i dettagli."
"La parte del processo di rimozione del rumore in cui verrà applicato l'adattatore di controllo.",
"In genere, gli adattatori di controllo applicati all'inizio del processo guidano la composizione, mentre quelli applicati alla fine guidano i dettagli."
]
},
"noiseUseCPU": {
@@ -1457,7 +1475,8 @@
},
"scaleBeforeProcessing": {
"paragraphs": [
"Ridimensiona l'area selezionata alla dimensione più adatta al modello prima del processo di generazione dell'immagine."
"\"Auto\" ridimensiona l'area selezionata alla dimensione più adatta al modello prima del processo di generazione dell'immagine.",
"\"Manuale\" consente di scegliere la larghezza e l'altezza a cui verrà ridimensionata l'area selezionata prima del processo di generazione dell'immagine."
],
"heading": "Scala prima dell'elaborazione"
},
@@ -1492,20 +1511,21 @@
"paramVAEPrecision": {
"heading": "Precisione VAE",
"paragraphs": [
"La precisione utilizzata durante la codifica e decodifica VAE. FP16/mezza precisione è più efficiente, a scapito di minori variazioni dell'immagine."
"La precisione utilizzata durante la codifica e decodifica VAE.",
"Fp16/Mezza precisione è più efficiente, a scapito di minori variazioni dell'immagine."
]
},
"paramSeed": {
"paragraphs": [
"Controlla il rumore iniziale utilizzato per la generazione.",
"Disabilita seme \"Casuale\" per produrre risultati identici con le stesse impostazioni di generazione."
"Disabilita l'opzione \"Casuale\" per produrre risultati identici con le stesse impostazioni di generazione."
],
"heading": "Seme"
},
"controlNetResizeMode": {
"heading": "Modalità ridimensionamento",
"paragraphs": [
"Come l'immagine ControlNet verrà adattata alle dimensioni di output dell'immagine."
"Metodo per adattare le dimensioni dell'immagine in ingresso dell'adattatore di controllo alle dimensioni della generazione di output."
]
},
"dynamicPromptsSeedBehaviour": {
@@ -1520,8 +1540,7 @@
"paramModel": {
"heading": "Modello",
"paragraphs": [
"Modello utilizzato per i passaggi di riduzione del rumore.",
"Diversi modelli sono generalmente addestrati per specializzarsi nella produzione di particolari risultati e contenuti estetici."
"Modello utilizzato per la generazione. Diversi modelli vengono addestrati per specializzarsi nella produzione di risultati e contenuti estetici diversi."
]
},
"paramDenoisingStrength": {
@@ -1539,25 +1558,26 @@
},
"infillMethod": {
"paragraphs": [
"Metodo per riempire l'area selezionata."
"Metodo di riempimento durante il processo di Outpainting o Inpainting."
],
"heading": "Metodo di riempimento"
},
"controlNetWeight": {
"heading": "Peso",
"paragraphs": [
"Quanto forte sarà l'impatto di ControlNet sull'immagine generata."
"Peso dell'adattatore di controllo. Un peso maggiore porterà a impatti maggiori sull'immagine finale."
]
},
"paramCFGScale": {
"heading": "Scala CFG",
"paragraphs": [
"Controlla quanto il tuo prompt influenza il processo di generazione."
"Controlla quanto il prompt influenza il processo di generazione.",
"Valori elevati della scala CFG possono provocare una saturazione eccessiva e distorsioni nei risultati della generazione. "
]
},
"controlNetControlMode": {
"paragraphs": [
"Attribuisce più peso al prompt o a ControlNet."
"Attribuisce più peso al prompt oppure a ControlNet."
],
"heading": "Modalità di controllo"
},
@@ -1569,9 +1589,9 @@
]
},
"lora": {
"heading": "Peso LoRA",
"heading": "LoRA",
"paragraphs": [
"Un peso LoRA più elevato porterà a impatti maggiori sull'immagine finale."
"Modelli leggeri utilizzati insieme ai modelli base."
]
},
"controlNet": {
@@ -1583,7 +1603,123 @@
"paramCFGRescaleMultiplier": {
"heading": "Moltiplicatore di riscala CFG",
"paragraphs": [
"Moltiplicatore di riscala per la guida CFG, utilizzato per modelli addestrati utilizzando SNR a terminale zero (ztsnr). Valore suggerito 0.7."
"Moltiplicatore di riscala per la guida CFG, utilizzato per modelli addestrati utilizzando SNR a terminale zero (ztsnr).",
"Valore suggerito di 0.7 per questi modelli."
]
},
"controlNetProcessor": {
"heading": "Processore",
"paragraphs": [
"Metodo di elaborazione dell'immagine di input per guidare il processo di generazione. Processori diversi forniranno effetti o stili diversi nelle immagini generate."
]
},
"imageFit": {
"heading": "Adatta l'immagine iniziale alle dimensioni di output",
"paragraphs": [
"Ridimensiona l'immagine iniziale in base alla larghezza e all'altezza dell'immagine di output. Si consiglia di abilitarlo."
]
},
"loraWeight": {
"heading": "Peso",
"paragraphs": [
"Peso del LoRA. Un peso maggiore comporterà un impatto maggiore sull'immagine finale."
]
},
"paramAspect": {
"heading": "Aspetto",
"paragraphs": [
"Proporzioni dell'immagine generata. La modifica del rapporto aggiornerà di conseguenza la larghezza e l'altezza.",
"\"Ottimizza\" imposterà la larghezza e l'altezza alle dimensioni ottimali per il modello scelto."
]
},
"paramHeight": {
"heading": "Altezza",
"paragraphs": [
"Altezza dell'immagine generata. Deve essere un multiplo di 8."
]
},
"paramHrf": {
"heading": "Abilita correzione alta risoluzione",
"paragraphs": [
"Genera immagini di alta qualità con una risoluzione maggiore di quella ottimale per il modello. Generalmente utilizzato per impedire la duplicazione nell'immagine generata."
]
},
"paramUpscaleMethod": {
"heading": "Metodo di ampliamento",
"paragraphs": [
"Metodo utilizzato per eseguire l'ampliamento dell'immagine per la correzione ad alta risoluzione."
]
},
"patchmatchDownScaleSize": {
"heading": "Ridimensiona",
"paragraphs": [
"Quanto ridimensionamento avviene prima del riempimento.",
"Un ridimensionamento più elevato migliorerà le prestazioni e ridurrà la qualità."
]
},
"paramWidth": {
"paragraphs": [
"Larghezza dell'immagine generata. Deve essere un multiplo di 8."
],
"heading": "Larghezza"
},
"refinerModel": {
"heading": "Modello Affinatore",
"paragraphs": [
"Modello utilizzato durante la parte di affinamento del processo di generazione.",
"Simile al modello di generazione."
]
},
"refinerNegativeAestheticScore": {
"paragraphs": [
"Valuta le generazioni in modo che siano più simili alle immagini con un punteggio estetico basso, in base ai dati di addestramento."
],
"heading": "Punteggio estetico negativo"
},
"refinerScheduler": {
"paragraphs": [
"Campionatore utilizzato durante la parte di affinamento del processo di generazione.",
"Simile al campionatore di generazione."
],
"heading": "Campionatore"
},
"refinerStart": {
"heading": "Inizio affinamento",
"paragraphs": [
"A che punto nel processo di generazione inizierà ad essere utilizzato l'affinatore.",
"0 significa che l'affinatore verrà utilizzato per l'intero processo di generazione, 0.8 significa che l'affinatore verrà utilizzato per l'ultimo 20% del processo di generazione."
]
},
"refinerSteps": {
"heading": "Passi",
"paragraphs": [
"Numero di passi che verranno eseguiti durante la parte di affinamento del processo di generazione.",
"Simile ai passi di generazione."
]
},
"refinerCfgScale": {
"heading": "Scala CFG",
"paragraphs": [
"Controlla quanto il prompt influenza il processo di generazione.",
"Simile alla scala CFG di generazione."
]
},
"seamlessTilingXAxis": {
"heading": "Asse X di piastrellatura senza cuciture",
"paragraphs": [
"Affianca senza soluzione di continuità un'immagine lungo l'asse orizzontale."
]
},
"seamlessTilingYAxis": {
"heading": "Asse Y di piastrellatura senza cuciture",
"paragraphs": [
"Affianca senza soluzione di continuità un'immagine lungo l'asse verticale."
]
},
"refinerPositiveAestheticScore": {
"heading": "Punteggio estetico positivo",
"paragraphs": [
"Valuta le generazioni in modo che siano più simili alle immagini con un punteggio estetico elevato, in base ai dati di addestramento."
]
}
},
@@ -1632,7 +1768,8 @@
"steps": "Passi",
"scheduler": "Campionatore",
"recallParameters": "Richiama i parametri",
"noRecallParameters": "Nessun parametro da richiamare trovato"
"noRecallParameters": "Nessun parametro da richiamare trovato",
"cfgRescaleMultiplier": "$t(parameters.cfgRescaleMultiplier)"
},
"hrf": {
"enableHrf": "Abilita Correzione Alta Risoluzione",

View File

@@ -1217,16 +1217,14 @@
"clipSkip": {
"paragraphs": [
"Kies hoeveel CLIP-modellagen je wilt overslaan.",
"Bepaalde modellen werken beter met bepaalde Overslaan CLIP-instellingen.",
"Een hogere waarde geeft meestal een minder gedetailleerde afbeelding."
"Bepaalde modellen werken beter met bepaalde Overslaan CLIP-instellingen."
],
"heading": "Overslaan CLIP"
},
"paramModel": {
"heading": "Model",
"paragraphs": [
"Model gebruikt voor de ontruisingsstappen.",
"Verschillende modellen zijn meestal getraind om zich te specialiseren in het maken van bepaalde esthetische resultaten en materiaal."
"Model gebruikt voor de ontruisingsstappen."
]
},
"compositingCoherencePass": {

View File

@@ -108,7 +108,16 @@
"preferencesLabel": "Предпочтения",
"or": "или",
"advancedOptions": "Расширенные настройки",
"free": "Свободно"
"free": "Свободно",
"aboutHeading": "Владей своей творческой силой",
"red": "Красный",
"green": "Зеленый",
"blue": "Синий",
"alpha": "Альфа",
"toResolve": "Чтоб решить",
"copy": "Копировать",
"localSystem": "Локальная система",
"aboutDesc": "Используя Invoke для работы? Проверьте это:"
},
"gallery": {
"generations": "Генерации",
@@ -152,17 +161,17 @@
},
"hotkeys": {
"keyboardShortcuts": "Горячие клавиши",
"appHotkeys": "Горячие клавиши приложения",
"generalHotkeys": "Общие горячие клавиши",
"galleryHotkeys": орячие клавиши галереи",
"unifiedCanvasHotkeys": "Горячие клавиши Единого холста",
"appHotkeys": "Приложение",
"generalHotkeys": "Общее",
"galleryHotkeys": "Галлерея",
"unifiedCanvasHotkeys": "Единый холст",
"invoke": {
"title": "Invoke",
"desc": "Сгенерировать изображение"
},
"cancel": {
"title": "Отменить",
"desc": "Отменить генерацию изображения"
"desc": "Отменить текущий элемент"
},
"focusPrompt": {
"title": "Переключиться на ввод запроса",
@@ -352,7 +361,7 @@
"desc": "Открывает меню добавления узла",
"title": "Добавление узлов"
},
"nodesHotkeys": "Горячие клавиши узлов",
"nodesHotkeys": "Узлы",
"cancelAndClear": {
"desc": "Отмена текущего элемента очереди и очистка всех ожидающих элементов",
"title": "Отменить и очистить"
@@ -367,7 +376,11 @@
"desc": "Открытие и закрытие панели опций и галереи",
"title": "Переключить опции и галерею"
},
"clearSearch": "Очистить поиск"
"clearSearch": "Очистить поиск",
"remixImage": {
"desc": "Используйте все параметры, кроме сида из текущего изображения",
"title": "Ремикс изображения"
}
},
"modelManager": {
"modelManager": "Менеджер моделей",
@@ -512,7 +525,8 @@
"modelType": "Тип модели",
"customConfigFileLocation": "Расположение пользовательского файла конфигурации",
"vaePrecision": "Точность VAE",
"noModelSelected": "Модель не выбрана"
"noModelSelected": "Модель не выбрана",
"configFile": "Файл конфигурации"
},
"parameters": {
"images": "Изображения",
@@ -583,8 +597,8 @@
"copyImage": "Скопировать изображение",
"showPreview": "Показать предпросмотр",
"noiseSettings": "Шум",
"seamlessXAxis": "Горизонтальная",
"seamlessYAxis": "Вертикальная",
"seamlessXAxis": "Бесшовность по оси X",
"seamlessYAxis": "Бесшовность по оси Y",
"scheduler": "Планировщик",
"boundingBoxWidth": "Ширина ограничивающей рамки",
"boundingBoxHeight": "Высота ограничивающей рамки",
@@ -612,7 +626,7 @@
"noControlImageForControlAdapter": "Адаптер контроля #{{number}} не имеет изображения",
"noModelForControlAdapter": "Не выбрана модель адаптера контроля #{{number}}.",
"unableToInvoke": "Невозможно вызвать",
"incompatibleBaseModelForControlAdapter": "Модель контрольного адаптера №{{number}} недействительна для основной модели.",
"incompatibleBaseModelForControlAdapter": "Адаптер контроля №{{number}} несовместим с основной моделью.",
"systemDisconnected": "Система отключена",
"missingNodeTemplate": "Отсутствует шаблон узла",
"readyToInvoke": "Готово к вызову",
@@ -653,7 +667,10 @@
"setToOptimalSize": "Установить оптимальный для модели размер",
"setToOptimalSizeTooSmall": "$t(parameters.setToOptimalSize) (может быть слишком маленьким)",
"setToOptimalSizeTooLarge": "$t(parameters.setToOptimalSize) (может быть слишком большим)",
"lockAspectRatio": "Заблокировать соотношение"
"lockAspectRatio": "Заблокировать соотношение",
"boxBlur": "Размытие прямоугольника",
"gaussianBlur": "Размытие по Гауссу",
"remixImage": "Ремикс изображения"
},
"settings": {
"models": "Модели",
@@ -787,7 +804,10 @@
"canvasSavedGallery": "Холст сохранен в галерею",
"imageUploadFailed": "Не удалось загрузить изображение",
"modelAdded": "Добавлена модель: {{modelName}}",
"problemImportingMask": "Проблема с импортом маски"
"problemImportingMask": "Проблема с импортом маски",
"problemDownloadingImage": "Не удается скачать изображение",
"uploadInitialImage": "Загрузить начальное изображение",
"resetInitialImage": "Сбросить начальное изображение"
},
"tooltip": {
"feature": {
@@ -892,7 +912,8 @@
"mode": "Режим",
"loadMore": "Загрузить больше",
"resetUI": "$t(accessibility.reset) интерфейс",
"createIssue": "Сообщить о проблеме"
"createIssue": "Сообщить о проблеме",
"about": "Об этом"
},
"ui": {
"showProgressImages": "Показывать промежуточный итог",
@@ -1117,7 +1138,18 @@
"unableToParseEdge": "Невозможно разобрать край",
"unknownInput": "Неизвестный вход: {{name}}",
"oNNXModelFieldDescription": "Поле модели ONNX.",
"imageCollection": "Коллекция изображений"
"imageCollection": "Коллекция изображений",
"newWorkflow": "Новый рабочий процесс",
"newWorkflowDesc": "Создать новый рабочий процесс?",
"clearWorkflow": "Очистить рабочий процесс",
"newWorkflowDesc2": "Текущий рабочий процесс имеет несохраненные изменения.",
"latentsCollection": "Коллекция латентов",
"clearWorkflowDesc": "Очистить этот рабочий процесс и создать новый?",
"clearWorkflowDesc2": "Текущий рабочий процесс имеет несохраненные измерения.",
"reorderLinearView": "Изменить порядок линейного просмотра",
"viewMode": "Использовать в линейном представлении",
"editMode": "Открыть в редакторе узлов",
"resetToDefaultValue": "Сбросить к стандартному значкнию"
},
"controlnet": {
"amult": "a_mult",
@@ -1198,7 +1230,18 @@
"enableIPAdapter": "Включить IP Adapter",
"maxFaces": "Макс Лица",
"mlsdDescription": "Минималистичный детектор отрезков линии",
"resizeSimple": "Изменить размер (простой)"
"resizeSimple": "Изменить размер (простой)",
"megaControl": "Mega контроль",
"base": "Базовый",
"depthAnything": "Глубина всего",
"depthAnythingDescription": "Создание карты глубины с использованием метода Depth Anything",
"face": "Лицо",
"dwOpenposeDescription": "Оценка позы человека с помощью DW Openpose",
"large": "Большой",
"modelSize": "Размер модели",
"small": "Маленький",
"body": "Тело",
"hands": "Руки"
},
"boards": {
"autoAddBoard": "Авто добавление Доски",
@@ -1281,7 +1324,7 @@
"compositingCoherenceSteps": {
"heading": "Шаги",
"paragraphs": [
null,
"Количество шагов снижения шума, используемых при прохождении когерентности.",
"То же, что и основной параметр «Шаги»."
]
},
@@ -1319,7 +1362,10 @@
]
},
"compositingCoherenceMode": {
"heading": "Режим"
"heading": "Режим",
"paragraphs": [
"Режим прохождения когерентности."
]
},
"paramSeed": {
"paragraphs": [
@@ -1353,16 +1399,14 @@
"clipSkip": {
"paragraphs": [
"Выберите, сколько слоев модели CLIP нужно пропустить.",
"Некоторые модели работают лучше с определенными настройками пропуска CLIP.",
"Более высокое значение обычно приводит к менее детализированному изображению."
"Некоторые модели работают лучше с определенными настройками пропуска CLIP."
],
"heading": "CLIP пропуск"
},
"paramModel": {
"heading": "Модель",
"paragraphs": [
"Модель, используемая для шагов шумоподавления.",
"Различные модели обычно обучаются, чтобы специализироваться на достижении определенных эстетических результатов и содержания."
"Модель, используемая для шагов шумоподавления."
]
},
"compositingCoherencePass": {
@@ -1601,7 +1645,7 @@
"openWorkflow": "Открытый рабочий процесс",
"clearWorkflowSearchFilter": "Очистить фильтр поиска рабочих процессов",
"workflowLibrary": "Библиотека",
"downloadWorkflow": "Скачать рабочий процесс",
"downloadWorkflow": "Сохранить в файл",
"noRecentWorkflows": "Нет недавних рабочих процессов",
"workflowSaved": "Рабочий процесс сохранен",
"workflowIsOpen": "Рабочий процесс открыт",
@@ -1614,9 +1658,12 @@
"deleteWorkflow": "Удалить рабочий процесс",
"workflows": "Рабочие процессы",
"noDescription": "Без описания",
"uploadWorkflow": "Загрузить рабочий процесс",
"uploadWorkflow": "Загрузить из файла",
"userWorkflows": "Мои рабочие процессы",
"newWorkflowCreated": "Создан новый рабочий процесс"
"newWorkflowCreated": "Создан новый рабочий процесс",
"saveWorkflowToProject": "Сохранить рабочий процесс в проект",
"workflowCleared": "Рабочий процесс очищен",
"noWorkflows": "Нет рабочих процессов"
},
"embedding": {
"noEmbeddingsLoaded": "встраивания не загружены",

View File

@@ -1444,16 +1444,14 @@
"clipSkip": {
"paragraphs": [
"选择要跳过 CLIP 模型多少层。",
"部分模型跳过特定数值的层时效果会更好。",
"较高的数值通常会导致图像细节更少。"
"部分模型跳过特定数值的层时效果会更好。"
],
"heading": "CLIP 跳过层"
},
"paramModel": {
"heading": "模型",
"paragraphs": [
"用于去噪过程的模型。",
"不同的模型一般会通过接受训练来专门产生特定的美学内容和结果。"
"用于去噪过程的模型。"
]
},
"paramIterations": {

View File

@@ -13,28 +13,46 @@ export type Feature =
| 'compositingCoherenceEdgeSize'
| 'compositingCoherenceMinDenoise'
| 'compositingMaskAdjustments'
| 'controlNet'
| 'controlNetBeginEnd'
| 'controlNetControlMode'
| 'controlNetProcessor'
| 'controlNetResizeMode'
| 'controlNet'
| 'controlNetWeight'
| 'dynamicPrompts'
| 'dynamicPromptsMaxPrompts'
| 'dynamicPromptsSeedBehaviour'
| 'imageFit'
| 'infillMethod'
| 'lora'
| 'loraWeight'
| 'noiseUseCPU'
| 'paramAspect'
| 'paramCFGScale'
| 'paramCFGRescaleMultiplier'
| 'paramDenoisingStrength'
| 'paramHeight'
| 'paramHrf'
| 'paramIterations'
| 'paramModel'
| 'paramRatio'
| 'paramSeed'
| 'paramSteps'
| 'paramUpscaleMethod'
| 'paramVAE'
| 'paramVAEPrecision'
| 'scaleBeforeProcessing';
| 'paramWidth'
| 'patchmatchDownScaleSize'
| 'refinerModel'
| 'refinerNegativeAestheticScore'
| 'refinerPositiveAestheticScore'
| 'refinerScheduler'
| 'refinerStart'
| 'refinerSteps'
| 'refinerCfgScale'
| 'scaleBeforeProcessing'
| 'seamlessTilingXAxis'
| 'seamlessTilingYAxis';
export type PopoverData = PopoverProps & {
image?: string;
@@ -46,21 +64,57 @@ export const POPOVER_DATA: { [key in Feature]?: PopoverData } = {
paramNegativeConditioning: {
placement: 'right',
},
clipSkip: {
href: 'https://support.invoke.ai/support/solutions/articles/151000178161-advanced-settings',
},
controlNet: {
href: 'https://support.invoke.ai/support/solutions/articles/151000105880',
},
controlNetBeginEnd: {
href: 'https://support.invoke.ai/support/solutions/articles/151000178148',
},
controlNetWeight: {
href: 'https://support.invoke.ai/support/solutions/articles/151000178148',
},
lora: {
href: 'https://support.invoke.ai/support/solutions/articles/151000159072',
},
loraWeight: {
href: 'https://support.invoke.ai/support/solutions/articles/151000159072-concepts-low-rank-adaptations-loras-',
},
compositingBlur: {
href: 'https://support.invoke.ai/support/solutions/articles/151000158838-compositing-settings',
},
compositingBlurMethod: {
href: 'https://support.invoke.ai/support/solutions/articles/151000158838-compositing-settings',
},
compositingCoherenceMode: {
href: 'https://support.invoke.ai/support/solutions/articles/151000158838',
href: 'https://support.invoke.ai/support/solutions/articles/151000158838-compositing-settings',
},
compositingCoherenceSteps: {
href: 'https://support.invoke.ai/support/solutions/articles/151000158838-compositing-settings',
},
compositingStrength: {
href: 'https://support.invoke.ai/support/solutions/articles/151000158838-compositing-settings',
},
infillMethod: {
href: 'https://support.invoke.ai/support/solutions/articles/151000158841',
href: 'https://support.invoke.ai/support/solutions/articles/151000158841-infill-and-scaling',
},
scaleBeforeProcessing: {
href: 'https://support.invoke.ai/support/solutions/articles/151000158841',
},
paramCFGScale: {
href: 'https://www.youtube.com/watch?v=1OeHEJrsTpI',
},
paramCFGRescaleMultiplier: {
href: 'https://support.invoke.ai/support/solutions/articles/151000178161-advanced-settings',
},
paramDenoisingStrength: {
href: 'https://support.invoke.ai/support/solutions/articles/151000094998-image-to-image',
},
paramHrf: {
href: 'https://support.invoke.ai/support/solutions/articles/151000096700-how-can-i-get-larger-images-what-does-upscaling-do-',
},
paramIterations: {
href: 'https://support.invoke.ai/support/solutions/articles/151000159073',
},
@@ -70,7 +124,10 @@ export const POPOVER_DATA: { [key in Feature]?: PopoverData } = {
},
paramScheduler: {
placement: 'right',
href: 'https://support.invoke.ai/support/solutions/articles/151000159073',
href: 'https://www.youtube.com/watch?v=1OeHEJrsTpI',
},
paramSeed: {
href: 'https://support.invoke.ai/support/solutions/articles/151000096684-what-is-a-seed-how-do-i-use-it-to-recreate-the-same-image-',
},
paramModel: {
placement: 'right',
@@ -81,15 +138,53 @@ export const POPOVER_DATA: { [key in Feature]?: PopoverData } = {
},
controlNetControlMode: {
placement: 'right',
href: 'https://support.invoke.ai/support/solutions/articles/151000178148',
},
controlNetProcessor: {
placement: 'right',
href: 'https://support.invoke.ai/support/solutions/articles/151000105880-using-controlnet',
},
controlNetResizeMode: {
placement: 'right',
href: 'https://support.invoke.ai/support/solutions/articles/151000178148',
},
paramVAE: {
placement: 'right',
href: 'https://support.invoke.ai/support/solutions/articles/151000178161-advanced-settings',
},
paramVAEPrecision: {
placement: 'right',
href: 'https://support.invoke.ai/support/solutions/articles/151000178161-advanced-settings',
},
paramUpscaleMethod: {
href: 'https://support.invoke.ai/support/solutions/articles/151000096700-how-can-i-get-larger-images-what-does-upscaling-do-',
},
refinerModel: {
href: 'https://support.invoke.ai/support/solutions/articles/151000178333-using-the-refiner',
},
refinerNegativeAestheticScore: {
href: 'https://support.invoke.ai/support/solutions/articles/151000178333-using-the-refiner',
},
refinerPositiveAestheticScore: {
href: 'https://support.invoke.ai/support/solutions/articles/151000178333-using-the-refiner',
},
refinerScheduler: {
href: 'https://support.invoke.ai/support/solutions/articles/151000178333-using-the-refiner',
},
refinerStart: {
href: 'https://support.invoke.ai/support/solutions/articles/151000178333-using-the-refiner',
},
refinerSteps: {
href: 'https://support.invoke.ai/support/solutions/articles/151000178333-using-the-refiner',
},
refinerCfgScale: {
href: 'https://support.invoke.ai/support/solutions/articles/151000178333-using-the-refiner',
},
seamlessTilingXAxis: {
href: 'https://support.invoke.ai/support/solutions/articles/151000178161-advanced-settings',
},
seamlessTilingYAxis: {
href: 'https://support.invoke.ai/support/solutions/articles/151000178161-advanced-settings',
},
} as const;

View File

@@ -1,5 +1,6 @@
import { CompositeRangeSlider, FormControl, FormLabel } from '@invoke-ai/ui-library';
import { useAppDispatch } from 'app/store/storeHooks';
import { InformationalPopover } from 'common/components/InformationalPopover/InformationalPopover';
import { useControlAdapterBeginEndStepPct } from 'features/controlAdapters/hooks/useControlAdapterBeginEndStepPct';
import { useControlAdapterIsEnabled } from 'features/controlAdapters/hooks/useControlAdapterIsEnabled';
import {
@@ -61,12 +62,10 @@ export const ParamControlAdapterBeginEnd = memo(({ id }: Props) => {
}
return (
<FormControl
isDisabled={!isEnabled}
// feature="controlNetBeginEnd"
orientation="vertical"
>
<FormLabel>{t('controlnet.beginEndStepPercent')}</FormLabel>
<FormControl isDisabled={!isEnabled} orientation="vertical">
<InformationalPopover feature="controlNetBeginEnd">
<FormLabel>{t('controlnet.beginEndStepPercent')}</FormLabel>
</InformationalPopover>
<CompositeRangeSlider
aria-label={ariaLabel}
value={value}

View File

@@ -2,6 +2,7 @@ import type { ComboboxOnChange, ComboboxOption } from '@invoke-ai/ui-library';
import { Combobox, FormControl, FormLabel } from '@invoke-ai/ui-library';
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { InformationalPopover } from 'common/components/InformationalPopover/InformationalPopover';
import { useControlAdapterIsEnabled } from 'features/controlAdapters/hooks/useControlAdapterIsEnabled';
import { useControlAdapterProcessorNode } from 'features/controlAdapters/hooks/useControlAdapterProcessorNode';
import { CONTROLNET_PROCESSORS } from 'features/controlAdapters/store/constants';
@@ -58,7 +59,9 @@ const ParamControlAdapterProcessorSelect = ({ id }: Props) => {
}
return (
<FormControl isDisabled={!isEnabled}>
<FormLabel>{t('controlnet.processor')}</FormLabel>
<InformationalPopover feature="controlNetProcessor">
<FormLabel>{t('controlnet.processor')}</FormLabel>
</InformationalPopover>
<Combobox value={value} options={options} onChange={onChange} />
</FormControl>
);

View File

@@ -1,6 +1,7 @@
import type { ComboboxOnChange, ComboboxOption } from '@invoke-ai/ui-library';
import { Combobox, FormControl, FormLabel } from '@invoke-ai/ui-library';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { InformationalPopover } from 'common/components/InformationalPopover/InformationalPopover';
import { setHrfMethod } from 'features/hrf/store/hrfSlice';
import { isParameterHRFMethod } from 'features/parameters/types/parameterSchemas';
import { memo, useCallback, useMemo } from 'react';
@@ -30,7 +31,9 @@ const ParamHrfMethodSelect = () => {
return (
<FormControl>
<FormLabel>{t('hrf.upscaleMethod')}</FormLabel>
<InformationalPopover feature="paramUpscaleMethod">
<FormLabel>{t('hrf.upscaleMethod')}</FormLabel>
</InformationalPopover>
<Combobox value={value} options={options} onChange={onChange} />
</FormControl>
);

View File

@@ -1,5 +1,6 @@
import { CompositeNumberInput, CompositeSlider, FormControl, FormLabel } from '@invoke-ai/ui-library';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { InformationalPopover } from 'common/components/InformationalPopover/InformationalPopover';
import { setHrfStrength } from 'features/hrf/store/hrfSlice';
import { memo, useCallback } from 'react';
import { useTranslation } from 'react-i18next';
@@ -25,7 +26,9 @@ const ParamHrfStrength = () => {
return (
<FormControl>
<FormLabel>{t('parameters.denoisingStrength')}</FormLabel>
<InformationalPopover feature="paramDenoisingStrength">
<FormLabel>{`${t('parameters.denoisingStrength')}`}</FormLabel>
</InformationalPopover>
<CompositeSlider
min={sliderMin}
max={sliderMax}

View File

@@ -1,5 +1,6 @@
import { FormControl, FormLabel, Switch } from '@invoke-ai/ui-library';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { InformationalPopover } from 'common/components/InformationalPopover/InformationalPopover';
import { setHrfEnabled } from 'features/hrf/store/hrfSlice';
import type { ChangeEvent } from 'react';
import { memo, useCallback } from 'react';
@@ -18,7 +19,9 @@ const ParamHrfToggle = () => {
return (
<FormControl w="full">
<FormLabel flexGrow={1}>{t('hrf.enableHrf')}</FormLabel>
<InformationalPopover feature="paramHrf">
<FormLabel flexGrow={1}>{t('hrf.enableHrf')}</FormLabel>
</InformationalPopover>
<Switch isChecked={hrfEnabled} onChange={handleHrfEnabled} />
</FormControl>
);

View File

@@ -10,6 +10,7 @@ import {
Text,
} from '@invoke-ai/ui-library';
import { useAppDispatch } from 'app/store/storeHooks';
import { InformationalPopover } from 'common/components/InformationalPopover/InformationalPopover';
import type { LoRA } from 'features/lora/store/loraSlice';
import { loraIsEnabledChanged, loraRemoved, loraWeightChanged } from 'features/lora/store/loraSlice';
import { memo, useCallback } from 'react';
@@ -59,29 +60,31 @@ export const LoRACard = memo((props: LoRACardProps) => {
</Flex>
</Flex>
</CardHeader>
<CardBody>
<CompositeSlider
value={lora.weight}
onChange={handleChange}
min={-1}
max={2}
step={0.01}
marks={marks}
defaultValue={0.75}
isDisabled={!lora.isEnabled}
/>
<CompositeNumberInput
value={lora.weight}
onChange={handleChange}
min={-5}
max={5}
step={0.01}
w={20}
flexShrink={0}
defaultValue={0.75}
isDisabled={!lora.isEnabled}
/>
</CardBody>
<InformationalPopover feature="loraWeight">
<CardBody>
<CompositeSlider
value={lora.weight}
onChange={handleChange}
min={-1}
max={2}
step={0.01}
marks={marks}
defaultValue={0.75}
isDisabled={!lora.isEnabled}
/>
<CompositeNumberInput
value={lora.weight}
onChange={handleChange}
min={-5}
max={5}
step={0.01}
w={20}
flexShrink={0}
defaultValue={0.75}
isDisabled={!lora.isEnabled}
/>
</CardBody>
</InformationalPopover>
</Card>
);
});

View File

@@ -2,6 +2,7 @@ import type { ChakraProps } from '@invoke-ai/ui-library';
import { Combobox, FormControl, FormLabel } from '@invoke-ai/ui-library';
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { InformationalPopover } from 'common/components/InformationalPopover/InformationalPopover';
import { useGroupedModelCombobox } from 'common/hooks/useGroupedModelCombobox';
import { loraAdded, selectLoraSlice } from 'features/lora/store/loraSlice';
import { memo, useCallback, useMemo } from 'react';
@@ -57,7 +58,9 @@ const LoRASelect = () => {
return (
<FormControl isDisabled={!options.length}>
<FormLabel>{t('models.lora')} </FormLabel>
<InformationalPopover feature="lora">
<FormLabel>{t('models.lora')} </FormLabel>
</InformationalPopover>
<Combobox
placeholder={placeholder}
value={null}

View File

@@ -1,5 +1,6 @@
import { CompositeNumberInput, CompositeSlider, FormControl, FormLabel } from '@invoke-ai/ui-library';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { InformationalPopover } from 'common/components/InformationalPopover/InformationalPopover';
import { setInfillPatchmatchDownscaleSize } from 'features/parameters/store/generationSlice';
import { memo, useCallback } from 'react';
import { useTranslation } from 'react-i18next';
@@ -27,7 +28,9 @@ const ParamInfillPatchmatchDownscaleSize = () => {
return (
<FormControl isDisabled={infillMethod !== 'patchmatch'}>
<FormLabel>{t('parameters.patchmatchDownScaleSize')}</FormLabel>
<InformationalPopover feature="patchmatchDownScaleSize">
<FormLabel>{t('parameters.patchmatchDownScaleSize')}</FormLabel>
</InformationalPopover>
<CompositeSlider
min={sliderMin}
max={sliderMax}

View File

@@ -1,5 +1,6 @@
import { CompositeNumberInput, CompositeSlider, FormControl, FormLabel } from '@invoke-ai/ui-library';
import { useAppSelector } from 'app/store/storeHooks';
import { InformationalPopover } from 'common/components/InformationalPopover/InformationalPopover';
import { useImageSizeContext } from 'features/parameters/components/ImageSize/ImageSizeContext';
import { selectOptimalDimension } from 'features/parameters/store/generationSlice';
import { memo, useCallback, useMemo } from 'react';
@@ -27,7 +28,9 @@ export const ParamHeight = memo(() => {
return (
<FormControl>
<FormLabel>{t('parameters.height')}</FormLabel>
<InformationalPopover feature="paramHeight">
<FormLabel>{t('parameters.height')}</FormLabel>
</InformationalPopover>
<CompositeSlider
value={ctx.height}
defaultValue={optimalDimension}

View File

@@ -1,5 +1,6 @@
import { CompositeNumberInput, CompositeSlider, FormControl, FormLabel } from '@invoke-ai/ui-library';
import { useAppSelector } from 'app/store/storeHooks';
import { InformationalPopover } from 'common/components/InformationalPopover/InformationalPopover';
import { useImageSizeContext } from 'features/parameters/components/ImageSize/ImageSizeContext';
import { selectOptimalDimension } from 'features/parameters/store/generationSlice';
import { memo, useCallback, useMemo } from 'react';
@@ -27,7 +28,9 @@ export const ParamWidth = memo(() => {
return (
<FormControl>
<FormLabel>{t('parameters.width')}</FormLabel>
<InformationalPopover feature="paramWidth">
<FormLabel>{t('parameters.width')}</FormLabel>
</InformationalPopover>
<CompositeSlider
value={ctx.width}
onChange={onChange}

View File

@@ -1,6 +1,7 @@
import type { ComboboxOption, SystemStyleObject } from '@invoke-ai/ui-library';
import { Combobox, FormControl, FormLabel } from '@invoke-ai/ui-library';
import type { SingleValue } from 'chakra-react-select';
import { InformationalPopover } from 'common/components/InformationalPopover/InformationalPopover';
import { ASPECT_RATIO_OPTIONS } from 'features/parameters/components/ImageSize/constants';
import { useImageSizeContext } from 'features/parameters/components/ImageSize/ImageSizeContext';
import { isAspectRatioID } from 'features/parameters/components/ImageSize/types';
@@ -28,7 +29,9 @@ export const AspectRatioSelect = memo(() => {
return (
<FormControl>
<FormLabel>{t('parameters.aspect')}</FormLabel>
<InformationalPopover feature="paramAspect">
<FormLabel>{t('parameters.aspect')}</FormLabel>
</InformationalPopover>
<Combobox value={value} onChange={onChange} options={ASPECT_RATIO_OPTIONS} sx={selectStyles} />
</FormControl>
);

View File

@@ -1,6 +1,7 @@
import { FormControl, FormLabel, Switch } from '@invoke-ai/ui-library';
import type { RootState } from 'app/store/store';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { InformationalPopover } from 'common/components/InformationalPopover/InformationalPopover';
import { setShouldFitToWidthHeight } from 'features/parameters/store/generationSlice';
import type { ChangeEvent } from 'react';
import { memo, useCallback } from 'react';
@@ -22,7 +23,9 @@ const ImageToImageFit = () => {
return (
<FormControl w="full">
<FormLabel flexGrow={1}>{t('parameters.imageFit')}</FormLabel>
<InformationalPopover feature="imageFit">
<FormLabel flexGrow={1}>{t('parameters.imageFit')}</FormLabel>
</InformationalPopover>
<Switch isChecked={shouldFitToWidthHeight} onChange={handleChangeFit} />
</FormControl>
);

View File

@@ -2,6 +2,7 @@ import { CustomSelect, FormControl, FormLabel } from '@invoke-ai/ui-library';
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { useModelCustomSelect } from 'common/hooks/useModelCustomSelect';
import { InformationalPopover } from 'common/components/InformationalPopover/InformationalPopover';
import { modelSelected } from 'features/parameters/store/actions';
import { selectGenerationSlice } from 'features/parameters/store/generationSlice';
import { memo, useCallback } from 'react';
@@ -37,7 +38,9 @@ const ParamMainModelSelect = () => {
return (
<FormControl isDisabled={!items.length} isInvalid={!selectedItem || !items.length}>
<FormLabel>{t('modelManager.model')}</FormLabel>
<InformationalPopover feature="paramModel">
<FormLabel>{t('modelManager.model')}</FormLabel>
</InformationalPopover>
<CustomSelect selectedItem={selectedItem} placeholder={placeholder} items={items} onChange={onChange} />
</FormControl>
);

View File

@@ -1,5 +1,6 @@
import { FormControl, FormLabel, Switch } from '@invoke-ai/ui-library';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { InformationalPopover } from 'common/components/InformationalPopover/InformationalPopover';
import { setSeamlessXAxis } from 'features/parameters/store/generationSlice';
import type { ChangeEvent } from 'react';
import { memo, useCallback } from 'react';
@@ -20,7 +21,9 @@ const ParamSeamlessXAxis = () => {
return (
<FormControl>
<FormLabel>{t('parameters.seamlessXAxis')}</FormLabel>
<InformationalPopover feature="seamlessTilingXAxis">
<FormLabel>{t('parameters.seamlessXAxis')}</FormLabel>
</InformationalPopover>
<Switch isChecked={seamlessXAxis} onChange={handleChange} />
</FormControl>
);

View File

@@ -1,5 +1,6 @@
import { FormControl, FormLabel, Switch } from '@invoke-ai/ui-library';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { InformationalPopover } from 'common/components/InformationalPopover/InformationalPopover';
import { setSeamlessYAxis } from 'features/parameters/store/generationSlice';
import type { ChangeEvent } from 'react';
import { memo, useCallback } from 'react';
@@ -18,7 +19,9 @@ const ParamSeamlessYAxis = () => {
return (
<FormControl>
<FormLabel>{t('parameters.seamlessYAxis')}</FormLabel>
<InformationalPopover feature="seamlessTilingYAxis">
<FormLabel>{t('parameters.seamlessYAxis')}</FormLabel>
</InformationalPopover>
<Switch isChecked={seamlessYAxis} onChange={handleChange} />
</FormControl>
);

View File

@@ -1,5 +1,6 @@
import { CompositeNumberInput, CompositeSlider, FormControl, FormLabel } from '@invoke-ai/ui-library';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { InformationalPopover } from 'common/components/InformationalPopover/InformationalPopover';
import { setRefinerCFGScale } from 'features/sdxl/store/sdxlSlice';
import { memo, useCallback, useMemo } from 'react';
import { useTranslation } from 'react-i18next';
@@ -21,7 +22,9 @@ const ParamSDXLRefinerCFGScale = () => {
return (
<FormControl>
<FormLabel>{t('sdxl.cfgScale')}</FormLabel>
<InformationalPopover feature="refinerCfgScale">
<FormLabel>{t('sdxl.cfgScale')}</FormLabel>
</InformationalPopover>
<CompositeSlider
value={refinerCFGScale}
defaultValue={initial}

View File

@@ -1,6 +1,7 @@
import { Combobox, FormControl, FormLabel } from '@invoke-ai/ui-library';
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { InformationalPopover } from 'common/components/InformationalPopover/InformationalPopover';
import { useModelCombobox } from 'common/hooks/useModelCombobox';
import { getModelKeyAndBase } from 'features/metadata/util/modelFetchingHelpers';
import { refinerModelChanged, selectSdxlSlice } from 'features/sdxl/store/sdxlSlice';
@@ -38,7 +39,9 @@ const ParamSDXLRefinerModelSelect = () => {
});
return (
<FormControl isDisabled={!options.length} isInvalid={!options.length}>
<FormLabel>{t('sdxl.refinermodel')}</FormLabel>
<InformationalPopover feature="refinerModel">
<FormLabel>{t('sdxl.refinermodel')}</FormLabel>
</InformationalPopover>
<Combobox
value={value}
placeholder={placeholder}

View File

@@ -1,5 +1,6 @@
import { CompositeNumberInput, CompositeSlider, FormControl, FormLabel } from '@invoke-ai/ui-library';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { InformationalPopover } from 'common/components/InformationalPopover/InformationalPopover';
import { setRefinerNegativeAestheticScore } from 'features/sdxl/store/sdxlSlice';
import { memo, useCallback } from 'react';
import { useTranslation } from 'react-i18next';
@@ -14,7 +15,9 @@ const ParamSDXLRefinerNegativeAestheticScore = () => {
return (
<FormControl>
<FormLabel>{t('sdxl.negAestheticScore')}</FormLabel>
<InformationalPopover feature="refinerNegativeAestheticScore">
<FormLabel>{t('sdxl.negAestheticScore')}</FormLabel>
</InformationalPopover>
<CompositeSlider
min={1}
max={10}

View File

@@ -1,5 +1,6 @@
import { CompositeNumberInput, CompositeSlider, FormControl, FormLabel } from '@invoke-ai/ui-library';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { InformationalPopover } from 'common/components/InformationalPopover/InformationalPopover';
import { setRefinerPositiveAestheticScore } from 'features/sdxl/store/sdxlSlice';
import { memo, useCallback } from 'react';
import { useTranslation } from 'react-i18next';
@@ -13,7 +14,9 @@ const ParamSDXLRefinerPositiveAestheticScore = () => {
return (
<FormControl>
<FormLabel>{t('sdxl.posAestheticScore')}</FormLabel>
<InformationalPopover feature="refinerPositiveAestheticScore">
<FormLabel>{t('sdxl.posAestheticScore')}</FormLabel>
</InformationalPopover>
<CompositeSlider
step={0.5}
min={1}

View File

@@ -1,6 +1,7 @@
import type { ComboboxOnChange } from '@invoke-ai/ui-library';
import { Combobox, FormControl, FormLabel } from '@invoke-ai/ui-library';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { InformationalPopover } from 'common/components/InformationalPopover/InformationalPopover';
import { SCHEDULER_OPTIONS } from 'features/parameters/types/constants';
import { isParameterScheduler } from 'features/parameters/types/parameterSchemas';
import { setRefinerScheduler } from 'features/sdxl/store/sdxlSlice';
@@ -26,7 +27,9 @@ const ParamSDXLRefinerScheduler = () => {
return (
<FormControl>
<FormLabel>{t('sdxl.scheduler')}</FormLabel>
<InformationalPopover feature="refinerScheduler">
<FormLabel>{t('sdxl.scheduler')}</FormLabel>
</InformationalPopover>
<Combobox value={value} options={SCHEDULER_OPTIONS} onChange={onChange} />
</FormControl>
);

View File

@@ -1,5 +1,6 @@
import { CompositeNumberInput, CompositeSlider, FormControl, FormLabel } from '@invoke-ai/ui-library';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { InformationalPopover } from 'common/components/InformationalPopover/InformationalPopover';
import { setRefinerStart } from 'features/sdxl/store/sdxlSlice';
import { memo, useCallback } from 'react';
import { useTranslation } from 'react-i18next';
@@ -12,7 +13,9 @@ const ParamSDXLRefinerStart = () => {
return (
<FormControl>
<FormLabel>{t('sdxl.refinerStart')}</FormLabel>
<InformationalPopover feature="refinerStart">
<FormLabel>{t('sdxl.refinerStart')}</FormLabel>
</InformationalPopover>
<CompositeSlider
step={0.01}
min={0}

View File

@@ -1,5 +1,6 @@
import { CompositeNumberInput, CompositeSlider, FormControl, FormLabel } from '@invoke-ai/ui-library';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { InformationalPopover } from 'common/components/InformationalPopover/InformationalPopover';
import { setRefinerSteps } from 'features/sdxl/store/sdxlSlice';
import { memo, useCallback, useMemo } from 'react';
import { useTranslation } from 'react-i18next';
@@ -27,7 +28,9 @@ const ParamSDXLRefinerSteps = () => {
return (
<FormControl>
<FormLabel>{t('sdxl.steps')}</FormLabel>
<InformationalPopover feature="refinerSteps">
<FormLabel>{t('sdxl.steps')}</FormLabel>
</InformationalPopover>
<CompositeSlider
value={refinerSteps}
defaultValue={initial}

View File

@@ -55,10 +55,22 @@ const dynamicBaseQuery: BaseQueryFn<string | FetchArgs, unknown, FetchBaseQueryE
const baseUrl = $baseUrl.get();
const authToken = $authToken.get();
const projectId = $projectId.get();
const isOpenAPIRequest =
(args instanceof Object && args.url.includes('openapi.json')) ||
(typeof args === 'string' && args.includes('openapi.json'));
const fetchBaseQueryArgs: FetchBaseQueryArgs = {
baseUrl: baseUrl || window.location.href.replace(/\/$/, ''),
prepareHeaders: (headers) => {
baseUrl: baseUrl ? `${baseUrl}/api/v1` : `${window.location.href.replace(/\/$/, '')}/api/v1`,
};
// When fetching the openapi.json, we need to remove circular references from the JSON.
if (isOpenAPIRequest) {
fetchBaseQueryArgs.jsonReplacer = getCircularReplacer();
}
// openapi.json isn't protected by authorization, but all other requests need to include the auth token and project id.
if (!isOpenAPIRequest) {
fetchBaseQueryArgs.prepareHeaders = (headers) => {
if (authToken) {
headers.set('Authorization', `Bearer ${authToken}`);
}
@@ -67,15 +79,7 @@ const dynamicBaseQuery: BaseQueryFn<string | FetchArgs, unknown, FetchBaseQueryE
}
return headers;
},
};
// When fetching the openapi.json, we need to remove circular references from the JSON.
if (
(args instanceof Object && args.url.includes('openapi.json')) ||
(typeof args === 'string' && args.includes('openapi.json'))
) {
fetchBaseQueryArgs.jsonReplacer = getCircularReplacer();
};
}
const rawBaseQuery = fetchBaseQuery(fetchBaseQueryArgs);

View File

@@ -1 +1 @@
__version__ = "3.6.3"
__version__ = "3.7.0"