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
- "cpn_id": "categorize:0",
32
- "not": False,
33
- "operator": "gt/gte/lt/lte/eq/in",
34
- "value": "",
35
  "to": ""
36
  }
37
  """
38
  self.conditions = []
39
- self.default = ""
 
 
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
- def operators(self, field, op, value):
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
- return pd.DataFrame([{"content": self._param.default}])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ }