bizyengine 1.2.77__py3-none-any.whl → 1.2.79__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.
@@ -1,6 +1,7 @@
1
1
  import asyncio
2
2
  import json
3
3
  import os
4
+ import urllib
4
5
 
5
6
  import aiohttp
6
7
  from openai import OpenAI
@@ -72,7 +73,6 @@ class APIClient:
72
73
  resp_json = json.loads(resp_text)
73
74
  except Exception:
74
75
  resp_json = resp_text
75
-
76
76
  if response.status != 200:
77
77
  print(
78
78
  f"\033[31m[BizyAir]\033[0m API Error: {method} {url} {response.status} Body: {resp_text}"
@@ -91,8 +91,11 @@ class APIClient:
91
91
  return resp_json, None
92
92
 
93
93
  async def do_get(self, url, params=None, headers=None):
94
+ if params:
95
+ query_string = urllib.parse.urlencode(params, doseq=True)
96
+ url = f"{url}?{query_string}"
94
97
  async with await self.get_session() as session:
95
- async with session.get(url, params=params, headers=headers) as response:
98
+ async with session.get(url, headers=headers) as response:
96
99
  return await self._handle_response(response, "GET", url)
97
100
 
98
101
  async def do_post(self, url, data=None, headers=None):
@@ -1208,3 +1211,22 @@ class APIClient:
1208
1211
  except aiohttp.ClientError as e:
1209
1212
  print(f"get_plugin_tmp_token error: {e}")
1210
1213
  return None, errnos.GET_PLUGIN_TMP_TOKEN
1214
+
1215
+ async def trd_api_pricing(self, model: str, data, request_api_key: str = None):
1216
+ server_url = f"{BIZYAIR_Y_SERVER}/trd_api/node/{model}/price"
1217
+
1218
+ headers, err = self.auth_header(api_key=request_api_key)
1219
+ if err is not None:
1220
+ return None, err
1221
+
1222
+ try:
1223
+ ret, err = await self.do_post(server_url, headers=headers, data=data)
1224
+ if err is not None:
1225
+ return None, err
1226
+
1227
+ return ret["data"], None
1228
+ except Exception as e:
1229
+ print(
1230
+ f"\033[31m[BizyAir]\033[0m Fail to get trd api node {model} pricing: {str(e)}"
1231
+ )
1232
+ return None, errnos.TRD_API_PRICING
@@ -510,3 +510,10 @@ class errnos:
510
510
  None,
511
511
  {"en": "Failed to get tmp token", "zh": "获取临时令牌失败"},
512
512
  )
513
+
514
+ TRD_API_PRICING = ErrorNo(
515
+ 500,
516
+ 500162,
517
+ None,
518
+ {"en": "Failed to get trd api node pricing", "zh": "获取第三方API节点定价失败"},
519
+ )
@@ -1,4 +1,5 @@
1
1
  import asyncio
2
+ import errno
2
3
  import json
3
4
  import logging
4
5
  import re
@@ -50,6 +51,10 @@ if not BIZYAIR_DEBUG:
50
51
  def _get_request_api_key(request_headers):
51
52
  if BIZYAIR_SERVER_MODE:
52
53
  encrypted_api_key = request_headers.get("Authorization")
54
+ if not encrypted_api_key:
55
+ # 尝试从cookie中读取auth_token
56
+ cookie_str = request_headers.get("Cookie")
57
+ encrypted_api_key = _get_auth_token_from_cookie(cookie_str)
53
58
  return decrypt_apikey(encrypted_api_key)
54
59
  return None, None
55
60
 
@@ -64,6 +69,17 @@ def _get_api_key_from_cookie(cookie_str):
64
69
  return None
65
70
 
66
71
 
72
+ def _get_auth_token_from_cookie(cookie_str):
73
+ if not cookie_str:
74
+ return None
75
+ cookies = cookie_str.split(";")
76
+ for cookie in cookies:
77
+ cookie = cookie.strip()
78
+ if cookie.startswith("auth_token="):
79
+ return cookie[11:]
80
+ return None
81
+
82
+
67
83
  class BizyAirServer:
68
84
  def __init__(self):
69
85
  BizyAirServer.instance = self
@@ -951,6 +967,24 @@ class BizyAirServer:
951
967
  print(f"\033[31m[BizyAir]\033[0m Chat request failed: {str(e)}")
952
968
  return ErrResponse(errnos.MODEL_API_ERROR)
953
969
 
