arthur-common 2.1.60__py3-none-any.whl → 2.1.61__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 arthur-common might be problematic. Click here for more details.
- arthur_common/aggregations/functions/agentic_aggregations.py +1 -1
- arthur_common/aggregations/functions/confusion_matrix.py +1 -1
- arthur_common/aggregations/functions/inference_count_by_class.py +1 -1
- arthur_common/aggregations/functions/mean_absolute_error.py +1 -1
- arthur_common/aggregations/functions/mean_squared_error.py +1 -1
- arthur_common/aggregations/functions/multiclass_confusion_matrix.py +1 -1
- arthur_common/aggregations/functions/multiclass_inference_count_by_class.py +1 -1
- arthur_common/aggregations/functions/shield_aggregations.py +1 -1
- arthur_common/models/common_schemas.py +208 -0
- arthur_common/models/connectors.py +3 -3
- arthur_common/models/constants.py +24 -0
- arthur_common/models/datasets.py +0 -9
- arthur_common/models/enums.py +144 -0
- arthur_common/models/metric_schemas.py +63 -0
- arthur_common/models/metrics.py +1 -1
- arthur_common/models/{shield.py → request_schemas.py} +204 -295
- arthur_common/models/response_schemas.py +682 -0
- arthur_common/models/schema_definitions.py +1 -1
- arthur_common/models/task_job_specs.py +3 -12
- {arthur_common-2.1.60.dist-info → arthur_common-2.1.61.dist-info}/METADATA +2 -1
- {arthur_common-2.1.60.dist-info → arthur_common-2.1.61.dist-info}/RECORD +22 -17
- {arthur_common-2.1.60.dist-info → arthur_common-2.1.61.dist-info}/WHEEL +0 -0
|
@@ -1,303 +1,39 @@
|
|
|
1
1
|
from datetime import datetime
|
|
2
|
-
from enum import Enum
|
|
3
2
|
from typing import Any, Dict, List, Optional, Self, Type, Union
|
|
4
3
|
|
|
5
4
|
from fastapi import HTTPException
|
|
5
|
+
from openinference.semconv.trace import OpenInferenceSpanKindValues
|
|
6
6
|
from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
class MetricType(str, Enum):
|
|
31
|
-
QUERY_RELEVANCE = "QueryRelevance"
|
|
32
|
-
RESPONSE_RELEVANCE = "ResponseRelevance"
|
|
33
|
-
TOOL_SELECTION = "ToolSelection"
|
|
34
|
-
|
|
35
|
-
def __str__(self) -> str:
|
|
36
|
-
return self.value
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
class BaseEnum(str, Enum):
|
|
40
|
-
@classmethod
|
|
41
|
-
def values(cls) -> list[Any]:
|
|
42
|
-
values: list[str] = [e for e in cls]
|
|
43
|
-
return values
|
|
44
|
-
|
|
45
|
-
def __str__(self) -> Any:
|
|
46
|
-
return self.value
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
# Note: These string values are not arbitrary and map to Presidio entity types: https://microsoft.github.io/presidio/supported_entities/
|
|
50
|
-
class PIIEntityTypes(BaseEnum):
|
|
51
|
-
CREDIT_CARD = "CREDIT_CARD"
|
|
52
|
-
CRYPTO = "CRYPTO"
|
|
53
|
-
DATE_TIME = "DATE_TIME"
|
|
54
|
-
EMAIL_ADDRESS = "EMAIL_ADDRESS"
|
|
55
|
-
IBAN_CODE = "IBAN_CODE"
|
|
56
|
-
IP_ADDRESS = "IP_ADDRESS"
|
|
57
|
-
NRP = "NRP"
|
|
58
|
-
LOCATION = "LOCATION"
|
|
59
|
-
PERSON = "PERSON"
|
|
60
|
-
PHONE_NUMBER = "PHONE_NUMBER"
|
|
61
|
-
MEDICAL_LICENSE = "MEDICAL_LICENSE"
|
|
62
|
-
URL = "URL"
|
|
63
|
-
US_BANK_NUMBER = "US_BANK_NUMBER"
|
|
64
|
-
US_DRIVER_LICENSE = "US_DRIVER_LICENSE"
|
|
65
|
-
US_ITIN = "US_ITIN"
|
|
66
|
-
US_PASSPORT = "US_PASSPORT"
|
|
67
|
-
US_SSN = "US_SSN"
|
|
68
|
-
|
|
69
|
-
@classmethod
|
|
70
|
-
def to_string(cls) -> str:
|
|
71
|
-
return ",".join(member.value for member in cls)
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
class KeywordsConfig(BaseModel):
|
|
75
|
-
keywords: List[str] = Field(description="List of Keywords")
|
|
76
|
-
|
|
77
|
-
model_config = ConfigDict(
|
|
78
|
-
json_schema_extra={
|
|
79
|
-
"example": {"keywords": ["Blocked_Keyword_1", "Blocked_Keyword_2"]},
|
|
80
|
-
},
|
|
81
|
-
)
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
class RegexConfig(BaseModel):
|
|
85
|
-
regex_patterns: List[str] = Field(
|
|
86
|
-
description="List of Regex patterns to be used for validation. Be sure to encode requests in JSON and account for escape characters.",
|
|
87
|
-
)
|
|
88
|
-
|
|
89
|
-
model_config = ConfigDict(
|
|
90
|
-
json_schema_extra={
|
|
91
|
-
"example": {
|
|
92
|
-
"regex_patterns": ["\\d{3}-\\d{2}-\\d{4}", "\\d{5}-\\d{6}-\\d{7}"],
|
|
93
|
-
},
|
|
94
|
-
},
|
|
95
|
-
extra="forbid",
|
|
96
|
-
)
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
class ToxicityConfig(BaseModel):
|
|
100
|
-
threshold: float = Field(
|
|
101
|
-
default=DEFAULT_TOXICITY_RULE_THRESHOLD,
|
|
102
|
-
description=f"Optional. Float (0, 1) indicating the level of tolerable toxicity to consider the rule passed or failed. Min: 0 (no toxic language) Max: 1 (very toxic language). Default: {DEFAULT_TOXICITY_RULE_THRESHOLD}",
|
|
103
|
-
)
|
|
104
|
-
|
|
105
|
-
model_config = ConfigDict(
|
|
106
|
-
extra="forbid",
|
|
107
|
-
json_schema_extra={"example": {"threshold": DEFAULT_TOXICITY_RULE_THRESHOLD}},
|
|
108
|
-
)
|
|
109
|
-
|
|
110
|
-
@field_validator("threshold")
|
|
111
|
-
def validate_toxicity_threshold(cls, v: float) -> float:
|
|
112
|
-
if v and ((v < 0) | (v > 1)):
|
|
113
|
-
raise ValueError(f'"threshold" must be between 0 and 1')
|
|
114
|
-
return v
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
class PIIConfig(BaseModel):
|
|
118
|
-
disabled_pii_entities: Optional[list[str]] = Field(
|
|
119
|
-
description=f"Optional. List of PII entities to disable. Valid values are: {PIIEntityTypes.to_string()}",
|
|
120
|
-
default=None,
|
|
121
|
-
)
|
|
122
|
-
|
|
123
|
-
confidence_threshold: Optional[float] = Field(
|
|
124
|
-
description=f"Optional. Float (0, 1) indicating the level of tolerable PII to consider the rule passed or failed. Min: 0 (less confident) Max: 1 (very confident). Default: {DEFAULT_PII_RULE_CONFIDENCE_SCORE_THRESHOLD}",
|
|
125
|
-
default=DEFAULT_PII_RULE_CONFIDENCE_SCORE_THRESHOLD,
|
|
126
|
-
json_schema_extra={"deprecated": True},
|
|
127
|
-
)
|
|
128
|
-
|
|
129
|
-
allow_list: Optional[list[str]] = Field(
|
|
130
|
-
description="Optional. List of strings to pass PII validation.",
|
|
131
|
-
default=None,
|
|
132
|
-
)
|
|
133
|
-
|
|
134
|
-
@field_validator("disabled_pii_entities")
|
|
135
|
-
def validate_pii_entities(cls, v: Optional[List[str]]) -> Optional[List[str]]:
|
|
136
|
-
if v:
|
|
137
|
-
entities_passed = set(v)
|
|
138
|
-
entities_supported = set(PIIEntityTypes.values())
|
|
139
|
-
invalid_entities = entities_passed - entities_supported
|
|
140
|
-
if invalid_entities:
|
|
141
|
-
raise ValueError(
|
|
142
|
-
f"The following values are not valid PII entities: {invalid_entities}",
|
|
143
|
-
)
|
|
144
|
-
|
|
145
|
-
# Fail the case where they are trying to disable all PII entity types
|
|
146
|
-
if (not invalid_entities) & (
|
|
147
|
-
len(entities_passed) == len(entities_supported)
|
|
148
|
-
):
|
|
149
|
-
raise ValueError(
|
|
150
|
-
f"Cannot disable all supported PII entities on PIIDataRule",
|
|
151
|
-
)
|
|
152
|
-
return v
|
|
153
|
-
else:
|
|
154
|
-
return v
|
|
155
|
-
|
|
156
|
-
@field_validator("confidence_threshold")
|
|
157
|
-
def validate_confidence_threshold(cls, v: Optional[float]) -> Optional[float]:
|
|
158
|
-
if v and ((v < 0) | (v > 1)):
|
|
159
|
-
raise ValueError(f'"confidence_threshold" must be between 0 and 1')
|
|
160
|
-
return v
|
|
161
|
-
|
|
162
|
-
model_config = ConfigDict(
|
|
163
|
-
json_schema_extra={
|
|
164
|
-
"example": {
|
|
165
|
-
"disabled_pii_entities": ["PERSON", "URL"],
|
|
166
|
-
"confidence_threshold": "0.5",
|
|
167
|
-
"allow_list": ["arthur.ai", "Arthur"],
|
|
168
|
-
},
|
|
169
|
-
},
|
|
170
|
-
extra="forbid",
|
|
171
|
-
)
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
NEGATIVE_BLOOD_EXAMPLE = "John has O negative blood group"
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
class ExampleConfig(BaseModel):
|
|
178
|
-
example: str = Field(description="Custom example for the sensitive data")
|
|
179
|
-
result: bool = Field(
|
|
180
|
-
description="Boolean value representing if the example passes or fails the the sensitive "
|
|
181
|
-
"data rule ",
|
|
182
|
-
)
|
|
183
|
-
|
|
184
|
-
model_config = ConfigDict(
|
|
185
|
-
json_schema_extra={
|
|
186
|
-
"example": {"example": NEGATIVE_BLOOD_EXAMPLE, "result": True},
|
|
187
|
-
},
|
|
188
|
-
)
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
class ExamplesConfig(BaseModel):
|
|
192
|
-
examples: List[ExampleConfig] = Field(
|
|
193
|
-
description="List of all the examples for Sensitive Data Rule",
|
|
194
|
-
)
|
|
195
|
-
|
|
196
|
-
model_config = ConfigDict(
|
|
197
|
-
json_schema_extra={
|
|
198
|
-
"example": {
|
|
199
|
-
"examples": [
|
|
200
|
-
{"example": NEGATIVE_BLOOD_EXAMPLE, "result": True},
|
|
201
|
-
{
|
|
202
|
-
"example": "Most of the people have A positive blood group",
|
|
203
|
-
"result": False,
|
|
204
|
-
},
|
|
205
|
-
],
|
|
206
|
-
"hint": "specific individual's blood type",
|
|
207
|
-
},
|
|
208
|
-
},
|
|
209
|
-
)
|
|
210
|
-
hint: Optional[str] = Field(
|
|
211
|
-
description="Optional. Hint added to describe what Sensitive Data Rule should be checking for",
|
|
212
|
-
default=None,
|
|
213
|
-
)
|
|
214
|
-
|
|
215
|
-
def to_dict(self) -> Dict[str, Any]:
|
|
216
|
-
d = self.__dict__
|
|
217
|
-
d["examples"] = [ex.__dict__ for ex in self.examples]
|
|
218
|
-
d["hint"] = self.hint
|
|
219
|
-
return d
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
class RuleResponse(BaseModel):
|
|
223
|
-
id: str = Field(description="ID of the Rule")
|
|
224
|
-
name: str = Field(description="Name of the Rule")
|
|
225
|
-
type: RuleType = Field(description="Type of Rule")
|
|
226
|
-
apply_to_prompt: bool = Field(description="Rule applies to prompt")
|
|
227
|
-
apply_to_response: bool = Field(description="Rule applies to response")
|
|
228
|
-
enabled: Optional[bool] = Field(
|
|
229
|
-
description="Rule is enabled for the task",
|
|
230
|
-
default=None,
|
|
231
|
-
)
|
|
232
|
-
scope: RuleScope = Field(
|
|
233
|
-
description="Scope of the rule. The rule can be set at default level or task level.",
|
|
234
|
-
)
|
|
235
|
-
# UNIX millis format
|
|
236
|
-
created_at: int = Field(
|
|
237
|
-
description="Time the rule was created in unix milliseconds",
|
|
238
|
-
)
|
|
239
|
-
updated_at: int = Field(
|
|
240
|
-
description="Time the rule was updated in unix milliseconds",
|
|
241
|
-
)
|
|
242
|
-
# added a title to this to differentiate it in the generated client from the
|
|
243
|
-
# config field on the NewRuleRequest object
|
|
244
|
-
config: Optional[
|
|
245
|
-
Union[KeywordsConfig, RegexConfig, ExamplesConfig, ToxicityConfig, PIIConfig]
|
|
246
|
-
] = Field(
|
|
247
|
-
description="Config of the rule",
|
|
248
|
-
default=None,
|
|
249
|
-
title="Rule Response Config",
|
|
250
|
-
)
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
class MetricResponse(BaseModel):
|
|
254
|
-
id: str = Field(description="ID of the Metric")
|
|
255
|
-
name: str = Field(description="Name of the Metric")
|
|
256
|
-
type: MetricType = Field(description="Type of the Metric")
|
|
257
|
-
metric_metadata: str = Field(description="Metadata of the Metric")
|
|
258
|
-
config: Optional[str] = Field(
|
|
259
|
-
description="JSON-serialized configuration for the Metric",
|
|
260
|
-
default=None,
|
|
261
|
-
)
|
|
262
|
-
created_at: datetime = Field(
|
|
263
|
-
description="Time the Metric was created in unix milliseconds",
|
|
264
|
-
)
|
|
265
|
-
updated_at: datetime = Field(
|
|
266
|
-
description="Time the Metric was updated in unix milliseconds",
|
|
267
|
-
)
|
|
268
|
-
enabled: Optional[bool] = Field(
|
|
269
|
-
description="Whether the Metric is enabled",
|
|
270
|
-
default=None,
|
|
271
|
-
)
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
class TaskResponse(BaseModel):
|
|
275
|
-
id: str = Field(description=" ID of the task")
|
|
276
|
-
name: str = Field(description="Name of the task")
|
|
277
|
-
created_at: int = Field(
|
|
278
|
-
description="Time the task was created in unix milliseconds",
|
|
279
|
-
)
|
|
280
|
-
updated_at: int = Field(
|
|
281
|
-
description="Time the task was created in unix milliseconds",
|
|
282
|
-
)
|
|
283
|
-
is_agentic: Optional[bool] = Field(
|
|
284
|
-
description="Whether the task is agentic or not",
|
|
285
|
-
default=None,
|
|
286
|
-
)
|
|
287
|
-
rules: List[RuleResponse] = Field(description="List of all the rules for the task.")
|
|
288
|
-
metrics: Optional[List[MetricResponse]] = Field(
|
|
289
|
-
description="List of all the metrics for the task.",
|
|
290
|
-
default=None,
|
|
291
|
-
)
|
|
8
|
+
from arthur_common.models.common_schemas import (
|
|
9
|
+
ExamplesConfig,
|
|
10
|
+
KeywordsConfig,
|
|
11
|
+
PIIConfig,
|
|
12
|
+
RegexConfig,
|
|
13
|
+
ToxicityConfig,
|
|
14
|
+
)
|
|
15
|
+
from arthur_common.models.constants import (
|
|
16
|
+
ERROR_PASSWORD_POLICY_NOT_MET,
|
|
17
|
+
GENAI_ENGINE_KEYCLOAK_PASSWORD_LENGTH,
|
|
18
|
+
HALLUCINATION_RULE_NAME,
|
|
19
|
+
NEGATIVE_BLOOD_EXAMPLE,
|
|
20
|
+
)
|
|
21
|
+
from arthur_common.models.enums import (
|
|
22
|
+
APIKeysRolesEnum,
|
|
23
|
+
InferenceFeedbackTarget,
|
|
24
|
+
MetricType,
|
|
25
|
+
PIIEntityTypes,
|
|
26
|
+
RuleScope,
|
|
27
|
+
RuleType,
|
|
28
|
+
)
|
|
29
|
+
from arthur_common.models.metric_schemas import RelevanceMetricConfig
|
|
292
30
|
|
|
293
31
|
|
|
294
32
|
class UpdateRuleRequest(BaseModel):
|
|
295
33
|
enabled: bool = Field(description="Boolean value to enable or disable the rule. ")
|
|
296
34
|
|
|
297
35
|
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
36
|
+
# Using the latest version from arthur-common
|
|
301
37
|
class NewRuleRequest(BaseModel):
|
|
302
38
|
name: str = Field(description="Name of the rule", examples=["SSN Regex Rule"])
|
|
303
39
|
type: str = Field(
|
|
@@ -525,19 +261,148 @@ class NewRuleRequest(BaseModel):
|
|
|
525
261
|
return self
|
|
526
262
|
|
|
527
263
|
|
|
528
|
-
class
|
|
529
|
-
|
|
264
|
+
class SearchTasksRequest(BaseModel):
|
|
265
|
+
task_ids: Optional[list[str]] = Field(
|
|
266
|
+
description="List of tasks to query for.",
|
|
267
|
+
default=None,
|
|
268
|
+
)
|
|
269
|
+
task_name: Optional[str] = Field(
|
|
270
|
+
description="Task name substring search string.",
|
|
271
|
+
default=None,
|
|
272
|
+
)
|
|
273
|
+
is_agentic: Optional[bool] = Field(
|
|
274
|
+
description="Filter tasks by agentic status. If not provided, returns both agentic and non-agentic tasks.",
|
|
275
|
+
default=None,
|
|
276
|
+
)
|
|
277
|
+
|
|
530
278
|
|
|
531
|
-
|
|
279
|
+
class SearchRulesRequest(BaseModel):
|
|
280
|
+
rule_ids: Optional[list[str]] = Field(
|
|
281
|
+
description="List of rule IDs to search for.",
|
|
532
282
|
default=None,
|
|
533
|
-
description="Threshold for determining relevance when not using LLM judge",
|
|
534
283
|
)
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
284
|
+
rule_scopes: Optional[list[RuleScope]] = Field(
|
|
285
|
+
description="List of rule scopes to search for.",
|
|
286
|
+
default=None,
|
|
287
|
+
)
|
|
288
|
+
prompt_enabled: Optional[bool] = Field(
|
|
289
|
+
description="Include or exclude prompt-enabled rules.",
|
|
290
|
+
default=None,
|
|
291
|
+
)
|
|
292
|
+
response_enabled: Optional[bool] = Field(
|
|
293
|
+
description="Include or exclude response-enabled rules.",
|
|
294
|
+
default=None,
|
|
295
|
+
)
|
|
296
|
+
rule_types: Optional[list[RuleType]] = Field(
|
|
297
|
+
description="List of rule types to search for.",
|
|
298
|
+
default=None,
|
|
538
299
|
)
|
|
539
300
|
|
|
540
301
|
|
|
302
|
+
class NewTaskRequest(BaseModel):
|
|
303
|
+
name: str = Field(description="Name of the task.", min_length=1)
|
|
304
|
+
is_agentic: bool = Field(
|
|
305
|
+
description="Whether the task is agentic or not.",
|
|
306
|
+
default=False,
|
|
307
|
+
)
|
|
308
|
+
|
|
309
|
+
|
|
310
|
+
class NewApiKeyRequest(BaseModel):
|
|
311
|
+
description: Optional[str] = Field(
|
|
312
|
+
description="Description of the API key. Optional.",
|
|
313
|
+
default=None,
|
|
314
|
+
)
|
|
315
|
+
roles: Optional[list[APIKeysRolesEnum]] = Field(
|
|
316
|
+
description=f"Role that will be assigned to API key. Allowed values: {[role for role in APIKeysRolesEnum]}",
|
|
317
|
+
default=[APIKeysRolesEnum.VALIDATION_USER],
|
|
318
|
+
)
|
|
319
|
+
|
|
320
|
+
|
|
321
|
+
class PromptValidationRequest(BaseModel):
|
|
322
|
+
prompt: str = Field(description="Prompt to be validated by GenAI Engine")
|
|
323
|
+
# context: Optional[str] = Field(
|
|
324
|
+
# description="Optional data provided as context for the prompt validation. "
|
|
325
|
+
# "Currently not used"
|
|
326
|
+
# )
|
|
327
|
+
conversation_id: Optional[str] = Field(
|
|
328
|
+
description="The unique conversation ID this prompt belongs to. All prompts and responses from this \
|
|
329
|
+
conversation can later be reconstructed with this ID.",
|
|
330
|
+
default=None,
|
|
331
|
+
)
|
|
332
|
+
user_id: Optional[str] = Field(
|
|
333
|
+
description="The user ID this prompt belongs to",
|
|
334
|
+
default=None,
|
|
335
|
+
)
|
|
336
|
+
|
|
337
|
+
|
|
338
|
+
class ResponseValidationRequest(BaseModel):
|
|
339
|
+
response: str = Field(description="LLM Response to be validated by GenAI Engine")
|
|
340
|
+
context: Optional[str] = Field(
|
|
341
|
+
description="Optional data provided as context for the validation.",
|
|
342
|
+
default=None,
|
|
343
|
+
)
|
|
344
|
+
# tokens: Optional[List[str]] = Field(description="optional, not used currently")
|
|
345
|
+
# token_likelihoods: Optional[List[str]] = Field(
|
|
346
|
+
# description="optional, not used currently"
|
|
347
|
+
# )
|
|
348
|
+
|
|
349
|
+
@model_validator(mode="after")
|
|
350
|
+
def check_prompt_or_response(cls, values: Any) -> Any:
|
|
351
|
+
if isinstance(values, PromptValidationRequest) and values.prompt is None:
|
|
352
|
+
raise ValueError("prompt is required when validating a prompt")
|
|
353
|
+
if isinstance(values, ResponseValidationRequest) and values.response is None:
|
|
354
|
+
raise ValueError("response is required when validating a response")
|
|
355
|
+
return values
|
|
356
|
+
|
|
357
|
+
|
|
358
|
+
class ChatRequest(BaseModel):
|
|
359
|
+
user_prompt: str = Field(description="Prompt user wants to send to chat.")
|
|
360
|
+
conversation_id: str = Field(description="Conversation ID")
|
|
361
|
+
file_ids: List[str] = Field(
|
|
362
|
+
description="list of file IDs to retrieve from during chat.",
|
|
363
|
+
)
|
|
364
|
+
|
|
365
|
+
|
|
366
|
+
class FeedbackRequest(BaseModel):
|
|
367
|
+
target: InferenceFeedbackTarget
|
|
368
|
+
score: int
|
|
369
|
+
reason: str | None
|
|
370
|
+
user_id: str | None = None
|
|
371
|
+
|
|
372
|
+
|
|
373
|
+
class CreateUserRequest(BaseModel):
|
|
374
|
+
email: str
|
|
375
|
+
password: str
|
|
376
|
+
temporary: bool = True
|
|
377
|
+
roles: list[str]
|
|
378
|
+
firstName: str
|
|
379
|
+
lastName: str
|
|
380
|
+
|
|
381
|
+
|
|
382
|
+
class PasswordResetRequest(BaseModel):
|
|
383
|
+
password: str
|
|
384
|
+
|
|
385
|
+
@field_validator("password")
|
|
386
|
+
@classmethod
|
|
387
|
+
def password_meets_security(cls, value: str) -> str:
|
|
388
|
+
special_characters = '!@#$%^&*()-+?_=,<>/"'
|
|
389
|
+
if not len(value) >= GENAI_ENGINE_KEYCLOAK_PASSWORD_LENGTH:
|
|
390
|
+
raise ValueError(ERROR_PASSWORD_POLICY_NOT_MET)
|
|
391
|
+
if (
|
|
392
|
+
not any(c.isupper() for c in value)
|
|
393
|
+
or not any(c.islower() for c in value)
|
|
394
|
+
or not any(c.isdigit() for c in value)
|
|
395
|
+
or not any(c in special_characters for c in value)
|
|
396
|
+
):
|
|
397
|
+
raise ValueError(ERROR_PASSWORD_POLICY_NOT_MET)
|
|
398
|
+
return value
|
|
399
|
+
|
|
400
|
+
|
|
401
|
+
class ChatDefaultTaskRequest(BaseModel):
|
|
402
|
+
task_id: str
|
|
403
|
+
|
|
404
|
+
|
|
405
|
+
# Using the latest version from arthur-common
|
|
541
406
|
class NewMetricRequest(BaseModel):
|
|
542
407
|
type: MetricType = Field(
|
|
543
408
|
description="Type of the metric. It can only be one of QueryRelevance, ResponseRelevance, ToolSelection",
|
|
@@ -640,3 +505,47 @@ class NewMetricRequest(BaseModel):
|
|
|
640
505
|
)
|
|
641
506
|
|
|
642
507
|
return values
|
|
508
|
+
|
|
509
|
+
|
|
510
|
+
class UpdateMetricRequest(BaseModel):
|
|
511
|
+
enabled: bool = Field(description="Boolean value to enable or disable the metric. ")
|
|
512
|
+
|
|
513
|
+
|
|
514
|
+
class SpanQueryRequest(BaseModel):
|
|
515
|
+
"""Request schema for querying spans with validation."""
|
|
516
|
+
|
|
517
|
+
task_ids: list[str] = Field(
|
|
518
|
+
...,
|
|
519
|
+
description="Task IDs to filter on. At least one is required.",
|
|
520
|
+
min_length=1,
|
|
521
|
+
)
|
|
522
|
+
span_types: Optional[list[str]] = Field(
|
|
523
|
+
None,
|
|
524
|
+
description=f"Span types to filter on. Optional. Valid values: {', '.join(sorted([kind.value for kind in OpenInferenceSpanKindValues]))}",
|
|
525
|
+
)
|
|
526
|
+
start_time: Optional[datetime] = Field(
|
|
527
|
+
None,
|
|
528
|
+
description="Inclusive start date in ISO8601 string format.",
|
|
529
|
+
)
|
|
530
|
+
end_time: Optional[datetime] = Field(
|
|
531
|
+
None,
|
|
532
|
+
description="Exclusive end date in ISO8601 string format.",
|
|
533
|
+
)
|
|
534
|
+
|
|
535
|
+
@field_validator("span_types")
|
|
536
|
+
@classmethod
|
|
537
|
+
def validate_span_types(cls, value: list[str]) -> list[str]:
|
|
538
|
+
"""Validate that all span_types are valid OpenInference span kinds."""
|
|
539
|
+
if not value:
|
|
540
|
+
return value
|
|
541
|
+
|
|
542
|
+
# Get all valid span kind values
|
|
543
|
+
valid_span_kinds = [kind.value for kind in OpenInferenceSpanKindValues]
|
|
544
|
+
invalid_types = [st for st in value if st not in valid_span_kinds]
|
|
545
|
+
|
|
546
|
+
if invalid_types:
|
|
547
|
+
raise ValueError(
|
|
548
|
+
f"Invalid span_types received: {invalid_types}. "
|
|
549
|
+
f"Valid values: {', '.join(sorted(valid_span_kinds))}",
|
|
550
|
+
)
|
|
551
|
+
return value
|