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.

Files changed (72) hide show
  1. uipath/_cli/__init__.py +4 -0
  2. uipath/_cli/_evals/_console_progress_reporter.py +2 -2
  3. uipath/_cli/_evals/_evaluator_factory.py +314 -29
  4. uipath/_cli/_evals/_helpers.py +194 -0
  5. uipath/_cli/_evals/_models/_evaluation_set.py +73 -7
  6. uipath/_cli/_evals/_models/_evaluator.py +183 -9
  7. uipath/_cli/_evals/_models/_evaluator_base_params.py +3 -3
  8. uipath/_cli/_evals/_models/_output.py +87 -3
  9. uipath/_cli/_evals/_progress_reporter.py +288 -28
  10. uipath/_cli/_evals/_runtime.py +80 -26
  11. uipath/_cli/_evals/mocks/input_mocker.py +1 -3
  12. uipath/_cli/_evals/mocks/llm_mocker.py +2 -2
  13. uipath/_cli/_evals/mocks/mocker_factory.py +2 -2
  14. uipath/_cli/_evals/mocks/mockito_mocker.py +2 -2
  15. uipath/_cli/_evals/mocks/mocks.py +5 -3
  16. uipath/_cli/_push/models.py +17 -0
  17. uipath/_cli/_push/sw_file_handler.py +336 -3
  18. uipath/_cli/_runtime/_contracts.py +2 -4
  19. uipath/_cli/_runtime/_runtime.py +2 -5
  20. uipath/_cli/_templates/custom_evaluator.py.template +65 -0
  21. uipath/_cli/_utils/_eval_set.py +30 -9
  22. uipath/_cli/_utils/_resources.py +21 -0
  23. uipath/_cli/_utils/_studio_project.py +18 -0
  24. uipath/_cli/cli_add.py +114 -0
  25. uipath/_cli/cli_eval.py +5 -1
  26. uipath/_cli/cli_init.py +5 -4
  27. uipath/_cli/cli_pull.py +11 -26
  28. uipath/_cli/cli_push.py +2 -0
  29. uipath/_cli/cli_register.py +45 -0
  30. uipath/_events/_events.py +6 -5
  31. uipath/_utils/constants.py +4 -0
  32. uipath/eval/_helpers/evaluators_helpers.py +494 -0
  33. uipath/eval/_helpers/helpers.py +30 -2
  34. uipath/eval/evaluators/__init__.py +60 -5
  35. uipath/eval/evaluators/base_evaluator.py +546 -44
  36. uipath/eval/evaluators/contains_evaluator.py +80 -0
  37. uipath/eval/evaluators/exact_match_evaluator.py +43 -12
  38. uipath/eval/evaluators/json_similarity_evaluator.py +41 -12
  39. uipath/eval/evaluators/legacy_base_evaluator.py +89 -0
  40. uipath/eval/evaluators/{deterministic_evaluator_base.py → legacy_deterministic_evaluator_base.py} +2 -2
  41. uipath/eval/evaluators/legacy_exact_match_evaluator.py +37 -0
  42. uipath/eval/evaluators/legacy_json_similarity_evaluator.py +151 -0
  43. uipath/eval/evaluators/legacy_llm_as_judge_evaluator.py +137 -0
  44. uipath/eval/evaluators/{trajectory_evaluator.py → legacy_trajectory_evaluator.py} +5 -6
  45. uipath/eval/evaluators/llm_as_judge_evaluator.py +143 -78
  46. uipath/eval/evaluators/llm_judge_output_evaluator.py +112 -0
  47. uipath/eval/evaluators/llm_judge_trajectory_evaluator.py +142 -0
  48. uipath/eval/evaluators/output_evaluator.py +117 -0
  49. uipath/eval/evaluators/tool_call_args_evaluator.py +82 -0
  50. uipath/eval/evaluators/tool_call_count_evaluator.py +87 -0
  51. uipath/eval/evaluators/tool_call_order_evaluator.py +84 -0
  52. uipath/eval/evaluators/tool_call_output_evaluator.py +87 -0
  53. uipath/eval/evaluators_types/ContainsEvaluator.json +73 -0
  54. uipath/eval/evaluators_types/ExactMatchEvaluator.json +89 -0
  55. uipath/eval/evaluators_types/JsonSimilarityEvaluator.json +81 -0
  56. uipath/eval/evaluators_types/LLMJudgeOutputEvaluator.json +110 -0
  57. uipath/eval/evaluators_types/LLMJudgeSimulationTrajectoryEvaluator.json +88 -0
  58. uipath/eval/evaluators_types/LLMJudgeStrictJSONSimilarityOutputEvaluator.json +110 -0
  59. uipath/eval/evaluators_types/LLMJudgeTrajectoryEvaluator.json +88 -0
  60. uipath/eval/evaluators_types/ToolCallArgsEvaluator.json +131 -0
  61. uipath/eval/evaluators_types/ToolCallCountEvaluator.json +104 -0
  62. uipath/eval/evaluators_types/ToolCallOrderEvaluator.json +100 -0
  63. uipath/eval/evaluators_types/ToolCallOutputEvaluator.json +124 -0
  64. uipath/eval/evaluators_types/generate_types.py +31 -0
  65. uipath/eval/models/__init__.py +16 -1
  66. uipath/eval/models/llm_judge_types.py +196 -0
  67. uipath/eval/models/models.py +109 -7
  68. {uipath-2.1.108.dist-info → uipath-2.1.110.dist-info}/METADATA +1 -1
  69. {uipath-2.1.108.dist-info → uipath-2.1.110.dist-info}/RECORD +72 -40
  70. {uipath-2.1.108.dist-info → uipath-2.1.110.dist-info}/WHEEL +0 -0
  71. {uipath-2.1.108.dist-info → uipath-2.1.110.dist-info}/entry_points.txt +0 -0
  72. {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
- eval_context.eval_set = eval_set or EvalHelpers.auto_discover_eval_set()
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
- default_download_configuration = {
57
+ download_configuration = {
71
58
  "source_code": root,
72
59
  "evals": root / "evals",
73
60
  }
74
61
 
75
- async def pull_with_updates():
76
- try:
77
- async for update in pull_project(
78
- project_id,
79
- default_download_configuration,
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
- with console.spinner("Pulling UiPath project files..."):
87
- asyncio.run(pull_with_updates())
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
@@ -61,6 +61,8 @@ async def upload_source_files_to_project(
61
61
  async for update in sw_file_handler.upload_source_files(settings):
62
62
  yield update
63
63
 
64
+ await sw_file_handler.upload_coded_evals_files()
65
+
64
66
 
65
67
  @click.command()
66
68
  @click.argument(
@@ -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 EvaluationItem
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
- evaluators: List[Any]
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: EvaluationItem
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: EvaluationItem
44
+ eval_item: AnyEvaluationItem
44
45
  eval_results: List[EvalItemResult]
45
46
  success: bool
46
47
  agent_output: Any
@@ -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://"