970
+ @self.prompt_server.routes.post(f"/{API_PREFIX}/trd_api_pricing")
971
+ async def trd_api_pricing(request):
972
+ request_api_key, err = _get_request_api_key(request.headers)
973
+ if err:
974
+ return ErrResponse(err)
975
+ model = request.rel_url.query.get("model", "")
976
+ if not model:
977
+ return ErrResponse(errnos.INVALID_MODEL_ID)
978
+ data = {}
979
+ if request.body_exists:
980
+ data = await request.json()
981
+ pricing, err = await self.api_client.trd_api_pricing(
982
+ model=model, data=data, request_api_key=request_api_key
983
+ )
984
+ if err:
985
+ return ErrResponse(err)
986
+ return OKResponse(pricing)
987
+
954
988
  # 服务器模式独占
955
989
  if BIZYAIR_SERVER_MODE:
956
990
  return
@@ -8,6 +8,7 @@ modules = [
8
8
  ".nodes_sora",
9
9
  ".nodes_veo3",
10
10
  ".nodes_wan_api",
11
+ ".nodes_vidu",
11
12
  ]
12
13
  from bizyengine.core.common.utils import safe_star_import
13
14
 
@@ -4,8 +4,11 @@ from .trd_nodes_base import BizyAirTrdApiBaseNode
4
4
 
5
5
 
6
6
  class Seedream4(BizyAirTrdApiBaseNode):
7
- RETURN_TYPES = ("IMAGE",)
8
- RETURN_NAMES = ("images",)
7
+ RETURN_TYPES = (
8
+ "IMAGE",
9
+ """{"doubao-seedream-4-0-250828": "doubao-seedream-4-0-250828"}""",
10
+ )
11
+ RETURN_NAMES = ("images", "bizyair_model_name")
9
12
  CATEGORY = "☁️BizyAir/External APIs/Doubao"
10
13
  NODE_DISPLAY_NAME = "Seedream4"
11
14
 
@@ -149,12 +152,15 @@ class Seedream4(BizyAirTrdApiBaseNode):
149
152
 
150
153
  def handle_outputs(self, outputs):
151
154
  images = self.combine_images(outputs[1])
152
- return (images,)
155
+ return (images, "")
153
156
 
154
157
 
155
158
  class Seedream4_5(BizyAirTrdApiBaseNode):
156
- RETURN_TYPES = ("IMAGE",)
157
- RETURN_NAMES = ("images",)
159
+ RETURN_TYPES = (
160
+ "IMAGE",
161
+ """{"doubao-seedream-4-5-251128": "doubao-seedream-4-5-251128"}""",
162
+ )
163
+ RETURN_NAMES = ("images", "bizyair_model_name")
158
164
  CATEGORY = "☁️BizyAir/External APIs/Doubao"
159
165
  NODE_DISPLAY_NAME = "Seedream 4.5"
160
166
  INPUT_IS_LIST = True
@@ -251,7 +257,8 @@ class Seedream4_5(BizyAirTrdApiBaseNode):
251
257
  # 多图的情况可以认为图片输入都是List[Image Batch]
252
258
  total_input_images = 0
253
259
  for _, img_batch in enumerate(images if images is not None else []):
254
- total_input_images += img_batch.shape[0]
260
+ if img_batch is not None:
261
+ total_input_images += img_batch.shape[0]
255
262
  extra_images, total_extra_images = self.get_extra_images(**kwargs)
256
263
  total_input_images += total_extra_images
257
264
  if total_input_images > 14:
@@ -316,12 +323,15 @@ class Seedream4_5(BizyAirTrdApiBaseNode):
316
323
 
317
324
  def handle_outputs(self, outputs):
318
325
  images = self.combine_images(outputs[1])
319
- return (images,)
326
+ return (images, "")
320
327
 
321
328
 
322
329
  class Seededit3(BizyAirTrdApiBaseNode):
323
- RETURN_TYPES = ("IMAGE",)
324
- RETURN_NAMES = ("image",)
330
+ RETURN_TYPES = (
331
+ "IMAGE",
332
+ """{"doubao-seededit-3-0-i2i-250628": "doubao-seededit-3-0-i2i-250628"}""",
333
+ )
334
+ RETURN_NAMES = ("image", "bizyair_model_name")
325
335
  CATEGORY = "☁️BizyAir/External APIs/Doubao"
326
336
  NODE_DISPLAY_NAME = "Seededit3"
327
337
 
@@ -374,12 +384,15 @@ class Seededit3(BizyAirTrdApiBaseNode):
374
384
 
