uipath-core 0.1.4__py3-none-any.whl → 0.1.6__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.
- uipath/core/guardrails/__init__.py +2 -0
- uipath/core/guardrails/_deterministic_guardrails_service.py +69 -3
- uipath/core/guardrails/_evaluators.py +21 -19
- uipath/core/guardrails/guardrails.py +13 -3
- {uipath_core-0.1.4.dist-info → uipath_core-0.1.6.dist-info}/METADATA +1 -1
- {uipath_core-0.1.4.dist-info → uipath_core-0.1.6.dist-info}/RECORD +8 -8
- {uipath_core-0.1.4.dist-info → uipath_core-0.1.6.dist-info}/WHEEL +0 -0
- {uipath_core-0.1.4.dist-info → uipath_core-0.1.6.dist-info}/licenses/LICENSE +0 -0
|
@@ -16,6 +16,7 @@ from .guardrails import (
|
|
|
16
16
|
GuardrailScope,
|
|
17
17
|
GuardrailSelector,
|
|
18
18
|
GuardrailValidationResult,
|
|
19
|
+
GuardrailValidationResultType,
|
|
19
20
|
NumberRule,
|
|
20
21
|
Rule,
|
|
21
22
|
SelectorType,
|
|
@@ -43,4 +44,5 @@ __all__ = [
|
|
|
43
44
|
"GuardrailScope",
|
|
44
45
|
"GuardrailSelector",
|
|
45
46
|
"GuardrailValidationResult",
|
|
47
|
+
"GuardrailValidationResultType",
|
|
46
48
|
]
|
|
@@ -10,10 +10,15 @@ from ._evaluators import (
|
|
|
10
10
|
evaluate_word_rule,
|
|
11
11
|
)
|
|
12
12
|
from .guardrails import (
|
|
13
|
+
AllFieldsSelector,
|
|
14
|
+
ApplyTo,
|
|
13
15
|
BooleanRule,
|
|
14
16
|
DeterministicGuardrail,
|
|
17
|
+
FieldSource,
|
|
15
18
|
GuardrailValidationResult,
|
|
19
|
+
GuardrailValidationResultType,
|
|
16
20
|
NumberRule,
|
|
21
|
+
SpecificFieldsSelector,
|
|
17
22
|
UniversalRule,
|
|
18
23
|
WordRule,
|
|
19
24
|
)
|
|
@@ -27,6 +32,16 @@ class DeterministicGuardrailsService(BaseModel):
|
|
|
27
32
|
guardrail: DeterministicGuardrail,
|
|
28
33
|
) -> GuardrailValidationResult:
|
|
29
34
|
"""Evaluate deterministic guardrail rules against input data (pre-execution)."""
|
|
35
|
+
# Check if guardrail contains any output-dependent rules
|
|
36
|
+
has_output_rule = self._has_output_dependent_rule(guardrail, [ApplyTo.OUTPUT])
|
|
37
|
+
|
|
38
|
+
# If guardrail has output-dependent rules, skip evaluation in pre-execution
|
|
39
|
+
# Output rules will be evaluated during post-execution
|
|
40
|
+
if has_output_rule:
|
|
41
|
+
return GuardrailValidationResult(
|
|
42
|
+
result=GuardrailValidationResultType.PASSED,
|
|
43
|
+
reason="Guardrail contains output-dependent rules that will be evaluated during post-execution",
|
|
44
|
+
)
|
|
30
45
|
return self._evaluate_deterministic_guardrail(
|
|
31
46
|
input_data=input_data,
|
|
32
47
|
output_data={},
|
|
@@ -41,12 +56,61 @@ class DeterministicGuardrailsService(BaseModel):
|
|
|
41
56
|
guardrail: DeterministicGuardrail,
|
|
42
57
|
) -> GuardrailValidationResult:
|
|
43
58
|
"""Evaluate deterministic guardrail rules against input and output data."""
|
|
59
|
+
# Check if guardrail contains any output-dependent rules
|
|
60
|
+
has_output_rule = self._has_output_dependent_rule(
|
|
61
|
+
guardrail, [ApplyTo.OUTPUT, ApplyTo.INPUT_AND_OUTPUT]
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
# If guardrail has no output-dependent rules, skip post-execution evaluation
|
|
65
|
+
# Only input rules exist and they should have been evaluated during pre-execution
|
|
66
|
+
if not has_output_rule:
|
|
67
|
+
return GuardrailValidationResult(
|
|
68
|
+
result=GuardrailValidationResultType.PASSED,
|
|
69
|
+
reason="Guardrail contains only input-dependent rules that were evaluated during pre-execution",
|
|
70
|
+
)
|
|
71
|
+
|
|
44
72
|
return self._evaluate_deterministic_guardrail(
|
|
45
73
|
input_data=input_data,
|
|
46
74
|
output_data=output_data,
|
|
47
75
|
guardrail=guardrail,
|
|
48
76
|
)
|
|
49
77
|
|
|
78
|
+
@staticmethod
|
|
79
|
+
def _has_output_dependent_rule(
|
|
80
|
+
guardrail: DeterministicGuardrail,
|
|
81
|
+
universal_rules_apply_to_values: list[ApplyTo],
|
|
82
|
+
) -> bool:
|
|
83
|
+
"""Check if at least one rule EXCLUSIVELY requires output data.
|
|
84
|
+
|
|
85
|
+
Args:
|
|
86
|
+
guardrail: The guardrail to check
|
|
87
|
+
universal_rules_apply_to_values: List of ApplyTo values to consider as output-dependent for UniversalRules.
|
|
88
|
+
|
|
89
|
+
Returns:
|
|
90
|
+
True if at least one rule exclusively depends on output data, False otherwise.
|
|
91
|
+
"""
|
|
92
|
+
for rule in guardrail.rules:
|
|
93
|
+
# UniversalRule: only return True if it applies to values in universal_rules_apply_to_values
|
|
94
|
+
if isinstance(rule, UniversalRule):
|
|
95
|
+
if rule.apply_to in universal_rules_apply_to_values:
|
|
96
|
+
return True
|
|
97
|
+
# Rules with field_selector
|
|
98
|
+
elif isinstance(rule, (WordRule, NumberRule, BooleanRule)):
|
|
99
|
+
field_selector = rule.field_selector
|
|
100
|
+
# AllFieldsSelector applies to both input and output, not exclusively output
|
|
101
|
+
# SpecificFieldsSelector: only return True if at least one field has OUTPUT source
|
|
102
|
+
if isinstance(field_selector, SpecificFieldsSelector):
|
|
103
|
+
if field_selector.fields and any(
|
|
104
|
+
field.source == FieldSource.OUTPUT
|
|
105
|
+
for field in field_selector.fields
|
|
106
|
+
):
|
|
107
|
+
return True
|
|
108
|
+
elif isinstance(field_selector, AllFieldsSelector):
|
|
109
|
+
if FieldSource.OUTPUT in field_selector.sources:
|
|
110
|
+
return True
|
|
111
|
+
|
|
112
|
+
return False
|
|
113
|
+
|
|
50
114
|
@staticmethod
|
|
51
115
|
def _evaluate_deterministic_guardrail(
|
|
52
116
|
input_data: dict[str, Any],
|
|
@@ -65,15 +129,17 @@ class DeterministicGuardrailsService(BaseModel):
|
|
|
65
129
|
passed, reason = evaluate_universal_rule(rule, output_data)
|
|
66
130
|
else:
|
|
67
131
|
return GuardrailValidationResult(
|
|
68
|
-
|
|
132
|
+
result=GuardrailValidationResultType.VALIDATION_FAILED,
|
|
69
133
|
reason=f"Unknown rule type: {type(rule)}",
|
|
70
134
|
)
|
|
71
135
|
|
|
72
136
|
if not passed:
|
|
73
137
|
return GuardrailValidationResult(
|
|
74
|
-
|
|
138
|
+
result=GuardrailValidationResultType.VALIDATION_FAILED,
|
|
139
|
+
reason=reason or "Rule validation failed",
|
|
75
140
|
)
|
|
76
141
|
|
|
77
142
|
return GuardrailValidationResult(
|
|
78
|
-
|
|
143
|
+
result=GuardrailValidationResultType.PASSED,
|
|
144
|
+
reason="All deterministic guardrail rules passed",
|
|
79
145
|
)
|
|
@@ -120,23 +120,25 @@ def get_fields_from_selector(
|
|
|
120
120
|
fields: list[tuple[Any, FieldReference]] = []
|
|
121
121
|
|
|
122
122
|
if isinstance(field_selector, AllFieldsSelector):
|
|
123
|
-
# For "all" selector, we need to collect all fields from
|
|
123
|
+
# For "all" selector, we need to collect all fields from the specified sources
|
|
124
124
|
# This is a simplified implementation - in practice, you might want to
|
|
125
125
|
# recursively collect all nested fields
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
(
|
|
129
|
-
|
|
130
|
-
|
|
126
|
+
if FieldSource.INPUT in field_selector.sources:
|
|
127
|
+
for key, value in input_data.items():
|
|
128
|
+
fields.append(
|
|
129
|
+
(
|
|
130
|
+
value,
|
|
131
|
+
FieldReference(path=key, source=FieldSource.INPUT),
|
|
132
|
+
)
|
|
131
133
|
)
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
134
|
+
if FieldSource.OUTPUT in field_selector.sources:
|
|
135
|
+
for key, value in output_data.items():
|
|
136
|
+
fields.append(
|
|
137
|
+
(
|
|
138
|
+
value,
|
|
139
|
+
FieldReference(path=key, source=FieldSource.OUTPUT),
|
|
140
|
+
)
|
|
138
141
|
)
|
|
139
|
-
)
|
|
140
142
|
elif isinstance(field_selector, SpecificFieldsSelector):
|
|
141
143
|
# For specific fields, extract values based on field references
|
|
142
144
|
for field_ref in field_selector.fields:
|
|
@@ -286,13 +288,13 @@ def evaluate_universal_rule(
|
|
|
286
288
|
|
|
287
289
|
Universal rules trigger based on the apply_to scope and execution phase:
|
|
288
290
|
- Pre-execution (empty output_data):
|
|
289
|
-
- INPUT: triggers (
|
|
290
|
-
- OUTPUT: does not trigger (
|
|
291
|
-
- INPUT_AND_OUTPUT: triggers (
|
|
291
|
+
- INPUT: triggers (result = VALIDATION_FAILED)
|
|
292
|
+
- OUTPUT: does not trigger (result = PASSED)
|
|
293
|
+
- INPUT_AND_OUTPUT: triggers (result = VALIDATION_FAILED)
|
|
292
294
|
- Post-execution (output_data has data):
|
|
293
|
-
- INPUT: does not trigger (
|
|
294
|
-
- OUTPUT: triggers (
|
|
295
|
-
- INPUT_AND_OUTPUT: triggers (
|
|
295
|
+
- INPUT: does not trigger (result = PASSED)
|
|
296
|
+
- OUTPUT: triggers (result = VALIDATION_FAILED)
|
|
297
|
+
- INPUT_AND_OUTPUT: triggers (result = VALIDATION_FAILED)
|
|
296
298
|
"""
|
|
297
299
|
# Determine if this is pre-execution (no output data) or post-execution
|
|
298
300
|
is_pre_execution = not output_data or len(output_data) == 0
|
|
@@ -6,18 +6,27 @@ from typing import Annotated, Callable, Literal
|
|
|
6
6
|
from pydantic import BaseModel, ConfigDict, Field
|
|
7
7
|
|
|
8
8
|
|
|
9
|
+
class GuardrailValidationResultType(str, Enum):
|
|
10
|
+
"""Guardrail validation result type enumeration."""
|
|
11
|
+
|
|
12
|
+
PASSED = "passed"
|
|
13
|
+
VALIDATION_FAILED = "validation_failed"
|
|
14
|
+
ENTITLEMENTS_MISSING = "entitlements_missing"
|
|
15
|
+
FEATURE_DISABLED = "feature_disabled"
|
|
16
|
+
|
|
17
|
+
|
|
9
18
|
class GuardrailValidationResult(BaseModel):
|
|
10
19
|
"""Result returned from validating input with a given guardrail.
|
|
11
20
|
|
|
12
21
|
Attributes:
|
|
13
|
-
|
|
22
|
+
result: The validation result type.
|
|
14
23
|
reason: Textual explanation describing why the validation passed or failed.
|
|
15
24
|
"""
|
|
16
25
|
|
|
17
26
|
model_config = ConfigDict(populate_by_name=True)
|
|
18
27
|
|
|
19
|
-
|
|
20
|
-
alias="
|
|
28
|
+
result: GuardrailValidationResultType = Field(
|
|
29
|
+
alias="result", description="Validation result."
|
|
21
30
|
)
|
|
22
31
|
reason: str = Field(
|
|
23
32
|
alias="reason", description="Explanation for the validation result."
|
|
@@ -59,6 +68,7 @@ class AllFieldsSelector(BaseModel):
|
|
|
59
68
|
"""All fields selector."""
|
|
60
69
|
|
|
61
70
|
selector_type: Literal["all"] = Field(alias="$selectorType")
|
|
71
|
+
sources: list[FieldSource]
|
|
62
72
|
|
|
63
73
|
model_config = ConfigDict(populate_by_name=True, extra="allow")
|
|
64
74
|
|
|
@@ -14,10 +14,10 @@ uipath/core/chat/meta.py,sha256=3t0eS9UHoAPHre97QTUeVbjDhnMX4zj4-qG6ju0B8wY,315
|
|
|
14
14
|
uipath/core/chat/tool.py,sha256=6e5pyX3hOWM5fIzr_fdG49Mbzz6XzJD3nsmha-yGa2k,2308
|
|
15
15
|
uipath/core/errors/__init__.py,sha256=gjxdLibZ0fjwgzPuLJY04P8dIX9rbSM2wQ97jP34ucE,278
|
|
16
16
|
uipath/core/errors/errors.py,sha256=5LajjuTfNW82ju07wT5mD3tXk0S-Ju7OqJqQpPN0F6g,486
|
|
17
|
-
uipath/core/guardrails/__init__.py,sha256=
|
|
18
|
-
uipath/core/guardrails/_deterministic_guardrails_service.py,sha256=
|
|
19
|
-
uipath/core/guardrails/_evaluators.py,sha256=
|
|
20
|
-
uipath/core/guardrails/guardrails.py,sha256=
|
|
17
|
+
uipath/core/guardrails/__init__.py,sha256=hUCmD4y5te2iy01YnJlBuf2RWvqxmsNzoyOamXLXf2E,1028
|
|
18
|
+
uipath/core/guardrails/_deterministic_guardrails_service.py,sha256=uX8f2HSGZ1bf5QFM9fnz0CvglxI3UIqY4OhHrKzemaU,5967
|
|
19
|
+
uipath/core/guardrails/_evaluators.py,sha256=ovmVm-8iB8Pm9arjG7mHM9-GIRkrG3V6oHRPHKxZVO0,14601
|
|
20
|
+
uipath/core/guardrails/guardrails.py,sha256=DraeFkoDKVDnc0EKdFYYP29lQu7U2hneTsj1dxveHU4,4935
|
|
21
21
|
uipath/core/tracing/__init__.py,sha256=1XNLYZ4J76XkRrizGO486mS6yxzVXUbrldpvxTyJe3E,483
|
|
22
22
|
uipath/core/tracing/_utils.py,sha256=FiCFGOFa4czruhlSF87Q5Q4jX9KKPHZiw8k14K7W5v4,6636
|
|
23
23
|
uipath/core/tracing/decorators.py,sha256=ag_MFwZ0TywrhbpLKqQwF1guvRA9sYiItxao5LN9_Iw,10942
|
|
@@ -25,7 +25,7 @@ uipath/core/tracing/exporters.py,sha256=FClouEEQfk3F8J7G_NFoarDJM3R0-gA5jUxA5xRH
|
|
|
25
25
|
uipath/core/tracing/processors.py,sha256=R_652rtjPmfpUtaXoIcmfZrRZylVXFRNwjOmJUUxOQw,1408
|
|
26
26
|
uipath/core/tracing/span_utils.py,sha256=WYBrd6ZbawAs7r1Js-Zvo9_8GzkD9LhHNOls00bK_xI,12235
|
|
27
27
|
uipath/core/tracing/trace_manager.py,sha256=51rscJcepkTK4bWoCZdE-DFc9wt2F-aSuFBaSXmkHl0,3130
|
|
28
|
-
uipath_core-0.1.
|
|
29
|
-
uipath_core-0.1.
|
|
30
|
-
uipath_core-0.1.
|
|
31
|
-
uipath_core-0.1.
|
|
28
|
+
uipath_core-0.1.6.dist-info/METADATA,sha256=R2wS5I85yHd-uTvGgepwbhKiZA7cLb389XJ5R57ED7I,938
|
|
29
|
+
uipath_core-0.1.6.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
30
|
+
uipath_core-0.1.6.dist-info/licenses/LICENSE,sha256=-KBavWXepyDjimmzH5fVAsi-6jNVpIKFc2kZs0Ri4ng,1058
|
|
31
|
+
uipath_core-0.1.6.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|