diff --git a/apps/application/workflow/content_type.py b/apps/application/workflow/content_type.py index 1920ec132a8..7f5cc3c9c39 100644 --- a/apps/application/workflow/content_type.py +++ b/apps/application/workflow/content_type.py @@ -17,3 +17,4 @@ class ContentType(Enum): CONTINUE = "CONTINUE" BREAK = "BREAK" FORM = "FORM" + PROGRESS="PROGRESS" diff --git a/apps/application/workflow/message/aggregator/aggregator_factory.py b/apps/application/workflow/message/aggregator/aggregator_factory.py index 18a96461447..95cbb1f2ca8 100644 --- a/apps/application/workflow/message/aggregator/aggregator_factory.py +++ b/apps/application/workflow/message/aggregator/aggregator_factory.py @@ -7,7 +7,9 @@ """ from typing import Dict, Type, Optional +from application.workflow.message.aggregator.impl import ProgressAggregator from application.workflow.message.struct.content import Content +from application.workflow.message.struct.progress_content import ProgressContent from application.workflow.message.struct.text_content import TextContent from application.workflow.message.struct.reasoning_content import ReasoningContent from application.workflow.message.struct.tool_content import ToolContent @@ -26,6 +28,7 @@ class AggregatorFactory: TextContent: TextAggregator(), ReasoningContent: ReasoningAggregator(), ToolContent: ToolAggregator(), + ProgressContent: ProgressAggregator() } @classmethod diff --git a/apps/application/workflow/message/aggregator/impl/__init__.py b/apps/application/workflow/message/aggregator/impl/__init__.py index 5b6b3cfe902..f007af7cdda 100644 --- a/apps/application/workflow/message/aggregator/impl/__init__.py +++ b/apps/application/workflow/message/aggregator/impl/__init__.py @@ -8,5 +8,6 @@ from application.workflow.message.aggregator.impl.text_aggregator import TextAggregator from application.workflow.message.aggregator.impl.reasoning_aggregator import ReasoningAggregator from application.workflow.message.aggregator.impl.tool_aggregator import ToolAggregator +from application.workflow.message.aggregator.impl.progress_aggregator import ProgressAggregator -__all__ = ['TextAggregator', 'ReasoningAggregator', 'ToolAggregator'] +__all__ = ['TextAggregator', 'ReasoningAggregator', 'ToolAggregator', 'ProgressAggregator'] diff --git a/apps/application/workflow/message/aggregator/impl/progress_aggregator.py b/apps/application/workflow/message/aggregator/impl/progress_aggregator.py new file mode 100644 index 00000000000..7e42ef784a4 --- /dev/null +++ b/apps/application/workflow/message/aggregator/impl/progress_aggregator.py @@ -0,0 +1,37 @@ +# coding=utf-8 +""" + @project: MaxKB + @file: progress_aggregator.py + @date:2026/7/22 16:24 + @desc: ReasoningContent 聚合器 +""" +from application.workflow.message.aggregator.content_aggregator import ContentAggregator +from application.workflow.message.struct.progress_content import ProgressContent + + +class ProgressAggregator(ContentAggregator[ProgressContent]): + """ + 推理内容聚合器 + 用于合并流式推理内容块 + """ + + def aggregate(self, prev: ProgressContent, chunk: ProgressContent) -> ProgressContent: + """ + 聚合推理内容 + + @param prev: 之前的内容 + @param chunk: 新的内容块 + @return: 合并后的内容 + """ + if prev is None: + return chunk + + # 合并 status: 优先使用 chunk 的,否则使用 prev 的 + merged_status = chunk.status if chunk.status else prev.status + # 合并基础字段 + merged_id = chunk.id if chunk.id else prev.id + merged_node_info = chunk.node_info if chunk.node_info else prev.node_info + merged_position = chunk.position if chunk.position else prev.position + result = ProgressContent(merged_id, merged_status, merged_node_info, merged_position) + + return result diff --git a/apps/application/workflow/message/struct/progress_content.py b/apps/application/workflow/message/struct/progress_content.py index cab37d98b59..cb19d50465c 100644 --- a/apps/application/workflow/message/struct/progress_content.py +++ b/apps/application/workflow/message/struct/progress_content.py @@ -14,7 +14,7 @@ class ProgressContent(Content): def __init__(self, _id, status: Status, node_info: NodeInfo, position: Position, **kwargs): - super().__init__(_id, status, ContentType.REASONING, node_info, position, **kwargs) + super().__init__(_id, status, ContentType.PROGRESS, node_info, position, **kwargs) def to_dict(self): result = super().to_dict() diff --git a/ui/src/components/conversation/index.ts b/ui/src/components/conversation/index.ts index 40a23fac959..c500cf2edd2 100644 --- a/ui/src/components/conversation/index.ts +++ b/ui/src/components/conversation/index.ts @@ -104,10 +104,21 @@ const FORM = (prev: any, chunk: any) => { } } +const PROGRESS = (prev: any = {}, chunk: any) => { + return { + type: 'PROGRESS', + id: chunk.id ?? prev.id, + status: chunk.status ?? prev.status, + workflowRunId: chunk.workflowRunId ?? prev.workflowRunId, + extra: chunk.extra ?? prev.extra + } +} + export const aggregators: Record any> = { TEXT, REASONING, FAILURE, TOOL, - FORM + FORM, + PROGRESS }