375
385
  def handle_outputs(self, outputs):
376
386
  images = self.combine_images(outputs[1])
377
- return (images,)
387
+ return (images, "")
378
388
 
379
389
 
380
390
  class Seedance_1_0_T2V_API(BizyAirTrdApiBaseNode):
381
- RETURN_TYPES = ("VIDEO",)
382
- RETURN_NAMES = ("video",)
391
+ RETURN_TYPES = (
392
+ "VIDEO",
393
+ """{"doubao-seedance-1-0-pro-250528": "doubao-seedance-1-0","doubao-seedance-1-0-pro-fast-251015": "doubao-seedance-1-0"}""",
394
+ )
395
+ RETURN_NAMES = ("video", "bizyair_model_name")
383
396
  CATEGORY = "☁️BizyAir/External APIs/Doubao"
384
397
  NODE_DISPLAY_NAME = "Seedance 1.0 Pro Text To Video"
385
398
 
@@ -458,12 +471,15 @@ class Seedance_1_0_T2V_API(BizyAirTrdApiBaseNode):
458
471
  return data, "doubao-seedance-1-0"
459
472
 
460
473
  def handle_outputs(self, outputs):
461
- return (outputs[0][0],)
474
+ return (outputs[0][0], "")
462
475
 
463
476
 
464
477
  class Seedance_1_0_I2V_API(BizyAirTrdApiBaseNode):
465
- RETURN_TYPES = ("VIDEO",)
466
- RETURN_NAMES = ("video",)
478
+ RETURN_TYPES = (
479
+ "VIDEO",
480
+ """{"doubao-seedance-1-0-pro-250528": "doubao-seedance-1-0","doubao-seedance-1-0-pro-fast-251015": "doubao-seedance-1-0"}""",
481
+ )
482
+ RETURN_NAMES = ("video", "bizyair_model_name")
467
483
  CATEGORY = "☁️BizyAir/External APIs/Doubao"
468
484
  NODE_DISPLAY_NAME = "Seedance 1.0 Pro Image To Video"
469
485
 
@@ -568,4 +584,4 @@ class Seedance_1_0_I2V_API(BizyAirTrdApiBaseNode):
568
584
  return data, "doubao-seedance-1-0"
569
585
 
570
586
  def handle_outputs(self, outputs):
571
- return (outputs[0][0],)
587
+ return (outputs[0][0], "")
@@ -5,8 +5,11 @@ from .trd_nodes_base import BizyAirTrdApiBaseNode
5
5
 
6
6
  class Flux_Kontext_API(BizyAirTrdApiBaseNode):
7
7
  NODE_DISPLAY_NAME = "Flux Kontext API"
8
- RETURN_TYPES = ("IMAGE",)
9
- RETURN_NAMES = ("image",)
8
+ RETURN_TYPES = (
9
+ "IMAGE",
10
+ """{"flux-kontext-pro": "flux-kontext","flux-kontext-max": "flux-kontext"}""",
11
+ )
12
+ RETURN_NAMES = ("image", "bizyair_model_name")
10
13
  CATEGORY = "☁️BizyAir/External APIs/Flux"
11
14
 
12
15
  @classmethod
@@ -58,13 +61,13 @@ class Flux_Kontext_API(BizyAirTrdApiBaseNode):
58
61
 
59
62
  def handle_outputs(self, outputs):
60
63
  images = self.combine_images(outputs[1])
61
- return (images,)
64
+ return (images, "")
62
65
 
63
66
 
64
67
  class Flux_2_API(BizyAirTrdApiBaseNode):
65
68
  NODE_DISPLAY_NAME = "Flux 2 API"
66
- RETURN_TYPES = ("IMAGE",)
67
- RETURN_NAMES = ("image",)
69
+ RETURN_TYPES = ("IMAGE", """{"flux-2-pro": "flux-2","flux-2-flex": "flux-2"}""")
70
+ RETURN_NAMES = ("image", "bizyair_model_name")
68
71
  CATEGORY = "☁️BizyAir/External APIs/Flux"
69
72
 
70
73
  @classmethod
@@ -170,4 +173,4 @@ class Flux_2_API(BizyAirTrdApiBaseNode):
170
173
 
171
174
  def handle_outputs(self, outputs):
172
175
  images = self.combine_images(outputs[1])
