uipath 2.1.108__py3-none-any.whl → 2.1.110__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of uipath might be problematic. Click here for more details.
- uipath/_cli/__init__.py +4 -0
- uipath/_cli/_evals/_console_progress_reporter.py +2 -2
- uipath/_cli/_evals/_evaluator_factory.py +314 -29
- uipath/_cli/_evals/_helpers.py +194 -0
- uipath/_cli/_evals/_models/_evaluation_set.py +73 -7
- uipath/_cli/_evals/_models/_evaluator.py +183 -9
- uipath/_cli/_evals/_models/_evaluator_base_params.py +3 -3
- uipath/_cli/_evals/_models/_output.py +87 -3
- uipath/_cli/_evals/_progress_reporter.py +288 -28
- uipath/_cli/_evals/_runtime.py +80 -26
- uipath/_cli/_evals/mocks/input_mocker.py +1 -3
- uipath/_cli/_evals/mocks/llm_mocker.py +2 -2
- uipath/_cli/_evals/mocks/mocker_factory.py +2 -2
- uipath/_cli/_evals/mocks/mockito_mocker.py +2 -2
- uipath/_cli/_evals/mocks/mocks.py +5 -3
- uipath/_cli/_push/models.py +17 -0
- uipath/_cli/_push/sw_file_handler.py +336 -3
- uipath/_cli/_runtime/_contracts.py +2 -4
- uipath/_cli/_runtime/_runtime.py +2 -5
- uipath/_cli/_templates/custom_evaluator.py.template +65 -0
- uipath/_cli/_utils/_eval_set.py +30 -9
- uipath/_cli/_utils/_resources.py +21 -0
- uipath/_cli/_utils/_studio_project.py +18 -0
- uipath/_cli/cli_add.py +114 -0
- uipath/_cli/cli_eval.py +5 -1
- uipath/_cli/cli_init.py +5 -4
- uipath/_cli/cli_pull.py +11 -26
- uipath/_cli/cli_push.py +2 -0
- uipath/_cli/cli_register.py +45 -0
- uipath/_events/_events.py +6 -5
- uipath/_utils/constants.py +4 -0
- uipath/eval/_helpers/evaluators_helpers.py +494 -0
- uipath/eval/_helpers/helpers.py +30 -2
- uipath/eval/evaluators/__init__.py +60 -5
- uipath/eval/evaluators/base_evaluator.py +546 -44
- uipath/eval/evaluators/contains_evaluator.py +80 -0
- uipath/eval/evaluators/exact_match_evaluator.py +43 -12
- uipath/eval/evaluators/json_similarity_evaluator.py +41 -12
- uipath/eval/evaluators/legacy_base_evaluator.py +89 -0
- uipath/eval/evaluators/{deterministic_evaluator_base.py → legacy_deterministic_evaluator_base.py} +2 -2
- uipath/eval/evaluators/legacy_exact_match_evaluator.py +37 -0
- uipath/eval/evaluators/legacy_json_similarity_evaluator.py +151 -0
- uipath/eval/evaluators/legacy_llm_as_judge_evaluator.py +137 -0
- uipath/eval/evaluators/{trajectory_evaluator.py → legacy_trajectory_evaluator.py} +5 -6
- uipath/eval/evaluators/llm_as_judge_evaluator.py +143 -78
- uipath/eval/evaluators/llm_judge_output_evaluator.py +112 -0
- uipath/eval/evaluators/llm_judge_trajectory_evaluator.py +142 -0
- uipath/eval/evaluators/output_evaluator.py +117 -0
- uipath/eval/evaluators/tool_call_args_evaluator.py +82 -0
- uipath/eval/evaluators/tool_call_count_evaluator.py +87 -0
- uipath/eval/evaluators/tool_call_order_evaluator.py +84 -0
- uipath/eval/evaluators/tool_call_output_evaluator.py +87 -0
- uipath/eval/evaluators_types/ContainsEvaluator.json +73 -0
- uipath/eval/evaluators_types/ExactMatchEvaluator.json +89 -0
- uipath/eval/evaluators_types/JsonSimilarityEvaluator.json +81 -0
- uipath/eval/evaluators_types/LLMJudgeOutputEvaluator.json +110 -0
- uipath/eval/evaluators_types/LLMJudgeSimulationTrajectoryEvaluator.json +88 -0
- uipath/eval/evaluators_types/LLMJudgeStrictJSONSimilarityOutputEvaluator.json +110 -0
- uipath/eval/evaluators_types/LLMJudgeTrajectoryEvaluator.json +88 -0
- uipath/eval/evaluators_types/ToolCallArgsEvaluator.json +131 -0
- uipath/eval/evaluators_types/ToolCallCountEvaluator.json +104 -0
- uipath/eval/evaluators_types/ToolCallOrderEvaluator.json +100 -0
- uipath/eval/evaluators_types/ToolCallOutputEvaluator.json +124 -0
- uipath/eval/evaluators_types/generate_types.py +31 -0
- uipath/eval/models/__init__.py +16 -1
- uipath/eval/models/llm_judge_types.py +196 -0
- uipath/eval/models/models.py +109 -7
- {uipath-2.1.108.dist-info → uipath-2.1.110.dist-info}/METADATA +1 -1
- {uipath-2.1.108.dist-info → uipath-2.1.110.dist-info}/RECORD +72 -40
- {uipath-2.1.108.dist-info → uipath-2.1.110.dist-info}/WHEEL +0 -0
- {uipath-2.1.108.dist-info → uipath-2.1.110.dist-info}/entry_points.txt +0 -0
- {uipath-2.1.108.dist-info → uipath-2.1.110.dist-info}/licenses/LICENSE +0 -0
uipath/_cli/cli_add.py
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import os
|
|
3
|
+
import re
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
from string import Template
|
|
6
|
+
|
|
7
|
+
import click
|
|
8
|
+
|
|
9
|
+
from ..telemetry import track
|
|
10
|
+
from ._utils._console import ConsoleLogger
|
|
11
|
+
from ._utils._resources import Resources
|
|
12
|
+
|
|
13
|
+
logger = logging.getLogger(__name__)
|
|
14
|
+
console = ConsoleLogger()
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def to_pascal_case(text: str) -> str:
|
|
18
|
+
"""Convert kebab-case or snake_case to PascalCase."""
|
|
19
|
+
return "".join(word.capitalize() for word in re.sub(r"[-_]", " ", text).split())
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def to_snake_case(text: str) -> str:
|
|
23
|
+
"""Convert kebab-case or PascalCase to snake_case."""
|
|
24
|
+
return re.sub(r"(?<!^)(?=[A-Z])|-", "_", text).lower()
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def generate_evaluator_template(evaluator_name: str) -> str:
|
|
28
|
+
"""Generate a generic evaluator template."""
|
|
29
|
+
class_name = to_pascal_case(evaluator_name)
|
|
30
|
+
if not class_name.endswith("Evaluator"):
|
|
31
|
+
class_name = class_name + "Evaluator"
|
|
32
|
+
|
|
33
|
+
variables = {
|
|
34
|
+
"class_name": class_name,
|
|
35
|
+
"evaluator_name": evaluator_name,
|
|
36
|
+
"criteria_class": class_name.replace("Evaluator", "EvaluationCriteria"),
|
|
37
|
+
"config_class": class_name + "Config",
|
|
38
|
+
}
|
|
39
|
+
templates_path = os.path.join(
|
|
40
|
+
os.path.dirname(__file__), "_templates", "custom_evaluator.py.template"
|
|
41
|
+
)
|
|
42
|
+
with open(templates_path, "r", encoding="utf-8-sig") as f:
|
|
43
|
+
content = f.read()
|
|
44
|
+
|
|
45
|
+
return Template(content).substitute(variables)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def create_evaluator(evaluator_name):
|
|
49
|
+
cwd = Path.cwd()
|
|
50
|
+
custom_evaluators_dir = cwd / "evals" / "evaluators" / "custom"
|
|
51
|
+
|
|
52
|
+
if not custom_evaluators_dir.exists():
|
|
53
|
+
console.info(
|
|
54
|
+
f"Creating {click.style('evals/evaluators/custom', fg='cyan')} folder"
|
|
55
|
+
)
|
|
56
|
+
custom_evaluators_dir.mkdir(parents=True, exist_ok=True)
|
|
57
|
+
|
|
58
|
+
filename = to_snake_case(evaluator_name)
|
|
59
|
+
if not filename.endswith(".py"):
|
|
60
|
+
filename = filename + ".py"
|
|
61
|
+
|
|
62
|
+
file_path = custom_evaluators_dir / filename
|
|
63
|
+
|
|
64
|
+
if file_path.exists():
|
|
65
|
+
console.error(f"Evaluator file already exists: {file_path}")
|
|
66
|
+
|
|
67
|
+
template_content = generate_evaluator_template(evaluator_name)
|
|
68
|
+
|
|
69
|
+
with open(file_path, "w") as f:
|
|
70
|
+
f.write(template_content)
|
|
71
|
+
|
|
72
|
+
relative_path = f"evals/evaluators/custom/{filename}"
|
|
73
|
+
|
|
74
|
+
console.success(f"Created new evaluator: {click.style(relative_path, fg='cyan')}")
|
|
75
|
+
console.hint("Next steps:")
|
|
76
|
+
console.hint(
|
|
77
|
+
f" 1. Edit {click.style(relative_path, fg='cyan')} to implement your evaluation logic"
|
|
78
|
+
)
|
|
79
|
+
console.hint(
|
|
80
|
+
f" 2. Run {click.style(f'uipath register evaluator {filename}', fg='cyan')} to generate the evaluator spec"
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
@click.command()
|
|
85
|
+
@click.argument("resource", required=True)
|
|
86
|
+
@click.argument("args", nargs=-1)
|
|
87
|
+
@track
|
|
88
|
+
def add(resource: str, args: tuple[str]) -> None:
|
|
89
|
+
"""Create a local resource.
|
|
90
|
+
|
|
91
|
+
Examples:
|
|
92
|
+
uipath add evaluator my-custom-evaluator
|
|
93
|
+
"""
|
|
94
|
+
match Resources.from_string(resource):
|
|
95
|
+
case Resources.EVALUATOR:
|
|
96
|
+
usage_hint = f"Usage: {click.style('uipath add evaluator <evaluator_name>', fg='cyan')}"
|
|
97
|
+
if len(args) < 1:
|
|
98
|
+
console.hint(usage_hint)
|
|
99
|
+
console.error("Missing required argument: evaluator_name")
|
|
100
|
+
return
|
|
101
|
+
if len(args) > 1:
|
|
102
|
+
console.hint(usage_hint)
|
|
103
|
+
console.error(
|
|
104
|
+
f"Too many arguments provided: {args}. Expected only evaluator_name."
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
evaluator_name = args[0]
|
|
108
|
+
|
|
109
|
+
if not isinstance(evaluator_name, str) or not evaluator_name.strip():
|
|
110
|
+
console.hint(usage_hint)
|
|
111
|
+
console.error("Invalid evaluator_name: must be a non-empty string")
|
|
112
|
+
return
|
|
113
|
+
|
|
114
|
+
create_evaluator(evaluator_name)
|
uipath/_cli/cli_eval.py
CHANGED
|
@@ -130,7 +130,11 @@ def eval(
|
|
|
130
130
|
|
|
131
131
|
eval_context.no_report = no_report
|
|
132
132
|
eval_context.workers = workers
|
|
133
|
-
|
|
133
|
+
|
|
134
|
+
# Load eval set to resolve the path
|
|
135
|
+
eval_set_path = eval_set or EvalHelpers.auto_discover_eval_set()
|
|
136
|
+
_, resolved_eval_set_path = EvalHelpers.load_eval_set(eval_set_path, eval_ids)
|
|
137
|
+
eval_context.eval_set = resolved_eval_set_path
|
|
134
138
|
eval_context.eval_ids = eval_ids
|
|
135
139
|
|
|
136
140
|
console_reporter = ConsoleProgressReporter()
|
uipath/_cli/cli_init.py
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# type: ignore
|
|
2
|
+
import asyncio
|
|
2
3
|
import importlib.resources
|
|
3
4
|
import json
|
|
4
5
|
import logging
|
|
@@ -218,15 +219,15 @@ def init(entrypoint: str, infer_bindings: bool, no_agents_md_override: bool) ->
|
|
|
218
219
|
"entrypoint": script_path,
|
|
219
220
|
}
|
|
220
221
|
|
|
221
|
-
def initialize() -> None:
|
|
222
|
+
async def initialize() -> None:
|
|
222
223
|
try:
|
|
223
224
|
runtime = generate_runtime_factory().new_runtime(**context_args)
|
|
224
225
|
bindings = Bindings(
|
|
225
226
|
version="2.0",
|
|
226
|
-
resources=runtime.get_binding_resources,
|
|
227
|
+
resources=await runtime.get_binding_resources(),
|
|
227
228
|
)
|
|
228
229
|
config_data = RuntimeSchema(
|
|
229
|
-
entryPoints=[runtime.get_entrypoint],
|
|
230
|
+
entryPoints=[await runtime.get_entrypoint()],
|
|
230
231
|
bindings=bindings,
|
|
231
232
|
)
|
|
232
233
|
config_path = write_config_file(config_data)
|
|
@@ -234,4 +235,4 @@ def init(entrypoint: str, infer_bindings: bool, no_agents_md_override: bool) ->
|
|
|
234
235
|
except Exception as e:
|
|
235
236
|
console.error(f"Error creating configuration file:\n {str(e)}")
|
|
236
237
|
|
|
237
|
-
initialize()
|
|
238
|
+
asyncio.run(initialize())
|
uipath/_cli/cli_pull.py
CHANGED
|
@@ -24,20 +24,6 @@ from ._utils._project_files import ProjectPullError, pull_project
|
|
|
24
24
|
console = ConsoleLogger()
|
|
25
25
|
|
|
26
26
|
|
|
27
|
-
class InteractiveConflictHandler:
|
|
28
|
-
"""Handler that prompts user for each conflict."""
|
|
29
|
-
|
|
30
|
-
def __init__(self, console: ConsoleLogger):
|
|
31
|
-
self.console = console
|
|
32
|
-
|
|
33
|
-
def should_overwrite(
|
|
34
|
-
self, file_path: str, local_hash: str, remote_hash: str
|
|
35
|
-
) -> bool:
|
|
36
|
-
self.console.warning(f" File {file_path} differs from remote version.")
|
|
37
|
-
response = click.confirm("Do you want to overwrite it?", default=False)
|
|
38
|
-
return response
|
|
39
|
-
|
|
40
|
-
|
|
41
27
|
@click.command()
|
|
42
28
|
@click.argument(
|
|
43
29
|
"root",
|
|
@@ -66,22 +52,21 @@ def pull(root: Path) -> None:
|
|
|
66
52
|
project_id = os.getenv(UIPATH_PROJECT_ID)
|
|
67
53
|
if not project_id:
|
|
68
54
|
console.error("UIPATH_PROJECT_ID environment variable not found.")
|
|
55
|
+
return
|
|
69
56
|
|
|
70
|
-
|
|
57
|
+
download_configuration = {
|
|
71
58
|
"source_code": root,
|
|
72
59
|
"evals": root / "evals",
|
|
73
60
|
}
|
|
74
61
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
InteractiveConflictHandler(console),
|
|
81
|
-
):
|
|
62
|
+
try:
|
|
63
|
+
|
|
64
|
+
async def run_pull():
|
|
65
|
+
async for update in pull_project(project_id, download_configuration):
|
|
66
|
+
console.info(f"Processing: {update.file_path}")
|
|
82
67
|
console.info(update.message)
|
|
83
|
-
except ProjectPullError as e:
|
|
84
|
-
console.error(e.message, include_traceback=True)
|
|
85
68
|
|
|
86
|
-
|
|
87
|
-
|
|
69
|
+
asyncio.run(run_pull())
|
|
70
|
+
console.success("Project pulled successfully")
|
|
71
|
+
except ProjectPullError as e:
|
|
72
|
+
console.error(f"Failed to pull UiPath project: {str(e)}")
|
uipath/_cli/cli_push.py
CHANGED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# type: ignore
|
|
2
|
+
import logging
|
|
3
|
+
|
|
4
|
+
import click
|
|
5
|
+
|
|
6
|
+
from ..telemetry import track
|
|
7
|
+
from ._evals._helpers import register_evaluator
|
|
8
|
+
from ._utils._console import ConsoleLogger
|
|
9
|
+
from ._utils._resources import Resources
|
|
10
|
+
|
|
11
|
+
logger = logging.getLogger(__name__)
|
|
12
|
+
console = ConsoleLogger()
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@click.command()
|
|
16
|
+
@click.argument("resource", required=True)
|
|
17
|
+
@click.argument("args", nargs=-1)
|
|
18
|
+
@track
|
|
19
|
+
def register(resource: str, args: tuple[str]) -> None:
|
|
20
|
+
"""Register a local resource.
|
|
21
|
+
|
|
22
|
+
Examples:
|
|
23
|
+
uipath register evaluator my-custom-evaluator.py
|
|
24
|
+
"""
|
|
25
|
+
match Resources.from_string(resource):
|
|
26
|
+
case Resources.EVALUATOR:
|
|
27
|
+
usage_hint = f"Usage: {click.style('uipath register evaluator <evaluator_file_name> (ex. my_custom_evaluator.py)', fg='cyan')}"
|
|
28
|
+
if len(args) < 1:
|
|
29
|
+
console.hint(usage_hint)
|
|
30
|
+
console.error("Missing required argument: evaluator_file_name.")
|
|
31
|
+
return
|
|
32
|
+
if len(args) > 1:
|
|
33
|
+
console.hint(usage_hint)
|
|
34
|
+
console.error(
|
|
35
|
+
f"Too many arguments provided: {args}. Expected only evaluator_file_name (ex. my_custom_evaluator.py)"
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
filename = args[0]
|
|
39
|
+
|
|
40
|
+
if not isinstance(filename, str) or not filename.strip():
|
|
41
|
+
console.hint(usage_hint)
|
|
42
|
+
console.error("Invalid filename: must be a non-empty string")
|
|
43
|
+
return
|
|
44
|
+
|
|
45
|
+
register_evaluator(filename)
|
uipath/_events/_events.py
CHANGED
|
@@ -3,9 +3,9 @@ from enum import Enum
|
|
|
3
3
|
from typing import Any, Dict, List, Optional, Union
|
|
4
4
|
|
|
5
5
|
from opentelemetry.sdk.trace import ReadableSpan
|
|
6
|
-
from pydantic import BaseModel, ConfigDict, Field, model_validator
|
|
6
|
+
from pydantic import BaseModel, ConfigDict, Field, SkipValidation, model_validator
|
|
7
7
|
|
|
8
|
-
from uipath._cli._evals._models._evaluation_set import
|
|
8
|
+
from uipath._cli._evals._models._evaluation_set import AnyEvaluationItem, AnyEvaluator
|
|
9
9
|
from uipath.eval.models import EvalItemResult
|
|
10
10
|
|
|
11
11
|
|
|
@@ -21,12 +21,13 @@ class EvalSetRunCreatedEvent(BaseModel):
|
|
|
21
21
|
entrypoint: str
|
|
22
22
|
eval_set_id: str
|
|
23
23
|
no_of_evals: int
|
|
24
|
-
|
|
24
|
+
# skip validation to avoid abstract class instantiation
|
|
25
|
+
evaluators: SkipValidation[List[AnyEvaluator]]
|
|
25
26
|
|
|
26
27
|
|
|
27
28
|
class EvalRunCreatedEvent(BaseModel):
|
|
28
29
|
execution_id: str
|
|
29
|
-
eval_item:
|
|
30
|
+
eval_item: AnyEvaluationItem
|
|
30
31
|
|
|
31
32
|
|
|
32
33
|
class EvalItemExceptionDetails(BaseModel):
|
|
@@ -40,7 +41,7 @@ class EvalRunUpdatedEvent(BaseModel):
|
|
|
40
41
|
model_config = ConfigDict(arbitrary_types_allowed=True)
|
|
41
42
|
|
|
42
43
|
execution_id: str
|
|
43
|
-
eval_item:
|
|
44
|
+
eval_item: AnyEvaluationItem
|
|
44
45
|
eval_results: List[EvalItemResult]
|
|
45
46
|
success: bool
|
|
46
47
|
agent_output: Any
|
uipath/_utils/constants.py
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# Environment variables
|
|
2
2
|
DOTENV_FILE = ".env"
|
|
3
3
|
ENV_BASE_URL = "UIPATH_URL"
|
|
4
|
+
ENV_EVAL_BACKEND_URL = "UIPATH_EVAL_BACKEND_URL"
|
|
4
5
|
ENV_UNATTENDED_USER_ACCESS_TOKEN = "UNATTENDED_USER_ACCESS_TOKEN"
|
|
5
6
|
ENV_UIPATH_ACCESS_TOKEN = "UIPATH_ACCESS_TOKEN"
|
|
6
7
|
ENV_FOLDER_KEY = "UIPATH_FOLDER_KEY"
|
|
@@ -46,3 +47,6 @@ COMMUNITY_agents_SUFFIX = "-community-agents"
|
|
|
46
47
|
|
|
47
48
|
# File names
|
|
48
49
|
UIPATH_CONFIG_FILE = "uipath.json"
|
|
50
|
+
|
|
51
|
+
# Evaluators
|
|
52
|
+
CUSTOM_EVALUATOR_PREFIX = "file://"
|