Skip to content

Commit 048dafc

Browse files
authored
fix: fix missing details in json output when running uipath eval (#1382)
1 parent 40de0d3 commit 048dafc

File tree

5 files changed

+32
-15
lines changed

5 files changed

+32
-15
lines changed

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "uipath"
3-
version = "2.10.1"
3+
version = "2.10.2"
44
description = "Python SDK and CLI for UiPath Platform, enabling programmatic interaction with automation services, process management, and deployment tools."
55
readme = { file = "README.md", content-type = "text/markdown" }
66
requires-python = ">=3.11"

src/uipath/_cli/cli_eval.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,12 @@ def _resolve_model_settings_override(
205205
default=False,
206206
help="Resume execution from a previous suspended state",
207207
)
208+
@click.option(
209+
"--verbose",
210+
is_flag=True,
211+
default=False,
212+
help="Include agent execution output (trace, result) in the output file",
213+
)
208214
def eval(
209215
entrypoint: str | None,
210216
eval_set: str | None,
@@ -220,6 +226,7 @@ def eval(
220226
max_llm_concurrency: int,
221227
input_overrides: dict[str, Any],
222228
resume: bool,
229+
verbose: bool,
223230
) -> None:
224231
"""Run an evaluation set against the agent.
225232
@@ -272,6 +279,7 @@ def eval(
272279
eval_context.report_coverage = report_coverage
273280
eval_context.input_overrides = input_overrides
274281
eval_context.resume = resume
282+
eval_context.verbose = verbose
275283

276284
try:
277285

src/uipath/eval/runtime/_types.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ class EvaluationResultDto(BaseModel):
5555
model_config = ConfigDict(alias_generator=to_camel, populate_by_name=True)
5656

5757
score: float
58-
details: str | BaseModel | None = None
58+
details: str | dict[str, Any] | None = None
5959
evaluation_time: float | None = None
6060

6161
@model_serializer(mode="wrap")
@@ -82,9 +82,17 @@ def from_evaluation_result(
8282
else:
8383
score = evaluation_result.score
8484

85+
# Convert BaseModel details to dict so Pydantic doesn't lose subclass fields
86+
if isinstance(evaluation_result.details, BaseModel):
87+
details: str | dict[str, Any] | None = (
88+
evaluation_result.details.model_dump()
89+
)
90+
else:
91+
details = evaluation_result.details
92+
8593
return cls(
8694
score=score,
87-
details=evaluation_result.details,
95+
details=details,
8896
evaluation_time=evaluation_result.evaluation_time,
8997
)
9098

tests/cli/eval/test_evaluate.py

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -120,24 +120,25 @@ async def dispose(self) -> None:
120120
)
121121

122122
# Assert that the output is json-serializable
123-
UiPathEvalOutput.model_validate(result.output).model_dump_json()
123+
eval_output = UiPathEvalOutput.model_validate(result.output)
124+
eval_output.model_dump_json()
124125
assert result.output
125126
output_dict = (
126127
result.output.model_dump()
127128
if isinstance(result.output, BaseModel)
128129
else result.output
129130
)
130131
assert isinstance(output_dict, dict)
131-
assert (
132-
output_dict["evaluationSetResults"][0]["evaluationRunResults"][0]["result"][
133-
"score"
134-
]
135-
== 1.0
136-
)
137-
assert (
138-
output_dict["evaluationSetResults"][0]["evaluationRunResults"][0]["evaluatorId"]
139-
== "ExactMatchEvaluator"
140-
)
132+
first_result = output_dict["evaluationSetResults"][0]["evaluationRunResults"][0]
133+
assert first_result["result"]["score"] == 1.0
134+
assert first_result["evaluatorId"] == "ExactMatchEvaluator"
135+
# Verify details are properly serialized (not empty dict)
136+
details = first_result["result"].get("details")
137+
if details is not None:
138+
assert details != {}, (
139+
"details should not be an empty dict - BaseModel serialization bug"
140+
)
141+
assert isinstance(details, (str, dict))
141142

142143

143144
async def test_eval_runtime_generates_uuid_when_no_custom_id():

uv.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)