173
- return (images,)
176
+ return (images, "")
@@ -60,7 +60,12 @@ def build_prompt_for_operation(
60
60
 
61
61
  class NanoBanana(BizyAirTrdApiBaseNode):
62
62
  NODE_DISPLAY_NAME = "NanoBanana"
63
- RETURN_TYPES = ("IMAGE", "STRING")
63
+ RETURN_TYPES = (
64
+ "IMAGE",
65
+ "STRING",
66
+ """{"gemini-2.5-flash-image": "gemini-2.5-flash-image"}""",
67
+ )
68
+ RETURN_NAMES = ("image", "string", "bizyair_model_name")
64
69
  CATEGORY = "☁️BizyAir/External APIs/Gemini"
65
70
 
66
71
  @classmethod
@@ -114,6 +119,7 @@ class NanoBanana(BizyAirTrdApiBaseNode):
114
119
  },
115
120
  ),
116
121
  },
122
+ "hidden": {"bizyair_model_name": {"default": "gemini-2.5-flash-image"}},
117
123
  }
118
124
 
119
125
  def handle_inputs(self, headers, prompt_id, **kwargs):
@@ -176,13 +182,17 @@ class NanoBanana(BizyAirTrdApiBaseNode):
176
182
  raise ValueError("No image found in response")
177
183
  if len(outputs[2]) > 0:
178
184
  text = outputs[2][0]
179
- return (image, text)
185
+ return (image, text, "")
180
186
 
181
187
 
182
188
  class NanoBananaPro(BizyAirTrdApiBaseNode):
183
189
  NODE_DISPLAY_NAME = "NanoBananaPro"
184
- RETURN_TYPES = ("IMAGE", "STRING")
185
- RETURN_NAMES = ("image", "string")
190
+ RETURN_TYPES = (
191
+ "IMAGE",
192
+ "STRING",
193
+ """{"gemini-3-pro-image-preview": "gemini-3-pro-image-preview"}""",
194
+ )
195
+ RETURN_NAMES = ("image", "string", "bizyair_model_name")
186
196
  CATEGORY = "☁️BizyAir/External APIs/Gemini"
187
197
  INPUT_IS_LIST = True
188
198
 
@@ -273,7 +283,8 @@ class NanoBananaPro(BizyAirTrdApiBaseNode):
273
283
  # 多图的情况可以认为图片输入都是List[Image Batch]
274
284
  total_input_images = 0
275
285
  for _, img_batch in enumerate(images if images is not None else []):
276
- total_input_images += img_batch.shape[0]
286
+ if img_batch is not None:
287
+ total_input_images += img_batch.shape[0]
277
288
  extra_images, total_extra_images = self.get_extra_images(**kwargs)
278
289
  total_input_images += total_extra_images
279
290
  if total_input_images > 14:
@@ -333,7 +344,7 @@ class NanoBananaPro(BizyAirTrdApiBaseNode):
333
344
  raise ValueError("No image found in response")
334
345
  if len(outputs[2]) > 0:
335
346
  text = outputs[2][0]
336
- return (image, text)
347
+ return (image, text, "")
337
348
 
338
349
 
339
350
  class NanoBananaProOfficial(BizyAirTrdApiBaseNode):
@@ -390,8 +401,12 @@ class NanoBananaProOfficial(BizyAirTrdApiBaseNode):
390
401
  },
391
402
  }
392
403
 
393
- RETURN_TYPES = ("IMAGE", "STRING")
394
- RETURN_NAMES = ("image", "string")
404
+ RETURN_TYPES = (
405
+ "IMAGE",
406
+ "STRING",
407
+ """{"gemini-3-pro-image-preview": "gemini-3-pro-image-preview"}""",
408
+ )
409
+ RETURN_NAMES = ("image", "string", "bizyair_model_name")
395
410
  CATEGORY = "☁️BizyAir/External APIs/Gemini"
396
411
  NODE_DISPLAY_NAME = "NanoBananaPro (Official Parameters)"
397
412
  INPUT_IS_LIST = True
@@ -409,7 +424,8 @@ class NanoBananaProOfficial(BizyAirTrdApiBaseNode):
409
424
  # 多图的情况可以认为图片输入都是List[Image Batch]
410
425
  total_input_images = 0
411
426
  for _, img_batch in enumerate(images if images is not None else []):
412
- total_input_images += img_batch.shape[0]
427
+ if img_batch is not None:
428
+ total_input_images += img_batch.shape[0]
413
429
  total_input_images += total_extra_images
414
430
  if total_input_images > 14:
415
431
  raise ValueError("Maximum number of images is 14")
@@ -457,4 +473,4 @@ class NanoBananaProOfficial(BizyAirTrdApiBaseNode):
457
473
  raise ValueError("No image found in response")
