mirror of
https://github.com/infiniflow/ragflow.git
synced 2025-12-08 20:42:30 +08:00
Feat: new component variable assigner (#11050)
### What problem does this PR solve? issue: https://github.com/infiniflow/ragflow/issues/10427 change: new component variable assigner ### Type of change - [x] New Feature (non-breaking change which adds functionality)
This commit is contained in:
@ -216,6 +216,38 @@ class Graph:
|
|||||||
else:
|
else:
|
||||||
cur = getattr(cur, key, None)
|
cur = getattr(cur, key, None)
|
||||||
return cur
|
return cur
|
||||||
|
|
||||||
|
def set_variable_value(self, exp: str,value):
|
||||||
|
exp = exp.strip("{").strip("}").strip(" ").strip("{").strip("}")
|
||||||
|
if exp.find("@") < 0:
|
||||||
|
self.globals[exp] = value
|
||||||
|
return
|
||||||
|
cpn_id, var_nm = exp.split("@")
|
||||||
|
cpn = self.get_component(cpn_id)
|
||||||
|
if not cpn:
|
||||||
|
raise Exception(f"Can't find variable: '{cpn_id}@{var_nm}'")
|
||||||
|
parts = var_nm.split(".", 1)
|
||||||
|
root_key = parts[0]
|
||||||
|
rest = parts[1] if len(parts) > 1 else ""
|
||||||
|
if not rest:
|
||||||
|
cpn["obj"].set_output(root_key, value)
|
||||||
|
return
|
||||||
|
root_val = cpn["obj"].output(root_key)
|
||||||
|
if not root_val:
|
||||||
|
root_val = {}
|
||||||
|
cpn["obj"].set_output(root_key, self.set_variable_param_value(root_val,rest,value))
|
||||||
|
|
||||||
|
def set_variable_param_value(self, obj: Any, path: str, value) -> Any:
|
||||||
|
cur = obj
|
||||||
|
keys = path.split('.')
|
||||||
|
if not path:
|
||||||
|
return value
|
||||||
|
for key in keys:
|
||||||
|
if key not in cur or not isinstance(cur[key], dict):
|
||||||
|
cur[key] = {}
|
||||||
|
cur = cur[key]
|
||||||
|
cur[keys[-1]] = value
|
||||||
|
return obj
|
||||||
|
|
||||||
def is_canceled(self) -> bool:
|
def is_canceled(self) -> bool:
|
||||||
return has_canceled(self.task_id)
|
return has_canceled(self.task_id)
|
||||||
|
|||||||
@ -1,3 +1,18 @@
|
|||||||
|
#
|
||||||
|
# Copyright 2024 The InfiniFlow Authors. All Rights Reserved.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
#
|
||||||
from abc import ABC
|
from abc import ABC
|
||||||
import ast
|
import ast
|
||||||
import os
|
import os
|
||||||
|
|||||||
@ -32,6 +32,7 @@ class IterationParam(ComponentParamBase):
|
|||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.items_ref = ""
|
self.items_ref = ""
|
||||||
|
self.veriable={}
|
||||||
|
|
||||||
def get_input_form(self) -> dict[str, dict]:
|
def get_input_form(self) -> dict[str, dict]:
|
||||||
return {
|
return {
|
||||||
|
|||||||
187
agent/component/variable_assigner.py
Normal file
187
agent/component/variable_assigner.py
Normal file
@ -0,0 +1,187 @@
|
|||||||
|
#
|
||||||
|
# Copyright 2024 The InfiniFlow Authors. All Rights Reserved.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
#
|
||||||
|
from abc import ABC
|
||||||
|
import os
|
||||||
|
import numbers
|
||||||
|
from agent.component.base import ComponentBase, ComponentParamBase
|
||||||
|
from api.utils.api_utils import timeout
|
||||||
|
|
||||||
|
class VariableAssignerParam(ComponentParamBase):
|
||||||
|
"""
|
||||||
|
Define the Variable Assigner component parameters.
|
||||||
|
"""
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__()
|
||||||
|
self.variables=[]
|
||||||
|
|
||||||
|
def check(self):
|
||||||
|
return True
|
||||||
|
|
||||||
|
def get_input_form(self) -> dict[str, dict]:
|
||||||
|
return {
|
||||||
|
"items": {
|
||||||
|
"type": "json",
|
||||||
|
"name": "Items"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class VariableAssigner(ComponentBase,ABC):
|
||||||
|
component_name = "VariableAssigner"
|
||||||
|
|
||||||
|
@timeout(int(os.environ.get("COMPONENT_EXEC_TIMEOUT", 10*60)))
|
||||||
|
def _invoke(self, **kwargs):
|
||||||
|
if not isinstance(self._param.variables,list):
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
for item in self._param.variables:
|
||||||
|
variable=item["variable"]
|
||||||
|
operator=item["operator"]
|
||||||
|
parameter=item["parameter"]
|
||||||
|
variable_value=self._canvas.get_variable_value(variable)
|
||||||
|
new_variable=self._operate(variable_value,operator,parameter)
|
||||||
|
self._canvas.set_variable_value(variable,new_variable)
|
||||||
|
|
||||||
|
def _operate(self,variable,operator,parameter):
|
||||||
|
if operator == "overwrite":
|
||||||
|
return self._overwrite(parameter)
|
||||||
|
elif operator == "clear":
|
||||||
|
return self._clear(variable)
|
||||||
|
elif operator == "set":
|
||||||
|
return self._set(variable,parameter)
|
||||||
|
elif operator == "append":
|
||||||
|
return self._append(variable,parameter)
|
||||||
|
elif operator == "extend":
|
||||||
|
return self._extend(variable,parameter)
|
||||||
|
elif operator == "remove_first":
|
||||||
|
return self._remove_first(variable)
|
||||||
|
elif operator == "remove_last":
|
||||||
|
return self._remove_last(variable)
|
||||||
|
elif operator == "+=":
|
||||||
|
return self._add(variable,parameter)
|
||||||
|
elif operator == "-=":
|
||||||
|
return self._subtract(variable,parameter)
|
||||||
|
elif operator == "*=":
|
||||||
|
return self._multiply(variable,parameter)
|
||||||
|
elif operator == "/=":
|
||||||
|
return self._divide(variable,parameter)
|
||||||
|
else:
|
||||||
|
return
|
||||||
|
|
||||||
|
def _overwrite(self,parameter):
|
||||||
|
return self._canvas.get_variable_value(parameter)
|
||||||
|
|
||||||
|
def _clear(self,variable):
|
||||||
|
if isinstance(variable,list):
|
||||||
|
return []
|
||||||
|
elif isinstance(variable,str):
|
||||||
|
return ""
|
||||||
|
elif isinstance(variable,dict):
|
||||||
|
return {}
|
||||||
|
elif isinstance(variable,int):
|
||||||
|
return 0
|
||||||
|
elif isinstance(variable,float):
|
||||||
|
return 0.0
|
||||||
|
elif isinstance(variable,bool):
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def _set(self,variable,parameter):
|
||||||
|
if variable is None:
|
||||||
|
return self._canvas.get_value_with_variable(parameter)
|
||||||
|
elif isinstance(variable,str):
|
||||||
|
return self._canvas.get_value_with_variable(parameter)
|
||||||
|
elif isinstance(variable,bool):
|
||||||
|
return parameter
|
||||||
|
elif isinstance(variable,int):
|
||||||
|
return parameter
|
||||||
|
elif isinstance(variable,float):
|
||||||
|
return parameter
|
||||||
|
else:
|
||||||
|
return parameter
|
||||||
|
|
||||||
|
def _append(self,variable,parameter):
|
||||||
|
parameter=self._canvas.get_variable_value(parameter)
|
||||||
|
if variable is None:
|
||||||
|
variable=[]
|
||||||
|
if not isinstance(variable,list):
|
||||||
|
return "ERROR:VARIABLE_NOT_LIST"
|
||||||
|
elif len(variable)!=0 and not isinstance(parameter,type(variable[0])):
|
||||||
|
return "ERROR:PARAMETER_NOT_LIST_ELEMENT_TYPE"
|
||||||
|
else:
|
||||||
|
return variable+parameter
|
||||||
|
|
||||||
|
def _extend(self,variable,parameter):
|
||||||
|
parameter=self._canvas.get_variable_value(parameter)
|
||||||
|
if variable is None:
|
||||||
|
variable=[]
|
||||||
|
if not isinstance(variable,list):
|
||||||
|
return "ERROR:VARIABLE_NOT_LIST"
|
||||||
|
elif not isinstance(parameter,list):
|
||||||
|
return "ERROR:PARAMETER_NOT_LIST"
|
||||||
|
elif len(variable)!=0 and len(parameter)!=0 and not isinstance(parameter[0],type(variable[0])):
|
||||||
|
return "ERROR:PARAMETER_NOT_LIST_ELEMENT_TYPE"
|
||||||
|
else:
|
||||||
|
return variable+parameter
|
||||||
|
|
||||||
|
def _remove_first(self,variable):
|
||||||
|
if len(variable)==0:
|
||||||
|
return variable
|
||||||
|
if not isinstance(variable,list):
|
||||||
|
return "ERROR:VARIABLE_NOT_LIST"
|
||||||
|
else:
|
||||||
|
return variable[1:]
|
||||||
|
|
||||||
|
def _remove_last(self,variable):
|
||||||
|
if len(variable)==0:
|
||||||
|
return variable
|
||||||
|
if not isinstance(variable,list):
|
||||||
|
return "ERROR:VARIABLE_NOT_LIST"
|
||||||
|
else:
|
||||||
|
return variable[:-1]
|
||||||
|
|
||||||
|
|
||||||
|
def is_number(self, value):
|
||||||
|
if isinstance(value, bool):
|
||||||
|
return False
|
||||||
|
return isinstance(value, numbers.Number)
|
||||||
|
|
||||||
|
def _add(self,variable,parameter):
|
||||||
|
if self.is_number(variable) and self.is_number(parameter):
|
||||||
|
return variable+parameter
|
||||||
|
else:
|
||||||
|
return "ERROR:VARIABLE_NOT_NUMBER or PARAMETER_NOT_NUMBER"
|
||||||
|
|
||||||
|
def _subtract(self,variable,parameter):
|
||||||
|
if self.is_number(variable) and self.is_number(parameter):
|
||||||
|
return variable-parameter
|
||||||
|
else:
|
||||||
|
return "ERROR:VARIABLE_NOT_NUMBER or PARAMETER_NOT_NUMBER"
|
||||||
|
|
||||||
|
def _multiply(self,variable,parameter):
|
||||||
|
if self.is_number(variable) and self.is_number(parameter):
|
||||||
|
return variable*parameter
|
||||||
|
else:
|
||||||
|
return "ERROR:VARIABLE_NOT_NUMBER or PARAMETER_NOT_NUMBER"
|
||||||
|
|
||||||
|
def _divide(self,variable,parameter):
|
||||||
|
if self.is_number(variable) and self.is_number(parameter):
|
||||||
|
if parameter==0:
|
||||||
|
return "ERROR:DIVIDE_BY_ZERO"
|
||||||
|
else:
|
||||||
|
return variable/parameter
|
||||||
|
else:
|
||||||
|
return "ERROR:VARIABLE_NOT_NUMBER or PARAMETER_NOT_NUMBER"
|
||||||
Reference in New Issue
Block a user