Skip to content
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

fix: In the dialogue, the form nodes of the sub-application are not displayed as separate cards. #1821

Merged
merged 1 commit into from
Dec 11, 2024

Conversation

shaohuzhang1
Copy link
Contributor

fix: In the dialogue, the form nodes of the sub-application are not displayed as separate cards.

Copy link

f2c-ci-robot bot commented Dec 11, 2024

Adding the "do-not-merge/release-note-label-needed" label because no release-note block was detected, please follow our release note process to remove it.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository.

Copy link

f2c-ci-robot bot commented Dec 11, 2024

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:

The full list of commands accepted by this bot can be found here.

Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@shaohuzhang1 shaohuzhang1 merged commit 37c963b into main Dec 11, 2024
4 checks passed
@shaohuzhang1 shaohuzhang1 deleted the pr@main@fix_ai_chat branch December 11, 2024 11:51
@@ -181,5 +233,6 @@ def get_details(self, index: int, **kwargs):
'err_message': self.err_message,
'global_fields': global_fields,
'document_list': self.workflow_manage.document_list,
'image_list': self.workflow_manage.image_list
'image_list': self.workflow_manage.image_list,
'application_node_dict': self.context.get('application_node_dict')
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. 类和方法命名

    • BaseApplicationNode 的方法 get_answer_text 重写了接口定义,返回一个包含更详细信息的字典(例如 contextworkflow_param)。这可能不符合 INode 接口的设计,并且需要确保所有继承自该基类的方法都遵循标准。
  2. 上下文变量

    • _write_context_stream 函数中,引入了新的上下文变量 application_node_dict,但这些变量在后续调用的 reset_application_node_dict 中并没有被使用或更新。
  3. 错误处理reset_application_node_dict 方法捕获并忽略异常,虽然这是临时措施,但仍建议记录或抛出异常以便于调试。

  4. 代码格式

    • 建议添加一些空行以提高可读性;函数内部的操作逻辑可以适当分解到不同的子函数中。
  5. 参数传递

    • 考虑将某些关键参数通过方法签名明确定义,如 workflow_manage,避免隐式传递。

以下是改进后的代码示例:

# 留下修改建议,具体实施还需根据项目需求进行调整

class BaseApplicationNode(IApplicationNode):
    def get_answer_list(self) -> List[Answer] | None:
        if self.answer_text is None:
            return None
        
        # 初始化答案列表,假设每个应用节点都有自己的内容和视图类型
        application_node_dict = self.context.get('application_node_dict', {}).values()
        
        answers = []
        for app_node in application_node_dict:
            answer = Answer(app_node.get('content'), app_node.get('view_type'))
            answer.set_chat_info(runtime_node_id=self.runtime_node_id, chat_record_id=app_node['chat_record_id'])
            
            children = app_node.get('children', [])
            nested_answers = self._process_children(children, app_node['runtime_node_id'], app_node['chat_record_id'])
            answer.add_nested_answers(nested_answers)
            
            answers.append(answer)
        
        return answers
    
    def reset_application_node_dict(self, runtime_node_id, node_data=None):
        """Reset the application node dictionary for a specific runtime node."""
        if not (self.context and 'application_node_dict' in self.context):
            return
        
        # 更新特定运行时节点的应用程序节点数据
        application_node_dict = {key: val for key, val in self.context['application_node_dict'].items() 
                                if val.get('runtime_node_id') != runtime_node_id}
        
        if node_data is not None:
            found = False
            for _, data in application_node_dict.items():
                if data.get('id') == node_data['id']:
                    existing_content = data['content']
                    content_with_form_renderer = self.insert_into_content(existing_content, node_data)
                    
                    # Update the content directly or append new entries to preserve order
                    if content_with_form_renderer is None:
                        continue
                        
                    application_node_dict[node_data['id']] = {
                        'id': node_data['id'],
                        'content': content_with_form_renderer,
                        'runtime_node_id': runtime_node_id,
                        'chat_record_id': data['chat_record_id'],
                        'index': list(application_node_dict).index(val) + 1
                    }
                    found = True
                    
            if not found:
                application_node_dict[node_data['id']] = {
                    'content': '',
                    'runtime_node_id': runtime_node_id,
                    'chat_record_id': UUID(node_data['uuid']),
                    'view_type': node_data['type'],
                    'index': len(application_node_dict)
                }
                application_node_dict[node_data['id']]['content'] = self.insert_into_content(content='', data=node_data)
                
        self.context['application_node_dict'] = application_node_dict
    
    @staticmethod
    def insert_into_content(content, node_data):
        """Insert node data into existing content with HTML tag."""
        match = re.search(r'<form_rander>.*?</form_rander>', content)
        if not match:
            return None
        
        form_setting_str = match.group().replace('<form_rander>', '').replace('</form_rander>', '')
        form_setting = json.loads(form_setting_str)
        
        form_setting.update({'is_submit': True})
        form_setting.update(node_data)
        
        replaced_content = f'<form_rander>{{"{json.dumps(form_setting)}"}}</form_rander>'
        
        if '[{' in replaced_content:
            start_bracket_index = replaced_content.find('[{')
            end_bracket_index = replaced_content.rfind('}]')
            content_without_brackets = replaced_content[start_bracket_index + 2:end_bracket_index]
            
            form_setting_json = json.loads(content_without_brackets)
            form_setting['fields'][0]['options'].append(form_setting_json['fields'][0]['options'][0])
            
            return replaced_content[:-len(content_without_brackets)] + '{{{"{}"}}}}'.format(json.dumps(form_setting))
        else:
            return replaced_content
    
    def execute(self, *, workflow_manage=None):  # 明确传入 workflow_manage 参数
        if not (workflow_manage and isinstance(workflow_manage, type(WorkflowManager))):
            raise ValueError("Missing WorkflowManage object")

