agenta 0.26.0a0__py3-none-any.whl → 0.27.0a0__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 +6 -7
- agenta/client/backend/client.py +22 -14
- agenta/client/backend/core/http_client.py +23 -15
- agenta/sdk/__init__.py +27 -6
- agenta/sdk/agenta_init.py +73 -26
- agenta/sdk/config_manager.py +2 -2
- agenta/sdk/context/__init__.py +0 -0
- agenta/sdk/context/routing.py +25 -0
- agenta/sdk/context/tracing.py +3 -0
- agenta/sdk/decorators/__init__.py +0 -0
- agenta/sdk/decorators/{llm_entrypoint.py → routing.py} +137 -124
- agenta/sdk/decorators/tracing.py +228 -76
- agenta/sdk/litellm/__init__.py +1 -0
- agenta/sdk/litellm/litellm.py +277 -0
- agenta/sdk/router.py +0 -7
- agenta/sdk/tracing/__init__.py +1 -0
- agenta/sdk/tracing/attributes.py +181 -0
- agenta/sdk/tracing/context.py +21 -0
- agenta/sdk/tracing/conventions.py +43 -0
- agenta/sdk/tracing/exporters.py +53 -0
- agenta/sdk/tracing/inline.py +1306 -0
- agenta/sdk/tracing/processors.py +65 -0
- agenta/sdk/tracing/spans.py +124 -0
- agenta/sdk/tracing/tracing.py +174 -0
- agenta/sdk/types.py +0 -12
- agenta/sdk/utils/{helper/openai_cost.py → costs.py} +3 -0
- agenta/sdk/utils/debug.py +5 -5
- agenta/sdk/utils/exceptions.py +19 -0
- agenta/sdk/utils/globals.py +3 -5
- agenta/sdk/{tracing/logger.py → utils/logging.py} +3 -5
- agenta/sdk/utils/singleton.py +13 -0
- {agenta-0.26.0a0.dist-info → agenta-0.27.0a0.dist-info}/METADATA +5 -1
- {agenta-0.26.0a0.dist-info → agenta-0.27.0a0.dist-info}/RECORD +35 -25
- agenta/sdk/context.py +0 -41
- agenta/sdk/decorators/base.py +0 -10
- agenta/sdk/tracing/callbacks.py +0 -187
- agenta/sdk/tracing/llm_tracing.py +0 -617
- agenta/sdk/tracing/tasks_manager.py +0 -129
- agenta/sdk/tracing/tracing_context.py +0 -27
- {agenta-0.26.0a0.dist-info → agenta-0.27.0a0.dist-info}/WHEEL +0 -0
- {agenta-0.26.0a0.dist-info → agenta-0.27.0a0.dist-info}/entry_points.txt +0 -0
agenta/__init__.py
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
from .sdk.utils.preinit import PreInitObject
|
|
2
|
-
from .sdk.context import get_contexts, save_context
|
|
3
2
|
from .sdk.types import (
|
|
4
|
-
Context,
|
|
5
3
|
DictInput,
|
|
6
4
|
MultipleChoice,
|
|
7
5
|
FloatParam,
|
|
@@ -15,16 +13,17 @@ from .sdk.types import (
|
|
|
15
13
|
BinaryParam,
|
|
16
14
|
)
|
|
17
15
|
|
|
18
|
-
from .sdk.
|
|
19
|
-
from .sdk.tracing
|
|
16
|
+
from .sdk.utils.logging import log as logging
|
|
17
|
+
from .sdk.tracing import Tracing
|
|
20
18
|
from .sdk.decorators.tracing import instrument
|
|
21
|
-
from .sdk.decorators.
|
|
19
|
+
from .sdk.decorators.routing import entrypoint, app, route
|
|
22
20
|
from .sdk.agenta_init import Config, AgentaSingleton, init
|
|
23
|
-
from .sdk.utils.
|
|
21
|
+
from .sdk.utils.costs import calculate_token_usage
|
|
24
22
|
from .sdk.client import Agenta
|
|
25
|
-
from .sdk.
|
|
23
|
+
from .sdk.litellm import litellm as callbacks
|
|
26
24
|
from .sdk.config_manager import ConfigManager
|
|
27
25
|
from .sdk import assets as assets
|
|
26
|
+
from .sdk import tracer
|
|
28
27
|
|
|
29
28
|
config = PreInitObject("agenta.config", Config)
|
|
30
29
|
DEFAULT_AGENTA_SINGLETON_INSTANCE = AgentaSingleton()
|
agenta/client/backend/client.py
CHANGED
|
@@ -88,13 +88,17 @@ class AgentaApi:
|
|
|
88
88
|
self._client_wrapper = SyncClientWrapper(
|
|
89
89
|
base_url=base_url,
|
|
90
90
|
api_key=api_key,
|
|
91
|
-
httpx_client=
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
91
|
+
httpx_client=(
|
|
92
|
+
httpx_client
|
|
93
|
+
if httpx_client is not None
|
|
94
|
+
else (
|
|
95
|
+
httpx.Client(
|
|
96
|
+
timeout=_defaulted_timeout, follow_redirects=follow_redirects
|
|
97
|
+
)
|
|
98
|
+
if follow_redirects is not None
|
|
99
|
+
else httpx.Client(timeout=_defaulted_timeout)
|
|
100
|
+
)
|
|
101
|
+
),
|
|
98
102
|
timeout=_defaulted_timeout,
|
|
99
103
|
)
|
|
100
104
|
self.observability = ObservabilityClient(client_wrapper=self._client_wrapper)
|
|
@@ -1603,13 +1607,17 @@ class AsyncAgentaApi:
|
|
|
1603
1607
|
self._client_wrapper = AsyncClientWrapper(
|
|
1604
1608
|
base_url=base_url,
|
|
1605
1609
|
api_key=api_key,
|
|
1606
|
-
httpx_client=
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1610
|
+
httpx_client=(
|
|
1611
|
+
httpx_client
|
|
1612
|
+
if httpx_client is not None
|
|
1613
|
+
else (
|
|
1614
|
+
httpx.AsyncClient(
|
|
1615
|
+
timeout=_defaulted_timeout, follow_redirects=follow_redirects
|
|
1616
|
+
)
|
|
1617
|
+
if follow_redirects is not None
|
|
1618
|
+
else httpx.AsyncClient(timeout=_defaulted_timeout)
|
|
1619
|
+
)
|
|
1620
|
+
),
|
|
1613
1621
|
timeout=_defaulted_timeout,
|
|
1614
1622
|
)
|
|
1615
1623
|
self.observability = AsyncObservabilityClient(
|
|
@@ -148,9 +148,9 @@ def get_request_body(
|
|
|
148
148
|
json_body = maybe_filter_request_body(json, request_options, omit)
|
|
149
149
|
|
|
150
150
|
# If you have an empty JSON body, you should just send None
|
|
151
|
-
return (
|
|
152
|
-
|
|
153
|
-
)
|
|
151
|
+
return (json_body if json_body != {} else None), (
|
|
152
|
+
data_body if data_body != {} else None
|
|
153
|
+
)
|
|
154
154
|
|
|
155
155
|
|
|
156
156
|
class HttpClient:
|
|
@@ -246,9 +246,11 @@ class HttpClient:
|
|
|
246
246
|
json=json_body,
|
|
247
247
|
data=data_body,
|
|
248
248
|
content=content,
|
|
249
|
-
files=
|
|
250
|
-
|
|
251
|
-
|
|
249
|
+
files=(
|
|
250
|
+
convert_file_dict_to_httpx_tuples(remove_none_from_dict(files))
|
|
251
|
+
if files is not None
|
|
252
|
+
else None
|
|
253
|
+
),
|
|
252
254
|
timeout=timeout,
|
|
253
255
|
)
|
|
254
256
|
|
|
@@ -345,9 +347,11 @@ class HttpClient:
|
|
|
345
347
|
json=json_body,
|
|
346
348
|
data=data_body,
|
|
347
349
|
content=content,
|
|
348
|
-
files=
|
|
349
|
-
|
|
350
|
-
|
|
350
|
+
files=(
|
|
351
|
+
convert_file_dict_to_httpx_tuples(remove_none_from_dict(files))
|
|
352
|
+
if files is not None
|
|
353
|
+
else None
|
|
354
|
+
),
|
|
351
355
|
timeout=timeout,
|
|
352
356
|
) as stream:
|
|
353
357
|
yield stream
|
|
@@ -447,9 +451,11 @@ class AsyncHttpClient:
|
|
|
447
451
|
json=json_body,
|
|
448
452
|
data=data_body,
|
|
449
453
|
content=content,
|
|
450
|
-
files=
|
|
451
|
-
|
|
452
|
-
|
|
454
|
+
files=(
|
|
455
|
+
convert_file_dict_to_httpx_tuples(remove_none_from_dict(files))
|
|
456
|
+
if files is not None
|
|
457
|
+
else None
|
|
458
|
+
),
|
|
453
459
|
timeout=timeout,
|
|
454
460
|
)
|
|
455
461
|
|
|
@@ -545,9 +551,11 @@ class AsyncHttpClient:
|
|
|
545
551
|
json=json_body,
|
|
546
552
|
data=data_body,
|
|
547
553
|
content=content,
|
|
548
|
-
files=
|
|
549
|
-
|
|
550
|
-
|
|
554
|
+
files=(
|
|
555
|
+
convert_file_dict_to_httpx_tuples(remove_none_from_dict(files))
|
|
556
|
+
if files is not None
|
|
557
|
+
else None
|
|
558
|
+
),
|
|
551
559
|
timeout=timeout,
|
|
552
560
|
) as stream:
|
|
553
561
|
yield stream
|
agenta/sdk/__init__.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
+
from typing import Optional
|
|
2
|
+
|
|
1
3
|
from .utils.preinit import PreInitObject # always the first import!
|
|
2
|
-
from .context import get_contexts, save_context
|
|
3
4
|
from .types import (
|
|
4
|
-
Context,
|
|
5
5
|
DictInput,
|
|
6
6
|
MultipleChoice,
|
|
7
7
|
FloatParam,
|
|
@@ -15,13 +15,34 @@ from .types import (
|
|
|
15
15
|
BinaryParam,
|
|
16
16
|
)
|
|
17
17
|
|
|
18
|
-
from .tracing
|
|
18
|
+
from .tracing import Tracing, get_tracer
|
|
19
19
|
from .decorators.tracing import instrument
|
|
20
|
-
from .decorators.
|
|
21
|
-
from .agenta_init import Config, AgentaSingleton, init
|
|
22
|
-
from .utils.
|
|
20
|
+
from .decorators.routing import entrypoint, app, route
|
|
21
|
+
from .agenta_init import Config, AgentaSingleton, init as _init
|
|
22
|
+
from .utils.costs import calculate_token_usage
|
|
23
23
|
from .config_manager import ConfigManager
|
|
24
24
|
|
|
25
25
|
config = PreInitObject("agenta.config", Config)
|
|
26
26
|
DEFAULT_AGENTA_SINGLETON_INSTANCE = AgentaSingleton()
|
|
27
27
|
tracing = DEFAULT_AGENTA_SINGLETON_INSTANCE.tracing # type: ignore
|
|
28
|
+
|
|
29
|
+
tracer = get_tracer(tracing)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def init(
|
|
33
|
+
host: Optional[str] = None,
|
|
34
|
+
app_id: Optional[str] = None,
|
|
35
|
+
api_key: Optional[str] = None,
|
|
36
|
+
config_fname: Optional[str] = None,
|
|
37
|
+
):
|
|
38
|
+
global tracing
|
|
39
|
+
global tracer
|
|
40
|
+
|
|
41
|
+
_init(
|
|
42
|
+
host=host,
|
|
43
|
+
app_id=app_id,
|
|
44
|
+
api_key=api_key,
|
|
45
|
+
config_fname=config_fname,
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
tracer = get_tracer(tracing)
|
agenta/sdk/agenta_init.py
CHANGED
|
@@ -2,10 +2,12 @@ import os
|
|
|
2
2
|
import logging
|
|
3
3
|
import toml
|
|
4
4
|
from typing import Optional
|
|
5
|
+
from importlib.metadata import version
|
|
5
6
|
|
|
7
|
+
from agenta.sdk.utils.logging import log
|
|
6
8
|
from agenta.sdk.utils.globals import set_global
|
|
7
9
|
from agenta.client.backend.client import AgentaApi
|
|
8
|
-
from agenta.sdk.tracing
|
|
10
|
+
from agenta.sdk.tracing import Tracing
|
|
9
11
|
from agenta.client.exceptions import APIRequestError
|
|
10
12
|
|
|
11
13
|
|
|
@@ -17,9 +19,8 @@ class AgentaSingleton:
|
|
|
17
19
|
"""Singleton class to save all the "global variables" for the sdk."""
|
|
18
20
|
|
|
19
21
|
_instance = None
|
|
20
|
-
setup = None
|
|
21
22
|
config = None
|
|
22
|
-
tracing
|
|
23
|
+
tracing = None
|
|
23
24
|
|
|
24
25
|
def __new__(cls):
|
|
25
26
|
if not cls._instance:
|
|
@@ -28,11 +29,18 @@ class AgentaSingleton:
|
|
|
28
29
|
|
|
29
30
|
def init(
|
|
30
31
|
self,
|
|
31
|
-
|
|
32
|
+
*,
|
|
32
33
|
host: Optional[str] = None,
|
|
34
|
+
project_id: Optional[str] = None,
|
|
33
35
|
api_key: Optional[str] = None,
|
|
34
36
|
config_fname: Optional[str] = None,
|
|
37
|
+
#
|
|
38
|
+
app_id: Optional[str] = None,
|
|
35
39
|
) -> None:
|
|
40
|
+
log.info(f"\n--------------------------------")
|
|
41
|
+
log.info(f"Using Agenta Python SDK version: {version('agenta')}")
|
|
42
|
+
log.info(f"--------------------------------\n")
|
|
43
|
+
|
|
36
44
|
"""Main function to initialize the singleton.
|
|
37
45
|
|
|
38
46
|
Initializes the singleton with the given `app_id`, `host`, and `api_key`. The order of precedence for these variables is:
|
|
@@ -54,20 +62,20 @@ class AgentaSingleton:
|
|
|
54
62
|
Raises:
|
|
55
63
|
ValueError: If `app_id` is not specified either as an argument, in the config file, or in the environment variables.
|
|
56
64
|
"""
|
|
65
|
+
|
|
57
66
|
config = {}
|
|
58
67
|
if config_fname:
|
|
59
68
|
config = toml.load(config_fname)
|
|
60
69
|
|
|
61
|
-
self.app_id = app_id or config.get("app_id") or os.environ.get("AGENTA_APP_ID")
|
|
62
70
|
self.host = (
|
|
63
71
|
host
|
|
72
|
+
or os.environ.get("AGENTA_HOST")
|
|
64
73
|
or config.get("backend_host")
|
|
65
|
-
or
|
|
66
|
-
|
|
67
|
-
self.api_key = (
|
|
68
|
-
api_key or config.get("api_key") or os.environ.get("AGENTA_API_KEY")
|
|
74
|
+
or config.get("host")
|
|
75
|
+
or "https://cloud.agenta.ai"
|
|
69
76
|
)
|
|
70
77
|
|
|
78
|
+
self.app_id = app_id or config.get("app_id") or os.environ.get("AGENTA_APP_ID")
|
|
71
79
|
if not self.app_id:
|
|
72
80
|
raise ValueError(
|
|
73
81
|
"App ID must be specified. You can provide it in one of the following ways:\n"
|
|
@@ -75,26 +83,60 @@ class AgentaSingleton:
|
|
|
75
83
|
"2. In the configuration file specified by config_fname.\n"
|
|
76
84
|
"3. As an environment variable 'AGENTA_APP_ID'."
|
|
77
85
|
)
|
|
86
|
+
|
|
87
|
+
self.project_id = (
|
|
88
|
+
project_id
|
|
89
|
+
or os.environ.get("AGENTA_PROJECT_ID")
|
|
90
|
+
or config.get("project_id")
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
self.api_key = (
|
|
94
|
+
api_key or os.environ.get("AGENTA_API_KEY") or config.get("api_key")
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
self.tracing = Tracing(
|
|
98
|
+
url=f"{self.host}/api/observability/v1/traces", # type: ignore
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
self.tracing.configure(
|
|
102
|
+
project_id=self.project_id,
|
|
103
|
+
api_key=self.api_key,
|
|
104
|
+
# DEPRECATED
|
|
105
|
+
app_id=self.app_id,
|
|
106
|
+
)
|
|
107
|
+
|
|
78
108
|
self.base_id = os.environ.get("AGENTA_BASE_ID")
|
|
79
|
-
if self.base_id is None:
|
|
80
|
-
print(
|
|
81
|
-
"Warning: Your configuration will not be saved permanently since base_id is not provided."
|
|
82
|
-
)
|
|
83
109
|
|
|
84
|
-
self.config = Config(
|
|
110
|
+
self.config = Config(
|
|
111
|
+
host=self.host,
|
|
112
|
+
base_id=self.base_id,
|
|
113
|
+
api_key=self.api_key,
|
|
114
|
+
)
|
|
85
115
|
|
|
86
116
|
|
|
87
117
|
class Config:
|
|
88
|
-
def __init__(
|
|
89
|
-
self
|
|
118
|
+
def __init__(
|
|
119
|
+
self,
|
|
120
|
+
host: str,
|
|
121
|
+
base_id: Optional[str] = None,
|
|
122
|
+
api_key: Optional[str] = "",
|
|
123
|
+
):
|
|
90
124
|
self.host = host
|
|
91
125
|
|
|
126
|
+
self.base_id = base_id
|
|
127
|
+
|
|
128
|
+
if self.base_id is None:
|
|
129
|
+
print(
|
|
130
|
+
"Warning: Your configuration will not be saved permanently since base_id is not provided.\n"
|
|
131
|
+
)
|
|
132
|
+
|
|
92
133
|
if base_id is None or host is None:
|
|
93
134
|
self.persist = False
|
|
94
135
|
else:
|
|
95
136
|
self.persist = True
|
|
96
137
|
self.client = AgentaApi(
|
|
97
|
-
base_url=self.host + "/api",
|
|
138
|
+
base_url=self.host + "/api",
|
|
139
|
+
api_key=api_key if api_key else "",
|
|
98
140
|
)
|
|
99
141
|
|
|
100
142
|
def register_default(self, overwrite=False, **kwargs):
|
|
@@ -208,11 +250,12 @@ class Config:
|
|
|
208
250
|
|
|
209
251
|
|
|
210
252
|
def init(
|
|
211
|
-
app_id: Optional[str] = None,
|
|
212
253
|
host: Optional[str] = None,
|
|
254
|
+
project_id: Optional[str] = None,
|
|
213
255
|
api_key: Optional[str] = None,
|
|
214
256
|
config_fname: Optional[str] = None,
|
|
215
|
-
|
|
257
|
+
# DEPRECATED
|
|
258
|
+
app_id: Optional[str] = None,
|
|
216
259
|
):
|
|
217
260
|
"""Main function to initialize the agenta sdk.
|
|
218
261
|
|
|
@@ -238,12 +281,16 @@ def init(
|
|
|
238
281
|
|
|
239
282
|
singleton = AgentaSingleton()
|
|
240
283
|
|
|
241
|
-
singleton.init(
|
|
284
|
+
singleton.init(
|
|
285
|
+
host=host,
|
|
286
|
+
project_id=project_id,
|
|
287
|
+
api_key=api_key,
|
|
288
|
+
config_fname=config_fname,
|
|
289
|
+
# DEPRECATED
|
|
290
|
+
app_id=app_id,
|
|
291
|
+
)
|
|
242
292
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
api_key=singleton.api_key,
|
|
247
|
-
max_workers=max_workers,
|
|
293
|
+
set_global(
|
|
294
|
+
config=singleton.config,
|
|
295
|
+
tracing=singleton.tracing,
|
|
248
296
|
)
|
|
249
|
-
set_global(setup=singleton.setup, config=singleton.config, tracing=tracing)
|
agenta/sdk/config_manager.py
CHANGED
|
@@ -7,7 +7,7 @@ import yaml
|
|
|
7
7
|
from pydantic import BaseModel, ValidationError
|
|
8
8
|
|
|
9
9
|
from agenta.client.backend.client import AgentaApi
|
|
10
|
-
from agenta.sdk.
|
|
10
|
+
from agenta.sdk.context.routing import routing_context
|
|
11
11
|
|
|
12
12
|
from . import AgentaSingleton
|
|
13
13
|
|
|
@@ -47,7 +47,7 @@ class ConfigManager:
|
|
|
47
47
|
3. 'variant'
|
|
48
48
|
Only one of these should be provided.
|
|
49
49
|
"""
|
|
50
|
-
context =
|
|
50
|
+
context = routing_context.get()
|
|
51
51
|
if ("config" in context and context["config"]) and (
|
|
52
52
|
("environment" in context and context["environment"])
|
|
53
53
|
or ("variant" in context and context["variant"])
|
|
File without changes
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
from contextlib import contextmanager
|
|
2
|
+
from contextvars import ContextVar
|
|
3
|
+
from typing import Any, Dict, Optional
|
|
4
|
+
|
|
5
|
+
routing_context = ContextVar("routing_context", default={})
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@contextmanager
|
|
9
|
+
def routing_context_manager(
|
|
10
|
+
config: Optional[Dict[str, Any]] = None,
|
|
11
|
+
environment: Optional[str] = None,
|
|
12
|
+
version: Optional[str] = None,
|
|
13
|
+
variant: Optional[str] = None,
|
|
14
|
+
):
|
|
15
|
+
context = {
|
|
16
|
+
"config": config,
|
|
17
|
+
"environment": environment,
|
|
18
|
+
"version": version,
|
|
19
|
+
"variant": variant,
|
|
20
|
+
}
|
|
21
|
+
token = routing_context.set(context)
|
|
22
|
+
try:
|
|
23
|
+
yield
|
|
24
|
+
finally:
|
|
25
|
+
routing_context.reset(token)
|
|
File without changes
|