458
474
  if len(outputs[2]) > 0:
459
475
  text = outputs[2][0]
460
- return (image, text)
476
+ return (image, text, "")
@@ -5,8 +5,8 @@ from .trd_nodes_base import BizyAirTrdApiBaseNode
5
5
 
6
6
  class GPT_IMAGE_1_T2I_API(BizyAirTrdApiBaseNode):
7
7
  NODE_DISPLAY_NAME = "GPT Image 1 Text To Image"
8
- RETURN_TYPES = ("IMAGE",)
9
- RETURN_NAMES = ("images",)
8
+ RETURN_TYPES = ("IMAGE", """{"gpt-image-1": "gpt-image-1"}""")
9
+ RETURN_NAMES = ("images", "bizyair_model_name")
10
10
  CATEGORY = "☁️BizyAir/External APIs/OpenAI"
11
11
 
12
12
  @classmethod
@@ -40,13 +40,13 @@ class GPT_IMAGE_1_T2I_API(BizyAirTrdApiBaseNode):
40
40
 
41
41
  def handle_outputs(self, outputs):
42
42
  images = self.combine_images(outputs[1])
43
- return (images,)
43
+ return (images, "")
44
44
 
45
45
 
46
46
  class GPT_IMAGE_EDIT_API(BizyAirTrdApiBaseNode):
47
47
  NODE_DISPLAY_NAME = "GPT Image Edit"
48
- RETURN_TYPES = ("IMAGE",)
49
- RETURN_NAMES = ("images",)
48
+ RETURN_TYPES = ("IMAGE", """{"gpt-image-1": "gpt-image-1"}""")
49
+ RETURN_NAMES = ("images", "bizyair_model_name")
50
50
  CATEGORY = "☁️BizyAir/External APIs/OpenAI"
51
51
 
52
52
  @classmethod
@@ -98,4 +98,4 @@ class GPT_IMAGE_EDIT_API(BizyAirTrdApiBaseNode):
98
98
 
99
99
  def handle_outputs(self, outputs):
100
100
  images = self.combine_images(outputs[1])
101
- return (images,)
101
+ return (images, "")
@@ -28,8 +28,8 @@ class Hailuo2_3_T2V(BizyAirTrdApiBaseNode):
28
28
  }
29
29
 
30
30
  NODE_DISPLAY_NAME = "Hailuo2.3 Text To Video"
31
- RETURN_TYPES = ("VIDEO",)
32
- RETURN_NAMES = ("video",)
31
+ RETURN_TYPES = ("VIDEO", """{"MiniMax-Hailuo-2.3-t2v": "MiniMax-Hailuo-2.3-t2v"}""")
32
+ RETURN_NAMES = ("video", "bizyair_model_name")
33
33
  CATEGORY = "☁️BizyAir/External APIs/Hailuo"
34
34
 
35
35
  def handle_inputs(self, headers, prompt_id, **kwargs):
@@ -50,7 +50,7 @@ class Hailuo2_3_T2V(BizyAirTrdApiBaseNode):
50
50
  return data, "MiniMax-Hailuo-2.3-t2v"
51
51
 
52
52
  def handle_outputs(self, outputs):
53
- return (outputs[0][0],)
53
+ return (outputs[0][0], "")
54
54
 
55
55
 
56
56
  class Hailuo2_3_I2V(BizyAirTrdApiBaseNode):
@@ -79,8 +79,8 @@ class Hailuo2_3_I2V(BizyAirTrdApiBaseNode):
79
79
  }
80
80
 
81
81
  NODE_DISPLAY_NAME = "Hailuo2.3 Image To Video"
82
- RETURN_TYPES = ("VIDEO",)
83
- RETURN_NAMES = ("video",)
82
+ RETURN_TYPES = ("VIDEO", """{"MiniMax-Hailuo-2.3-i2v": "MiniMax-Hailuo-2.3-i2v"}""")
83
+ RETURN_NAMES = ("video", "bizyair_model_name")
84
84
  CATEGORY = "☁️BizyAir/External APIs/Hailuo"
85
85
 
86
86
  def handle_inputs(self, headers, prompt_id, **kwargs):
@@ -112,4 +112,4 @@ class Hailuo2_3_I2V(BizyAirTrdApiBaseNode):
112
112
  return data, "MiniMax-Hailuo-2.3-i2v"
113
113
 
114
114
  def handle_outputs(self, outputs):
115
- return (outputs[0][0],)
115
+ return (outputs[0][0], "")