-
Notifications
You must be signed in to change notification settings - Fork 2.6k
feat: Variable aggregation node #4246
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,42 @@ | ||
| # coding=utf-8 | ||
|
|
||
| from typing import Type | ||
|
|
||
| from django.utils.translation import gettext_lazy as _ | ||
| from rest_framework import serializers | ||
|
|
||
| from application.flow.i_step_node import INode, NodeResult | ||
|
|
||
|
|
||
|
|
||
|
|
||
| class VariableListSerializer(serializers.Serializer): | ||
| v_id = serializers.CharField(required=True, label=_("Variable id")) | ||
| variable = serializers.ListField(required=True, label=_("Variable")) | ||
|
|
||
|
|
||
| class VariableGroupSerializer(serializers.Serializer): | ||
| id = serializers.CharField(required=True, label=_("Group id")) | ||
| group_name = serializers.CharField(required=True, label=_("group_name")) | ||
| variable_list = VariableListSerializer(many=True) | ||
|
|
||
|
|
||
| class VariableAggregationNodeSerializer(serializers.Serializer): | ||
| strategy = serializers.CharField(required=True, label=_("Strategy")) | ||
| group_list = VariableGroupSerializer(many=True) | ||
|
|
||
|
|
||
| class IVariableAggregation(INode): | ||
| type = 'variable-aggregation-node' | ||
|
|
||
|
|
||
| def get_node_params_serializer_class(self) -> Type[serializers.Serializer]: | ||
| return VariableAggregationNodeSerializer | ||
|
|
||
| def _run(self): | ||
| return self.execute(**self.node_params_serializer.data, **self.flow_params_serializer.data) | ||
|
|
||
| def execute(self,strategy,group_list,**kwargs) -> NodeResult: | ||
| pass | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,54 @@ | ||
| #coding=utf-8 | ||
| """ | ||
| @project: MaxKB | ||
| @Author:虎² | ||
| @file: base_variable_aggregation_node.py | ||
| @date:2025/10/23 17:42 | ||
| @desc: | ||
| """ | ||
| from application.flow.i_step_node import NodeResult | ||
| from application.flow.step_node.variable_aggregation_node.i_variable_aggregation_node import IVariableAggregation | ||
|
|
||
|
|
||
| class BaseVariableAggregationNode(IVariableAggregation): | ||
|
|
||
| def save_context(self, details, workflow_manage): | ||
| for key, value in details.get('result').items(): | ||
| self.context['key'] = value | ||
| self.context['result'] = details.get('result') | ||
|
|
||
| def get_first_non_null(self, variable_list): | ||
|
|
||
| for variable in variable_list: | ||
| v = self.workflow_manage.get_reference_field( | ||
| variable.get('variable')[0], | ||
| variable.get('variable')[1:]) | ||
| if v is not None: | ||
| return v | ||
| return None | ||
|
|
||
| def set_variable_to_json(self, variable_list): | ||
|
|
||
| return {variable.get('variable')[1:][0]: self.workflow_manage.get_reference_field( | ||
| variable.get('variable')[0], | ||
| variable.get('variable')[1:]) for variable in variable_list} | ||
|
|
||
| def execute(self,strategy,group_list,**kwargs) -> NodeResult: | ||
| strategy_map = {'first_non_null':self.get_first_non_null, | ||
| 'variable_to_json': self.set_variable_to_json, | ||
| } | ||
|
|
||
| result = { item.get('group_name'):strategy_map[strategy](item.get('variable_list')) for item in group_list} | ||
|
|
||
| return NodeResult({'result': result,**result},{}) | ||
|
|
||
| def get_details(self, index: int, **kwargs): | ||
| return { | ||
| 'name': self.node.properties.get('stepName'), | ||
| "index": index, | ||
| 'run_time': self.context.get('run_time'), | ||
| 'type': self.node.type, | ||
| 'result': self.context.get('result'), | ||
| 'status': self.status, | ||
| 'err_message': self.err_message | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -263,6 +263,15 @@ You are a master of problem optimization, adept at accurately inferring user int | |
| variableAggregationNode: { | ||
| label: 'Variable Aggregation', | ||
| text: 'Perform aggregation processing on the outputs of multiple branches', | ||
| Strategy: 'Aggregation Strategy', | ||
| placeholder: 'Return the first non-null value of each group', | ||
| placeholder1: 'Structurally aggregate each group of variables', | ||
| group: { | ||
| placeholder: 'Please select a variable', | ||
| noneError: 'Name cannot be empty', | ||
| dupError: 'Name cannot be duplicated', | ||
| }, | ||
| add: 'Add Group', | ||
| }, | ||
| mcpNode: { | ||
| label: 'MCP Node', | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The provided code snippet appears to be part of a configuration file for a software interface that manages different types of nodes used in processing data pipelines. Here's a brief review of the changes and potential optimizations:
Overall, these additions provide additional functionality and clarify the purpose behind each feature. However, there isn't enough information in the given code sample about how these features interact with other parts of the system or any specific performance requirements for efficiency. If you're looking for further optimization suggestions based on typical practices for such interfaces, consider the following general tips:
For production-ready applications, integrating user feedback mechanisms and ensuring robust testing will also be important steps. |
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall, the code looks well-structured and follows Django Rest Framework conventions. However, there are a few areas where improvements can be made:
Docstring for Methods: You have docstrings in all classes but no documentation strings (like
__doc__) for each method. It would be helpful to add brief descriptions for methods that describe what they do.Error Handling: While not explicitly shown here, it's generally good practice to implement error handling across different parts of your application to make it more robust against unexpected inputs or failures during execution.
Type Hints on Arguments: The use of type hints is present within the serializer classes and elsewhere in the code, which is a good approach. Make sure that these are consistent throughout, including function parameters and class variables.
Class Names: Class names follow best practices, such as using meaningful and descriptive names like
IVariableAggregationinstead of generic ones likeINode.Method Naming: Method names should typically start with lowercase letters followed by underscores if they aren't functions (as they appear). Consider renaming
_runto something more explicit, perhaps likeprocess, depending on its intended functionality.Code Style: Ensure consistency in indentation and spacing across the file. This makes the code easier to read and maintain.
Documentation: Add detailed comments at key points in the code, especially around complex logic or data flow. Use Markdown formatting within docstrings where appropriate.
With these considerations addressed, your code will be cleaner, safer, and easier to understand. Here’s an example of how some specific parts could benefit from additional context:
Each class now has a comprehensive docstring describing its purpose, fields, and methods, enhancing understanding among developers who may work with or contribute to the codebase.