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:
@@ -284,6 +284,111 @@ class WorkflowGraphTests(unittest.TestCase):
|
||||
)
|
||||
)
|
||||
|
||||
def test_all_source_nodes_allow_multiple_conditional_paths(self):
|
||||
expression = {
|
||||
"combinator": "and",
|
||||
"rules": [{"variable": "route", "operator": "eq", "value": "yes"}],
|
||||
}
|
||||
cases = {
|
||||
"start": {
|
||||
"nodes": [
|
||||
{"id": "start", "type": "start", "data": {}},
|
||||
{"id": "agent", "type": "agent", "data": {}},
|
||||
{"id": "action", "type": "action", "data": {}},
|
||||
{"id": "end", "type": "end", "data": {}},
|
||||
],
|
||||
"edges": [
|
||||
{"id": "default", "source": "start", "target": "agent", "data": {"mode": "always", "priority": 10}},
|
||||
{"id": "llm", "source": "start", "target": "end", "data": {"mode": "llm", "priority": 20, "condition": "应当结束"}},
|
||||
{"id": "expr", "source": "start", "target": "action", "data": {"mode": "expression", "priority": 30, "expression": expression}},
|
||||
{"id": "action-end", "source": "action", "target": "end", "data": {"mode": "always", "priority": 10}},
|
||||
],
|
||||
},
|
||||
"agent": {
|
||||
"nodes": [
|
||||
{"id": "start", "type": "start", "data": {}},
|
||||
{"id": "agent", "type": "agent", "data": {}},
|
||||
{"id": "action", "type": "action", "data": {}},
|
||||
{"id": "handoff", "type": "handoff", "data": {}},
|
||||
{"id": "end", "type": "end", "data": {}},
|
||||
],
|
||||
"edges": [
|
||||
{"id": "begin", "source": "start", "target": "agent", "data": {"mode": "always", "priority": 10}},
|
||||
{"id": "default", "source": "agent", "target": "end", "data": {"mode": "always", "priority": 10}},
|
||||
{"id": "llm", "source": "agent", "target": "action", "data": {"mode": "llm", "priority": 20, "condition": "执行操作"}},
|
||||
{"id": "expr", "source": "agent", "target": "handoff", "data": {"mode": "expression", "priority": 30, "expression": expression}},
|
||||
{"id": "action-end", "source": "action", "target": "end", "data": {"mode": "always", "priority": 10}},
|
||||
],
|
||||
},
|
||||
"action": {
|
||||
"nodes": [
|
||||
{"id": "start", "type": "start", "data": {}},
|
||||
{"id": "action", "type": "action", "data": {}},
|
||||
{"id": "agent", "type": "agent", "data": {}},
|
||||
{"id": "handoff", "type": "handoff", "data": {}},
|
||||
{"id": "end", "type": "end", "data": {}},
|
||||
],
|
||||
"edges": [
|
||||
{"id": "begin", "source": "start", "target": "action", "data": {"mode": "always", "priority": 10}},
|
||||
{"id": "default", "source": "action", "target": "agent", "data": {"mode": "always", "priority": 10}},
|
||||
{"id": "llm", "source": "action", "target": "end", "data": {"mode": "llm", "priority": 20, "condition": "执行失败"}},
|
||||
{"id": "expr", "source": "action", "target": "handoff", "data": {"mode": "expression", "priority": 30, "expression": expression}},
|
||||
],
|
||||
},
|
||||
"handoff": {
|
||||
"nodes": [
|
||||
{"id": "start", "type": "start", "data": {}},
|
||||
{"id": "handoff", "type": "handoff", "data": {}},
|
||||
{"id": "agent", "type": "agent", "data": {}},
|
||||
{"id": "action", "type": "action", "data": {}},
|
||||
{"id": "end", "type": "end", "data": {}},
|
||||
],
|
||||
"edges": [
|
||||
{"id": "begin", "source": "start", "target": "handoff", "data": {"mode": "always", "priority": 10}},
|
||||
{"id": "default", "source": "handoff", "target": "agent", "data": {"mode": "always", "priority": 10}},
|
||||
{"id": "llm", "source": "handoff", "target": "end", "data": {"mode": "llm", "priority": 20, "condition": "转接完成"}},
|
||||
{"id": "expr", "source": "handoff", "target": "action", "data": {"mode": "expression", "priority": 30, "expression": expression}},
|
||||
{"id": "action-end", "source": "action", "target": "end", "data": {"mode": "always", "priority": 10}},
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
for source_type, parts in cases.items():
|
||||
graph = {"specVersion": 3, "settings": {}, **parts}
|
||||
with self.subTest(source_type=source_type):
|
||||
self.assertEqual(validate_graph(graph), [])
|
||||
|
||||
graph["edges"].append(
|
||||
{
|
||||
"id": "duplicate-default",
|
||||
"source": source_type,
|
||||
"target": "end",
|
||||
"data": {"mode": "always", "priority": 40},
|
||||
}
|
||||
)
|
||||
self.assertTrue(
|
||||
any("最多只能有一条默认路径" in error for error in validate_graph(graph))
|
||||
)
|
||||
|
||||
def test_v2_condition_on_non_agent_becomes_llm_path(self):
|
||||
graph = normalize_graph(
|
||||
{
|
||||
"nodes": [
|
||||
{"id": "start", "type": "start", "data": {}},
|
||||
{"id": "handoff", "type": "handoff", "data": {}},
|
||||
],
|
||||
"edges": [
|
||||
{
|
||||
"id": "route",
|
||||
"source": "start",
|
||||
"target": "handoff",
|
||||
"data": {"condition": "用户需要人工服务"},
|
||||
}
|
||||
],
|
||||
}
|
||||
)
|
||||
self.assertEqual(graph["edges"][0]["data"]["mode"], "llm")
|
||||
|
||||
def test_v2_start_prompt_is_preserved_in_synthetic_agent(self):
|
||||
graph = normalize_graph(
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user