Skip to content

Commit 3eb2c8e

Browse files
Merge branch 'main' into main
2 parents 0c0637f + 0ad0016 commit 3eb2c8e

File tree

37 files changed

+1303
-1335
lines changed

37 files changed

+1303
-1335
lines changed

.github/workflows/build-container.yml

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -76,9 +76,6 @@ jobs:
7676
latest=${{ matrix.gpu-driver == 'cuda' && github.ref == 'refs/heads/main' }}
7777
suffix=-${{ matrix.gpu-driver }},onlatest=false
7878
79-
- name: Set up QEMU
80-
uses: docker/setup-qemu-action@v3
81-
8279
- name: Set up Docker Buildx
8380
uses: docker/setup-buildx-action@v3
8481
with:
@@ -103,7 +100,7 @@ jobs:
103100
push: ${{ github.ref == 'refs/heads/main' || github.ref_type == 'tag' || github.event.inputs.push-to-registry }}
104101
tags: ${{ steps.meta.outputs.tags }}
105102
labels: ${{ steps.meta.outputs.labels }}
106-
cache-from: |
107-
type=gha,scope=${{ github.ref_name }}-${{ matrix.gpu-driver }}
108-
type=gha,scope=main-${{ matrix.gpu-driver }}
109-
cache-to: type=gha,mode=max,scope=${{ github.ref_name }}-${{ matrix.gpu-driver }}
103+
# cache-from: |
104+
# type=gha,scope=${{ github.ref_name }}-${{ matrix.gpu-driver }}
105+
# type=gha,scope=main-${{ matrix.gpu-driver }}
106+
# cache-to: type=gha,mode=max,scope=${{ github.ref_name }}-${{ matrix.gpu-driver }}

docs/RELEASE.md

Lines changed: 60 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -1,104 +1,103 @@
11
# Release Process
22

3-
The app is published in twice, in different build formats.
3+
The Invoke application is published as a python package on [PyPI]. This includes both a source distribution and built distribution (a wheel).
44

