novelai-python 0.7.11__tar.gz → 0.7.12__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 (82) hide show
  1. {novelai_python-0.7.11 → novelai_python-0.7.12}/PKG-INFO +1 -1
  2. {novelai_python-0.7.11 → novelai_python-0.7.12}/pyproject.toml +1 -1
  3. {novelai_python-0.7.11 → novelai_python-0.7.12}/src/novelai_python/sdk/ai/_enum.py +18 -18
  4. {novelai_python-0.7.11 → novelai_python-0.7.12}/src/novelai_python/sdk/ai/generate_image/__init__.py +14 -4
  5. {novelai_python-0.7.11 → novelai_python-0.7.12}/src/novelai_python/sdk/ai/generate_image/params.py +35 -4
  6. {novelai_python-0.7.11 → novelai_python-0.7.12}/src/novelai_python/sdk/ai/generate_image/schema.py +2 -2
  7. {novelai_python-0.7.11 → novelai_python-0.7.12}/src/novelai_python/utils/encode.py +1 -1
  8. {novelai_python-0.7.11 → novelai_python-0.7.12}/LICENSE +0 -0
  9. {novelai_python-0.7.11 → novelai_python-0.7.12}/NOTICE.MD +0 -0
  10. {novelai_python-0.7.11 → novelai_python-0.7.12}/README.md +0 -0
  11. {novelai_python-0.7.11 → novelai_python-0.7.12}/src/novelai_python/__init__.py +0 -0
  12. {novelai_python-0.7.11 → novelai_python-0.7.12}/src/novelai_python/_enum.py +0 -0
  13. {novelai_python-0.7.11 → novelai_python-0.7.12}/src/novelai_python/_exceptions.py +0 -0
  14. {novelai_python-0.7.11 → novelai_python-0.7.12}/src/novelai_python/_response/__init__.py +0 -0
  15. {novelai_python-0.7.11 → novelai_python-0.7.12}/src/novelai_python/_response/ai/__init__.py +0 -0
  16. {novelai_python-0.7.11 → novelai_python-0.7.12}/src/novelai_python/_response/ai/generate.py +0 -0
  17. {novelai_python-0.7.11 → novelai_python-0.7.12}/src/novelai_python/_response/ai/generate_image.py +0 -0
  18. {novelai_python-0.7.11 → novelai_python-0.7.12}/src/novelai_python/_response/ai/generate_stream.py +0 -0
  19. {novelai_python-0.7.11 → novelai_python-0.7.12}/src/novelai_python/_response/ai/generate_voice.py +0 -0
  20. {novelai_python-0.7.11 → novelai_python-0.7.12}/src/novelai_python/_response/ai/upscale.py +0 -0
  21. {novelai_python-0.7.11 → novelai_python-0.7.12}/src/novelai_python/_response/schema.py +0 -0
  22. {novelai_python-0.7.11 → novelai_python-0.7.12}/src/novelai_python/_response/user/__init__.py +0 -0
  23. {novelai_python-0.7.11 → novelai_python-0.7.12}/src/novelai_python/_response/user/information.py +0 -0
  24. {novelai_python-0.7.11 → novelai_python-0.7.12}/src/novelai_python/_response/user/login.py +0 -0
  25. {novelai_python-0.7.11 → novelai_python-0.7.12}/src/novelai_python/_response/user/subscription.py +0 -0
  26. {novelai_python-0.7.11 → novelai_python-0.7.12}/src/novelai_python/credential/ApiToken.py +0 -0
  27. {novelai_python-0.7.11 → novelai_python-0.7.12}/src/novelai_python/credential/JwtToken.py +0 -0
  28. {novelai_python-0.7.11 → novelai_python-0.7.12}/src/novelai_python/credential/UserAuth.py +0 -0
  29. {novelai_python-0.7.11 → novelai_python-0.7.12}/src/novelai_python/credential/__init__.py +0 -0
  30. {novelai_python-0.7.11 → novelai_python-0.7.12}/src/novelai_python/credential/_base.py +0 -0
  31. {novelai_python-0.7.11 → novelai_python-0.7.12}/src/novelai_python/sdk/__init__.py +0 -0
  32. {novelai_python-0.7.11 → novelai_python-0.7.12}/src/novelai_python/sdk/ai/LICENSE +0 -0
  33. {novelai_python-0.7.11 → novelai_python-0.7.12}/src/novelai_python/sdk/ai/__init__.py +0 -0
  34. {novelai_python-0.7.11 → novelai_python-0.7.12}/src/novelai_python/sdk/ai/_const.py +0 -0
  35. {novelai_python-0.7.11 → novelai_python-0.7.12}/src/novelai_python/sdk/ai/_cost.py +0 -0
  36. {novelai_python-0.7.11 → novelai_python-0.7.12}/src/novelai_python/sdk/ai/augment_image/__init__.py +0 -0
  37. {novelai_python-0.7.11 → novelai_python-0.7.12}/src/novelai_python/sdk/ai/augment_image/_enum.py +0 -0
  38. {novelai_python-0.7.11 → novelai_python-0.7.12}/src/novelai_python/sdk/ai/generate/__init__.py +0 -0
  39. {novelai_python-0.7.11 → novelai_python-0.7.12}/src/novelai_python/sdk/ai/generate/_const.py +0 -0
  40. {novelai_python-0.7.11 → novelai_python-0.7.12}/src/novelai_python/sdk/ai/generate/_enum.py +0 -0
  41. {novelai_python-0.7.11 → novelai_python-0.7.12}/src/novelai_python/sdk/ai/generate/_schema.py +0 -0
  42. {novelai_python-0.7.11 → novelai_python-0.7.12}/src/novelai_python/sdk/ai/generate/themes.json +0 -0
  43. {novelai_python-0.7.11 → novelai_python-0.7.12}/src/novelai_python/sdk/ai/generate_image/suggest_tags.py +0 -0
  44. {novelai_python-0.7.11 → novelai_python-0.7.12}/src/novelai_python/sdk/ai/generate_image/tokenizer.py +0 -0
  45. {novelai_python-0.7.11 → novelai_python-0.7.12}/src/novelai_python/sdk/ai/generate_stream.py +0 -0
  46. {novelai_python-0.7.11 → novelai_python-0.7.12}/src/novelai_python/sdk/ai/generate_voice/__init__.py +0 -0
  47. {novelai_python-0.7.11 → novelai_python-0.7.12}/src/novelai_python/sdk/ai/generate_voice/_enum.py +0 -0
  48. {novelai_python-0.7.11 → novelai_python-0.7.12}/src/novelai_python/sdk/ai/upscale.py +0 -0
  49. {novelai_python-0.7.11 → novelai_python-0.7.12}/src/novelai_python/sdk/schema.py +0 -0
  50. {novelai_python-0.7.11 → novelai_python-0.7.12}/src/novelai_python/sdk/user/__init__.py +0 -0
  51. {novelai_python-0.7.11 → novelai_python-0.7.12}/src/novelai_python/sdk/user/information.py +0 -0
  52. {novelai_python-0.7.11 → novelai_python-0.7.12}/src/novelai_python/sdk/user/login.py +0 -0
  53. {novelai_python-0.7.11 → novelai_python-0.7.12}/src/novelai_python/sdk/user/subscription.py +0 -0
  54. {novelai_python-0.7.11 → novelai_python-0.7.12}/src/novelai_python/server.py +0 -0
  55. {novelai_python-0.7.11 → novelai_python-0.7.12}/src/novelai_python/tokenizer/__init__.py +0 -0
  56. {novelai_python-0.7.11 → novelai_python-0.7.12}/src/novelai_python/tokenizer/clip_simple_tokenizer.py +0 -0
  57. {novelai_python-0.7.11 → novelai_python-0.7.12}/src/novelai_python/tokenizer/nerdstash_v1.model +0 -0
  58. {novelai_python-0.7.11 → novelai_python-0.7.12}/src/novelai_python/tokenizer/nerdstash_v2.model +0 -0
  59. {novelai_python-0.7.11 → novelai_python-0.7.12}/src/novelai_python/tokenizer/novelai.model +0 -0
  60. {novelai_python-0.7.11 → novelai_python-0.7.12}/src/novelai_python/tokenizer/novelai_v2.model +0 -0
  61. {novelai_python-0.7.11 → novelai_python-0.7.12}/src/novelai_python/tool/__init__.py +0 -0
  62. {novelai_python-0.7.11 → novelai_python-0.7.12}/src/novelai_python/tool/image_metadata/__init__.py +0 -0
  63. {novelai_python-0.7.11 → novelai_python-0.7.12}/src/novelai_python/tool/image_metadata/bch_utils.py +0 -0
  64. {novelai_python-0.7.11 → novelai_python-0.7.12}/src/novelai_python/tool/image_metadata/lsb_extractor.py +0 -0
  65. {novelai_python-0.7.11 → novelai_python-0.7.12}/src/novelai_python/tool/image_metadata/lsb_injector.py +0 -0
  66. {novelai_python-0.7.11 → novelai_python-0.7.12}/src/novelai_python/tool/paint_mask/__init__.py +0 -0
  67. {novelai_python-0.7.11 → novelai_python-0.7.12}/src/novelai_python/tool/random_prompt/__init__.py +0 -0
  68. {novelai_python-0.7.11 → novelai_python-0.7.12}/src/novelai_python/tool/random_prompt/generate_scene_composition.py +0 -0
  69. {novelai_python-0.7.11 → novelai_python-0.7.12}/src/novelai_python/tool/random_prompt/generate_scene_tags.py +0 -0
  70. {novelai_python-0.7.11 → novelai_python-0.7.12}/src/novelai_python/tool/random_prompt/generate_tags.py +0 -0
  71. {novelai_python-0.7.11 → novelai_python-0.7.12}/src/novelai_python/utils/__init__.py +0 -0
  72. {novelai_python-0.7.11 → novelai_python-0.7.12}/src/novelai_python/utils/useful.py +0 -0
  73. {novelai_python-0.7.11 → novelai_python-0.7.12}/tests/__init__.py +0 -0
  74. {novelai_python-0.7.11 → novelai_python-0.7.12}/tests/test_generate_voice.py +0 -0
  75. {novelai_python-0.7.11 → novelai_python-0.7.12}/tests/test_random_prompt.py +0 -0
  76. {novelai_python-0.7.11 → novelai_python-0.7.12}/tests/test_server.py +0 -0
  77. {novelai_python-0.7.11 → novelai_python-0.7.12}/tests/test_server_run.py +0 -0
  78. {novelai_python-0.7.11 → novelai_python-0.7.12}/tests/test_tokenizer.py +0 -0
  79. {novelai_python-0.7.11 → novelai_python-0.7.12}/tests/test_upscale.py +0 -0
  80. {novelai_python-0.7.11 → novelai_python-0.7.12}/tests/test_user_information.py +0 -0
  81. {novelai_python-0.7.11 → novelai_python-0.7.12}/tests/test_user_login.py +0 -0
  82. {novelai_python-0.7.11 → novelai_python-0.7.12}/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.11
