Skip to content

Commit 35fc809

Browse files
authored
Merge branch 'main' into release/revamped-evals
2 parents 7efe612 + 9b79004 commit 35fc809

File tree

10 files changed

+114
-19
lines changed

10 files changed

+114
-19
lines changed

src/uipath/_cli/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
from .cli_debug import debug as debug # type: ignore
1010
from .cli_deploy import deploy as deploy # type: ignore
1111
from .cli_dev import dev as dev
12-
from .cli_eval import eval as eval # type: ignore
12+
from .cli_eval import eval as eval
1313
from .cli_init import init as init # type: ignore
1414
from .cli_invoke import invoke as invoke # type: ignore
1515
from .cli_new import new as new # type: ignore

src/uipath/_cli/_debug/_bridge.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -434,7 +434,8 @@ def get_remote_debug_bridge(context: UiPathRuntimeContext) -> UiPathDebugBridge:
434434
if not context.trace_context:
435435
raise ValueError("trace_context is required for remote debugging")
436436

437-
signalr_url = uipath_url + "/agenthub_/wsstunnel?jobId=" + context.job_id
437+
signalr_url = f"{uipath_url.rstrip('/')}/orchestrator_/signalr/robotdebug?sessionId={context.job_id}"
438+
438439
return SignalRDebugBridge(
439440
hub_url=signalr_url,
440441
access_token=os.environ.get("UIPATH_ACCESS_TOKEN"),

src/uipath/_cli/_evals/__init__.py

Whitespace-only changes.
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
from typing import TypeVar
2+
3+
from uipath._cli._evals._runtime import UiPathEvalContext, UiPathEvalRuntime
4+
from uipath._cli._runtime._contracts import (
5+
UiPathBaseRuntime,
6+
UiPathRuntimeContext,
7+
UiPathRuntimeFactory,
8+
UiPathRuntimeResult,
9+
)
10+
from uipath._events._event_bus import EventBus
11+
12+
T = TypeVar("T", bound=UiPathBaseRuntime)
13+
C = TypeVar("C", bound=UiPathRuntimeContext)
14+
15+
16+
async def evaluate(
17+
runtime_factory: UiPathRuntimeFactory[T, C],
18+
eval_context: UiPathEvalContext,
19+
event_bus: EventBus,
20+
) -> UiPathRuntimeResult:
21+
async with UiPathEvalRuntime.from_eval_context(
22+
factory=runtime_factory,
23+
context=eval_context,
24+
event_bus=event_bus,
25+
) as eval_runtime:
26+
results = await eval_runtime.execute()
27+
await event_bus.wait_for_all(timeout=10)
28+
return results

src/uipath/_cli/_evals/_runtime.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ def from_eval_context(
183183
) -> "UiPathEvalRuntime[T, C]":
184184
return cls(context, factory, event_bus)
185185

186-
async def execute(self) -> Optional[UiPathRuntimeResult]:
186+
async def execute(self) -> UiPathRuntimeResult:
187187
if self.context.eval_set is None:
188188
raise ValueError("eval_set must be provided for evaluation runs")
189189

src/uipath/_cli/cli_eval.py

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
# type: ignore
21
import ast
32
import asyncio
43
import os
@@ -7,10 +6,10 @@
76
import click
87

98
from uipath._cli._evals._console_progress_reporter import ConsoleProgressReporter
9+
from uipath._cli._evals._evaluate import evaluate
1010
from uipath._cli._evals._progress_reporter import StudioWebProgressReporter
1111
from uipath._cli._evals._runtime import (
1212
UiPathEvalContext,
13-
UiPathEvalRuntime,
1413
)
1514
from uipath._cli._runtime._runtime_factory import generate_runtime_factory
1615
from uipath._cli._utils._constants import UIPATH_PROJECT_ID
@@ -46,9 +45,9 @@ def setup_reporting_prereq(no_report: bool) -> bool:
4645
)
4746
return False
4847
if not os.getenv("UIPATH_FOLDER_KEY"):
49-
os.environ["UIPATH_FOLDER_KEY"] = asyncio.run(
50-
get_personal_workspace_key_async()
51-
)
48+
folder_key = asyncio.run(get_personal_workspace_key_async())
49+
if folder_key:
50+
os.environ["UIPATH_FOLDER_KEY"] = folder_key
5251
return True
5352

