novelai-python 0.3.1__tar.gz → 0.3.3__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.3.1 → novelai_python-0.3.3}/PKG-INFO +2 -2
- {novelai_python-0.3.1 → novelai_python-0.3.3}/README.md +1 -1
- {novelai_python-0.3.1 → novelai_python-0.3.3}/pyproject.toml +1 -1
- {novelai_python-0.3.1 → novelai_python-0.3.3}/src/novelai_python/__init__.py +4 -0
- {novelai_python-0.3.1 → novelai_python-0.3.3}/src/novelai_python/_response/ai/generate_image.py +9 -0
- {novelai_python-0.3.1 → novelai_python-0.3.3}/src/novelai_python/credential/ApiToken.py +1 -0
- {novelai_python-0.3.1 → novelai_python-0.3.3}/src/novelai_python/credential/JwtToken.py +1 -1
- {novelai_python-0.3.1 → novelai_python-0.3.3}/src/novelai_python/credential/UserAuth.py +1 -1
- {novelai_python-0.3.1 → novelai_python-0.3.3}/src/novelai_python/sdk/__init__.py +2 -1
- novelai_python-0.3.1/src/novelai_python/sdk/ai/generate_image.py → novelai_python-0.3.3/src/novelai_python/sdk/ai/generate_image/__init__.py +10 -83
- novelai_python-0.3.3/src/novelai_python/sdk/ai/generate_image/_enum.py +78 -0
- novelai_python-0.3.3/src/novelai_python/sdk/ai/generate_image/suggest_tags.py +127 -0
- {novelai_python-0.3.1 → novelai_python-0.3.3}/src/novelai_python/sdk/ai/upscale.py +1 -1
- {novelai_python-0.3.1 → novelai_python-0.3.3}/src/novelai_python/sdk/user/information.py +2 -1
- {novelai_python-0.3.1 → novelai_python-0.3.3}/src/novelai_python/sdk/user/subscription.py +2 -1
- {novelai_python-0.3.1 → novelai_python-0.3.3}/src/novelai_python/server.py +20 -0
- {novelai_python-0.3.1 → novelai_python-0.3.3}/src/novelai_python/utils/random_prompt/__init__.py +16 -21
- {novelai_python-0.3.1 → novelai_python-0.3.3}/src/novelai_python/utils/useful.py +30 -10
- novelai_python-0.3.1/src/novelai_python/utils/random_prompt/tag_artist.py +0 -398
- {novelai_python-0.3.1 → novelai_python-0.3.3}/LICENSE +0 -0
- {novelai_python-0.3.1 → novelai_python-0.3.3}/NOTICE.MD +0 -0
- {novelai_python-0.3.1 → novelai_python-0.3.3}/src/novelai_python/_exceptions.py +0 -0
- {novelai_python-0.3.1 → novelai_python-0.3.3}/src/novelai_python/_response/__init__.py +0 -0
- {novelai_python-0.3.1 → novelai_python-0.3.3}/src/novelai_python/_response/ai/__init__.py +0 -0
- {novelai_python-0.3.1 → novelai_python-0.3.3}/src/novelai_python/_response/ai/upscale.py +0 -0
- {novelai_python-0.3.1 → novelai_python-0.3.3}/src/novelai_python/_response/schema.py +0 -0
- {novelai_python-0.3.1 → novelai_python-0.3.3}/src/novelai_python/_response/user/__init__.py +0 -0
- {novelai_python-0.3.1 → novelai_python-0.3.3}/src/novelai_python/_response/user/information.py +0 -0
- {novelai_python-0.3.1 → novelai_python-0.3.3}/src/novelai_python/_response/user/login.py +0 -0
- {novelai_python-0.3.1 → novelai_python-0.3.3}/src/novelai_python/_response/user/subscription.py +0 -0
- {novelai_python-0.3.1 → novelai_python-0.3.3}/src/novelai_python/credential/__init__.py +0 -0
- {novelai_python-0.3.1 → novelai_python-0.3.3}/src/novelai_python/credential/_base.py +0 -0
- {novelai_python-0.3.1 → novelai_python-0.3.3}/src/novelai_python/sdk/ai/LICENSE +0 -0
- {novelai_python-0.3.1 → novelai_python-0.3.3}/src/novelai_python/sdk/ai/__init__.py +0 -0
- {novelai_python-0.3.1 → novelai_python-0.3.3}/src/novelai_python/sdk/schema.py +0 -0
- {novelai_python-0.3.1 → novelai_python-0.3.3}/src/novelai_python/sdk/user/__init__.py +0 -0
- {novelai_python-0.3.1 → novelai_python-0.3.3}/src/novelai_python/sdk/user/login.py +0 -0
- {novelai_python-0.3.1 → novelai_python-0.3.3}/src/novelai_python/utils/__init__.py +0 -0
- {novelai_python-0.3.1 → novelai_python-0.3.3}/src/novelai_python/utils/encode.py +0 -0
- {novelai_python-0.3.1 → novelai_python-0.3.3}/src/novelai_python/utils/hash.py +0 -0
- {novelai_python-0.3.1 → novelai_python-0.3.3}/src/novelai_python/utils/random_prompt/tag.py +0 -0
- {novelai_python-0.3.1 → novelai_python-0.3.3}/src/novelai_python/utils/random_prompt/tag_character.py +0 -0
- {novelai_python-0.3.1 → novelai_python-0.3.3}/src/novelai_python/utils/random_prompt/tag_nsfw.py +0 -0
- {novelai_python-0.3.1 → novelai_python-0.3.3}/tests/__init__.py +0 -0
- {novelai_python-0.3.1 → novelai_python-0.3.3}/tests/test_random_prompt.py +0 -0
- {novelai_python-0.3.1 → novelai_python-0.3.3}/tests/test_server.py +0 -0
- {novelai_python-0.3.1 → novelai_python-0.3.3}/tests/test_server_run.py +0 -0
- {novelai_python-0.3.1 → novelai_python-0.3.3}/tests/test_upscale.py +0 -0
- {novelai_python-0.3.1 → novelai_python-0.3.3}/tests/test_user_information.py +0 -0
- {novelai_python-0.3.1 → novelai_python-0.3.3}/tests/test_user_login.py +0 -0
- {novelai_python-0.3.1 → novelai_python-0.3.3}/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.
|
|
3
|
+
Version: 0.3.3
|
|
4
4
|
Summary: Novelai Python Binding With Pydantic
|
|
5
5
|
Author-Email: sudoskys <coldlando@hotmail.com>
|
|
6
6
|
License: Apache License 2.0
|
|
@@ -39,7 +39,7 @@ The goal of this repository is to use Pydantic to build legitimate requests to a
|
|
|
39
39
|
- [x] /user/login
|
|
40
40
|
- [x] /user/information
|
|
41
41
|
- [x] /ai/upscale
|
|
42
|
-
- [
|
|
42
|
+
- [x] /ai/generate-image/suggest-tags
|
|
43
43
|
- [ ] /ai/annotate-image
|
|
44
44
|
- [ ] /ai/classify
|
|
45
45
|
- [ ] /ai/generate-prompt
|
|
@@ -12,7 +12,7 @@ The goal of this repository is to use Pydantic to build legitimate requests to a
|
|
|
12
12
|
- [x] /user/login
|
|
13
13
|
- [x] /user/information
|
|
14
14
|
- [x] /ai/upscale
|
|
15
|
-
- [
|
|
15
|
+
- [x] /ai/generate-image/suggest-tags
|
|
16
16
|
- [ ] /ai/annotate-image
|
|
17
17
|
- [ ] /ai/classify
|
|
18
18
|
- [ ] /ai/generate-prompt
|
|
@@ -13,6 +13,7 @@ from ._exceptions import (
|
|
|
13
13
|
)
|
|
14
14
|
from .credential import JwtCredential, LoginCredential, ApiCredential
|
|
15
15
|
from .sdk import GenerateImageInfer, ImageGenerateResp
|
|
16
|
+
from .sdk import SuggestTags, SuggestTagsResp
|
|
16
17
|
from .sdk import Information, InformationResp
|
|
17
18
|
from .sdk import Login, LoginResp
|
|
18
19
|
from .sdk import Subscription, SubscriptionResp
|
|
@@ -31,6 +32,9 @@ __all__ = [
|
|
|
31
32
|
"Login",
|
|
32
33
|
"LoginResp",
|
|
33
34
|
|
|
35
|
+
"SuggestTags",
|
|
36
|
+
"SuggestTagsResp",
|
|
37
|
+
|
|
34
38
|
"Information",
|
|
35
39
|
"InformationResp",
|
|
36
40
|
|
{novelai_python-0.3.1 → novelai_python-0.3.3}/src/novelai_python/_response/ai/generate_image.py
RENAMED
|
@@ -22,3 +22,12 @@ class ImageGenerateResp(RespBase):
|
|
|
22
22
|
if not isinstance(self.meta.raw_request.get("parameters"), dict):
|
|
23
23
|
raise Exception("Resp parameters is not dict")
|
|
24
24
|
return self.meta.raw_request.get("parameters").get(key, default)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class SuggestTagsResp(RespBase):
|
|
28
|
+
class Tag(BaseModel):
|
|
29
|
+
tag: str
|
|
30
|
+
count: int
|
|
31
|
+
confidence: float
|
|
32
|
+
|
|
33
|
+
tags: List[Tag] = None
|
|
@@ -25,6 +25,7 @@ class ApiCredential(CredentialBase):
|
|
|
25
25
|
"Accept": "*/*",
|
|
26
26
|
"Accept-Language": "zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2",
|
|
27
27
|
"Accept-Encoding": "gzip, deflate, br",
|
|
28
|
+
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 13_2_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36",
|
|
28
29
|
"Authorization": f"Bearer {self.api_token.get_secret_value()}",
|
|
29
30
|
"Content-Type": "application/json",
|
|
30
31
|
"Origin": "https://novelai.net",
|
|
@@ -24,7 +24,7 @@ class JwtCredential(CredentialBase):
|
|
|
24
24
|
self._session = AsyncSession(timeout=timeout, headers={
|
|
25
25
|
"Accept": "*/*",
|
|
26
26
|
"Accept-Language": "zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2",
|
|
27
|
-
"User-Agent": "Mozilla/5.0 (
|
|
27
|
+
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 13_2_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36",
|
|
28
28
|
"Accept-Encoding": "gzip, deflate, br",
|
|
29
29
|
"Authorization": f"Bearer {self.jwt_token.get_secret_value()}",
|
|
30
30
|
"Content-Type": "application/json",
|
|
@@ -30,7 +30,7 @@ class LoginCredential(CredentialBase):
|
|
|
30
30
|
resp = await Login.build(user_name=self.username, password=self.password.get_secret_value()).request()
|
|
31
31
|
self._session = AsyncSession(timeout=timeout, headers={
|
|
32
32
|
"Accept": "*/*",
|
|
33
|
-
"User-Agent": "Mozilla/5.0 (
|
|
33
|
+
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 13_2_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36",
|
|
34
34
|
"Accept-Language": "zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2",
|
|
35
35
|
"Accept-Encoding": "gzip, deflate, br",
|
|
36
36
|
"Authorization": f"Bearer {resp.accessToken}",
|
|
@@ -5,7 +5,8 @@
|
|
|
5
5
|
# @Software: PyCharm
|
|
6
6
|
|
|
7
7
|
from .ai.generate_image import GenerateImageInfer, ImageGenerateResp # noqa 401
|
|
8
|
+
from .ai.generate_image.suggest_tags import SuggestTags, SuggestTagsResp # noqa 401
|
|
9
|
+
from .ai.upscale import Upscale, UpscaleResp # noqa 401
|
|
8
10
|
from .user.information import Information, InformationResp # noqa 401
|
|
9
11
|
from .user.login import Login, LoginResp # noqa 401
|
|
10
12
|
from .user.subscription import Subscription, SubscriptionResp # noqa 401
|
|
11
|
-
from .ai.upscale import Upscale, UpscaleResp # noqa 401
|
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
# -*- coding: utf-8 -*-
|
|
2
|
-
# @Time : 2024/
|
|
2
|
+
# @Time : 2024/2/13 下午8:08
|
|
3
3
|
# @Author : sudoskys
|
|
4
|
-
# @File :
|
|
4
|
+
# @File : __init__.py.py
|
|
5
5
|
# @Software: PyCharm
|
|
6
6
|
import base64
|
|
7
7
|
import json
|
|
8
8
|
import math
|
|
9
9
|
import random
|
|
10
10
|
from copy import deepcopy
|
|
11
|
-
from enum import Enum, IntEnum
|
|
12
11
|
from io import BytesIO
|
|
13
12
|
from typing import Optional, Union
|
|
14
13
|
from urllib.parse import urlparse
|
|
@@ -21,84 +20,12 @@ from loguru import logger
|
|
|
21
20
|
from pydantic import BaseModel, ConfigDict, PrivateAttr, field_validator, model_validator, Field
|
|
22
21
|
from typing_extensions import override
|
|
23
22
|
|
|
24
|
-
from
|
|
25
|
-
from ...
|
|
26
|
-
from
|
|
27
|
-
from
|
|
28
|
-
from
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
class Sampler(Enum):
|
|
32
|
-
K_EULER = "k_euler"
|
|
33
|
-
K_EULER_ANCESTRAL = "k_euler_ancestral"
|
|
34
|
-
K_DPMPP_2S_ANCESTRAL = "k_dpmpp_2s_ancestral"
|
|
35
|
-
K_DPMPP_2M = "k_dpmpp_2m"
|
|
36
|
-
K_DPMPP_SDE = "k_dpmpp_sde"
|
|
37
|
-
DDIM_V3 = "ddim_v3"
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
class NoiseSchedule(Enum):
|
|
41
|
-
NATIVE = "native"
|
|
42
|
-
KARRAS = "karras"
|
|
43
|
-
EXPONENTIAL = "exponential"
|
|
44
|
-
POLYEXPONENTIAL = "polyexponential"
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
class UCPreset(IntEnum):
|
|
48
|
-
TYPE0 = 0
|
|
49
|
-
TYPE1 = 1
|
|
50
|
-
TYPE2 = 2
|
|
51
|
-
TYPE3 = 3
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
class Action(Enum):
|
|
55
|
-
GENERATE = "generate"
|
|
56
|
-
"""Generate Image"""
|
|
57
|
-
IMG2IMG = "img2img"
|
|
58
|
-
"""Image to Image"""
|
|
59
|
-
INFILL = "infill"
|
|
60
|
-
"""Inpainting"""
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
class Model(Enum):
|
|
64
|
-
NAI_DIFFUSION_3 = "nai-diffusion-3"
|
|
65
|
-
NAI_DIFFUSION_3_INPAINTING = "nai-diffusion-3-inpainting"
|
|
66
|
-
|
|
67
|
-
NAI_DIFFUSION = "nai-diffusion"
|
|
68
|
-
NAI_DIFFUSION_INPAINTING = "nai-diffusion-inpainting"
|
|
69
|
-
|
|
70
|
-
SAFE_DIFFUSION = "safe-diffusion"
|
|
71
|
-
SAFE_DIFFUSION_INPAINTING = "safe-diffusion-inpainting"
|
|
72
|
-
|
|
73
|
-
NAI_DIFFUSION_FURRY = "nai-diffusion-furry"
|
|
74
|
-
FURRY_DIFFUSION_INPAINTING = "furry-diffusion-inpainting"
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
class ControlNetModel(Enum):
|
|
78
|
-
HED = "hed"
|
|
79
|
-
"""边缘检测"""
|
|
80
|
-
MIDAS = "midas"
|
|
81
|
-
"""景深"""
|
|
82
|
-
FAKE_SCRIBBLE = "fake_scribble"
|
|
83
|
-
"""伪涂鸦"""
|
|
84
|
-
M_LSD = "mlsd"
|
|
85
|
-
"""(建筑)线条检测"""
|
|
86
|
-
LANDSCAPER = "uniformer"
|
|
87
|
-
"""风景生成"""
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
class Resolution(Enum):
|
|
91
|
-
RES_512_768 = (512, 768)
|
|
92
|
-
RES_768_512 = (768, 512)
|
|
93
|
-
RES_640_640 = (640, 640)
|
|
94
|
-
RES_832_1216 = (832, 1216)
|
|
95
|
-
RES_1216_832 = (1216, 832)
|
|
96
|
-
RES_1024_1024 = (1024, 1024)
|
|
97
|
-
RES_1024_1536 = (1024, 1536)
|
|
98
|
-
RES_1536_1024 = (1536, 1024)
|
|
99
|
-
RES_1472_1472 = (1472, 1472)
|
|
100
|
-
RES_1088_1920 = (1088, 1920)
|
|
101
|
-
RES_1920_1088 = (1920, 1088)
|
|
23
|
+
from ._enum import Model, Sampler, NoiseSchedule, ControlNetModel, Action, UCPreset
|
|
24
|
+
from ...schema import ApiBaseModel
|
|
25
|
+
from ...._exceptions import APIError, AuthError, ConcurrentGenerationError, SessionHttpError
|
|
26
|
+
from ...._response.ai.generate_image import ImageGenerateResp
|
|
27
|
+
from ....credential import CredentialBase
|
|
28
|
+
from ....utils import try_jsonfy, NovelAiMetadata
|
|
102
29
|
|
|
103
30
|
|
|
104
31
|
class GenerateImageInfer(ApiBaseModel):
|
|
@@ -309,7 +236,7 @@ class GenerateImageInfer(ApiBaseModel):
|
|
|
309
236
|
seed: int = None,
|
|
310
237
|
steps: int = 28,
|
|
311
238
|
scale: float = 6.0,
|
|
312
|
-
cfg_rescale:
|
|
239
|
+
cfg_rescale: float = 0,
|
|
313
240
|
sampler: Union[Sampler, str] = Sampler.K_EULER,
|
|
314
241
|
width: int = 832,
|
|
315
242
|
height: int = 1216,
|
|
@@ -395,7 +322,7 @@ class GenerateImageInfer(ApiBaseModel):
|
|
|
395
322
|
"Sec-Fetch-Site": "same-site",
|
|
396
323
|
"Pragma": "no-cache",
|
|
397
324
|
"Cache-Control": "no-cache",
|
|
398
|
-
"User-Agent": "Mozilla/5.0 (
|
|
325
|
+
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 13_2_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36",
|
|
399
326
|
}
|
|
400
327
|
|
|
401
328
|
async def request(self,
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# @Time : 2024/2/13 下午8:10
|
|
3
|
+
# @Author : sudoskys
|
|
4
|
+
# @File : _enum.py
|
|
5
|
+
# @Software: PyCharm
|
|
6
|
+
from enum import Enum, IntEnum
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class Sampler(Enum):
|
|
10
|
+
K_EULER = "k_euler"
|
|
11
|
+
K_EULER_ANCESTRAL = "k_euler_ancestral"
|
|
12
|
+
K_DPMPP_2S_ANCESTRAL = "k_dpmpp_2s_ancestral"
|
|
13
|
+
K_DPMPP_2M = "k_dpmpp_2m"
|
|
14
|
+
K_DPMPP_SDE = "k_dpmpp_sde"
|
|
15
|
+
DDIM_V3 = "ddim_v3"
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class NoiseSchedule(Enum):
|
|
19
|
+
NATIVE = "native"
|
|
20
|
+
KARRAS = "karras"
|
|
21
|
+
EXPONENTIAL = "exponential"
|
|
22
|
+
POLYEXPONENTIAL = "polyexponential"
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class UCPreset(IntEnum):
|
|
26
|
+
TYPE0 = 0
|
|
27
|
+
TYPE1 = 1
|
|
28
|
+
TYPE2 = 2
|
|
29
|
+
TYPE3 = 3
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class Action(Enum):
|
|
33
|
+
GENERATE = "generate"
|
|
34
|
+
"""Generate Image"""
|
|
35
|
+
IMG2IMG = "img2img"
|
|
36
|
+
"""Image to Image"""
|
|
37
|
+
INFILL = "infill"
|
|
38
|
+
"""Inpainting"""
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class ControlNetModel(Enum):
|
|
42
|
+
HED = "hed"
|
|
43
|
+
"""边缘检测"""
|
|
44
|
+
MIDAS = "midas"
|
|
45
|
+
"""景深"""
|
|
46
|
+
FAKE_SCRIBBLE = "fake_scribble"
|
|
47
|
+
"""伪涂鸦"""
|
|
48
|
+
M_LSD = "mlsd"
|
|
49
|
+
"""(建筑)线条检测"""
|
|
50
|
+
LANDSCAPER = "uniformer"
|
|
51
|
+
"""风景生成"""
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class Resolution(Enum):
|
|
55
|
+
RES_512_768 = (512, 768)
|
|
56
|
+
RES_768_512 = (768, 512)
|
|
57
|
+
RES_640_640 = (640, 640)
|
|
58
|
+
RES_832_1216 = (832, 1216)
|
|
59
|
+
RES_1216_832 = (1216, 832)
|
|
60
|
+
RES_1024_1024 = (1024, 1024)
|
|
61
|
+
RES_1024_1536 = (1024, 1536)
|
|
62
|
+
RES_1536_1024 = (1536, 1024)
|
|
63
|
+
RES_1472_1472 = (1472, 1472)
|
|
64
|
+
RES_1088_1920 = (1088, 1920)
|
|
65
|
+
RES_1920_1088 = (1920, 1088)
|
|
66
|
+
|
|
67
|
+
class Model(Enum):
|
|
68
|
+
NAI_DIFFUSION_3 = "nai-diffusion-3"
|
|
69
|
+
NAI_DIFFUSION_3_INPAINTING = "nai-diffusion-3-inpainting"
|
|
70
|
+
|
|
71
|
+
NAI_DIFFUSION = "nai-diffusion"
|
|
72
|
+
NAI_DIFFUSION_INPAINTING = "nai-diffusion-inpainting"
|
|
73
|
+
|
|
74
|
+
SAFE_DIFFUSION = "safe-diffusion"
|
|
75
|
+
SAFE_DIFFUSION_INPAINTING = "safe-diffusion-inpainting"
|
|
76
|
+
|
|
77
|
+
NAI_DIFFUSION_FURRY = "nai-diffusion-furry"
|
|
78
|
+
FURRY_DIFFUSION_INPAINTING = "furry-diffusion-inpainting"
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# @Time : 2024/2/13 下午8:09
|
|
3
|
+
# @Author : sudoskys
|
|
4
|
+
# @File : suggest-tags.py
|
|
5
|
+
# @Software: PyCharm
|
|
6
|
+
from typing import Optional, Union
|
|
7
|
+
from urllib.parse import urlparse
|
|
8
|
+
|
|
9
|
+
import curl_cffi
|
|
10
|
+
import httpx
|
|
11
|
+
from curl_cffi.requests import AsyncSession
|
|
12
|
+
from loguru import logger
|
|
13
|
+
from pydantic import PrivateAttr
|
|
14
|
+
|
|
15
|
+
from ._enum import Model
|
|
16
|
+
from ...schema import ApiBaseModel
|
|
17
|
+
from ...._exceptions import APIError, AuthError, SessionHttpError
|
|
18
|
+
from ...._response.ai.generate_image import SuggestTagsResp
|
|
19
|
+
from ....credential import CredentialBase
|
|
20
|
+
from ....utils import try_jsonfy
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class SuggestTags(ApiBaseModel):
|
|
24
|
+
_endpoint: Optional[str] = PrivateAttr("https://api.novelai.net")
|
|
25
|
+
model: Model = Model.NAI_DIFFUSION_3
|
|
26
|
+
prompt: str = "landscape"
|
|
27
|
+
|
|
28
|
+
@property
|
|
29
|
+
def endpoint(self):
|
|
30
|
+
return self._endpoint
|
|
31
|
+
|
|
32
|
+
@endpoint.setter
|
|
33
|
+
def endpoint(self, value):
|
|
34
|
+
self._endpoint = value
|
|
35
|
+
|
|
36
|
+
@property
|
|
37
|
+
def base_url(self):
|
|
38
|
+
return f"{self.endpoint.strip('/')}/ai/generate-image/suggest-tags"
|
|
39
|
+
|
|
40
|
+
async def necessary_headers(self, request_data) -> dict:
|
|
41
|
+
return {
|
|
42
|
+
"Host": urlparse(self.endpoint).netloc,
|
|
43
|
+
"Accept": "*/*",
|
|
44
|
+
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 13_2_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36",
|
|
45
|
+
"Accept-Language": "zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2",
|
|
46
|
+
"Accept-Encoding": "gzip, deflate, br",
|
|
47
|
+
"Access-Control-Allow-Origin": "*",
|
|
48
|
+
"Referer": "https://novelai.net/",
|
|
49
|
+
"Content-Type": "application/json",
|
|
50
|
+
"Origin": "https://novelai.net",
|
|
51
|
+
"Connection": "keep-alive",
|
|
52
|
+
"Sec-Fetch-Dest": "empty",
|
|
53
|
+
"Sec-Fetch-Mode": "cors",
|
|
54
|
+
"Sec-Fetch-Site": "same-site",
|
|
55
|
+
"Pragma": "no-cache",
|
|
56
|
+
"Cache-Control": "no-cache",
|
|
57
|
+
"TE": "trailers",
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
async def request(self,
|
|
61
|
+
session: Union[AsyncSession, CredentialBase],
|
|
62
|
+
*,
|
|
63
|
+
override_headers: Optional[dict] = None
|
|
64
|
+
) -> SuggestTagsResp:
|
|
65
|
+
"""
|
|
66
|
+
Request to get user subscription information
|
|
67
|
+
:param override_headers:
|
|
68
|
+
:param session:
|
|
69
|
+
:return:
|
|
70
|
+
"""
|
|
71
|
+
# Data Build
|
|
72
|
+
request_data = self.model_dump(mode="json", exclude_none=True)
|
|
73
|
+
if isinstance(session, AsyncSession):
|
|
74
|
+
session.headers.update(await self.necessary_headers(request_data))
|
|
75
|
+
elif isinstance(session, CredentialBase):
|
|
76
|
+
session = await session.get_session(update_headers=await self.necessary_headers(request_data))
|
|
77
|
+
# Header
|
|
78
|
+
if override_headers:
|
|
79
|
+
session.headers.clear()
|
|
80
|
+
session.headers.update(override_headers)
|
|
81
|
+
logger.debug("SuggestTags")
|
|
82
|
+
try:
|
|
83
|
+
assert hasattr(session, "get"), "session must have get method."
|
|
84
|
+
response = await session.get(
|
|
85
|
+
url=self.base_url + "?" + "&".join([f"{k}={v}" for k, v in request_data.items()])
|
|
86
|
+
)
|
|
87
|
+
if "application/json" not in response.headers.get('Content-Type') or response.status_code != 200:
|
|
88
|
+
logger.error(
|
|
89
|
+
f"Error with content type: {response.headers.get('Content-Type')} and code: {response.status_code}"
|
|
90
|
+
)
|
|
91
|
+
try:
|
|
92
|
+
_msg = response.json()
|
|
93
|
+
except Exception as e:
|
|
94
|
+
logger.warning(e)
|
|
95
|
+
if not isinstance(response.content, str) and len(response.content) < 50:
|
|
96
|
+
raise APIError(
|
|
97
|
+
message=f"Unexpected content type: {response.headers.get('Content-Type')}",
|
|
98
|
+
request=request_data,
|
|
99
|
+
code=response.status_code,
|
|
100
|
+
response=try_jsonfy(response.content)
|
|
101
|
+
)
|
|
102
|
+
else:
|
|
103
|
+
_msg = {"statusCode": response.status_code, "message": response.content}
|
|
104
|
+
status_code = _msg.get("statusCode", response.status_code)
|
|
105
|
+
message = _msg.get("message", "Unknown error")
|
|
106
|
+
if status_code in [400, 401, 402]:
|
|
107
|
+
# 400 : validation error
|
|
108
|
+
# 401 : unauthorized
|
|
109
|
+
# 402 : payment required
|
|
110
|
+
# 409 : conflict
|
|
111
|
+
raise AuthError(message, request=request_data, code=status_code, response=_msg)
|
|
112
|
+
if status_code in [500]:
|
|
113
|
+
# An unknown error occured.
|
|
114
|
+
raise APIError(message, request=request_data, code=status_code, response=_msg)
|
|
115
|
+
raise APIError(message, request=request_data, code=status_code, response=_msg)
|
|
116
|
+
return SuggestTagsResp.model_validate(response.json())
|
|
117
|
+
except curl_cffi.requests.errors.RequestsError as exc:
|
|
118
|
+
logger.exception(exc)
|
|
119
|
+
raise SessionHttpError("An AsyncSession RequestsError occurred, maybe SSL error. Try again later!")
|
|
120
|
+
except httpx.HTTPError as exc:
|
|
121
|
+
logger.exception(exc)
|
|
122
|
+
raise SessionHttpError("An HTTPError occurred, maybe SSL error. Try again later!")
|
|
123
|
+
except APIError as e:
|
|
124
|
+
raise e
|
|
125
|
+
except Exception as e:
|
|
126
|
+
logger.opt(exception=e).exception("An Unexpected error occurred")
|
|
127
|
+
raise e
|
|
@@ -73,7 +73,7 @@ class Upscale(ApiBaseModel):
|
|
|
73
73
|
return {
|
|
74
74
|
"Host": urlparse(self.endpoint).netloc,
|
|
75
75
|
"Accept": "*/*",
|
|
76
|
-
"User-Agent": "Mozilla/5.0 (
|
|
76
|
+
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 13_2_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36",
|
|
77
77
|
"Accept-Language": "zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2",
|
|
78
78
|
"Accept-Encoding": "gzip, deflate, br",
|
|
79
79
|
"Referer": "https://novelai.net/",
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
# @File : information.py
|
|
5
5
|
# @Software: PyCharm
|
|
6
6
|
from typing import Optional, Union
|
|
7
|
+
from urllib.parse import urlparse
|
|
7
8
|
|
|
8
9
|
import curl_cffi
|
|
9
10
|
import httpx
|
|
@@ -35,7 +36,7 @@ class Information(ApiBaseModel):
|
|
|
35
36
|
|
|
36
37
|
async def necessary_headers(self, request_data) -> dict:
|
|
37
38
|
return {
|
|
38
|
-
"Host":
|
|
39
|
+
"Host": urlparse(self.endpoint).netloc,
|
|
39
40
|
"Accept": "*/*",
|
|
40
41
|
"Accept-Language": "zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2",
|
|
41
42
|
"Accept-Encoding": "gzip, deflate, br",
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
# @File : subscription.py.py
|
|
5
5
|
# @Software: PyCharm
|
|
6
6
|
from typing import Optional, Union
|
|
7
|
+
from urllib.parse import urlparse
|
|
7
8
|
|
|
8
9
|
import curl_cffi
|
|
9
10
|
import httpx
|
|
@@ -35,7 +36,7 @@ class Subscription(ApiBaseModel):
|
|
|
35
36
|
|
|
36
37
|
async def necessary_headers(self, request_data) -> dict:
|
|
37
38
|
return {
|
|
38
|
-
"Host":
|
|
39
|
+
"Host": urlparse(self.endpoint).netloc,
|
|
39
40
|
"Accept": "*/*",
|
|
40
41
|
"Accept-Language": "zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2",
|
|
41
42
|
"Accept-Encoding": "gzip, deflate, br",
|
|
@@ -15,6 +15,7 @@ from starlette.responses import JSONResponse, StreamingResponse
|
|
|
15
15
|
|
|
16
16
|
from .credential import JwtCredential, SecretStr
|
|
17
17
|
from .sdk.ai.generate_image import GenerateImageInfer
|
|
18
|
+
from .sdk.ai.generate_image.suggest_tags import SuggestTags
|
|
18
19
|
from .sdk.ai.upscale import Upscale
|
|
19
20
|
from .sdk.user.information import Information
|
|
20
21
|
from .sdk.user.login import Login
|
|
@@ -118,6 +119,25 @@ async def upscale(
|
|
|
118
119
|
return JSONResponse(status_code=500, content=e.__dict__)
|
|
119
120
|
|
|
120
121
|
|
|
122
|
+
@app.get("/ai/generate_image/suggest_tags")
|
|
123
|
+
async def suggest_tags(
|
|
124
|
+
req: SuggestTags,
|
|
125
|
+
current_token: str = Depends(get_current_token)
|
|
126
|
+
):
|
|
127
|
+
"""
|
|
128
|
+
生成建议
|
|
129
|
+
:param current_token: Authorization
|
|
130
|
+
:param req: SuggestTags
|
|
131
|
+
:return:
|
|
132
|
+
"""
|
|
133
|
+
try:
|
|
134
|
+
_result = await req.request(session=get_session(current_token))
|
|
135
|
+
return _result.model_dump()
|
|
136
|
+
except Exception as e:
|
|
137
|
+
logger.exception(e)
|
|
138
|
+
return JSONResponse(status_code=500, content=e.__dict__)
|
|
139
|
+
|
|
140
|
+
|
|
121
141
|
@app.post("/ai/generate_image")
|
|
122
142
|
async def generate_image(
|
|
123
143
|
req: GenerateImageInfer,
|
{novelai_python-0.3.1 → novelai_python-0.3.3}/src/novelai_python/utils/random_prompt/__init__.py
RENAMED
|
@@ -13,7 +13,6 @@ from .tag import (
|
|
|
13
13
|
socks,
|
|
14
14
|
action, expression, footwears, bottoms, color as colors
|
|
15
15
|
)
|
|
16
|
-
from .tag_artist import rankArtist
|
|
17
16
|
from .tag_character import rankMoods, rankCharacter, rankIdentity
|
|
18
17
|
from .tag_nsfw import nsfw
|
|
19
18
|
|
|
@@ -30,9 +29,11 @@ class RandomPromptGenerator(object):
|
|
|
30
29
|
:param existing_tags: a list of existing tags
|
|
31
30
|
:return: a tag
|
|
32
31
|
"""
|
|
33
|
-
valid_tags = [
|
|
34
|
-
|
|
35
|
-
|
|
32
|
+
valid_tags = [
|
|
33
|
+
tag
|
|
34
|
+
for tag in tags
|
|
35
|
+
if len(tag) < 3 or not tag[2] or any(sub_tag in existing_tags for sub_tag in tag[2])
|
|
36
|
+
]
|
|
36
37
|
total_weight = sum(tagr[1] for tagr in valid_tags if len(tagr) > 1)
|
|
37
38
|
if total_weight == 0:
|
|
38
39
|
if isinstance(tags, list):
|
|
@@ -70,7 +71,7 @@ class RandomPromptGenerator(object):
|
|
|
70
71
|
has_unique_feature = any(feature in features for feature in unique_features)
|
|
71
72
|
if random.random() < 0.1 and enable_skin_color:
|
|
72
73
|
features.append(self.get_weighted_choice(sinkColor, features))
|
|
73
|
-
if random.random() < 0.
|
|
74
|
+
if random.random() < 0.7:
|
|
74
75
|
features.append(self.get_weighted_choice(eyeColors, features))
|
|
75
76
|
if random.random() < 0.1:
|
|
76
77
|
features.append(self.get_weighted_choice(eyeCharacteristics, features))
|
|
@@ -230,12 +231,6 @@ class RandomPromptGenerator(object):
|
|
|
230
231
|
return ', '.join(tags)
|
|
231
232
|
if random.random() < 0.3:
|
|
232
233
|
tags.append(self.get_weighted_choice(artStyle, tags))
|
|
233
|
-
if random.random() < 0.6:
|
|
234
|
-
tags.append("{" + self.get_weighted_choice(rankArtist, tags) + "}")
|
|
235
|
-
if random.random() < 0.5:
|
|
236
|
-
tags.append("[" + self.get_weighted_choice(rankArtist, tags) + "]")
|
|
237
|
-
if random.random() < 0.4:
|
|
238
|
-
tags.append("{{" + self.get_weighted_choice(rankArtist, tags) + "}}")
|
|
239
234
|
c_count = 0
|
|
240
235
|
d_count = 0
|
|
241
236
|
u_count = 0
|
|
@@ -286,23 +281,23 @@ class RandomPromptGenerator(object):
|
|
|
286
281
|
features = []
|
|
287
282
|
if random.random() < 0.2:
|
|
288
283
|
features = self.character_features(nsfw['fu'], None, True, irs)
|
|
289
|
-
if random.random() < 0.
|
|
284
|
+
if random.random() < 0.3:
|
|
290
285
|
tags.append(self.get_weighted_choice(nsfw["sex"], tags))
|
|
291
|
-
if random.random() < 0.
|
|
286
|
+
if random.random() < 0.5:
|
|
292
287
|
tags.append(self.get_weighted_choice(nsfw["pussy"], tags))
|
|
293
|
-
if random.random() < 0.
|
|
288
|
+
if random.random() < 0.3:
|
|
294
289
|
tags.append(self.get_weighted_choice(nsfw["sexMod"], tags))
|
|
295
|
-
if random.random() < 0.
|
|
290
|
+
if random.random() < 0.5:
|
|
296
291
|
tags.append(self.get_weighted_choice(nsfw["sexActionMode"], tags))
|
|
297
|
-
if random.random() < 0.
|
|
292
|
+
if random.random() < 0.1:
|
|
298
293
|
tags.append(self.get_weighted_choice(nsfw["bdsm"], tags))
|
|
299
|
-
if random.random() < 0.
|
|
294
|
+
if random.random() < 0.2:
|
|
300
295
|
tags.append(self.get_weighted_choice(nsfw["sexAccessories"], tags))
|
|
301
296
|
tags.extend(features)
|
|
302
|
-
if random.random() < 0.
|
|
297
|
+
if random.random() < 0.4 and enable_moods:
|
|
303
298
|
# 心情
|
|
304
299
|
tags.append("[" + self.get_weighted_choice(rankMoods, tags) + "]")
|
|
305
|
-
if random.random() < 0.
|
|
300
|
+
if random.random() < 0.4 and enable_identity:
|
|
306
301
|
# 身份
|
|
307
302
|
tags.append("[" + self.get_weighted_choice(rankIdentity, tags) + "]")
|
|
308
303
|
if random.random() < 0.2 and enable_character:
|
|
@@ -315,9 +310,9 @@ class RandomPromptGenerator(object):
|
|
|
315
310
|
num_objects = random.randint(1, 3)
|
|
316
311
|
for _ in range(num_objects):
|
|
317
312
|
tags.append(self.get_weighted_choice(backgroundObjects, tags))
|
|
318
|
-
if random.random() < 0.
|
|
313
|
+
if random.random() < 0.1:
|
|
319
314
|
tags.append(self.get_weighted_choice(cameraPerspective, tags))
|
|
320
|
-
if random.random() < 0.
|
|
315
|
+
if random.random() < 0.5:
|
|
321
316
|
tags.append(self.get_weighted_choice(cameraAngle, tags))
|
|
322
317
|
for _ in range(c_count):
|
|
323
318
|
if random.random() < 0.2:
|
|
@@ -47,20 +47,27 @@ class QueSelect(object):
|
|
|
47
47
|
return selected
|
|
48
48
|
|
|
49
49
|
|
|
50
|
+
import cv2 as cv
|
|
51
|
+
import numpy as np
|
|
52
|
+
|
|
53
|
+
|
|
50
54
|
def create_mask_from_sketch(original_img_bytes: bytes,
|
|
51
55
|
sketch_img_bytes: bytes,
|
|
52
|
-
|
|
53
|
-
jagged_edges: bool = True
|
|
56
|
+
min_block_size: int = 15,
|
|
57
|
+
jagged_edges: bool = True,
|
|
58
|
+
output_format: str = '.png'
|
|
54
59
|
) -> bytes:
|
|
55
60
|
"""
|
|
56
|
-
Function to create a mask from original and sketch images input as bytes. Returns
|
|
57
|
-
|
|
58
|
-
:param
|
|
59
|
-
:param
|
|
60
|
-
:param
|
|
61
|
-
:param
|
|
62
|
-
:
|
|
61
|
+
Function to create a mask from original and sketch images input as bytes. Returns BytesIO object.
|
|
62
|
+
|
|
63
|
+
:param original_img_bytes: Bytes corresponding to the original image.
|
|
64
|
+
:param sketch_img_bytes: Bytes corresponding to the sketch image.
|
|
65
|
+
:param min_block_size: The minimum size of the pixel blocks. Default is 1, i.e., no pixelation.
|
|
66
|
+
:param jagged_edges: If set to True, the edges of the resulting mask will be more jagged.
|
|
67
|
+
:param output_format: Format of the output image. Defaults to '.png'. It could also be '.jpg'
|
|
68
|
+
:return: bytes corresponding to the resultant mask
|
|
63
69
|
"""
|
|
70
|
+
|
|
64
71
|
# Load images
|
|
65
72
|
ori_img = cv.imdecode(np.frombuffer(original_img_bytes, np.uint8), cv.IMREAD_COLOR)
|
|
66
73
|
sketch_img = cv.imdecode(np.frombuffer(sketch_img_bytes, np.uint8), cv.IMREAD_COLOR)
|
|
@@ -78,6 +85,7 @@ def create_mask_from_sketch(original_img_bytes: bytes,
|
|
|
78
85
|
# Threshold to create the mask
|
|
79
86
|
_, thresh = cv.threshold(diff_gray, 10, 255, cv.THRESH_BINARY)
|
|
80
87
|
|
|
88
|
+
# Create bigger kernel for morphological operations
|
|
81
89
|
if jagged_edges:
|
|
82
90
|
# Use a bigger kernel for dilation to create larger 'step' effect at the edges
|
|
83
91
|
kernel = np.ones((7, 7), np.uint8)
|
|
@@ -87,8 +95,20 @@ def create_mask_from_sketch(original_img_bytes: bytes,
|
|
|
87
95
|
# Perform morphological opening to remove small noise
|
|
88
96
|
opening = cv.morphologyEx(thresh, cv.MORPH_OPEN, kernel, iterations=2)
|
|
89
97
|
|
|
98
|
+
# Perform morphological dilation
|
|
99
|
+
dilation = cv.dilate(opening, kernel, iterations=2)
|
|
100
|
+
|
|
101
|
+
# Perform morphological closing to connect separated areas
|
|
102
|
+
closing = cv.morphologyEx(dilation, cv.MORPH_CLOSE, kernel, iterations=3)
|
|
103
|
+
|
|
90
104
|
# Further remove noise with a Gaussian filter
|
|
91
|
-
smooth = cv.GaussianBlur(
|
|
105
|
+
smooth = cv.GaussianBlur(closing, (5, 5), 0)
|
|
106
|
+
|
|
107
|
+
if min_block_size > 1:
|
|
108
|
+
# Resize to smaller image, then resize back to original size to create a pixelated effect
|
|
109
|
+
small = cv.resize(smooth, (smooth.shape[1] // min_block_size, smooth.shape[0] // min_block_size),
|
|
110
|
+
interpolation=cv.INTER_LINEAR)
|
|
111
|
+
smooth = cv.resize(small, (smooth.shape[1], smooth.shape[0]), interpolation=cv.INTER_NEAREST)
|
|
92
112
|
|
|
93
113
|
if jagged_edges:
|
|
94
114
|
# Apply additional thresholding to create sharper, jagged edges
|
|
@@ -1,398 +0,0 @@
|
|
|
1
|
-
# -*- coding: utf-8 -*-
|
|
2
|
-
# @Time : 2024/1/26 下午5:08
|
|
3
|
-
# @Author : sudoskys
|
|
4
|
-
# @File : tag_artist.py
|
|
5
|
-
# @Software: PyCharm
|
|
6
|
-
|
|
7
|
-
rankArtist = [
|
|
8
|
-
[
|
|
9
|
-
"redi_(rasec_asdjh)",
|
|
10
|
-
50
|
|
11
|
-
],
|
|
12
|
-
[
|
|
13
|
-
"suoiresnu",
|
|
14
|
-
41
|
|
15
|
-
],
|
|
16
|
-
[
|
|
17
|
-
"kulo_jawa",
|
|
18
|
-
30
|
|
19
|
-
],
|
|
20
|
-
[
|
|
21
|
-
"sakanaya_(sakanaya952)",
|
|
22
|
-
25
|
|
23
|
-
],
|
|
24
|
-
[
|
|
25
|
-
"momisan",
|
|
26
|
-
20
|
|
27
|
-
],
|
|
28
|
-
[
|
|
29
|
-
"tansuan_(ensj3875)",
|
|
30
|
-
19
|
|
31
|
-
],
|
|
32
|
-
[
|
|
33
|
-
"hitmanatee",
|
|
34
|
-
18
|
|
35
|
-
],
|
|
36
|
-
[
|
|
37
|
-
"yoru0409",
|
|
38
|
-
18
|
|
39
|
-
],
|
|
40
|
-
[
|
|
41
|
-
"zovokia",
|
|
42
|
-
14
|
|
43
|
-
],
|
|
44
|
-
[
|
|
45
|
-
"memeh",
|
|
46
|
-
13
|
|
47
|
-
],
|
|
48
|
-
[
|
|
49
|
-
"honashi",
|
|
50
|
-
13
|
|
51
|
-
],
|
|
52
|
-
[
|
|
53
|
-
"pinkmill",
|
|
54
|
-
13
|
|
55
|
-
],
|
|
56
|
-
[
|
|
57
|
-
"kanjy00u",
|
|
58
|
-
12
|
|
59
|
-
],
|
|
60
|
-
[
|
|
61
|
-
"eckert&eich",
|
|
62
|
-
12
|
|
63
|
-
],
|
|
64
|
-
[
|
|
65
|
-
"ningen mame",
|
|
66
|
-
100
|
|
67
|
-
],
|
|
68
|
-
[
|
|
69
|
-
"ciloranko",
|
|
70
|
-
100
|
|
71
|
-
],
|
|
72
|
-
[
|
|
73
|
-
"sho (sho lwlw)",
|
|
74
|
-
80
|
|
75
|
-
],
|
|
76
|
-
[
|
|
77
|
-
"tianliang duohe fangdongye",
|
|
78
|
-
100
|
|
79
|
-
],
|
|
80
|
-
[
|
|
81
|
-
"alphonse (white datura)",
|
|
82
|
-
80
|
|
83
|
-
],
|
|
84
|
-
[
|
|
85
|
-
"rei (sanbonzakura)",
|
|
86
|
-
100
|
|
87
|
-
],
|
|
88
|
-
[
|
|
89
|
-
"mamyouda",
|
|
90
|
-
80
|
|
91
|
-
],
|
|
92
|
-
[
|
|
93
|
-
"ogipote",
|
|
94
|
-
100
|
|
95
|
-
],
|
|
96
|
-
[
|
|
97
|
-
"fuzichoco",
|
|
98
|
-
100
|
|
99
|
-
],
|
|
100
|
-
[
|
|
101
|
-
"norza",
|
|
102
|
-
80
|
|
103
|
-
],
|
|
104
|
-
[
|
|
105
|
-
"AkiZero1510",
|
|
106
|
-
100
|
|
107
|
-
],
|
|
108
|
-
[
|
|
109
|
-
"ATDAN",
|
|
110
|
-
100
|
|
111
|
-
],
|
|
112
|
-
[
|
|
113
|
-
"mignon",
|
|
114
|
-
80
|
|
115
|
-
],
|
|
116
|
-
[
|
|
117
|
-
"shexyo",
|
|
118
|
-
100
|
|
119
|
-
],
|
|
120
|
-
[
|
|
121
|
-
"musashi (dishwasher1910)",
|
|
122
|
-
100
|
|
123
|
-
],
|
|
124
|
-
[
|
|
125
|
-
"modare",
|
|
126
|
-
80
|
|
127
|
-
],
|
|
128
|
-
[
|
|
129
|
-
"asteroidill",
|
|
130
|
-
80
|
|
131
|
-
],
|
|
132
|
-
[
|
|
133
|
-
"potg(piotegu)",
|
|
134
|
-
80
|
|
135
|
-
],
|
|
136
|
-
[
|
|
137
|
-
"kedama milk",
|
|
138
|
-
100
|
|
139
|
-
],
|
|
140
|
-
[
|
|
141
|
-
"jun (aousa0328)",
|
|
142
|
-
80
|
|
143
|
-
],
|
|
144
|
-
[
|
|
145
|
-
"sky freedom",
|
|
146
|
-
80
|
|
147
|
-
],
|
|
148
|
-
[
|
|
149
|
-
"ask (askzy)",
|
|
150
|
-
100
|
|
151
|
-
],
|
|
152
|
-
[
|
|
153
|
-
"toridamono",
|
|
154
|
-
100
|
|
155
|
-
],
|
|
156
|
-
[
|
|
157
|
-
"sencha (senchat)",
|
|
158
|
-
80
|
|
159
|
-
],
|
|
160
|
-
[
|
|
161
|
-
"void_0",
|
|
162
|
-
80
|
|
163
|
-
],
|
|
164
|
-
[
|
|
165
|
-
"mandrill",
|
|
166
|
-
100
|
|
167
|
-
],
|
|
168
|
-
[
|
|
169
|
-
"tokkyu",
|
|
170
|
-
100
|
|
171
|
-
],
|
|
172
|
-
[
|
|
173
|
-
"houkisei",
|
|
174
|
-
80
|
|
175
|
-
],
|
|
176
|
-
[
|
|
177
|
-
"konya karasue",
|
|
178
|
-
100
|
|
179
|
-
],
|
|
180
|
-
[
|
|
181
|
-
"akakura",
|
|
182
|
-
100
|
|
183
|
-
],
|
|
184
|
-
[
|
|
185
|
-
"kawacy",
|
|
186
|
-
100
|
|
187
|
-
],
|
|
188
|
-
[
|
|
189
|
-
"reoen",
|
|
190
|
-
100
|
|
191
|
-
],
|
|
192
|
-
[
|
|
193
|
-
"nixeu",
|
|
194
|
-
100
|
|
195
|
-
],
|
|
196
|
-
[
|
|
197
|
-
"cierra_(ra-bit)",
|
|
198
|
-
100
|
|
199
|
-
],
|
|
200
|
-
[
|
|
201
|
-
"artistask_(askzy)",
|
|
202
|
-
100
|
|
203
|
-
],
|
|
204
|
-
[
|
|
205
|
-
"gomzi",
|
|
206
|
-
100
|
|
207
|
-
],
|
|
208
|
-
[
|
|
209
|
-
"you_shimizu",
|
|
210
|
-
100
|
|
211
|
-
],
|
|
212
|
-
[
|
|
213
|
-
"demizu_posuka",
|
|
214
|
-
100
|
|
215
|
-
],
|
|
216
|
-
[
|
|
217
|
-
"asakuraf",
|
|
218
|
-
100
|
|
219
|
-
],
|
|
220
|
-
[
|
|
221
|
-
"ningen_mame",
|
|
222
|
-
100
|
|
223
|
-
],
|
|
224
|
-
[
|
|
225
|
-
"sho_(sho_lwlw)",
|
|
226
|
-
100
|
|
227
|
-
],
|
|
228
|
-
[
|
|
229
|
-
"alphonse_(white_datura)",
|
|
230
|
-
100
|
|
231
|
-
],
|
|
232
|
-
[
|
|
233
|
-
"rei_(sanbonzakura)",
|
|
234
|
-
100
|
|
235
|
-
],
|
|
236
|
-
[
|
|
237
|
-
"wlop",
|
|
238
|
-
100
|
|
239
|
-
],
|
|
240
|
-
[
|
|
241
|
-
"as109",
|
|
242
|
-
100
|
|
243
|
-
],
|
|
244
|
-
[
|
|
245
|
-
"Milkychu",
|
|
246
|
-
100
|
|
247
|
-
],
|
|
248
|
-
[
|
|
249
|
-
"Cogecha",
|
|
250
|
-
100
|
|
251
|
-
],
|
|
252
|
-
[
|
|
253
|
-
"liduke",
|
|
254
|
-
100
|
|
255
|
-
],
|
|
256
|
-
[
|
|
257
|
-
"infukun",
|
|
258
|
-
100
|
|
259
|
-
],
|
|
260
|
-
[
|
|
261
|
-
"amazuyu_tatsuki",
|
|
262
|
-
100
|
|
263
|
-
],
|
|
264
|
-
[
|
|
265
|
-
"Happ\u014dbi Jin",
|
|
266
|
-
100
|
|
267
|
-
],
|
|
268
|
-
[
|
|
269
|
-
"Rella",
|
|
270
|
-
100
|
|
271
|
-
],
|
|
272
|
-
[
|
|
273
|
-
"omone hokoma agm",
|
|
274
|
-
100
|
|
275
|
-
],
|
|
276
|
-
[
|
|
277
|
-
"toosaka asagi",
|
|
278
|
-
100
|
|
279
|
-
],
|
|
280
|
-
[
|
|
281
|
-
"Mochizuki Kei",
|
|
282
|
-
100
|
|
283
|
-
],
|
|
284
|
-
[
|
|
285
|
-
"Namie",
|
|
286
|
-
100
|
|
287
|
-
],
|
|
288
|
-
[
|
|
289
|
-
"Hoji",
|
|
290
|
-
100
|
|
291
|
-
],
|
|
292
|
-
[
|
|
293
|
-
"sy4",
|
|
294
|
-
100
|
|
295
|
-
],
|
|
296
|
-
[
|
|
297
|
-
"mika_pikazo",
|
|
298
|
-
100
|
|
299
|
-
],
|
|
300
|
-
[
|
|
301
|
-
"momoko(momopoco)",
|
|
302
|
-
100
|
|
303
|
-
],
|
|
304
|
-
[
|
|
305
|
-
"rurudo",
|
|
306
|
-
100
|
|
307
|
-
],
|
|
308
|
-
[
|
|
309
|
-
"missile228",
|
|
310
|
-
100
|
|
311
|
-
],
|
|
312
|
-
[
|
|
313
|
-
"miyase_mahiro",
|
|
314
|
-
100
|
|
315
|
-
],
|
|
316
|
-
[
|
|
317
|
-
"touzai(poppin phl95)",
|
|
318
|
-
100
|
|
319
|
-
],
|
|
320
|
-
[
|
|
321
|
-
"kukka",
|
|
322
|
-
100
|
|
323
|
-
],
|
|
324
|
-
[
|
|
325
|
-
"kantoku",
|
|
326
|
-
100
|
|
327
|
-
],
|
|
328
|
-
[
|
|
329
|
-
"poco(asahi age)",
|
|
330
|
-
100
|
|
331
|
-
],
|
|
332
|
-
[
|
|
333
|
-
"refeia",
|
|
334
|
-
100
|
|
335
|
-
],
|
|
336
|
-
[
|
|
337
|
-
"ke-ta",
|
|
338
|
-
100
|
|
339
|
-
],
|
|
340
|
-
[
|
|
341
|
-
"anmi",
|
|
342
|
-
100
|
|
343
|
-
],
|
|
344
|
-
[
|
|
345
|
-
"tiv",
|
|
346
|
-
100
|
|
347
|
-
],
|
|
348
|
-
[
|
|
349
|
-
"chen_bin",
|
|
350
|
-
100
|
|
351
|
-
],
|
|
352
|
-
[
|
|
353
|
-
"lm7 (op-center)",
|
|
354
|
-
100
|
|
355
|
-
],
|
|
356
|
-
[
|
|
357
|
-
"shion (mirudakemann)",
|
|
358
|
-
100
|
|
359
|
-
],
|
|
360
|
-
[
|
|
361
|
-
"asteroid ill",
|
|
362
|
-
100
|
|
363
|
-
],
|
|
364
|
-
[
|
|
365
|
-
"potg (piotegu)",
|
|
366
|
-
100
|
|
367
|
-
],
|
|
368
|
-
[
|
|
369
|
-
"KinHasu",
|
|
370
|
-
100
|
|
371
|
-
],
|
|
372
|
-
[
|
|
373
|
-
"ryou_(ryoutarou)",
|
|
374
|
-
100
|
|
375
|
-
],
|
|
376
|
-
[
|
|
377
|
-
"mamimi_(mamamimi)",
|
|
378
|
-
100
|
|
379
|
-
],
|
|
380
|
-
]
|
|
381
|
-
|
|
382
|
-
if __name__ == "__main__":
|
|
383
|
-
var = vars().copy()
|
|
384
|
-
|
|
385
|
-
# 获取tags列表
|
|
386
|
-
tags = []
|
|
387
|
-
for key, value in var.items():
|
|
388
|
-
if not key.startswith('_') and key != 'var':
|
|
389
|
-
tags.extend(value)
|
|
390
|
-
print(tags)
|
|
391
|
-
|
|
392
|
-
# 展开二级列表
|
|
393
|
-
tags = [tag[0] for tag in tags]
|
|
394
|
-
print(tags)
|
|
395
|
-
import json
|
|
396
|
-
|
|
397
|
-
with open('../../../../playground/cos/tag_artist.json', 'w') as f:
|
|
398
|
-
json.dump(tags, f)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{novelai_python-0.3.1 → novelai_python-0.3.3}/src/novelai_python/_response/user/information.py
RENAMED
|
File without changes
|
|
File without changes
|
{novelai_python-0.3.1 → novelai_python-0.3.3}/src/novelai_python/_response/user/subscription.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{novelai_python-0.3.1 → novelai_python-0.3.3}/src/novelai_python/utils/random_prompt/tag_nsfw.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|