5-
- A [PyPI] distribution. This includes both a source distribution and built distribution (a wheel). Users install with `pip install invokeai`. The updater uses this build.
6-
- An installer on the [InvokeAI Releases Page]. This is a zip file with install scripts and a wheel. This is only used for new installs.
5+
Most users install it with the [Launcher](https://github.com/invoke-ai/launcher/), others with `pip`.
76

8-
## General Prep
7+
The launcher uses GitHub as the source of truth for available releases.
8+
9+
## Broad Strokes
10+
11+
- Merge all changes and bump the version in the codebase.
12+
- Tag the release commit.
13+
- Wait for the release workflow to complete.
14+
- Approve the PyPI publish jobs.
15+
- Write GH release notes.
916

10-
Make a developer call-out for PRs to merge. Merge and test things out.
17+
## General Prep
1118

12-
While the release workflow does not include end-to-end tests, it does pause before publishing so you can download and test the final build.
19+
Make a developer call-out for PRs to merge. Merge and test things out. Bump the version by editing `invokeai/version/invokeai_version.py`.
1320

1421
## Release Workflow
1522

1623
The `release.yml` workflow runs a number of jobs to handle code checks, tests, build and publish on PyPI.
1724

18-
It is triggered on **tag push**, when the tag matches `v*`. It doesn't matter if you've prepped a release branch like `release/v3.5.0` or are releasing from `main` - it works the same.
19-
20-
> Because commits are reference-counted, it is safe to create a release branch, tag it, let the workflow run, then delete the branch. So long as the tag exists, that commit will exist.
25+
It is triggered on **tag push**, when the tag matches `v*`.
2126

2227
### Triggering the Workflow
2328

24-
Run `make tag-release` to tag the current commit and kick off the workflow.
29+
Ensure all commits that should be in the release are merged, and you have pulled them locally.
30+
31+
Double-check that you have checked out the commit that will represent the release (typically the latest commit on `main`).
2532

26-
The release may also be dispatched [manually].
33+
Run `make tag-release` to tag the current commit and kick off the workflow. You will be prompted to provide a message - use the version specifier.
34+
35+
If this version's tag already exists for some reason (maybe you had to make a last minute change), the script will overwrite it.
36+
37+
> In case you cannot use the Make target, the release may also be dispatched [manually] via GH.
2738
2839
### Workflow Jobs and Process
2940

30-
The workflow consists of a number of concurrently-run jobs, and two final publish jobs.
41+
The workflow consists of a number of concurrently-run checks and tests, then two final publish jobs.
3142

3243
The publish jobs require manual approval and are only run if the other jobs succeed.
3344

3445
#### `check-version` Job
3546

36-
This job checks that the git ref matches the app version. It matches the ref against the `__version__` variable in `invokeai/version/invokeai_version.py`.
37-
38-
When the workflow is triggered by tag push, the ref is the tag. If the workflow is run manually, the ref is the target selected from the **Use workflow from** dropdown.
47+
This job ensures that the `invokeai` python package version specifier matches the tag for the release. The version specifier is pulled from the `__version__` variable in `invokeai/version/invokeai_version.py`.
3948

4049
This job uses [samuelcolvin/check-python-version].
4150

4251
> Any valid [version specifier] works, so long as the tag matches the version. The release workflow works exactly the same for `RC`, `post`, `dev`, etc.
4352
4453
#### Check and Test Jobs
4554

55+
Next, these jobs run and must pass. They are the same jobs that are run for every PR.
56+
4657
- **`python-tests`**: runs `pytest` on matrix of platforms
4758
- **`python-checks`**: runs `ruff` (format and lint)
4859
- **`frontend-tests`**: runs `vitest`
4960
- **`frontend-checks`**: runs `prettier` (format), `eslint` (lint), `dpdm` (circular refs), `tsc` (static type check) and `knip` (unused imports)
50-
51-
> **TODO** We should add `mypy` or `pyright` to the **`check-python`** job.
52-
53-
> **TODO** We should add an end-to-end test job that generates an image.
61+
- **`typegen-checks`**: ensures the frontend and backend types are synced
5462

5563
#### `build-installer` Job
5664

5765
This sets up both python and frontend dependencies and builds the python package. Internally, this runs `installer/create_installer.sh` and uploads two artifacts:
5866

5967
- **`dist`**: the python distribution, to be published on PyPI
60-
- **`InvokeAI-installer-${VERSION}.zip`**: the installer to be included in the GitHub release
68+
- **`InvokeAI-installer-${VERSION}.zip`**: the legacy install scripts
6169

62-
#### Sanity Check & Smoke Test
70+
You don't need to download either of these files.
6371

64-
At this point, the release workflow pauses as the remaining publish jobs require approval. Time to test the installer.
72+
> The legacy install scripts are no longer used, but we haven't updated the workflow to skip building them.
6573
66-
Because the installer pulls from PyPI, and we haven't published to PyPI yet, you will need to install from the wheel:
74+
#### Sanity Check & Smoke Test
6775

68-
- Download and unzip `dist.zip` and the installer from the **Summary** tab of the workflow
69-
- Run the installer script using the `--wheel` CLI arg, pointing at the wheel:
76+
At this point, the release workflow pauses as the remaining publish jobs require approval.
7077

71-
```sh
72-
./install.sh --wheel ../InvokeAI-4.0.0rc6-py3-none-any.whl
73-
```
78+
It's possible to test the python package before it gets published to PyPI. We've never had problems with it, so it's not necessary to do this.
7479

75-
- Install to a temporary directory so you get the new user experience
76-
- Download a model and generate
80+
But, if you want to be extra-super careful, here's how to test it:
7781

78-
> The same wheel file is bundled in the installer and in the `dist` artifact, which is uploaded to PyPI. You should end up with the exactly the same installation as if the installer got the wheel from PyPI.
82+
- Download the `dist.zip` build artifact from the `build-installer` job
83+
- Unzip it and find the wheel file
84+
- Create a fresh Invoke install by following the [manual install guide](https://invoke-ai.github.io/InvokeAI/installation/manual/) - but instead of installing from PyPI, install from the wheel
85+
- Test the app
7986

8087
##### Something isn't right
8188

82-
If testing reveals any issues, no worries. Cancel the workflow, which will cancel the pending publish jobs (you didn't approve them prematurely, right?).
83-
84-
Now you can start from the top:
85-
86-
- Fix the issues and PR the fixes per usual
87-
- Get the PR approved and merged per usual
88-
- Switch to `main` and pull in the fixes
89-
- Run `make tag-release` to move the tag to `HEAD` (which has the fixes) and kick off the release workflow again
90-
- Re-do the sanity check
89+
If testing reveals any issues, no worries. Cancel the workflow, which will cancel the pending publish jobs (you didn't approve them prematurely, right?) and start over.
9190

9291
#### PyPI Publish Jobs
9392

94-
The publish jobs will run if any of the previous jobs fail.
93+
The publish jobs will not run if any of the previous jobs fail.
9594

9695
They use [GitHub environments], which are configured as [trusted publishers] on PyPI.
9796

98-
Both jobs require a maintainer to approve them from the workflow's **Summary** tab.
97+
Both jobs require a @hipsterusername or @psychedelicious to approve them from the workflow's **Summary** tab.
9998

10099
- Click the **Review deployments** button
101-
- Select the environment (either `testpypi` or `pypi`)
100+
- Select the environment (either `testpypi` or `pypi` - typically you select both)
102101
- Click **Approve and deploy**
103102

104103
> **If the version already exists on PyPI, the publish jobs will fail.** PyPI only allows a given version to be published once - you cannot change it. If version published on PyPI has a problem, you'll need to "fail forward" by bumping the app version and publishing a followup release.
@@ -113,59 +112,44 @@ If there are no incidents, contact @hipsterusername or @lstein, who have owner a
113112

114113
Publishes the distribution on the [Test PyPI] index, using the `testpypi` GitHub environment.
115114

116-
This job is not required for the production PyPI publish, but included just in case you want to test the PyPI release.
115+
This job is not required for the production PyPI publish, but included just in case you want to test the PyPI release for some reason:
117116

118-
If approved and successful, you could try out the test release like this:
119-
120-
```sh
121-
# Create a new virtual environment
122-
python -m venv ~/.test-invokeai-dist --prompt test-invokeai-dist
123-
# Install the distribution from Test PyPI
124-
pip install --index-url https://test.pypi.org/simple/ invokeai
125-
# Run and test the app
126-
invokeai-web
127-
# Cleanup
128-
deactivate
129-
rm -rf ~/.test-invokeai-dist
130-
```
117+
- Approve this publish job without approving the prod publish
118+
- Let it finish
119+
- Create a fresh Invoke install by following the [manual install guide](https://invoke-ai.github.io/InvokeAI/installation/manual/), making sure to use the Test PyPI index URL: `https://test.pypi.org/simple/`
120+
- Test the app
131121

132122
#### `publish-pypi` Job
133123

134124
Publishes the distribution on the production PyPI index, using the `pypi` GitHub environment.
135125

136-
## Publish the GitHub Release with installer
126+
It's a good idea to wait to approve and run this job until you have the release notes ready!
137127

138-
Once the release is published to PyPI, it's time to publish the GitHub release.
128+
## Prep and publish the GitHub Release
139129

140130
1. [Draft a new release] on GitHub, choosing the tag that triggered the release.
141-
1. Write the release notes, describing important changes. The **Generate release notes** button automatically inserts the changelog and new contributors, and you can copy/paste the intro from previous releases.
142-
1. Use `scripts/get_external_contributions.py` to get a list of external contributions to shout out in the release notes.
143-
1. Upload the zip file created in **`build`** job into the Assets section of the release notes.
144-
1. Check **Set as a pre-release** if it's a pre-release.
145-
1. Check **Create a discussion for this release**.
146-
1. Publish the release.
147-
1. Announce the release in Discord.
148-
149-
> **TODO** Workflows can create a GitHub release from a template and upload release assets. One popular action to handle this is [ncipollo/release-action]. A future enhancement to the release process could set this up.
150-
151-
## Manual Build
152-
153-
The `build installer` workflow can be dispatched manually. This is useful to test the installer for a given branch or tag.
154-
155-
No checks are run, it just builds.
131+
2. The **Generate release notes** button automatically inserts the changelog and new contributors. Make sure to select the correct tags for this release and the last stable release. GH often selects the wrong tags - do this manually.
132+
3. Write the release notes, describing important changes. Contributions from community members should be shouted out. Use the GH-generated changelog to see all contributors. If there are Weblate translation updates, open that PR and shout out every person who contributed a translation.
133+
4. Check **Set as a pre-release** if it's a pre-release.
134+
5. Approve and wait for the `publish-pypi` job to finish if you haven't already.
135+
6. Publish the GH release.
136+
7. Post the release in Discord in the [releases](https://discord.com/channels/1020123559063990373/1149260708098359327) channel with abbreviated notes. For example:
137+
> Invoke v5.7.0 (stable): <https://github.com/invoke-ai/InvokeAI/releases/tag/v5.7.0>
138+
>
139+
> It's a pretty big one - Form Builder, Metadata Nodes (thanks @SkunkWorxDark!), and much more.
140+
8. Right click the message in releases and copy the link to it. Then, post that link in the [new-release-discussion](https://discord.com/channels/1020123559063990373/1149506274971631688) channel. For example:
141+
> Invoke v5.7.0 (stable): <https://discord.com/channels/1020123559063990373/1149260708098359327/1344521744916021248>
156142
157143
## Manual Release
158144

159145
The `release` workflow can be dispatched manually. You must dispatch the workflow from the right tag, else it will fail the version check.
160146

161147
This functionality is available as a fallback in case something goes wonky. Typically, releases should be triggered via tag push as described above.
162148

163-
[InvokeAI Releases Page]: https://github.com/invoke-ai/InvokeAI/releases
164149
[PyPI]: https://pypi.org/
165150
[Draft a new release]: https://github.com/invoke-ai/InvokeAI/releases/new
166151
[Test PyPI]: https://test.pypi.org/
167152
[version specifier]: https://packaging.python.org/en/latest/specifications/version-specifiers/
168-
[ncipollo/release-action]: https://github.com/ncipollo/release-action
169153
[GitHub environments]: https://docs.github.com/en/actions/deployment/targeting-different-environments/using-environments-for-deployment
170154
[trusted publishers]: https://docs.pypi.org/trusted-publishers/
171155
[samuelcolvin/check-python-version]: https://github.com/samuelcolvin/check-python-version

docs/features/low-vram.md

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ It is possible to fine-tune the settings for best performance or if you still ge
3131
Low-VRAM mode involves 4 features, each of which can be configured or fine-tuned:
3232

3333
- Partial model loading (`enable_partial_loading`)
34+
- PyTorch CUDA allocator config (`pytorch_cuda_alloc_conf`)
3435
- Dynamic RAM and VRAM cache sizes (`max_cache_ram_gb`, `max_cache_vram_gb`)
3536
- Working memory (`device_working_mem_gb`)
3637
- Keeping a RAM weight copy (`keep_ram_copy_of_weights`)
@@ -51,6 +52,16 @@ As described above, you can enable partial model loading by adding this line to
5152
enable_partial_loading: true
5253
```
5354

55+
### PyTorch CUDA allocator config
56+
57+
The PyTorch CUDA allocator's behavior can be configured using the `pytorch_cuda_alloc_conf` config. Tuning the allocator configuration can help to reduce the peak reserved VRAM. The optimal configuration is dependent on many factors (e.g. device type, VRAM, CUDA driver version, etc.), but switching from PyTorch's native allocator to using CUDA's built-in allocator works well on many systems. To try this, add the following line to your `invokeai.yaml` file:
58+
59+
```yaml
60+
pytorch_cuda_alloc_conf: "backend:cudaMallocAsync"
61+
```
62+
63+
A more complete explanation of the available configuration options is [here](https://pytorch.org/docs/stable/notes/cuda.html#optimizing-memory-usage-with-pytorch-cuda-alloc-conf).
64+
5465
### Dynamic RAM and VRAM cache sizes
5566

5667
Loading models from disk is slow and can be a major bottleneck for performance. Invoke uses two model caches - RAM and VRAM - to reduce loading from disk to a minimum.
@@ -75,24 +86,26 @@ But, if your GPU has enough VRAM to hold models fully, you might get a perf boos
7586
# As an example, if your system has 32GB of RAM and no other heavy processes, setting the `max_cache_ram_gb` to 28GB
7687
# might be a good value to achieve aggressive model caching.
7788
max_cache_ram_gb: 28
89+
7890
# The default max cache VRAM size is adjusted dynamically based on the amount of available VRAM (taking into
7991
# consideration the VRAM used by other processes).
80-
# You can override the default value by setting `max_cache_vram_gb`. Note that this value takes precedence over the
81-
# `device_working_mem_gb`.
82-
# It is recommended to set the VRAM cache size to be as large as possible while leaving enough room for the working
83-
# memory of the tasks you will be doing. For example, on a 24GB GPU that will be running unquantized FLUX without any
84-
# auxiliary models, 18GB might be a good value.
85-
max_cache_vram_gb: 18
92+
# You can override the default value by setting `max_cache_vram_gb`.
93+
# CAUTION: Most users should not manually set this value. See warning below.
94+
max_cache_vram_gb: 16
8695
```
8796
88-
!!! tip "Max safe value for `max_cache_vram_gb`"
97+
!!! warning "Max safe value for `max_cache_vram_gb`"
8998

90-
To determine the max safe value for `max_cache_vram_gb`, subtract `device_working_mem_gb` from your GPU's VRAM. As described below, the default for `device_working_mem_gb` is 3GB.
99+
Most users should not manually configure the `max_cache_vram_gb`. This configuration value takes precedence over the `device_working_mem_gb` and any operations that explicitly reserve additional working memory (e.g. VAE decode). As such, manually configuring it increases the likelihood of encountering out-of-memory errors.
100+
101+
For users who wish to configure `max_cache_vram_gb`, the max safe value can be determined by subtracting `device_working_mem_gb` from your GPU's VRAM. As described below, the default for `device_working_mem_gb` is 3GB.
91102

92103
For example, if you have a 12GB GPU, the max safe value for `max_cache_vram_gb` is `12GB - 3GB = 9GB`.
93104

94105
If you had increased `device_working_mem_gb` to 4GB, then the max safe value for `max_cache_vram_gb` is `12GB - 4GB = 8GB`.
95106

107+
Most users who override `max_cache_vram_gb` are doing so because they wish to use significantly less VRAM, and should be setting `max_cache_vram_gb` to a value significantly less than the 'max safe value'.
108+
96109
### Working memory
97110

98111
Invoke cannot use _all_ of your VRAM for model caching and loading. It requires some VRAM to use as working memory for various operations.

invokeai/app/api/routers/session_queue.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,9 @@ async def enqueue_batch(
4848
) -> EnqueueBatchResult:
4949
"""Processes a batch and enqueues the output graphs for execution."""
5050

51-
return ApiDependencies.invoker.services.session_queue.enqueue_batch(queue_id=queue_id, batch=batch, prepend=prepend)
51+
return await ApiDependencies.invoker.services.session_queue.enqueue_batch(
52+
queue_id=queue_id, batch=batch, prepend=prepend
53+
)
5254

5355

5456
@session_queue_router.get(

0 commit comments

Comments
 (0)