5453

@@ -145,17 +144,8 @@ def eval(
145144
runtime_factory = generate_runtime_factory()
146145
if eval_context.job_id:
147146
runtime_factory.add_span_exporter(LlmOpsHttpExporter())
147+
asyncio.run(evaluate(runtime_factory, eval_context, event_bus))
148148

149-
async def execute():
150-
async with UiPathEvalRuntime.from_eval_context(
151-
factory=runtime_factory,
152-
context=eval_context,
153-
event_bus=event_bus,
154-
) as eval_runtime:
155-
await eval_runtime.execute()
156-
await event_bus.wait_for_all(timeout=10)
157-
158-
asyncio.run(execute())
159149
except Exception as e:
160150
console.error(
161151
f"Error occurred: {e or 'Execution failed'}", include_traceback=True
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
{
2+
"fileName": "default.json",
3+
"id": "default-eval-set-id",
4+
"name": "Basic Calculator Evaluation Set",
5+
"batchSize": 10,
6+
"evaluatorRefs": [
7+
"equality"
8+
],
9+
"evaluations": [
10+
{
11+
"id": "test-addition",
12+
"name": "Test Addition",
13+
"inputs": {"foo": "bar"},
14+
"expectedOutput": {"foo": "bar"},
15+
"expectedAgentBehavior": "",
16+
"evalSetId": "default-eval-set-id",
17+
"createdAt": "2025-09-04T18:54:58.378Z",
18+
"updatedAt": "2025-09-04T18:55:55.416Z"
19+
}
20+
],
21+
"modelSettings": [],
22+
"createdAt": "2025-09-04T18:54:58.379Z",
23+
"updatedAt": "2025-09-04T18:55:55.416Z"
24+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"fileName": "equality.json",
3+
"id": "equality",
4+
"name": "Equality Evaluator",
5+
"description": "An evaluator that judges the agent based on expected output.",
6+
"category": 0,
7+
"type": 1,
8+
"targetOutputKey": "*",
9+
"createdAt": "2025-06-26T17:45:39.651Z",
10+
"updatedAt": "2025-06-26T17:45:39.651Z"
11+
}

tests/cli/eval/test_evaluate.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
from pathlib import Path
2+
from typing import Any
3+
4+
from uipath._cli._evals._evaluate import evaluate
5+
from uipath._cli._evals._runtime import UiPathEvalContext
6+
from uipath._cli._runtime._contracts import UiPathRuntimeContext, UiPathRuntimeFactory
7+
from uipath._cli._runtime._runtime import UiPathRuntime
8+
from uipath._events._event_bus import EventBus
9+
10+
11+
async def test_evaluate():
12+
# Arrange
13+
event_bus = EventBus()
14+
context = UiPathEvalContext(
15+
eval_set=str(Path(__file__).parent / "evals" / "eval-sets" / "default.json")
16+
)
17+
18+
async def identity(input: Any) -> Any:
19+
return input
20+
21+
class MyFactory(UiPathRuntimeFactory[UiPathRuntime, UiPathRuntimeContext]):
22+
def __init__(self):
23+
super().__init__(
24+
UiPathRuntime,
25+
UiPathRuntimeContext,
26+
runtime_generator=lambda context: UiPathRuntime(
27+
context, executor=identity
28+
),
29+
)
30+
31+
# Act
32+
result = await evaluate(MyFactory(), context, event_bus)
33+
34+
# Assert
35+
assert result.output
36+
assert (
37+
result.output["evaluationSetResults"][0]["evaluationRunResults"][0]["result"][
38+
"score"
39+
]
40+
== 100.0
41+
)

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)