Skip to content

Commit 35e5fad

Browse files
authored
Feat: new component variable assigner (#11050)
### What problem does this PR solve? issue: #10427 change: new component variable assigner ### Type of change - [x] New Feature (non-breaking change which adds functionality)
1 parent 4942a23 commit 35e5fad

File tree

4 files changed

+235
-0
lines changed

4 files changed

+235
-0
lines changed

agent/canvas.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,38 @@ def get_variable_param_value(self, obj: Any, path: str) -> Any:
216216
else:
217217
cur = getattr(cur, key, None)
218218
return cur
219+
220+
def set_variable_value(self, exp: str,value):
221+
exp = exp.strip("{").strip("}").strip(" ").strip("{").strip("}")
222+
if exp.find("@") < 0:
223+
self.globals[exp] = value
224+
return
225+
cpn_id, var_nm = exp.split("@")
226+
cpn = self.get_component(cpn_id)
227+
if not cpn:
228+
raise Exception(f"Can't find variable: '{cpn_id}@{var_nm}'")
229+
parts = var_nm.split(".", 1)
230+
root_key = parts[0]
231+
rest = parts[1] if len(parts) > 1 else ""
232+
if not rest:
233+
cpn["obj"].set_output(root_key, value)
234+
return
235+
root_val = cpn["obj"].output(root_key)
236+
if not root_val:
237+
root_val = {}
238+
cpn["obj"].set_output(root_key, self.set_variable_param_value(root_val,rest,value))
239+
240+
def set_variable_param_value(self, obj: Any, path: str, value) -> Any:
241+
cur = obj
242+
keys = path.split('.')
243+
if not path:
244+
return value
245+
for key in keys:
246+
if key not in cur or not isinstance(cur[key], dict):
247+
cur[key] = {}
248+
cur = cur[key]
249+
cur[keys[-1]] = value
250+
return obj
219251

220252
def is_canceled(self) -> bool:
221253
return has_canceled(self.task_id)

agent/component/data_operations.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,18 @@
1+
#
2+
# Copyright 2024 The InfiniFlow Authors. All Rights Reserved.
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
#
116
from abc import ABC
217
import ast
318
import os

agent/component/iteration.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ class IterationParam(ComponentParamBase):
3232
def __init__(self):
3333
super().__init__()
3434
self.items_ref = ""
35+
self.veriable={}
3536

3637
def get_input_form(self) -> dict[str, dict]:
3738
return {
Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
#
2+
# Copyright 2024 The InfiniFlow Authors. All Rights Reserved.
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
#
16+
from abc import ABC
17+
import os
18+
import numbers
19+
from agent.component.base import ComponentBase, ComponentParamBase
20+
from api.utils.api_utils import timeout
21+
22+
class VariableAssignerParam(ComponentParamBase):
23+
"""
24+
Define the Variable Assigner component parameters.
25+
"""
26+
def __init__(self):
27+
super().__init__()
28+
self.variables=[]
29+
30+
def check(self):
31+
return True
32+
33+
def get_input_form(self) -> dict[str, dict]:
34+
return {
35+
"items": {
36+
"type": "json",
37+
"name": "Items"
38+
}
39+
}
40+
41+
class VariableAssigner(ComponentBase,ABC):
42+
component_name = "VariableAssigner"
43+
44+
@timeout(int(os.environ.get("COMPONENT_EXEC_TIMEOUT", 10*60)))
45+
def _invoke(self, **kwargs):
46+
if not isinstance(self._param.variables,list):
47+
return
48+
else:
49+
for item in self._param.variables:
50+
variable=item["variable"]
51+
operator=item["operator"]
52+
parameter=item["parameter"]
53+
variable_value=self._canvas.get_variable_value(variable)
54+
new_variable=self._operate(variable_value,operator,parameter)
55+
self._canvas.set_variable_value(variable,new_variable)
56+
57+
def _operate(self,variable,operator,parameter):
58+
if operator == "overwrite":
59+
return self._overwrite(parameter)
60+
elif operator == "clear":
61+
return self._clear(variable)
62+
elif operator == "set":
63+
return self._set(variable,parameter)
64+
elif operator == "append":
65+
return self._append(variable,parameter)
66+
elif operator == "extend":
67+
return self._extend(variable,parameter)
68+
elif operator == "remove_first":
69+
return self._remove_first(variable)
70+
elif operator == "remove_last":
71+
return self._remove_last(variable)
72+
elif operator == "+=":
73+
return self._add(variable,parameter)
74+
elif operator == "-=":
75+
return self._subtract(variable,parameter)
76+
elif operator == "*=":
77+
return self._multiply(variable,parameter)
78+
elif operator == "/=":
79+
return self._divide(variable,parameter)
80+
else:
81+
return
82+
83+
def _overwrite(self,parameter):
84+
return self._canvas.get_variable_value(parameter)
85+
86+
def _clear(self,variable):
87+
if isinstance(variable,list):
88+
return []
89+
elif isinstance(variable,str):
90+
return ""
91+
elif isinstance(variable,dict):
92+
return {}
93+
elif isinstance(variable,int):
94+
return 0
95+
elif isinstance(variable,float):
96+
return 0.0
97+
elif isinstance(variable,bool):
98+
return False
99+
else:
100+
return None
101+
102+
def _set(self,variable,parameter):
103+
if variable is None:
104+
return self._canvas.get_value_with_variable(parameter)
105+
elif isinstance(variable,str):
106+
return self._canvas.get_value_with_variable(parameter)
107+
elif isinstance(variable,bool):
108+
return parameter
109+
elif isinstance(variable,int):
110+
return parameter
111+
elif isinstance(variable,float):
112+
return parameter
113+
else:
114+
return parameter
115+
116+
def _append(self,variable,parameter):
117+
parameter=self._canvas.get_variable_value(parameter)
118+
if variable is None:
119+
variable=[]
120+
if not isinstance(variable,list):
121+
return "ERROR:VARIABLE_NOT_LIST"
122+
elif len(variable)!=0 and not isinstance(parameter,type(variable[0])):
123+
return "ERROR:PARAMETER_NOT_LIST_ELEMENT_TYPE"
124+
else:
125+
return variable+parameter
126+
127+
def _extend(self,variable,parameter):
128+
parameter=self._canvas.get_variable_value(parameter)
129+
if variable is None:
130+
variable=[]
131+
if not isinstance(variable,list):
132+
return "ERROR:VARIABLE_NOT_LIST"
133+
elif not isinstance(parameter,list):
134+
return "ERROR:PARAMETER_NOT_LIST"
135+
elif len(variable)!=0 and len(parameter)!=0 and not isinstance(parameter[0],type(variable[0])):
136+
return "ERROR:PARAMETER_NOT_LIST_ELEMENT_TYPE"
137+
else:
138+
return variable+parameter
139+
140+
def _remove_first(self,variable):
141+
if len(variable)==0:
142+
return variable
143+
if not isinstance(variable,list):
144+
return "ERROR:VARIABLE_NOT_LIST"
145+
else:
146+
return variable[1:]
147+
148+
def _remove_last(self,variable):
149+
if len(variable)==0:
150+
return variable
151+
if not isinstance(variable,list):
152+
return "ERROR:VARIABLE_NOT_LIST"
153+
else:
154+
return variable[:-1]
155+
156+
157+
def is_number(self, value):
158+
if isinstance(value, bool):
159+
return False
160+
return isinstance(value, numbers.Number)
161+
162+
def _add(self,variable,parameter):
163+
if self.is_number(variable) and self.is_number(parameter):
164+
return variable+parameter
165+
else:
166+
return "ERROR:VARIABLE_NOT_NUMBER or PARAMETER_NOT_NUMBER"
167+
168+
def _subtract(self,variable,parameter):
169+
if self.is_number(variable) and self.is_number(parameter):
170+
return variable-parameter
171+
else:
172+
return "ERROR:VARIABLE_NOT_NUMBER or PARAMETER_NOT_NUMBER"
173+
174+
def _multiply(self,variable,parameter):
175+
if self.is_number(variable) and self.is_number(parameter):
176+
return variable*parameter
177+
else:
178+
return "ERROR:VARIABLE_NOT_NUMBER or PARAMETER_NOT_NUMBER"
179+
180+
def _divide(self,variable,parameter):
181+
if self.is_number(variable) and self.is_number(parameter):
182+
if parameter==0:
183+
return "ERROR:DIVIDE_BY_ZERO"
184+
else:
185+
return variable/parameter
186+
else:
187+
return "ERROR:VARIABLE_NOT_NUMBER or PARAMETER_NOT_NUMBER"

0 commit comments

Comments
 (0)