fix: evaluation (#35744)

Co-authored-by: jyong <718720800@qq.com>
Co-authored-by: Yansong Zhang <916125788@qq.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: hj24 <mambahj24@gmail.com>
Co-authored-by: hj24 <huangjian@dify.ai>
Co-authored-by: Joel <iamjoel007@gmail.com>
Co-authored-by: Stephen Zhou <38493346+hyoban@users.noreply.github.com>
Co-authored-by: CodingOnStar <hanxujiang@dify.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
This commit is contained in:
FFXN 2026-04-30 17:40:28 +08:00 committed by GitHub
parent e3a939c81d
commit da7cb4dc29
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 59 additions and 3 deletions

View File

@ -139,6 +139,11 @@ class WorkflowAppLogPartialResponse(ResponseModel):
return int(value.timestamp())
return value
@field_validator("evaluation", mode="before")
@classmethod
def _normalize_evaluation(cls, value: Any) -> list[dict[str, Any]] | list[WorkflowAppLogEvaluationItemResponse]:
return value or []
class WorkflowArchivedLogPartialResponse(ResponseModel):
id: str

View File

@ -174,6 +174,11 @@ class WorkflowAppLogPartialResponse(ResponseModel):
def _normalize_timestamp(cls, value: datetime | int | None) -> int | None:
return _to_timestamp(value)
@field_validator("evaluation", mode="before")
@classmethod
def _normalize_evaluation(cls, value: Any) -> list[dict[str, Any]] | list[WorkflowAppLogEvaluationItemResponse]:
return value or []
class WorkflowAppLogPaginationResponse(ResponseModel):
page: int

View File

@ -136,6 +136,11 @@ class WorkflowAppLogPartialResponse(ResponseModel):
def _normalize_timestamp(cls, value: datetime | int | None) -> int | None:
return _to_timestamp(value)
@field_validator("evaluation", mode="before")
@classmethod
def _normalize_evaluation(cls, value: Any) -> list[dict[str, Any]] | list[WorkflowAppLogEvaluationItemResponse]:
return value or []
class WorkflowArchivedLogPartialResponse(ResponseModel):
id: str

View File

@ -24,6 +24,8 @@ class LogView:
- Exposes `details_` for marshalling to `details` in API response
- Exposes `evaluation_` for marshalling evaluation metrics in API response
- Normalizes missing evaluation results to an empty list because the API
schema treats "no evaluation data" as an empty collection, not `null`
- Proxies all other attributes to the underlying `WorkflowAppLog`
"""
@ -35,14 +37,14 @@ class LogView:
):
self.log = log
self.details_ = details
self.evaluation_ = evaluation
self.evaluation_ = evaluation or []
@property
def details(self) -> LogViewDetails | None:
return self.details_
@property
def evaluation(self) -> list[dict] | None:
def evaluation(self) -> list[dict]:
return self.evaluation_
def __getattr__(self, name):
@ -192,7 +194,7 @@ class WorkflowAppService:
eval_map = self._batch_query_evaluation_metrics(session, workflow_run_ids)
items = [
LogView(log, details, evaluation=eval_map.get(log.workflow_run_id))
LogView(log, details, evaluation=eval_map.get(log.workflow_run_id, []))
for log, details in logs_with_details
]
return {

View File

@ -65,6 +65,25 @@ def test_workflow_app_log_pagination_response_normalizes_nested_fields():
assert response["data"][0]["evaluation"][0]["nodeInfo"]["node_id"] == "node-1"
def test_workflow_app_log_pagination_response_normalizes_null_evaluation_to_empty_list():
response = workflow_app_log_module.WorkflowAppLogPaginationResponse.model_validate(
{
"page": 1,
"limit": 20,
"total": 1,
"has_more": False,
"data": [
{
"id": "log-1",
"evaluation": None,
}
],
}
).model_dump(mode="json")
assert response["data"][0]["evaluation"] == []
def test_workflow_archived_log_pagination_response_normalizes_nested_fields():
created_at = datetime(2026, 1, 2, 3, 4, 5, tzinfo=UTC)
response = workflow_app_log_module.WorkflowArchivedLogPaginationResponse.model_validate(

View File

@ -29,6 +29,7 @@ from controllers.service_api.app.workflow import (
DifyAPIRepositoryFactory,
GraphEngineManager,
WorkflowAppLogApi,
WorkflowAppLogPaginationResponse,
WorkflowLogQuery,
WorkflowRunApi,
WorkflowRunByIdApi,
@ -238,6 +239,25 @@ class TestWorkflowAppService:
assert result.limit == 20
def test_workflow_app_log_pagination_response_normalizes_null_evaluation_to_empty_list():
response = WorkflowAppLogPaginationResponse.model_validate(
{
"page": 1,
"limit": 20,
"total": 1,
"has_more": False,
"data": [
{
"id": "log-1",
"evaluation": None,
}
],
}
).model_dump(mode="json")
assert response["data"][0]["evaluation"] == []
class TestWorkflowExecutionStatus:
"""Test WorkflowExecutionStatus enum."""