novelai-python 0.5.3__tar.gz → 0.6.0__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 (81) hide show
  1. {novelai_python-0.5.3 → novelai_python-0.6.0}/PKG-INFO +30 -5
  2. {novelai_python-0.5.3 → novelai_python-0.6.0}/README.md +28 -3
  3. {novelai_python-0.5.3 → novelai_python-0.6.0}/pyproject.toml +2 -2
  4. {novelai_python-0.5.3 → novelai_python-0.6.0}/src/novelai_python/_response/__init__.py +1 -1
  5. {novelai_python-0.5.3 → novelai_python-0.6.0}/src/novelai_python/_response/ai/__init__.py +1 -1
  6. {novelai_python-0.5.3 → novelai_python-0.6.0}/src/novelai_python/_response/ai/generate_image.py +1 -1
  7. {novelai_python-0.5.3 → novelai_python-0.6.0}/src/novelai_python/_response/ai/upscale.py +1 -1
  8. {novelai_python-0.5.3 → novelai_python-0.6.0}/src/novelai_python/_response/schema.py +1 -1
  9. {novelai_python-0.5.3 → novelai_python-0.6.0}/src/novelai_python/_response/user/__init__.py +1 -1
  10. {novelai_python-0.5.3 → novelai_python-0.6.0}/src/novelai_python/_response/user/information.py +1 -1
  11. {novelai_python-0.5.3 → novelai_python-0.6.0}/src/novelai_python/_response/user/login.py +1 -1
  12. {novelai_python-0.5.3 → novelai_python-0.6.0}/src/novelai_python/_response/user/subscription.py +1 -1
  13. {novelai_python-0.5.3 → novelai_python-0.6.0}/src/novelai_python/credential/ApiToken.py +3 -3
  14. {novelai_python-0.5.3 → novelai_python-0.6.0}/src/novelai_python/credential/JwtToken.py +3 -3
  15. {novelai_python-0.5.3 → novelai_python-0.6.0}/src/novelai_python/credential/UserAuth.py +8 -8
  16. {novelai_python-0.5.3 → novelai_python-0.6.0}/src/novelai_python/credential/__init__.py +1 -1
  17. {novelai_python-0.5.3 → novelai_python-0.6.0}/src/novelai_python/credential/_base.py +1 -1
  18. {novelai_python-0.5.3 → novelai_python-0.6.0}/src/novelai_python/sdk/__init__.py +1 -1
  19. {novelai_python-0.5.3 → novelai_python-0.6.0}/src/novelai_python/sdk/ai/__init__.py +1 -1
  20. {novelai_python-0.5.3 → novelai_python-0.6.0}/src/novelai_python/sdk/ai/_cost.py +7 -7
  21. {novelai_python-0.5.3 → novelai_python-0.6.0}/src/novelai_python/sdk/ai/_enum.py +158 -2
  22. {novelai_python-0.5.3 → novelai_python-0.6.0}/src/novelai_python/sdk/ai/augment_image/__init__.py +3 -3
  23. {novelai_python-0.5.3 → novelai_python-0.6.0}/src/novelai_python/sdk/ai/generate/__init__.py +1 -0
  24. {novelai_python-0.5.3 → novelai_python-0.6.0}/src/novelai_python/sdk/ai/generate/_schema.py +17 -15
  25. novelai_python-0.6.0/src/novelai_python/sdk/ai/generate_image/__init__.py +990 -0
  26. novelai_python-0.6.0/src/novelai_python/sdk/ai/generate_image/schema.py +129 -0
  27. {novelai_python-0.5.3 → novelai_python-0.6.0}/src/novelai_python/sdk/ai/generate_image/suggest_tags.py +1 -1
  28. {novelai_python-0.5.3 → novelai_python-0.6.0}/src/novelai_python/sdk/ai/upscale.py +0 -1
  29. {novelai_python-0.5.3 → novelai_python-0.6.0}/src/novelai_python/sdk/schema.py +1 -1
  30. {novelai_python-0.5.3 → novelai_python-0.6.0}/src/novelai_python/sdk/user/__init__.py +1 -1
  31. {novelai_python-0.5.3 → novelai_python-0.6.0}/src/novelai_python/sdk/user/information.py +1 -1
  32. {novelai_python-0.5.3 → novelai_python-0.6.0}/src/novelai_python/sdk/user/login.py +1 -1
  33. {novelai_python-0.5.3 → novelai_python-0.6.0}/src/novelai_python/sdk/user/subscription.py +1 -1
  34. {novelai_python-0.5.3 → novelai_python-0.6.0}/src/novelai_python/tokenizer/clip_simple_tokenizer.py +3 -2
  35. {novelai_python-0.5.3 → novelai_python-0.6.0}/src/novelai_python/tool/random_prompt/tag.py +1 -1
  36. {novelai_python-0.5.3 → novelai_python-0.6.0}/src/novelai_python/tool/random_prompt/tag_character.py +1 -1
  37. {novelai_python-0.5.3 → novelai_python-0.6.0}/src/novelai_python/tool/random_prompt/tag_nsfw.py +1 -1
  38. {novelai_python-0.5.3 → novelai_python-0.6.0}/src/novelai_python/utils/__init__.py +1 -1
  39. {novelai_python-0.5.3 → novelai_python-0.6.0}/src/novelai_python/utils/useful.py +1 -1
  40. {novelai_python-0.5.3 → novelai_python-0.6.0}/tests/test_random_prompt.py +1 -1
  41. {novelai_python-0.5.3 → novelai_python-0.6.0}/tests/test_server.py +7 -2
  42. {novelai_python-0.5.3 → novelai_python-0.6.0}/tests/test_server_run.py +1 -1
  43. {novelai_python-0.5.3 → novelai_python-0.6.0}/tests/test_upscale.py +2 -2
  44. {novelai_python-0.5.3 → novelai_python-0.6.0}/tests/test_user_information.py +1 -1
  45. {novelai_python-0.5.3 → novelai_python-0.6.0}/tests/test_user_login.py +1 -1
  46. {novelai_python-0.5.3 → novelai_python-0.6.0}/tests/test_user_subscription.py +1 -1
  47. novelai_python-0.5.3/src/novelai_python/sdk/ai/generate_image/__init__.py +0 -741
  48. {novelai_python-0.5.3 → novelai_python-0.6.0}/LICENSE +0 -0
  49. {novelai_python-0.5.3 → novelai_python-0.6.0}/NOTICE.MD +0 -0
  50. {novelai_python-0.5.3 → novelai_python-0.6.0}/src/novelai_python/__init__.py +0 -0
  51. {novelai_python-0.5.3 → novelai_python-0.6.0}/src/novelai_python/_enum.py +0 -0
  52. {novelai_python-0.5.3 → novelai_python-0.6.0}/src/novelai_python/_exceptions.py +0 -0
  53. {novelai_python-0.5.3 → novelai_python-0.6.0}/src/novelai_python/_response/ai/generate.py +0 -0
  54. {novelai_python-0.5.3 → novelai_python-0.6.0}/src/novelai_python/_response/ai/generate_stream.py +0 -0
  55. {novelai_python-0.5.3 → novelai_python-0.6.0}/src/novelai_python/_response/ai/generate_voice.py +0 -0
  56. {novelai_python-0.5.3 → novelai_python-0.6.0}/src/novelai_python/sdk/ai/LICENSE +0 -0
  57. {novelai_python-0.5.3 → novelai_python-0.6.0}/src/novelai_python/sdk/ai/_const.py +0 -0
  58. {novelai_python-0.5.3 → novelai_python-0.6.0}/src/novelai_python/sdk/ai/augment_image/_enum.py +0 -0
  59. {novelai_python-0.5.3 → novelai_python-0.6.0}/src/novelai_python/sdk/ai/generate/_const.py +0 -0
  60. {novelai_python-0.5.3 → novelai_python-0.6.0}/src/novelai_python/sdk/ai/generate/_enum.py +0 -0
  61. {novelai_python-0.5.3 → novelai_python-0.6.0}/src/novelai_python/sdk/ai/generate/themes.json +0 -0
  62. {novelai_python-0.5.3 → novelai_python-0.6.0}/src/novelai_python/sdk/ai/generate_stream.py +0 -0
  63. {novelai_python-0.5.3 → novelai_python-0.6.0}/src/novelai_python/sdk/ai/generate_voice/__init__.py +0 -0
  64. {novelai_python-0.5.3 → novelai_python-0.6.0}/src/novelai_python/sdk/ai/generate_voice/_enum.py +0 -0
  65. {novelai_python-0.5.3 → novelai_python-0.6.0}/src/novelai_python/server.py +0 -0
  66. {novelai_python-0.5.3 → novelai_python-0.6.0}/src/novelai_python/tokenizer/__init__.py +0 -0
  67. {novelai_python-0.5.3 → novelai_python-0.6.0}/src/novelai_python/tokenizer/nerdstash_v1.model +0 -0
  68. {novelai_python-0.5.3 → novelai_python-0.6.0}/src/novelai_python/tokenizer/nerdstash_v2.model +0 -0
  69. {novelai_python-0.5.3 → novelai_python-0.6.0}/src/novelai_python/tokenizer/novelai.model +0 -0
  70. {novelai_python-0.5.3 → novelai_python-0.6.0}/src/novelai_python/tokenizer/novelai_v2.model +0 -0
  71. {novelai_python-0.5.3 → novelai_python-0.6.0}/src/novelai_python/tool/__init__.py +0 -0
  72. {novelai_python-0.5.3 → novelai_python-0.6.0}/src/novelai_python/tool/image_metadata/__init__.py +0 -0
  73. {novelai_python-0.5.3 → novelai_python-0.6.0}/src/novelai_python/tool/image_metadata/_type.py +0 -0
  74. {novelai_python-0.5.3 → novelai_python-0.6.0}/src/novelai_python/tool/image_metadata/bch_utils.py +0 -0
  75. {novelai_python-0.5.3 → novelai_python-0.6.0}/src/novelai_python/tool/image_metadata/lsb_extractor.py +0 -0
  76. {novelai_python-0.5.3 → novelai_python-0.6.0}/src/novelai_python/tool/image_metadata/lsb_injector.py +0 -0
  77. {novelai_python-0.5.3 → novelai_python-0.6.0}/src/novelai_python/tool/paint_mask/__init__.py +0 -0
  78. {novelai_python-0.5.3 → novelai_python-0.6.0}/src/novelai_python/tool/random_prompt/__init__.py +0 -0
  79. {novelai_python-0.5.3 → novelai_python-0.6.0}/src/novelai_python/utils/encode.py +0 -0
  80. {novelai_python-0.5.3 → novelai_python-0.6.0}/tests/__init__.py +0 -0
  81. {novelai_python-0.5.3 → novelai_python-0.6.0}/tests/test_generate_voice.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: novelai-python
