novelai-python 0.7.0__tar.gz → 0.7.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. {novelai_python-0.7.0 → novelai_python-0.7.2}/PKG-INFO +1 -1
  2. {novelai_python-0.7.0 → novelai_python-0.7.2}/pyproject.toml +1 -1
  3. {novelai_python-0.7.0 → novelai_python-0.7.2}/src/novelai_python/sdk/ai/_enum.py +75 -34
  4. {novelai_python-0.7.0 → novelai_python-0.7.2}/src/novelai_python/sdk/ai/generate_image/__init__.py +127 -24
  5. {novelai_python-0.7.0 → novelai_python-0.7.2}/tests/test_random_prompt.py +1 -1
  6. {novelai_python-0.7.0 → novelai_python-0.7.2}/LICENSE +0 -0
  7. {novelai_python-0.7.0 → novelai_python-0.7.2}/NOTICE.MD +0 -0
  8. {novelai_python-0.7.0 → novelai_python-0.7.2}/README.md +0 -0
  9. {novelai_python-0.7.0 → novelai_python-0.7.2}/src/novelai_python/__init__.py +0 -0
  10. {novelai_python-0.7.0 → novelai_python-0.7.2}/src/novelai_python/_enum.py +0 -0
  11. {novelai_python-0.7.0 → novelai_python-0.7.2}/src/novelai_python/_exceptions.py +0 -0
  12. {novelai_python-0.7.0 → novelai_python-0.7.2}/src/novelai_python/_response/__init__.py +0 -0
  13. {novelai_python-0.7.0 → novelai_python-0.7.2}/src/novelai_python/_response/ai/__init__.py +0 -0
  14. {novelai_python-0.7.0 → novelai_python-0.7.2}/src/novelai_python/_response/ai/generate.py +0 -0
  15. {novelai_python-0.7.0 → novelai_python-0.7.2}/src/novelai_python/_response/ai/generate_image.py +0 -0
  16. {novelai_python-0.7.0 → novelai_python-0.7.2}/src/novelai_python/_response/ai/generate_stream.py +0 -0
  17. {novelai_python-0.7.0 → novelai_python-0.7.2}/src/novelai_python/_response/ai/generate_voice.py +0 -0
  18. {novelai_python-0.7.0 → novelai_python-0.7.2}/src/novelai_python/_response/ai/upscale.py +0 -0
  19. {novelai_python-0.7.0 → novelai_python-0.7.2}/src/novelai_python/_response/schema.py +0 -0
  20. {novelai_python-0.7.0 → novelai_python-0.7.2}/src/novelai_python/_response/user/__init__.py +0 -0
  21. {novelai_python-0.7.0 → novelai_python-0.7.2}/src/novelai_python/_response/user/information.py +0 -0
  22. {novelai_python-0.7.0 → novelai_python-0.7.2}/src/novelai_python/_response/user/login.py +0 -0
  23. {novelai_python-0.7.0 → novelai_python-0.7.2}/src/novelai_python/_response/user/subscription.py +0 -0
  24. {novelai_python-0.7.0 → novelai_python-0.7.2}/src/novelai_python/credential/ApiToken.py +0 -0
  25. {novelai_python-0.7.0 → novelai_python-0.7.2}/src/novelai_python/credential/JwtToken.py +0 -0
  26. {novelai_python-0.7.0 → novelai_python-0.7.2}/src/novelai_python/credential/UserAuth.py +0 -0
  27. {novelai_python-0.7.0 → novelai_python-0.7.2}/src/novelai_python/credential/__init__.py +0 -0
  28. {novelai_python-0.7.0 → novelai_python-0.7.2}/src/novelai_python/credential/_base.py +0 -0
  29. {novelai_python-0.7.0 → novelai_python-0.7.2}/src/novelai_python/sdk/__init__.py +0 -0
  30. {novelai_python-0.7.0 → novelai_python-0.7.2}/src/novelai_python/sdk/ai/LICENSE +0 -0
  31. {novelai_python-0.7.0 → novelai_python-0.7.2}/src/novelai_python/sdk/ai/__init__.py +0 -0
  32. {novelai_python-0.7.0 → novelai_python-0.7.2}/src/novelai_python/sdk/ai/_const.py +0 -0
  33. {novelai_python-0.7.0 → novelai_python-0.7.2}/src/novelai_python/sdk/ai/_cost.py +0 -0
  34. {novelai_python-0.7.0 → novelai_python-0.7.2}/src/novelai_python/sdk/ai/augment_image/__init__.py +0 -0
  35. {novelai_python-0.7.0 → novelai_python-0.7.2}/src/novelai_python/sdk/ai/augment_image/_enum.py +0 -0
  36. {novelai_python-0.7.0 → novelai_python-0.7.2}/src/novelai_python/sdk/ai/generate/__init__.py +0 -0
  37. {novelai_python-0.7.0 → novelai_python-0.7.2}/src/novelai_python/sdk/ai/generate/_const.py +0 -0
  38. {novelai_python-0.7.0 → novelai_python-0.7.2}/src/novelai_python/sdk/ai/generate/_enum.py +0 -0
  39. {novelai_python-0.7.0 → novelai_python-0.7.2}/src/novelai_python/sdk/ai/generate/_schema.py +0 -0
  40. {novelai_python-0.7.0 → novelai_python-0.7.2}/src/novelai_python/sdk/ai/generate/themes.json +0 -0
  41. {novelai_python-0.7.0 → novelai_python-0.7.2}/src/novelai_python/sdk/ai/generate_image/schema.py +0 -0
  42. {novelai_python-0.7.0 → novelai_python-0.7.2}/src/novelai_python/sdk/ai/generate_image/suggest_tags.py +0 -0
  43. {novelai_python-0.7.0 → novelai_python-0.7.2}/src/novelai_python/sdk/ai/generate_stream.py +0 -0
  44. {novelai_python-0.7.0 → novelai_python-0.7.2}/src/novelai_python/sdk/ai/generate_voice/__init__.py +0 -0
  45. {novelai_python-0.7.0 → novelai_python-0.7.2}/src/novelai_python/sdk/ai/generate_voice/_enum.py +0 -0
  46. {novelai_python-0.7.0 → novelai_python-0.7.2}/src/novelai_python/sdk/ai/upscale.py +0 -0
  47. {novelai_python-0.7.0 → novelai_python-0.7.2}/src/novelai_python/sdk/schema.py +0 -0
  48. {novelai_python-0.7.0 → novelai_python-0.7.2}/src/novelai_python/sdk/user/__init__.py +0 -0
  49. {novelai_python-0.7.0 → novelai_python-0.7.2}/src/novelai_python/sdk/user/information.py +0 -0
  50. {novelai_python-0.7.0 → novelai_python-0.7.2}/src/novelai_python/sdk/user/login.py +0 -0
  51. {novelai_python-0.7.0 → novelai_python-0.7.2}/src/novelai_python/sdk/user/subscription.py +0 -0
  52. {novelai_python-0.7.0 → novelai_python-0.7.2}/src/novelai_python/server.py +0 -0
  53. {novelai_python-0.7.0 → novelai_python-0.7.2}/src/novelai_python/tokenizer/__init__.py +0 -0
  54. {novelai_python-0.7.0 → novelai_python-0.7.2}/src/novelai_python/tokenizer/clip_simple_tokenizer.py +0 -0
  55. {novelai_python-0.7.0 → novelai_python-0.7.2}/src/novelai_python/tokenizer/nerdstash_v1.model +0 -0
  56. {novelai_python-0.7.0 → novelai_python-0.7.2}/src/novelai_python/tokenizer/nerdstash_v2.model +0 -0
  57. {novelai_python-0.7.0 → novelai_python-0.7.2}/src/novelai_python/tokenizer/novelai.model +0 -0
  58. {novelai_python-0.7.0 → novelai_python-0.7.2}/src/novelai_python/tokenizer/novelai_v2.model +0 -0
  59. {novelai_python-0.7.0 → novelai_python-0.7.2}/src/novelai_python/tool/__init__.py +0 -0
  60. {novelai_python-0.7.0 → novelai_python-0.7.2}/src/novelai_python/tool/image_metadata/__init__.py +0 -0
  61. {novelai_python-0.7.0 → novelai_python-0.7.2}/src/novelai_python/tool/image_metadata/bch_utils.py +0 -0
  62. {novelai_python-0.7.0 → novelai_python-0.7.2}/src/novelai_python/tool/image_metadata/lsb_extractor.py +0 -0
  63. {novelai_python-0.7.0 → novelai_python-0.7.2}/src/novelai_python/tool/image_metadata/lsb_injector.py +0 -0
  64. {novelai_python-0.7.0 → novelai_python-0.7.2}/src/novelai_python/tool/paint_mask/__init__.py +0 -0
  65. {novelai_python-0.7.0 → novelai_python-0.7.2}/src/novelai_python/tool/random_prompt/__init__.py +0 -0
  66. {novelai_python-0.7.0 → novelai_python-0.7.2}/src/novelai_python/tool/random_prompt/generate_scene_composition.py +0 -0
  67. {novelai_python-0.7.0 → novelai_python-0.7.2}/src/novelai_python/tool/random_prompt/generate_scene_tags.py +0 -0
  68. {novelai_python-0.7.0 → novelai_python-0.7.2}/src/novelai_python/tool/random_prompt/generate_tags.py +0 -0
  69. {novelai_python-0.7.0 → novelai_python-0.7.2}/src/novelai_python/utils/__init__.py +0 -0
  70. {novelai_python-0.7.0 → novelai_python-0.7.2}/src/novelai_python/utils/encode.py +0 -0
  71. {novelai_python-0.7.0 → novelai_python-0.7.2}/src/novelai_python/utils/useful.py +0 -0
  72. {novelai_python-0.7.0 → novelai_python-0.7.2}/tests/__init__.py +0 -0
  73. {novelai_python-0.7.0 → novelai_python-0.7.2}/tests/test_generate_voice.py +0 -0
  74. {novelai_python-0.7.0 → novelai_python-0.7.2}/tests/test_server.py +0 -0
  75. {novelai_python-0.7.0 → novelai_python-0.7.2}/tests/test_server_run.py +0 -0
  76. {novelai_python-0.7.0 → novelai_python-0.7.2}/tests/test_tokenizer.py +0 -0
  77. {novelai_python-0.7.0 → novelai_python-0.7.2}/tests/test_upscale.py +0 -0
  78. {novelai_python-0.7.0 → novelai_python-0.7.2}/tests/test_user_information.py +0 -0
  79. {novelai_python-0.7.0 → novelai_python-0.7.2}/tests/test_user_login.py +0 -0
  80. {novelai_python-0.7.0 → novelai_python-0.7.2}/tests/test_user_subscription.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: novelai-python
