mirror of
https://github.com/langgenius/dify.git
synced 2026-03-04 15:26:21 +08:00
148 lines
5.7 KiB
Python
148 lines
5.7 KiB
Python
"""
|
|
Domain entities for workflow node execution.
|
|
|
|
This module contains the domain model for workflow node execution, which is used
|
|
by the core workflow module. These models are independent of the storage mechanism
|
|
and don't contain implementation details like tenant_id, app_id, etc.
|
|
"""
|
|
|
|
from collections.abc import Mapping
|
|
from datetime import datetime
|
|
from typing import Any
|
|
|
|
from pydantic import BaseModel, Field, PrivateAttr
|
|
|
|
from dify_graph.enums import NodeType, WorkflowNodeExecutionMetadataKey, WorkflowNodeExecutionStatus
|
|
|
|
|
|
class WorkflowNodeExecution(BaseModel):
|
|
"""
|
|
Domain model for workflow node execution.
|
|
|
|
This model represents the core business entity of a node execution,
|
|
without implementation details like tenant_id, app_id, etc.
|
|
|
|
Note: User/context-specific fields (triggered_from, created_by, created_by_role)
|
|
have been moved to the repository implementation to keep the domain model clean.
|
|
These fields are still accepted in the constructor for backward compatibility,
|
|
but they are not stored in the model.
|
|
"""
|
|
|
|
# --------- Core identification fields ---------
|
|
|
|
# Unique identifier for this execution record, used when persisting to storage.
|
|
# Value is a UUID string (e.g., '09b3e04c-f9ae-404c-ad82-290b8d7bd382').
|
|
id: str
|
|
|
|
# Optional secondary ID for cross-referencing purposes.
|
|
#
|
|
# NOTE: For referencing the persisted record, use `id` rather than `node_execution_id`.
|
|
# While `node_execution_id` may sometimes be a UUID string, this is not guaranteed.
|
|
# In most scenarios, `id` should be used as the primary identifier.
|
|
node_execution_id: str | None = None
|
|
workflow_id: str # ID of the workflow this node belongs to
|
|
workflow_execution_id: str | None = None # ID of the specific workflow run (null for single-step debugging)
|
|
# --------- Core identification fields ends ---------
|
|
|
|
# Execution positioning and flow
|
|
index: int # Sequence number for ordering in trace visualization
|
|
predecessor_node_id: str | None = None # ID of the node that executed before this one
|
|
node_id: str # ID of the node being executed
|
|
node_type: NodeType # Type of node (e.g., start, llm, knowledge)
|
|
title: str # Display title of the node
|
|
|
|
# Execution data
|
|
# The `inputs` and `outputs` fields hold the full content
|
|
inputs: Mapping[str, Any] | None = None # Input variables used by this node
|
|
process_data: Mapping[str, Any] | None = None # Intermediate processing data
|
|
outputs: Mapping[str, Any] | None = None # Output variables produced by this node
|
|
|
|
# Execution state
|
|
status: WorkflowNodeExecutionStatus = WorkflowNodeExecutionStatus.RUNNING # Current execution status
|
|
error: str | None = None # Error message if execution failed
|
|
elapsed_time: float = Field(default=0.0) # Time taken for execution in seconds
|
|
|
|
# Additional metadata
|
|
metadata: Mapping[WorkflowNodeExecutionMetadataKey, Any] | None = None # Execution metadata (tokens, cost, etc.)
|
|
|
|
# Timing information
|
|
created_at: datetime # When execution started
|
|
finished_at: datetime | None = None # When execution completed
|
|
|
|
_truncated_inputs: Mapping[str, Any] | None = PrivateAttr(None)
|
|
_truncated_outputs: Mapping[str, Any] | None = PrivateAttr(None)
|
|
_truncated_process_data: Mapping[str, Any] | None = PrivateAttr(None)
|
|
|
|
def get_truncated_inputs(self) -> Mapping[str, Any] | None:
|
|
return self._truncated_inputs
|
|
|
|
def get_truncated_outputs(self) -> Mapping[str, Any] | None:
|
|
return self._truncated_outputs
|
|
|
|
def get_truncated_process_data(self) -> Mapping[str, Any] | None:
|
|
return self._truncated_process_data
|
|
|
|
def set_truncated_inputs(self, truncated_inputs: Mapping[str, Any] | None):
|
|
self._truncated_inputs = truncated_inputs
|
|
|
|
def set_truncated_outputs(self, truncated_outputs: Mapping[str, Any] | None):
|
|
self._truncated_outputs = truncated_outputs
|
|
|
|
def set_truncated_process_data(self, truncated_process_data: Mapping[str, Any] | None):
|
|
self._truncated_process_data = truncated_process_data
|
|
|
|
def get_response_inputs(self) -> Mapping[str, Any] | None:
|
|
inputs = self.get_truncated_inputs()
|
|
if inputs:
|
|
return inputs
|
|
return self.inputs
|
|
|
|
@property
|
|
def inputs_truncated(self):
|
|
return self._truncated_inputs is not None
|
|
|
|
@property
|
|
def outputs_truncated(self):
|
|
return self._truncated_outputs is not None
|
|
|
|
@property
|
|
def process_data_truncated(self):
|
|
return self._truncated_process_data is not None
|
|
|
|
def get_response_outputs(self) -> Mapping[str, Any] | None:
|
|
outputs = self.get_truncated_outputs()
|
|
if outputs is not None:
|
|
return outputs
|
|
return self.outputs
|
|
|
|
def get_response_process_data(self) -> Mapping[str, Any] | None:
|
|
process_data = self.get_truncated_process_data()
|
|
if process_data is not None:
|
|
return process_data
|
|
return self.process_data
|
|
|
|
def update_from_mapping(
|
|
self,
|
|
inputs: Mapping[str, Any] | None = None,
|
|
process_data: Mapping[str, Any] | None = None,
|
|
outputs: Mapping[str, Any] | None = None,
|
|
metadata: Mapping[WorkflowNodeExecutionMetadataKey, Any] | None = None,
|
|
):
|
|
"""
|
|
Update the model from mappings.
|
|
|
|
Args:
|
|
inputs: The inputs to update
|
|
process_data: The process data to update
|
|
outputs: The outputs to update
|
|
metadata: The metadata to update
|
|
"""
|
|
if inputs is not None:
|
|
self.inputs = dict(inputs)
|
|
if process_data is not None:
|
|
self.process_data = dict(process_data)
|
|
if outputs is not None:
|
|
self.outputs = dict(outputs)
|
|
if metadata is not None:
|
|
self.metadata = dict(metadata)
|