novelai-python 0.6.1__tar.gz → 0.7.1__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.
- {novelai_python-0.6.1 → novelai_python-0.7.1}/PKG-INFO +18 -7
- {novelai_python-0.6.1 → novelai_python-0.7.1}/README.md +17 -6
- {novelai_python-0.6.1 → novelai_python-0.7.1}/pyproject.toml +2 -1
- {novelai_python-0.6.1 → novelai_python-0.7.1}/src/novelai_python/_enum.py +1 -0
- {novelai_python-0.6.1 → novelai_python-0.7.1}/src/novelai_python/sdk/ai/_enum.py +75 -34
- {novelai_python-0.6.1 → novelai_python-0.7.1}/src/novelai_python/sdk/ai/generate/__init__.py +2 -1
- {novelai_python-0.6.1 → novelai_python-0.7.1}/src/novelai_python/sdk/ai/generate/_schema.py +1 -1
- {novelai_python-0.6.1 → novelai_python-0.7.1}/src/novelai_python/sdk/ai/generate_image/__init__.py +82 -23
- {novelai_python-0.6.1 → novelai_python-0.7.1}/src/novelai_python/tokenizer/__init__.py +15 -2
- {novelai_python-0.6.1 → novelai_python-0.7.1}/src/novelai_python/tool/image_metadata/__init__.py +160 -111
- {novelai_python-0.6.1 → novelai_python-0.7.1}/src/novelai_python/tool/image_metadata/lsb_extractor.py +41 -13
- novelai_python-0.7.1/src/novelai_python/tool/random_prompt/__init__.py +95 -0
- novelai_python-0.7.1/src/novelai_python/tool/random_prompt/generate_scene_composition.py +2960 -0
- novelai_python-0.7.1/src/novelai_python/tool/random_prompt/generate_scene_tags.py +2276 -0
- novelai_python-0.7.1/src/novelai_python/tool/random_prompt/generate_tags.py +2517 -0
- novelai_python-0.7.1/tests/test_random_prompt.py +61 -0
- novelai_python-0.7.1/tests/test_tokenizer.py +32 -0
- novelai_python-0.6.1/src/novelai_python/tool/image_metadata/_type.py +0 -21
- novelai_python-0.6.1/src/novelai_python/tool/random_prompt/__init__.py +0 -367
- novelai_python-0.6.1/src/novelai_python/tool/random_prompt/tag.py +0 -7542
- novelai_python-0.6.1/src/novelai_python/tool/random_prompt/tag_character.py +0 -270
- novelai_python-0.6.1/src/novelai_python/tool/random_prompt/tag_nsfw.py +0 -984
- novelai_python-0.6.1/tests/test_random_prompt.py +0 -70
- {novelai_python-0.6.1 → novelai_python-0.7.1}/LICENSE +0 -0
- {novelai_python-0.6.1 → novelai_python-0.7.1}/NOTICE.MD +0 -0
- {novelai_python-0.6.1 → novelai_python-0.7.1}/src/novelai_python/__init__.py +0 -0
- {novelai_python-0.6.1 → novelai_python-0.7.1}/src/novelai_python/_exceptions.py +0 -0
- {novelai_python-0.6.1 → novelai_python-0.7.1}/src/novelai_python/_response/__init__.py +0 -0
- {novelai_python-0.6.1 → novelai_python-0.7.1}/src/novelai_python/_response/ai/__init__.py +0 -0
- {novelai_python-0.6.1 → novelai_python-0.7.1}/src/novelai_python/_response/ai/generate.py +0 -0
- {novelai_python-0.6.1 → novelai_python-0.7.1}/src/novelai_python/_response/ai/generate_image.py +0 -0
- {novelai_python-0.6.1 → novelai_python-0.7.1}/src/novelai_python/_response/ai/generate_stream.py +0 -0
- {novelai_python-0.6.1 → novelai_python-0.7.1}/src/novelai_python/_response/ai/generate_voice.py +0 -0
- {novelai_python-0.6.1 → novelai_python-0.7.1}/src/novelai_python/_response/ai/upscale.py +0 -0
- {novelai_python-0.6.1 → novelai_python-0.7.1}/src/novelai_python/_response/schema.py +0 -0
- {novelai_python-0.6.1 → novelai_python-0.7.1}/src/novelai_python/_response/user/__init__.py +0 -0
- {novelai_python-0.6.1 → novelai_python-0.7.1}/src/novelai_python/_response/user/information.py +0 -0
- {novelai_python-0.6.1 → novelai_python-0.7.1}/src/novelai_python/_response/user/login.py +0 -0
- {novelai_python-0.6.1 → novelai_python-0.7.1}/src/novelai_python/_response/user/subscription.py +0 -0
- {novelai_python-0.6.1 → novelai_python-0.7.1}/src/novelai_python/credential/ApiToken.py +0 -0
- {novelai_python-0.6.1 → novelai_python-0.7.1}/src/novelai_python/credential/JwtToken.py +0 -0
- {novelai_python-0.6.1 → novelai_python-0.7.1}/src/novelai_python/credential/UserAuth.py +0 -0
- {novelai_python-0.6.1 → novelai_python-0.7.1}/src/novelai_python/credential/__init__.py +0 -0
- {novelai_python-0.6.1 → novelai_python-0.7.1}/src/novelai_python/credential/_base.py +0 -0
- {novelai_python-0.6.1 → novelai_python-0.7.1}/src/novelai_python/sdk/__init__.py +0 -0
- {novelai_python-0.6.1 → novelai_python-0.7.1}/src/novelai_python/sdk/ai/LICENSE +0 -0
- {novelai_python-0.6.1 → novelai_python-0.7.1}/src/novelai_python/sdk/ai/__init__.py +0 -0
- {novelai_python-0.6.1 → novelai_python-0.7.1}/src/novelai_python/sdk/ai/_const.py +0 -0
- {novelai_python-0.6.1 → novelai_python-0.7.1}/src/novelai_python/sdk/ai/_cost.py +0 -0
- {novelai_python-0.6.1 → novelai_python-0.7.1}/src/novelai_python/sdk/ai/augment_image/__init__.py +0 -0
- {novelai_python-0.6.1 → novelai_python-0.7.1}/src/novelai_python/sdk/ai/augment_image/_enum.py +0 -0
- {novelai_python-0.6.1 → novelai_python-0.7.1}/src/novelai_python/sdk/ai/generate/_const.py +0 -0
- {novelai_python-0.6.1 → novelai_python-0.7.1}/src/novelai_python/sdk/ai/generate/_enum.py +0 -0
- {novelai_python-0.6.1 → novelai_python-0.7.1}/src/novelai_python/sdk/ai/generate/themes.json +0 -0
- {novelai_python-0.6.1 → novelai_python-0.7.1}/src/novelai_python/sdk/ai/generate_image/schema.py +0 -0
- {novelai_python-0.6.1 → novelai_python-0.7.1}/src/novelai_python/sdk/ai/generate_image/suggest_tags.py +0 -0
- {novelai_python-0.6.1 → novelai_python-0.7.1}/src/novelai_python/sdk/ai/generate_stream.py +0 -0
- {novelai_python-0.6.1 → novelai_python-0.7.1}/src/novelai_python/sdk/ai/generate_voice/__init__.py +0 -0
- {novelai_python-0.6.1 → novelai_python-0.7.1}/src/novelai_python/sdk/ai/generate_voice/_enum.py +0 -0
- {novelai_python-0.6.1 → novelai_python-0.7.1}/src/novelai_python/sdk/ai/upscale.py +0 -0
- {novelai_python-0.6.1 → novelai_python-0.7.1}/src/novelai_python/sdk/schema.py +0 -0
- {novelai_python-0.6.1 → novelai_python-0.7.1}/src/novelai_python/sdk/user/__init__.py +0 -0
- {novelai_python-0.6.1 → novelai_python-0.7.1}/src/novelai_python/sdk/user/information.py +0 -0
- {novelai_python-0.6.1 → novelai_python-0.7.1}/src/novelai_python/sdk/user/login.py +0 -0
- {novelai_python-0.6.1 → novelai_python-0.7.1}/src/novelai_python/sdk/user/subscription.py +0 -0
- {novelai_python-0.6.1 → novelai_python-0.7.1}/src/novelai_python/server.py +0 -0
- {novelai_python-0.6.1 → novelai_python-0.7.1}/src/novelai_python/tokenizer/clip_simple_tokenizer.py +0 -0
- {novelai_python-0.6.1 → novelai_python-0.7.1}/src/novelai_python/tokenizer/nerdstash_v1.model +0 -0
- {novelai_python-0.6.1 → novelai_python-0.7.1}/src/novelai_python/tokenizer/nerdstash_v2.model +0 -0
- {novelai_python-0.6.1 → novelai_python-0.7.1}/src/novelai_python/tokenizer/novelai.model +0 -0
- {novelai_python-0.6.1 → novelai_python-0.7.1}/src/novelai_python/tokenizer/novelai_v2.model +0 -0
- {novelai_python-0.6.1 → novelai_python-0.7.1}/src/novelai_python/tool/__init__.py +0 -0
- {novelai_python-0.6.1 → novelai_python-0.7.1}/src/novelai_python/tool/image_metadata/bch_utils.py +0 -0
- {novelai_python-0.6.1 → novelai_python-0.7.1}/src/novelai_python/tool/image_metadata/lsb_injector.py +0 -0
- {novelai_python-0.6.1 → novelai_python-0.7.1}/src/novelai_python/tool/paint_mask/__init__.py +0 -0
- {novelai_python-0.6.1 → novelai_python-0.7.1}/src/novelai_python/utils/__init__.py +0 -0
- {novelai_python-0.6.1 → novelai_python-0.7.1}/src/novelai_python/utils/encode.py +0 -0
- {novelai_python-0.6.1 → novelai_python-0.7.1}/src/novelai_python/utils/useful.py +0 -0
- {novelai_python-0.6.1 → novelai_python-0.7.1}/tests/__init__.py +0 -0
- {novelai_python-0.6.1 → novelai_python-0.7.1}/tests/test_generate_voice.py +0 -0
- {novelai_python-0.6.1 → novelai_python-0.7.1}/tests/test_server.py +0 -0
- {novelai_python-0.6.1 → novelai_python-0.7.1}/tests/test_server_run.py +0 -0
- {novelai_python-0.6.1 → novelai_python-0.7.1}/tests/test_upscale.py +0 -0
- {novelai_python-0.6.1 → novelai_python-0.7.1}/tests/test_user_information.py +0 -0
- {novelai_python-0.6.1 → novelai_python-0.7.1}/tests/test_user_login.py +0 -0
- {novelai_python-0.6.1 → novelai_python-0.7.1}/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.
|
|
3
|
+
Version: 0.7.1
|
|
4
4
|
Summary: NovelAI Python Binding With Pydantic
|
|
5
5
|
Author-Email: sudoskys <coldlando@hotmail.com>
|
|
6
6
|
License: Apache License 2.0
|
|
@@ -45,7 +45,8 @@ Description-Content-Type: text/markdown
|
|
|
45
45
|
|
|
46
46
|
✨ NovelAI api python sdk with Pydantic, modern and user-friendly.
|
|
47
47
|
|
|
48
|
-
The goal of this repository is to use Pydantic to build legitimate requests to access
|
|
48
|
+
The goal of this repository is to use Pydantic to build legitimate requests to access
|
|
49
|
+
the [NovelAI API service](https://api.novelai.net/docs).
|
|
49
50
|
|
|
50
51
|
> Python >= 3.9 is required.
|
|
51
52
|
|
|
@@ -60,6 +61,8 @@ The goal of this repository is to use Pydantic to build legitimate requests to a
|
|
|
60
61
|
pip -U install novelai-python
|
|
61
62
|
```
|
|
62
63
|
|
|
64
|
+
All API users must adhere to the NovelAI Terms of Service: https://novelai.net/terms.
|
|
65
|
+
|
|
63
66
|
**More examples can be found in the [playground](https://github.com/LlmKira/novelai-python/tree/main/playground)
|
|
64
67
|
directory, read code as documentation.**
|
|
65
68
|
|
|
@@ -76,6 +79,7 @@ from novelai_python.sdk.ai.generate_image.schema import PositionMap
|
|
|
76
79
|
|
|
77
80
|
load_dotenv()
|
|
78
81
|
session = ApiCredential(api_token=SecretStr(os.getenv("NOVELAI_JWT"))) # pst-***
|
|
82
|
+
# For security reasons, storing user credentials in plaintext is strongly discouraged.
|
|
79
83
|
|
|
80
84
|
prompt = "1girl, year 2023,dynamic angle, best quality, amazing quality, very aesthetic, absurdres"
|
|
81
85
|
|
|
@@ -175,8 +179,12 @@ loop.run_until_complete(chat("Hello"))
|
|
|
175
179
|
```python
|
|
176
180
|
from novelai_python.tool.random_prompt import RandomPromptGenerator
|
|
177
181
|
|
|
178
|
-
|
|
179
|
-
|
|
182
|
+
generator = RandomPromptGenerator()
|
|
183
|
+
for i in range(10):
|
|
184
|
+
print(generator.generate_common_tags(nsfw=False))
|
|
185
|
+
print(generator.generate_scene_tags())
|
|
186
|
+
print(generator.generate_scene_composition())
|
|
187
|
+
print(generator.get_holiday_themed_tags())
|
|
180
188
|
```
|
|
181
189
|
|
|
182
190
|
#### 📦 Run A Server
|
|
@@ -189,10 +197,15 @@ python3 -m novelai_python.server -h '127.0.0.1' -p 7888
|
|
|
189
197
|
#### 📦 Tokenizer
|
|
190
198
|
|
|
191
199
|
```python
|
|
192
|
-
from novelai_python._enum import get_tokenizer_model, TextLLMModel
|
|
200
|
+
from novelai_python._enum import get_tokenizer_model, TextLLMModel, TextTokenizerGroup
|
|
193
201
|
from novelai_python.tokenizer import NaiTokenizer
|
|
194
202
|
|
|
203
|
+
# Through llm model name to get the tokenizer
|
|
195
204
|
tokenizer_package = NaiTokenizer(get_tokenizer_model(TextLLMModel.ERATO))
|
|
205
|
+
# Directly use the tokenizer
|
|
206
|
+
clip_tokenizer = NaiTokenizer(TextTokenizerGroup.CLIP)
|
|
207
|
+
|
|
208
|
+
# Tokenize a text
|
|
196
209
|
t_text = "a fox jumped over the lazy dog"
|
|
197
210
|
encode_tokens = tokenizer_package.encode(t_text)
|
|
198
211
|
print(tokenizer_package.tokenize_text(t_text))
|
|
@@ -236,8 +249,6 @@ https://dghs-imgutils.deepghs.org/main/api_doc/operate/censor.html
|
|
|
236
249
|
|
|
237
250
|
## 🙏 Acknowledgements
|
|
238
251
|
|
|
239
|
-
[BackEnd](https://api.novelai.net/docs)
|
|
240
|
-
|
|
241
252
|
[novelai-api](https://github.com/Aedial/novelai-api)
|
|
242
253
|
|
|
243
254
|
[NovelAI-API](https://github.com/HanaokaYuzu/NovelAI-API)
|
|
@@ -7,7 +7,8 @@
|
|
|
7
7
|
|
|
8
8
|
✨ NovelAI api python sdk with Pydantic, modern and user-friendly.
|
|
9
9
|
|
|
10
|
-
The goal of this repository is to use Pydantic to build legitimate requests to access
|
|
10
|
+
The goal of this repository is to use Pydantic to build legitimate requests to access
|
|
11
|
+
the [NovelAI API service](https://api.novelai.net/docs).
|
|
11
12
|
|
|
12
13
|
> Python >= 3.9 is required.
|
|
13
14
|
|
|
@@ -22,6 +23,8 @@ The goal of this repository is to use Pydantic to build legitimate requests to a
|
|
|
22
23
|
pip -U install novelai-python
|
|
23
24
|
```
|
|
24
25
|
|
|
26
|
+
All API users must adhere to the NovelAI Terms of Service: https://novelai.net/terms.
|
|
27
|
+
|
|
25
28
|
**More examples can be found in the [playground](https://github.com/LlmKira/novelai-python/tree/main/playground)
|
|
26
29
|
directory, read code as documentation.**
|
|
27
30
|
|
|
@@ -38,6 +41,7 @@ from novelai_python.sdk.ai.generate_image.schema import PositionMap
|
|
|
38
41
|
|
|
39
42
|
load_dotenv()
|
|
40
43
|
session = ApiCredential(api_token=SecretStr(os.getenv("NOVELAI_JWT"))) # pst-***
|
|
44
|
+
# For security reasons, storing user credentials in plaintext is strongly discouraged.
|
|
41
45
|
|
|
42
46
|
prompt = "1girl, year 2023,dynamic angle, best quality, amazing quality, very aesthetic, absurdres"
|
|
43
47
|
|
|
@@ -137,8 +141,12 @@ loop.run_until_complete(chat("Hello"))
|
|
|
137
141
|
```python
|
|
138
142
|
from novelai_python.tool.random_prompt import RandomPromptGenerator
|
|
139
143
|
|
|
140
|
-
|
|
141
|
-
|
|
144
|
+
generator = RandomPromptGenerator()
|
|
145
|
+
for i in range(10):
|
|
146
|
+
print(generator.generate_common_tags(nsfw=False))
|
|
147
|
+
print(generator.generate_scene_tags())
|
|
148
|
+
print(generator.generate_scene_composition())
|
|
149
|
+
print(generator.get_holiday_themed_tags())
|
|
142
150
|
```
|
|
143
151
|
|
|
144
152
|
#### 📦 Run A Server
|
|
@@ -151,10 +159,15 @@ python3 -m novelai_python.server -h '127.0.0.1' -p 7888
|
|
|
151
159
|
#### 📦 Tokenizer
|
|
152
160
|
|
|
153
161
|
```python
|
|
154
|
-
from novelai_python._enum import get_tokenizer_model, TextLLMModel
|
|
162
|
+
from novelai_python._enum import get_tokenizer_model, TextLLMModel, TextTokenizerGroup
|
|
155
163
|
from novelai_python.tokenizer import NaiTokenizer
|
|
156
164
|
|
|
165
|
+
# Through llm model name to get the tokenizer
|
|
157
166
|
tokenizer_package = NaiTokenizer(get_tokenizer_model(TextLLMModel.ERATO))
|
|
167
|
+
# Directly use the tokenizer
|
|
168
|
+
clip_tokenizer = NaiTokenizer(TextTokenizerGroup.CLIP)
|
|
169
|
+
|
|
170
|
+
# Tokenize a text
|
|
158
171
|
t_text = "a fox jumped over the lazy dog"
|
|
159
172
|
encode_tokens = tokenizer_package.encode(t_text)
|
|
160
173
|
print(tokenizer_package.tokenize_text(t_text))
|
|
@@ -198,8 +211,6 @@ https://dghs-imgutils.deepghs.org/main/api_doc/operate/censor.html
|
|
|
198
211
|
|
|
199
212
|
## 🙏 Acknowledgements
|
|
200
213
|
|
|
201
|
-
[BackEnd](https://api.novelai.net/docs)
|
|
202
|
-
|
|
203
214
|
[novelai-api](https://github.com/Aedial/novelai-api)
|
|
204
215
|
|
|
205
216
|
[NovelAI-API](https://github.com/HanaokaYuzu/NovelAI-API)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "novelai-python"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.7.1"
|
|
4
4
|
description = "NovelAI Python Binding With Pydantic"
|
|
5
5
|
authors = [
|
|
6
6
|
{ name = "sudoskys", email = "coldlando@hotmail.com" },
|
|
@@ -59,4 +59,5 @@ distribution = true
|
|
|
59
59
|
[tool.pdm.dev-dependencies]
|
|
60
60
|
dev = [
|
|
61
61
|
"pre-commit>=3.5.0",
|
|
62
|
+
"wasmtime>=28.0.0",
|
|
62
63
|
]
|
|
@@ -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
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
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
|
-
|
|
402
|
-
|
|
403
|
-
|
|
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
|
-
|
|
410
|
-
|
|
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",
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
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",
|
|
419
|
-
|
|
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
|
-
|
|
424
|
-
|
|
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
|
-
|
|
432
|
-
|
|
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:
|
{novelai_python-0.6.1 → novelai_python-0.7.1}/src/novelai_python/sdk/ai/generate/__init__.py
RENAMED
|
@@ -341,7 +341,8 @@ class LLM(ApiBaseModel):
|
|
|
341
341
|
override_headers: Optional[dict] = None
|
|
342
342
|
) -> LLMResp:
|
|
343
343
|
"""
|
|
344
|
-
|
|
344
|
+
Generate text using NovelAI's large language 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.
|
|
345
|
+
|
|
345
346
|
:param override_headers:
|
|
346
347
|
:param session: session
|
|
347
348
|
:return: LLMStreamResp
|
|
@@ -115,7 +115,7 @@ class LLMGenerationParams(BaseModel):
|
|
|
115
115
|
repetition_penalty_slope: Optional[Union[float, int]] = Field(default=None, ge=0, allow_inf_nan=False)
|
|
116
116
|
|
|
117
117
|
eos_token_id: int = None
|
|
118
|
-
bad_words_ids: List[List[int]] = None
|
|
118
|
+
bad_words_ids: Optional[List[List[int]]] = None
|
|
119
119
|
logit_bias_groups: Optional[List[LogitBiasGroup]] = Field(default_factory=list)
|
|
120
120
|
|
|
121
121
|
repetition_penalty_frequency: Optional[Union[float, int]] = Field(default=None, allow_inf_nan=False)
|
{novelai_python-0.6.1 → novelai_python-0.7.1}/src/novelai_python/sdk/ai/generate_image/__init__.py
RENAMED
|
@@ -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(
|
|
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"""
|
|
@@ -371,15 +373,63 @@ class GenerateImageInfer(ApiBaseModel):
|
|
|
371
373
|
|
|
372
374
|
# Add negative prompt based on ucPreset
|
|
373
375
|
if self.parameters.ucPreset is not None:
|
|
374
|
-
|
|
376
|
+
uc_preset = self.parameters.ucPreset
|
|
377
|
+
# If ucPreset is Enum, get the value
|
|
378
|
+
if isinstance(self.parameters.ucPreset, Enum):
|
|
379
|
+
uc_preset = self.parameters.ucPreset.value
|
|
380
|
+
default_negative_prompt = get_default_uc_preset(self.model, uc_preset)
|
|
375
381
|
self.parameters.negative_prompt = ", ".join(
|
|
376
382
|
filter(None, [default_negative_prompt, self.parameters.negative_prompt])
|
|
377
383
|
)
|
|
378
384
|
|
|
379
|
-
# Add quality prompt
|
|
385
|
+
# Add quality prompt based on qualityToggle
|
|
380
386
|
modifier = get_modifiers(self.model)
|
|
381
|
-
|
|
382
|
-
|
|
387
|
+
quality_tags, suffix = modifier.qualityTags, modifier.suffix
|
|
388
|
+
|
|
389
|
+
def enhance_text_part(_part, _quality_tags, _suffix):
|
|
390
|
+
text_parts = _part.split(" Text:")
|
|
391
|
+
enhanced_text_parts = [
|
|
392
|
+
_quality_tags + text_part + _suffix + ('.' if _suffix and len(text_parts) > 1 else '')
|
|
393
|
+
if index == 0
|
|
394
|
+
else text_part
|
|
395
|
+
for index, text_part in enumerate(text_parts)
|
|
396
|
+
]
|
|
397
|
+
return " Text:".join(enhanced_text_parts)
|
|
398
|
+
|
|
399
|
+
def enhance_simple_part(_part, _quality_tags, _suffix):
|
|
400
|
+
match = re.search(r"(:[\d.]+$)", _part)
|
|
401
|
+
matched_value = match.group(0) if match else None
|
|
402
|
+
core_part = _part[:-len(matched_value)] if matched_value else _part
|
|
403
|
+
return _quality_tags + core_part + _suffix + (matched_value or "")
|
|
404
|
+
|
|
405
|
+
def enhance_message(_prompt):
|
|
406
|
+
try:
|
|
407
|
+
if get_supported_params(self.model).characterPrompts:
|
|
408
|
+
parts = _prompt.split("|")
|
|
409
|
+
enhanced_parts = [
|
|
410
|
+
quality_tags + part + suffix
|
|
411
|
+
if index == 0 and not get_supported_params(self.model).text
|
|
412
|
+
else enhance_text_part(part, quality_tags, suffix)
|
|
413
|
+
if index == 0
|
|
414
|
+
else part
|
|
415
|
+
for index, part in enumerate(parts)
|
|
416
|
+
]
|
|
417
|
+
return "|".join(enhanced_parts)
|
|
418
|
+
else:
|
|
419
|
+
parts = _prompt.split("|")
|
|
420
|
+
enhanced_parts = [
|
|
421
|
+
enhance_simple_part(part, quality_tags, suffix)
|
|
422
|
+
for part in parts
|
|
423
|
+
]
|
|
424
|
+
return "|".join(enhanced_parts)
|
|
425
|
+
except Exception as e:
|
|
426
|
+
logger.error(
|
|
427
|
+
f"Failed to enhance `{_prompt}` because {e},"
|
|
428
|
+
f"Report this issue to https://github.com/LLMKIRA/novelai-python/issues"
|
|
429
|
+
)
|
|
430
|
+
return _prompt
|
|
431
|
+
|
|
432
|
+
self.input = enhance_message(self.input)
|
|
383
433
|
|
|
384
434
|
@model_validator(mode="after")
|
|
385
435
|
def _build_nai4_prompt(self):
|
|
@@ -464,7 +514,30 @@ class GenerateImageInfer(ApiBaseModel):
|
|
|
464
514
|
self.parameters.sm_dyn = True
|
|
465
515
|
|
|
466
516
|
if self.parameters.sm_dyn and (not self.parameters.sm):
|
|
467
|
-
self.parameters.
|
|
517
|
+
self.parameters.sm = True
|
|
518
|
+
|
|
519
|
+
# AUTO SMEA SETTING
|
|
520
|
+
"""
|
|
521
|
+
def sm_size_cast(model: Model):
|
|
522
|
+
if model in [
|
|
523
|
+
Model.NAI_DIFFUSION_V3,
|
|
524
|
+
Model.NAI_DIFFUSION_V3_INPAINTING,
|
|
525
|
+
Model.NAI_DIFFUSION_FURRY_V3,
|
|
526
|
+
Model.NAI_DIFFUSION_FURRY_V3_INPAINTING,
|
|
527
|
+
Model.CUSTOM
|
|
528
|
+
]:
|
|
529
|
+
return 2166785
|
|
530
|
+
return 1064961
|
|
531
|
+
if self.parameters.autoSmea and (self.parameters.width * self.parameters.height < sm_size_cast(self.model)):
|
|
532
|
+
self.parameters.autoSmea = False
|
|
533
|
+
"""
|
|
534
|
+
|
|
535
|
+
if self.parameters.characterPrompts:
|
|
536
|
+
self.parameters.use_coords = any([c.center != PositionMap.AUTO for c in self.parameters.characterPrompts])
|
|
537
|
+
|
|
538
|
+
# Mix Prompt Warning
|
|
539
|
+
if self.input.count('|') > 6:
|
|
540
|
+
logger.warning("Maximum prompt mixes exceeded. Extra will be ignored.")
|
|
468
541
|
|
|
469
542
|
if self.parameters.sampler in [
|
|
470
543
|
Sampler.DDIM,
|
|
@@ -572,7 +645,6 @@ class GenerateImageInfer(ApiBaseModel):
|
|
|
572
645
|
prompt: str,
|
|
573
646
|
*,
|
|
574
647
|
model: Union[Model, str],
|
|
575
|
-
qualitySuffix: bool = True,
|
|
576
648
|
negative_prompt: str = "",
|
|
577
649
|
ucPreset: UCPresetTypeAlias = UCPreset.TYPE0,
|
|
578
650
|
sm: bool = False,
|
|
@@ -602,7 +674,6 @@ class GenerateImageInfer(ApiBaseModel):
|
|
|
602
674
|
:param prompt: Given prompt.
|
|
603
675
|
:param model: Model for generation.
|
|
604
676
|
:param negative_prompt: The things you don't want to see in the image.
|
|
605
|
-
:param qualitySuffix: Add quality suffix to prompt
|
|
606
677
|
:param ucPreset: The negative prompt preset.
|
|
607
678
|
:param steps: The steps for generation.
|
|
608
679
|
:param seed: The seed for generation.
|
|
@@ -619,9 +690,6 @@ class GenerateImageInfer(ApiBaseModel):
|
|
|
619
690
|
"""
|
|
620
691
|
if character_prompts is None:
|
|
621
692
|
character_prompts = []
|
|
622
|
-
if qualitySuffix:
|
|
623
|
-
modifier = get_modifiers(model)
|
|
624
|
-
prompt += modifier.suffix
|
|
625
693
|
if seed is None:
|
|
626
694
|
seed = random.randint(0, 4294967295 - 7)
|
|
627
695
|
if reference_strength_multiple is None:
|
|
@@ -668,7 +736,6 @@ class GenerateImageInfer(ApiBaseModel):
|
|
|
668
736
|
seed: int = None,
|
|
669
737
|
extra_noise_seed: int = None,
|
|
670
738
|
model: Union[Model, str] = Model.NAI_DIFFUSION_3,
|
|
671
|
-
qualitySuffix: bool = True,
|
|
672
739
|
negative_prompt: str = "",
|
|
673
740
|
ucPreset: UCPresetTypeAlias = UCPreset.TYPE0,
|
|
674
741
|
steps: int = 23,
|
|
@@ -699,7 +766,6 @@ class GenerateImageInfer(ApiBaseModel):
|
|
|
699
766
|
:param prompt: Given prompt.
|
|
700
767
|
:param model: Model for generation.
|
|
701
768
|
:param negative_prompt: The things you don't want to see in the image.
|
|
702
|
-
:param qualitySuffix: Add quality suffix to prompt
|
|
703
769
|
:param ucPreset: The negative prompt preset.
|
|
704
770
|
:param steps: The steps for generation.
|
|
705
771
|
:param seed: The seed for generation.
|
|
@@ -716,9 +782,6 @@ class GenerateImageInfer(ApiBaseModel):
|
|
|
716
782
|
"""
|
|
717
783
|
if character_prompts is None:
|
|
718
784
|
character_prompts = []
|
|
719
|
-
if qualitySuffix:
|
|
720
|
-
modifier = get_modifiers(model)
|
|
721
|
-
prompt += modifier.suffix
|
|
722
785
|
if seed is None:
|
|
723
786
|
seed = random.randint(0, 4294967295 - 7)
|
|
724
787
|
if extra_noise_seed is None:
|
|
@@ -768,7 +831,6 @@ class GenerateImageInfer(ApiBaseModel):
|
|
|
768
831
|
mask: Union[bytes, str],
|
|
769
832
|
strength: float = 0.7,
|
|
770
833
|
model: Union[Model, str] = Model.NAI_DIFFUSION_3,
|
|
771
|
-
qualitySuffix: bool = True,
|
|
772
834
|
negative_prompt: str = "",
|
|
773
835
|
ucPreset: UCPresetTypeAlias = UCPreset.TYPE0,
|
|
774
836
|
steps: int = 23,
|
|
@@ -799,7 +861,6 @@ class GenerateImageInfer(ApiBaseModel):
|
|
|
799
861
|
:param prompt: Given prompt.
|
|
800
862
|
:param model: Model for generation.
|
|
801
863
|
:param negative_prompt: The things you don't want to see in the image.
|
|
802
|
-
:param qualitySuffix: Add quality suffix to prompt
|
|
803
864
|
:param ucPreset: The negative prompt preset.
|
|
804
865
|
:param steps: The steps for generation.
|
|
805
866
|
:param seed: The seed for generation.
|
|
@@ -816,9 +877,6 @@ class GenerateImageInfer(ApiBaseModel):
|
|
|
816
877
|
"""
|
|
817
878
|
if character_prompts is None:
|
|
818
879
|
character_prompts = []
|
|
819
|
-
if qualitySuffix:
|
|
820
|
-
modifier = get_modifiers(model)
|
|
821
|
-
prompt += modifier.suffix
|
|
822
880
|
if seed is None:
|
|
823
881
|
seed = random.randint(0, 4294967295 - 7)
|
|
824
882
|
if reference_strength_multiple is None:
|
|
@@ -891,7 +949,8 @@ class GenerateImageInfer(ApiBaseModel):
|
|
|
891
949
|
override_headers: Optional[dict] = None,
|
|
892
950
|
) -> ImageGenerateResp:
|
|
893
951
|
"""
|
|
894
|
-
|
|
952
|
+
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.
|
|
953
|
+
|
|
895
954
|
:param override_headers: the headers to override
|
|
896
955
|
:param session: session
|
|
897
956
|
:return:
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import gzip
|
|
2
2
|
import io
|
|
3
|
+
import json
|
|
3
4
|
import pathlib
|
|
4
5
|
import zlib
|
|
5
6
|
from typing import Dict, List, Optional
|
|
@@ -56,6 +57,14 @@ class LLMTokenizerSetting(TokenizerSetting):
|
|
|
56
57
|
return self
|
|
57
58
|
|
|
58
59
|
|
|
60
|
+
def is_clip_model(model_name: str) -> bool:
|
|
61
|
+
return model_name.lower().startswith("clip_tokenizer")
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def is_t5_model(model_name: str) -> bool:
|
|
65
|
+
return model_name.lower().startswith("t5_tokenizer")
|
|
66
|
+
|
|
67
|
+
|
|
59
68
|
class NaiTokenizer:
|
|
60
69
|
def __init__(self,
|
|
61
70
|
model: str,
|
|
@@ -129,8 +138,10 @@ class NaiTokenizer:
|
|
|
129
138
|
decoded_str = self._read_compressed_def(model_bytes)
|
|
130
139
|
repaired_data = repair_json(decoded_str, return_objects=True)
|
|
131
140
|
try:
|
|
132
|
-
if
|
|
141
|
+
if is_clip_model(self.model_full_name):
|
|
133
142
|
self.tokenizer_setting = ClipTokenizerSetting.model_validate(repaired_data)
|
|
143
|
+
elif is_t5_model(self.model_full_name):
|
|
144
|
+
self.tokenizer_setting = json.dumps(repaired_data)
|
|
134
145
|
else:
|
|
135
146
|
self.tokenizer_setting = LLMTokenizerSetting.model_validate(repaired_data)
|
|
136
147
|
except Exception as e:
|
|
@@ -140,8 +151,10 @@ class NaiTokenizer:
|
|
|
140
151
|
)
|
|
141
152
|
|
|
142
153
|
def _create_tokenizer(self):
|
|
143
|
-
if
|
|
154
|
+
if is_clip_model(self.model_full_name):
|
|
144
155
|
self._create_clip_tokenizer()
|
|
156
|
+
elif is_t5_model(self.model_full_name):
|
|
157
|
+
self.tokenizer = Tokenizer.from_str(self.tokenizer_setting)
|
|
145
158
|
else:
|
|
146
159
|
self._create_bpe_tokenizer()
|
|
147
160
|
|