bizyengine 1.2.45__py3-none-any.whl → 1.2.71__py3-none-any.whl

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 (40) hide show
  1. bizyengine/bizy_server/errno.py +21 -0
  2. bizyengine/bizy_server/server.py +130 -160
  3. bizyengine/bizy_server/utils.py +3 -0
  4. bizyengine/bizyair_extras/__init__.py +38 -31
  5. bizyengine/bizyair_extras/third_party_api/__init__.py +15 -0
  6. bizyengine/bizyair_extras/third_party_api/nodes_doubao.py +535 -0
  7. bizyengine/bizyair_extras/third_party_api/nodes_flux.py +173 -0
  8. bizyengine/bizyair_extras/third_party_api/nodes_gemini.py +403 -0
  9. bizyengine/bizyair_extras/third_party_api/nodes_gpt.py +101 -0
  10. bizyengine/bizyair_extras/third_party_api/nodes_hailuo.py +115 -0
  11. bizyengine/bizyair_extras/third_party_api/nodes_kling.py +404 -0
  12. bizyengine/bizyair_extras/third_party_api/nodes_sora.py +218 -0
  13. bizyengine/bizyair_extras/third_party_api/nodes_veo3.py +193 -0
  14. bizyengine/bizyair_extras/third_party_api/nodes_wan_api.py +198 -0
  15. bizyengine/bizyair_extras/third_party_api/trd_nodes_base.py +183 -0
  16. bizyengine/bizyair_extras/utils/aliyun_oss.py +92 -0
  17. bizyengine/bizyair_extras/utils/audio.py +88 -0
  18. bizyengine/bizybot/__init__.py +12 -0
  19. bizyengine/bizybot/client.py +774 -0
  20. bizyengine/bizybot/config.py +129 -0
  21. bizyengine/bizybot/coordinator.py +556 -0
  22. bizyengine/bizybot/exceptions.py +186 -0
  23. bizyengine/bizybot/mcp/__init__.py +3 -0
  24. bizyengine/bizybot/mcp/manager.py +520 -0
  25. bizyengine/bizybot/mcp/models.py +46 -0
  26. bizyengine/bizybot/mcp/registry.py +129 -0
  27. bizyengine/bizybot/mcp/routing.py +378 -0
  28. bizyengine/bizybot/models.py +344 -0
  29. bizyengine/core/__init__.py +1 -0
  30. bizyengine/core/commands/servers/prompt_server.py +10 -1
  31. bizyengine/core/common/client.py +8 -7
  32. bizyengine/core/common/utils.py +30 -1
  33. bizyengine/core/image_utils.py +12 -283
  34. bizyengine/misc/llm.py +32 -15
  35. bizyengine/misc/utils.py +179 -2
  36. bizyengine/version.txt +1 -1
  37. {bizyengine-1.2.45.dist-info → bizyengine-1.2.71.dist-info}/METADATA +3 -1
  38. {bizyengine-1.2.45.dist-info → bizyengine-1.2.71.dist-info}/RECORD +40 -16
  39. {bizyengine-1.2.45.dist-info → bizyengine-1.2.71.dist-info}/WHEEL +0 -0
  40. {bizyengine-1.2.45.dist-info → bizyengine-1.2.71.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,535 @@
1
+ from bizyairsdk import tensor_to_bytesio
2
+
3
+ from .trd_nodes_base import BizyAirTrdApiBaseNode
4
+
5
+
6
+ class Seedream4(BizyAirTrdApiBaseNode):
7
+ RETURN_TYPES = ("IMAGE",)
8
+ RETURN_NAMES = ("images",)
9
+ CATEGORY = "☁️BizyAir/External APIs/Doubao"
10
+ NODE_DISPLAY_NAME = "Seedream4"
11
+
12
+ @classmethod
13
+ def INPUT_TYPES(s):
14
+ return {
15
+ "required": {
16
+ "prompt": (
17
+ "STRING",
18
+ {
19
+ "multiline": True,
20
+ "default": "",
21
+ },
22
+ ),
23
+ "size": (
24
+ [
25
+ "1K Square (1024x1024)",
26
+ "2K Square (2048x2048)",
27
+ "4K Square (4096x4096)",
28
+ "HD 16:9 (1920x1080)",
29
+ "2K 16:9 (2560x1440)",
30
+ "4K 16:9 (3840x2160)",
31
+ "Portrait 9:16 (1080x1920)",
32
+ "Portrait 3:4 (1536x2048)",
33
+ "Landscape 4:3 (2048x1536)",
34
+ "Ultra-wide 21:9 (3440x1440)",
35
+ "Custom",
36
+ ],
37
+ {
38
+ "default": "HD 16:9 (1920x1080)",
39
+ },
40
+ ),
41
+ "custom_width": ("INT", {"default": 1920, "min": 1024, "max": 4096}),
42
+ "custom_height": ("INT", {"default": 1080, "min": 1024, "max": 4096}),
43
+ "model": (
44
+ ["doubao-seedream-4-0-250828"],
45
+ {"default": "doubao-seedream-4-0-250828"},
46
+ ),
47
+ },
48
+ "optional": {
49
+ "image": ("IMAGE",),
50
+ "image2": ("IMAGE",),
51
+ "image3": ("IMAGE",),
52
+ "image4": ("IMAGE",),
53
+ "image5": ("IMAGE",),
54
+ "image6": ("IMAGE",),
55
+ "image7": ("IMAGE",),
56
+ "image8": ("IMAGE",),
57
+ "image9": ("IMAGE",),
58
+ "image10": ("IMAGE",),
59
+ },
60
+ }
61
+
62
+ def handle_inputs(self, headers, prompt_id, **kwargs):
63
+ model = kwargs.get("model", "doubao-seedream-4-0-250828")
64
+ prompt = kwargs.get("prompt", "")
65
+ size = kwargs.get("size", "1K Square (1024x1024)")
66
+
67
+ match size:
68
+ case "1K Square (1024x1024)":
69
+ width = 1024
70
+ height = 1024
71
+ case "2K Square (2048x2048)":
72
+ width = 2048
73
+ height = 2048
74
+ case "4K Square (4096x4096)":
75
+ width = 4096
76
+ height = 4096
77
+ case "HD 16:9 (1920x1080)":
78
+ width = 1920
79
+ height = 1080
80
+ case "2K 16:9 (2560x1440)":
81
+ width = 2560
82
+ height = 1440
83
+ case "4K 16:9 (3840x2160)":
84
+ width = 3840
85
+ height = 2160
86
+ case "Portrait 9:16 (1080x1920)":
87
+ width = 1080
88
+ height = 1920
89
+ case "Portrait 3:4 (1536x2048)":
90
+ width = 1536
91
+ height = 2048
92
+ case "Landscape 4:3 (2048x1536)":
93
+ width = 2048
94
+ height = 1536
95
+ case "Ultra-wide 21:9 (3440x1440)":
96
+ width = 3440
97
+ height = 1440
98
+ case "Custom":
99
+ width = kwargs.get("custom_width", 1920)
100
+ height = kwargs.get("custom_height", 1080)
101
+
102
+ case _:
103
+ raise ValueError(f"Invalid size: {size}")
104
+
105
+ sizeStr = f"{width}x{height}"
106
+
107
+ images = []
108
+ total_size = 0
109
+ for i, img in enumerate(
110
+ [
111
+ kwargs.get("image", None),
112
+ kwargs.get("image2", None),
113
+ kwargs.get("image3", None),
114
+ kwargs.get("image4", None),
115
+ kwargs.get("image5", None),
116
+ kwargs.get("image6", None),
117
+ kwargs.get("image7", None),
118
+ kwargs.get("image8", None),
119
+ kwargs.get("image9", None),
120
+ kwargs.get("image10", None),
121
+ ],
122
+ 1,
123
+ ):
124
+ if img is not None:
125
+ # 都当作PNG就行
126
+ bio = tensor_to_bytesio(image=img, total_pixels=4096 * 4096)
127
+ length = bio.getbuffer().nbytes
128
+ if length > 10 * 1024 * 1024:
129
+ raise ValueError(
130
+ "Image size is too large, Seedream 4.0 only supports up to 10MB"
131
+ )
132
+ total_size += length
133
+ if total_size > 50 * 1024 * 1024:
134
+ raise ValueError(
135
+ "Total size of images is too large, BizyAir only supports up to 50MB"
136
+ )
137
+ images.append(self.upload_file(bio, f"{prompt_id}_{i}.png", headers))
138
+
139
+ data = {
140
+ "prompt": prompt,
141
+ "size": sizeStr,
142
+ "image": images,
143
+ "model": model,
144
+ "watermark": False,
145
+ "response_format": "url",
146
+ }
147
+
148
+ return data, model
149
+
150
+ def handle_outputs(self, outputs):
151
+ images = self.combine_images(outputs[1])
152
+ return (images,)
153
+
154
+
155
+ class Seedream4_5(BizyAirTrdApiBaseNode):
156
+ RETURN_TYPES = ("IMAGE",)
157
+ RETURN_NAMES = ("images",)
158
+ CATEGORY = "☁️BizyAir/External APIs/Doubao"
159
+ NODE_DISPLAY_NAME = "Seedream 4.5"
160
+
161
+ @classmethod
162
+ def INPUT_TYPES(s):
163
+ return {
164
+ "required": {
165
+ "prompt": (
166
+ "STRING",
167
+ {
168
+ "multiline": True,
169
+ "default": "",
170
+ },
171
+ ),
172
+ "model": (
173
+ ["doubao-seedream-4-5-251128"],
174
+ {"default": "doubao-seedream-4-5-251128"},
175
+ ),
176
+ "size": (
177
+ [
178
+ "2K",
179
+ "4K",
180
+ "Custom",
181
+ ],
182
+ {
183
+ "default": "2K",
184
+ },
185
+ ),
186
+ "custom_width": (
187
+ "INT",
188
+ {
189
+ "default": 2048,
190
+ "min": 480,
191
+ "max": 4096,
192
+ "tooltip": "总像素取值范围 [2560x1440=3686400, 4096x4096=16777216], 宽高比取值范围:[1/16, 16]",
193
+ },
194
+ ),
195
+ "custom_height": (
196
+ "INT",
197
+ {
198
+ "default": 2048,
199
+ "min": 480,
200
+ "max": 4096,
201
+ "tooltip": "总像素取值范围 [2560x1440=3686400, 4096x4096=16777216], 宽高比取值范围:[1/16, 16]",
202
+ },
203
+ ),
204
+ "max_images": (
205
+ "INT",
206
+ {
207
+ "default": 1,
208
+ "min": 1,
209
+ "max": 15,
210
+ "tooltip": "实际可生成的图片数量,除受到 max_images 影响外,还受到输入的参考图数量影响。输入的参考图数量+最终生成的图片数量≤15张。",
211
+ },
212
+ ),
213
+ "optimize_prompt": (
214
+ ["disabled", "standard"],
215
+ {
216
+ "default": "disabled",
217
+ "tooltip": "提示词优化功能的配置。standard:标准模式,生成内容的质量更高,耗时较长。",
218
+ },
219
+ ),
220
+ },
221
+ "optional": {
222
+ "images": (
223
+ "IMAGE",
224
+ {"tooltip": "参考图,数量不超过14张。会影响组图生成数量"},
225
+ ),
226
+ },
227
+ }
228
+
229
+ def handle_inputs(self, headers, prompt_id, **kwargs):
230
+ # up to 14 ref images
231
+ # 10mb each
232
+ # custom total pixels [3686400, 16777216]
233
+ # custom size ratio [1/16, 16]
234
+ model = kwargs.get("model", "doubao-seedream-4-0-250828")
235
+ prompt = kwargs.get("prompt", "")
236
+ size = kwargs.get("size", "2K")
237
+ images = kwargs.get("images", None)
238
+ optimize_prompt = kwargs.get("optimize_prompt", "disabled")
239
+ max_images = kwargs.get("max_images", 1)
240
+
241
+ if images is not None and len(images) > 14:
242
+ raise ValueError("Maximum number of images is 14")
243
+ if size == "Custom":
244
+ width = kwargs.get("custom_width", 2048)
245
+ height = kwargs.get("custom_height", 2048)
246
+ if width * height < 3686400 or width * height > 16777216:
247
+ raise ValueError("Total pixels must be between 3686400 and 16777216")
248
+ if width / height < 1 / 16 or width / height > 16:
249
+ raise ValueError("Width/height ratio must be between 1/16 and 16")
250
+ size = f"{width}x{height}"
251
+
252
+ parts = []
253
+ for batch_number, img in enumerate(images if images is not None else []):
254
+ if img is not None:
255
+ bio = tensor_to_bytesio(image=img, total_pixels=4096 * 4096)
256
+ length = bio.getbuffer().nbytes
257
+ if length > 10 * 1024 * 1024:
258
+ raise ValueError(
259
+ "Image size is too large, Seedream 4.5 only supports up to 10MB"
260
+ )
261
+ url = self.upload_file(
262
+ bio,
263
+ f"{prompt_id}_{batch_number}.png",
264
+ headers,
265
+ )
266
+ parts.append(url)
267
+
268
+ data = {
269
+ "prompt": prompt,
270
+ "size": size,
271
+ "model": model,
272
+ "max_images": max_images,
273
+ }
274
+ if len(parts) > 0:
275
+ data["image"] = parts
276
+ if optimize_prompt != "disabled":
277
+ data["optimize_prompt"] = optimize_prompt
278
+
279
+ return data, model
280
+
281
+ def handle_outputs(self, outputs):
282
+ images = self.combine_images(outputs[1])
283
+ return (images,)
284
+
285
+
286
+ class Seededit3(BizyAirTrdApiBaseNode):
287
+ RETURN_TYPES = ("IMAGE",)
288
+ RETURN_NAMES = ("image",)
289
+ CATEGORY = "☁️BizyAir/External APIs/Doubao"
290
+ NODE_DISPLAY_NAME = "Seededit3"
291
+
292
+ @classmethod
293
+ def INPUT_TYPES(cls):
294
+ return {
295
+ "required": {
296
+ "image": ("IMAGE",),
297
+ "prompt": (
298
+ "STRING",
299
+ {
300
+ "multiline": True,
301
+ "default": "",
302
+ },
303
+ ),
304
+ "model": (
305
+ ["doubao-seededit-3-0-i2i-250628"],
306
+ {"default": "doubao-seededit-3-0-i2i-250628"},
307
+ ),
308
+ "seed": ("INT", {"default": -1, "min": -1, "max": 2147483647}),
309
+ "guidance_scale": ("FLOAT", {"default": 5.5, "min": 1.0, "max": 10.0}),
310
+ },
311
+ }
312
+
313
+ def handle_inputs(self, headers, prompt_id, **kwargs):
314
+ model = kwargs.get("model", "doubao-seededit-3-0-i2i-250628")
315
+ prompt = kwargs.get("prompt", "")
316
+ image = kwargs.get("image", None)
317
+ seed = kwargs.get("seed", -1)
318
+ guidance_scale = kwargs.get("guidance_scale", 5.5)
319
+ if image is None:
320
+ raise ValueError("Image is required")
321
+ # 上传图片
322
+ image_url = self.upload_file(
323
+ tensor_to_bytesio(image=image, total_pixels=4096 * 4096),
324
+ f"{prompt_id}.png",
325
+ headers,
326
+ )
327
+ data = {
328
+ "prompt": prompt,
329
+ "model": model,
330
+ "image": image_url,
331
+ "seed": seed,
332
+ "guidance_scale": guidance_scale,
333
+ "size": "adaptive",
334
+ "response_format": "url",
335
+ "watermark": False,
336
+ }
337
+ return data, model
338
+
339
+ def handle_outputs(self, outputs):
340
+ images = self.combine_images(outputs[1])
341
+ return (images,)
342
+
343
+
344
+ class Seedance_1_0_T2V_API(BizyAirTrdApiBaseNode):
345
+ RETURN_TYPES = ("VIDEO",)
346
+ RETURN_NAMES = ("video",)
347
+ CATEGORY = "☁️BizyAir/External APIs/Doubao"
348
+ NODE_DISPLAY_NAME = "Seedance 1.0 Pro Text To Video"
349
+
350
+ @classmethod
351
+ def INPUT_TYPES(cls):
352
+ return {
353
+ "required": {
354
+ "prompt": (
355
+ "STRING",
356
+ {
357
+ "multiline": True,
358
+ "default": "",
359
+ },
360
+ ),
361
+ "model": (
362
+ [
363
+ "doubao-seedance-1-0-pro-250528",
364
+ "doubao-seedance-1-0-pro-fast-251015",
365
+ ],
366
+ {"default": "doubao-seedance-1-0-pro-250528"},
367
+ ),
368
+ "resolution": (
369
+ ["480p", "720p", "1080p"],
370
+ {
371
+ "default": "1080p",
372
+ "tooltip": "分辨率+比例共同决定视频尺寸,具体尺寸请参考官方文档说明",
373
+ },
374
+ ),
375
+ "ratio": (
376
+ ["16:9", "4:3", "1:1", "3:4", "9:16", "21:9", "adaptive"],
377
+ {
378
+ "default": "adaptive",
379
+ "tooltip": "比例+分辨率共同决定视频尺寸,具体尺寸请参考官方文档说明",
380
+ },
381
+ ),
382
+ "duration": ("INT", {"default": 12, "min": 2, "max": 12}),
383
+ "fps": (
384
+ [24],
385
+ {
386
+ "default": 24,
387
+ "tooltip": "帧率固定24",
388
+ },
389
+ ),
390
+ "camerafixed": (
391
+ "BOOLEAN",
392
+ {
393
+ "default": False,
394
+ "tooltip": "平台可能在提示词中追加固定摄像机指令(效果不保证) ",
395
+ },
396
+ ),
397
+ "seed": ("INT", {"default": -1, "min": -1, "max": 2147483647}),
398
+ },
399
+ }
400
+
401
+ def handle_inputs(self, headers, prompt_id, **kwargs):
402
+ model = kwargs.get("model", "doubao-seedance-1-0-pro-250528")
403
+ prompt = kwargs.get("prompt", "")
404
+ resolution = kwargs.get("resolution", "1080p")
405
+ ratio = kwargs.get("ratio", "adaptive")
406
+ duration = kwargs.get("duration", 12)
407
+ camerafixed = kwargs.get("camerafixed", False)
408
+ seed = kwargs.get("seed", -1)
409
+ if prompt is None or prompt.strip() == "":
410
+ raise ValueError("Prompt is required")
411
+ data = {
412
+ "prompt": prompt,
413
+ "model": model,
414
+ "resolution": resolution,
415
+ "ratio": ratio,
416
+ "duration": duration,
417
+ "camerafixed": camerafixed,
418
+ "seed": seed,
419
+ "watermark": False,
420
+ "fps": 24,
421
+ }
422
+ return data, "doubao-seedance-1-0"
423
+
424
+ def handle_outputs(self, outputs):
425
+ return (outputs[0][0],)
426
+
427
+
428
+ class Seedance_1_0_I2V_API(BizyAirTrdApiBaseNode):
429
+ RETURN_TYPES = ("VIDEO",)
430
+ RETURN_NAMES = ("video",)
431
+ CATEGORY = "☁️BizyAir/External APIs/Doubao"
432
+ NODE_DISPLAY_NAME = "Seedance 1.0 Pro Image To Video"
433
+
434
+ @classmethod
435
+ def INPUT_TYPES(cls):
436
+ return {
437
+ "required": {
438
+ "first_frame_image": ("IMAGE",),
439
+ "prompt": (
440
+ "STRING",
441
+ {
442
+ "multiline": True,
443
+ "default": "",
444
+ },
445
+ ),
446
+ "model": (
447
+ [
448
+ "doubao-seedance-1-0-pro-250528",
449
+ "doubao-seedance-1-0-pro-fast-251015",
450
+ ],
451
+ {"default": "doubao-seedance-1-0-pro-250528"},
452
+ ),
453
+ "resolution": (
454
+ ["480p", "720p", "1080p"],
455
+ {
456
+ "default": "1080p",
457
+ "tooltip": "分辨率+比例共同决定视频尺寸,具体尺寸请参考官方文档说明",
458
+ },
459
+ ),
460
+ "ratio": (
461
+ ["16:9", "4:3", "1:1", "3:4", "9:16", "21:9", "adaptive"],
462
+ {
463
+ "default": "adaptive",
464
+ "tooltip": "比例+分辨率共同决定视频尺寸,具体尺寸请参考官方文档说明",
465
+ },
466
+ ),
467
+ "duration": ("INT", {"default": 12, "min": 2, "max": 12}),
468
+ "fps": (
469
+ [24],
470
+ {
471
+ "default": 24,
472
+ "tooltip": "帧率固定24",
473
+ },
474
+ ),
475
+ "camerafixed": (
476
+ "BOOLEAN",
477
+ {
478
+ "default": False,
479
+ "tooltip": "平台可能在提示词中追加固定摄像机指令(效果不保证) ",
480
+ },
481
+ ),
482
+ "seed": ("INT", {"default": -1, "min": -1, "max": 2147483647}),
483
+ },
484
+ "optional": {
485
+ "last_frame_image": ("IMAGE",),
486
+ },
487
+ }
488
+
489
+ def handle_inputs(self, headers, prompt_id, **kwargs):
490
+ model = kwargs.get("model", "doubao-seedance-1-0-pro-250528")
491
+ prompt = kwargs.get("prompt", "")
492
+ resolution = kwargs.get("resolution", "1080p")
493
+ ratio = kwargs.get("ratio", "adaptive")
494
+ duration = kwargs.get("duration", 12)
495
+ camerafixed = kwargs.get("camerafixed", False)
496
+ seed = kwargs.get("seed", -1)
497
+ first_frame_image = kwargs.get("first_frame_image", None)
498
+ last_frame_image = kwargs.get("last_frame_image", None)
499
+ if first_frame_image is None:
500
+ raise ValueError("First frame image is required")
501
+ if (
502
+ last_frame_image is not None
503
+ and model == "doubao-seedance-1-0-pro-fast-251015"
504
+ ):
505
+ raise ValueError(
506
+ "Last frame image is not supported for doubao-seedance-1-0-pro-fast-251015"
507
+ )
508
+ first_frame_image_url = self.upload_file(
509
+ tensor_to_bytesio(image=first_frame_image, total_pixels=4096 * 4096),
510
+ f"{prompt_id}_first.png",
511
+ headers,
512
+ )
513
+ data = {
514
+ "prompt": prompt,
515
+ "model": model,
516
+ "resolution": resolution,
517
+ "ratio": ratio,
518
+ "duration": duration,
519
+ "camerafixed": camerafixed,
520
+ "seed": seed,
521
+ "watermark": False,
522
+ "fps": 24,
523
+ "first_frame_image": first_frame_image_url,
524
+ }
525
+ if last_frame_image is not None:
526
+ last_frame_image_url = self.upload_file(
527
+ tensor_to_bytesio(image=last_frame_image, total_pixels=4096 * 4096),
528
+ f"{prompt_id}_last.png",
529
+ headers,
530
+ )
531
+ data["last_frame_image"] = last_frame_image_url
532
+ return data, "doubao-seedance-1-0"
533
+
534
+ def handle_outputs(self, outputs):
535
+ return (outputs[0][0],)