Quellcode durchsuchen

feat: add agent node log

Novice Lee vor 5 Monaten
Ursprung
Commit
491d641485

+ 1 - 0
api/core/app/entities/queue_entities.py

@@ -329,6 +329,7 @@ class QueueAgentLogEvent(AppQueueEvent):
     error: str | None
     status: str
     data: Mapping[str, Any]
+    metadata: Optional[Mapping[str, Any]] = None
 
 
 class QueueNodeRetryEvent(QueueNodeStartedEvent):

+ 1 - 0
api/core/app/entities/task_entities.py

@@ -716,6 +716,7 @@ class AgentLogStreamResponse(StreamResponse):
         error: str | None
         status: str
         data: Mapping[str, Any]
+        metadata: Optional[Mapping[str, Any]] = None
 
     event: StreamEvent = StreamEvent.AGENT_LOG
     data: Data

+ 1 - 0
api/core/app/task_pipeline/workflow_cycle_manage.py

@@ -862,5 +862,6 @@ class WorkflowCycleManage:
                 error=event.error,
                 status=event.status,
                 data=event.data,
+                metadata=event.metadata,
             ),
         )

+ 1 - 0
api/core/tools/entities/tool_entities.py

@@ -167,6 +167,7 @@ class ToolInvokeMessage(BaseModel):
         error: Optional[str] = Field(default=None, description="The error message")
         status: LogStatus = Field(..., description="The status of the log")
         data: Mapping[str, Any] = Field(..., description="Detailed log data")
+        metadata: Optional[Mapping[str, Any]] = Field(default=None, description="The metadata of the log")
 
     class MessageType(Enum):
         TEXT = "text"

+ 1 - 0
api/core/workflow/graph_engine/entities/event.py

@@ -203,6 +203,7 @@ class AgentLogEvent(BaseAgentEvent):
     error: str | None = Field(..., description="error")
     status: str = Field(..., description="status")
     data: Mapping[str, Any] = Field(..., description="data")
+    metadata: Optional[Mapping[str, Any]] = Field(default=None, description="metadata")
 
 
 InNodeEvent = BaseNodeEvent | BaseParallelBranchEvent | BaseIterationEvent | BaseAgentEvent

+ 11 - 2
api/core/workflow/nodes/agent/agent_node.py

@@ -89,7 +89,11 @@ class AgentNode(ToolNode):
 
         try:
             # convert tool messages
-            yield from self._transform_message(message_stream, {}, parameters_for_log)
+            yield from self._transform_message(
+                message_stream,
+                {"provider": (cast(AgentNodeData, self.node_data)).agent_strategy_provider_name},
+                parameters_for_log,
+            )
         except PluginDaemonClientSideError as e:
             yield RunCompletedEvent(
                 run_result=NodeRunResult(
@@ -170,7 +174,12 @@ class AgentNode(ToolNode):
                                 extra.get("descrption", "") or tool_runtime.entity.description.llm
                             )
 
-                        tool_value.append(tool_runtime.entity.model_dump(mode="json"))
+                        tool_value.append(
+                            {
+                                **tool_runtime.entity.model_dump(mode="json"),
+                                "runtime_parameters": tool_runtime.runtime.runtime_parameters,
+                            }
+                        )
                     value = tool_value
                 if parameter.type == "model-selector":
                     value = cast(dict[str, Any], value)

+ 14 - 2
api/core/workflow/nodes/tool/tool_node.py

@@ -1,5 +1,5 @@
 from collections.abc import Generator, Mapping, Sequence
-from typing import Any, cast
+from typing import Any, Optional, cast
 
 from sqlalchemy import select
 from sqlalchemy.orm import Session
@@ -197,6 +197,7 @@ class ToolNode(BaseNode[ToolNodeData]):
         json: list[dict] = []
 
         agent_logs: list[AgentLogEvent] = []
+        agent_execution_metadata: Optional[Mapping[NodeRunMetadataKey, Any]] = {}
 
         variables: dict[str, Any] = {}
 
@@ -264,6 +265,11 @@ class ToolNode(BaseNode[ToolNodeData]):
                 )
             elif message.type == ToolInvokeMessage.MessageType.JSON:
                 assert isinstance(message.message, ToolInvokeMessage.JsonMessage)
+                if self.node_type == NodeType.AGENT:
+                    msg_metadata = message.message.json_object.pop("execution_metadata", {})
+                    agent_execution_metadata = {
+                        key: value for key, value in msg_metadata.items() if key in NodeRunMetadataKey
+                    }
                 json.append(message.message.json_object)
             elif message.type == ToolInvokeMessage.MessageType.LINK:
                 assert isinstance(message.message, ToolInvokeMessage.TextMessage)
@@ -299,6 +305,7 @@ class ToolNode(BaseNode[ToolNodeData]):
                     status=message.message.status.value,
                     data=message.message.data,
                     label=message.message.label,
+                    metadata=message.message.metadata,
                 )
 
                 # check if the agent log is already in the list
@@ -309,6 +316,7 @@ class ToolNode(BaseNode[ToolNodeData]):
                         log.status = agent_log.status
                         log.error = agent_log.error
                         log.label = agent_log.label
+                        log.metadata = agent_log.metadata
                         break
                 else:
                     agent_logs.append(agent_log)
@@ -319,7 +327,11 @@ class ToolNode(BaseNode[ToolNodeData]):
             run_result=NodeRunResult(
                 status=WorkflowNodeExecutionStatus.SUCCEEDED,
                 outputs={"text": text, "files": files, "json": json, **variables},
-                metadata={NodeRunMetadataKey.TOOL_INFO: tool_info, NodeRunMetadataKey.AGENT_LOG: agent_logs},
+                metadata={
+                    **agent_execution_metadata,
+                    NodeRunMetadataKey.TOOL_INFO: tool_info,
+                    NodeRunMetadataKey.AGENT_LOG: agent_logs,
+                },
                 inputs=parameters_for_log,
             )
         )