vectorvein 0.2.45__py3-none-any.whl → 0.2.47__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.
@@ -180,21 +180,21 @@ QWEN_MODELS: Final[Dict[str, Dict[str, Any]]] = {
180
180
  "id": "qwen2.5-7b-instruct",
181
181
  "context_length": 131072,
182
182
  "max_output_tokens": 8192,
183
- "function_call_available": False,
183
+ "function_call_available": True,
184
184
  "response_format_available": True,
185
185
  },
186
186
  "qwen2.5-14b-instruct": {
187
187
  "id": "qwen2.5-14b-instruct",
188
188
  "context_length": 131072,
189
189
  "max_output_tokens": 8192,
190
- "function_call_available": False,
190
+ "function_call_available": True,
191
191
  "response_format_available": True,
192
192
  },
193
193
  "qwen2.5-32b-instruct": {
194
194
  "id": "qwen2.5-32b-instruct",
195
195
  "context_length": 131072,
196
196
  "max_output_tokens": 8192,
197
- "function_call_available": False,
197
+ "function_call_available": True,
198
198
  "response_format_available": True,
199
199
  },
200
200
  "qwen2.5-coder-32b-instruct": {
@@ -215,7 +215,7 @@ QWEN_MODELS: Final[Dict[str, Dict[str, Any]]] = {
215
215
  "id": "qwen2.5-72b-instruct",
216
216
  "context_length": 131072,
217
217
  "max_output_tokens": 8192,
218
- "function_call_available": False,
218
+ "function_call_available": True,
219
219
  "response_format_available": True,
220
220
  },
221
221
  "qwen2-vl-72b-instruct": {
@@ -254,28 +254,28 @@ QWEN_MODELS: Final[Dict[str, Dict[str, Any]]] = {
254
254
  "id": "qwen-max",
255
255
  "context_length": 8096,
256
256
  "max_output_tokens": 2048,
257
- "function_call_available": False,
257
+ "function_call_available": True,
258
258
  "response_format_available": True,
259
259
  },
260
260
  "qwen-max-longcontext": {
261
261
  "id": "qwen-max-longcontext",
262
262
  "context_length": 30000,
263
263
  "max_output_tokens": 2048,
264
- "function_call_available": False,
264
+ "function_call_available": True,
265
265
  "response_format_available": True,
266
266
  },
267
267
  "qwen-plus": {
268
268
  "id": "qwen-plus",
269
269
  "context_length": 131072,
270
270
  "max_output_tokens": 8096,
271
- "function_call_available": False,
271
+ "function_call_available": True,
272
272
  "response_format_available": True,
273
273
  },
274
274
  "qwen-turbo": {
275
275
  "id": "qwen-turbo",
276
276
  "context_length": 8096,
277
277
  "max_output_tokens": 1500,
278
- "function_call_available": False,
278
+ "function_call_available": True,
279
279
  "response_format_available": True,
280
280
  },
281
281
  }
@@ -3,13 +3,23 @@ from typing import List, Union, TypedDict
3
3
 
4
4
  from .node import Node
5
5
  from .edge import Edge
6
+ from .port import InputPort
6
7
 
7
8
 
8
- class WorkflowCheckResult(TypedDict):
9
+ class UIWarning(TypedDict, total=False):
10
+ """UI警告类型。"""
11
+
12
+ input_ports_shown_but_connected: list[dict] # 显示的输入端口但被连接
13
+ has_shown_input_ports: bool # 是否存在显示的输入端口
14
+ has_output_nodes: bool # 是否存在输出节点
15
+
16
+
17
+ class WorkflowCheckResult(TypedDict, total=False):
9
18
  """工作流检查结果类型。"""
10
19
 
11
20
  no_cycle: bool # 工作流是否不包含环
12
21
  no_isolated_nodes: bool # 工作流是否不包含孤立节点
22
+ ui_warnings: UIWarning # UI相关警告
13
23
 
14
24
 
15
25
  class Workflow:
@@ -215,10 +225,61 @@ class Workflow:
215
225
 
216
226
  return result
217
227
 
228
+ def _check_ui(self) -> UIWarning:
229
+ """
230
+ 检查工作流的 UI 情况。
231
+ 以下情况会警告:
232
+ 1. 某个输入端口的 show=True,但是又有连线连接到该端口(实际运行时会被覆盖)。
233
+ 2. 整个工作流没有任何输入端口是 show=True 的,说明没有让用户输入的地方。
234
+ 3. 整个工作流没有任何输出节点,这样工作流结果无法呈现。
235
+ """
236
+ warnings: UIWarning = {
237
+ "input_ports_shown_but_connected": [],
238
+ "has_shown_input_ports": False,
239
+ "has_output_nodes": False,
240
+ }
241
+
242
+ # 检查是否有任何显示的输入端口
243
+ has_shown_input_ports = False
244
+
245
+ # 找出所有连接的目标端口
246
+ connected_ports = {(edge.target, edge.target_handle) for edge in self.edges}
247
+
248
+ # 遍历所有节点
249
+ for node in self.nodes:
250
+ # 检查是否为输出节点
251
+ if hasattr(node, "category") and node.category == "outputs":
252
+ warnings["has_output_nodes"] = True
253
+
254
+ # 检查节点的输入端口
255
+ for port_name in node.ports.keys() if hasattr(node, "ports") else []:
256
+ port = node.ports.get(port_name)
257
+ # 确保是输入端口且设置为显示
258
+ if hasattr(port, "show") and getattr(port, "show", False) and isinstance(port, InputPort):
259
+ has_shown_input_ports = True
260
+
261
+ # 检查显示的端口是否也被连接
262
+ if (node.id, port_name) in connected_ports:
263
+ warnings["input_ports_shown_but_connected"].append(
264
+ {"node_id": node.id, "node_type": node.type, "port_name": port_name}
265
+ )
266
+
267
+ # 如果没有任何显示的输入端口
268
+ warnings["has_shown_input_ports"] = has_shown_input_ports
269
+
270
+ return warnings
271
+
218
272
  def check(self) -> WorkflowCheckResult:
219
273
  """检查流程图的有效性。
220
274
 
221
275
  Returns:
222
276
  WorkflowCheckResult: 包含各种检查结果的字典
223
277
  """
224
- return self._check_dag()
278
+ dag_check = self._check_dag()
279
+ ui_check = self._check_ui()
280
+
281
+ # 合并结果
282
+ result: WorkflowCheckResult = dag_check
283
+ result["ui_warnings"] = ui_check
284
+
285
+ return result
@@ -17,6 +17,7 @@ class FileLoader(Node):
17
17
  port_type=PortType.FILE,
18
18
  value=list(),
19
19
  multiple=True,
20
+ show=True,
20
21
  ),
