novelai-python 0.3.4__tar.gz → 0.3.5__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 (50) hide show
  1. {novelai_python-0.3.4 → novelai_python-0.3.5}/LICENSE +0 -0
  2. {novelai_python-0.3.4 → novelai_python-0.3.5}/NOTICE.MD +0 -0
  3. {novelai_python-0.3.4 → novelai_python-0.3.5}/PKG-INFO +1 -1
  4. {novelai_python-0.3.4 → novelai_python-0.3.5}/README.md +0 -0
  5. {novelai_python-0.3.4 → novelai_python-0.3.5}/pyproject.toml +1 -1
  6. {novelai_python-0.3.4 → novelai_python-0.3.5}/src/novelai_python/__init__.py +0 -0
  7. {novelai_python-0.3.4 → novelai_python-0.3.5}/src/novelai_python/_exceptions.py +0 -0
  8. {novelai_python-0.3.4 → novelai_python-0.3.5}/src/novelai_python/_response/__init__.py +0 -0
  9. {novelai_python-0.3.4 → novelai_python-0.3.5}/src/novelai_python/_response/ai/__init__.py +0 -0
  10. {novelai_python-0.3.4 → novelai_python-0.3.5}/src/novelai_python/_response/ai/generate_image.py +0 -0
  11. {novelai_python-0.3.4 → novelai_python-0.3.5}/src/novelai_python/_response/ai/upscale.py +0 -0
  12. {novelai_python-0.3.4 → novelai_python-0.3.5}/src/novelai_python/_response/schema.py +0 -0
  13. {novelai_python-0.3.4 → novelai_python-0.3.5}/src/novelai_python/_response/user/__init__.py +0 -0
  14. {novelai_python-0.3.4 → novelai_python-0.3.5}/src/novelai_python/_response/user/information.py +0 -0
  15. {novelai_python-0.3.4 → novelai_python-0.3.5}/src/novelai_python/_response/user/login.py +0 -0
  16. {novelai_python-0.3.4 → novelai_python-0.3.5}/src/novelai_python/_response/user/subscription.py +0 -0
  17. {novelai_python-0.3.4 → novelai_python-0.3.5}/src/novelai_python/credential/ApiToken.py +0 -0
  18. {novelai_python-0.3.4 → novelai_python-0.3.5}/src/novelai_python/credential/JwtToken.py +0 -0
  19. {novelai_python-0.3.4 → novelai_python-0.3.5}/src/novelai_python/credential/UserAuth.py +0 -0
  20. {novelai_python-0.3.4 → novelai_python-0.3.5}/src/novelai_python/credential/__init__.py +0 -0
  21. {novelai_python-0.3.4 → novelai_python-0.3.5}/src/novelai_python/credential/_base.py +0 -0
  22. {novelai_python-0.3.4 → novelai_python-0.3.5}/src/novelai_python/sdk/__init__.py +0 -0
  23. {novelai_python-0.3.4 → novelai_python-0.3.5}/src/novelai_python/sdk/ai/LICENSE +0 -0
  24. {novelai_python-0.3.4 → novelai_python-0.3.5}/src/novelai_python/sdk/ai/__init__.py +0 -0
  25. {novelai_python-0.3.4 → novelai_python-0.3.5}/src/novelai_python/sdk/ai/generate_image/__init__.py +55 -23
  26. {novelai_python-0.3.4 → novelai_python-0.3.5}/src/novelai_python/sdk/ai/generate_image/_enum.py +0 -0
  27. {novelai_python-0.3.4 → novelai_python-0.3.5}/src/novelai_python/sdk/ai/generate_image/suggest_tags.py +1 -1
  28. {novelai_python-0.3.4 → novelai_python-0.3.5}/src/novelai_python/sdk/ai/upscale.py +1 -1
  29. {novelai_python-0.3.4 → novelai_python-0.3.5}/src/novelai_python/sdk/schema.py +0 -0
  30. {novelai_python-0.3.4 → novelai_python-0.3.5}/src/novelai_python/sdk/user/__init__.py +0 -0
  31. {novelai_python-0.3.4 → novelai_python-0.3.5}/src/novelai_python/sdk/user/information.py +1 -1
  32. {novelai_python-0.3.4 → novelai_python-0.3.5}/src/novelai_python/sdk/user/login.py +1 -1
  33. {novelai_python-0.3.4 → novelai_python-0.3.5}/src/novelai_python/sdk/user/subscription.py +1 -1
  34. {novelai_python-0.3.4 → novelai_python-0.3.5}/src/novelai_python/server.py +0 -0
  35. {novelai_python-0.3.4 → novelai_python-0.3.5}/src/novelai_python/utils/__init__.py +0 -0
  36. {novelai_python-0.3.4 → novelai_python-0.3.5}/src/novelai_python/utils/encode.py +0 -0
  37. {novelai_python-0.3.4 → novelai_python-0.3.5}/src/novelai_python/utils/hash.py +0 -0
  38. {novelai_python-0.3.4 → novelai_python-0.3.5}/src/novelai_python/utils/random_prompt/__init__.py +0 -0
  39. {novelai_python-0.3.4 → novelai_python-0.3.5}/src/novelai_python/utils/random_prompt/tag.py +0 -0
  40. {novelai_python-0.3.4 → novelai_python-0.3.5}/src/novelai_python/utils/random_prompt/tag_character.py +0 -0
  41. {novelai_python-0.3.4 → novelai_python-0.3.5}/src/novelai_python/utils/random_prompt/tag_nsfw.py +0 -0
  42. {novelai_python-0.3.4 → novelai_python-0.3.5}/src/novelai_python/utils/useful.py +0 -0
  43. {novelai_python-0.3.4 → novelai_python-0.3.5}/tests/__init__.py +0 -0
  44. {novelai_python-0.3.4 → novelai_python-0.3.5}/tests/test_random_prompt.py +0 -0
  45. {novelai_python-0.3.4 → novelai_python-0.3.5}/tests/test_server.py +0 -0
  46. {novelai_python-0.3.4 → novelai_python-0.3.5}/tests/test_server_run.py +0 -0
  47. {novelai_python-0.3.4 → novelai_python-0.3.5}/tests/test_upscale.py +0 -0
  48. {novelai_python-0.3.4 → novelai_python-0.3.5}/tests/test_user_information.py +0 -0
  49. {novelai_python-0.3.4 → novelai_python-0.3.5}/tests/test_user_login.py +0 -0
  50. {novelai_python-0.3.4 → novelai_python-0.3.5}/tests/test_user_subscription.py +0 -0
