H
commited on
Commit
·
629a826
1
Parent(s):
3894d27
Refactor switch component (#1940)
Browse files### What problem does this PR solve?
### Type of change
- [x] Refactoring
agent/component/switch.py
CHANGED
@@ -14,50 +14,36 @@
|
|
14 |
# limitations under the License.
|
15 |
#
|
16 |
from abc import ABC
|
17 |
-
|
18 |
-
import pandas as pd
|
19 |
from agent.component.base import ComponentBase, ComponentParamBase
|
20 |
|
21 |
|
22 |
class SwitchParam(ComponentParamBase):
|
23 |
-
|
24 |
"""
|
25 |
Define the Switch component parameters.
|
26 |
"""
|
|
|
27 |
def __init__(self):
|
28 |
super().__init__()
|
29 |
"""
|
30 |
{
|
31 |
-
"
|
32 |
-
"
|
33 |
-
|
34 |
-
|
35 |
"to": ""
|
36 |
}
|
37 |
"""
|
38 |
self.conditions = []
|
39 |
-
self.
|
|
|
|
|
40 |
|
41 |
def check(self):
|
42 |
self.check_empty(self.conditions, "[Switch] conditions")
|
43 |
-
self.check_empty(self.default, "[Switch] Default path")
|
44 |
for cond in self.conditions:
|
45 |
if not cond["to"]: raise ValueError(f"[Switch] 'To' can not be empty!")
|
46 |
-
|
47 |
-
|
48 |
-
if op == "gt":
|
49 |
-
return float(field) > float(value)
|
50 |
-
if op == "gte":
|
51 |
-
return float(field) >= float(value)
|
52 |
-
if op == "lt":
|
53 |
-
return float(field) < float(value)
|
54 |
-
if op == "lte":
|
55 |
-
return float(field) <= float(value)
|
56 |
-
if op == "eq":
|
57 |
-
return str(field) == str(value)
|
58 |
-
if op == "in":
|
59 |
-
return str(field).find(str(value)) >= 0
|
60 |
-
return False
|
61 |
|
62 |
|
63 |
class Switch(ComponentBase, ABC):
|
@@ -65,13 +51,77 @@ class Switch(ComponentBase, ABC):
|
|
65 |
|
66 |
def _run(self, history, **kwargs):
|
67 |
for cond in self._param.conditions:
|
68 |
-
input = self._canvas.get_component(cond["cpn_id"])["obj"].output()[1]
|
69 |
-
if self._param.operators(input.iloc[0, 0], cond["operator"], cond["value"]):
|
70 |
-
if not cond["not"]:
|
71 |
-
return pd.DataFrame([{"content": cond["to"]}])
|
72 |
|
73 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
74 |
|
|
|
75 |
|
|
|
|
|
|
|
76 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
77 |
|
|
|
|
14 |
# limitations under the License.
|
15 |
#
|
16 |
from abc import ABC
|
|
|
|
|
17 |
from agent.component.base import ComponentBase, ComponentParamBase
|
18 |
|
19 |
|
20 |
class SwitchParam(ComponentParamBase):
|
|
|
21 |
"""
|
22 |
Define the Switch component parameters.
|
23 |
"""
|
24 |
+
|
25 |
def __init__(self):
|
26 |
super().__init__()
|
27 |
"""
|
28 |
{
|
29 |
+
"logical_operator" : "and | or"
|
30 |
+
"items" : [
|
31 |
+
{"cpn_id": "categorize:0", "operator": "contains", "value": ""},
|
32 |
+
{"cpn_id": "categorize:0", "operator": "contains", "value": ""},...],
|
33 |
"to": ""
|
34 |
}
|
35 |
"""
|
36 |
self.conditions = []
|
37 |
+
self.end_cpn_id = "answer:0"
|
38 |
+
self.operators = ['contains', 'not contains', 'start with', 'end with', 'empty', 'not empty', '=', '≠', '>',
|
39 |
+
'<', '≥', '≤']
|
40 |
|
41 |
def check(self):
|
42 |
self.check_empty(self.conditions, "[Switch] conditions")
|
|
|
43 |
for cond in self.conditions:
|
44 |
if not cond["to"]: raise ValueError(f"[Switch] 'To' can not be empty!")
|
45 |
+
if cond["logical_operator"] not in ["and", "or"] and len(cond["items"]) > 1:
|
46 |
+
raise ValueError(f"[Switch] Please set logical_operator correctly!")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
47 |
|
48 |
|
49 |
class Switch(ComponentBase, ABC):
|
|
|
51 |
|
52 |
def _run(self, history, **kwargs):
|
53 |
for cond in self._param.conditions:
|
|
|
|
|
|
|
|
|
54 |
|
55 |
+
if len(cond["items"]) == 1:
|
56 |
+
out = self._canvas.get_component(cond["items"][0]["cpn_id"])["obj"].output()[1]
|
57 |
+
cpn_input = "" if "content" not in out.columns else " ".join(out["content"])
|
58 |
+
if self.process_operator(cpn_input, cond["items"][0]["operator"], cond["items"][0]["value"]):
|
59 |
+
return Switch.be_output(cond["to"])
|
60 |
+
continue
|
61 |
+
|
62 |
+
if cond["logical_operator"] == "and":
|
63 |
+
res = True
|
64 |
+
for item in cond["items"]:
|
65 |
+
out = self._canvas.get_component(item["cpn_id"])["obj"].output()[1]
|
66 |
+
cpn_input = "" if "content" not in out.columns else " ".join(out["content"])
|
67 |
+
if not self.process_operator(cpn_input, item["operator"], item["value"]):
|
68 |
+
res = False
|
69 |
+
break
|
70 |
+
if res:
|
71 |
+
return Switch.be_output(cond["to"])
|
72 |
+
continue
|
73 |
+
|
74 |
+
res = False
|
75 |
+
for item in cond["items"]:
|
76 |
+
out = self._canvas.get_component(item["cpn_id"])["obj"].output()[1]
|
77 |
+
cpn_input = "" if "content" not in out.columns else " ".join(out["content"])
|
78 |
+
if self.process_operator(cpn_input, item["operator"], item["value"]):
|
79 |
+
res = True
|
80 |
+
break
|
81 |
+
if res:
|
82 |
+
return Switch.be_output(cond["to"])
|
83 |
|
84 |
+
return Switch.be_output(self._param.end_cpn_id)
|
85 |
|
86 |
+
def process_operator(self, input: str, operator: str, value: str) -> bool:
|
87 |
+
if not isinstance(input, str) or not isinstance(value, str):
|
88 |
+
raise ValueError('Invalid input or value type: string')
|
89 |
|
90 |
+
if operator == "contains":
|
91 |
+
return True if value.lower() in input.lower() else False
|
92 |
+
elif operator == "not contains":
|
93 |
+
return True if value.lower() not in input.lower() else False
|
94 |
+
elif operator == "start with":
|
95 |
+
return True if input.lower().startswith(value.lower()) else False
|
96 |
+
elif operator == "end with":
|
97 |
+
return True if input.lower().endswith(value.lower()) else False
|
98 |
+
elif operator == "empty":
|
99 |
+
return True if not input else False
|
100 |
+
elif operator == "not empty":
|
101 |
+
return True if input else False
|
102 |
+
elif operator == "=":
|
103 |
+
return True if input == value else False
|
104 |
+
elif operator == "≠":
|
105 |
+
return True if input != value else False
|
106 |
+
elif operator == ">":
|
107 |
+
try:
|
108 |
+
return True if float(input) > float(value) else False
|
109 |
+
except Exception as e:
|
110 |
+
return True if input > value else False
|
111 |
+
elif operator == "<":
|
112 |
+
try:
|
113 |
+
return True if float(input) < float(value) else False
|
114 |
+
except Exception as e:
|
115 |
+
return True if input < value else False
|
116 |
+
elif operator == "≥":
|
117 |
+
try:
|
118 |
+
return True if float(input) >= float(value) else False
|
119 |
+
except Exception as e:
|
120 |
+
return True if input >= value else False
|
121 |
+
elif operator == "≤":
|
122 |
+
try:
|
123 |
+
return True if float(input) <= float(value) else False
|
124 |
+
except Exception as e:
|
125 |
+
return True if input <= value else False
|
126 |
|
127 |
+
raise ValueError('Not supported operator' + operator)
|
agent/test/dsl_examples/baidu_generate_and_switch.json
ADDED
@@ -0,0 +1,129 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"components": {
|
3 |
+
"begin": {
|
4 |
+
"obj":{
|
5 |
+
"component_name": "Begin",
|
6 |
+
"params": {
|
7 |
+
"prologue": "Hi there!"
|
8 |
+
}
|
9 |
+
},
|
10 |
+
"downstream": ["answer:0"],
|
11 |
+
"upstream": []
|
12 |
+
},
|
13 |
+
"answer:0": {
|
14 |
+
"obj": {
|
15 |
+
"component_name": "Answer",
|
16 |
+
"params": {}
|
17 |
+
},
|
18 |
+
"downstream": ["baidu:0"],
|
19 |
+
"upstream": ["begin", "message:0","message:1"]
|
20 |
+
},
|
21 |
+
"baidu:0": {
|
22 |
+
"obj": {
|
23 |
+
"component_name": "Baidu",
|
24 |
+
"params": {}
|
25 |
+
},
|
26 |
+
"downstream": ["generate:0"],
|
27 |
+
"upstream": ["answer:0"]
|
28 |
+
},
|
29 |
+
"generate:0": {
|
30 |
+
"obj": {
|
31 |
+
"component_name": "Generate",
|
32 |
+
"params": {
|
33 |
+
"llm_id": "deepseek-chat",
|
34 |
+
"prompt": "You are an intelligent assistant. Please answer the user's question based on what Baidu searched. First, please output the user's question and the content searched by Baidu, and then answer yes, no, or i don't know.Here is the user's question:{user_input}The above is the user's question.Here is what Baidu searched for:{baidu}The above is the content searched by Baidu.",
|
35 |
+
"temperature": 0.2
|
36 |
+
},
|
37 |
+
"parameters": [
|
38 |
+
{
|
39 |
+
"component_id": "answer:0",
|
40 |
+
"id": "69415446-49bf-4d4b-8ec9-ac86066f7709",
|
41 |
+
"key": "user_input"
|
42 |
+
},
|
43 |
+
{
|
44 |
+
"component_id": "baidu:0",
|
45 |
+
"id": "83363c2a-00a8-402f-a45c-ddc4097d7d8b",
|
46 |
+
"key": "baidu"
|
47 |
+
}
|
48 |
+
]
|
49 |
+
},
|
50 |
+
"downstream": ["switch:0"],
|
51 |
+
"upstream": ["baidu:0"]
|
52 |
+
},
|
53 |
+
"switch:0": {
|
54 |
+
"obj": {
|
55 |
+
"component_name": "Switch",
|
56 |
+
"params": {
|
57 |
+
"conditions": [
|
58 |
+
{
|
59 |
+
"logical_operator" : "or",
|
60 |
+
"items" : [
|
61 |
+
{"cpn_id": "generate:0", "operator": "contains", "value": "yes"},
|
62 |
+
{"cpn_id": "generate:0", "operator": "contains", "value": "yeah"}
|
63 |
+
],
|
64 |
+
"to": "message:0"
|
65 |
+
},
|
66 |
+
{
|
67 |
+
"logical_operator" : "and",
|
68 |
+
"items" : [
|
69 |
+
{"cpn_id": "generate:0", "operator": "contains", "value": "no"},
|
70 |
+
{"cpn_id": "generate:0", "operator": "not contains", "value": "yes"},
|
71 |
+
{"cpn_id": "generate:0", "operator": "not contains", "value": "know"}
|
72 |
+
],
|
73 |
+
"to": "message:1"
|
74 |
+
},
|
75 |
+
{
|
76 |
+
"logical_operator" : "",
|
77 |
+
"items" : [
|
78 |
+
{"cpn_id": "generate:0", "operator": "contains", "value": "know"}
|
79 |
+
],
|
80 |
+
"to": "message:2"
|
81 |
+
}
|
82 |
+
],
|
83 |
+
"end_cpn_id": "answer:0"
|
84 |
+
|
85 |
+
}
|
86 |
+
},
|
87 |
+
"downstream": ["message:0","message:1"],
|
88 |
+
"upstream": ["generate:0"]
|
89 |
+
},
|
90 |
+
"message:0": {
|
91 |
+
"obj": {
|
92 |
+
"component_name": "Message",
|
93 |
+
"params": {
|
94 |
+
"messages": ["YES YES YES YES YES YES YES YES YES YES YES YES"]
|
95 |
+
}
|
96 |
+
},
|
97 |
+
|
98 |
+
"upstream": ["switch:0"],
|
99 |
+
"downstream": ["answer:0"]
|
100 |
+
},
|
101 |
+
"message:1": {
|
102 |
+
"obj": {
|
103 |
+
"component_name": "Message",
|
104 |
+
"params": {
|
105 |
+
"messages": ["NO NO NO NO NO NO NO NO NO NO NO NO NO NO"]
|
106 |
+
}
|
107 |
+
},
|
108 |
+
|
109 |
+
"upstream": ["switch:0"],
|
110 |
+
"downstream": ["answer:0"]
|
111 |
+
},
|
112 |
+
"message:2": {
|
113 |
+
"obj": {
|
114 |
+
"component_name": "Message",
|
115 |
+
"params": {
|
116 |
+
"messages": ["I DON'T KNOW---------------------------"]
|
117 |
+
}
|
118 |
+
},
|
119 |
+
|
120 |
+
"upstream": ["switch:0"],
|
121 |
+
"downstream": ["answer:0"]
|
122 |
+
}
|
123 |
+
},
|
124 |
+
"history": [],
|
125 |
+
"messages": [],
|
126 |
+
"reference": {},
|
127 |
+
"path": [],
|
128 |
+
"answer": []
|
129 |
+
}
|