21
22
  "parse_quality": InputPort(
22
23
  name="parse_quality",
@@ -75,6 +76,7 @@ class FileUpload(Node):
75
76
  value=list(),
76
77
  support_file_types=["*/*"],
77
78
  multiple=True,
79
+ show=True,
78
80
  ),
79
81
  "unzip_files": InputPort(
80
82
  name="unzip_files",
@@ -18,6 +18,7 @@ class BackgroundGeneration(Node):
18
18
  value=list(),
19
19
  support_file_types=[".jpg", ".jpeg", ".png", ".webp"],
20
20
  multiple=True,
21
+ show=True,
21
22
  ),
22
23
  "remove_background": InputPort(
23
24
  name="remove_background",
@@ -266,6 +267,7 @@ class Inpainting(Node):
266
267
  value=list(),
267
268
  support_file_types=[".jpg", ".jpeg", ".png", ".webp"],
268
269
  multiple=True,
270
+ show=True,
269
271
  ),
270
272
  "inpainting_method": InputPort(
271
273
  name="inpainting_method",
@@ -402,12 +404,14 @@ class Pulid(Node):
402
404
  value=list(),
403
405
  support_file_types=[".jpg", ".jpeg", ".png", ".webp"],
404
406
  multiple=True,
407
+ show=True,
405
408
  ),
406
409
  "prompt": InputPort(
407
410
  name="prompt",
408
411
  port_type=PortType.TEXTAREA,
409
412
  value="",
410
413
  multiple=True,
414
+ show=True,
411
415
  ),
412
416
  "negative_prompt": InputPort(
413
417
  name="negative_prompt",
@@ -18,6 +18,7 @@ class AudioEditing(Node):
18
18
  value=list(),
19
19
  support_file_types=[".mp3", ".wav", ".ogg", ".m4a"],
20
20
  multiple=True,
21
+ show=True,
21
22
  ),
22
23
  "audio_processing_logic": InputPort(
23
24
  name="audio_processing_logic",
@@ -166,6 +167,7 @@ class ImageBackgroundRemoval(Node):
166
167
  value=list(),
167
168
  support_file_types=[".jpg", ".jpeg", ".png", ".webp"],
168
169
  multiple=True,
170
+ show=True,
169
171
  ),
170
172
  "remove_background_method": InputPort(
171
173
  name="remove_background_method",
@@ -223,6 +225,7 @@ class ImageEditing(Node):
223
225
  value=list(),
224
226
  support_file_types=[".jpg", ".jpeg", ".png", ".webp"],
225
227
  multiple=True,
228
+ show=True,
226
229
  ),
227
230
  "crop": InputPort(
228
231
  name="crop",
@@ -365,6 +368,7 @@ class ImageSegmentation(Node):
365
368
  value=list(),
366
369
  support_file_types=[".jpg", ".jpeg", ".png", ".webp"],
367
370
  multiple=True,
371
+ show=True,
368
372
  ),
369
373
  "selection_method": InputPort(
370
374
  name="selection_method",
@@ -426,6 +430,7 @@ class ImageWatermark(Node):
426
430
  value=list(),
427
431
  support_file_types=[".jpg", ".jpeg", ".png", ".webp"],
428
432
  multiple=True,
433
+ show=True,
429
434
  ),
430
435
  "image_or_text": InputPort(
431
436
  name="image_or_text",
@@ -559,6 +564,7 @@ class VideoEditing(Node):
559
564
  value=list(),
560
565
  support_file_types=["video/*"],
561
566
  multiple=True,
567
+ show=True,
562
568
  ),
563
569
  "video_processing_logic": InputPort(
564
570
  name="video_processing_logic",
@@ -637,6 +643,7 @@ class VideoScreenshot(Node):
637
643
  value=list(),
638
644
  support_file_types=["video/*"],
639
645
  multiple=True,
646
+ show=True,
640
647
  ),
641
648
  "screenshot_method": InputPort(
642
649
  name="screenshot_method",
@@ -51,6 +51,7 @@ class ClaudeVision(Node):
51
51
  multiple=True,
52
52
  support_file_types=[".jpg", ".jpeg", ".png", ".webp"],
53
53
  condition="fields_data.get('images_or_urls') == 'images'",
54
+ show=True,
54
55
  ),
55
56
  "urls": InputPort(
56
57
  name="urls",
@@ -100,6 +101,7 @@ class DeepseekVl(Node):
100
101
  multiple=True,
101
102
  support_file_types=[".jpg", ".jpeg", ".png", ".webp"],
102
103
  condition="fields_data.get('images_or_urls') == 'images'",
104
+ show=True,
103
105
  ),
104
106
  "urls": InputPort(
105
107
  name="urls",
@@ -159,6 +161,7 @@ class GeminiVision(Node):
159
161
  multiple=True,
160
162
  support_file_types=[".jpg", ".jpeg", ".png", ".webp"],
161
163
  condition="fields_data.get('images_or_urls') == 'images'",
164
+ show=True,
162
165
  ),
163
166
  "urls": InputPort(
164
167
  name="urls",
@@ -210,6 +213,7 @@ class GlmVision(Node):
210
213
  multiple=True,
211
214
  support_file_types=[".jpg", ".jpeg", ".png", ".webp"],
212
215
  condition="fields_data.images_or_urls.value == 'images'",
216
+ show=True,
213
217
  ),
214
218
  "urls": InputPort(
215
219
  name="urls",
@@ -260,6 +264,7 @@ class GptVision(Node):
260
264
  multiple=True,
261
265
  support_file_types=[".jpg", ".jpeg", ".png", ".webp"],
262
266
  condition="fields_data.get('images_or_urls') == 'images'",
267
+ show=True,
263
268
  ),
264
269
  "urls": InputPort(
265
270
  name="urls",
@@ -320,6 +325,7 @@ class InternVision(Node):
320
325
  multiple=True,
321
326
  support_file_types=[".jpg", ".jpeg", ".png", ".webp"],
322
327
  condition="fields_data.get('images_or_urls') == 'images'",
328
+ show=True,
323
329
  ),
324
330
  "urls": InputPort(
325
331
  name="urls",
@@ -366,6 +372,7 @@ class Ocr(Node):
366
372
  multiple=True,
367
373
  support_file_types=[".jpg", ".jpeg", ".png", ".webp"],
368
374
  condition="fields_data.get('images_or_urls') == 'images'",
375
+ show=True,
369
376
  ),