3
+ Version: 0.7.12
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.11"
3
+ version = "0.7.12"
4
4
  description = "NovelAI Python Binding With Pydantic"
5
5
  authors = [
6
6
  { name = "sudoskys", email = "coldlando@hotmail.com" },
@@ -464,7 +464,7 @@ def get_modifiers(model: Model) -> Modifier:
464
464
  ]:
465
465
  return Modifier(
466
466
  qualityTags="",
467
- suffix=", location, very aesthetic, masterpiece, no text"
467
+ suffix=", very aesthetic, masterpiece, no text"
468
468
  )
469
469
  if model in [
470
470
  Model.NAI_DIFFUSION_4_5_CURATED,
@@ -661,12 +661,12 @@ def get_uc_preset(model: ModelTypeAlias) -> List[UcPrompt]:
661
661
  UcPrompt(
662
662
  category="heavy",
663
663
  name="lowQualityPlusBadAnatomy",
664
- 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"
664
+ text="nsfw, 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"
665
665
  ),
666
666
  UcPrompt(
667
667
  category="light",
668
668
  name="lowQuality",
669
- text="lowres, text, cropped, worst quality, low quality, normal quality, jpeg artifacts, signature, watermark, username, blurry"
669
+ text="nsfw, lowres, text, cropped, worst quality, low quality, normal quality, jpeg artifacts, signature, watermark, username, blurry"
670
670
  ),
671
671
  UcPrompt(
672
672
  category="none",
@@ -682,12 +682,12 @@ def get_uc_preset(model: ModelTypeAlias) -> List[UcPrompt]:
682
682
  UcPrompt(
683
683
  category="light",
684
684
  name="lowQuality",
685
- text="worst quality, low quality, what has science done, what, nightmare fuel, eldritch horror, where is your god now, why"
685
+ text="nsfw, worst quality, low quality, what has science done, what, nightmare fuel, eldritch horror, where is your god now, why"
686
686
  ),
687
687
  UcPrompt(
688
688
  category="heavy",
689
689
  name="badAnatomy",
690
- text="{worst quality}, low quality, distracting watermark, [nightmare fuel], {{unfinished}}, deformed, outline, pattern, simple background"
690
+ text="nsfw, {worst quality}, low quality, distracting watermark, [nightmare fuel], {{unfinished}}, deformed, outline, pattern, simple background"
691
691
  ),
692
692
  UcPrompt(
693
693
  category="none",
@@ -702,12 +702,12 @@ def get_uc_preset(model: ModelTypeAlias) -> List[UcPrompt]:
702
702
  UcPrompt(
703
703
  category="heavy",
704
704
  name="heavy",
705
- text="lowres, bad, text, error, missing, extra, fewer, cropped, jpeg artifacts, worst quality, bad quality, watermark, displeasing, unfinished, chromatic aberration, scan, scan artifacts"
705
+ text="nsfw, lowres, bad, text, error, missing, extra, fewer, cropped, jpeg artifacts, worst quality, bad quality, watermark, displeasing, unfinished, chromatic aberration, scan, scan artifacts"
706
706
  ),
707
707
  UcPrompt(
708
708
  category="light",
709
709
  name="light",
710
- text="lowres, jpeg artifacts, worst quality, watermark, blurry, very displeasing"
710
+ text="nsfw, lowres, jpeg artifacts, worst quality, watermark, blurry, very displeasing"
711
711
  ),
712
712
  UcPrompt(
713
713
  category="none",
@@ -723,17 +723,17 @@ def get_uc_preset(model: ModelTypeAlias) -> List[UcPrompt]:
723
723
  UcPrompt(
724
724
  category="heavy",
725
725
  name="heavy",
726
- 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]"
726
+ text="nsfw, 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]"
727
727
  ),
728
728
  UcPrompt(
729
729
  category="light",
730
730
  name="light",
731
- text="lowres, jpeg artifacts, worst quality, watermark, blurry, very displeasing"
731
+ text="nsfw, lowres, jpeg artifacts, worst quality, watermark, blurry, very displeasing"
732
732
  ),
733
733
  UcPrompt(
734
734
  category="human",
735
735
  name="humanFocus",
736
- 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"
736
+ text="nsfw, 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"
737
737
  ),
738
738
  UcPrompt(
739
739
  category="none",
@@ -749,12 +749,12 @@ def get_uc_preset(model: ModelTypeAlias) -> List[UcPrompt]:
749
749
  UcPrompt(
750
750
  category="heavy",
751
751
  name="heavy",
752
- 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"
752
+ text="nsfw, {{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"
753
753
  ),
754
754
  UcPrompt(
755
755
  category="light",
756
756
  name="light",
757
- text="{worst quality}, guide lines, unfinished, bad, url, tall image, widescreen, compression artifacts, unknown text"
757
+ text="nsfw, {worst quality}, guide lines, unfinished, bad, url, tall image, widescreen, compression artifacts, unknown text"
758
758
  ),
759
759
  UcPrompt(
760
760
  category="none",
@@ -791,12 +791,12 @@ def get_uc_preset(model: ModelTypeAlias) -> List[UcPrompt]:
791
791
  UcPrompt(
792
792
  category="heavy",
793
793
  name="heavy",
794
- text="blurry, lowres, error, film grain, scan artifacts, worst quality, bad quality, jpeg artifacts, very displeasing, chromatic aberration, multiple views, logo, too many watermarks, white blank page, blank page"
794
+ text="nsfw, blurry, lowres, error, film grain, scan artifacts, worst quality, bad quality, jpeg artifacts, very displeasing, chromatic aberration, multiple views, logo, too many watermarks, white blank page, blank page"
795
795
  ),
796
796
  UcPrompt(
797
797
  category="light",
798
798
  name="light",
799
- text="blurry, lowres, error, worst quality, bad quality, jpeg artifacts, very displeasing, white blank page, blank page"
799
+ text="nsfw, blurry, lowres, error, worst quality, bad quality, jpeg artifacts, very displeasing, white blank page, blank page"
800
800
  ),
801
801
  UcPrompt(
802
802
  category="none",
@@ -839,22 +839,22 @@ def get_uc_preset(model: ModelTypeAlias) -> List[UcPrompt]:
839
839
  UcPrompt(
840
840
  category="heavy",
841
841
  name="heavy",
842
- text="lowres, artistic error, film grain, scan artifacts, worst quality, bad quality, jpeg artifacts, very displeasing, chromatic aberration, dithering, halftone, screentone, multiple views, logo, too many watermarks, negative space, blank page"
842
+ text="nsfw, lowres, artistic error, film grain, scan artifacts, worst quality, bad quality, jpeg artifacts, very displeasing, chromatic aberration, dithering, halftone, screentone, multiple views, logo, too many watermarks, negative space, blank page"
843
843
  ),
844
844
  UcPrompt(
845
845
  category="light",
846
846
  name="light",
847
- text="lowres, artistic error, scan artifacts, worst quality, bad quality, jpeg artifacts, multiple views, very displeasing, too many watermarks, negative space, blank page"
847
+ text="nsfw, lowres, artistic error, scan artifacts, worst quality, bad quality, jpeg artifacts, multiple views, very displeasing, too many watermarks, negative space, blank page"
848
848
  ),
849
849
  UcPrompt(
850
850
  category="furry",
851
851
  name="furryFocus",
852
- text="{worst quality}, distracting watermark, unfinished, bad quality, {widescreen}, upscale, {sequence}, {{grandfathered content}}, blurred foreground, chromatic aberration, sketch, everyone, [sketch background], simple, [flat colors], ych (character), outline, multiple scenes, [[horror (theme)]], comic"
852
+ text="nsfw, {worst quality}, distracting watermark, unfinished, bad quality, {widescreen}, upscale, {sequence}, {{grandfathered content}}, blurred foreground, chromatic aberration, sketch, everyone, [sketch background], simple, [flat colors], ych (character), outline, multiple scenes, [[horror (theme)]], comic"
853
853
  ),
854
854
  UcPrompt(
855
855
  category="human",
856
856
  name="humanFocus",
857
- text="lowres, artistic error, film grain, scan artifacts, worst quality, bad quality, jpeg artifacts, very displeasing, chromatic aberration, dithering, halftone, screentone, multiple views, logo, too many watermarks, negative space, blank page, @_@, mismatched pupils, glowing eyes, bad anatomy"
857
+ text="nsfw, lowres, artistic error, film grain, scan artifacts, worst quality, bad quality, jpeg artifacts, very displeasing, chromatic aberration, dithering, halftone, screentone, multiple views, logo, too many watermarks, negative space, blank page, @_@, mismatched pupils, glowing eyes, bad anatomy"
858
858
  ),
859
859
  UcPrompt(
860
860
  category="none",
@@ -157,7 +157,14 @@ class GenerateImageInfer(ApiBaseModel):
157
157
  for key in input_prompt:
158
158
  if key in uc_prompt:
159
159
  uc_prompt.pop(key)
160
- self.parameters.negative_prompt = ",".join(uc_prompt.values())
160
+ self.parameters.negative_prompt = ",".join(uc_prompt.values()).strip()
161
+
162
+ # Instantly remove nsfw if input contains it
163
+ elif "nsfw" in self.input and "nsfw" in self.parameters.negative_prompt:
164
+ uc_prompt = {x.strip(): x for x in self.parameters.negative_prompt.split(",")}
165
+ uc_prompt.pop("nsfw", None)
166
+
167
+ self.parameters.negative_prompt = ",".join(uc_prompt.values()).strip()
161
168
 
162
169
  @model_validator(mode="after")
163
170
  def _build_nai4_prompt(self):
@@ -187,9 +194,9 @@ class GenerateImageInfer(ApiBaseModel):
187
194
  if not get_supported_params(self.model).vibetransfer:
188
195
  if self.parameters.reference_image_multiple:
189
196
  logger.warning("Vibe transfer is not supported for this model.")
190
- self.parameters.reference_image_multiple = []
191
- self.parameters.reference_information_extracted_multiple = []
192
- self.parameters.reference_strength_multiple = []
197
+ self.parameters.reference_image_multiple = None # Auto exclude None values
198
+ self.parameters.reference_information_extracted_multiple = None # Auto exclude None values
199
+ self.parameters.reference_strength_multiple = None # Auto exclude None values
193
200
 
194
201
  if not get_supported_params(self.model).controlnet:
195
202
  if self.parameters.controlnet_condition is not None:
@@ -210,6 +217,9 @@ class GenerateImageInfer(ApiBaseModel):
210
217
  """
211
218
  if self.parameters.characterPrompts:
212
219
  self.parameters.use_coords = any([c.center != PositionMap.AUTO for c in self.parameters.characterPrompts])
220
+
221
+ if get_supported_params(self.model).v4Prompts and self.parameters.v4_prompt is not None:
222
+ self.parameters.v4_prompt.use_coords = self.parameters.use_coords
213
223
  # Mix Prompt Warning
214
224
  if self.input.count('|') > 6:
215
225
  logger.warning("Maximum prompt mixes exceeded. Extra will be ignored.")
@@ -1,13 +1,14 @@
1
1
  import base64
2
2
  import random
3
3
  from io import BytesIO
4
- from typing import Optional, List, Union, Tuple
4
+ from collections import OrderedDict
5
+ from typing import Optional, List, Set, Union, Tuple
5
6
 
6
7
  import cv2
7
8
  import numpy as np
8
9
  from PIL import Image
9
10
  from loguru import logger
10
- from pydantic import BaseModel, Field, model_validator, field_validator
11
+ from pydantic import BaseModel, Field, model_serializer, model_validator, field_validator
11
12
 
12
13
  from novelai_python.sdk.ai._enum import Sampler, UCPresetTypeAlias, NoiseSchedule, ImageBytesTypeAlias, ControlNetModel, \
13
14
  Model
@@ -62,6 +63,8 @@ class Params(BaseModel):
62
63
  """Use Coordinates"""
63
64
  legacy_uc: bool = False
64
65
  normalize_reference_strength_multiple: bool = True
66
+ inpaintImg2ImgStrength: Optional[float] = Field(None, ge=0, le=1, multiple_of=0.01)
67
+ """For SameFeel"""
65
68
  seed: int = Field(
66
69
  default_factory=lambda: random.randint(0, 4294967295 - 7),
67
70
  gt=0,
@@ -107,8 +110,6 @@ class Params(BaseModel):
107
110
  """Extra Noise Seed"""
108
111
  color_correct: Optional[bool] = None
109
112
  """For Inpaint"""
110
- inpaintImg2ImgStrength: Optional[float] = Field(None, ge=0, le=1, multiple_of=0.01)
111
- """For SameFeel"""
112
113
  controlnet_condition: Optional[str] = None
113
114
  """ControlNet Condition"""
114
115
  controlnet_model: Optional[ControlNetModel] = None
@@ -116,6 +117,36 @@ class Params(BaseModel):
116
117
  uncond_scale: Optional[float] = Field(None, ge=0, le=1.5, multiple_of=0.05)
117
118
  """Undesired Content Strength"""
118
119
 
120
+ # region Custom serializer
121
+ __strong_values__: Set[str] = {
122
+ "skip_cfg_above_sigma", # See models before Anime V3
123
+ }
124
+ """Settings with none value to strongly include"""
125
+
126
+ @model_serializer(mode="wrap")
127
+ def _serialize(self, handler):
128
+ """
129
+ Custom serializer to force include specific fields even when they are None
130
+ """
131
+ data = handler(self)
132
+
133
+ # Force include strong fields and ensure proper ordering
134
+ # Create ordered dict following JavaScript field order
135
+ ordered_fields = list(self.__class__.model_fields.keys())
136
+ ordered_data = OrderedDict()
137
+
138
+ for field_name in ordered_fields:
139
+ if field_name in data:
140
+ # Field exists in data, include it
141
+ ordered_data[field_name] = data[field_name]
142
+ elif field_name in self.__strong_values__:
143
+ # Since we iterate from `self.__class__.model_fields`,、
144
+ # the field is guaranteed to exist. The previous safety check was redundant.
145
+ ordered_data[field_name] = getattr(self, field_name, None)
146
+
147
+ return ordered_data
148
+ # endregion
149
+
119
150
  @model_validator(mode="after")
120
151
  def v_character(self):
121
152
  if len(self.characterPrompts) > 6:
@@ -84,14 +84,14 @@ class Caption(BaseModel):
84
84
 
85
85
  class V4Prompt(BaseModel):
86
86
  caption: Caption = Field(default_factory=Caption, description="Caption")
87
- use_coords: bool = Field(True, description="Use Coordinates")
87
+ use_coords: bool = Field(False, description="Use Coordinates")
88
88
  use_order: bool = Field(True, description="Use Order")
89
89
 
90
90
  @classmethod
91
91
  def build_from_character_prompts(cls,
92
92
  base_caption: str,
93
93
  character_prompts: List[Character],
94
- use_coords: bool = True,
94
+ use_coords: bool = False,
95
95
  use_order: bool = True
96
96
  ) -> "V4Prompt":
97
97
  """
@@ -16,7 +16,7 @@ def encode_access_key(username: str, password: str) -> str:
16
16
  :param password: str (plaintext)
17
17
  :return: str
18
18
  """
19
- pre_salt = f"{password[:6]}{username}novelai_data_access_key"
19
+ pre_salt = f"{password[:6]}{username.lower()}novelai_data_access_key"
20
20
 
21
21
  blake = blake2b(digest_size=16)
22
22
  blake.update(pre_salt.encode())
File without changes