agenta 0.27.2a2__py3-none-any.whl → 0.27.4a0__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/client/backend/__init__.py +0 -63
- agenta/client/backend/client.py +22 -22
- agenta/client/backend/core/http_client.py +7 -15
- agenta/client/backend/observability/client.py +4 -4
- agenta/client/backend/types/__init__.py +0 -58
- agenta/client/backend/variants/client.py +16 -24
- agenta/sdk/__init__.py +0 -2
- agenta/sdk/agenta_init.py +7 -9
- agenta/sdk/decorators/routing.py +29 -5
- agenta/sdk/middleware/__init__.py +0 -0
- agenta/sdk/middleware/auth.py +136 -0
- agenta/sdk/middleware/cache.py +43 -0
- agenta/sdk/tracing/exporters.py +1 -1
- agenta/sdk/tracing/inline.py +140 -29
- agenta/sdk/tracing/processors.py +1 -1
- agenta/sdk/types.py +2 -5
- {agenta-0.27.2a2.dist-info → agenta-0.27.4a0.dist-info}/METADATA +1 -1
- {agenta-0.27.2a2.dist-info → agenta-0.27.4a0.dist-info}/RECORD +20 -51
- agenta/client/backend/observability_v_1/__init__.py +0 -5
- agenta/client/backend/observability_v_1/client.py +0 -560
- agenta/client/backend/observability_v_1/types/__init__.py +0 -6
- agenta/client/backend/observability_v_1/types/format.py +0 -5
- agenta/client/backend/observability_v_1/types/query_traces_response.py +0 -11
- agenta/client/backend/types/agenta_node_dto.py +0 -48
- agenta/client/backend/types/agenta_node_dto_nodes_value.py +0 -6
- agenta/client/backend/types/agenta_nodes_response.py +0 -30
- agenta/client/backend/types/agenta_root_dto.py +0 -30
- agenta/client/backend/types/agenta_roots_response.py +0 -30
- agenta/client/backend/types/agenta_tree_dto.py +0 -30
- agenta/client/backend/types/agenta_trees_response.py +0 -30
- agenta/client/backend/types/collect_status_response.py +0 -22
- agenta/client/backend/types/exception_dto.py +0 -26
- agenta/client/backend/types/link_dto.py +0 -24
- agenta/client/backend/types/node_dto.py +0 -24
- agenta/client/backend/types/node_type.py +0 -19
- agenta/client/backend/types/o_tel_context_dto.py +0 -22
- agenta/client/backend/types/o_tel_event_dto.py +0 -23
- agenta/client/backend/types/o_tel_extra_dto.py +0 -26
- agenta/client/backend/types/o_tel_link_dto.py +0 -23
- agenta/client/backend/types/o_tel_span_dto.py +0 -37
- agenta/client/backend/types/o_tel_span_kind.py +0 -15
- agenta/client/backend/types/o_tel_spans_response.py +0 -24
- agenta/client/backend/types/o_tel_status_code.py +0 -8
- agenta/client/backend/types/parent_dto.py +0 -21
- agenta/client/backend/types/root_dto.py +0 -21
- agenta/client/backend/types/span_dto.py +0 -54
- agenta/client/backend/types/span_dto_nodes_value.py +0 -9
- agenta/client/backend/types/status_code.py +0 -5
- agenta/client/backend/types/status_dto.py +0 -23
- agenta/client/backend/types/time_dto.py +0 -23
- agenta/client/backend/types/tree_dto.py +0 -23
- agenta/client/backend/types/tree_type.py +0 -5
- {agenta-0.27.2a2.dist-info → agenta-0.27.4a0.dist-info}/WHEEL +0 -0
- {agenta-0.27.2a2.dist-info → agenta-0.27.4a0.dist-info}/entry_points.txt +0 -0
agenta/sdk/agenta_init.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import os
|
|
2
1
|
import logging
|
|
3
2
|
import toml
|
|
3
|
+
from os import getenv
|
|
4
4
|
from typing import Optional
|
|
5
5
|
from importlib.metadata import version
|
|
6
6
|
|
|
@@ -72,13 +72,13 @@ class AgentaSingleton:
|
|
|
72
72
|
|
|
73
73
|
self.host = (
|
|
74
74
|
host
|
|
75
|
-
or
|
|
75
|
+
or getenv("AGENTA_HOST")
|
|
76
76
|
or config.get("backend_host")
|
|
77
77
|
or config.get("host")
|
|
78
78
|
or "https://cloud.agenta.ai"
|
|
79
79
|
)
|
|
80
80
|
|
|
81
|
-
self.app_id = app_id or config.get("app_id") or
|
|
81
|
+
self.app_id = app_id or config.get("app_id") or getenv("AGENTA_APP_ID")
|
|
82
82
|
# if not self.app_id:
|
|
83
83
|
# raise ValueError(
|
|
84
84
|
# "App ID must be specified. You can provide it in one of the following ways:\n"
|
|
@@ -87,9 +87,7 @@ class AgentaSingleton:
|
|
|
87
87
|
# "3. As an environment variable 'AGENTA_APP_ID'."
|
|
88
88
|
# )
|
|
89
89
|
|
|
90
|
-
self.api_key = (
|
|
91
|
-
api_key or os.environ.get("AGENTA_API_KEY") or config.get("api_key")
|
|
92
|
-
)
|
|
90
|
+
self.api_key = api_key or getenv("AGENTA_API_KEY") or config.get("api_key")
|
|
93
91
|
|
|
94
92
|
self.tracing = Tracing(
|
|
95
93
|
url=f"{self.host}/api/observability/v1/otlp/traces", # type: ignore
|
|
@@ -103,15 +101,15 @@ class AgentaSingleton:
|
|
|
103
101
|
|
|
104
102
|
self.api = AgentaApi(
|
|
105
103
|
base_url=self.host + "/api",
|
|
106
|
-
api_key=api_key if api_key else "",
|
|
104
|
+
api_key=self.api_key if self.api_key else "",
|
|
107
105
|
)
|
|
108
106
|
|
|
109
107
|
self.async_api = AsyncAgentaApi(
|
|
110
108
|
base_url=self.host + "/api",
|
|
111
|
-
api_key=api_key if api_key else "",
|
|
109
|
+
api_key=self.api_key if self.api_key else "",
|
|
112
110
|
)
|
|
113
111
|
|
|
114
|
-
self.base_id =
|
|
112
|
+
self.base_id = getenv("AGENTA_BASE_ID")
|
|
115
113
|
|
|
116
114
|
self.config = Config(
|
|
117
115
|
host=self.host,
|
agenta/sdk/decorators/routing.py
CHANGED
|
@@ -14,9 +14,10 @@ from os import environ
|
|
|
14
14
|
from fastapi.middleware.cors import CORSMiddleware
|
|
15
15
|
from fastapi import Body, FastAPI, UploadFile, HTTPException
|
|
16
16
|
|
|
17
|
+
from agenta.sdk.middleware.auth import AuthorizationMiddleware
|
|
17
18
|
from agenta.sdk.context.routing import routing_context_manager, routing_context
|
|
18
19
|
from agenta.sdk.context.tracing import tracing_context
|
|
19
|
-
from agenta.sdk.router import router
|
|
20
|
+
from agenta.sdk.router import router
|
|
20
21
|
from agenta.sdk.utils.exceptions import suppress
|
|
21
22
|
from agenta.sdk.utils.logging import log
|
|
22
23
|
from agenta.sdk.types import (
|
|
@@ -50,6 +51,9 @@ app.add_middleware(
|
|
|
50
51
|
allow_headers=["*"],
|
|
51
52
|
)
|
|
52
53
|
|
|
54
|
+
_MIDDLEWARES = True
|
|
55
|
+
|
|
56
|
+
|
|
53
57
|
app.include_router(router, prefix="")
|
|
54
58
|
|
|
55
59
|
|
|
@@ -121,6 +125,26 @@ class entrypoint:
|
|
|
121
125
|
route_path="",
|
|
122
126
|
config_schema: Optional[BaseModel] = None,
|
|
123
127
|
):
|
|
128
|
+
### --- Update Middleware --- #
|
|
129
|
+
try:
|
|
130
|
+
global _MIDDLEWARES # pylint: disable=global-statement
|
|
131
|
+
|
|
132
|
+
if _MIDDLEWARES:
|
|
133
|
+
app.add_middleware(
|
|
134
|
+
AuthorizationMiddleware,
|
|
135
|
+
host=ag.DEFAULT_AGENTA_SINGLETON_INSTANCE.host,
|
|
136
|
+
resource_id=ag.DEFAULT_AGENTA_SINGLETON_INSTANCE.app_id,
|
|
137
|
+
resource_type="application",
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
_MIDDLEWARES = False
|
|
141
|
+
|
|
142
|
+
except: # pylint: disable=bare-except
|
|
143
|
+
log.error("------------------------------------")
|
|
144
|
+
log.error("Agenta SDK - failed to secure route: %s", route_path)
|
|
145
|
+
log.error("------------------------------------")
|
|
146
|
+
### --- Update Middleware --- #
|
|
147
|
+
|
|
124
148
|
DEFAULT_PATH = "generate"
|
|
125
149
|
PLAYGROUND_PATH = "/playground"
|
|
126
150
|
RUN_PATH = "/run"
|
|
@@ -226,7 +250,7 @@ class entrypoint:
|
|
|
226
250
|
with routing_context_manager(
|
|
227
251
|
application={
|
|
228
252
|
"id": app_id,
|
|
229
|
-
"slug": kwargs
|
|
253
|
+
"slug": kwargs.get("app"),
|
|
230
254
|
},
|
|
231
255
|
variant={
|
|
232
256
|
"slug": kwargs.get("config"),
|
|
@@ -330,9 +354,9 @@ class entrypoint:
|
|
|
330
354
|
*args,
|
|
331
355
|
**func_params,
|
|
332
356
|
):
|
|
333
|
-
log.info(
|
|
357
|
+
log.info("---------------------------")
|
|
334
358
|
log.info(f"Agenta SDK - running route: {repr(self.route_path or '/')}")
|
|
335
|
-
log.info(
|
|
359
|
+
log.info("---------------------------")
|
|
336
360
|
|
|
337
361
|
tracing_context.set(routing_context.get())
|
|
338
362
|
|
|
@@ -362,7 +386,7 @@ class entrypoint:
|
|
|
362
386
|
log.info(f"Agenta SDK - exiting with success: 200")
|
|
363
387
|
log.info(f"----------------------------------")
|
|
364
388
|
|
|
365
|
-
return BaseResponse(data=data,
|
|
389
|
+
return BaseResponse(data=data, trace=trace)
|
|
366
390
|
|
|
367
391
|
def handle_failure(self, error: Exception):
|
|
368
392
|
log.error("--------------------------------------------------")
|
|
File without changes
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
from typing import Callable, Optional
|
|
2
|
+
from os import environ
|
|
3
|
+
from uuid import UUID
|
|
4
|
+
from json import dumps
|
|
5
|
+
from traceback import format_exc
|
|
6
|
+
|
|
7
|
+
import httpx
|
|
8
|
+
from starlette.middleware.base import BaseHTTPMiddleware
|
|
9
|
+
from fastapi import FastAPI, Request, Response
|
|
10
|
+
|
|
11
|
+
from agenta.sdk.utils.logging import log
|
|
12
|
+
from agenta.sdk.middleware.cache import TTLLRUCache
|
|
13
|
+
|
|
14
|
+
AGENTA_SDK_AUTH_CACHE_CAPACITY = environ.get(
|
|
15
|
+
"AGENTA_SDK_AUTH_CACHE_CAPACITY",
|
|
16
|
+
512,
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
AGENTA_SDK_AUTH_CACHE_TTL = environ.get(
|
|
20
|
+
"AGENTA_SDK_AUTH_CACHE_TTL",
|
|
21
|
+
15 * 60, # 15 minutes
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
AGENTA_UNAUTHORIZED_EXECUTION_ALLOWED = str(
|
|
25
|
+
environ.get("AGENTA_UNAUTHORIZED_EXECUTION_ALLOWED", False)
|
|
26
|
+
).lower() in ("true", "1", "t")
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class Deny(Response):
|
|
30
|
+
def __init__(self) -> None:
|
|
31
|
+
super().__init__(status_code=401, content="Unauthorized")
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
cache = TTLLRUCache(
|
|
35
|
+
capacity=AGENTA_SDK_AUTH_CACHE_CAPACITY,
|
|
36
|
+
ttl=AGENTA_SDK_AUTH_CACHE_TTL,
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class AuthorizationMiddleware(BaseHTTPMiddleware):
|
|
41
|
+
def __init__(
|
|
42
|
+
self,
|
|
43
|
+
app: FastAPI,
|
|
44
|
+
host: str,
|
|
45
|
+
resource_id: UUID,
|
|
46
|
+
resource_type: str,
|
|
47
|
+
):
|
|
48
|
+
super().__init__(app)
|
|
49
|
+
|
|
50
|
+
self.host = host
|
|
51
|
+
self.resource_id = resource_id
|
|
52
|
+
self.resource_type = resource_type
|
|
53
|
+
|
|
54
|
+
async def dispatch(
|
|
55
|
+
self,
|
|
56
|
+
request: Request,
|
|
57
|
+
call_next: Callable,
|
|
58
|
+
project_id: Optional[UUID] = None,
|
|
59
|
+
):
|
|
60
|
+
if AGENTA_UNAUTHORIZED_EXECUTION_ALLOWED:
|
|
61
|
+
return await call_next(request)
|
|
62
|
+
|
|
63
|
+
try:
|
|
64
|
+
authorization = (
|
|
65
|
+
request.headers.get("Authorization")
|
|
66
|
+
or request.headers.get("authorization")
|
|
67
|
+
or None
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
headers = {"Authorization": authorization} if authorization else None
|
|
71
|
+
|
|
72
|
+
cookies = {"sAccessToken": request.cookies.get("sAccessToken")}
|
|
73
|
+
|
|
74
|
+
params = {
|
|
75
|
+
"action": "run_service",
|
|
76
|
+
"resource_type": self.resource_type,
|
|
77
|
+
"resource_id": self.resource_id,
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if project_id:
|
|
81
|
+
params["project_id"] = project_id
|
|
82
|
+
|
|
83
|
+
_hash = dumps(
|
|
84
|
+
{
|
|
85
|
+
"headers": headers,
|
|
86
|
+
"cookies": cookies,
|
|
87
|
+
"params": params,
|
|
88
|
+
},
|
|
89
|
+
sort_keys=True,
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
cached_policy = cache.get(_hash)
|
|
93
|
+
|
|
94
|
+
if not cached_policy:
|
|
95
|
+
async with httpx.AsyncClient() as client:
|
|
96
|
+
response = await client.get(
|
|
97
|
+
f"{self.host}/api/permissions/verify",
|
|
98
|
+
headers=headers,
|
|
99
|
+
cookies=cookies,
|
|
100
|
+
params=params,
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
if response.status_code != 200:
|
|
104
|
+
cache.put(_hash, {"effect": "deny"})
|
|
105
|
+
return Deny()
|
|
106
|
+
|
|
107
|
+
auth = response.json()
|
|
108
|
+
|
|
109
|
+
if auth.get("effect") != "allow":
|
|
110
|
+
cache.put(_hash, {"effect": "deny"})
|
|
111
|
+
return Deny()
|
|
112
|
+
|
|
113
|
+
cached_policy = {
|
|
114
|
+
"effect": "allow",
|
|
115
|
+
"credentials": auth.get("credentials"),
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
cache.put(_hash, cached_policy)
|
|
119
|
+
|
|
120
|
+
if cached_policy.get("effect") == "deny":
|
|
121
|
+
return Deny()
|
|
122
|
+
|
|
123
|
+
request.state.credentials = cached_policy.get("credentials")
|
|
124
|
+
|
|
125
|
+
print(f"credentials: {request.state.credentials}")
|
|
126
|
+
|
|
127
|
+
return await call_next(request)
|
|
128
|
+
|
|
129
|
+
except: # pylint: disable=bare-except
|
|
130
|
+
log.error("------------------------------------------------------")
|
|
131
|
+
log.error("Agenta SDK - handling auth middleware exception below:")
|
|
132
|
+
log.error("------------------------------------------------------")
|
|
133
|
+
log.error(format_exc().strip("\n"))
|
|
134
|
+
log.error("------------------------------------------------------")
|
|
135
|
+
|
|
136
|
+
return Deny()
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
from time import time
|
|
2
|
+
from collections import OrderedDict
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class TTLLRUCache:
|
|
6
|
+
def __init__(self, capacity: int, ttl: int):
|
|
7
|
+
self.cache = OrderedDict()
|
|
8
|
+
self.capacity = capacity
|
|
9
|
+
self.ttl = ttl
|
|
10
|
+
|
|
11
|
+
def get(self, key):
|
|
12
|
+
# CACHE
|
|
13
|
+
if key not in self.cache:
|
|
14
|
+
return None
|
|
15
|
+
|
|
16
|
+
value, expiry = self.cache[key]
|
|
17
|
+
# -----
|
|
18
|
+
|
|
19
|
+
# TTL
|
|
20
|
+
if time() > expiry:
|
|
21
|
+
del self.cache[key]
|
|
22
|
+
|
|
23
|
+
return None
|
|
24
|
+
# ---
|
|
25
|
+
|
|
26
|
+
# LRU
|
|
27
|
+
self.cache.move_to_end(key)
|
|
28
|
+
# ---
|
|
29
|
+
|
|
30
|
+
return value
|
|
31
|
+
|
|
32
|
+
def put(self, key, value):
|
|
33
|
+
# CACHE
|
|
34
|
+
if key in self.cache:
|
|
35
|
+
del self.cache[key]
|
|
36
|
+
# CACHE & LRU
|
|
37
|
+
elif len(self.cache) >= self.capacity:
|
|
38
|
+
self.cache.popitem(last=False)
|
|
39
|
+
# -----------
|
|
40
|
+
|
|
41
|
+
# TTL
|
|
42
|
+
self.cache[key] = (value, time() + self.ttl)
|
|
43
|
+
# ---
|
agenta/sdk/tracing/exporters.py
CHANGED
|
@@ -58,7 +58,7 @@ class InlineTraceExporter(SpanExporter):
|
|
|
58
58
|
return trace
|
|
59
59
|
|
|
60
60
|
|
|
61
|
-
OTLPSpanExporter._MAX_RETRY_TIMEOUT = 2
|
|
61
|
+
OTLPSpanExporter._MAX_RETRY_TIMEOUT = 2 # pylint: disable=protected-access
|
|
62
62
|
|
|
63
63
|
ConsoleExporter = ConsoleSpanExporter
|
|
64
64
|
InlineExporter = InlineTraceExporter
|
agenta/sdk/tracing/inline.py
CHANGED
|
@@ -903,9 +903,9 @@ def parse_to_agenta_span_dto(
|
|
|
903
903
|
if span_dto.data:
|
|
904
904
|
span_dto.data = _unmarshal_attributes(span_dto.data)
|
|
905
905
|
|
|
906
|
-
if "outputs" in span_dto.data:
|
|
907
|
-
|
|
908
|
-
|
|
906
|
+
# if "outputs" in span_dto.data:
|
|
907
|
+
# if "__default__" in span_dto.data["outputs"]:
|
|
908
|
+
# span_dto.data["outputs"] = span_dto.data["outputs"]["__default__"]
|
|
909
909
|
|
|
910
910
|
# METRICS
|
|
911
911
|
if span_dto.metrics:
|
|
@@ -934,17 +934,6 @@ def parse_to_agenta_span_dto(
|
|
|
934
934
|
else:
|
|
935
935
|
parse_to_agenta_span_dto(v)
|
|
936
936
|
|
|
937
|
-
# MASK LINKS FOR NOW
|
|
938
|
-
span_dto.links = None
|
|
939
|
-
# ------------------
|
|
940
|
-
|
|
941
|
-
# MASK LIFECYCLE FOR NOW
|
|
942
|
-
# span_dto.lifecycle = None
|
|
943
|
-
if span_dto.lifecycle:
|
|
944
|
-
span_dto.lifecycle.updated_at = None
|
|
945
|
-
span_dto.lifecycle.updated_by_id = None
|
|
946
|
-
# ----------------------
|
|
947
|
-
|
|
948
937
|
return span_dto
|
|
949
938
|
|
|
950
939
|
|
|
@@ -956,8 +945,6 @@ def parse_to_agenta_span_dto(
|
|
|
956
945
|
from litellm import cost_calculator
|
|
957
946
|
from opentelemetry.sdk.trace import ReadableSpan
|
|
958
947
|
|
|
959
|
-
from agenta.sdk.types import AgentaNodeDto, AgentaNodesResponse
|
|
960
|
-
|
|
961
948
|
|
|
962
949
|
def parse_inline_trace(
|
|
963
950
|
spans: Dict[str, ReadableSpan],
|
|
@@ -1005,19 +992,51 @@ def parse_inline_trace(
|
|
|
1005
992
|
### services.observability.service.query() ###
|
|
1006
993
|
##############################################
|
|
1007
994
|
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
)
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
995
|
+
LEGACY = True
|
|
996
|
+
inline_trace = None
|
|
997
|
+
|
|
998
|
+
if LEGACY:
|
|
999
|
+
legacy_spans = [
|
|
1000
|
+
_parse_to_legacy_span(span_dto) for span_dto in span_idx.values()
|
|
1001
|
+
]
|
|
1002
|
+
|
|
1003
|
+
root_span = agenta_span_dtos[0]
|
|
1004
|
+
|
|
1005
|
+
trace_id = root_span.root.id.hex
|
|
1006
|
+
latency = root_span.time.span / 1_000_000
|
|
1007
|
+
cost = root_span.metrics.get("acc", {}).get("costs", {}).get("total", 0.0)
|
|
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
|
+
|
|
1021
1040
|
return inline_trace
|
|
1022
1041
|
|
|
1023
1042
|
|
|
@@ -1101,6 +1120,98 @@ class LlmTokens(BaseModel):
|
|
|
1101
1120
|
total_tokens: Optional[int] = 0
|
|
1102
1121
|
|
|
1103
1122
|
|
|
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
|
+
|
|
1104
1215
|
TYPES_WITH_COSTS = [
|
|
1105
1216
|
"embedding",
|
|
1106
1217
|
"query",
|
agenta/sdk/tracing/processors.py
CHANGED
agenta/sdk/types.py
CHANGED
|
@@ -4,9 +4,6 @@ from typing import Dict, List, Optional, Any, Union
|
|
|
4
4
|
|
|
5
5
|
from pydantic import ConfigDict, BaseModel, HttpUrl
|
|
6
6
|
|
|
7
|
-
from agenta.client.backend.types.agenta_node_dto import AgentaNodeDto
|
|
8
|
-
from agenta.client.backend.types.agenta_nodes_response import AgentaNodesResponse
|
|
9
|
-
|
|
10
7
|
|
|
11
8
|
@dataclass
|
|
12
9
|
class MultipleChoice:
|
|
@@ -26,9 +23,9 @@ class LLMTokenUsage(BaseModel):
|
|
|
26
23
|
|
|
27
24
|
|
|
28
25
|
class BaseResponse(BaseModel):
|
|
29
|
-
version: Optional[str] = "
|
|
26
|
+
version: Optional[str] = "2.0"
|
|
30
27
|
data: Optional[Union[str, Dict[str, Any]]]
|
|
31
|
-
|
|
28
|
+
trace: Optional[Dict[str, Any]]
|
|
32
29
|
|
|
33
30
|
|
|
34
31
|
class DictInput(dict):
|