File without changes
File without changes
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: novelai-python
3
- Version: 0.3.4
3
+ Version: 0.3.5
4
4
  Summary: Novelai Python Binding With Pydantic
5
5
  Author-Email: sudoskys <coldlando@hotmail.com>
6
6
  License: Apache License 2.0
File without changes
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "novelai-python"
3
- version = "0.3.4"
3
+ version = "0.3.5"
4
4
  description = "Novelai Python Binding With Pydantic"
5
5
  authors = [
6
6
  { name = "sudoskys", email = "coldlando@hotmail.com" },
@@ -34,7 +34,7 @@ class GenerateImageInfer(ApiBaseModel):
34
34
 
35
35
  class Params(BaseModel):
36
36
  # Inpaint
37
- add_original_image: Optional[bool] = False
37
+ add_original_image: Optional[bool] = False # FIXME: 未知作用
38
38
  mask: Optional[Union[str, bytes]] = None # img2img,base64
39
39
 
40
40
  cfg_rescale: Optional[float] = Field(0, ge=0, le=1, multiple_of=0.02)
@@ -57,6 +57,20 @@ class GenerateImageInfer(ApiBaseModel):
57
57
 
58
58
  # Misc
59
59
  params_version: Optional[int] = 1
60
+ reference_image: Optional[Union[str, bytes]] = None
61
+ reference_information_extracted: Optional[float] = Field(1,
62
+ ge=0,
63
+ le=1,
64
+ multiple_of=0.01,
65
+ description="extracting concepts or features"
66
+ )
67
+ reference_strength: Optional[float] = Field(0.6,
68
+ ge=0,
69
+ le=1,
70
+ multiple_of=0.01,
71
+ description="the stronger the AI will try to emulate visual cues."
72
+ )
73
+
60
74
  legacy: Optional[bool] = False
61
75
  legacy_v3_extend: Optional[bool] = False
62
76
 
@@ -84,14 +98,6 @@ class GenerateImageInfer(ApiBaseModel):
84
98
  """Undesired Content Strength"""
85
99
  width: Optional[int] = Field(832, ge=64, le=49152)
86
100
 
87
- @model_validator(mode="after")
88
- def validate_img2img(self):
89
- image = True if self.image else False
90
- add_origin = True if self.add_original_image else False
91
- if image != add_origin:
92
- raise ValueError('Invalid Model Params For img2img2 mode... image should match add_original_image!')
93
- return self
94
-
95
101
  @field_validator('mask')
96
102
  def mask_validator(cls, v: Union[str, bytes]):
97
103
  if isinstance(v, str) and v.startswith("data:image/"):
@@ -108,6 +114,14 @@ class GenerateImageInfer(ApiBaseModel):
108
114
  return base64.b64encode(v).decode("utf-8")
109
115
  return v
110
116
 
117
+ @field_validator('reference_image')
118
+ def image_validator(cls, v: Union[str, bytes]):
119
+ if isinstance(v, str) and v.startswith("data:image/"):
120
+ raise ValueError("Invalid image format, must be base64 encoded.")
121
+ if isinstance(v, bytes):
122
+ return base64.b64encode(v).decode("utf-8")
123
+ return v
124
+
111
125
  @field_validator('width')
112
126
  def width_validator(cls, v: int):
113
127
  """
@@ -176,13 +190,20 @@ class GenerateImageInfer(ApiBaseModel):
176
190
 
177
191
  @model_validator(mode="after")
178
192
  def validate_model(self):
179
- if self.action == Action.INFILL and not self.parameters.mask:
180
- logger.warning("Mask maybe required for infill mode.")
193
+ if self.action == Action.INFILL:
194
+ if not self.parameters.mask:
195
+ logger.warning("Mask maybe required for infill mode.")
181
196
  if self.action != Action.GENERATE:
182
197
  self.parameters.extra_noise_seed = self.parameters.seed
183
198
  if self.action == Action.IMG2IMG:
184
199
  self.parameters.sm = False
185
200
  self.parameters.sm_dyn = False
201
+ if not self.parameters.image:
202
+ raise ValueError("image is must required for img2img mode.")
203
+ if not self.parameters.add_original_image:
204
+ raise ValueError("add_original_image is must required for img2img mode.")
205
+ if self.parameters.image and self.parameters.reference_image:
206
+ logger.warning("image and reference_image should not be used together.")
186
207
  return self
187
208
 
188
209
  @property
@@ -247,11 +268,13 @@ class GenerateImageInfer(ApiBaseModel):
247
268
  qualityToggle: bool = True,
248
269
  ucPreset: Union[UCPreset, int] = UCPreset.TYPE0,
249
270
  image: Union[str, bytes] = None,
271
+ reference_mode: bool = False,
250
272
  add_original_image: bool = None,
251
273
  strength: float = None,
252
274
  mask: Union[str, bytes] = None,
253
275
  controlnet_model: Union[ControlNetModel, str] = None,
254
276
  controlnet_condition: str = None,
277
+ sm_dyn: bool = False,
255
278
  **kwargs
256
279
  ):
257
280
  """
@@ -264,17 +287,19 @@ class GenerateImageInfer(ApiBaseModel):
264
287
  :param negative_prompt: The content of negative prompt
265
288
  :param seed: The seed for generate image
266
289
  :param steps: The steps for generate image
267
- :param scale: Prompt Guidance
290
+ :param scale: The scale for generate image
268
291
  :param cfg_rescale: Prompt Guidance Rescale 0-1 lower is more creative
269
292
  :param sampler: The sampler for generate image
270
293
  :param width: 宽
271
294
  :param height: 高
272
295
  :param image: 图片
296
+ :param reference_mode: 是否是参考模式
273
297
  :param add_original_image: 是否添加原始图片
274
298
  :param strength: IMG2IMG 强度
275
299
  :param mask: Inpainting mask
276
300
  :param controlnet_model: 控制网络模型
277
301
  :param controlnet_condition: 控制网络条件
302
+ :param sm_dyn: 是否使用动态sm
278
303
  :return: self
279
304
  """
280
305
  assert isinstance(prompt, str)
@@ -290,13 +315,22 @@ class GenerateImageInfer(ApiBaseModel):
290
315
  "height": height,
291
316
  "qualityToggle": qualityToggle,
292
317
  "ucPreset": ucPreset,
293
- "image": image,
294
318
  "add_original_image": add_original_image,
295
- "strength": strength,
296
319
  "mask": mask,
297
320
  "controlnet_model": controlnet_model,
298
- "controlnet_condition": controlnet_condition
321
+ "controlnet_condition": controlnet_condition,
322
+ "sm_dyn": sm_dyn,
299
323
  })
324
+ if reference_mode:
325
+ kwargs.update({
326
+ "reference_image": image,
327
+ "reference_strength": strength,
328
+ })
329
+ else:
330
+ kwargs.update({
331
+ "image": image,
332
+ "strength": strength,
333
+ })
300
334
  # 清理空值
301
335
  param = {k: v for k, v in kwargs.items() if v is not None}
302
336
  return cls(
@@ -361,17 +395,15 @@ class GenerateImageInfer(ApiBaseModel):
361
395
  try:
362
396
  _log_data = deepcopy(request_data)
363
397
  if self.action == Action.GENERATE:
398
+ _log_data.get("parameters", {}).update({
399
+ "reference_image": "base64 data" if self.parameters.reference_image else None,
400
+ })
364
401
  logger.debug(f"Request Data: {_log_data}")
365
402
  else:
366
403
  _log_data.get("parameters", {}).update({
367
404
  "image": "base64 data" if self.parameters.image else None,
368
- }
369
- )
370
- _log_data.get("parameters", {}).update(
371
- {
372
- "mask": "base64 data" if self.parameters.mask else None,
373
- }
374
- )
405
+ "mask": "base64 data" if self.parameters.mask else None,
406
+ })
375
407
  logger.debug(f"Request Data: {_log_data}")
376
408
  del _log_data
377
409
  except Exception as e:
@@ -383,7 +415,7 @@ class GenerateImageInfer(ApiBaseModel):
383
415
  data=json.dumps(request_data).encode("utf-8")
384
416
  )
385
417
  if response.headers.get('Content-Type') not in ['binary/octet-stream', 'application/x-zip-compressed']:
386
- logger.error(
418
+ logger.warning(
387
419
  f"Error with content type: {response.headers.get('Content-Type')} and code: {response.status_code}"
388
420
  )
389
421
  try:
@@ -84,7 +84,7 @@ class SuggestTags(ApiBaseModel):
84
84
  url=self.base_url + "?" + "&".join([f"{k}={v}" for k, v in request_data.items()])
85
85
  )
86
86
  if "application/json" not in response.headers.get('Content-Type') or response.status_code != 200:
87
- logger.error(
87
+ logger.warning(
88
88
  f"Error with content type: {response.headers.get('Content-Type')} and code: {response.status_code}"
89
89
  )
90
90
  try:
@@ -131,7 +131,7 @@ class Upscale(ApiBaseModel):
131
131
  data=json.dumps(request_data).encode("utf-8")
132
132
  )
133
133
  if response.headers.get('Content-Type') not in ['binary/octet-stream', 'application/x-zip-compressed']:
134
- logger.error(
134
+ logger.warning(
135
135
  f"Error with content type: {response.headers.get('Content-Type')} and code: {response.status_code}"
136
136
  )
137
137
  try:
@@ -73,7 +73,7 @@ class Information(ApiBaseModel):
73
73
  self.base_url
74
74
  )
75
75
  if "application/json" not in response.headers.get('Content-Type') or response.status_code != 200:
76
- logger.error(
76
+ logger.warning(
77
77
  f"Error with content type: {response.headers.get('Content-Type')} and code: {response.status_code}"
78
78
  )
79
79
  try:
@@ -92,7 +92,7 @@ class Login(ApiBaseModel):
92
92
  data=json.dumps(request_data).encode("utf-8")
93
93
  )
94
94
  if "application/json" not in response.headers.get('Content-Type') or response.status_code != 201:
95
- logger.error(
95
+ logger.warning(
96
96
  f"Error with content type: {response.headers.get('Content-Type')} and code: {response.status_code}"
97
97
  )
98
98
  try:
@@ -80,7 +80,7 @@ class Subscription(ApiBaseModel):
80
80
  url=self.base_url,
81
81
  )
82
82
  if "application/json" not in response.headers.get('Content-Type') or response.status_code != 200:
83
- logger.error(
83
+ logger.warning(
84
84
  f"Error with content type: {response.headers.get('Content-Type')} and code: {response.status_code}"
85
85
  )
86
86
  try: