vectorvein 0.2.48__py3-none-any.whl → 0.2.50__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.
@@ -698,7 +698,7 @@ GEMINI_MODELS: Final[Dict[str, Dict[str, Any]]] = {
698
698
  "id": "gemini-2.0-flash-thinking-exp-01-21",
699
699
  "context_length": 1048576,
700
700
  "max_output_tokens": 8192,
701
- "function_call_available": True,
701
+ "function_call_available": False,
702
702
  "response_format_available": True,
703
703
  "native_multimodal": False,
704
704
  },
@@ -1,9 +1,10 @@
1
1
  import json
2
- from typing import List, Union, TypedDict
2
+ from typing import List, Union, TypedDict, Dict, Any, Optional
3
3
 
4
4
  from .node import Node
5
5
  from .edge import Edge
6
6
  from .port import InputPort
7
+ from ..utils.layout import layout
7
8
 
8
9
 
9
10
  class UIWarning(TypedDict, total=False):
@@ -283,3 +284,22 @@ class Workflow:
283
284
  result["ui_warnings"] = ui_check
284
285
 
285
286
  return result
287
+
288
+ def layout(self, options: Optional[Dict[str, Any]] = None) -> "Workflow":
289
+ """对工作流中的节点进行自动布局,计算并更新每个节点的位置。
290
+
291
+ 此方法实现了一个简单的分层布局算法,将节点按照有向图的拓扑结构进行排列。
292
+
293
+ Args:
294
+ options: 布局选项,包括:
295
+ - direction: 布局方向 ('TB', 'BT', 'LR', 'RL'),默认 'LR'
296
+ - node_spacing: 同一层级节点间的间距,默认 500
297
+ - layer_spacing: 不同层级间的间距,默认 400
298
+ - margin_x: 图形左右边距,默认 20
299
+ - margin_y: 图形上下边距,默认 20
300
+
301
+ Returns:
302
+ 布局后的工作流对象
303
+ """
304
+ layout(self.nodes, self.edges, options)
305
+ return self
@@ -0,0 +1,114 @@
1
+ from typing import Optional, Dict, Any, List, TYPE_CHECKING
2
+
3
+
4
+ if TYPE_CHECKING:
5
+ from vectorvein.workflow.graph.node import Node
6
+ from vectorvein.workflow.graph.edge import Edge
7
+
8
+
9
+ def layout(nodes: List["Node"], edges: List["Edge"], options: Optional[Dict[str, Any]] = None):
10
+ """对工作流中的节点进行自动布局,计算并更新每个节点的位置。
11
+
12
+ 此方法实现了一个简单的分层布局算法,将节点按照有向图的拓扑结构进行排列。
13
+
14
+ Args:
15
+ options: 布局选项,包括:
16
+ - direction: 布局方向 ('TB', 'BT', 'LR', 'RL'),默认 'TB'
17
+ - node_spacing: 同一层级节点间的间距,默认 150
18
+ - layer_spacing: 不同层级间的间距,默认 100
19
+ - margin_x: 图形左右边距,默认 20
20
+ - margin_y: 图形上下边距,默认 20
21
+
22
+ Returns:
23
+ 布局后的工作流对象
24
+ """
25
+ # 设置默认选项
26
+ default_options = {
27
+ "direction": "LR", # 从上到下的布局
28
+ "node_spacing": 400, # 同一层级节点间的间距
29
+ "layer_spacing": 500, # 不同层级间的间距
30
+ "margin_x": 20, # 图形左右边距
31
+ "margin_y": 20, # 图形上下边距
32
+ }
33
+
34
+ # 合并用户提供的选项
35
+ if options:
36
+ default_options.update(options)
37
+
38
+ # 构建邻接表
39
+ adjacency = {node.id: [] for node in nodes}
40
+ in_degree = {node.id: 0 for node in nodes}
41
+
42
+ for edge in edges:
43
+ if edge.source in adjacency:
44
+ adjacency[edge.source].append(edge.target)
45
+ in_degree[edge.target] = in_degree.get(edge.target, 0) + 1
46
+
47
+ # 找出所有入度为0的节点(根节点)
48
+ roots = [node_id for node_id, degree in in_degree.items() if degree == 0]
49
+
50
+ # 如果没有根节点,选择第一个节点作为起点
51
+ if not roots and nodes:
52
+ roots = [nodes[0].id]
53
+
54
+ # 按层级排列节点
55
+ layers = []
56
+ visited = set()
57
+
58
+ current_layer = roots
59
+ while current_layer:
60
+ layers.append(current_layer)
61
+ next_layer = []
62
+ for node_id in current_layer:
63
+ visited.add(node_id)
64
+ for neighbor in adjacency.get(node_id, []):
65
+ if neighbor not in visited and all(
66
+ parent in visited for parent in [e.source for e in edges if e.target == neighbor]
67
+ ):
68
+ next_layer.append(neighbor)
69
+ current_layer = next_layer
70
+
71
+ # 还有未访问的节点(可能是孤立节点或环的一部分)
72
+ remaining = [node.id for node in nodes if node.id not in visited]
73
+ if remaining:
74
+ layers.append(remaining)
75
+
76
+ # 根据层级信息设置节点位置
77
+ layer_spacing = default_options["layer_spacing"]
78
+ node_spacing = default_options["node_spacing"]
79
+ margin_x = default_options["margin_x"]
80
+ margin_y = default_options["margin_y"]
81
+
82
+ # 布局方向
83
+ is_vertical = default_options["direction"] in ["TB", "BT"]
84
+ is_reversed = default_options["direction"] in ["BT", "RL"]
85
+
86
+ for layer_idx, layer in enumerate(layers):
87
+ for node_idx, node_id in enumerate(layer):
88
+ # 根据布局方向计算位置
89
+ if is_vertical:
90
+ # 垂直布局 (TB 或 BT)
91
+ x = node_idx * node_spacing + margin_x
92
+ y = layer_idx * layer_spacing + margin_y
93
+ if is_reversed: # BT 布局需要反转 y 坐标
94
+ y = (len(layers) - 1 - layer_idx) * layer_spacing + margin_y
95
+ else:
96
+ # 水平布局 (LR 或 RL)
97
+ x = layer_idx * layer_spacing + margin_x
98
+ y = node_idx * node_spacing + margin_y
99
+ if is_reversed: # RL 布局需要反转 x 坐标
100
+ x = (len(layers) - 1 - layer_idx) * layer_spacing + margin_x
101
+
102
+ # 找到节点对象并设置位置
103
+ for node in nodes:
104
+ if node.id == node_id:
105
+ # 确保节点有 position 属性
106
+ if not hasattr(node, "position"):
107
+ node.position = {"x": x, "y": y}
108
+ else:
109
+ # 如果已经有 position 属性,更新它
110
+ if isinstance(node.position, dict):
111
+ node.position.update({"x": x, "y": y})
112
+ else:
113
+ node.position = {"x": x, "y": y}
114
+ break
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: vectorvein
3
- Version: 0.2.48
3
+ Version: 0.2.50
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.48.dist-info/METADATA,sha256=5zz-Cv6NkNsXQ8TqbojdH8VB4-HgbAgGtZX3IXJX3CE,4570
2
- vectorvein-0.2.48.dist-info/WHEEL,sha256=thaaA2w1JzcGC48WYufAs8nrYZjJm8LqNfnXFOFyCC4,90
3
- vectorvein-0.2.48.dist-info/entry_points.txt,sha256=6OYgBcLyFCUgeqLgnvMyOJxPCWzgy7se4rLPKtNonMs,34
1
+ vectorvein-0.2.50.dist-info/METADATA,sha256=ltuWwgnho44gDn6eGM8ED7_dtnefHd1KZ89yMM4bqrY,4570
2
+ vectorvein-0.2.50.dist-info/WHEEL,sha256=thaaA2w1JzcGC48WYufAs8nrYZjJm8LqNfnXFOFyCC4,90
3
+ vectorvein-0.2.50.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=RA4bERvJQ9hy3UFmrF2K3qA7Pp1CKkgudH3PsX14lGs,27562
35
+ vectorvein/types/defaults.py,sha256=MpDvT9vNwIqwHFKXTlBq3FY02PLr4BncCdvNhfbxM60,27563
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,7 +44,7 @@ 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=jDa8dedgtW39Gx0PrqgYrs7XQ_NfQbhgGge88xElksI,11159
47
+ vectorvein/workflow/graph/workflow.py,sha256=rXLIKQiOFjyP3YwYf0deHUcRNBCHJcTGj2omM4a9SpE,12070
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
@@ -62,4 +62,5 @@ 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.48.dist-info/RECORD,,
65
+ vectorvein/workflow/utils/layout.py,sha256=j0bRD3uaXu40xCS6U6BGahBI8FrHa5MiF55GbTrZ1LM,4565
66
+ vectorvein-0.2.50.dist-info/RECORD,,