agenta 0.70.1__py3-none-any.whl → 0.75.0__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.
- agenta/__init__.py +9 -3
- agenta/sdk/__init__.py +2 -4
- agenta/sdk/agenta_init.py +22 -75
- agenta/sdk/assets.py +57 -0
- agenta/sdk/context/serving.py +2 -0
- agenta/sdk/contexts/routing.py +2 -0
- agenta/sdk/contexts/running.py +3 -2
- agenta/sdk/decorators/running.py +8 -4
- agenta/sdk/decorators/serving.py +65 -26
- agenta/sdk/decorators/tracing.py +51 -30
- agenta/sdk/engines/tracing/inline.py +8 -1
- agenta/sdk/engines/tracing/processors.py +23 -12
- agenta/sdk/evaluations/preview/evaluate.py +36 -8
- agenta/sdk/evaluations/runs.py +2 -1
- agenta/sdk/litellm/mockllm.py +2 -2
- agenta/sdk/managers/config.py +3 -1
- agenta/sdk/managers/secrets.py +25 -8
- agenta/sdk/managers/testsets.py +143 -227
- agenta/sdk/middleware/config.py +3 -1
- agenta/sdk/middleware/otel.py +3 -1
- agenta/sdk/middleware/vault.py +33 -18
- agenta/sdk/middlewares/routing/otel.py +1 -1
- agenta/sdk/middlewares/running/vault.py +33 -17
- agenta/sdk/router.py +30 -5
- agenta/sdk/tracing/inline.py +8 -1
- agenta/sdk/tracing/processors.py +8 -3
- agenta/sdk/tracing/propagation.py +9 -12
- agenta/sdk/types.py +19 -21
- agenta/sdk/utils/client.py +10 -9
- agenta/sdk/utils/lazy.py +253 -0
- agenta/sdk/workflows/builtin.py +2 -0
- agenta/sdk/workflows/configurations.py +1 -0
- agenta/sdk/workflows/handlers.py +236 -81
- agenta/sdk/workflows/interfaces.py +47 -0
- agenta/sdk/workflows/runners/base.py +6 -2
- agenta/sdk/workflows/runners/daytona.py +250 -131
- agenta/sdk/workflows/runners/local.py +22 -56
- agenta/sdk/workflows/runners/registry.py +1 -1
- agenta/sdk/workflows/sandbox.py +17 -5
- agenta/sdk/workflows/templates.py +81 -0
- agenta/sdk/workflows/utils.py +6 -0
- {agenta-0.70.1.dist-info → agenta-0.75.0.dist-info}/METADATA +4 -8
- {agenta-0.70.1.dist-info → agenta-0.75.0.dist-info}/RECORD +44 -44
- agenta/config.py +0 -25
- agenta/config.toml +0 -4
- {agenta-0.70.1.dist-info → agenta-0.75.0.dist-info}/WHEEL +0 -0
agenta/sdk/managers/testsets.py
CHANGED
|
@@ -1,248 +1,212 @@
|
|
|
1
1
|
from typing import List, Dict, Any, Optional
|
|
2
|
-
from uuid import UUID
|
|
2
|
+
from uuid import UUID, uuid4
|
|
3
3
|
|
|
4
4
|
from agenta.sdk.utils.client import authed_api
|
|
5
5
|
from agenta.sdk.utils.references import get_slug_from_name_and_id
|
|
6
6
|
from agenta.sdk.models.testsets import (
|
|
7
|
-
LegacyTestset,
|
|
8
|
-
#
|
|
9
|
-
Testcase,
|
|
10
7
|
TestsetRevisionData,
|
|
11
8
|
TestsetRevision,
|
|
12
9
|
#
|
|
13
10
|
TestsetRevisionResponse,
|
|
11
|
+
#
|
|
12
|
+
SimpleTestsetResponse,
|
|
14
13
|
)
|
|
15
14
|
|
|
16
15
|
|
|
17
|
-
|
|
16
|
+
def _normalize_csvdata(
|
|
17
|
+
data: List[Dict[str, Any]] | TestsetRevisionData,
|
|
18
|
+
) -> List[Dict[str, Any]]:
|
|
19
|
+
if isinstance(data, TestsetRevisionData) and data.testcases:
|
|
20
|
+
return [testcase.data for testcase in data.testcases]
|
|
21
|
+
|
|
22
|
+
if isinstance(data, list):
|
|
23
|
+
return data
|
|
24
|
+
|
|
25
|
+
return []
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
async def _create_simple_testset(
|
|
18
29
|
*,
|
|
19
30
|
csvdata: List[Dict[str, Any]],
|
|
20
31
|
name: str,
|
|
21
32
|
testset_id: Optional[UUID] = None,
|
|
22
33
|
) -> Optional[TestsetRevision]:
|
|
34
|
+
slug_seed = testset_id or uuid4()
|
|
35
|
+
|
|
36
|
+
payload = {
|
|
37
|
+
"testset": {
|
|
38
|
+
"slug": get_slug_from_name_and_id(name, slug_seed),
|
|
39
|
+
"name": name,
|
|
40
|
+
"data": {
|
|
41
|
+
"testcases": [
|
|
42
|
+
{"data": testcase_data}
|
|
43
|
+
for testcase_data in csvdata
|
|
44
|
+
if isinstance(testcase_data, dict)
|
|
45
|
+
]
|
|
46
|
+
},
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
23
50
|
response = authed_api()(
|
|
24
51
|
method="POST",
|
|
25
|
-
endpoint="/testsets/",
|
|
26
|
-
json=
|
|
27
|
-
"testset_id": str(testset_id) if testset_id else None,
|
|
28
|
-
"name": name,
|
|
29
|
-
"csvdata": csvdata,
|
|
30
|
-
},
|
|
52
|
+
endpoint="/preview/simple/testsets/",
|
|
53
|
+
json=payload,
|
|
31
54
|
)
|
|
32
55
|
|
|
33
56
|
if response.status_code != 200:
|
|
34
57
|
print("Failed to create testset:", response.status_code, response.text)
|
|
35
58
|
return None
|
|
36
59
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
# print(" --- legacy_testset:", legacy_testset)
|
|
60
|
+
simple_testset_response = SimpleTestsetResponse(**response.json())
|
|
61
|
+
simple_testset = simple_testset_response.testset
|
|
40
62
|
|
|
41
|
-
if not
|
|
63
|
+
if not simple_testset or not simple_testset.id or not simple_testset.data:
|
|
42
64
|
return None
|
|
43
65
|
|
|
44
|
-
|
|
45
|
-
id=UUID(legacy_testset.id),
|
|
46
|
-
slug=get_slug_from_name_and_id(
|
|
47
|
-
name=legacy_testset.name,
|
|
48
|
-
id=UUID(legacy_testset.id),
|
|
49
|
-
),
|
|
50
|
-
name=legacy_testset.name,
|
|
51
|
-
data=TestsetRevisionData(
|
|
52
|
-
testcases=[
|
|
53
|
-
Testcase(
|
|
54
|
-
data=testcase_data,
|
|
55
|
-
testset_id=UUID(legacy_testset.id),
|
|
56
|
-
)
|
|
57
|
-
for testcase_data in csvdata
|
|
58
|
-
]
|
|
59
|
-
),
|
|
60
|
-
)
|
|
66
|
+
retrieved = await _retrieve_testset(testset_id=simple_testset.id)
|
|
61
67
|
|
|
62
|
-
|
|
68
|
+
if retrieved:
|
|
69
|
+
return retrieved
|
|
63
70
|
|
|
64
|
-
return
|
|
71
|
+
return TestsetRevision(
|
|
72
|
+
id=simple_testset.id,
|
|
73
|
+
slug=simple_testset.slug,
|
|
74
|
+
name=simple_testset.name,
|
|
75
|
+
data=simple_testset.data,
|
|
76
|
+
testset_id=simple_testset.id,
|
|
77
|
+
)
|
|
65
78
|
|
|
66
79
|
|
|
67
|
-
async def
|
|
80
|
+
async def _fetch_simple_testset(
|
|
68
81
|
testset_id: Optional[UUID] = None,
|
|
69
|
-
#
|
|
70
82
|
name: Optional[str] = None,
|
|
71
83
|
) -> Optional[TestsetRevision]:
|
|
72
|
-
|
|
84
|
+
if not testset_id and not name:
|
|
85
|
+
return None
|
|
73
86
|
|
|
74
87
|
if testset_id:
|
|
75
88
|
response = authed_api()(
|
|
76
89
|
method="GET",
|
|
77
|
-
endpoint=f"/testsets/{testset_id}",
|
|
90
|
+
endpoint=f"/preview/simple/testsets/{testset_id}",
|
|
78
91
|
)
|
|
79
92
|
|
|
80
|
-
if response.status_code
|
|
81
|
-
|
|
82
|
-
|
|
93
|
+
if response.status_code == 200:
|
|
94
|
+
simple_testset_response = SimpleTestsetResponse(**response.json())
|
|
95
|
+
simple_testset = simple_testset_response.testset
|
|
96
|
+
|
|
97
|
+
if simple_testset and simple_testset.id and simple_testset.data:
|
|
98
|
+
retrieved = await _retrieve_testset(
|
|
99
|
+
testset_id=UUID(str(simple_testset.id))
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
if retrieved:
|
|
103
|
+
return retrieved
|
|
104
|
+
|
|
105
|
+
return TestsetRevision(
|
|
106
|
+
id=simple_testset.id,
|
|
107
|
+
slug=simple_testset.slug,
|
|
108
|
+
name=simple_testset.name,
|
|
109
|
+
data=simple_testset.data,
|
|
110
|
+
testset_id=simple_testset.id,
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
elif response.status_code != 404:
|
|
114
|
+
print("Failed to fetch testset:", response.status_code, response.text)
|
|
83
115
|
return None
|
|
84
116
|
|
|
85
|
-
|
|
86
|
-
elif name:
|
|
117
|
+
if name:
|
|
87
118
|
response = authed_api()(
|
|
88
|
-
method="
|
|
89
|
-
endpoint="/testsets/",
|
|
90
|
-
|
|
119
|
+
method="POST",
|
|
120
|
+
endpoint="/preview/simple/testsets/query",
|
|
121
|
+
json={"testset": {"name": name}},
|
|
91
122
|
)
|
|
92
123
|
|
|
93
124
|
if response.status_code != 200:
|
|
94
125
|
print("Failed to list testsets:", response.status_code, response.text)
|
|
95
126
|
return None
|
|
96
127
|
|
|
97
|
-
|
|
128
|
+
testsets = response.json().get("testsets", [])
|
|
98
129
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
testset["id"] = _id
|
|
130
|
+
if testsets:
|
|
131
|
+
first = testsets[0]
|
|
102
132
|
|
|
103
|
-
|
|
133
|
+
if first.get("id"):
|
|
134
|
+
return await _fetch_simple_testset(testset_id=UUID(first["id"]))
|
|
104
135
|
|
|
105
|
-
|
|
106
|
-
print("Expected exactly one testset with name:", name)
|
|
107
|
-
return None
|
|
108
|
-
|
|
109
|
-
legacy_testset = legacy_testsets[0]
|
|
136
|
+
return None
|
|
110
137
|
|
|
111
|
-
# print(" --- legacy_testset:", legacy_testset)
|
|
112
138
|
|
|
113
|
-
|
|
114
|
-
return None
|
|
115
|
-
|
|
116
|
-
testset_revision = TestsetRevision(
|
|
117
|
-
testset_id=UUID(legacy_testset.id),
|
|
118
|
-
slug=get_slug_from_name_and_id(
|
|
119
|
-
name=legacy_testset.name,
|
|
120
|
-
id=UUID(legacy_testset.id),
|
|
121
|
-
),
|
|
122
|
-
name=legacy_testset.name,
|
|
123
|
-
data=(
|
|
124
|
-
TestsetRevisionData(
|
|
125
|
-
testcases=[
|
|
126
|
-
Testcase(
|
|
127
|
-
data=testcase_data,
|
|
128
|
-
testset_id=UUID(legacy_testset.id),
|
|
129
|
-
)
|
|
130
|
-
for testcase_data in legacy_testset.csvdata
|
|
131
|
-
]
|
|
132
|
-
)
|
|
133
|
-
if legacy_testset.csvdata
|
|
134
|
-
else None
|
|
135
|
-
),
|
|
136
|
-
)
|
|
137
|
-
|
|
138
|
-
# print(" --- testset_revision:", testset_revision)
|
|
139
|
-
|
|
140
|
-
return testset_revision
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
async def _edit_legacy_testset(
|
|
139
|
+
async def _edit_simple_testset(
|
|
144
140
|
*,
|
|
145
141
|
testset_id: UUID,
|
|
146
142
|
csvdata: List[Dict[str, Any]],
|
|
147
143
|
name: Optional[str] = None,
|
|
148
144
|
) -> Optional[TestsetRevision]:
|
|
145
|
+
payload = {
|
|
146
|
+
"testset": {
|
|
147
|
+
"id": str(testset_id),
|
|
148
|
+
"name": name,
|
|
149
|
+
"data": {
|
|
150
|
+
"testcases": [
|
|
151
|
+
{"data": testcase_data}
|
|
152
|
+
for testcase_data in csvdata
|
|
153
|
+
if isinstance(testcase_data, dict)
|
|
154
|
+
]
|
|
155
|
+
},
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
149
159
|
response = authed_api()(
|
|
150
160
|
method="PUT",
|
|
151
|
-
endpoint=f"/testsets/{testset_id}",
|
|
152
|
-
json=
|
|
153
|
-
"name": name,
|
|
154
|
-
"csvdata": csvdata,
|
|
155
|
-
},
|
|
161
|
+
endpoint=f"/preview/simple/testsets/{testset_id}",
|
|
162
|
+
json=payload,
|
|
156
163
|
)
|
|
157
164
|
|
|
158
165
|
if response.status_code != 200:
|
|
159
166
|
print("Failed to edit testset:", response.status_code, response.text)
|
|
160
167
|
return None
|
|
161
168
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
endpoint=f"/testsets/{testset_id}",
|
|
165
|
-
)
|
|
166
|
-
|
|
167
|
-
legacy_testset = LegacyTestset(**response.json())
|
|
169
|
+
simple_testset_response = SimpleTestsetResponse(**response.json())
|
|
170
|
+
simple_testset = simple_testset_response.testset
|
|
168
171
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
if not legacy_testset.id or not legacy_testset.name:
|
|
172
|
+
if not simple_testset or not simple_testset.id or not simple_testset.data:
|
|
172
173
|
return None
|
|
173
174
|
|
|
174
|
-
|
|
175
|
-
id=
|
|
176
|
-
slug=
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
name=legacy_testset.name,
|
|
181
|
-
data=(
|
|
182
|
-
TestsetRevisionData(
|
|
183
|
-
testcases=[
|
|
184
|
-
Testcase(
|
|
185
|
-
data=testcase_data,
|
|
186
|
-
testset_id=UUID(legacy_testset.id),
|
|
187
|
-
)
|
|
188
|
-
for testcase_data in legacy_testset.csvdata
|
|
189
|
-
]
|
|
190
|
-
)
|
|
191
|
-
if legacy_testset.csvdata
|
|
192
|
-
else None
|
|
193
|
-
),
|
|
175
|
+
return TestsetRevision(
|
|
176
|
+
id=simple_testset.id,
|
|
177
|
+
slug=simple_testset.slug,
|
|
178
|
+
name=simple_testset.name,
|
|
179
|
+
data=simple_testset.data,
|
|
180
|
+
testset_id=simple_testset.id,
|
|
194
181
|
)
|
|
195
182
|
|
|
196
|
-
# print(" --- testset_revision:", testset_revision)
|
|
197
|
-
|
|
198
|
-
return testset_revision
|
|
199
183
|
|
|
200
|
-
|
|
201
|
-
async def _list_legacy_testsets(
|
|
184
|
+
async def _list_simple_testsets(
|
|
202
185
|
#
|
|
203
186
|
) -> List[TestsetRevision]:
|
|
204
187
|
response = authed_api()(
|
|
205
|
-
method="
|
|
206
|
-
endpoint="/testsets/",
|
|
188
|
+
method="POST",
|
|
189
|
+
endpoint="/preview/simple/testsets/query",
|
|
190
|
+
json={},
|
|
207
191
|
)
|
|
208
192
|
|
|
209
193
|
if response.status_code != 200:
|
|
210
194
|
print("Failed to list testsets:", response.status_code, response.text)
|
|
211
195
|
return []
|
|
212
196
|
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
name=legacy_testset.name,
|
|
222
|
-
id=UUID(legacy_testset.id),
|
|
223
|
-
),
|
|
224
|
-
name=legacy_testset.name,
|
|
225
|
-
data=(
|
|
226
|
-
TestsetRevisionData(
|
|
227
|
-
testcases=[
|
|
228
|
-
Testcase(
|
|
229
|
-
data=testcase_data,
|
|
230
|
-
testset_id=UUID(legacy_testset.id),
|
|
231
|
-
)
|
|
232
|
-
for testcase_data in legacy_testset.csvdata
|
|
233
|
-
]
|
|
234
|
-
)
|
|
235
|
-
if legacy_testset.csvdata
|
|
236
|
-
else None
|
|
237
|
-
),
|
|
238
|
-
)
|
|
239
|
-
for legacy_testset in legacy_testsets
|
|
240
|
-
if legacy_testset.id and legacy_testset.name
|
|
241
|
-
]
|
|
197
|
+
testsets = response.json().get("testsets", [])
|
|
198
|
+
revisions = []
|
|
199
|
+
|
|
200
|
+
for ts in testsets:
|
|
201
|
+
if not ts.get("id"):
|
|
202
|
+
continue
|
|
203
|
+
|
|
204
|
+
fetched = await _fetch_simple_testset(testset_id=UUID(ts["id"]))
|
|
242
205
|
|
|
243
|
-
|
|
206
|
+
if fetched:
|
|
207
|
+
revisions.append(fetched)
|
|
244
208
|
|
|
245
|
-
return
|
|
209
|
+
return revisions
|
|
246
210
|
|
|
247
211
|
|
|
248
212
|
async def _retrieve_testset(
|
|
@@ -266,8 +230,6 @@ async def _retrieve_testset(
|
|
|
266
230
|
),
|
|
267
231
|
}
|
|
268
232
|
|
|
269
|
-
# print(" --- payload:", payload)
|
|
270
|
-
|
|
271
233
|
response = authed_api()(
|
|
272
234
|
method="POST",
|
|
273
235
|
endpoint="/preview/testsets/revisions/retrieve",
|
|
@@ -277,14 +239,10 @@ async def _retrieve_testset(
|
|
|
277
239
|
|
|
278
240
|
testset_revision_response = TestsetRevisionResponse(**response.json())
|
|
279
241
|
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
# print(" --- testset_revision:", testset_revision)
|
|
242
|
+
return testset_revision_response.testset_revision
|
|
283
243
|
|
|
284
|
-
return testset_revision
|
|
285
244
|
|
|
286
|
-
|
|
287
|
-
async def _sync_legacy_testset(
|
|
245
|
+
async def _sync_simple_testset(
|
|
288
246
|
*,
|
|
289
247
|
testset_id: Optional[UUID] = None,
|
|
290
248
|
#
|
|
@@ -293,11 +251,7 @@ async def _sync_legacy_testset(
|
|
|
293
251
|
name: Optional[str] = None,
|
|
294
252
|
) -> Optional[TestsetRevision]:
|
|
295
253
|
try:
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
# print(" ---:", testset_revision_data.model_dump(mode="json", exclude_none=True))
|
|
299
|
-
|
|
300
|
-
testset_revision = await _fetch_legacy_testset(
|
|
254
|
+
testset_revision = await _fetch_simple_testset(
|
|
301
255
|
testset_id=testset_id,
|
|
302
256
|
name=name,
|
|
303
257
|
)
|
|
@@ -306,34 +260,18 @@ async def _sync_legacy_testset(
|
|
|
306
260
|
print("[ERROR]: Failed to prepare testset:", e)
|
|
307
261
|
return None
|
|
308
262
|
|
|
309
|
-
# print("Fetch response:", testset_revision)
|
|
310
|
-
|
|
311
263
|
if testset_revision and testset_revision.testset_id:
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
testset_revision = await _edit_legacy_testset(
|
|
264
|
+
return await _edit_simple_testset(
|
|
315
265
|
testset_id=testset_revision.testset_id,
|
|
316
266
|
name=name,
|
|
317
267
|
csvdata=csvdata,
|
|
318
268
|
)
|
|
319
269
|
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
testset_revision = await _create_legacy_testset(
|
|
326
|
-
testset_id=testset_id,
|
|
327
|
-
name=name,
|
|
328
|
-
csvdata=csvdata,
|
|
329
|
-
)
|
|
330
|
-
|
|
331
|
-
if not testset_revision or not testset_revision.id:
|
|
332
|
-
return None
|
|
333
|
-
|
|
334
|
-
# print(" --- testset_revision:", testset_revision)
|
|
335
|
-
|
|
336
|
-
return testset_revision
|
|
270
|
+
return await _create_simple_testset(
|
|
271
|
+
name=name or "Testset",
|
|
272
|
+
csvdata=csvdata,
|
|
273
|
+
testset_id=testset_id,
|
|
274
|
+
)
|
|
337
275
|
|
|
338
276
|
|
|
339
277
|
async def aupsert(
|
|
@@ -344,15 +282,9 @@ async def aupsert(
|
|
|
344
282
|
#
|
|
345
283
|
data: List[Dict[str, Any]] | TestsetRevisionData,
|
|
346
284
|
) -> Optional[TestsetRevision]:
|
|
347
|
-
csvdata =
|
|
348
|
-
if isinstance(data, TestsetRevisionData) and data.testcases:
|
|
349
|
-
csvdata = [testcase.data for testcase in data.testcases]
|
|
350
|
-
elif isinstance(data, list):
|
|
351
|
-
csvdata = data
|
|
352
|
-
else:
|
|
353
|
-
csvdata = list()
|
|
285
|
+
csvdata = _normalize_csvdata(data)
|
|
354
286
|
|
|
355
|
-
return await
|
|
287
|
+
return await _sync_simple_testset(
|
|
356
288
|
testset_id=testset_id,
|
|
357
289
|
name=name,
|
|
358
290
|
csvdata=csvdata, # type: ignore
|
|
@@ -367,15 +299,9 @@ async def acreate(
|
|
|
367
299
|
#
|
|
368
300
|
data: List[Dict[str, Any]] | TestsetRevisionData,
|
|
369
301
|
) -> Optional[TestsetRevision]:
|
|
370
|
-
csvdata =
|
|
371
|
-
if isinstance(data, TestsetRevisionData) and data.testcases:
|
|
372
|
-
csvdata = [testcase.data for testcase in data.testcases]
|
|
373
|
-
elif isinstance(data, list):
|
|
374
|
-
csvdata = data
|
|
375
|
-
else:
|
|
376
|
-
csvdata = list()
|
|
302
|
+
csvdata = _normalize_csvdata(data)
|
|
377
303
|
|
|
378
|
-
return await
|
|
304
|
+
return await _create_simple_testset(
|
|
379
305
|
testset_id=(
|
|
380
306
|
testset_id
|
|
381
307
|
if isinstance(testset_id, UUID)
|
|
@@ -383,7 +309,7 @@ async def acreate(
|
|
|
383
309
|
if testset_id
|
|
384
310
|
else None
|
|
385
311
|
),
|
|
386
|
-
name=name,
|
|
312
|
+
name=name or "Testset",
|
|
387
313
|
csvdata=csvdata, # type: ignore
|
|
388
314
|
)
|
|
389
315
|
|
|
@@ -396,15 +322,9 @@ async def aedit(
|
|
|
396
322
|
#
|
|
397
323
|
data: List[Dict[str, Any]] | TestsetRevisionData,
|
|
398
324
|
) -> Optional[TestsetRevision]:
|
|
399
|
-
csvdata =
|
|
400
|
-
if isinstance(data, TestsetRevisionData) and data.testcases:
|
|
401
|
-
csvdata = [testcase.data for testcase in data.testcases]
|
|
402
|
-
elif isinstance(data, list):
|
|
403
|
-
csvdata = data
|
|
404
|
-
else:
|
|
405
|
-
csvdata = list()
|
|
325
|
+
csvdata = _normalize_csvdata(data)
|
|
406
326
|
|
|
407
|
-
return await
|
|
327
|
+
return await _edit_simple_testset(
|
|
408
328
|
testset_id=testset_id if isinstance(testset_id, UUID) else UUID(testset_id),
|
|
409
329
|
name=name,
|
|
410
330
|
csvdata=csvdata, # type: ignore
|
|
@@ -415,7 +335,7 @@ async def afetch(
|
|
|
415
335
|
*,
|
|
416
336
|
testset_id: UUID | str,
|
|
417
337
|
) -> Optional[TestsetRevision]:
|
|
418
|
-
return await
|
|
338
|
+
return await _fetch_simple_testset(
|
|
419
339
|
testset_id=testset_id if isinstance(testset_id, UUID) else UUID(testset_id)
|
|
420
340
|
)
|
|
421
341
|
|
|
@@ -423,7 +343,7 @@ async def afetch(
|
|
|
423
343
|
async def alist(
|
|
424
344
|
#
|
|
425
345
|
) -> List[TestsetRevision]:
|
|
426
|
-
return await
|
|
346
|
+
return await _list_simple_testsets()
|
|
427
347
|
|
|
428
348
|
|
|
429
349
|
async def aretrieve(
|
|
@@ -431,11 +351,7 @@ async def aretrieve(
|
|
|
431
351
|
#
|
|
432
352
|
testset_revision_id: Optional[UUID] = None,
|
|
433
353
|
) -> Optional[TestsetRevision]:
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
response = await _retrieve_testset(
|
|
354
|
+
return await _retrieve_testset(
|
|
437
355
|
testset_id=testset_id,
|
|
438
356
|
testset_revision_id=testset_revision_id,
|
|
439
357
|
)
|
|
440
|
-
|
|
441
|
-
return response
|
agenta/sdk/middleware/config.py
CHANGED
|
@@ -224,6 +224,7 @@ class ConfigMiddleware(BaseHTTPMiddleware):
|
|
|
224
224
|
baggage.get("ag.refs.variant.slug")
|
|
225
225
|
# ALTERNATIVE
|
|
226
226
|
or request.query_params.get("variant_slug")
|
|
227
|
+
or body.get("variant_slug")
|
|
227
228
|
# LEGACY
|
|
228
229
|
or baggage.get("variant_slug")
|
|
229
230
|
or request.query_params.get("config")
|
|
@@ -234,6 +235,7 @@ class ConfigMiddleware(BaseHTTPMiddleware):
|
|
|
234
235
|
baggage.get("ag.refs.variant.version")
|
|
235
236
|
# ALTERNATIVE
|
|
236
237
|
or request.query_params.get("variant_version")
|
|
238
|
+
or body.get("variant_version")
|
|
237
239
|
# LEGACY
|
|
238
240
|
or baggage.get("variant_version")
|
|
239
241
|
)
|
|
@@ -244,7 +246,7 @@ class ConfigMiddleware(BaseHTTPMiddleware):
|
|
|
244
246
|
return Reference(
|
|
245
247
|
id=variant_id,
|
|
246
248
|
slug=variant_slug,
|
|
247
|
-
version=variant_version,
|
|
249
|
+
version=str(variant_version) if variant_version is not None else None,
|
|
248
250
|
)
|
|
249
251
|
|
|
250
252
|
async def _parse_environment_ref(
|
agenta/sdk/middleware/otel.py
CHANGED
|
@@ -5,8 +5,10 @@ from fastapi import Request, FastAPI
|
|
|
5
5
|
|
|
6
6
|
from agenta.sdk.utils.exceptions import suppress
|
|
7
7
|
from agenta.sdk.tracing.propagation import extract
|
|
8
|
-
|
|
8
|
+
from agenta.sdk.utils.exceptions import suppress
|
|
9
9
|
from agenta.sdk.utils.logging import get_module_logger
|
|
10
|
+
from fastapi import FastAPI, Request
|
|
11
|
+
from starlette.middleware.base import BaseHTTPMiddleware
|
|
10
12
|
|
|
11
13
|
log = get_module_logger(__name__)
|
|
12
14
|
|
agenta/sdk/middleware/vault.py
CHANGED
|
@@ -82,13 +82,17 @@ class VaultMiddleware(BaseHTTPMiddleware):
|
|
|
82
82
|
request.state.vault = {}
|
|
83
83
|
|
|
84
84
|
with suppress():
|
|
85
|
-
secrets = await self._get_secrets(request)
|
|
85
|
+
secrets, vault_secrets, local_secrets = await self._get_secrets(request)
|
|
86
86
|
|
|
87
|
-
request.state.vault = {
|
|
87
|
+
request.state.vault = {
|
|
88
|
+
"secrets": secrets,
|
|
89
|
+
"vault_secrets": vault_secrets,
|
|
90
|
+
"local_secrets": local_secrets,
|
|
91
|
+
}
|
|
88
92
|
|
|
89
93
|
return await call_next(request)
|
|
90
94
|
|
|
91
|
-
async def _get_secrets(self, request: Request) ->
|
|
95
|
+
async def _get_secrets(self, request: Request) -> tuple[list, list, list]:
|
|
92
96
|
credentials = request.state.auth.get("credentials")
|
|
93
97
|
|
|
94
98
|
headers = None
|
|
@@ -107,8 +111,13 @@ class VaultMiddleware(BaseHTTPMiddleware):
|
|
|
107
111
|
|
|
108
112
|
if secrets_cache:
|
|
109
113
|
secrets = secrets_cache.get("secrets")
|
|
114
|
+
vault_secrets = secrets_cache.get("vault_secrets")
|
|
115
|
+
local_secrets = secrets_cache.get("local_secrets")
|
|
110
116
|
|
|
111
|
-
|
|
117
|
+
if vault_secrets is None or local_secrets is None:
|
|
118
|
+
return secrets, [], []
|
|
119
|
+
|
|
120
|
+
return secrets, vault_secrets, local_secrets
|
|
112
121
|
|
|
113
122
|
local_secrets: List[Dict[str, Any]] = []
|
|
114
123
|
allow_secrets = True
|
|
@@ -137,7 +146,7 @@ class VaultMiddleware(BaseHTTPMiddleware):
|
|
|
137
146
|
except DenyException as e: # pylint: disable=bare-except
|
|
138
147
|
log.warning(f"Agenta [secrets] {e.status_code}: {e.content}")
|
|
139
148
|
allow_secrets = False
|
|
140
|
-
except: # pylint: disable=bare-except
|
|
149
|
+
except Exception: # pylint: disable=bare-except
|
|
141
150
|
display_exception("Vault: Local Secrets Exception")
|
|
142
151
|
|
|
143
152
|
vault_secrets: List[Dict[str, Any]] = []
|
|
@@ -154,33 +163,39 @@ class VaultMiddleware(BaseHTTPMiddleware):
|
|
|
154
163
|
|
|
155
164
|
else:
|
|
156
165
|
vault_secrets = response.json()
|
|
157
|
-
except: # pylint: disable=bare-except
|
|
166
|
+
except Exception: # pylint: disable=bare-except
|
|
158
167
|
display_exception("Vault: Vault Secrets Exception")
|
|
159
168
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
custom_secrets = []
|
|
169
|
+
local_standard = {}
|
|
170
|
+
vault_standard = {}
|
|
171
|
+
vault_custom = []
|
|
164
172
|
|
|
165
173
|
if local_secrets:
|
|
166
174
|
for secret in local_secrets:
|
|
167
|
-
|
|
175
|
+
local_standard[secret["data"]["kind"]] = secret # type: ignore
|
|
168
176
|
|
|
169
177
|
if vault_secrets:
|
|
170
178
|
for secret in vault_secrets:
|
|
171
179
|
if secret["kind"] == "provider_key": # type: ignore
|
|
172
|
-
|
|
180
|
+
vault_standard[secret["data"]["kind"]] = secret # type: ignore
|
|
173
181
|
elif secret["kind"] == "custom_provider": # type: ignore
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
standard_secrets = list(standard_secrets.values())
|
|
182
|
+
vault_custom.append(secret)
|
|
177
183
|
|
|
178
|
-
|
|
184
|
+
combined_standard = {**local_standard, **vault_standard}
|
|
185
|
+
combined_vault = list(vault_standard.values()) + vault_custom
|
|
186
|
+
secrets = list(combined_standard.values()) + vault_custom
|
|
179
187
|
|
|
180
188
|
if not allow_secrets:
|
|
181
|
-
_cache.put(
|
|
189
|
+
_cache.put(
|
|
190
|
+
_hash,
|
|
191
|
+
{
|
|
192
|
+
"secrets": secrets,
|
|
193
|
+
"vault_secrets": combined_vault,
|
|
194
|
+
"local_secrets": local_secrets,
|
|
195
|
+
},
|
|
196
|
+
)
|
|
182
197
|
|
|
183
|
-
return secrets
|
|
198
|
+
return secrets, combined_vault, local_secrets
|
|
184
199
|
|
|
185
200
|
async def _allow_local_secrets(self, credentials):
|
|
186
201
|
try:
|
|
@@ -6,7 +6,7 @@ from fastapi import Request
|
|
|
6
6
|
|
|
7
7
|
from agenta.sdk.utils.logging import get_module_logger
|
|
8
8
|
from agenta.sdk.utils.exceptions import suppress
|
|
9
|
-
from agenta.sdk.
|
|
9
|
+
from agenta.sdk.tracing.propagation import extract
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
log = get_module_logger(__name__)
|