3
- Version: 0.5.3
3
+ Version: 0.6.0
4
4
  Summary: NovelAI Python Binding With Pydantic
5
5
  Author-Email: sudoskys <coldlando@hotmail.com>
6
6
  License: Apache License 2.0
@@ -10,7 +10,7 @@ Requires-Python: >=3.9
10
10
  Requires-Dist: elara>=0.5.5
11
11
  Requires-Dist: loguru>=0.7.2
12
12
  Requires-Dist: pydantic-settings>=2.1.0
13
- Requires-Dist: pydantic>=2.5.3
13
+ Requires-Dist: pydantic>=2.9.0
14
14
  Requires-Dist: httpx>=0.26.0
15
15
  Requires-Dist: shortuuid>=1.0.11
16
16
  Requires-Dist: Pillow>=10.2.0
@@ -41,7 +41,7 @@ Description-Content-Type: text/markdown
41
41
  ---
42
42
 
43
43
  [![PyPI version](https://badge.fury.io/py/novelai-python.svg)](https://badge.fury.io/py/novelai-python)
44
- [![Downloads](https://pepy.tech/badge/novelai_python)](https://pepy.tech/project/novelai_python)
44
+ [![Downloads](https://static.pepy.tech/badge/novelai_python)](https://static.pepy.tech/project/novelai_python)
45
45
 
46
46
  ✨ NovelAI api python sdk with Pydantic, modern and user-friendly.
47
47
 
@@ -91,14 +91,39 @@ from dotenv import load_dotenv
91
91
  from pydantic import SecretStr
92
92
 
93
93
  from novelai_python import GenerateImageInfer, ImageGenerateResp, ApiCredential
94
+ from novelai_python.sdk.ai.generate_image import Model, Character, Sampler, UCPreset
95
+ from novelai_python.sdk.ai.generate_image.schema import PositionMap
94
96
 
95
97
  load_dotenv()
96
- enhance = "year 2023,dynamic angle, best quality, amazing quality, very aesthetic, absurdres"
97
98
  session = ApiCredential(api_token=SecretStr(os.getenv("NOVELAI_JWT"))) # pst-***
98
99
 
100
+ prompt = "1girl, year 2023,dynamic angle, best quality, amazing quality, very aesthetic, absurdres"
101
+
99
102
 
100
103
  async def main():
101
- gen = await GenerateImageInfer.build(prompt=f"1girl,{enhance}")
104
+ gen = GenerateImageInfer.build_generate(
105
+ prompt=prompt,
106
+ model=Model.NAI_DIFFUSION_4_CURATED_PREVIEW,
107
+ character_prompts=[
108
+ Character(
109
+ prompt="1girl",
110
+ uc="red hair",
111
+ center=PositionMap.AUTO
112
+ ),
113
+ Character(
114
+ prompt="1boy",
115
+ center=PositionMap.E5
116
+ )
117
+ ],
118
+ sampler=Sampler.K_EULER_ANCESTRAL,
119
+ ucPreset=UCPreset.TYPE0,
120
+ # Recommended, using preset negative_prompt depends on selected model
121
+ qualitySuffix=True,
122
+ qualityToggle=True,
123
+ decrisp_mode=False,
124
+ variety_boost=True,
125
+ # Checkbox in novelai.net
126
+ )
102
127
  cost = gen.calculate_cost(is_opus=True)
103
128
  print(f"charge: {cost} if you are vip3")
104
129
  resp = gen.request(session=session)
@@ -3,7 +3,7 @@
3
3
  ---
4
4
 
5
5
  [![PyPI version](https://badge.fury.io/py/novelai-python.svg)](https://badge.fury.io/py/novelai-python)
6
- [![Downloads](https://pepy.tech/badge/novelai_python)](https://pepy.tech/project/novelai_python)
6
+ [![Downloads](https://static.pepy.tech/badge/novelai_python)](https://static.pepy.tech/project/novelai_python)
7
7
 
8
8
  ✨ NovelAI api python sdk with Pydantic, modern and user-friendly.
9
9
 
@@ -53,14 +53,39 @@ from dotenv import load_dotenv
53
53
  from pydantic import SecretStr
54
54
 
55
55
  from novelai_python import GenerateImageInfer, ImageGenerateResp, ApiCredential
56
+ from novelai_python.sdk.ai.generate_image import Model, Character, Sampler, UCPreset
57
+ from novelai_python.sdk.ai.generate_image.schema import PositionMap
56
58
 
57
59
  load_dotenv()
58
- enhance = "year 2023,dynamic angle, best quality, amazing quality, very aesthetic, absurdres"
59
60
  session = ApiCredential(api_token=SecretStr(os.getenv("NOVELAI_JWT"))) # pst-***
60
61
 
62
+ prompt = "1girl, year 2023,dynamic angle, best quality, amazing quality, very aesthetic, absurdres"
63
+
61
64
 
62
65
  async def main():
63
- gen = await GenerateImageInfer.build(prompt=f"1girl,{enhance}")
66
+ gen = GenerateImageInfer.build_generate(
67
+ prompt=prompt,
68
+ model=Model.NAI_DIFFUSION_4_CURATED_PREVIEW,
69
+ character_prompts=[
70
+ Character(
71
+ prompt="1girl",
72
+ uc="red hair",
73
+ center=PositionMap.AUTO
74
+ ),
75
+ Character(
76
+ prompt="1boy",
77
+ center=PositionMap.E5
78
+ )
79
+ ],
80
+ sampler=Sampler.K_EULER_ANCESTRAL,
81
+ ucPreset=UCPreset.TYPE0,
82
+ # Recommended, using preset negative_prompt depends on selected model
83
+ qualitySuffix=True,
84
+ qualityToggle=True,
85
+ decrisp_mode=False,
86
+ variety_boost=True,
87
+ # Checkbox in novelai.net
88
+ )
64
89
  cost = gen.calculate_cost(is_opus=True)
65
90
  print(f"charge: {cost} if you are vip3")
66
91
  resp = gen.request(session=session)
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "novelai-python"
3
- version = "0.5.3"
3
+ version = "0.6.0"
4
4
  description = "NovelAI Python Binding With Pydantic"
5
5
  authors = [
6
6
  { name = "sudoskys", email = "coldlando@hotmail.com" },
@@ -9,7 +9,7 @@ dependencies = [
9
9
  "elara>=0.5.5",
10
10
  "loguru>=0.7.2",
11
11
  "pydantic-settings>=2.1.0",
12
- "pydantic>=2.5.3",
12
+ "pydantic>=2.9.0",
13
13
  "httpx>=0.26.0",
14
14
  "shortuuid>=1.0.11",
15
15
  "Pillow>=10.2.0",
@@ -2,7 +2,7 @@
2
2
  # @Time : 2024/1/26 上午10:51
3
3
  # @Author : sudoskys
4
4
  # @File : __init__.py.py
5
- # @Software: PyCharm
5
+
6
6
  from .ai.generate_image import ImageGenerateResp
7
7
  from .user.information import InformationResp
8
8
  from .user.login import LoginResp
@@ -2,4 +2,4 @@
2
2
  # @Time : 2024/1/26 上午11:20
3
3
  # @Author : sudoskys
4
4
  # @File : __init__.py
5
- # @Software: PyCharm
5
+
@@ -2,7 +2,7 @@
2
2
  # @Time : 2024/1/26 上午11:16
3
3
  # @Author : sudoskys
4
4
  # @File : text2image.py
5
- # @Software: PyCharm
5
+
6
6
  from typing import Tuple, List
7
7
 
8
8
  from pydantic import BaseModel
@@ -2,7 +2,7 @@
2
2
  # @Time : 2024/2/13 上午11:29
3
3
  # @Author : sudoskys
4
4
  # @File : upscale.py
5
- # @Software: PyCharm
5
+
6
6
  from typing import Tuple
7
7
 
8
8
  from pydantic import BaseModel
@@ -2,7 +2,7 @@
2
2
  # @Time : 2024/2/13 上午11:30
3
3
  # @Author : sudoskys
4
4
  # @File : schema.py
5
- # @Software: PyCharm
5
+
6
6
 
7
7
  from pydantic import BaseModel
8
8
 
@@ -2,4 +2,4 @@
2
2
  # @Time : 2024/2/7 上午9:57
3
3
  # @Author : sudoskys
4
4
  # @File : __init__.py.py
5
- # @Software: PyCharm
5
+
@@ -2,7 +2,7 @@
2
2
  # @Time : 2024/2/8 下午3:10
3
3
  # @Author : sudoskys
4
4
  # @File : information.py
5
- # @Software: PyCharm
5
+
6
6
 
7
7
  from pydantic import Field
8
8
 
@@ -2,7 +2,7 @@
2
2
  # @Time : 2024/2/7 上午11:57
3
3
  # @Author : sudoskys
4
4
  # @File : login.py
5
- # @Software: PyCharm
5
+
6
6
 
7
7
  from ..schema import RespBase
8
8
 
@@ -2,7 +2,7 @@
2
2
  # @Time : 2024/2/7 上午9:57
3
3
  # @Author : sudoskys
4
4
  # @File : subscription.py
5
- # @Software: PyCharm
5
+
6
6
  from typing import Optional, Dict, Any, List
7
7
 
8
8
  from pydantic import BaseModel, Field
@@ -2,7 +2,7 @@
2
2
  # @Time : 2024/2/8 下午3:05
3
3
  # @Author : sudoskys
4
4
  # @File : ApiToken.py
5
- # @Software: PyCharm
5
+
6
6
 
7
7
  import arrow
8
8
  import shortuuid
@@ -18,7 +18,7 @@ class ApiCredential(CredentialBase):
18
18
  ApiCredential is the base class for all credential.
19
19
  """
20
20
  api_token: SecretStr = Field(None, description="api token")
21
- _x_correlation_id: str = shortuuid.uuid()[0:6]
21
+ x_correlation_id: str = shortuuid.uuid()[0:6]
22
22
 
23
23
  async def get_session(self, timeout: int = 180, update_headers: dict = None):
24
24
  headers = {
@@ -29,7 +29,7 @@ class ApiCredential(CredentialBase):
29
29
  "Content-Type": "application/json",
30
30
  "Origin": "https://novelai.net",
31
31
  "Referer": "https://novelai.net/",
32
- "x-correlation-id": self._x_correlation_id,
32
+ "x-correlation-id": self.x_correlation_id,
33
33
  "x-initiated-at": f"{arrow.utcnow().isoformat()}Z",
34
34
  }
35
35
 
@@ -2,7 +2,7 @@
2
2
  # @Time : 2024/1/26 上午11:04
3
3
  # @Author : sudoskys
4
4
  # @File : JwtToken.py
5
- # @Software: PyCharm
5
+
6
6
 
7
7
  import arrow
8
8
  import shortuuid
@@ -18,7 +18,7 @@ class JwtCredential(CredentialBase):
18
18
  JwtCredential is the base class for all credential.
19
19
  """
20
20
  jwt_token: SecretStr = Field(None, description="jwt token")
21
- _x_correlation_id: str = shortuuid.uuid()[0:6]
21
+ x_correlation_id: str = shortuuid.uuid()[0:6]
22
22
 
23
23
  async def get_session(self, timeout: int = 180, update_headers: dict = None):
24
24
  headers = {
@@ -29,7 +29,7 @@ class JwtCredential(CredentialBase):
29
29
  "Content-Type": "application/json",
30
30
  "Origin": "https://novelai.net",
31
31
  "Referer": "https://novelai.net/",
32
- "x-correlation-id": self._x_correlation_id,
32
+ "x-correlation-id": self.x_correlation_id,
33
33
  "x-initiated-at": f"{arrow.utcnow().isoformat()}Z",
34
34
  }
35
35
 
@@ -19,9 +19,9 @@ class LoginCredential(CredentialBase):
19
19
  """
20
20
  username: str = Field(None, description="username")
21
21
  password: SecretStr = Field(None, description="password")
22
- _session_headers: dict = {}
23
- _update_at: Optional[int] = None
24
- _x_correlation_id: str = shortuuid.uuid()[0:6]
22
+ session_headers: dict = Field(default_factory=dict)
23
+ update_at: Optional[int] = None
24
+ x_correlation_id: str = shortuuid.uuid()[0:6]
25
25
 
26
26
  async def get_session(self, timeout: int = 180, update_headers: dict = None):
27
27
  headers = {
@@ -32,19 +32,19 @@ class LoginCredential(CredentialBase):
32
32
  "Content-Type": "application/json",
33
33
  "Origin": "https://novelai.net",
34
34
  "Referer": "https://novelai.net/",
35
- "x-correlation-id": self._x_correlation_id,
35
+ "x-correlation-id": self.x_correlation_id,
36
36
  "x-initiated-at": f"{arrow.utcnow().isoformat()}Z",
37
37
  }
38
38
 
39
39
  # 30 天有效期
40
- if not self._session_headers or int(time.time()) - self._update_at > 29 * 24 * 60 * 60:
40
+ if not self.session_headers or int(time.time()) - self.update_at > 29 * 24 * 60 * 60:
41
41
  from ..sdk import Login
42
42
  resp = await Login.build(user_name=self.username, password=self.password.get_secret_value()).request()
43
43
  headers["Authorization"] = f"Bearer {resp.accessToken}"
44
- self._session_headers = headers
45
- self._update_at = int(time.time())
44
+ self.session_headers = headers
45
+ self.update_at = int(time.time())
46
46
  else:
47
- headers.update(self._session_headers)
47
+ headers.update(self.session_headers)
48
48
 
49
49
  if update_headers:
50
50
  headers.update(update_headers)
@@ -2,7 +2,7 @@
2
2
  # @Time : 2024/1/26 上午10:51
3
3
  # @Author : sudoskys
4
4
  # @File : __init__.py.py
5
- # @Software: PyCharm
5
+
6
6
  from pydantic import SecretStr
7
7
 
8
8
  from .ApiToken import ApiCredential
@@ -2,7 +2,7 @@
2
2
  # @Time : 2024/2/7 下午12:14
3
3
  # @Author : sudoskys
4
4
  # @File : _shema.py
5
- # @Software: PyCharm
5
+
6
6
  from curl_cffi.requests import AsyncSession
7
7
  from fake_useragent import UserAgent
8
8
  from pydantic import BaseModel
@@ -2,7 +2,7 @@
2
2
  # @Time : 2024/1/26 上午10:51
3
3
  # @Author : sudoskys
4
4
  # @File : __init__.py.py
5
- # @Software: PyCharm
5
+
6
6
 
7
7
  from .ai.augment_image import AugmentImageInfer # noqa 401
8
8
  from .ai.generate import LLM, LLMResp # noqa 401
@@ -2,4 +2,4 @@
2
2
  # @Time : 2024/1/26 上午11:20
3
3
  # @Author : sudoskys
4
4
  # @File : __init__.py.py
5
- # @Software: PyCharm
5
+
@@ -11,9 +11,9 @@ from novelai_python.sdk.ai._enum import Sampler, ModelGroups, get_model_group, M
11
11
  class Args(BaseModel):
12
12
  height: int
13
13
  width: int
14
- image: Optional[str]
14
+ image: bool
15
15
  n_samples: int
16
- strength: float
16
+ strength: Optional[float]
17
17
  steps: int
18
18
  sm: bool
19
19
  sm_dyn: bool
@@ -34,11 +34,10 @@ class CostCalculator:
34
34
  width: int,
35
35
  height: int,
36
36
  steps: int,
37
- image: str,
37
+ image: bool,
38
38
  n_samples: int,
39
39
  account_tier: int,
40
- strength: float,
41
-
40
+ strength: Optional[float],
42
41
  is_sm_enabled: bool,
43
42
  is_sm_dynamic: bool,
44
43
  is_account_active: bool,
@@ -138,14 +137,15 @@ class CostCalculator:
138
137
  dimension = 65536
139
138
 
140
139
  base_dimension = 1048576
141
- strength_multiplier = params.strength if params.image else 1
140
+ strength_multiplier = params.strength if (isinstance(params.strength, float) and params.image) else 1
142
141
  steps = params.steps
143
142
  samples = params.n_samples
144
143
 
145
144
  if steps <= 28 and dimension <= base_dimension and account_tier >= 3 and is_account_active and not is_tool_active:
146
145
  samples -= 1
147
146
 
148
- if model_group and model_group in [ModelGroups.STABLE_DIFFUSION_XL, ModelGroups.STABLE_DIFFUSION_XL_FURRY]:
147
+ if model_group and model_group in [ModelGroups.STABLE_DIFFUSION_XL, ModelGroups.STABLE_DIFFUSION_XL_FURRY,
148
+ ModelGroups.V4]:
149
149
  cost = calculate_dimension_cost(img_width, img_height, steps, params.sm, params.sm_dyn)
150
150
  elif dimension <= base_dimension and params.sampler in [
151
151
  Sampler.PLMS, Sampler.DDIM,
@@ -2,7 +2,6 @@
2
2
  # @Time : 2024/2/13 下午8:10
3
3
  # @Author : sudoskys
4
4
  # @File : _enum.py
5
- # @Software: PyCharm
6
5
  from enum import Enum, IntEnum
7
6
  from typing import List, Optional, Union
8
7
 
@@ -92,6 +91,8 @@ class Resolution(Enum):
92
91
 
93
92
 
94
93
  class Model(Enum):
94
+ NAI_DIFFUSION_4_CURATED_PREVIEW = "nai-diffusion-4-curated-preview"
95
+
95
96
  NAI_DIFFUSION_3 = "nai-diffusion-3"
96
97
  NAI_DIFFUSION_3_INPAINTING = "nai-diffusion-3-inpainting"
97
98
  NAI_DIFFUSION_FURRY_3 = "nai-diffusion-furry-3"
@@ -112,6 +113,7 @@ class Model(Enum):
112
113
  WAIFU_DIFFUSION = "waifu-diffusion"
113
114
  CURATED_DIFFUSION_TEST = "curated-diffusion-test"
114
115
  NAI_DIFFUSION_XL = "nai-diffusion-xl"
116
+ DALLE_MINI = "dalle-mini"
115
117
 
116
118
 
117
119
  class ModelGroups(Enum):
@@ -119,6 +121,7 @@ class ModelGroups(Enum):
119
121
  STABLE_DIFFUSION_GROUP_2 = "stable_diffusion_group2"
120
122
  STABLE_DIFFUSION_XL = "stable_diffusion_xl"
121
123
  STABLE_DIFFUSION_XL_FURRY = "stable_diffusion_xl_furry"
124
+ V4 = "v4"
122
125
 
123
126
 
124
127
  INPAINTING_MODEL_LIST = [
@@ -155,6 +158,158 @@ ImageBytesTypeAlias = Optional[Union[str, bytes]]
155
158
  UCPresetTypeAlias = Optional[Union[UCPreset, int]]
156
159
 
157
160
 
161
+ @dataclass
162
+ class SupportCondition:
163
+ controlnet: bool
164
+ vibetransfer: bool
165
+ scaleMax: int
166
+ negativePromptGuidance: bool
167
+ noiseSchedule: bool
168
+ inpainting: bool
169
+ cfgDelay: bool
170
+ characterPrompts: bool
171
+ v4Prompts: bool
172
+ smea: bool
173
+ text: bool
174
+
175
+
176
+ def get_supported_params(model: Model):
177
+ """
178
+ Get supported parameters for a given model
179
+ :param model: Model
180
+ :return: SupportCondition
181
+ """
182
+ if model in [
183
+ Model.STABLE_DIFFUSION,
184
+ Model.NAI_DIFFUSION,
185
+ Model.SAFE_DIFFUSION,
186
+ Model.WAIFU_DIFFUSION,
187
+ Model.NAI_DIFFUSION_FURRY,
188
+ Model.CURATED_DIFFUSION_TEST,
189
+ Model.NAI_DIFFUSION_INPAINTING,
190
+ Model.SAFE_DIFFUSION_INPAINTING,
191
+ Model.FURRY_DIFFUSION_INPAINTING
192
+ ]:
193
+ return SupportCondition(
194
+ controlnet=True,
195
+ vibetransfer=False,
196
+ scaleMax=25,
197
+ negativePromptGuidance=False,
198
+ noiseSchedule=False,
199
+ inpainting=True,
200
+ cfgDelay=False,
201
+ characterPrompts=False,
202
+ v4Prompts=False,
203
+ smea=True,
204
+ text=False
205
+ )
206
+ if model in [Model.NAI_DIFFUSION_2]:
207
+ return SupportCondition(
208
+ controlnet=True,
209
+ vibetransfer=False,
210
+ scaleMax=25,
211
+ negativePromptGuidance=True,
212
+ noiseSchedule=False,
213
+ inpainting=True,
214
+ cfgDelay=False,
215
+ characterPrompts=False,
216
+ v4Prompts=False,
217
+ smea=True,
218
+ text=False
219
+ )
220
+ if model in [
221
+ Model.NAI_DIFFUSION_XL,
222
+ Model.NAI_DIFFUSION_3,
223
+ Model.NAI_DIFFUSION_3_INPAINTING,
224
+ Model.NAI_DIFFUSION_FURRY_3,
225
+ Model.NAI_DIFFUSION_FURRY_3_INPAINTING
226
+ ]:
227
+ return SupportCondition(
228
+ controlnet=False,
229
+ vibetransfer=True,
230
+ scaleMax=10,
231
+ negativePromptGuidance=True,
232
+ noiseSchedule=True,
233
+ inpainting=True,
234
+ cfgDelay=True,
235
+ characterPrompts=False,
236
+ v4Prompts=False,
237
+ smea=True,
238
+ text=False
239
+ )
240
+ if model in [Model.CUSTOM, Model.NAI_DIFFUSION_4_CURATED_PREVIEW]:
241
+ return SupportCondition(
242
+ controlnet=False,
243
+ vibetransfer=False,
244
+ scaleMax=10,
245
+ negativePromptGuidance=True,
246
+ noiseSchedule=True,
247
+ inpainting=True,
248
+ cfgDelay=False,
249
+ characterPrompts=True,
250
+ v4Prompts=True,
251
+ smea=False,
252
+ text=True
253
+ )
254
+ return SupportCondition(
255
+ controlnet=False,
256
+ vibetransfer=False,
257
+ scaleMax=25,
258
+ negativePromptGuidance=False,
259
+ noiseSchedule=False,
260
+ inpainting=False,
261
+ cfgDelay=False,
262
+ characterPrompts=False,
263
+ v4Prompts=False,
264
+ smea=False,
265
+ text=False
266
+ )
267
+
268
+
269
+ @dataclass
270
+ class Modifier(object):
271
+ qualityTags: str
272
+ suffix: str
273
+
274
+
275
+ def get_modifiers(model: Model) -> Modifier:
276
+ """
277
+ Get modifiers from model
278
+ :param model:
279
+ :return:
280
+ """
281
+ if model in [Model.CUSTOM, Model.NAI_DIFFUSION_4_CURATED_PREVIEW]:
282
+ return Modifier(
283
+ qualityTags="",
284
+ suffix=", rating:general, amazing quality, very aesthetic, absurdres"
285
+ )
286
+ if model in [Model.NAI_DIFFUSION_2]:
287
+ return Modifier(
288
+ qualityTags="very aesthetic, best quality, absurdres, ",
289
+ suffix=""
290
+ )
291
+ if model in [
292
+ Model.NAI_DIFFUSION_3,
293
+ Model.NAI_DIFFUSION_3_INPAINTING
294
+ ]:
295
+ return Modifier(
296
+ qualityTags="",
297
+ suffix=", best quality, amazing quality, very aesthetic, absurdres"
298
+ )
299
+ if model in [
300
+ Model.NAI_DIFFUSION_FURRY_3,
301
+ Model.NAI_DIFFUSION_FURRY_3_INPAINTING
302
+ ]:
303
+ return Modifier(
304
+ qualityTags="",
305
+ suffix=", {best quality}, {amazing quality}"
306
+ )
307
+ return Modifier(
308
+ qualityTags="masterpiece, best quality, ",
309
+ suffix=""
310
+ )
311
+
312
+
158
313
  def get_supported_noise_schedule(sample_type: Sampler) -> List[NoiseSchedule]:
159
314
  """
160
315
  Get supported noise schedule for a given sample type
@@ -224,9 +379,10 @@ def get_model_group(model: ModelTypeAlias) -> ModelGroups:
224
379
  "nai-diffusion-xl": ModelGroups.STABLE_DIFFUSION_XL,
225
380
  "nai-diffusion-3": ModelGroups.STABLE_DIFFUSION_XL,
226
381
  "nai-diffusion-3-inpainting": ModelGroups.STABLE_DIFFUSION_XL,
227
- "custom": ModelGroups.STABLE_DIFFUSION_XL,
382
+ "custom": ModelGroups.V4,
228
383
  "nai-diffusion-furry-3": ModelGroups.STABLE_DIFFUSION_XL_FURRY,
229
384
  "nai-diffusion-furry-3-inpainting": ModelGroups.STABLE_DIFFUSION_XL_FURRY,
385
+ "nai-diffusion-4-curated-preview": ModelGroups.V4,
230
386
  }
231
387
  return mapping.get(model, ModelGroups.STABLE_DIFFUSION)
232
388
 
@@ -2,7 +2,7 @@
2
2
  # @Time : 2024/2/13 下午8:08
3
3
  # @Author : sudoskys
4
4
  # @File : __init__.py.py
5
- # @Software: PyCharm
5
+
6
6
  import base64
7
7
  import io
8
8
  import json
@@ -85,7 +85,7 @@ class AugmentImageInfer(ApiBaseModel):
85
85
  height=self.height,
86
86
  steps=28,
87
87
  model=Model.NAI_DIFFUSION_3,
88
- image=self.image,
88
+ image=bool(self.image),
89
89
  n_samples=1,
90
90
  account_tier=1,
91
91
  strength=1,
@@ -100,7 +100,7 @@ class AugmentImageInfer(ApiBaseModel):
100
100
  height=self.height,
101
101
  steps=28,
102
102
  model=Model.NAI_DIFFUSION_3,
103
- image=self.image,
103
+ image=bool(self.image),
104
104
  n_samples=1,
105
105
  account_tier=3 if is_opus else 1,
106
106
  strength=1,
@@ -306,6 +306,7 @@ class LLM(ApiBaseModel):
306
306
  ) -> "LLM":
307
307
  """
308
308
  Generate
309
+ :param phrase_rep_pen: Phrase_rep_pen
309
310
  :param prompt: prompt, exp "Hello, World!"
310
311
  :param model: TextLLMModelTypeAlias
311
312
  :param advanced_setting: AdvanceLLMSetting, default None means auto-select