以上更改主要集中在:

  • BaseApplicationNode 添加 get_answer_list 方法来支持多应用节点输出答案;
  • 修改 reset_application_node_dict 方法用于处理特定运行时节点的数据;
  • 添加 insert_into_content 静态方法用于插入 FormRenderer 数据;
  • workflow_manage 参数明确作为执行方法的关键参数。

if len(result) == 0:
# 如果没有响应 就响应一个空数据
return [Answer('', '', '', '', {}).to_dict()]
return [r.to_dict() for r in result]

def get_next_node(self):
"""
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

问题和优化建议:

  1. 类导入顺序: from rest_framework.exceptions import ErrorDetail, ValidationError 应该在 tools 导入之前,以确保它们能够正常访问。

  2. **get_node_params 函数中的注释`: 注释中提到的“start_node”应该替换为实际使用的变量名,以提高可读性。

  3. **hand_event_node_result 函数中的异常处理`: 这个函数需要更全面的错误处理,特别是在连接断开情况下。

  4. **逻辑合并`: 将多个相似的操作(如添加下一个节点ID列表)合并到一个地方更容易维护并减少重复代码。

  5. 答案整合改进: 在将答案组合成最终结果时,可以考虑更好的策略来处理多视图或单视图的回答,并确保不会产生多余的换行符。

  6. 返回值检查: 确保所有可能的情况都被正确地覆盖,特别是当你从不同的上下文中获取答案时,比如子步骤的结果或其他流程的状态。


def to_dict(self):
return {'view_type': self.view_type, 'content': self.content, 'runtime_node_id': self.runtime_node_id,
'chat_record_id': self.chat_record_id, 'child_node': self.child_node}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

代码中有一些规范和潜在优化建议:

  1. 编码格式声明

    • 可以将utf-8编码放在文件的第一行(如你所示),但推荐在文档字符串之前。
  2. 文件头注释格式

    • 注释可以更简洁一些。MaxKB是项目名称,可以考虑替换为具体的模块名或功能说明。
      • 建议改为:“@module`: max_kb_common”
  3. 类属性名

    • 在Python中,变量通常采用小写加下划线的形式命名,以保持一致性。
      • 将所有属性改为其蛇形命名法:e.g., view_type, content
  4. 构造函数参数顺序

    • 参数顺序应该按字母升序排列,便于维护。
      • 改为:def __init__(self, view_type, runtime_node_id, content, chat_record_id, child_node):
  5. 返回字典方法

    • 方法名应更具描述性,可以将其命名为to_representation
      • 修改为:def to_representation(self):

以下是修改后的代码示例:

# coding=utf-8

"""
    @moduL: max_kb_common
    @AuthoR:虎
    @file: common.py
    @date:2023/6/26 17:57
    @desc:
"""

from typing import Dict


class Answer:
    def __init__(self, view_type: str, runtime_node_id: int, content: str, chat_record_id: int, child_node=None):
        self.view_type = view_type
        self.content = content
        self.runtime_node_id = runtime_node_id
        self.chat_record_id = chat_record_id
        self.child_node = child_node

    def to_representation(self) -> Dict[str, any]:
        return {
            'view_type': self.view_type,
            'content': self.content,
            'runtime_node_id': self.runtime_node_id,
            'chat_record_id': self.chat_record_id,
            'child_node': self.child_node
        }

总结:

  • 按照Python的最佳实践重新排版和重构了代码。
  • 删除不必要的空格和缩进,并根据需求调整了数据类型、方法名和文件结构。

shaohuzhang1 added a commit that referenced this pull request Dec 11, 2024
…isplayed as separate cards. (#1821)

(cherry picked from commit 37c963b)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant