diff --git a/api/core/workflow/nodes/agent/agent_node.py b/api/core/workflow/nodes/agent/agent_node.py index fa912d5035..fc2ad2702d 100644 --- a/api/core/workflow/nodes/agent/agent_node.py +++ b/api/core/workflow/nodes/agent/agent_node.py @@ -579,7 +579,7 @@ class AgentNode(Node): for key, value in msg_metadata.items() if key in WorkflowNodeExecutionMetadataKey.__members__.values() } - if message.message.json_object is not None: + if message.message.json_object: json_list.append(message.message.json_object) elif message.type == ToolInvokeMessage.MessageType.LINK: assert isinstance(message.message, ToolInvokeMessage.TextMessage) diff --git a/api/core/workflow/nodes/base/entities.py b/api/core/workflow/nodes/base/entities.py index 5503ea7519..fd2eb68dc0 100644 --- a/api/core/workflow/nodes/base/entities.py +++ b/api/core/workflow/nodes/base/entities.py @@ -73,9 +73,6 @@ class DefaultValue(BaseModel): @model_validator(mode="after") def validate_value_type(self) -> "DefaultValue": - if self.type is None: - raise DefaultValueTypeError("type field is required") - # Type validation configuration type_validators = { DefaultValueType.STRING: { diff --git a/api/core/workflow/nodes/code/code_node.py b/api/core/workflow/nodes/code/code_node.py index 624b71028a..61820cc700 100644 --- a/api/core/workflow/nodes/code/code_node.py +++ b/api/core/workflow/nodes/code/code_node.py @@ -108,8 +108,6 @@ class CodeNode(Node): """ if value is None: return None - if not isinstance(value, str): - raise OutputValidationError(f"Output variable `{variable}` must be a string") if len(value) > dify_config.CODE_MAX_STRING_LENGTH: raise OutputValidationError( @@ -122,8 +120,6 @@ class CodeNode(Node): def _check_boolean(self, value: bool | None, variable: str) -> bool | None: if value is None: return None - if not isinstance(value, bool): - raise OutputValidationError(f"Output variable `{variable}` must be a boolean") return value @@ -136,8 +132,6 @@ class CodeNode(Node): """ if value is None: return None - if not isinstance(value, int | float): - raise OutputValidationError(f"Output variable `{variable}` must be a number") if value > dify_config.CODE_MAX_NUMBER or value < dify_config.CODE_MIN_NUMBER: raise OutputValidationError( diff --git a/api/core/workflow/nodes/http_request/executor.py b/api/core/workflow/nodes/http_request/executor.py index ed48bc6484..a36a0a9d98 100644 --- a/api/core/workflow/nodes/http_request/executor.py +++ b/api/core/workflow/nodes/http_request/executor.py @@ -263,8 +263,6 @@ class Executor: if authorization.config is None: raise AuthorizationConfigError("authorization config is required") - if self.auth.config.api_key is None: - raise AuthorizationConfigError("api_key is required") if not authorization.config.header: authorization.config.header = "Authorization" @@ -409,30 +407,22 @@ class Executor: if self.files and not all(f[0] == "__multipart_placeholder__" for f in self.files): for file_entry in self.files: # file_entry should be (key, (filename, content, mime_type)), but handle edge cases - if len(file_entry) != 2 or not isinstance(file_entry[1], tuple) or len(file_entry[1]) < 2: + if len(file_entry) != 2 or len(file_entry[1]) < 2: continue # skip malformed entries key = file_entry[0] content = file_entry[1][1] body_string += f"--{boundary}\r\n" body_string += f'Content-Disposition: form-data; name="{key}"\r\n\r\n' # decode content safely - if isinstance(content, bytes): - try: - body_string += content.decode("utf-8") - except UnicodeDecodeError: - body_string += content.decode("utf-8", errors="replace") - elif isinstance(content, str): - body_string += content - else: - body_string += f"[Unsupported content type: {type(content).__name__}]" + try: + body_string += content.decode("utf-8") + except UnicodeDecodeError: + body_string += content.decode("utf-8", errors="replace") body_string += "\r\n" body_string += f"--{boundary}--\r\n" elif self.node_data.body: if self.content: - if isinstance(self.content, str): - body_string = self.content - elif isinstance(self.content, bytes): - body_string = self.content.decode("utf-8", errors="replace") + body_string = self.content.decode("utf-8", errors="replace") elif self.data and self.node_data.body.type == "x-www-form-urlencoded": body_string = urlencode(self.data) elif self.data and self.node_data.body.type == "form-data": diff --git a/api/core/workflow/nodes/list_operator/node.py b/api/core/workflow/nodes/list_operator/node.py index 05197aafa5..96220b635b 100644 --- a/api/core/workflow/nodes/list_operator/node.py +++ b/api/core/workflow/nodes/list_operator/node.py @@ -170,27 +170,21 @@ class ListOperatorNode(Node): ) result = list(filter(filter_func, variable.value)) variable = variable.model_copy(update={"value": result}) - elif isinstance(variable, ArrayBooleanSegment): - if not isinstance(condition.value, bool): - raise InvalidFilterValueError(f"Invalid filter value: {condition.value}") + else: filter_func = _get_boolean_filter_func(condition=condition.comparison_operator, value=condition.value) result = list(filter(filter_func, variable.value)) variable = variable.model_copy(update={"value": result}) - else: - raise AssertionError("this statment should be unreachable.") return variable def _apply_order(self, variable: _SUPPORTED_TYPES_ALIAS) -> _SUPPORTED_TYPES_ALIAS: if isinstance(variable, (ArrayStringSegment, ArrayNumberSegment, ArrayBooleanSegment)): - result = sorted(variable.value, reverse=self._node_data.order_by == Order.DESC) + result = sorted(variable.value, reverse=self._node_data.order_by.value == Order.DESC) variable = variable.model_copy(update={"value": result}) - elif isinstance(variable, ArrayFileSegment): + else: result = _order_file( order=self._node_data.order_by.value, order_by=self._node_data.order_by.key, array=variable.value ) variable = variable.model_copy(update={"value": result}) - else: - raise AssertionError("this statement should be unreachable") return variable @@ -304,7 +298,7 @@ def _get_file_filter_func(*, key: str, condition: str, value: str | Sequence[str if key in {"name", "extension", "mime_type", "url"} and isinstance(value, str): extract_func = _get_file_extract_string_func(key=key) return lambda x: _get_string_filter_func(condition=condition, value=value)(extract_func(x)) - if key in {"type", "transfer_method"} and isinstance(value, Sequence): + if key in {"type", "transfer_method"}: extract_func = _get_file_extract_string_func(key=key) return lambda x: _get_sequence_filter_func(condition=condition, value=value)(extract_func(x)) elif key == "size" and isinstance(value, str): diff --git a/api/core/workflow/nodes/llm/node.py b/api/core/workflow/nodes/llm/node.py index abf2a36a35..d8cf33be18 100644 --- a/api/core/workflow/nodes/llm/node.py +++ b/api/core/workflow/nodes/llm/node.py @@ -195,9 +195,8 @@ class LLMNode(Node): generator = self._fetch_context(node_data=self._node_data) context = None for event in generator: - if isinstance(event, RunRetrieverResourceEvent): - context = event.context - yield event + context = event.context + yield event if context: node_inputs["#context#"] = context @@ -282,7 +281,7 @@ class LLMNode(Node): outputs = {"text": result_text, "usage": jsonable_encoder(usage), "finish_reason": finish_reason} if structured_output: outputs["structured_output"] = structured_output.structured_output - if self._file_outputs is not None: + if self._file_outputs: outputs["files"] = ArrayFileSegment(value=self._file_outputs) # Send final chunk event to indicate streaming is complete @@ -827,9 +826,7 @@ class LLMNode(Node): prompt_template = typed_node_data.prompt_template variable_selectors = [] - if isinstance(prompt_template, list) and all( - isinstance(prompt, LLMNodeChatModelMessage) for prompt in prompt_template - ): + if isinstance(prompt_template, list): for prompt in prompt_template: if prompt.edition_type != "jinja2": variable_template_parser = VariableTemplateParser(template=prompt.text) @@ -1063,7 +1060,7 @@ class LLMNode(Node): return if isinstance(contents, str): yield contents - elif isinstance(contents, list): + else: for item in contents: if isinstance(item, TextPromptMessageContent): yield item.data @@ -1077,9 +1074,6 @@ class LLMNode(Node): else: logger.warning("unknown item type encountered, type=%s", type(item)) yield str(item) - else: - logger.warning("unknown contents type encountered, type=%s", type(contents)) - yield str(contents) @property def retry(self) -> bool: diff --git a/api/core/workflow/nodes/parameter_extractor/entities.py b/api/core/workflow/nodes/parameter_extractor/entities.py index 4e93cd9688..cb221d39e6 100644 --- a/api/core/workflow/nodes/parameter_extractor/entities.py +++ b/api/core/workflow/nodes/parameter_extractor/entities.py @@ -31,8 +31,6 @@ _VALID_PARAMETER_TYPES = frozenset( def _validate_type(parameter_type: str) -> SegmentType: - if not isinstance(parameter_type, str): - raise TypeError(f"type should be str, got {type(parameter_type)}, value={parameter_type}") if parameter_type not in _VALID_PARAMETER_TYPES: raise ValueError(f"type {parameter_type} is not allowd to use in Parameter Extractor node.") diff --git a/api/core/workflow/nodes/parameter_extractor/parameter_extractor_node.py b/api/core/workflow/nodes/parameter_extractor/parameter_extractor_node.py index 648ea69936..445fe364ff 100644 --- a/api/core/workflow/nodes/parameter_extractor/parameter_extractor_node.py +++ b/api/core/workflow/nodes/parameter_extractor/parameter_extractor_node.py @@ -10,7 +10,7 @@ from core.file import File from core.memory.token_buffer_memory import TokenBufferMemory from core.model_manager import ModelInstance from core.model_runtime.entities import ImagePromptMessageContent -from core.model_runtime.entities.llm_entities import LLMResult, LLMUsage +from core.model_runtime.entities.llm_entities import LLMUsage from core.model_runtime.entities.message_entities import ( AssistantPromptMessage, PromptMessage, @@ -38,7 +38,6 @@ from factories.variable_factory import build_segment_with_type from .entities import ParameterExtractorNodeData from .exc import ( - InvalidInvokeResultError, InvalidModelModeError, InvalidModelTypeError, InvalidNumberOfParametersError, @@ -304,8 +303,6 @@ class ParameterExtractorNode(Node): ) # handle invoke result - if not isinstance(invoke_result, LLMResult): - raise InvalidInvokeResultError(f"Invalid invoke result: {invoke_result}") text = invoke_result.message.content or "" if not isinstance(text, str): @@ -317,9 +314,6 @@ class ParameterExtractorNode(Node): # deduct quota llm_utils.deduct_llm_quota(tenant_id=self.tenant_id, model_instance=model_instance, usage=usage) - if text is None: - text = "" - return text, usage, tool_call def _generate_function_call_prompt( @@ -583,8 +577,6 @@ class ParameterExtractorNode(Node): return int(value) elif isinstance(value, (int, float)): return value - elif not isinstance(value, str): - return None if "." in value: try: return float(value) @@ -697,7 +689,7 @@ class ParameterExtractorNode(Node): for parameter in data.parameters: if parameter.type == "number": result[parameter.name] = 0 - elif parameter.type == "bool": + elif parameter.type == "boolean": result[parameter.name] = False elif parameter.type in {"string", "select"}: result[parameter.name] = "" diff --git a/api/core/workflow/nodes/tool/tool_node.py b/api/core/workflow/nodes/tool/tool_node.py index 9708edcb38..63d7a0eea5 100644 --- a/api/core/workflow/nodes/tool/tool_node.py +++ b/api/core/workflow/nodes/tool/tool_node.py @@ -323,7 +323,7 @@ class ToolNode(Node): elif message.type == ToolInvokeMessage.MessageType.JSON: assert isinstance(message.message, ToolInvokeMessage.JsonMessage) # JSON message handling for tool node - if message.message.json_object is not None: + if message.message.json_object: json.append(message.message.json_object) elif message.type == ToolInvokeMessage.MessageType.LINK: assert isinstance(message.message, ToolInvokeMessage.TextMessage) diff --git a/api/core/workflow/nodes/variable_assigner/v1/node.py b/api/core/workflow/nodes/variable_assigner/v1/node.py index 1c7baf3a18..9b3a7c61f7 100644 --- a/api/core/workflow/nodes/variable_assigner/v1/node.py +++ b/api/core/workflow/nodes/variable_assigner/v1/node.py @@ -117,12 +117,8 @@ class VariableAssignerNode(Node): case WriteMode.CLEAR: income_value = get_zero_value(original_variable.value_type) - if income_value is None: - raise VariableOperatorNodeError("income value not found") updated_variable = original_variable.model_copy(update={"value": income_value.to_object()}) - case _: - raise VariableOperatorNodeError(f"unsupported write mode: {self._node_data.write_mode}") # Over write the variable. self.graph_runtime_state.variable_pool.add(assigned_variable_selector, updated_variable) diff --git a/api/core/workflow/nodes/variable_assigner/v2/helpers.py b/api/core/workflow/nodes/variable_assigner/v2/helpers.py index 324f23a900..f5490fb900 100644 --- a/api/core/workflow/nodes/variable_assigner/v2/helpers.py +++ b/api/core/workflow/nodes/variable_assigner/v2/helpers.py @@ -25,8 +25,6 @@ def is_operation_supported(*, variable_type: SegmentType, operation: Operation): # Only array variable can be appended or extended # Only array variable can have elements removed return variable_type.is_array_type() - case _: - return False def is_variable_input_supported(*, operation: Operation): diff --git a/api/core/workflow/nodes/variable_assigner/v2/node.py b/api/core/workflow/nodes/variable_assigner/v2/node.py index b863204dda..277021bc94 100644 --- a/api/core/workflow/nodes/variable_assigner/v2/node.py +++ b/api/core/workflow/nodes/variable_assigner/v2/node.py @@ -274,5 +274,3 @@ class VariableAssignerNode(Node): if not variable.value: return variable.value return variable.value[:-1] - case _: - raise OperationNotSupportedError(operation=operation, variable_type=variable.value_type)