3
- Version: 0.7.0
3
+ Version: 0.7.2
4
4
  Summary: NovelAI Python Binding With Pydantic
5
5
  Author-Email: sudoskys <coldlando@hotmail.com>
6
6
  License: Apache License 2.0
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "novelai-python"
3
- version = "0.7.0"
3
+ version = "0.7.2"
4
4
  description = "NovelAI Python Binding With Pydantic"
5
5
  authors = [
6
6
  { name = "sudoskys", email = "coldlando@hotmail.com" },
@@ -361,6 +361,7 @@ def get_default_noise_schedule(sample_type: Sampler) -> NoiseSchedule:
361
361
 
362
362
 
363
363
  def get_model_group(model: ModelTypeAlias) -> ModelGroups:
364
+ # 一般情况禁止转换
364
365
  if isinstance(model, Enum):
365
366
  model = model.value
366
367
  else:
@@ -387,49 +388,89 @@ def get_model_group(model: ModelTypeAlias) -> ModelGroups:
387
388
  return mapping.get(model, ModelGroups.STABLE_DIFFUSION)
388
389
 
389
390
 
390
- def get_default_uc_preset(model: ModelTypeAlias, uc_preset: int) -> str:
391
- if isinstance(model, Enum):
392
- model = model.value
393
- if isinstance(uc_preset, Enum):
394
- uc_preset = uc_preset.value
391
+ @dataclass
392
+ class UcPrompt:
393
+ category: str
394
+ name: str
395
+ text: str
395
396
 
396
- @dataclass
397
- class UcPrompt:
398
- label: str
399
- text: str
400
397
 
401
- mapper = {
402
- ModelGroups.STABLE_DIFFUSION: [
403
- UcPrompt("lowQualityPlusBadAnatomy",
398
+ def get_uc_preset(model: ModelTypeAlias) -> List[UcPrompt]:
399
+ prompts: List[UcPrompt] = []
400
+ if model in [
401
+ Model.SAFE_DIFFUSION,
402
+ Model.NAI_DIFFUSION,
403
+ Model.NAI_DIFFUSION_INPAINTING,
404
+ Model.SAFE_DIFFUSION_INPAINTING,
405
+ ]:
406
+ prompts = [
407
+ UcPrompt(category="heavy", name="lowQualityPlusBadAnatomy",
404
408
  text="lowres, bad anatomy, bad hands, text, error, missing fingers, extra digit, fewer digits, cropped, worst quality, low quality, normal quality, jpeg artifacts, signature, watermark, username, blurry"),
405
- UcPrompt("lowQuality",
409
+ UcPrompt(category="light", name="lowQuality",
406
410
  text="lowres, text, cropped, worst quality, low quality, normal quality, jpeg artifacts, signature, watermark, username, blurry"),
407
- UcPrompt("none", text="lowres")
408
- ],
409
- ModelGroups.STABLE_DIFFUSION_GROUP_2: [
410
- UcPrompt("heavy",
411
+ UcPrompt(category="none", name="none", text="lowres"),
412
+ ]
413
+ elif model in [
414
+ Model.NAI_DIFFUSION_FURRY,
415
+ Model.FURRY_DIFFUSION_INPAINTING,
416
+ ]:
417
+ prompts = [
418
+ UcPrompt(category="light", name="lowQuality",
419
+ text="worst quality, low quality, what has science done, what, nightmare fuel, eldritch horror, where is your god now, why"),
420
+ UcPrompt(category="heavy", name="badAnatomy",
421
+ text="{worst quality}, low quality, distracting watermark, [nightmare fuel], {{unfinished}}, deformed, outline, pattern, simple background"),
422
+ UcPrompt(category="none", name="none", text="low res"),
423
+ ]
424
+ elif model in [
425
+ Model.NAI_DIFFUSION_2,
426
+ ]:
427
+ prompts = [
428
+ UcPrompt(category="heavy", name="heavy",
411
429
  text="lowres, bad, text, error, missing, extra, fewer, cropped, jpeg artifacts, worst quality, bad quality, watermark, displeasing, unfinished, chromatic aberration, scan, scan artifacts"),
412
- UcPrompt("light", text="lowres, jpeg artifacts, worst quality, watermark, blurry, very displeasing"),
413
- UcPrompt("none", text="lowres")
414
- ],
415
- ModelGroups.STABLE_DIFFUSION_XL: [
416
- UcPrompt("heavy",
430
+ UcPrompt(category="light", name="light",
431
+ text="lowres, jpeg artifacts, worst quality, watermark, blurry, very displeasing"),
432
+ UcPrompt(category="none", name="none", text="lowres"),
433
+ ]
434
+ elif model in [
435
+ Model.NAI_DIFFUSION_3,
436
+ Model.NAI_DIFFUSION_3_INPAINTING,
437
+ ]:
438
+ prompts = [
439
+ UcPrompt(category="heavy", name="heavy",
417
440
  text="lowres, {bad}, error, fewer, extra, missing, worst quality, jpeg artifacts, bad quality, watermark, unfinished, displeasing, chromatic aberration, signature, extra digits, artistic error, username, scan, [abstract]"),
418
- UcPrompt("light", text="lowres, jpeg artifacts, worst quality, watermark, blurry, very displeasing"),
419
- UcPrompt("humanFocus",
441
+ UcPrompt(category="light", name="light",
442
+ text="lowres, jpeg artifacts, worst quality, watermark, blurry, very displeasing"),
443
+ UcPrompt(category="human", name="humanFocus",
420
444
  text="lowres, {bad}, error, fewer, extra, missing, worst quality, jpeg artifacts, bad quality, watermark, unfinished, displeasing, chromatic aberration, signature, extra digits, artistic error, username, scan, [abstract], bad anatomy, bad hands, @_@, mismatched pupils, heart-shaped pupils, glowing eyes"),
421
- UcPrompt("none", text="lowres")
422
- ],
423
- ModelGroups.STABLE_DIFFUSION_XL_FURRY: [
424
- UcPrompt("heavy",
445
+ UcPrompt(category="none", name="none", text="lowres"),
446
+ ]
447
+ elif model in [
448
+ Model.NAI_DIFFUSION_FURRY_3,
449
+ Model.NAI_DIFFUSION_FURRY_3_INPAINTING,
450
+ ]:
451
+ prompts = [
452
+ UcPrompt(category="heavy", name="heavy",
425
453
  text="{{worst quality}}, [displeasing], {unusual pupils}, guide lines, {{unfinished}}, {bad}, url, artist name, {{tall image}}, mosaic, {sketch page}, comic panel, impact (font), [dated], {logo}, ych, {what}, {where is your god now}, {distorted text}, repeated text, {floating head}, {1994}, {widescreen}, absolutely everyone, sequence, {compression artifacts}, hard translated, {cropped}, {commissioner name}, unknown text, high contrast"),
426
- UcPrompt("light",
454
+ UcPrompt(category="light", name="light",
427
455
  text="{worst quality}, guide lines, unfinished, bad, url, tall image, widescreen, compression artifacts, unknown text"),
428
- UcPrompt("none", text="lowres")
429
- ],
430
- }
431
- model_group = get_model_group(model)
432
- prompts: List[UcPrompt] = mapper.get(model_group, [UcPrompt("none", "lowres")])
456
+ UcPrompt(category="none", name="none", text="lowres"),
457
+ ]
458
+ elif model in [
459
+ Model.CUSTOM,
460
+ Model.NAI_DIFFUSION_4_CURATED_PREVIEW,
461
+ ]:
462
+ prompts = [
463
+ UcPrompt(category="heavy", name="heavy",
464
+ text="blurry, lowres, error, film grain, scan artifacts, worst quality, bad quality, jpeg artifacts, very displeasing, chromatic aberration, logo, dated, signature, multiple views, gigantic breasts"),
465
+ UcPrompt(category="light", name="light",
466
+ text="blurry, lowres, error, worst quality, bad quality, jpeg artifacts, very displeasing, logo, dated, signature"),
467
+ UcPrompt(category="none", name="none", text=""),
468
+ ]
469
+ return prompts
470
+
471
+
472
+ def get_default_uc_preset(model: ModelTypeAlias, uc_preset: int) -> str:
473
+ prompts = get_uc_preset(model)
433
474
  if 0 <= uc_preset < len(prompts):
434
475
  return prompts[uc_preset].text
435
476
  else:
@@ -6,7 +6,9 @@ import base64
6
6
  import json
7
7
  import math
8
8
  import random
9
+ import re
9
10
  from copy import deepcopy
11
+ from enum import Enum
10
12
  from io import BytesIO
11
13
  from typing import Optional, Union, Tuple, List
12
14
  from urllib.parse import urlparse
@@ -28,7 +30,7 @@ from novelai_python.sdk.ai._enum import Model, Sampler, NoiseSchedule, ControlNe
28
30
  INPAINTING_MODEL_LIST, get_default_uc_preset, \
29
31
  ModelTypeAlias, UCPresetTypeAlias, get_default_noise_schedule, get_supported_noise_schedule, \
30
32
  get_model_group, ModelGroups, get_supported_params, get_modifiers, ImageBytesTypeAlias
31
- from .schema import Character, V4Prompt, V4NegativePrompt
33
+ from .schema import Character, V4Prompt, V4NegativePrompt, PositionMap
32
34
  from ...schema import ApiBaseModel
33
35
  from ...._exceptions import APIError, AuthError, ConcurrentGenerationError, SessionHttpError
34
36
  from ...._response.ai.generate_image import ImageGenerateResp, RequestParams
@@ -110,7 +112,7 @@ class Params(BaseModel):
110
112
  Overlay Original Image.Prevents the existing image from changing,
111
113
  but can introduce seams along the edge of the mask.
112
114
  """
113
- use_coords: bool = Field(True, description="Use Coordinates")
115
+ use_coords: bool = Field(False, description="Use Coordinates")
114
116
  """Use Coordinates"""
115
117
  characterPrompts: List[Character] = Field(default_factory=list)
116
118
  """Character Prompts"""
@@ -342,6 +344,35 @@ class Params(BaseModel):
342
344
 
343
345
  class GenerateImageInfer(ApiBaseModel):
344
346
  _endpoint: str = PrivateAttr("https://image.novelai.net")
347
+ _mutual_exclusion: bool = PrivateAttr(False)
348
+ """Positive words and negative words are mutually exclusive, and conflicting negative words are deleted first."""
349
+ _quality_modifier: bool = PrivateAttr(True)
350
+ """Add Quality Modifier To Input"""
351
+
352
+ def set_mutual_exclusion(self, value: bool):
353
+ """
354
+ **Enable This will modify the negative prompt.**
355
+ Default is False.
356
+
357
+ Positive words and negative words are mutually exclusive, and conflicting negative words are deleted first.
358
+ :param value: bool
359
+ :return: self
360
+ """
361
+ self._mutual_exclusion = bool(value)
362
+ return self
363
+
364
+ def set_quality_modifier(self, value: bool):
365
+ """
366
+ **Enable This will modify the input prompt.**
367
+ Default is True.
368
+
369
+ Add Quality Modifier To Input.
370
+ Whether to add the quality vocabulary used by the web application.
371
+ :param value:
372
+ :return:
373
+ """
374
+ self._quality_modifier = bool(value)
375
+ return self
345
376
 
346
377
  @property
347
378
  def endpoint(self):
@@ -371,15 +402,75 @@ class GenerateImageInfer(ApiBaseModel):
371
402
 
372
403
  # Add negative prompt based on ucPreset
373
404
  if self.parameters.ucPreset is not None:
374
- default_negative_prompt = get_default_uc_preset(self.model, self.parameters.ucPreset)
405
+ uc_preset = self.parameters.ucPreset
406
+ # If ucPreset is Enum, get the value
407
+ if isinstance(self.parameters.ucPreset, Enum):
408
+ uc_preset = self.parameters.ucPreset.value
409
+ default_negative_prompt = get_default_uc_preset(self.model, uc_preset)
375
410
  self.parameters.negative_prompt = ", ".join(
376
411
  filter(None, [default_negative_prompt, self.parameters.negative_prompt])
377
412
  )
378
413
 
379
- # Add quality prompt
414
+ # Add quality prompt based on qualityToggle
380
415
  modifier = get_modifiers(self.model)
381
- if self.parameters.qualityToggle:
382
- self.input += modifier.qualityTags
416
+ quality_tags, suffix = modifier.qualityTags, modifier.suffix
417
+
418
+ def enhance_text_part(_part, _quality_tags, _suffix):
419
+ text_parts = _part.split(" Text:")
420
+ enhanced_text_parts = [
421
+ _quality_tags + text_part + _suffix + ('.' if _suffix and len(text_parts) > 1 else '')
422
+ if index == 0
423
+ else text_part
424
+ for index, text_part in enumerate(text_parts)
425
+ ]
426
+ return " Text:".join(enhanced_text_parts)
427
+
428
+ def enhance_simple_part(_part, _quality_tags, _suffix):
429
+ match = re.search(r"(:[\d.]+$)", _part)
430
+ matched_value = match.group(0) if match else None
431
+ core_part = _part[:-len(matched_value)] if matched_value else _part
432
+ return _quality_tags + core_part + _suffix + (matched_value or "")
433
+
434
+ def enhance_message(_prompt):
435
+ try:
436
+ if get_supported_params(self.model).characterPrompts:
437
+ parts = _prompt.split("|")
438
+ enhanced_parts = [
439
+ quality_tags + part + suffix
440
+ if index == 0 and not get_supported_params(self.model).text
441
+ else enhance_text_part(part, quality_tags, suffix)
442
+ if index == 0
443
+ else part
444
+ for index, part in enumerate(parts)
445
+ ]
446
+ return "|".join(enhanced_parts)
447
+ else:
448
+ parts = _prompt.split("|")
449
+ enhanced_parts = [
450
+ enhance_simple_part(part, quality_tags, suffix)
451
+ for part in parts
452
+ ]
453
+ return "|".join(enhanced_parts)
454
+ except Exception as e:
455
+ logger.error(
456
+ f"Failed to enhance `{_prompt}` because {e},"
457
+ f"Report this issue to https://github.com/LLMKIRA/novelai-python/issues"
458
+ )
459
+ return _prompt
460
+
461
+ if self._quality_modifier:
462
+ logger.trace("Enhancing input with quality modifier, will modify input prompt.")
463
+ self.input = enhance_message(self.input)
464
+
465
+ if self._mutual_exclusion:
466
+ logger.trace("Mutual exclusion is enabled, will modify negative prompt.")
467
+ input_prompt = {x.strip(): x for x in self.input.split(",")}
468
+ uc_prompt = {x.strip(): x for x in self.parameters.negative_prompt.split(",")}
469
+ # Remove conflicting negative words
470
+ for key in input_prompt:
471
+ if key in uc_prompt:
472
+ uc_prompt.pop(key)
473
+ self.parameters.negative_prompt = ",".join(uc_prompt.values())
383
474
 
384
475
  @model_validator(mode="after")
385
476
  def _build_nai4_prompt(self):
@@ -417,7 +508,9 @@ class GenerateImageInfer(ApiBaseModel):
417
508
  @model_validator(mode="after")
418
509
  def _backend_logic(self):
419
510
  """
420
- Backend logic for GenerateImageInfer.
511
+ Calibration results.
512
+
513
+ **NOTE: It is forbidden to write logic that does not belong to novelai.net here**
421
514
  :return: self
422
515
  """
423
516
  if self.action == Action.GENERATE:
@@ -464,7 +557,30 @@ class GenerateImageInfer(ApiBaseModel):
464
557
  self.parameters.sm_dyn = True
465
558
 
466
559
  if self.parameters.sm_dyn and (not self.parameters.sm):
467
- self.parameters.sm_dyn = False
560
+ self.parameters.sm = True
561
+
562
+ # AUTO SMEA SETTING
563
+ """
564
+ def sm_size_cast(model: Model):
565
+ if model in [
566
+ Model.NAI_DIFFUSION_V3,
567
+ Model.NAI_DIFFUSION_V3_INPAINTING,
568
+ Model.NAI_DIFFUSION_FURRY_V3,
569
+ Model.NAI_DIFFUSION_FURRY_V3_INPAINTING,
570
+ Model.CUSTOM
571
+ ]:
572
+ return 2166785
573
+ return 1064961
574
+ if self.parameters.autoSmea and (self.parameters.width * self.parameters.height < sm_size_cast(self.model)):
575
+ self.parameters.autoSmea = False
576
+ """
577
+
578
+ if self.parameters.characterPrompts:
579
+ self.parameters.use_coords = any([c.center != PositionMap.AUTO for c in self.parameters.characterPrompts])
580
+
581
+ # Mix Prompt Warning
582
+ if self.input.count('|') > 6:
583
+ logger.warning("Maximum prompt mixes exceeded. Extra will be ignored.")
468
584
 
469
585
  if self.parameters.sampler in [
470
586
  Sampler.DDIM,
@@ -572,7 +688,6 @@ class GenerateImageInfer(ApiBaseModel):
572
688
  prompt: str,
573
689
  *,
574
690
  model: Union[Model, str],
575
- qualitySuffix: bool = True,
576
691
  negative_prompt: str = "",
577
692
  ucPreset: UCPresetTypeAlias = UCPreset.TYPE0,
578
693
  sm: bool = False,
@@ -602,7 +717,6 @@ class GenerateImageInfer(ApiBaseModel):
602
717
  :param prompt: Given prompt.
603
718
  :param model: Model for generation.
604
719
  :param negative_prompt: The things you don't want to see in the image.
605
- :param qualitySuffix: Add quality suffix to prompt
606
720
  :param ucPreset: The negative prompt preset.
607
721
  :param steps: The steps for generation.
608
722
  :param seed: The seed for generation.
@@ -619,9 +733,6 @@ class GenerateImageInfer(ApiBaseModel):
619
733
  """
620
734
  if character_prompts is None:
621
735
  character_prompts = []
622
- if qualitySuffix:
623
- modifier = get_modifiers(model)
624
- prompt += modifier.suffix
625
736
  if seed is None:
626
737
  seed = random.randint(0, 4294967295 - 7)
627
738
  if reference_strength_multiple is None:
@@ -668,7 +779,6 @@ class GenerateImageInfer(ApiBaseModel):
668
779
  seed: int = None,
669
780
  extra_noise_seed: int = None,
670
781
  model: Union[Model, str] = Model.NAI_DIFFUSION_3,
671
- qualitySuffix: bool = True,
672
782
  negative_prompt: str = "",
673
783
  ucPreset: UCPresetTypeAlias = UCPreset.TYPE0,
674
784
  steps: int = 23,
@@ -699,7 +809,6 @@ class GenerateImageInfer(ApiBaseModel):
699
809
  :param prompt: Given prompt.
700
810
  :param model: Model for generation.
701
811
  :param negative_prompt: The things you don't want to see in the image.
702
- :param qualitySuffix: Add quality suffix to prompt
703
812
  :param ucPreset: The negative prompt preset.
704
813
  :param steps: The steps for generation.
705
814
  :param seed: The seed for generation.
@@ -716,9 +825,6 @@ class GenerateImageInfer(ApiBaseModel):
716
825
  """
717
826
  if character_prompts is None:
718
827
  character_prompts = []
719
- if qualitySuffix:
720
- modifier = get_modifiers(model)
721
- prompt += modifier.suffix
722
828
  if seed is None:
723
829
  seed = random.randint(0, 4294967295 - 7)
724
830
  if extra_noise_seed is None:
@@ -768,7 +874,6 @@ class GenerateImageInfer(ApiBaseModel):
768
874
  mask: Union[bytes, str],
769
875
  strength: float = 0.7,
770
876
  model: Union[Model, str] = Model.NAI_DIFFUSION_3,
771
- qualitySuffix: bool = True,
772
877
  negative_prompt: str = "",
773
878
  ucPreset: UCPresetTypeAlias = UCPreset.TYPE0,
774
879
  steps: int = 23,
@@ -799,7 +904,6 @@ class GenerateImageInfer(ApiBaseModel):
799
904
  :param prompt: Given prompt.
800
905
  :param model: Model for generation.
801
906
  :param negative_prompt: The things you don't want to see in the image.
802
- :param qualitySuffix: Add quality suffix to prompt
803
907
  :param ucPreset: The negative prompt preset.
804
908
  :param steps: The steps for generation.
805
909
  :param seed: The seed for generation.
@@ -816,9 +920,6 @@ class GenerateImageInfer(ApiBaseModel):
816
920
  """
817
921
  if character_prompts is None:
818
922
  character_prompts = []
819
- if qualitySuffix:
820
- modifier = get_modifiers(model)
821
- prompt += modifier.suffix
822
923
  if seed is None:
823
924
  seed = random.randint(0, 4294967295 - 7)
824
925
  if reference_strength_multiple is None:
@@ -891,7 +992,9 @@ class GenerateImageInfer(ApiBaseModel):
891
992
  override_headers: Optional[dict] = None,
892
993
  ) -> ImageGenerateResp:
893
994
  """
894
- Generate images using NovelAI's diffusion models. According to our Terms of Service, all generation requests must be initiated by a human action. Automating text or image generation to create excessive load on our systems is not allowed.
995
+ **Generate images using NovelAI's diffusion models.**
996
+
997
+ According to our Terms of Service, all generation requests must be initiated by a human action. Automating text or image generation to create excessive load on our systems is not allowed.
895
998
 
896
999
  :param override_headers: the headers to override
897
1000
  :param session: session
@@ -58,4 +58,4 @@ def test_get_holiday_themed_tags():
58
58
  result_m = generator.get_holiday_themed_tags()
59
59
  result_f = generator.get_holiday_themed_tags()
60
60
  result_o = generator.get_holiday_themed_tags()
61
- assert result_m != result_f != result_o
61
+ assert len({result_m, result_f, result_o}) != 1
File without changes
File without changes
File without changes