Skip to content

Commit

Permalink
feat: QR code generation (#409)
Browse files Browse the repository at this point in the history
  • Loading branch information
db0 authored May 20, 2024
1 parent 85bed96 commit 1467ad7
Show file tree
Hide file tree
Showing 10 changed files with 56 additions and 6 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changelog

# 4.35.0

* Added ability to generate QR-code images

# 4.34.1

* fix missing `allow_downgrade` doc from the API
Expand Down
9 changes: 8 additions & 1 deletion horde/apis/models/stable_v2.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from flask_restx import fields

from horde.apis.models import v2
from horde.consts import KNOWN_POST_PROCESSORS, KNOWN_SAMPLERS
from horde.consts import KNOWN_POST_PROCESSORS, KNOWN_SAMPLERS, KNOWN_WORKFLOWS
from horde.vars import horde_title


Expand Down Expand Up @@ -390,6 +390,13 @@ def __init__(self, api):
"loras": fields.List(fields.Nested(self.input_model_loras, skip_none=True)),
"tis": fields.List(fields.Nested(self.input_model_tis, skip_none=True)),
"special": fields.Nested(self.input_model_special_payload, skip_none=True),
"extra_texts": fields.List(fields.Nested(self.model_extra_texts)),
"workflow": fields.String(
required=False,
default=None,
enum=list(KNOWN_WORKFLOWS),
description="Explicitly specify the horde-engine workflow to use.",
),
},
)
self.response_model_generation_payload = api.inherit(
Expand Down
7 changes: 7 additions & 0 deletions horde/apis/models/v2.py
Original file line number Diff line number Diff line change
Expand Up @@ -1485,3 +1485,10 @@ def __init__(self, api):
"strength": fields.Float(description="Optional field, determining the strength to use for the processing", default=1.0),
},
)
self.model_extra_texts = api.model(
"ExtraText",
{
"text": fields.String(description="The extra text to send along with this generation.", min_length=1),
"reference": fields.String(description="The reference which points how and where this text should be used.", min_length=3),
},
)
16 changes: 13 additions & 3 deletions horde/apis/v2/stable.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
from horde.logger import logger
from horde.model_reference import model_reference
from horde.patreon import patrons
from horde.utils import hash_dictionary
from horde.utils import does_extra_text_reference_exist, hash_dictionary
from horde.vars import horde_title

models = ImageModels(api)
Expand Down Expand Up @@ -100,9 +100,7 @@ def get_size_too_big_message(self):
)

def validate(self):
# logger.warning(datetime.utcnow())
super().validate()
# logger.warning(datetime.utcnow())
# During raids, we prevent VPNs
if settings.mode_raid() and not self.user.trusted and not patrons.is_patron(self.user.id):
self.safe_ip = CounterMeasures.is_ip_safe(self.user_ip)
Expand Down Expand Up @@ -187,6 +185,18 @@ def validate(self):
if self.args.extra_source_images is not None and len(self.args.extra_source_images) > 0:
if self.args.source_processing != "remix":
raise e.BadRequest("This request type does not accept extra source images.", rc="InvalidExtraSourceImages.")
if self.params.get("extra_texts") is not None and len(self.params.get("extra_texts")) > 0:
if self.params.get("workflow") not in ["qr_code"]:
raise e.BadRequest("This request type does not accept extra texts.", rc="InvalidExtraTexts.")
if self.params.get("workflow") == "qr_code":
# QR-code pipeline cannot do batching currently
self.args["disable_batching"] = True
if not all(model_reference.get_model_baseline(model_name).startswith("stable diffusion 1") for model_name in self.args.models):
raise e.BadRequest("QR Code controlnet only works with SD 1.5 models currently", rc="ControlNetMismatch.")
if self.params.get("extra_texts") is None or len(self.params.get("extra_texts")) == 0:
raise e.BadRequest("This request requires you pass the required extra texts for this workflow.", rc="MissingExtraTexts.")
if not does_extra_text_reference_exist(self.params.get("extra_texts"), "qr_code"):
raise e.BadRequest("This request requires you pass the required extra texts for this workflow.", rc="MissingExtraTexts.")
if self.params.get("init_as_image") and self.params.get("return_control_map"):
raise e.UnsupportedModel(
"Invalid ControlNet parameters - cannot send inital map and return the same map",
Expand Down
1 change: 1 addition & 0 deletions horde/bridge_reference.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

BRIDGE_CAPABILITIES = {
"AI Horde Worker reGen": {
7: {"qr_code", "extra_texts", "worfkflow"},
6: {"stable_cascade_2pass"},
5: {"extra_source_images"},
3: {"lora_versions"},
Expand Down
11 changes: 11 additions & 0 deletions horde/classes/base/news.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,17 @@

class News:
HORDE_NEWS = [
{
"date_published": "2024-05-20",
"newspiece": (
"You can now generate QR Codes on the AI Horde!"
"Currently this functionality is only available for Stable Diffusion 1.5."
"To use this functionality, your frontend needs to support it so that you can type the text you wish"
"to be made into a QR code and to specify the specific qr_code workflow."
),
"tags": ["db0", "nlnet", "text2img"],
"importance": "Information",
},
{
"date_published": "2024-05-12",
"newspiece": (
Expand Down
4 changes: 3 additions & 1 deletion horde/consts.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
HORDE_VERSION = "4.34.1"
HORDE_VERSION = "4.35.0"

WHITELISTED_SERVICE_IPS = {
"212.227.227.178", # Turing Bot
Expand Down Expand Up @@ -52,6 +52,8 @@
"lcm",
}

KNOWN_WORKFLOWS = {"qr_code"}

# These samplers perform double the steps per image
# As such we need to take it into account for the upfront kudos requirements
SECOND_ORDER_SAMPLERS = [
Expand Down
1 change: 0 additions & 1 deletion horde/database/functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,6 @@ def find_user_by_sharedkey(shared_key):
try:
sharedkey_uuid = uuid.UUID(shared_key)
except ValueError:
logger.debug(f"Non-UUID sharedkey_id sent: '{shared_key}'.")
return None
if SQLITE_MODE:
sharedkey_uuid = str(sharedkey_uuid)
Expand Down
2 changes: 2 additions & 0 deletions horde/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,8 @@
"ExcessiveStopSequence",
"TokenOverflow",
"MoreThanMinExtraSourceImage",
"InvalidExtraTexts",
"MissingExtraTexts",
]


Expand Down
7 changes: 7 additions & 0 deletions horde/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,3 +120,10 @@ def validate_regex(regex_string):
except Exception:
return False
return True


def does_extra_text_reference_exist(extra_texts, reference):
for et in extra_texts:
if et["reference"] == reference:
return True
return False

0 comments on commit 1467ad7

Please sign in to comment.