mirror of
https://github.com/langgenius/dify.git
synced 2026-03-04 23:36:20 +08:00
112 lines
4.8 KiB
Python
112 lines
4.8 KiB
Python
from collections.abc import Mapping, Sequence
|
|
from typing import TYPE_CHECKING, Any
|
|
|
|
from dify_graph.constants import CONVERSATION_VARIABLE_NODE_ID
|
|
from dify_graph.entities import GraphInitParams
|
|
from dify_graph.enums import NodeType, WorkflowNodeExecutionStatus
|
|
from dify_graph.node_events import NodeRunResult
|
|
from dify_graph.nodes.base.node import Node
|
|
from dify_graph.nodes.variable_assigner.common import helpers as common_helpers
|
|
from dify_graph.nodes.variable_assigner.common.exc import VariableOperatorNodeError
|
|
from dify_graph.variables import SegmentType, VariableBase
|
|
|
|
from .node_data import VariableAssignerData, WriteMode
|
|
|
|
if TYPE_CHECKING:
|
|
from dify_graph.runtime import GraphRuntimeState
|
|
|
|
|
|
class VariableAssignerNode(Node[VariableAssignerData]):
|
|
node_type = NodeType.VARIABLE_ASSIGNER
|
|
|
|
def __init__(
|
|
self,
|
|
id: str,
|
|
config: Mapping[str, Any],
|
|
graph_init_params: "GraphInitParams",
|
|
graph_runtime_state: "GraphRuntimeState",
|
|
):
|
|
super().__init__(
|
|
id=id,
|
|
config=config,
|
|
graph_init_params=graph_init_params,
|
|
graph_runtime_state=graph_runtime_state,
|
|
)
|
|
|
|
def blocks_variable_output(self, variable_selectors: set[tuple[str, ...]]) -> bool:
|
|
"""
|
|
Check if this Variable Assigner node blocks the output of specific variables.
|
|
|
|
Returns True if this node updates any of the requested conversation variables.
|
|
"""
|
|
assigned_selector = tuple(self.node_data.assigned_variable_selector)
|
|
return assigned_selector in variable_selectors
|
|
|
|
@classmethod
|
|
def version(cls) -> str:
|
|
return "1"
|
|
|
|
@classmethod
|
|
def _extract_variable_selector_to_variable_mapping(
|
|
cls,
|
|
*,
|
|
graph_config: Mapping[str, Any],
|
|
node_id: str,
|
|
node_data: Mapping[str, Any],
|
|
) -> Mapping[str, Sequence[str]]:
|
|
# Create typed NodeData from dict
|
|
typed_node_data = VariableAssignerData.model_validate(node_data)
|
|
|
|
mapping = {}
|
|
assigned_variable_node_id = typed_node_data.assigned_variable_selector[0]
|
|
if assigned_variable_node_id == CONVERSATION_VARIABLE_NODE_ID:
|
|
selector_key = ".".join(typed_node_data.assigned_variable_selector)
|
|
key = f"{node_id}.#{selector_key}#"
|
|
mapping[key] = typed_node_data.assigned_variable_selector
|
|
|
|
selector_key = ".".join(typed_node_data.input_variable_selector)
|
|
key = f"{node_id}.#{selector_key}#"
|
|
mapping[key] = typed_node_data.input_variable_selector
|
|
return mapping
|
|
|
|
def _run(self) -> NodeRunResult:
|
|
assigned_variable_selector = self.node_data.assigned_variable_selector
|
|
# Should be String, Number, Object, ArrayString, ArrayNumber, ArrayObject
|
|
original_variable = self.graph_runtime_state.variable_pool.get(assigned_variable_selector)
|
|
if not isinstance(original_variable, VariableBase):
|
|
raise VariableOperatorNodeError("assigned variable not found")
|
|
|
|
match self.node_data.write_mode:
|
|
case WriteMode.OVER_WRITE:
|
|
income_value = self.graph_runtime_state.variable_pool.get(self.node_data.input_variable_selector)
|
|
if not income_value:
|
|
raise VariableOperatorNodeError("input value not found")
|
|
updated_variable = original_variable.model_copy(update={"value": income_value.value})
|
|
|
|
case WriteMode.APPEND:
|
|
income_value = self.graph_runtime_state.variable_pool.get(self.node_data.input_variable_selector)
|
|
if not income_value:
|
|
raise VariableOperatorNodeError("input value not found")
|
|
updated_value = original_variable.value + [income_value.value]
|
|
updated_variable = original_variable.model_copy(update={"value": updated_value})
|
|
|
|
case WriteMode.CLEAR:
|
|
income_value = SegmentType.get_zero_value(original_variable.value_type)
|
|
updated_variable = original_variable.model_copy(update={"value": income_value.to_object()})
|
|
|
|
# Over write the variable.
|
|
self.graph_runtime_state.variable_pool.add(assigned_variable_selector, updated_variable)
|
|
|
|
updated_variables = [common_helpers.variable_to_processed_data(assigned_variable_selector, updated_variable)]
|
|
return NodeRunResult(
|
|
status=WorkflowNodeExecutionStatus.SUCCEEDED,
|
|
inputs={
|
|
"value": income_value.to_object(),
|
|
},
|
|
# NOTE(QuantumGhost): although only one variable is updated in `v1.VariableAssignerNode`,
|
|
# we still set `output_variables` as a list to ensure the schema of output is
|
|
# compatible with `v2.VariableAssignerNode`.
|
|
process_data=common_helpers.set_updated_variables({}, updated_variables),
|
|
outputs={},
|
|
)
|