agenta 0.27.6a2__py3-none-any.whl → 0.27.7__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/cli/main.py +4 -51
- agenta/client/backend/__init__.py +63 -0
- agenta/client/backend/apps/client.py +12 -58
- agenta/client/backend/client.py +22 -22
- agenta/client/backend/core/http_client.py +15 -7
- agenta/client/backend/evaluations/client.py +0 -11
- agenta/client/backend/observability/client.py +4 -4
- agenta/client/backend/observability_v_1/__init__.py +5 -0
- agenta/client/backend/observability_v_1/client.py +560 -0
- agenta/client/backend/observability_v_1/types/__init__.py +6 -0
- agenta/client/backend/observability_v_1/types/format.py +5 -0
- agenta/client/backend/observability_v_1/types/query_traces_response.py +11 -0
- agenta/client/backend/testsets/client.py +8 -40
- agenta/client/backend/types/__init__.py +58 -0
- agenta/client/backend/types/agenta_node_dto.py +48 -0
- agenta/client/backend/types/agenta_node_dto_nodes_value.py +6 -0
- agenta/client/backend/types/agenta_nodes_response.py +30 -0
- agenta/client/backend/types/agenta_root_dto.py +30 -0
- agenta/client/backend/types/agenta_roots_response.py +30 -0
- agenta/client/backend/types/agenta_tree_dto.py +30 -0
- agenta/client/backend/types/agenta_trees_response.py +30 -0
- agenta/client/backend/types/collect_status_response.py +22 -0
- agenta/client/backend/types/exception_dto.py +26 -0
- agenta/client/backend/types/link_dto.py +24 -0
- agenta/client/backend/types/node_dto.py +24 -0
- agenta/client/backend/types/node_type.py +19 -0
- agenta/client/backend/types/o_tel_context_dto.py +22 -0
- agenta/client/backend/types/o_tel_event_dto.py +23 -0
- agenta/client/backend/types/o_tel_extra_dto.py +26 -0
- agenta/client/backend/types/o_tel_link_dto.py +23 -0
- agenta/client/backend/types/o_tel_span_dto.py +37 -0
- agenta/client/backend/types/o_tel_span_kind.py +15 -0
- agenta/client/backend/types/o_tel_spans_response.py +24 -0
- agenta/client/backend/types/o_tel_status_code.py +8 -0
- agenta/client/backend/types/parent_dto.py +21 -0
- agenta/client/backend/types/root_dto.py +21 -0
- agenta/client/backend/types/span_dto.py +54 -0
- agenta/client/backend/types/span_dto_nodes_value.py +9 -0
- agenta/client/backend/types/status_code.py +5 -0
- agenta/client/backend/types/status_dto.py +23 -0
- agenta/client/backend/types/time_dto.py +23 -0
- agenta/client/backend/types/tree_dto.py +23 -0
- agenta/client/backend/types/tree_type.py +5 -0
- agenta/client/backend/variants/client.py +24 -16
- agenta/sdk/__init__.py +2 -0
- agenta/sdk/agenta_init.py +4 -9
- agenta/sdk/decorators/routing.py +41 -56
- agenta/sdk/litellm/litellm.py +30 -75
- agenta/sdk/middleware/auth.py +10 -7
- agenta/sdk/tracing/context.py +6 -6
- agenta/sdk/tracing/inline.py +48 -151
- agenta/sdk/tracing/processors.py +1 -3
- agenta/sdk/tracing/tracing.py +1 -5
- agenta/sdk/types.py +5 -2
- agenta/sdk/utils/exceptions.py +15 -9
- agenta/sdk/utils/logging.py +5 -1
- {agenta-0.27.6a2.dist-info → agenta-0.27.7.dist-info}/METADATA +1 -1
- {agenta-0.27.6a2.dist-info → agenta-0.27.7.dist-info}/RECORD +60 -27
- agenta/sdk/utils/debug.py +0 -68
- {agenta-0.27.6a2.dist-info → agenta-0.27.7.dist-info}/WHEEL +0 -0
- {agenta-0.27.6a2.dist-info → agenta-0.27.7.dist-info}/entry_points.txt +0 -0
agenta/sdk/decorators/routing.py
CHANGED
|
@@ -37,27 +37,21 @@ from agenta.sdk.types import (
|
|
|
37
37
|
|
|
38
38
|
import agenta as ag
|
|
39
39
|
|
|
40
|
-
app = FastAPI()
|
|
41
|
-
|
|
42
|
-
origins = [
|
|
43
|
-
"*",
|
|
44
|
-
]
|
|
45
40
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
allow_methods=["*"],
|
|
51
|
-
allow_headers=["*"],
|
|
41
|
+
AGENTA_USE_CORS = str(environ.get("AGENTA_USE_CORS", "true")).lower() in (
|
|
42
|
+
"true",
|
|
43
|
+
"1",
|
|
44
|
+
"t",
|
|
52
45
|
)
|
|
53
46
|
|
|
54
|
-
|
|
47
|
+
app = FastAPI()
|
|
48
|
+
log.setLevel("DEBUG")
|
|
55
49
|
|
|
56
50
|
|
|
57
|
-
|
|
51
|
+
_MIDDLEWARES = True
|
|
58
52
|
|
|
59
53
|
|
|
60
|
-
|
|
54
|
+
app.include_router(router, prefix="")
|
|
61
55
|
|
|
62
56
|
|
|
63
57
|
class PathValidator(BaseModel):
|
|
@@ -137,12 +131,19 @@ class entrypoint:
|
|
|
137
131
|
resource_type="application",
|
|
138
132
|
)
|
|
139
133
|
|
|
134
|
+
if AGENTA_USE_CORS:
|
|
135
|
+
app.add_middleware(
|
|
136
|
+
CORSMiddleware,
|
|
137
|
+
allow_origins=["*"],
|
|
138
|
+
allow_methods=["*"],
|
|
139
|
+
allow_headers=["*"],
|
|
140
|
+
allow_credentials=True,
|
|
141
|
+
)
|
|
142
|
+
|
|
140
143
|
_MIDDLEWARES = False
|
|
141
144
|
|
|
142
145
|
except: # pylint: disable=bare-except
|
|
143
|
-
log.
|
|
144
|
-
log.error("Agenta SDK - failed to secure route: %s", route_path)
|
|
145
|
-
log.error("------------------------------------")
|
|
146
|
+
log.warning("Agenta SDK - failed to secure route: %s", route_path)
|
|
146
147
|
### --- Update Middleware --- #
|
|
147
148
|
|
|
148
149
|
DEFAULT_PATH = "generate"
|
|
@@ -354,9 +355,7 @@ class entrypoint:
|
|
|
354
355
|
*args,
|
|
355
356
|
**func_params,
|
|
356
357
|
):
|
|
357
|
-
log.info("
|
|
358
|
-
log.info(f"Agenta SDK - running route: {repr(self.route_path or '/')}")
|
|
359
|
-
log.info("---------------------------")
|
|
358
|
+
log.info("Agenta SDK - handling route: %s", repr(self.route_path or "/"))
|
|
360
359
|
|
|
361
360
|
tracing_context.set(routing_context.get())
|
|
362
361
|
|
|
@@ -374,36 +373,32 @@ class entrypoint:
|
|
|
374
373
|
|
|
375
374
|
async def handle_success(self, result: Any, inline_trace: bool):
|
|
376
375
|
data = None
|
|
377
|
-
|
|
376
|
+
tree = None
|
|
378
377
|
|
|
379
378
|
with suppress():
|
|
380
379
|
data = self.patch_result(result)
|
|
381
380
|
|
|
382
381
|
if inline_trace:
|
|
383
|
-
|
|
382
|
+
tree = await self.fetch_inline_trace(inline_trace)
|
|
384
383
|
|
|
385
384
|
log.info(f"----------------------------------")
|
|
386
385
|
log.info(f"Agenta SDK - exiting with success: 200")
|
|
387
386
|
log.info(f"----------------------------------")
|
|
388
387
|
|
|
389
|
-
return BaseResponse(data=data,
|
|
388
|
+
return BaseResponse(data=data, tree=tree)
|
|
390
389
|
|
|
391
390
|
def handle_failure(self, error: Exception):
|
|
392
|
-
log.
|
|
393
|
-
log.
|
|
394
|
-
log.
|
|
395
|
-
log.
|
|
396
|
-
log.
|
|
391
|
+
log.warning("--------------------------------------------------")
|
|
392
|
+
log.warning("Agenta SDK - handling application exception below:")
|
|
393
|
+
log.warning("--------------------------------------------------")
|
|
394
|
+
log.warning(format_exc().strip("\n"))
|
|
395
|
+
log.warning("--------------------------------------------------")
|
|
397
396
|
|
|
398
397
|
status_code = error.status_code if hasattr(error, "status_code") else 500
|
|
399
398
|
message = str(error)
|
|
400
399
|
stacktrace = format_exception(error, value=error, tb=error.__traceback__) # type: ignore
|
|
401
400
|
detail = {"message": message, "stacktrace": stacktrace}
|
|
402
401
|
|
|
403
|
-
log.error(f"----------------------------------")
|
|
404
|
-
log.error(f"Agenta SDK - exiting with failure: {status_code}")
|
|
405
|
-
log.error(f"----------------------------------")
|
|
406
|
-
|
|
407
402
|
raise HTTPException(status_code=status_code, detail=detail)
|
|
408
403
|
|
|
409
404
|
def patch_result(self, result: Any):
|
|
@@ -680,10 +675,7 @@ class entrypoint:
|
|
|
680
675
|
|
|
681
676
|
loop = get_event_loop()
|
|
682
677
|
|
|
683
|
-
with routing_context_manager(
|
|
684
|
-
config=args_config_params,
|
|
685
|
-
environment="terminal",
|
|
686
|
-
):
|
|
678
|
+
with routing_context_manager(config=args_config_params):
|
|
687
679
|
result = loop.run_until_complete(
|
|
688
680
|
self.execute_function(
|
|
689
681
|
func,
|
|
@@ -692,30 +684,23 @@ class entrypoint:
|
|
|
692
684
|
)
|
|
693
685
|
)
|
|
694
686
|
|
|
695
|
-
SHOW_DETAILS = True
|
|
696
|
-
SHOW_DATA = False
|
|
697
|
-
SHOW_TRACE = False
|
|
698
|
-
|
|
699
687
|
if result.trace:
|
|
700
688
|
log.info("\n========= Result =========\n")
|
|
701
689
|
|
|
702
690
|
log.info(f"trace_id: {result.trace['trace_id']}")
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
log.info(f"----------------")
|
|
717
|
-
log.info(dumps(result.trace.get("spans", []), indent=2))
|
|
718
|
-
log.info(f"----------------")
|
|
691
|
+
log.info(f"latency: {result.trace.get('latency')}")
|
|
692
|
+
log.info(f"cost: {result.trace.get('cost')}")
|
|
693
|
+
log.info(f"usage: {list(result.trace.get('usage', {}).values())}")
|
|
694
|
+
|
|
695
|
+
log.info(" ")
|
|
696
|
+
log.info("data:")
|
|
697
|
+
log.info(dumps(result.data, indent=2))
|
|
698
|
+
|
|
699
|
+
log.info(" ")
|
|
700
|
+
log.info("trace:")
|
|
701
|
+
log.info("----------------")
|
|
702
|
+
log.info(dumps(result.trace.get("spans", []), indent=2))
|
|
703
|
+
log.info("----------------")
|
|
719
704
|
|
|
720
705
|
log.info("\n==========================\n")
|
|
721
706
|
|
agenta/sdk/litellm/litellm.py
CHANGED
|
@@ -60,7 +60,11 @@ def litellm_handler():
|
|
|
60
60
|
)
|
|
61
61
|
|
|
62
62
|
if not self.span:
|
|
63
|
-
log.
|
|
63
|
+
log.warning("Agenta SDK - litellm tracing failed")
|
|
64
|
+
return
|
|
65
|
+
|
|
66
|
+
if not self.span.is_recording():
|
|
67
|
+
log.error("Agenta SDK - litellm span not recording.")
|
|
64
68
|
return
|
|
65
69
|
|
|
66
70
|
self.span.set_attributes(
|
|
@@ -86,43 +90,11 @@ def litellm_handler():
|
|
|
86
90
|
end_time,
|
|
87
91
|
):
|
|
88
92
|
if not self.span:
|
|
89
|
-
log.
|
|
93
|
+
log.warning("Agenta SDK - litellm tracing failed")
|
|
90
94
|
return
|
|
91
95
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
for choice in response_obj.choices:
|
|
95
|
-
message = choice.message.__dict__
|
|
96
|
-
result.append(message)
|
|
97
|
-
|
|
98
|
-
outputs = {"completion": result}
|
|
99
|
-
self.span.set_attributes(
|
|
100
|
-
attributes={"outputs": outputs},
|
|
101
|
-
namespace="data",
|
|
102
|
-
)
|
|
103
|
-
|
|
104
|
-
except Exception as e:
|
|
105
|
-
pass
|
|
106
|
-
|
|
107
|
-
self.span.set_attributes(
|
|
108
|
-
attributes={"total": kwargs.get("response_cost")},
|
|
109
|
-
namespace="metrics.unit.costs",
|
|
110
|
-
)
|
|
111
|
-
|
|
112
|
-
self.span.set_attributes(
|
|
113
|
-
attributes=(
|
|
114
|
-
{
|
|
115
|
-
"prompt": response_obj.usage.prompt_tokens,
|
|
116
|
-
"completion": response_obj.usage.completion_tokens,
|
|
117
|
-
"total": response_obj.usage.total_tokens,
|
|
118
|
-
}
|
|
119
|
-
),
|
|
120
|
-
namespace="metrics.unit.tokens",
|
|
121
|
-
)
|
|
122
|
-
|
|
123
|
-
self.span.set_status(status="OK")
|
|
124
|
-
|
|
125
|
-
self.span.end()
|
|
96
|
+
if not self.span.is_recording():
|
|
97
|
+
return
|
|
126
98
|
|
|
127
99
|
def log_success_event(
|
|
128
100
|
self,
|
|
@@ -131,8 +103,14 @@ def litellm_handler():
|
|
|
131
103
|
start_time,
|
|
132
104
|
end_time,
|
|
133
105
|
):
|
|
106
|
+
if kwargs.get("stream"):
|
|
107
|
+
return
|
|
108
|
+
|
|
134
109
|
if not self.span:
|
|
135
|
-
log.
|
|
110
|
+
log.warning("Agenta SDK - litellm tracing failed")
|
|
111
|
+
return
|
|
112
|
+
|
|
113
|
+
if not self.span.is_recording():
|
|
136
114
|
return
|
|
137
115
|
|
|
138
116
|
try:
|
|
@@ -178,7 +156,10 @@ def litellm_handler():
|
|
|
178
156
|
end_time,
|
|
179
157
|
):
|
|
180
158
|
if not self.span:
|
|
181
|
-
log.
|
|
159
|
+
log.warning("Agenta SDK - litellm tracing failed")
|
|
160
|
+
return
|
|
161
|
+
|
|
162
|
+
if not self.span.is_recording():
|
|
182
163
|
return
|
|
183
164
|
|
|
184
165
|
self.span.record_exception(kwargs["exception"])
|
|
@@ -195,43 +176,11 @@ def litellm_handler():
|
|
|
195
176
|
end_time,
|
|
196
177
|
):
|
|
197
178
|
if not self.span:
|
|
198
|
-
log.
|
|
179
|
+
log.warning("Agenta SDK - litellm tracing failed")
|
|
199
180
|
return
|
|
200
181
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
for choice in response_obj.choices:
|
|
204
|
-
message = choice.message.__dict__
|
|
205
|
-
result.append(message)
|
|
206
|
-
|
|
207
|
-
outputs = {"completion": result}
|
|
208
|
-
self.span.set_attributes(
|
|
209
|
-
attributes={"outputs": outputs},
|
|
210
|
-
namespace="data",
|
|
211
|
-
)
|
|
212
|
-
|
|
213
|
-
except Exception as e:
|
|
214
|
-
pass
|
|
215
|
-
|
|
216
|
-
self.span.set_attributes(
|
|
217
|
-
attributes={"total": kwargs.get("response_cost")},
|
|
218
|
-
namespace="metrics.unit.costs",
|
|
219
|
-
)
|
|
220
|
-
|
|
221
|
-
self.span.set_attributes(
|
|
222
|
-
attributes=(
|
|
223
|
-
{
|
|
224
|
-
"prompt": response_obj.usage.prompt_tokens,
|
|
225
|
-
"completion": response_obj.usage.completion_tokens,
|
|
226
|
-
"total": response_obj.usage.total_tokens,
|
|
227
|
-
}
|
|
228
|
-
),
|
|
229
|
-
namespace="metrics.unit.tokens",
|
|
230
|
-
)
|
|
231
|
-
|
|
232
|
-
self.span.set_status(status="OK")
|
|
233
|
-
|
|
234
|
-
self.span.end()
|
|
182
|
+
if not self.span.is_recording():
|
|
183
|
+
return
|
|
235
184
|
|
|
236
185
|
async def async_log_success_event(
|
|
237
186
|
self,
|
|
@@ -241,7 +190,10 @@ def litellm_handler():
|
|
|
241
190
|
end_time,
|
|
242
191
|
):
|
|
243
192
|
if not self.span:
|
|
244
|
-
log.
|
|
193
|
+
log.warning("Agenta SDK - litellm tracing failed")
|
|
194
|
+
return
|
|
195
|
+
|
|
196
|
+
if not self.span.is_recording():
|
|
245
197
|
return
|
|
246
198
|
|
|
247
199
|
try:
|
|
@@ -287,7 +239,10 @@ def litellm_handler():
|
|
|
287
239
|
end_time,
|
|
288
240
|
):
|
|
289
241
|
if not self.span:
|
|
290
|
-
log.
|
|
242
|
+
log.warning("Agenta SDK - litellm tracing failed")
|
|
243
|
+
return
|
|
244
|
+
|
|
245
|
+
if not self.span.is_recording():
|
|
291
246
|
return
|
|
292
247
|
|
|
293
248
|
self.span.record_exception(kwargs["exception"])
|
agenta/sdk/middleware/auth.py
CHANGED
|
@@ -27,6 +27,8 @@ AGENTA_SDK_AUTH_CACHE = str(environ.get("AGENTA_SDK_AUTH_CACHE", True)).lower()
|
|
|
27
27
|
"t",
|
|
28
28
|
)
|
|
29
29
|
|
|
30
|
+
AGENTA_SDK_AUTH_CACHE = False
|
|
31
|
+
|
|
30
32
|
AGENTA_UNAUTHORIZED_EXECUTION_ALLOWED = str(
|
|
31
33
|
environ.get("AGENTA_UNAUTHORIZED_EXECUTION_ALLOWED", False)
|
|
32
34
|
).lower() in ("true", "1", "t")
|
|
@@ -61,7 +63,6 @@ class AuthorizationMiddleware(BaseHTTPMiddleware):
|
|
|
61
63
|
self,
|
|
62
64
|
request: Request,
|
|
63
65
|
call_next: Callable,
|
|
64
|
-
project_id: Optional[UUID] = None,
|
|
65
66
|
):
|
|
66
67
|
if AGENTA_UNAUTHORIZED_EXECUTION_ALLOWED:
|
|
67
68
|
return await call_next(request)
|
|
@@ -83,6 +84,8 @@ class AuthorizationMiddleware(BaseHTTPMiddleware):
|
|
|
83
84
|
"resource_id": self.resource_id,
|
|
84
85
|
}
|
|
85
86
|
|
|
87
|
+
project_id = request.query_params.get("project_id")
|
|
88
|
+
|
|
86
89
|
if project_id:
|
|
87
90
|
params["project_id"] = project_id
|
|
88
91
|
|
|
@@ -125,7 +128,7 @@ class AuthorizationMiddleware(BaseHTTPMiddleware):
|
|
|
125
128
|
|
|
126
129
|
cache.put(_hash, policy)
|
|
127
130
|
|
|
128
|
-
if policy.get("effect") == "deny":
|
|
131
|
+
if not policy or policy.get("effect") == "deny":
|
|
129
132
|
return Deny()
|
|
130
133
|
|
|
131
134
|
request.state.credentials = policy.get("credentials")
|
|
@@ -133,10 +136,10 @@ class AuthorizationMiddleware(BaseHTTPMiddleware):
|
|
|
133
136
|
return await call_next(request)
|
|
134
137
|
|
|
135
138
|
except: # pylint: disable=bare-except
|
|
136
|
-
log.
|
|
137
|
-
log.
|
|
138
|
-
log.
|
|
139
|
-
log.
|
|
140
|
-
log.
|
|
139
|
+
log.warning("------------------------------------------------------")
|
|
140
|
+
log.warning("Agenta SDK - handling auth middleware exception below:")
|
|
141
|
+
log.warning("------------------------------------------------------")
|
|
142
|
+
log.warning(format_exc().strip("\n"))
|
|
143
|
+
log.warning("------------------------------------------------------")
|
|
141
144
|
|
|
142
145
|
return Deny()
|
agenta/sdk/tracing/context.py
CHANGED
|
@@ -14,11 +14,11 @@ def tracing_context_manager():
|
|
|
14
14
|
token = tracing_context.set(_tracing_context)
|
|
15
15
|
try:
|
|
16
16
|
yield
|
|
17
|
-
except
|
|
18
|
-
log.
|
|
19
|
-
log.
|
|
20
|
-
log.
|
|
21
|
-
log.
|
|
22
|
-
log.
|
|
17
|
+
except: # pylint: disable=bare-except
|
|
18
|
+
log.warning("----------------------------------------------")
|
|
19
|
+
log.warning("Agenta SDK - handling tracing exception below:")
|
|
20
|
+
log.warning("----------------------------------------------")
|
|
21
|
+
log.warning(format_exc().strip("\n"))
|
|
22
|
+
log.warning("----------------------------------------------")
|
|
23
23
|
finally:
|
|
24
24
|
tracing_context.reset(token)
|
agenta/sdk/tracing/inline.py
CHANGED
|
@@ -41,7 +41,6 @@ from uuid import UUID
|
|
|
41
41
|
class TimeDTO(BaseModel):
|
|
42
42
|
start: datetime
|
|
43
43
|
end: datetime
|
|
44
|
-
span: int
|
|
45
44
|
|
|
46
45
|
|
|
47
46
|
class StatusCode(Enum):
|
|
@@ -846,12 +845,9 @@ def parse_from_otel_span_dto(
|
|
|
846
845
|
else None
|
|
847
846
|
)
|
|
848
847
|
|
|
849
|
-
duration = (otel_span_dto.end_time - otel_span_dto.start_time).total_seconds()
|
|
850
|
-
|
|
851
848
|
time = TimeDTO(
|
|
852
849
|
start=otel_span_dto.start_time,
|
|
853
850
|
end=otel_span_dto.end_time,
|
|
854
|
-
span=round(duration * 1_000_000), # microseconds
|
|
855
851
|
)
|
|
856
852
|
|
|
857
853
|
status = StatusDTO(
|
|
@@ -863,6 +859,13 @@ def parse_from_otel_span_dto(
|
|
|
863
859
|
|
|
864
860
|
data, metrics, meta, tags, refs = _parse_from_attributes(otel_span_dto)
|
|
865
861
|
|
|
862
|
+
duration = (otel_span_dto.end_time - otel_span_dto.start_time).total_seconds()
|
|
863
|
+
|
|
864
|
+
if metrics is None:
|
|
865
|
+
metrics = dict()
|
|
866
|
+
|
|
867
|
+
metrics["acc.duration.total"] = round(duration * 1_000, 3) # milliseconds
|
|
868
|
+
|
|
866
869
|
root_id = str(tree_id)
|
|
867
870
|
if refs is not None:
|
|
868
871
|
root_id = refs.get("scenario.id", root_id)
|
|
@@ -903,9 +906,9 @@ def parse_to_agenta_span_dto(
|
|
|
903
906
|
if span_dto.data:
|
|
904
907
|
span_dto.data = _unmarshal_attributes(span_dto.data)
|
|
905
908
|
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
+
if "outputs" in span_dto.data:
|
|
910
|
+
if "__default__" in span_dto.data["outputs"]:
|
|
911
|
+
span_dto.data["outputs"] = span_dto.data["outputs"]["__default__"]
|
|
909
912
|
|
|
910
913
|
# METRICS
|
|
911
914
|
if span_dto.metrics:
|
|
@@ -934,6 +937,17 @@ def parse_to_agenta_span_dto(
|
|
|
934
937
|
else:
|
|
935
938
|
parse_to_agenta_span_dto(v)
|
|
936
939
|
|
|
940
|
+
# MASK LINKS FOR NOW
|
|
941
|
+
span_dto.links = None
|
|
942
|
+
# ------------------
|
|
943
|
+
|
|
944
|
+
# MASK LIFECYCLE FOR NOW
|
|
945
|
+
# span_dto.lifecycle = None
|
|
946
|
+
if span_dto.lifecycle:
|
|
947
|
+
span_dto.lifecycle.updated_at = None
|
|
948
|
+
span_dto.lifecycle.updated_by_id = None
|
|
949
|
+
# ----------------------
|
|
950
|
+
|
|
937
951
|
return span_dto
|
|
938
952
|
|
|
939
953
|
|
|
@@ -945,6 +959,8 @@ def parse_to_agenta_span_dto(
|
|
|
945
959
|
from litellm import cost_calculator
|
|
946
960
|
from opentelemetry.sdk.trace import ReadableSpan
|
|
947
961
|
|
|
962
|
+
from agenta.sdk.types import AgentaNodeDto, AgentaNodesResponse
|
|
963
|
+
|
|
948
964
|
|
|
949
965
|
def parse_inline_trace(
|
|
950
966
|
spans: Dict[str, ReadableSpan],
|
|
@@ -992,51 +1008,19 @@ def parse_inline_trace(
|
|
|
992
1008
|
### services.observability.service.query() ###
|
|
993
1009
|
##############################################
|
|
994
1010
|
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
tokens = {
|
|
1009
|
-
"prompt_tokens": root_span.metrics.get("acc", {})
|
|
1010
|
-
.get("tokens", {})
|
|
1011
|
-
.get("prompt", 0),
|
|
1012
|
-
"completion_tokens": root_span.metrics.get("acc", {})
|
|
1013
|
-
.get("tokens", {})
|
|
1014
|
-
.get("completion", 0),
|
|
1015
|
-
"total_tokens": root_span.metrics.get("acc", {})
|
|
1016
|
-
.get("tokens", {})
|
|
1017
|
-
.get("total", 0),
|
|
1018
|
-
}
|
|
1019
|
-
|
|
1020
|
-
spans = [
|
|
1021
|
-
loads(span.model_dump_json(exclude_none=True)) for span in legacy_spans
|
|
1022
|
-
]
|
|
1023
|
-
|
|
1024
|
-
inline_trace = {
|
|
1025
|
-
"trace_id": trace_id,
|
|
1026
|
-
"latency": latency,
|
|
1027
|
-
"cost": cost,
|
|
1028
|
-
"usage": tokens,
|
|
1029
|
-
"spans": spans,
|
|
1030
|
-
}
|
|
1031
|
-
|
|
1032
|
-
else:
|
|
1033
|
-
spans = [
|
|
1034
|
-
loads(span_dto.model_dump_json(exclude_none=True))
|
|
1035
|
-
for span_dto in agenta_span_dtos
|
|
1036
|
-
]
|
|
1037
|
-
|
|
1038
|
-
inline_trace = spans # turn into Agenta Model ?
|
|
1039
|
-
|
|
1011
|
+
spans = [
|
|
1012
|
+
loads(
|
|
1013
|
+
span_dto.model_dump_json(
|
|
1014
|
+
exclude_none=True,
|
|
1015
|
+
exclude_defaults=True,
|
|
1016
|
+
)
|
|
1017
|
+
)
|
|
1018
|
+
for span_dto in agenta_span_dtos
|
|
1019
|
+
]
|
|
1020
|
+
inline_trace = AgentaNodesResponse(
|
|
1021
|
+
version="1.0.0",
|
|
1022
|
+
nodes=[AgentaNodeDto(**span) for span in spans],
|
|
1023
|
+
).model_dump(exclude_none=True, exclude_unset=True)
|
|
1040
1024
|
return inline_trace
|
|
1041
1025
|
|
|
1042
1026
|
|
|
@@ -1120,98 +1104,6 @@ class LlmTokens(BaseModel):
|
|
|
1120
1104
|
total_tokens: Optional[int] = 0
|
|
1121
1105
|
|
|
1122
1106
|
|
|
1123
|
-
class CreateSpan(BaseModel):
|
|
1124
|
-
id: str
|
|
1125
|
-
app_id: str
|
|
1126
|
-
variant_id: Optional[str] = None
|
|
1127
|
-
variant_name: Optional[str] = None
|
|
1128
|
-
inputs: Optional[Dict[str, Optional[Any]]] = None
|
|
1129
|
-
internals: Optional[Dict[str, Optional[Any]]] = None
|
|
1130
|
-
outputs: Optional[Union[str, Dict[str, Optional[Any]], List[Any]]] = None
|
|
1131
|
-
config: Optional[Dict[str, Optional[Any]]] = None
|
|
1132
|
-
environment: Optional[str] = None
|
|
1133
|
-
tags: Optional[List[str]] = None
|
|
1134
|
-
token_consumption: Optional[int] = None
|
|
1135
|
-
name: str
|
|
1136
|
-
parent_span_id: Optional[str] = None
|
|
1137
|
-
attributes: Optional[Dict[str, Optional[Any]]] = None
|
|
1138
|
-
spankind: str
|
|
1139
|
-
status: str
|
|
1140
|
-
user: Optional[str] = None
|
|
1141
|
-
start_time: datetime
|
|
1142
|
-
end_time: datetime
|
|
1143
|
-
tokens: Optional[LlmTokens] = None
|
|
1144
|
-
cost: Optional[float] = None
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
def _parse_to_legacy_span(span: SpanDTO) -> CreateSpan:
|
|
1148
|
-
attributes = None
|
|
1149
|
-
if span.otel:
|
|
1150
|
-
attributes = span.otel.attributes or {}
|
|
1151
|
-
|
|
1152
|
-
if span.otel.events:
|
|
1153
|
-
for event in span.otel.events:
|
|
1154
|
-
if event.name == "exception":
|
|
1155
|
-
attributes.update(**event.attributes)
|
|
1156
|
-
|
|
1157
|
-
legacy_span = CreateSpan(
|
|
1158
|
-
id=span.node.id.hex[:24],
|
|
1159
|
-
spankind=span.node.type,
|
|
1160
|
-
name=span.node.name,
|
|
1161
|
-
#
|
|
1162
|
-
status=span.status.code.name,
|
|
1163
|
-
#
|
|
1164
|
-
start_time=span.time.start,
|
|
1165
|
-
end_time=span.time.end,
|
|
1166
|
-
#
|
|
1167
|
-
parent_span_id=span.parent.id.hex[:24] if span.parent else None,
|
|
1168
|
-
#
|
|
1169
|
-
inputs=span.data.get("inputs") if span.data else {},
|
|
1170
|
-
internals=span.data.get("internals") if span.data else {},
|
|
1171
|
-
outputs=span.data.get("outputs") if span.data else {},
|
|
1172
|
-
#
|
|
1173
|
-
environment=span.meta.get("environment") if span.meta else None,
|
|
1174
|
-
config=span.meta.get("configuration") if span.meta else None,
|
|
1175
|
-
#
|
|
1176
|
-
tokens=(
|
|
1177
|
-
LlmTokens(
|
|
1178
|
-
prompt_tokens=span.metrics.get("acc", {})
|
|
1179
|
-
.get("tokens", {})
|
|
1180
|
-
.get("prompt", 0.0),
|
|
1181
|
-
completion_tokens=span.metrics.get("acc", {})
|
|
1182
|
-
.get("tokens", {})
|
|
1183
|
-
.get("completion", 0.0),
|
|
1184
|
-
total_tokens=span.metrics.get("acc", {})
|
|
1185
|
-
.get("tokens", {})
|
|
1186
|
-
.get("total", 0.0),
|
|
1187
|
-
)
|
|
1188
|
-
if span.metrics
|
|
1189
|
-
else None
|
|
1190
|
-
),
|
|
1191
|
-
cost=(
|
|
1192
|
-
span.metrics.get("acc", {}).get("costs", {}).get("total", 0.0)
|
|
1193
|
-
if span.metrics
|
|
1194
|
-
else None
|
|
1195
|
-
),
|
|
1196
|
-
#
|
|
1197
|
-
app_id=(
|
|
1198
|
-
span.refs.get("application", {}).get("id", "missing-app-id")
|
|
1199
|
-
if span.refs
|
|
1200
|
-
else "missing-app-id"
|
|
1201
|
-
),
|
|
1202
|
-
#
|
|
1203
|
-
attributes=attributes,
|
|
1204
|
-
#
|
|
1205
|
-
variant_id=None,
|
|
1206
|
-
variant_name=None,
|
|
1207
|
-
tags=None,
|
|
1208
|
-
token_consumption=None,
|
|
1209
|
-
user=None,
|
|
1210
|
-
)
|
|
1211
|
-
|
|
1212
|
-
return legacy_span
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
1107
|
TYPES_WITH_COSTS = [
|
|
1216
1108
|
"embedding",
|
|
1217
1109
|
"query",
|
|
@@ -1229,13 +1121,15 @@ def calculate_costs(span_idx: Dict[str, SpanDTO]):
|
|
|
1229
1121
|
and span.meta
|
|
1230
1122
|
and span.metrics
|
|
1231
1123
|
):
|
|
1124
|
+
model = span.meta.get("response.model")
|
|
1125
|
+
prompt_tokens = span.metrics.get("unit.tokens.prompt", 0.0)
|
|
1126
|
+
completion_tokens = span.metrics.get("unit.tokens.completion", 0.0)
|
|
1127
|
+
|
|
1232
1128
|
try:
|
|
1233
1129
|
costs = cost_calculator.cost_per_token(
|
|
1234
|
-
model=
|
|
1235
|
-
prompt_tokens=
|
|
1236
|
-
completion_tokens=
|
|
1237
|
-
call_type=span.node.type.name.lower(),
|
|
1238
|
-
response_time_ms=span.time.span // 1_000,
|
|
1130
|
+
model=model,
|
|
1131
|
+
prompt_tokens=prompt_tokens,
|
|
1132
|
+
completion_tokens=completion_tokens,
|
|
1239
1133
|
)
|
|
1240
1134
|
|
|
1241
1135
|
if not costs:
|
|
@@ -1248,5 +1142,8 @@ def calculate_costs(span_idx: Dict[str, SpanDTO]):
|
|
|
1248
1142
|
span.metrics["unit.costs.completion"] = completion_cost
|
|
1249
1143
|
span.metrics["unit.costs.total"] = total_cost
|
|
1250
1144
|
|
|
1251
|
-
except:
|
|
1252
|
-
|
|
1145
|
+
except: # pylint: disable=bare-except
|
|
1146
|
+
print("Failed to calculate costs:")
|
|
1147
|
+
print(
|
|
1148
|
+
f"model={model}, prompt_tokens={prompt_tokens}, completion_tokens={completion_tokens}"
|
|
1149
|
+
)
|
agenta/sdk/tracing/processors.py
CHANGED
|
@@ -91,9 +91,7 @@ class TraceProcessor(BatchSpanProcessor):
|
|
|
91
91
|
ret = super().force_flush(timeout_millis)
|
|
92
92
|
|
|
93
93
|
if not ret:
|
|
94
|
-
log.
|
|
95
|
-
log.error("Agenta SDK - skipping export due to timeout.")
|
|
96
|
-
log.error("--------------------------------------------")
|
|
94
|
+
log.warning("Agenta SDK - skipping export due to timeout.")
|
|
97
95
|
|
|
98
96
|
def is_ready(
|
|
99
97
|
self,
|