Refactor workflow routing and greeting management in Brain classes
- Update WorkflowBrain to handle greeting playback more effectively, ensuring that the initial greeting completes before transitioning to the first node. - Introduce new methods for managing greeting states and conditions, enhancing the interaction flow for user turns. - Refactor WorkflowLLMRouter to improve routing logic and ensure proper handling of conditional paths. - Enhance tests to verify the correct behavior of greeting management and routing under various scenarios, including waiting for audio playback to finish. - Update frontend components to reflect changes in edge handling and improve user experience in workflow configurations.
This commit is contained in:
@@ -116,7 +116,7 @@ def node_types_response() -> dict[str, Any]:
|
||||
return {"specVersion": SPEC_VERSION, "nodeTypes": NODE_SPECS}
|
||||
|
||||
|
||||
def _edge_data_v3(edge: dict, source_type: str) -> dict:
|
||||
def _edge_data_v3(edge: dict) -> dict:
|
||||
data = deepcopy(edge.get("data") or {})
|
||||
if data.get("mode") in EDGE_MODES:
|
||||
data.setdefault("priority", 10)
|
||||
@@ -125,7 +125,7 @@ def _edge_data_v3(edge: dict, source_type: str) -> dict:
|
||||
transition = data.pop("transition_speech", data.get("transitionSpeech", ""))
|
||||
data.update(
|
||||
{
|
||||
"mode": "llm" if condition and source_type == "agent" else "always",
|
||||
"mode": "llm" if condition else "always",
|
||||
"priority": 10,
|
||||
"condition": condition,
|
||||
"transitionSpeech": transition,
|
||||
@@ -185,7 +185,6 @@ def normalize_graph(graph: dict[str, Any] | None) -> dict[str, Any]:
|
||||
edges = source.get("edges") or []
|
||||
global_prompt = ""
|
||||
mapped_nodes: list[dict] = []
|
||||
type_by_id: dict[str, str] = {}
|
||||
start_prompt_nodes: dict[str, str] = {}
|
||||
|
||||
type_map = {
|
||||
@@ -220,15 +219,11 @@ def normalize_graph(graph: dict[str, Any] | None) -> dict[str, Any]:
|
||||
data.pop(key, None)
|
||||
migrated["data"] = data
|
||||
mapped_nodes.append(migrated)
|
||||
if migrated.get("id"):
|
||||
type_by_id[str(migrated["id"])] = new_type
|
||||
|
||||
mapped_edges: list[dict] = []
|
||||
for edge in edges:
|
||||
migrated = deepcopy(edge)
|
||||
migrated["data"] = _edge_data_v3(
|
||||
migrated, type_by_id.get(str(migrated.get("source")), "")
|
||||
)
|
||||
migrated["data"] = _edge_data_v3(migrated)
|
||||
mapped_edges.append(migrated)
|
||||
|
||||
# A v2 Start was conversational. Insert a synthetic Agent so its prompt remains active.
|
||||
@@ -254,7 +249,7 @@ def normalize_graph(graph: dict[str, Any] | None) -> dict[str, Any]:
|
||||
for edge in mapped_edges:
|
||||
if edge.get("source") == start_id:
|
||||
edge["source"] = synthetic_id
|
||||
edge["data"] = _edge_data_v3(edge, "agent")
|
||||
edge["data"] = _edge_data_v3(edge)
|
||||
if str(edge["data"].get("condition") or "").strip():
|
||||
edge["data"]["mode"] = "llm"
|
||||
mapped_edges.append(
|
||||
@@ -352,10 +347,8 @@ def validate_graph(graph: dict[str, Any]) -> list[str]:
|
||||
mode = data.get("mode")
|
||||
if mode not in EDGE_MODES:
|
||||
errors.append(f"边 {edge_id} 的判断模式无效:{mode}")
|
||||
if mode == "llm" and node_by_id[source_id].get("type") != "agent":
|
||||
errors.append(f"LLM 判断边只能从 Agent 发出:{edge_id}")
|
||||
if mode == "llm" and not str(data.get("condition") or "").strip():
|
||||
errors.append(f"LLM 判断边缺少自然语言条件:{edge_id}")
|
||||
errors.append(f"大模型判断边缺少自然语言条件:{edge_id}")
|
||||
if mode == "expression":
|
||||
expression_errors = _validate_expression(data.get("expression"))
|
||||
errors.extend(f"边 {edge_id}:{item}" for item in expression_errors)
|
||||
@@ -370,7 +363,7 @@ def validate_graph(graph: dict[str, Any]) -> list[str]:
|
||||
if mode == "always":
|
||||
always_counts[source_id] += 1
|
||||
if always_counts[source_id] > 1:
|
||||
errors.append(f"节点 {source_id} 最多只能有一条默认边")
|
||||
errors.append(f"节点 {source_id} 最多只能有一条默认路径")
|
||||
incoming[target_id] += 1
|
||||
outgoing[source_id] += 1
|
||||
adj[source_id].append(target_id)
|
||||
@@ -394,14 +387,6 @@ def validate_graph(graph: dict[str, Any]) -> list[str]:
|
||||
errors.append(f"节点 {node_id} 的{label}不能少于 {lo}")
|
||||
if hi is not None and actual > hi:
|
||||
errors.append(f"节点 {node_id} 的{label}不能多于 {hi}")
|
||||
node_type = node.get("type")
|
||||
if (
|
||||
node_type in AUTOMATIC_NODE_TYPES
|
||||
and outgoing[node_id] > 0
|
||||
and always_counts[node_id] != 1
|
||||
):
|
||||
errors.append(f"自动节点 {node_id} 存在出边时必须有且仅有一条默认边")
|
||||
|
||||
start_id = next(
|
||||
(node_id for node_id, node in node_by_id.items() if node.get("type") == "start"),
|
||||
None,
|
||||
|
||||
Reference in New Issue
Block a user