Files
ragflow/agent/component/variable_aggregator.py
T

93 lines
3.6 KiB
Python

#
# 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.
import os
from typing import Any
from agent.component.base import ComponentBase, ComponentParamBase
from common.connection_utils import timeout
class VariableAggregatorParam(ComponentParamBase):
"""
Parameters for VariableAggregator
- groups: list of dicts {"group_name": str, "variables": [variable selectors]}
"""
def __init__(self):
super().__init__()
# each group expects: {"group_name": str, "variables": List[str]}
self.groups = []
def check(self):
self.check_empty(self.groups, "[VariableAggregator] groups")
for g in self.groups:
if not g.get("group_name"):
raise ValueError("[VariableAggregator] group_name can not be empty!")
if not g.get("variables"):
raise ValueError(f"[VariableAggregator] variables of group `{g.get('group_name')}` can not be empty")
if not isinstance(g.get("variables"), list):
raise TypeError(f"[VariableAggregator] variables of group `{g.get('group_name')}` should be a list of strings")
def get_input_form(self) -> dict[str, dict]:
return {
"variables": {
"name": "Variables",
"type": "list",
}
}
class VariableAggregator(ComponentBase):
component_name = "VariableAggregator"
def param_refs(self) -> list[str]:
return [selector.get("value") if isinstance(selector, dict) else selector for group in self._param.groups for selector in group.get("variables", [])]
@timeout(int(os.environ.get("COMPONENT_EXEC_TIMEOUT", "3")))
def _invoke(self, **kwargs):
# Group mode: for each group, pick the first available variable
for group in self._param.groups:
gname = group.get("group_name")
# record candidate selectors within this group
self.set_input_value(f"{gname}.variables", list(group.get("variables", [])))
for selector in group.get("variables", []):
# Selectors may be {"value": ref} dicts (UI form) or plain
# reference strings (SDK/API-built canvases); param_refs
# already accepts both, so resolve them the same way here.
ref = selector.get("value") if isinstance(selector, dict) else selector
if not isinstance(ref, str):
continue
ref = ref.strip("{}").strip()
if not ref:
continue
val = self._canvas.get_variable_value(ref)
if val:
self.set_output(gname, val)
break
@staticmethod
def _to_object(value: Any) -> Any:
# Try to convert value to serializable object if it has to_object()
try:
return value.to_object() # type: ignore[attr-defined]
except (AttributeError, TypeError):
return value
def thoughts(self) -> str:
return "Aggregating variables from canvas and grouping as configured."