Skip to content

Commit

Permalink
update v1.1
Browse files Browse the repository at this point in the history
- Added prompt generation modes
- Added face swap support using ReActor extension
- Added new configuration options for FaceSwapLab extension
- Added debug mode and changed various messages to only log when it's enabled
- Updated readme to add better installation instructions
- Renamed some configuration options to better reflect what they do
- Fixed FaceSwapLab settings never being actually used (except for source face)
- Fixed various options being defined as integer instead of float such as cfg scale or upscaler scale
- Fixed special html characters rendering incorrectly such as apostrophes
- Disabled image generation if not used in chat mode
  • Loading branch information
Trojaner committed Dec 17, 2023
1 parent 8928b9e commit 58d2b4b
Show file tree
Hide file tree
Showing 11 changed files with 636 additions and 146 deletions.
15 changes: 8 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,14 @@ Demo:

## Supported Stable Diffusion WebUI Extensions
- [FaceSwapLab](https://github.com/glucauze/sd-webui-faceswaplab)
- [ReActor](https://github.com/Gourieff/sd-webui-reactor)

## Installation
- Open a shell inside the text-generation-webui root directory.
- Open a shell with cmd_linux.sh/cmd_macos.sh/cmd_windows.bat inside text-generation-webui folder.
- Run `git clone https://github.com/Trojaner/text-generation-webui-stable_diffusion extensions/stable_diffusion`.
- Open the [settings.debug.yaml](https://github.com/Trojaner/text-generation-webui-stable_diffusion/blob/main/settings.debug.yaml) file, copy the extension related settings to your own settings.json and adjust them to your own preferences.
- Add `stable_diffusion` to the enabled extensions.
- Run `pip install -r extensions/stable_diffusion/requirements.txt` to install the required dependencies.
- Open the [settings.debug.yaml](https://github.com/Trojaner/text-generation-webui-stable_diffusion/blob/main/settings.debug.yaml) file, copy the extension related settings to your own settings.json in the text-generation-webui directory.
- Add `stable_diffusion` to the enabled extensions in settings.json.

> **Note**
> If you install this extension manually, make sure the extension directory is called stable_diffusion.
Expand Down Expand Up @@ -54,17 +56,16 @@ text-generation-webui, Visual Studio Code and Python 3.10 are required for devel
- Last but not least, ensure that you do not accidentally commit changes you might have made to the `settings.debug.yaml` or `launch.json` files unless intentional.

## Ethical Guidelines
This extension integrates with the FaceSwapLab extension for stable-diffusion-webui and hence allows to swap faces in the generated images. This extension is not intended to for the creation of non-consensual deepfake content. Please use this extension responsibly and do not use it to create such content. The main purpose of the face swapping functionality is to allow the creation of consistent images of text-generation-webui characters. If you are unsure whether your use case is ethical, please refrain from using this extension.
This extension integrates with various face swap extensions for stable-diffusion-webui and hence allows to swap faces in the generated images. This extension is not intended to for the creation of non-consensual deepfake content. Please use this extension responsibly and do not use it to create such content. The main purpose of the face swapping functionality is to allow the creation of consistent images of text-generation-webui characters. If you are unsure whether your use case is ethical, please refrain from using this extension.

The maintainers and contributors of this extension cannot be held liable for any misuse of this extension but will try to prevent such misuse by all means.

## Todo
- Some basic Gradio UI for fine-tuning the extension parameters at runtime
- ~~Some basic Gradio UI for fine-tuning the extension parameters at runtime~~
- ~~Support [ReActor](https://github.com/Gourieff/sd-webui-reactor) as alternative faceswap integration [[api implementation](https://github.com/Gourieff/sd-webui-reactor/blob/main/scripts/reactor_api.py)]~~
- Character specific parameters
- Custom LogitsProcessor or grammar implementation for generating proper and weighted SD image generation prompts
- Support [ReActor](https://github.com/Gourieff/sd-webui-reactor) as alternative faceswap integration [[api implementation](https://github.com/Gourieff/sd-webui-reactor/blob/main/scripts/reactor_api.py)]
- Test with vanilla AUTOMATIC1111
- Standalone mode using diffusers and without stable-diffusion-webui
- Integrate with other SD extensions / scripts?

## See also
Expand Down
Binary file modified assets/demo1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified assets/demo2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
112 changes: 76 additions & 36 deletions ext_modules/image_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,34 +7,39 @@
from webuiapi import WebUIApiResult
from modules.logging_colors import logger
from ..context import GenerationContext
from ..params import TriggerMode
from ..params import (
ContinuousModePromptGenerationMode,
InteractiveModePromptGenerationMode,
TriggerMode,
)
from .vram_manager import VramReallocationTarget, attempt_vram_reallocation


def normalize_prompt(prompt: str) -> str:
if prompt is None or prompt.replace(",", "").replace("\n", "").strip() == "":
if prompt is None:
return ""

return prompt.strip().strip(",").strip().strip("\n")


def description_to_prompt(description: str) -> str:
return normalize_prompt(
description.replace("*", "")
return (
prompt.split("\n")[0]
.replace("*", "")
.replace('"', "")
.replace(".", "")
.replace("!", "")
.replace("?", "")
.replace("#", "")
.replace(":", "")
.replace(";", "")
.split("\n")[0]
.replace(".", ",")
.replace("!", ",")
.replace("?", ",")
.replace(":", ",")
.replace(";", ",")
.strip()
.strip("(")
.strip(")")
.strip(",")
.strip()
.lower()
)


def generate_html_images_for_context(context: GenerationContext) -> str | None:
def generate_html_images_for_context(
context: GenerationContext,
) -> tuple[str | None, str, str]:
"""
Generates images for the given context using Stable Diffusion
and returns the result as HTML output
Expand All @@ -43,27 +48,41 @@ def generate_html_images_for_context(context: GenerationContext) -> str | None:
attempt_vram_reallocation(VramReallocationTarget.STABLE_DIFFUSION, context)
sd_client = context.sd_client

if context.params.trigger_mode == TriggerMode.INTERACTIVE:
full_prompt = (
description_to_prompt(context.output_text) + ","
if context.output_text
else ""
) + normalize_prompt(context.params.base_prompt_suffix)
else:
full_prompt = (
normalize_prompt(context.params.default_prompt)
+ ","
+ normalize_prompt(context.params.base_prompt_suffix)
)
base_prompt = context.params.default_prompt

if context.params.trigger_mode == TriggerMode.INTERACTIVE and (
context.params.interactive_mode_prompt_generation_mode
== InteractiveModePromptGenerationMode.GENERATED_TEXT
or InteractiveModePromptGenerationMode.DYNAMIC
):
base_prompt = context.output_text or ""

if context.params.trigger_mode == TriggerMode.CONTINUOUS and (
context.params.continuous_mode_prompt_generation_mode
== ContinuousModePromptGenerationMode.GENERATED_TEXT
):
base_prompt = context.output_text or ""

base_prompt = normalize_prompt(base_prompt)

full_prompt = (
base_prompt
+ (", " if base_prompt and base_prompt != "" else "")
+ normalize_prompt(context.params.base_prompt_suffix)
)

full_negative_prompt = normalize_prompt(context.params.base_negative_prompt)

logger.info(
(
"[SD WebUI Integration] Using stable-diffusion-webui to generate images.\n"
logger.info
(
"[SD WebUI Integration] Using stable-diffusion-webui to generate images."
+ (
f"\n"
f" Prompt: {full_prompt}\n"
f" Negative Prompt: {full_negative_prompt}"
)
if context.params.debug_mode_enabled
else ""
)

try:
Expand All @@ -89,23 +108,44 @@ def generate_html_images_for_context(context: GenerationContext) -> str | None:

if len(response.images) == 0:
logger.error("[SD WebUI Integration] Failed to generate any images.")
return None
return None, full_prompt, full_negative_prompt

formatted_result = ""
style = 'style="width: 100%; max-height: 100vh;"'
for image in response.images:
if context.params.faceswaplab_enabled:
logger.info("[SD WebUI Integration] Using FaceSwapLab to swap faces.")
if context.params.debug_mode_enabled:
logger.info(
"[SD WebUI Integration] Using FaceSwapLab to swap faces."
)

try:
response = sd_client.faceswaplab_swap_face(
image,
face=context.params.faceswaplab_source_face,
params=context.params,
use_async=False,
)
image = response.image
except Exception as e:
logger.error(f"[SD WebUI Integration] Failed to swap faces: {e}")
logger.error(
f"[SD WebUI Integration] FaceSwapLab failed to swap faces: {e}"
)

if context.params.reactor_enabled:
if context.params.debug_mode_enabled:
logger.info("[SD WebUI Integration] Using Reactor to swap faces.")

try:
response = sd_client.reactor_swap_face(
image,
params=context.params,
use_async=False,
)
image = response.image
except Exception as e:
logger.error(
f"[SD WebUI Integration] Reactor failed to swap faces: {e}"
)

if context.params.save_images:
character = (
Expand Down Expand Up @@ -140,4 +180,4 @@ def generate_html_images_for_context(context: GenerationContext) -> str | None:
finally:
attempt_vram_reallocation(VramReallocationTarget.LLM, context)

return formatted_result.rstrip("\n")
return formatted_result.rstrip("\n"), full_prompt, full_negative_prompt
2 changes: 1 addition & 1 deletion ext_modules/text_analyzer.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ def try_get_description_prompt(
Checks if the given message contains any triggers and returns the prompt if it does.
"""

trigger_regex = params.interactive_mode_trigger_regex
trigger_regex = params.interactive_mode_input_trigger_regex
subject_regex = params.interactive_mode_subject_regex
default_subject = params.interactive_mode_default_subject
default_description_prompt = params.interactive_mode_description_prompt
Expand Down
Loading

0 comments on commit 58d2b4b

Please sign in to comment.