vectorvein 0.2.69__tar.gz → 0.2.72__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.
- {vectorvein-0.2.69 → vectorvein-0.2.72}/PKG-INFO +1 -1
- {vectorvein-0.2.69 → vectorvein-0.2.72}/pyproject.toml +1 -1
- vectorvein-0.2.72/src/vectorvein/workflow/utils/analyse.py +422 -0
- {vectorvein-0.2.69 → vectorvein-0.2.72}/src/vectorvein/workflow/utils/json_to_code.py +8 -2
- {vectorvein-0.2.69 → vectorvein-0.2.72}/README.md +0 -0
- {vectorvein-0.2.69 → vectorvein-0.2.72}/src/vectorvein/__init__.py +0 -0
- {vectorvein-0.2.69 → vectorvein-0.2.72}/src/vectorvein/api/__init__.py +0 -0
- {vectorvein-0.2.69 → vectorvein-0.2.72}/src/vectorvein/api/client.py +0 -0
- {vectorvein-0.2.69 → vectorvein-0.2.72}/src/vectorvein/api/exceptions.py +0 -0
- {vectorvein-0.2.69 → vectorvein-0.2.72}/src/vectorvein/api/models.py +0 -0
- {vectorvein-0.2.69 → vectorvein-0.2.72}/src/vectorvein/chat_clients/__init__.py +0 -0
- {vectorvein-0.2.69 → vectorvein-0.2.72}/src/vectorvein/chat_clients/anthropic_client.py +0 -0
- {vectorvein-0.2.69 → vectorvein-0.2.72}/src/vectorvein/chat_clients/baichuan_client.py +0 -0
- {vectorvein-0.2.69 → vectorvein-0.2.72}/src/vectorvein/chat_clients/base_client.py +0 -0
- {vectorvein-0.2.69 → vectorvein-0.2.72}/src/vectorvein/chat_clients/deepseek_client.py +0 -0
- {vectorvein-0.2.69 → vectorvein-0.2.72}/src/vectorvein/chat_clients/ernie_client.py +0 -0
- {vectorvein-0.2.69 → vectorvein-0.2.72}/src/vectorvein/chat_clients/gemini_client.py +0 -0
- {vectorvein-0.2.69 → vectorvein-0.2.72}/src/vectorvein/chat_clients/groq_client.py +0 -0
- {vectorvein-0.2.69 → vectorvein-0.2.72}/src/vectorvein/chat_clients/local_client.py +0 -0
- {vectorvein-0.2.69 → vectorvein-0.2.72}/src/vectorvein/chat_clients/minimax_client.py +0 -0
- {vectorvein-0.2.69 → vectorvein-0.2.72}/src/vectorvein/chat_clients/mistral_client.py +0 -0
- {vectorvein-0.2.69 → vectorvein-0.2.72}/src/vectorvein/chat_clients/moonshot_client.py +0 -0
- {vectorvein-0.2.69 → vectorvein-0.2.72}/src/vectorvein/chat_clients/openai_client.py +0 -0
- {vectorvein-0.2.69 → vectorvein-0.2.72}/src/vectorvein/chat_clients/openai_compatible_client.py +0 -0
- {vectorvein-0.2.69 → vectorvein-0.2.72}/src/vectorvein/chat_clients/py.typed +0 -0
- {vectorvein-0.2.69 → vectorvein-0.2.72}/src/vectorvein/chat_clients/qwen_client.py +0 -0
- {vectorvein-0.2.69 → vectorvein-0.2.72}/src/vectorvein/chat_clients/stepfun_client.py +0 -0
- {vectorvein-0.2.69 → vectorvein-0.2.72}/src/vectorvein/chat_clients/utils.py +0 -0
- {vectorvein-0.2.69 → vectorvein-0.2.72}/src/vectorvein/chat_clients/xai_client.py +0 -0
- {vectorvein-0.2.69 → vectorvein-0.2.72}/src/vectorvein/chat_clients/yi_client.py +0 -0
- {vectorvein-0.2.69 → vectorvein-0.2.72}/src/vectorvein/chat_clients/zhipuai_client.py +0 -0
- {vectorvein-0.2.69 → vectorvein-0.2.72}/src/vectorvein/py.typed +0 -0
- {vectorvein-0.2.69 → vectorvein-0.2.72}/src/vectorvein/server/token_server.py +0 -0
- {vectorvein-0.2.69 → vectorvein-0.2.72}/src/vectorvein/settings/__init__.py +0 -0
- {vectorvein-0.2.69 → vectorvein-0.2.72}/src/vectorvein/settings/py.typed +0 -0
- {vectorvein-0.2.69 → vectorvein-0.2.72}/src/vectorvein/types/__init__.py +0 -0
- {vectorvein-0.2.69 → vectorvein-0.2.72}/src/vectorvein/types/defaults.py +0 -0
- {vectorvein-0.2.69 → vectorvein-0.2.72}/src/vectorvein/types/enums.py +0 -0
- {vectorvein-0.2.69 → vectorvein-0.2.72}/src/vectorvein/types/exception.py +0 -0
- {vectorvein-0.2.69 → vectorvein-0.2.72}/src/vectorvein/types/llm_parameters.py +0 -0
- {vectorvein-0.2.69 → vectorvein-0.2.72}/src/vectorvein/types/py.typed +0 -0
- {vectorvein-0.2.69 → vectorvein-0.2.72}/src/vectorvein/types/settings.py +0 -0
- {vectorvein-0.2.69 → vectorvein-0.2.72}/src/vectorvein/utilities/media_processing.py +0 -0
- {vectorvein-0.2.69 → vectorvein-0.2.72}/src/vectorvein/utilities/rate_limiter.py +0 -0
- {vectorvein-0.2.69 → vectorvein-0.2.72}/src/vectorvein/utilities/retry.py +0 -0
- {vectorvein-0.2.69 → vectorvein-0.2.72}/src/vectorvein/workflow/graph/edge.py +0 -0
- {vectorvein-0.2.69 → vectorvein-0.2.72}/src/vectorvein/workflow/graph/node.py +0 -0
- {vectorvein-0.2.69 → vectorvein-0.2.72}/src/vectorvein/workflow/graph/port.py +0 -0
- {vectorvein-0.2.69 → vectorvein-0.2.72}/src/vectorvein/workflow/graph/workflow.py +0 -0
- {vectorvein-0.2.69 → vectorvein-0.2.72}/src/vectorvein/workflow/nodes/__init__.py +0 -0
- {vectorvein-0.2.69 → vectorvein-0.2.72}/src/vectorvein/workflow/nodes/audio_generation.py +0 -0
- {vectorvein-0.2.69 → vectorvein-0.2.72}/src/vectorvein/workflow/nodes/control_flows.py +0 -0
- {vectorvein-0.2.69 → vectorvein-0.2.72}/src/vectorvein/workflow/nodes/file_processing.py +0 -0
- {vectorvein-0.2.69 → vectorvein-0.2.72}/src/vectorvein/workflow/nodes/image_generation.py +0 -0
- {vectorvein-0.2.69 → vectorvein-0.2.72}/src/vectorvein/workflow/nodes/llms.py +0 -0
- {vectorvein-0.2.69 → vectorvein-0.2.72}/src/vectorvein/workflow/nodes/media_editing.py +0 -0
- {vectorvein-0.2.69 → vectorvein-0.2.72}/src/vectorvein/workflow/nodes/media_processing.py +0 -0
- {vectorvein-0.2.69 → vectorvein-0.2.72}/src/vectorvein/workflow/nodes/output.py +0 -0
- {vectorvein-0.2.69 → vectorvein-0.2.72}/src/vectorvein/workflow/nodes/relational_db.py +0 -0
- {vectorvein-0.2.69 → vectorvein-0.2.72}/src/vectorvein/workflow/nodes/text_processing.py +0 -0
- {vectorvein-0.2.69 → vectorvein-0.2.72}/src/vectorvein/workflow/nodes/tools.py +0 -0
- {vectorvein-0.2.69 → vectorvein-0.2.72}/src/vectorvein/workflow/nodes/triggers.py +0 -0
- {vectorvein-0.2.69 → vectorvein-0.2.72}/src/vectorvein/workflow/nodes/vector_db.py +0 -0
- {vectorvein-0.2.69 → vectorvein-0.2.72}/src/vectorvein/workflow/nodes/video_generation.py +0 -0
- {vectorvein-0.2.69 → vectorvein-0.2.72}/src/vectorvein/workflow/nodes/web_crawlers.py +0 -0
- {vectorvein-0.2.69 → vectorvein-0.2.72}/src/vectorvein/workflow/utils/check.py +0 -0
- {vectorvein-0.2.69 → vectorvein-0.2.72}/src/vectorvein/workflow/utils/layout.py +0 -0
@@ -0,0 +1,422 @@
|
|
1
|
+
import json
|
2
|
+
from typing import TypedDict, Any, overload
|
3
|
+
|
4
|
+
|
5
|
+
class PortRecord(TypedDict):
|
6
|
+
"""
|
7
|
+
端口记录
|
8
|
+
"""
|
9
|
+
|
10
|
+
name: str
|
11
|
+
type: str
|
12
|
+
show: bool
|
13
|
+
value: Any
|
14
|
+
connected: bool
|
15
|
+
|
16
|
+
|
17
|
+
class NodeRecord(TypedDict):
|
18
|
+
"""
|
19
|
+
节点记录
|
20
|
+
"""
|
21
|
+
|
22
|
+
id: str
|
23
|
+
name: str
|
24
|
+
type: str
|
25
|
+
category: str
|
26
|
+
ports: list[PortRecord]
|
27
|
+
|
28
|
+
|
29
|
+
class AnalyseResult(TypedDict):
|
30
|
+
"""
|
31
|
+
分析结果
|
32
|
+
"""
|
33
|
+
|
34
|
+
nodes: list[NodeRecord]
|
35
|
+
|
36
|
+
|
37
|
+
def analyse_workflow_record(
|
38
|
+
json_str: str, connected_only: bool = False, reserver_programming_function_ports: bool = False
|
39
|
+
) -> AnalyseResult:
|
40
|
+
"""
|
41
|
+
分析工作流JSON字符串,提取节点和端口信息
|
42
|
+
|
43
|
+
Args:
|
44
|
+
json_str: 工作流JSON字符串
|
45
|
+
|
46
|
+
Returns:
|
47
|
+
分析结果
|
48
|
+
"""
|
49
|
+
# 解析JSON
|
50
|
+
workflow_data = json.loads(json_str)
|
51
|
+
|
52
|
+
# 收集所有连接的端口
|
53
|
+
connected_ports = set()
|
54
|
+
for edge in workflow_data["edges"]:
|
55
|
+
source_id = edge["source"]
|
56
|
+
target_id = edge["target"]
|
57
|
+
source_handle = edge["sourceHandle"]
|
58
|
+
target_handle = edge["targetHandle"]
|
59
|
+
connected_ports.add((source_id, source_handle))
|
60
|
+
connected_ports.add((target_id, target_handle))
|
61
|
+
|
62
|
+
# 分析节点
|
63
|
+
nodes_records = []
|
64
|
+
|
65
|
+
for node in workflow_data["nodes"]:
|
66
|
+
node_id = node["id"]
|
67
|
+
node_type = node["type"]
|
68
|
+
category = node["category"]
|
69
|
+
|
70
|
+
# 跳过辅助节点
|
71
|
+
if category == "assistedNodes":
|
72
|
+
continue
|
73
|
+
|
74
|
+
# 获取任务名称
|
75
|
+
task_name = node["data"]["task_name"].split(".")[-1] if "task_name" in node["data"] else ""
|
76
|
+
|
77
|
+
# 收集端口信息
|
78
|
+
ports_records = []
|
79
|
+
|
80
|
+
if "template" in node["data"]:
|
81
|
+
for port in node["data"]["template"].values():
|
82
|
+
if "name" not in port:
|
83
|
+
continue
|
84
|
+
|
85
|
+
port_is_connected = (node_id, port["name"]) in connected_ports
|
86
|
+
|
87
|
+
if node_type != "ProgrammingFunction" or not reserver_programming_function_ports:
|
88
|
+
if connected_only and not port_is_connected:
|
89
|
+
continue
|
90
|
+
|
91
|
+
port_record: PortRecord = {
|
92
|
+
"name": port["name"],
|
93
|
+
"type": port.get("field_type", port.get("type", "")),
|
94
|
+
"show": port.get("show", False),
|
95
|
+
"value": port.get("value", None),
|
96
|
+
"connected": port_is_connected,
|
97
|
+
}
|
98
|
+
|
99
|
+
ports_records.append(port_record)
|
100
|
+
|
101
|
+
# 创建节点记录
|
102
|
+
node_record: NodeRecord = {
|
103
|
+
"id": node_id,
|
104
|
+
"name": task_name,
|
105
|
+
"type": node_type,
|
106
|
+
"category": category,
|
107
|
+
"ports": ports_records,
|
108
|
+
}
|
109
|
+
|
110
|
+
nodes_records.append(node_record)
|
111
|
+
|
112
|
+
# 返回分析结果
|
113
|
+
result: AnalyseResult = {"nodes": nodes_records}
|
114
|
+
|
115
|
+
return result
|
116
|
+
|
117
|
+
|
118
|
+
@overload
|
119
|
+
def prettify_value(
|
120
|
+
value: str,
|
121
|
+
max_length: int,
|
122
|
+
preserve_escapes: bool = True,
|
123
|
+
only_control_chars: bool = True,
|
124
|
+
) -> str: ...
|
125
|
+
|
126
|
+
|
127
|
+
@overload
|
128
|
+
def prettify_value(
|
129
|
+
value: list,
|
130
|
+
max_length: int,
|
131
|
+
preserve_escapes: bool = True,
|
132
|
+
only_control_chars: bool = True,
|
133
|
+
) -> list: ...
|
134
|
+
|
135
|
+
|
136
|
+
@overload
|
137
|
+
def prettify_value(
|
138
|
+
value: dict,
|
139
|
+
max_length: int,
|
140
|
+
preserve_escapes: bool = True,
|
141
|
+
only_control_chars: bool = True,
|
142
|
+
) -> dict: ...
|
143
|
+
|
144
|
+
|
145
|
+
@overload
|
146
|
+
def prettify_value(
|
147
|
+
value: Any,
|
148
|
+
max_length: int,
|
149
|
+
preserve_escapes: bool = True,
|
150
|
+
only_control_chars: bool = True,
|
151
|
+
) -> Any: ...
|
152
|
+
|
153
|
+
|
154
|
+
def prettify_value(
|
155
|
+
value: Any,
|
156
|
+
max_length: int,
|
157
|
+
preserve_escapes: bool = False,
|
158
|
+
only_control_chars: bool = True,
|
159
|
+
) -> Any:
|
160
|
+
"""
|
161
|
+
截断字符串或列表值,使其不超过指定的最大长度
|
162
|
+
|
163
|
+
Args:
|
164
|
+
value: 要截断的值,可以是字符串或列表
|
165
|
+
max_length: 最大长度限制
|
166
|
+
preserve_escapes: 是否保留转义字符
|
167
|
+
only_control_chars: 如果为True,仅转义控制字符;如果为False,转义所有非ASCII字符
|
168
|
+
|
169
|
+
Returns:
|
170
|
+
截断后的值
|
171
|
+
"""
|
172
|
+
if value is None:
|
173
|
+
return None
|
174
|
+
|
175
|
+
# 处理字符串
|
176
|
+
if isinstance(value, str):
|
177
|
+
# 如果需要保留转义字符
|
178
|
+
display_value = value
|
179
|
+
if preserve_escapes:
|
180
|
+
if only_control_chars:
|
181
|
+
# 只转义控制字符,保留其他字符原样
|
182
|
+
control_chars = {
|
183
|
+
"\n": "\\n",
|
184
|
+
"\r": "\\r",
|
185
|
+
"\t": "\\t",
|
186
|
+
"\b": "\\b",
|
187
|
+
"\f": "\\f",
|
188
|
+
"\\": "\\\\",
|
189
|
+
"\v": "\\v", # 垂直制表符
|
190
|
+
"\a": "\\a", # 响铃
|
191
|
+
"\0": "\\0", # 空字符
|
192
|
+
}
|
193
|
+
for char, escape in control_chars.items():
|
194
|
+
display_value = display_value.replace(char, escape)
|
195
|
+
else:
|
196
|
+
# 转义所有特殊字符(包括非ASCII字符如中文)
|
197
|
+
display_value = value.encode("unicode_escape").decode("utf-8")
|
198
|
+
|
199
|
+
if len(display_value) <= max_length:
|
200
|
+
return display_value
|
201
|
+
|
202
|
+
# 如果超过长度,截断中间部分,保留开头和结尾
|
203
|
+
half_length = max_length // 2 - 2 # 减2是为了留出"..."的空间
|
204
|
+
half_length = max(half_length, 5) # 确保至少有5个字符
|
205
|
+
return f"{display_value[:half_length]}...{display_value[-half_length:]}"
|
206
|
+
|
207
|
+
# 处理列表 - 保留所有元素但截断每个元素的值
|
208
|
+
elif isinstance(value, list):
|
209
|
+
if not value:
|
210
|
+
return []
|
211
|
+
|
212
|
+
# 计算每个元素最大长度 - 确保每个元素都有展示空间
|
213
|
+
item_max_length = max(max_length // len(value), 10) # 确保至少有10个字符
|
214
|
+
|
215
|
+
return [prettify_value(item, item_max_length, preserve_escapes, only_control_chars) for item in value]
|
216
|
+
|
217
|
+
# 处理字典 - 保留所有键值对但截断值
|
218
|
+
elif isinstance(value, dict):
|
219
|
+
result = {}
|
220
|
+
item_max_length = max_length // len(value) if value else max_length
|
221
|
+
for k, v in value.items():
|
222
|
+
# 截断每个值
|
223
|
+
result[k] = prettify_value(v, item_max_length, preserve_escapes, only_control_chars)
|
224
|
+
return result
|
225
|
+
|
226
|
+
# 其他类型直接返回
|
227
|
+
return value
|
228
|
+
|
229
|
+
|
230
|
+
def format_analysis_result(analysis_result: AnalyseResult, max_value_length: int = 100) -> str:
|
231
|
+
"""
|
232
|
+
格式化工作流分析结果,生成一个简洁的字符串表示
|
233
|
+
|
234
|
+
Args:
|
235
|
+
analysis_result: 工作流分析结果字典
|
236
|
+
max_value_length: 值的最大长度,超过此长度将被截断
|
237
|
+
|
238
|
+
Returns:
|
239
|
+
格式化后的字符串
|
240
|
+
"""
|
241
|
+
if not analysis_result:
|
242
|
+
return "空分析结果"
|
243
|
+
|
244
|
+
formatted_parts = []
|
245
|
+
|
246
|
+
# 添加节点信息
|
247
|
+
if "nodes" in analysis_result:
|
248
|
+
nodes = analysis_result["nodes"]
|
249
|
+
formatted_parts.append(f"节点数量: {len(nodes)}")
|
250
|
+
|
251
|
+
for idx, node in enumerate(nodes):
|
252
|
+
truncated_node = {
|
253
|
+
"id": node.get("id", "未知ID"),
|
254
|
+
"name": node.get("name", "未知名称"),
|
255
|
+
"type": node.get("type", "未知类型"),
|
256
|
+
"category": node.get("category", "未知类别"),
|
257
|
+
}
|
258
|
+
|
259
|
+
# 添加端口信息摘要
|
260
|
+
if "ports" in node:
|
261
|
+
ports = node.get("ports", [])
|
262
|
+
port_summary = []
|
263
|
+
|
264
|
+
for port in ports:
|
265
|
+
port_info = {
|
266
|
+
"name": port.get("name", "未知端口"),
|
267
|
+
"type": port.get("type", "未知类型"),
|
268
|
+
"connected": port.get("connected", False),
|
269
|
+
}
|
270
|
+
|
271
|
+
# 如果有值且不是隐藏的端口,添加值的摘要
|
272
|
+
if "value" in port and port.get("show", True):
|
273
|
+
port_info["value"] = prettify_value(port.get("value"), max_value_length)
|
274
|
+
|
275
|
+
port_summary.append(port_info)
|
276
|
+
|
277
|
+
truncated_node["ports_summary"] = (
|
278
|
+
f"{len(ports)}个端口,其中{sum(1 for p in ports if p.get('connected'))}个已连接"
|
279
|
+
)
|
280
|
+
|
281
|
+
node_str = f"节点{idx + 1}: {json.dumps(truncated_node, ensure_ascii=False, indent=2)}"
|
282
|
+
formatted_parts.append(node_str)
|
283
|
+
|
284
|
+
# 添加其他可能的顶级信息
|
285
|
+
for key, value in analysis_result.items():
|
286
|
+
if key != "nodes":
|
287
|
+
if isinstance(value, (dict, list)):
|
288
|
+
summary = f"{key}: 包含{len(value)}个项目"
|
289
|
+
else:
|
290
|
+
summary = f"{key}: {prettify_value(value, max_value_length)}"
|
291
|
+
formatted_parts.append(summary)
|
292
|
+
|
293
|
+
return "\n".join(formatted_parts)
|
294
|
+
|
295
|
+
|
296
|
+
def format_workflow_analysis_for_llm(analysis_result: AnalyseResult, max_value_length: int = 100) -> str:
|
297
|
+
"""
|
298
|
+
将工作流分析结果格式化为适合LLM分析的字符串,使用更紧凑的Python风格表示
|
299
|
+
|
300
|
+
Args:
|
301
|
+
analysis_result: 工作流分析结果字典或其JSON字符串表示
|
302
|
+
max_value_length: 值的最大长度,超过此长度将被截断
|
303
|
+
|
304
|
+
Returns:
|
305
|
+
格式化后的字符串
|
306
|
+
"""
|
307
|
+
if not isinstance(analysis_result, dict):
|
308
|
+
return f"无效的分析结果类型: {type(analysis_result)}"
|
309
|
+
|
310
|
+
# 构建LLM友好的格式
|
311
|
+
llm_friendly_format = []
|
312
|
+
|
313
|
+
# 处理节点信息
|
314
|
+
if "nodes" in analysis_result:
|
315
|
+
nodes = analysis_result["nodes"]
|
316
|
+
llm_friendly_format.append("\n## 节点信息")
|
317
|
+
|
318
|
+
for node in nodes:
|
319
|
+
node_id = node.get("id", "未知ID")
|
320
|
+
node_name = node.get("name", "未知名称")
|
321
|
+
node_type = node.get("type", "未知类型")
|
322
|
+
node_category = node.get("category", "未知类别")
|
323
|
+
|
324
|
+
# 截断节点ID,仅保留前3位和后3位
|
325
|
+
short_id = f"{node_id[:3]}...{node_id[-3:]}" if len(node_id) > 6 else node_id
|
326
|
+
|
327
|
+
node_info = [
|
328
|
+
f"- {node_name} <ID: {short_id}>",
|
329
|
+
f" - 类型: {node_type}",
|
330
|
+
f" - 类别: {node_category}",
|
331
|
+
" - 端口",
|
332
|
+
]
|
333
|
+
|
334
|
+
# 添加端口信息
|
335
|
+
if "ports" in node:
|
336
|
+
ports = node.get("ports", [])
|
337
|
+
|
338
|
+
# 遍历所有端口
|
339
|
+
for port in ports:
|
340
|
+
port_name = port.get("name", "未知端口")
|
341
|
+
port_type = port.get("type", "未知类型")
|
342
|
+
|
343
|
+
port_line = f" - `{port_name}` ({port_type})"
|
344
|
+
node_info.append(port_line)
|
345
|
+
|
346
|
+
# 添加值的紧凑描述
|
347
|
+
if "value" in port:
|
348
|
+
value = port.get("value")
|
349
|
+
if isinstance(value, list):
|
350
|
+
# 列表值,使用Python风格显示
|
351
|
+
truncated_list = []
|
352
|
+
item_max_length = max(max_value_length // len(value) if value else max_value_length, 10)
|
353
|
+
node_info.append(
|
354
|
+
f" - value(list): {json.dumps(prettify_value(value, item_max_length), ensure_ascii=False)}"
|
355
|
+
)
|
356
|
+
elif isinstance(value, dict):
|
357
|
+
# 字典值,使用Python风格显示
|
358
|
+
dict_items = []
|
359
|
+
key_max_length = max(max_value_length // len(value) if value else max_value_length, 10)
|
360
|
+
node_info.append(
|
361
|
+
f" - value(dict): {json.dumps(prettify_value(value, key_max_length), ensure_ascii=False)}"
|
362
|
+
)
|
363
|
+
elif isinstance(value, str):
|
364
|
+
# 字符串值,带引号
|
365
|
+
truncated = prettify_value(value, max_value_length)
|
366
|
+
node_info.append(f' - value(str): "{truncated}"')
|
367
|
+
else:
|
368
|
+
# 其他类型的值
|
369
|
+
type_name = type(value).__name__
|
370
|
+
node_info.append(f" - value({type_name}): {value}")
|
371
|
+
else:
|
372
|
+
# 如果没有端口,移除端口标题
|
373
|
+
node_info.pop()
|
374
|
+
|
375
|
+
llm_friendly_format.append("\n".join(node_info))
|
376
|
+
|
377
|
+
# 添加其他可能的顶级信息
|
378
|
+
other_info = []
|
379
|
+
for key, value in analysis_result.items():
|
380
|
+
if key != "nodes":
|
381
|
+
if isinstance(value, dict):
|
382
|
+
# 字典,Python风格显示
|
383
|
+
dict_items = []
|
384
|
+
key_max_length = max(max_value_length // len(value) if value else max_value_length, 10)
|
385
|
+
|
386
|
+
for k, v in value.items():
|
387
|
+
if isinstance(v, str):
|
388
|
+
truncated_v = f'"{prettify_value(v, key_max_length)}"'
|
389
|
+
else:
|
390
|
+
truncated_v = str(prettify_value(v, key_max_length))
|
391
|
+
dict_items.append(f'"{k}": {truncated_v}')
|
392
|
+
|
393
|
+
dict_repr = "{" + ", ".join(dict_items) + "}"
|
394
|
+
other_info.append(f"- **{key}**(dict): {dict_repr}")
|
395
|
+
elif isinstance(value, list):
|
396
|
+
# 列表,Python风格显示
|
397
|
+
truncated_list = []
|
398
|
+
item_max_length = max(max_value_length // len(value) if value else max_value_length, 10)
|
399
|
+
|
400
|
+
for item in value:
|
401
|
+
if isinstance(item, str):
|
402
|
+
truncated_item = f'"{prettify_value(item, item_max_length)}"'
|
403
|
+
else:
|
404
|
+
truncated_item = str(prettify_value(item, item_max_length))
|
405
|
+
truncated_list.append(truncated_item)
|
406
|
+
|
407
|
+
list_repr = "[" + ", ".join(truncated_list) + "]"
|
408
|
+
other_info.append(f"- **{key}**(list): {list_repr}")
|
409
|
+
else:
|
410
|
+
# 基本类型
|
411
|
+
type_name = type(value).__name__
|
412
|
+
if isinstance(value, str):
|
413
|
+
truncated = prettify_value(value, max_value_length)
|
414
|
+
other_info.append(f'- **{key}**({type_name}): "{truncated}"')
|
415
|
+
else:
|
416
|
+
other_info.append(f"- **{key}**({type_name}): {prettify_value(value, max_value_length)}")
|
417
|
+
|
418
|
+
if other_info:
|
419
|
+
llm_friendly_format.append("\n### 其他信息")
|
420
|
+
llm_friendly_format.append("\n".join(other_info))
|
421
|
+
|
422
|
+
return "\n".join(llm_friendly_format)
|
@@ -135,12 +135,18 @@ def generate_python_code(
|
|
135
135
|
port_value = port["value"]
|
136
136
|
default_value = node_instance.ports[port_name].value if port_name in node_instance.ports else None
|
137
137
|
|
138
|
-
#
|
138
|
+
# 判断端口是否有值且值与默认不同,并且端口满足以下条件之一:
|
139
|
+
# 有连接、是输入端口、在UI上显示、是编程节点
|
139
140
|
port_is_connected = (node["id"], port["name"]) in connected_ports
|
140
141
|
if (
|
141
142
|
port_value
|
142
143
|
and port_value != default_value
|
143
|
-
and (
|
144
|
+
and (
|
145
|
+
port_is_connected
|
146
|
+
or not port.get("is_output", False)
|
147
|
+
or port.get("show", False)
|
148
|
+
or node_type == "ProgrammingFunction"
|
149
|
+
)
|
144
150
|
):
|
145
151
|
values.append(port)
|
146
152
|
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{vectorvein-0.2.69 → vectorvein-0.2.72}/src/vectorvein/chat_clients/openai_compatible_client.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|