370
377
  "urls": InputPort(
371
378
  name="urls",
@@ -439,6 +446,7 @@ class QwenVision(Node):
439
446
  multiple=True,
440
447
  support_file_types=[".jpg", ".jpeg", ".png", ".webp"],
441
448
  condition="fields_data.get('images_or_urls') == 'images'",
449
+ show=True,
442
450
  ),
443
451
  "urls": InputPort(
444
452
  name="urls",
@@ -475,6 +483,7 @@ class SpeechRecognition(Node):
475
483
  multiple=True,
476
484
  support_file_types=[".wav", ".mp3", ".mp4", ".m4a", ".wma", ".aac", ".ogg", ".amr", ".flac"],
477
485
  condition="fields_data.get('files_or_urls') == 'files'",
486
+ show=True,
478
487
  ),
479
488
  "urls": InputPort(
480
489
  name="urls",
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: vectorvein
3
- Version: 0.2.45
3
+ Version: 0.2.47
4
4
  Summary: VectorVein Python SDK
5
5
  Author-Email: Anderson <andersonby@163.com>
6
6
  License: MIT
@@ -1,6 +1,6 @@
1
- vectorvein-0.2.45.dist-info/METADATA,sha256=MOa2CywVU8Bj0cGja2WL5V1wdAMUf0YKhkxVG2uXxO8,4570
2
- vectorvein-0.2.45.dist-info/WHEEL,sha256=thaaA2w1JzcGC48WYufAs8nrYZjJm8LqNfnXFOFyCC4,90
3
- vectorvein-0.2.45.dist-info/entry_points.txt,sha256=6OYgBcLyFCUgeqLgnvMyOJxPCWzgy7se4rLPKtNonMs,34
1
+ vectorvein-0.2.47.dist-info/METADATA,sha256=sb9ZNRg7tklqTMEbC2uTLERQk72bycaYDYZCw6c0cpY,4570
2
+ vectorvein-0.2.47.dist-info/WHEEL,sha256=thaaA2w1JzcGC48WYufAs8nrYZjJm8LqNfnXFOFyCC4,90
3
+ vectorvein-0.2.47.dist-info/entry_points.txt,sha256=6OYgBcLyFCUgeqLgnvMyOJxPCWzgy7se4rLPKtNonMs,34
4
4
  vectorvein/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
5
  vectorvein/api/__init__.py,sha256=lfY-XA46fgD2iIZTU0VYP8i07AwA03Egj4Qua0vUKrQ,738
6
6
  vectorvein/api/client.py,sha256=xF-leKDQzVyyy9FnIRaz0k4eElYW1XbbzeRLcpnyk90,33047
@@ -32,7 +32,7 @@ vectorvein/server/token_server.py,sha256=36F9PKSNOX8ZtYBXY_l-76GQTpUSmQ2Y8EMy1H7
32
32
  vectorvein/settings/__init__.py,sha256=3Kw3hbvqcIQepAR6Q2m2UXbBnwyJTUm8yAz-aHmbUTg,11163
33
33
  vectorvein/settings/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
34
34
  vectorvein/types/__init__.py,sha256=ypg8c8AwF49FrFBMqmgH_eIBH4LFf0KN4kjqQa7zrvM,3376
35
- vectorvein/types/defaults.py,sha256=Tx3bJKcZN0GKeMGJK4gokliOj_MWRPGKnec8csPXO0M,27569
35
+ vectorvein/types/defaults.py,sha256=z97XbwcmwN75CQrY33GtQ02wmRZmkue1WyosnwyrDYY,27561
36
36
  vectorvein/types/enums.py,sha256=LplSVkXLBK-t8TWtJKj_f7ktWTd6CSHWRLb67XKMm54,1716
37
37
  vectorvein/types/exception.py,sha256=KtnqZ-1DstHm95SZAyZdHhkGq1bJ4A9Aw3Zfdu-VIFo,130
38
38
  vectorvein/types/llm_parameters.py,sha256=2rF-CQsWcHqTzI2r5x55gSsFm7LW_iCxQxZTEnk0yF8,7843
@@ -44,15 +44,15 @@ vectorvein/utilities/retry.py,sha256=6KFS9R2HdhqM3_9jkjD4F36ZSpEx2YNFGOVlpOsUetM
44
44
  vectorvein/workflow/graph/edge.py,sha256=1ckyyjCue_PLm7P1ItUfKOy6AKkemOpZ9m1WJ8UXIHQ,1072
45
45
  vectorvein/workflow/graph/node.py,sha256=U3LAq01wOaDANVUuYWc2BhIq-Pl2-33FirJZkkNL_wA,5329
46
46
  vectorvein/workflow/graph/port.py,sha256=_QpHCBGAu657VhYAh0Wzjri3ZZ8-WYJp99J465mqmwo,6492
47
- vectorvein/workflow/graph/workflow.py,sha256=K-1-FMfHO49Ww3sHKDOr_sD8GH-i36ylS7qtyJ-Vivg,8617
47
+ vectorvein/workflow/graph/workflow.py,sha256=jDa8dedgtW39Gx0PrqgYrs7XQ_NfQbhgGge88xElksI,11159
48
48
  vectorvein/workflow/nodes/__init__.py,sha256=dWrWtL3q0Vsn-MLgJ7gNgLCrwZ5BrqjrN2QFPNeBMuc,3240
49
49
  vectorvein/workflow/nodes/audio_generation.py,sha256=ZRFZ_ycMTSJ2LKmekctagQdJYTl-3q4TNOIKETpS9AM,5870
50
50
  vectorvein/workflow/nodes/control_flows.py,sha256=l8CjFQlsGV3fNGM6SVzS1Kz361K1xDv1fGT7acuDXuU,6613
51
- vectorvein/workflow/nodes/file_processing.py,sha256=Rsjc8al0z-2KuweO0nIybWvceqxbqOPQyTs0-pgy5m4,3980
52
- vectorvein/workflow/nodes/image_generation.py,sha256=WNUj0gbcq-qJ0bJLgFLYN8iDKId7YuzamTQxPjd3oyg,33571
51
+ vectorvein/workflow/nodes/file_processing.py,sha256=h9FZM88ZAaLZq6obGCTs6mRXF6uYkwqca5JEiFxmd_k,4044
52
+ vectorvein/workflow/nodes/image_generation.py,sha256=MJ628Luc5CwDWTu3uYM_nkIe6JgSV6Gqv0IiOrrsKm8,33699
53
53
  vectorvein/workflow/nodes/llms.py,sha256=_q65zdfugjNh1N83dytHG69TfkmpOPw2lwxKQUQnmrs,38589
54
- vectorvein/workflow/nodes/media_editing.py,sha256=qJImXwBJt59Ud0tzsRVKItPvrVZws3BEYirOgan65Io,29621
55
- vectorvein/workflow/nodes/media_processing.py,sha256=jkSP287gyhvF7hqY8Nohdc1Rdn-br3zAj9sklPs6PAs,19778
54
+ vectorvein/workflow/nodes/media_editing.py,sha256=hqOQCqxCPYdpnswlj4XM9fLRFJ0BTWUxW_oKH650hGs,29845
55
+ vectorvein/workflow/nodes/media_processing.py,sha256=0NuJCkcRY68yO9ZJ7xmXA8RXXxPvptu_89nR83pxTEk,20066
56
56
  vectorvein/workflow/nodes/output.py,sha256=_UQxiddHtGv2rkjhUFE-KDgrjnh0AGJQJyq9-4Aji5A,12567
57
57
  vectorvein/workflow/nodes/relational_db.py,sha256=zfzUhV25TpZGhkIzO18PmAT5xhcsJC4AXKy0zyA05w8,5408
58
58
  vectorvein/workflow/nodes/text_processing.py,sha256=MRo_-oaC65hbzMxm7TYoeiS3rgvqh9y_Rny5RCfoATE,8342
@@ -62,4 +62,4 @@ vectorvein/workflow/nodes/vector_db.py,sha256=t6I17q6iR3yQreiDHpRrksMdWDPIvgqJs0
62
62
  vectorvein/workflow/nodes/video_generation.py,sha256=qmdg-t_idpxq1veukd-jv_ChICMOoInKxprV9Z4Vi2w,4118
63
63
  vectorvein/workflow/nodes/web_crawlers.py,sha256=BhJBX1AZH7-22Gu95Ox4qJqmH5DU-m4dbUb5N5DTA-M,5559
64
64
  vectorvein/workflow/utils/json_to_code.py,sha256=F7dhDy8kGc8ndOeihGLRLGFGlquoxVlb02ENtxnQ0C8,5914
65
- vectorvein-0.2.45.dist-info/RECORD,,
65
+ vectorvein-0.2.47.dist-info/RECORD,,