agenta 0.27.0__py3-none-any.whl → 0.27.0a1__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 agenta might be problematic. Click here for more details.
- agenta/__init__.py +3 -22
- agenta/cli/helper.py +1 -5
- agenta/client/backend/__init__.py +0 -14
- agenta/client/backend/apps/client.py +20 -28
- agenta/client/backend/client.py +2 -25
- agenta/client/backend/containers/client.py +1 -5
- agenta/client/backend/core/__init__.py +1 -2
- agenta/client/backend/core/client_wrapper.py +6 -6
- agenta/client/backend/core/file.py +11 -33
- agenta/client/backend/core/http_client.py +18 -24
- agenta/client/backend/core/pydantic_utilities.py +29 -144
- agenta/client/backend/core/request_options.py +0 -3
- agenta/client/backend/core/serialization.py +42 -139
- agenta/client/backend/evaluations/client.py +2 -7
- agenta/client/backend/evaluators/client.py +1 -349
- agenta/client/backend/observability/client.py +2 -11
- agenta/client/backend/testsets/client.py +10 -10
- agenta/client/backend/types/__init__.py +0 -14
- agenta/client/backend/types/app.py +0 -1
- agenta/client/backend/types/app_variant_response.py +1 -3
- agenta/client/backend/types/create_span.py +2 -3
- agenta/client/backend/types/environment_output.py +0 -1
- agenta/client/backend/types/environment_output_extended.py +0 -1
- agenta/client/backend/types/evaluation.py +2 -1
- agenta/client/backend/types/evaluator.py +0 -2
- agenta/client/backend/types/evaluator_config.py +0 -1
- agenta/client/backend/types/human_evaluation.py +2 -1
- agenta/client/backend/types/llm_tokens.py +2 -2
- agenta/client/backend/types/span.py +0 -1
- agenta/client/backend/types/span_detail.py +1 -7
- agenta/client/backend/types/test_set_output_response.py +2 -5
- agenta/client/backend/types/trace_detail.py +1 -7
- agenta/client/backend/types/with_pagination.py +2 -4
- agenta/client/backend/variants/client.py +273 -1566
- agenta/docker/docker-assets/Dockerfile.cloud.template +1 -1
- agenta/sdk/__init__.py +5 -20
- agenta/sdk/agenta_init.py +26 -30
- agenta/sdk/config_manager.py +205 -0
- agenta/sdk/context/routing.py +5 -6
- agenta/sdk/decorators/routing.py +135 -142
- agenta/sdk/decorators/tracing.py +245 -206
- agenta/sdk/litellm/litellm.py +36 -47
- agenta/sdk/tracing/attributes.py +2 -7
- agenta/sdk/tracing/context.py +2 -5
- agenta/sdk/tracing/conventions.py +8 -10
- agenta/sdk/tracing/exporters.py +6 -15
- agenta/sdk/tracing/inline.py +98 -70
- agenta/sdk/tracing/processors.py +14 -55
- agenta/sdk/tracing/spans.py +4 -16
- agenta/sdk/tracing/tracing.py +50 -54
- agenta/sdk/types.py +2 -61
- agenta/sdk/utils/exceptions.py +1 -31
- {agenta-0.27.0.dist-info → agenta-0.27.0a1.dist-info}/METADATA +1 -1
- {agenta-0.27.0.dist-info → agenta-0.27.0a1.dist-info}/RECORD +56 -67
- agenta/client/backend/types/config_dto.py +0 -32
- agenta/client/backend/types/config_response_model.py +0 -32
- agenta/client/backend/types/evaluator_mapping_output_interface.py +0 -21
- agenta/client/backend/types/evaluator_output_interface.py +0 -21
- agenta/client/backend/types/lifecycle_dto.py +0 -24
- agenta/client/backend/types/reference_dto.py +0 -23
- agenta/client/backend/types/reference_request_model.py +0 -23
- agenta/sdk/managers/__init__.py +0 -6
- agenta/sdk/managers/config.py +0 -318
- agenta/sdk/managers/deployment.py +0 -45
- agenta/sdk/managers/shared.py +0 -639
- agenta/sdk/managers/variant.py +0 -182
- {agenta-0.27.0.dist-info → agenta-0.27.0a1.dist-info}/WHEEL +0 -0
- {agenta-0.27.0.dist-info → agenta-0.27.0a1.dist-info}/entry_points.txt +0 -0
|
@@ -10,7 +10,6 @@ import typing_extensions
|
|
|
10
10
|
import pydantic
|
|
11
11
|
|
|
12
12
|
from .datetime_utils import serialize_datetime
|
|
13
|
-
from .serialization import convert_and_respect_annotation_metadata
|
|
14
13
|
|
|
15
14
|
IS_PYDANTIC_V2 = pydantic.VERSION.startswith("2.")
|
|
16
15
|
|
|
@@ -57,14 +56,11 @@ Model = typing.TypeVar("Model", bound=pydantic.BaseModel)
|
|
|
57
56
|
|
|
58
57
|
|
|
59
58
|
def parse_obj_as(type_: typing.Type[T], object_: typing.Any) -> T:
|
|
60
|
-
dealiased_object = convert_and_respect_annotation_metadata(
|
|
61
|
-
object_=object_, annotation=type_, direction="read"
|
|
62
|
-
)
|
|
63
59
|
if IS_PYDANTIC_V2:
|
|
64
60
|
adapter = pydantic.TypeAdapter(type_) # type: ignore # Pydantic v2
|
|
65
|
-
return adapter.validate_python(
|
|
61
|
+
return adapter.validate_python(object_)
|
|
66
62
|
else:
|
|
67
|
-
return pydantic.parse_obj_as(type_,
|
|
63
|
+
return pydantic.parse_obj_as(type_, object_)
|
|
68
64
|
|
|
69
65
|
|
|
70
66
|
def to_jsonable_with_fallback(
|
|
@@ -79,53 +75,9 @@ def to_jsonable_with_fallback(
|
|
|
79
75
|
|
|
80
76
|
|
|
81
77
|
class UniversalBaseModel(pydantic.BaseModel):
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
protected_namespaces=(),
|
|
86
|
-
) # type: ignore # Pydantic v2
|
|
87
|
-
|
|
88
|
-
@pydantic.model_serializer(mode="wrap", when_used="json") # type: ignore # Pydantic v2
|
|
89
|
-
def serialize_model(
|
|
90
|
-
self, handler: pydantic.SerializerFunctionWrapHandler
|
|
91
|
-
) -> typing.Any: # type: ignore # Pydantic v2
|
|
92
|
-
serialized = handler(self)
|
|
93
|
-
data = {
|
|
94
|
-
k: serialize_datetime(v) if isinstance(v, dt.datetime) else v
|
|
95
|
-
for k, v in serialized.items()
|
|
96
|
-
}
|
|
97
|
-
return data
|
|
98
|
-
|
|
99
|
-
else:
|
|
100
|
-
|
|
101
|
-
class Config:
|
|
102
|
-
smart_union = True
|
|
103
|
-
json_encoders = {dt.datetime: serialize_datetime}
|
|
104
|
-
|
|
105
|
-
@classmethod
|
|
106
|
-
def model_construct(
|
|
107
|
-
cls: typing.Type["Model"],
|
|
108
|
-
_fields_set: typing.Optional[typing.Set[str]] = None,
|
|
109
|
-
**values: typing.Any,
|
|
110
|
-
) -> "Model":
|
|
111
|
-
dealiased_object = convert_and_respect_annotation_metadata(
|
|
112
|
-
object_=values, annotation=cls, direction="read"
|
|
113
|
-
)
|
|
114
|
-
return cls.construct(_fields_set, **dealiased_object)
|
|
115
|
-
|
|
116
|
-
@classmethod
|
|
117
|
-
def construct(
|
|
118
|
-
cls: typing.Type["Model"],
|
|
119
|
-
_fields_set: typing.Optional[typing.Set[str]] = None,
|
|
120
|
-
**values: typing.Any,
|
|
121
|
-
) -> "Model":
|
|
122
|
-
dealiased_object = convert_and_respect_annotation_metadata(
|
|
123
|
-
object_=values, annotation=cls, direction="read"
|
|
124
|
-
)
|
|
125
|
-
if IS_PYDANTIC_V2:
|
|
126
|
-
return super().model_construct(_fields_set, **dealiased_object) # type: ignore # Pydantic v2
|
|
127
|
-
else:
|
|
128
|
-
return super().construct(_fields_set, **dealiased_object)
|
|
78
|
+
class Config:
|
|
79
|
+
populate_by_name = True
|
|
80
|
+
json_encoders = {dt.datetime: serialize_datetime}
|
|
129
81
|
|
|
130
82
|
def json(self, **kwargs: typing.Any) -> str:
|
|
131
83
|
kwargs_with_defaults: typing.Any = {
|
|
@@ -143,97 +95,30 @@ class UniversalBaseModel(pydantic.BaseModel):
|
|
|
143
95
|
Override the default dict method to `exclude_unset` by default. This function patches
|
|
144
96
|
`exclude_unset` to work include fields within non-None default values.
|
|
145
97
|
"""
|
|
146
|
-
|
|
147
|
-
# Pydantic V1's .dict can be extremely slow, so we do not want to call it twice.
|
|
148
|
-
#
|
|
149
|
-
# We'd ideally do the same for Pydantic V2, but it shells out to a library to serialize models
|
|
150
|
-
# that we have less control over, and this is less intrusive than custom serializers for now.
|
|
151
|
-
if IS_PYDANTIC_V2:
|
|
152
|
-
kwargs_with_defaults_exclude_unset: typing.Any = {
|
|
153
|
-
**kwargs,
|
|
154
|
-
"by_alias": True,
|
|
155
|
-
"exclude_unset": True,
|
|
156
|
-
"exclude_none": False,
|
|
157
|
-
}
|
|
158
|
-
kwargs_with_defaults_exclude_none: typing.Any = {
|
|
159
|
-
**kwargs,
|
|
160
|
-
"by_alias": True,
|
|
161
|
-
"exclude_none": True,
|
|
162
|
-
"exclude_unset": False,
|
|
163
|
-
}
|
|
164
|
-
dict_dump = deep_union_pydantic_dicts(
|
|
165
|
-
super().model_dump(**kwargs_with_defaults_exclude_unset), # type: ignore # Pydantic v2
|
|
166
|
-
super().model_dump(**kwargs_with_defaults_exclude_none), # type: ignore # Pydantic v2
|
|
167
|
-
)
|
|
98
|
+
_fields_set = self.__fields_set__
|
|
168
99
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
# the latter passes through intentionally set none values.
|
|
180
|
-
if default is not None or (
|
|
181
|
-
"exclude_unset" in kwargs and not kwargs["exclude_unset"]
|
|
182
|
-
):
|
|
183
|
-
_fields_set.add(name)
|
|
184
|
-
|
|
185
|
-
if default is not None:
|
|
186
|
-
self.__fields_set__.add(name)
|
|
187
|
-
|
|
188
|
-
kwargs_with_defaults_exclude_unset_include_fields: typing.Any = {
|
|
189
|
-
"by_alias": True,
|
|
190
|
-
"exclude_unset": True,
|
|
191
|
-
"include": _fields_set,
|
|
192
|
-
**kwargs,
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
dict_dump = super().dict(
|
|
196
|
-
**kwargs_with_defaults_exclude_unset_include_fields
|
|
197
|
-
)
|
|
198
|
-
|
|
199
|
-
return convert_and_respect_annotation_metadata(
|
|
200
|
-
object_=dict_dump, annotation=self.__class__, direction="write"
|
|
201
|
-
)
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
def _union_list_of_pydantic_dicts(
|
|
205
|
-
source: typing.List[typing.Any], destination: typing.List[typing.Any]
|
|
206
|
-
) -> typing.List[typing.Any]:
|
|
207
|
-
converted_list: typing.List[typing.Any] = []
|
|
208
|
-
for i, item in enumerate(source):
|
|
209
|
-
destination_value = destination[i] # type: ignore
|
|
210
|
-
if isinstance(item, dict):
|
|
211
|
-
converted_list.append(deep_union_pydantic_dicts(item, destination_value))
|
|
212
|
-
elif isinstance(item, list):
|
|
213
|
-
converted_list.append(
|
|
214
|
-
_union_list_of_pydantic_dicts(item, destination_value)
|
|
215
|
-
)
|
|
216
|
-
else:
|
|
217
|
-
converted_list.append(item)
|
|
218
|
-
return converted_list
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
def deep_union_pydantic_dicts(
|
|
222
|
-
source: typing.Dict[str, typing.Any], destination: typing.Dict[str, typing.Any]
|
|
223
|
-
) -> typing.Dict[str, typing.Any]:
|
|
224
|
-
for key, value in source.items():
|
|
225
|
-
node = destination.setdefault(key, {})
|
|
226
|
-
if isinstance(value, dict):
|
|
227
|
-
deep_union_pydantic_dicts(value, node)
|
|
228
|
-
# Note: we do not do this same processing for sets given we do not have sets of models
|
|
229
|
-
# and given the sets are unordered, the processing of the set and matching objects would
|
|
230
|
-
# be non-trivial.
|
|
231
|
-
elif isinstance(value, list):
|
|
232
|
-
destination[key] = _union_list_of_pydantic_dicts(value, node)
|
|
233
|
-
else:
|
|
234
|
-
destination[key] = value
|
|
100
|
+
fields = _get_model_fields(self.__class__)
|
|
101
|
+
for name, field in fields.items():
|
|
102
|
+
if name not in _fields_set:
|
|
103
|
+
default = _get_field_default(field)
|
|
104
|
+
|
|
105
|
+
# If the default values are non-null act like they've been set
|
|
106
|
+
# This effectively allows exclude_unset to work like exclude_none where
|
|
107
|
+
# the latter passes through intentionally set none values.
|
|
108
|
+
if default != None:
|
|
109
|
+
_fields_set.add(name)
|
|
235
110
|
|
|
236
|
-
|
|
111
|
+
kwargs_with_defaults_exclude_unset: typing.Any = {
|
|
112
|
+
"by_alias": True,
|
|
113
|
+
"exclude_unset": True,
|
|
114
|
+
"include": _fields_set,
|
|
115
|
+
**kwargs,
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
if IS_PYDANTIC_V2:
|
|
119
|
+
return super().model_dump(**kwargs_with_defaults_exclude_unset) # type: ignore # Pydantic v2
|
|
120
|
+
else:
|
|
121
|
+
return super().dict(**kwargs_with_defaults_exclude_unset)
|
|
237
122
|
|
|
238
123
|
|
|
239
124
|
if IS_PYDANTIC_V2:
|
|
@@ -260,11 +145,11 @@ def encode_by_type(o: typing.Any) -> typing.Any:
|
|
|
260
145
|
return encoder(o)
|
|
261
146
|
|
|
262
147
|
|
|
263
|
-
def update_forward_refs(model: typing.Type["Model"]
|
|
148
|
+
def update_forward_refs(model: typing.Type["Model"]) -> None:
|
|
264
149
|
if IS_PYDANTIC_V2:
|
|
265
150
|
model.model_rebuild(raise_errors=False) # type: ignore # Pydantic v2
|
|
266
151
|
else:
|
|
267
|
-
model.update_forward_refs(
|
|
152
|
+
model.update_forward_refs()
|
|
268
153
|
|
|
269
154
|
|
|
270
155
|
# Mirrors Pydantic's internal typing
|
|
@@ -23,8 +23,6 @@ class RequestOptions(typing.TypedDict, total=False):
|
|
|
23
23
|
- additional_query_parameters: typing.Dict[str, typing.Any]. A dictionary containing additional parameters to spread into the request's query parameters dict
|
|
24
24
|
|
|
25
25
|
- additional_body_parameters: typing.Dict[str, typing.Any]. A dictionary containing additional parameters to spread into the request's body parameters dict
|
|
26
|
-
|
|
27
|
-
- chunk_size: int. The size, in bytes, to process each chunk of data being streamed back within the response. This equates to leveraging `chunk_size` within `requests` or `httpx`, and is only leveraged for file downloads.
|
|
28
26
|
"""
|
|
29
27
|
|
|
30
28
|
timeout_in_seconds: NotRequired[int]
|
|
@@ -32,4 +30,3 @@ class RequestOptions(typing.TypedDict, total=False):
|
|
|
32
30
|
additional_headers: NotRequired[typing.Dict[str, typing.Any]]
|
|
33
31
|
additional_query_parameters: NotRequired[typing.Dict[str, typing.Any]]
|
|
34
32
|
additional_body_parameters: NotRequired[typing.Dict[str, typing.Any]]
|
|
35
|
-
chunk_size: NotRequired[int]
|
|
@@ -1,13 +1,10 @@
|
|
|
1
1
|
# This file was auto-generated by Fern from our API Definition.
|
|
2
2
|
|
|
3
3
|
import collections
|
|
4
|
-
import inspect
|
|
5
4
|
import typing
|
|
6
5
|
|
|
7
6
|
import typing_extensions
|
|
8
7
|
|
|
9
|
-
import pydantic
|
|
10
|
-
|
|
11
8
|
|
|
12
9
|
class FieldMetadata:
|
|
13
10
|
"""
|
|
@@ -32,7 +29,6 @@ def convert_and_respect_annotation_metadata(
|
|
|
32
29
|
object_: typing.Any,
|
|
33
30
|
annotation: typing.Any,
|
|
34
31
|
inner_type: typing.Optional[typing.Any] = None,
|
|
35
|
-
direction: typing.Literal["read", "write"],
|
|
36
32
|
) -> typing.Any:
|
|
37
33
|
"""
|
|
38
34
|
Respect the metadata annotations on a field, such as aliasing. This function effectively
|
|
@@ -60,79 +56,49 @@ def convert_and_respect_annotation_metadata(
|
|
|
60
56
|
inner_type = annotation
|
|
61
57
|
|
|
62
58
|
clean_type = _remove_annotations(inner_type)
|
|
63
|
-
# Pydantic models
|
|
64
|
-
if (
|
|
65
|
-
inspect.isclass(clean_type)
|
|
66
|
-
and issubclass(clean_type, pydantic.BaseModel)
|
|
67
|
-
and isinstance(object_, typing.Mapping)
|
|
68
|
-
):
|
|
69
|
-
return _convert_mapping(object_, clean_type, direction)
|
|
70
|
-
# TypedDicts
|
|
71
59
|
if typing_extensions.is_typeddict(clean_type) and isinstance(
|
|
72
60
|
object_, typing.Mapping
|
|
73
61
|
):
|
|
74
|
-
return
|
|
62
|
+
return _convert_typeddict(object_, clean_type)
|
|
75
63
|
|
|
76
64
|
if (
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
) and isinstance(object_, typing.Dict):
|
|
81
|
-
key_type = typing_extensions.get_args(clean_type)[0]
|
|
82
|
-
value_type = typing_extensions.get_args(clean_type)[1]
|
|
83
|
-
|
|
84
|
-
return {
|
|
85
|
-
key: convert_and_respect_annotation_metadata(
|
|
86
|
-
object_=value,
|
|
87
|
-
annotation=annotation,
|
|
88
|
-
inner_type=value_type,
|
|
89
|
-
direction=direction,
|
|
90
|
-
)
|
|
91
|
-
for key, value in object_.items()
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
# If you're iterating on a string, do not bother to coerce it to a sequence.
|
|
95
|
-
if not isinstance(object_, str):
|
|
96
|
-
if (
|
|
97
|
-
typing_extensions.get_origin(clean_type) == typing.Set
|
|
98
|
-
or typing_extensions.get_origin(clean_type) == set
|
|
99
|
-
or clean_type == typing.Set
|
|
100
|
-
) and isinstance(object_, typing.Set):
|
|
101
|
-
inner_type = typing_extensions.get_args(clean_type)[0]
|
|
102
|
-
return {
|
|
103
|
-
convert_and_respect_annotation_metadata(
|
|
104
|
-
object_=item,
|
|
105
|
-
annotation=annotation,
|
|
106
|
-
inner_type=inner_type,
|
|
107
|
-
direction=direction,
|
|
108
|
-
)
|
|
109
|
-
for item in object_
|
|
110
|
-
}
|
|
111
|
-
elif (
|
|
65
|
+
# If you're iterating on a string, do not bother to coerce it to a sequence.
|
|
66
|
+
(not isinstance(object_, str))
|
|
67
|
+
and (
|
|
112
68
|
(
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
69
|
+
(
|
|
70
|
+
typing_extensions.get_origin(clean_type) == typing.List
|
|
71
|
+
or typing_extensions.get_origin(clean_type) == list
|
|
72
|
+
or clean_type == typing.List
|
|
73
|
+
)
|
|
74
|
+
and isinstance(object_, typing.List)
|
|
116
75
|
)
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
76
|
+
or (
|
|
77
|
+
(
|
|
78
|
+
typing_extensions.get_origin(clean_type) == typing.Set
|
|
79
|
+
or typing_extensions.get_origin(clean_type) == set
|
|
80
|
+
or clean_type == typing.Set
|
|
81
|
+
)
|
|
82
|
+
and isinstance(object_, typing.Set)
|
|
123
83
|
)
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
annotation=annotation,
|
|
131
|
-
inner_type=inner_type,
|
|
132
|
-
direction=direction,
|
|
84
|
+
or (
|
|
85
|
+
(
|
|
86
|
+
typing_extensions.get_origin(clean_type) == typing.Sequence
|
|
87
|
+
or typing_extensions.get_origin(clean_type)
|
|
88
|
+
== collections.abc.Sequence
|
|
89
|
+
or clean_type == typing.Sequence
|
|
133
90
|
)
|
|
134
|
-
|
|
135
|
-
|
|
91
|
+
and isinstance(object_, typing.Sequence)
|
|
92
|
+
)
|
|
93
|
+
)
|
|
94
|
+
):
|
|
95
|
+
inner_type = typing_extensions.get_args(clean_type)[0]
|
|
96
|
+
return [
|
|
97
|
+
convert_and_respect_annotation_metadata(
|
|
98
|
+
object_=item, annotation=annotation, inner_type=inner_type
|
|
99
|
+
)
|
|
100
|
+
for item in object_
|
|
101
|
+
]
|
|
136
102
|
|
|
137
103
|
if typing_extensions.get_origin(clean_type) == typing.Union:
|
|
138
104
|
# We should be able to ~relatively~ safely try to convert keys against all
|
|
@@ -141,10 +107,7 @@ def convert_and_respect_annotation_metadata(
|
|
|
141
107
|
# Or if another member aliases a field of the same name that another member does not.
|
|
142
108
|
for member in typing_extensions.get_args(clean_type):
|
|
143
109
|
object_ = convert_and_respect_annotation_metadata(
|
|
144
|
-
object_=object_,
|
|
145
|
-
annotation=annotation,
|
|
146
|
-
inner_type=member,
|
|
147
|
-
direction=direction,
|
|
110
|
+
object_=object_, annotation=annotation, inner_type=member
|
|
148
111
|
)
|
|
149
112
|
return object_
|
|
150
113
|
|
|
@@ -157,37 +120,19 @@ def convert_and_respect_annotation_metadata(
|
|
|
157
120
|
return object_
|
|
158
121
|
|
|
159
122
|
|
|
160
|
-
def
|
|
161
|
-
object_: typing.Mapping[str, object],
|
|
162
|
-
expected_type: typing.Any,
|
|
163
|
-
direction: typing.Literal["read", "write"],
|
|
123
|
+
def _convert_typeddict(
|
|
124
|
+
object_: typing.Mapping[str, object], expected_type: typing.Any
|
|
164
125
|
) -> typing.Mapping[str, object]:
|
|
165
126
|
converted_object: typing.Dict[str, object] = {}
|
|
166
127
|
annotations = typing_extensions.get_type_hints(expected_type, include_extras=True)
|
|
167
|
-
aliases_to_field_names = _get_alias_to_field_name(annotations)
|
|
168
128
|
for key, value in object_.items():
|
|
169
|
-
|
|
170
|
-
dealiased_key = aliases_to_field_names.get(key)
|
|
171
|
-
if dealiased_key is not None:
|
|
172
|
-
type_ = annotations.get(dealiased_key)
|
|
173
|
-
else:
|
|
174
|
-
type_ = annotations.get(key)
|
|
175
|
-
# Note you can't get the annotation by the field name if you're in read mode, so you must check the aliases map
|
|
176
|
-
#
|
|
177
|
-
# So this is effectively saying if we're in write mode, and we don't have a type, or if we're in read mode and we don't have an alias
|
|
178
|
-
# then we can just pass the value through as is
|
|
129
|
+
type_ = annotations.get(key)
|
|
179
130
|
if type_ is None:
|
|
180
131
|
converted_object[key] = value
|
|
181
|
-
elif direction == "read" and key not in aliases_to_field_names:
|
|
182
|
-
converted_object[key] = convert_and_respect_annotation_metadata(
|
|
183
|
-
object_=value, annotation=type_, direction=direction
|
|
184
|
-
)
|
|
185
132
|
else:
|
|
186
133
|
converted_object[
|
|
187
|
-
_alias_key(key, type_
|
|
188
|
-
] = convert_and_respect_annotation_metadata(
|
|
189
|
-
object_=value, annotation=type_, direction=direction
|
|
190
|
-
)
|
|
134
|
+
_alias_key(key, type_)
|
|
135
|
+
] = convert_and_respect_annotation_metadata(object_=value, annotation=type_)
|
|
191
136
|
return converted_object
|
|
192
137
|
|
|
193
138
|
|
|
@@ -220,39 +165,7 @@ def _remove_annotations(type_: typing.Any) -> typing.Any:
|
|
|
220
165
|
return type_
|
|
221
166
|
|
|
222
167
|
|
|
223
|
-
def
|
|
224
|
-
annotations = typing_extensions.get_type_hints(type_, include_extras=True)
|
|
225
|
-
return _get_alias_to_field_name(annotations)
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
def get_field_to_alias_mapping(type_: typing.Any) -> typing.Dict[str, str]:
|
|
229
|
-
annotations = typing_extensions.get_type_hints(type_, include_extras=True)
|
|
230
|
-
return _get_field_to_alias_name(annotations)
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
def _get_alias_to_field_name(
|
|
234
|
-
field_to_hint: typing.Dict[str, typing.Any],
|
|
235
|
-
) -> typing.Dict[str, str]:
|
|
236
|
-
aliases = {}
|
|
237
|
-
for field, hint in field_to_hint.items():
|
|
238
|
-
maybe_alias = _get_alias_from_type(hint)
|
|
239
|
-
if maybe_alias is not None:
|
|
240
|
-
aliases[maybe_alias] = field
|
|
241
|
-
return aliases
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
def _get_field_to_alias_name(
|
|
245
|
-
field_to_hint: typing.Dict[str, typing.Any],
|
|
246
|
-
) -> typing.Dict[str, str]:
|
|
247
|
-
aliases = {}
|
|
248
|
-
for field, hint in field_to_hint.items():
|
|
249
|
-
maybe_alias = _get_alias_from_type(hint)
|
|
250
|
-
if maybe_alias is not None:
|
|
251
|
-
aliases[field] = maybe_alias
|
|
252
|
-
return aliases
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
def _get_alias_from_type(type_: typing.Any) -> typing.Optional[str]:
|
|
168
|
+
def _alias_key(key: str, type_: typing.Any) -> str:
|
|
256
169
|
maybe_annotated_type = _get_annotation(type_)
|
|
257
170
|
|
|
258
171
|
if maybe_annotated_type is not None:
|
|
@@ -262,15 +175,5 @@ def _get_alias_from_type(type_: typing.Any) -> typing.Optional[str]:
|
|
|
262
175
|
for annotation in annotations:
|
|
263
176
|
if isinstance(annotation, FieldMetadata) and annotation.alias is not None:
|
|
264
177
|
return annotation.alias
|
|
265
|
-
return None
|
|
266
|
-
|
|
267
178
|
|
|
268
|
-
|
|
269
|
-
key: str,
|
|
270
|
-
type_: typing.Any,
|
|
271
|
-
direction: typing.Literal["read", "write"],
|
|
272
|
-
aliases_to_field_names: typing.Dict[str, str],
|
|
273
|
-
) -> str:
|
|
274
|
-
if direction == "read":
|
|
275
|
-
return aliases_to_field_names.get(key, key)
|
|
276
|
-
return _get_alias_from_type(type_=type_) or key
|
|
179
|
+
return key
|
|
@@ -10,7 +10,6 @@ from json.decoder import JSONDecodeError
|
|
|
10
10
|
from ..core.api_error import ApiError
|
|
11
11
|
from ..types.evaluation import Evaluation
|
|
12
12
|
from ..types.llm_run_rate_limit import LlmRunRateLimit
|
|
13
|
-
from ..core.serialization import convert_and_respect_annotation_metadata
|
|
14
13
|
from ..core.jsonable_encoder import jsonable_encoder
|
|
15
14
|
from ..types.evaluation_scenario import EvaluationScenario
|
|
16
15
|
from ..core.client_wrapper import AsyncClientWrapper
|
|
@@ -250,9 +249,7 @@ class EvaluationsClient:
|
|
|
250
249
|
"variant_ids": variant_ids,
|
|
251
250
|
"evaluators_configs": evaluators_configs,
|
|
252
251
|
"testset_id": testset_id,
|
|
253
|
-
"rate_limit":
|
|
254
|
-
object_=rate_limit, annotation=LlmRunRateLimit, direction="write"
|
|
255
|
-
),
|
|
252
|
+
"rate_limit": rate_limit,
|
|
256
253
|
"lm_providers_keys": lm_providers_keys,
|
|
257
254
|
"correct_answer_column": correct_answer_column,
|
|
258
255
|
},
|
|
@@ -962,9 +959,7 @@ class AsyncEvaluationsClient:
|
|
|
962
959
|
"variant_ids": variant_ids,
|
|
963
960
|
"evaluators_configs": evaluators_configs,
|
|
964
961
|
"testset_id": testset_id,
|
|
965
|
-
"rate_limit":
|
|
966
|
-
object_=rate_limit, annotation=LlmRunRateLimit, direction="write"
|
|
967
|
-
),
|
|
962
|
+
"rate_limit": rate_limit,
|
|
968
963
|
"lm_providers_keys": lm_providers_keys,
|
|
969
964
|
"correct_answer_column": correct_answer_column,
|
|
970
965
|
},
|