TraceStudio-dev/server/tests/graph_runtime_schema.py
2026-01-09 21:37:02 +08:00

84 lines
2.9 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
TraceStudio 节点图运行时数据结构设计
本文件定义了节点图执行所需的核心数据结构,确保前后端一致。
"""
from enum import Enum
from typing import Any, Dict, List, Optional
from dataclasses import dataclass, field
from app.core.node_base import NodeType
class DimensionMode(Enum):
NONE = "none"
EXPAND = "expand"
COLLAPSE = "collapse"
BROADCAST = "broadcast"
@dataclass
class EdgeMetadata:
source_node: str
source_port: str
target_node: str
target_port: str
dimension_mode: DimensionMode = DimensionMode.NONE
@dataclass
class NodeMetadata:
node_id: str
# 严格约定type 必须为 NodeType 的值("input"/"normal"/"output"/"function"/...
type: str
# 实现类名(必须提供,用于从 NodeRegistry 加载实现)
class_name: str
params: Dict[str, Any] = field(default_factory=dict)
sub_workflow_nodes: Optional[List[Dict]] = None
sub_workflow_edges: Optional[List[Dict]] = None
@dataclass
class GraphRuntime:
nodes: List[NodeMetadata]
edges: List[EdgeMetadata]
# 可扩展:全局上下文、运行参数等
def to_executor_format(self) -> Dict[str, Any]:
"""
将运行时 Graph 格式转换为 WorkflowExecutor 接受的 nodes/edges 列表。
- 将 EdgeMetadata 字段命名转换为 executor 期望的 snake_casesource, source_port, target, target_port
- 将 NodeMetadata 中的 sub_workflow_* 字段展开为 executor 可识别的键名sub_workflow_nodes/sub_workflow_edges
- 保持 params 原样传递
"""
nodes_out = []
for n in self.nodes:
# 验证 type 为 NodeType 的合法值
try:
NodeType(n.type)
except Exception:
raise ValueError(f"NodeMetadata.type 必须为 NodeType 的值之一: {[t.value for t in NodeType]} (got {n.type})")
nd = {
"id": n.node_id,
"type": n.type,
"class_name": n.class_name,
"params": n.params or {}
}
# 支持两种约定:直接 sub_workflow_* 或嵌套 sub_workflow
if n.sub_workflow_nodes:
nd["sub_workflow_nodes"] = n.sub_workflow_nodes
if n.sub_workflow_edges:
nd["sub_workflow_edges"] = n.sub_workflow_edges
nodes_out.append(nd)
edges_out = []
for e in self.edges:
edges_out.append({
"source": e.source_node,
"source_port": e.source_port,
"target": e.target_node,
"target_port": e.target_port,
# executor currently ignores dimension_mode on input dicts,
# but we include it for completeness (as string)
"dimension_mode": e.dimension_mode.value if e.dimension_mode else DimensionMode.NONE.value
})
return {"nodes": nodes_out, "edges": edges_out}