agenta 0.72.4__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/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 +82 -41
- agenta/sdk/engines/tracing/inline.py +8 -1
- 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/vault.py +33 -18
- agenta/sdk/middlewares/running/vault.py +33 -17
- agenta/sdk/router.py +30 -5
- agenta/sdk/tracing/inline.py +8 -1
- agenta/sdk/types.py +13 -19
- 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.72.4.dist-info → agenta-0.75.0.dist-info}/METADATA +4 -8
- {agenta-0.72.4.dist-info → agenta-0.75.0.dist-info}/RECORD +36 -36
- agenta/config.py +0 -25
- agenta/config.toml +0 -4
- {agenta-0.72.4.dist-info → agenta-0.75.0.dist-info}/WHEEL +0 -0
agenta/__init__.py
CHANGED
|
@@ -8,7 +8,7 @@ from .sdk import assets as assets
|
|
|
8
8
|
# evaluations
|
|
9
9
|
from .sdk import testsets as testsets
|
|
10
10
|
from .sdk import tracer
|
|
11
|
-
from .sdk.agenta_init import AgentaSingleton
|
|
11
|
+
from .sdk.agenta_init import AgentaSingleton
|
|
12
12
|
from .sdk.agenta_init import init as _init
|
|
13
13
|
from .sdk.context.running import workflow_mode_enabled
|
|
14
14
|
from .sdk.decorators.running import (
|
|
@@ -18,7 +18,6 @@ from .sdk.decorators.running import (
|
|
|
18
18
|
)
|
|
19
19
|
from .sdk.decorators.serving import app, route
|
|
20
20
|
from .sdk.decorators.tracing import instrument
|
|
21
|
-
from .sdk.litellm import litellm as callbacks
|
|
22
21
|
from .sdk.managers.apps import AppManager
|
|
23
22
|
from .sdk.managers.config import ConfigManager
|
|
24
23
|
from .sdk.managers.deployment import DeploymentManager
|
|
@@ -46,7 +45,6 @@ from .sdk.utils.costs import calculate_token_usage
|
|
|
46
45
|
from .sdk.utils.logging import get_module_logger
|
|
47
46
|
from .sdk.utils.preinit import PreInitObject
|
|
48
47
|
|
|
49
|
-
config = PreInitObject("agenta.config", Config)
|
|
50
48
|
DEFAULT_AGENTA_SINGLETON_INSTANCE = AgentaSingleton()
|
|
51
49
|
|
|
52
50
|
types = client_types
|
|
@@ -58,6 +56,14 @@ tracing = DEFAULT_AGENTA_SINGLETON_INSTANCE.tracing # type: ignore
|
|
|
58
56
|
tracer = get_tracer(tracing)
|
|
59
57
|
|
|
60
58
|
|
|
59
|
+
def __getattr__(name: str):
|
|
60
|
+
if name == "callbacks":
|
|
61
|
+
from .sdk.litellm import litellm as callbacks
|
|
62
|
+
|
|
63
|
+
return callbacks
|
|
64
|
+
raise AttributeError(f"module '{__name__}' has no attribute '{name}'")
|
|
65
|
+
|
|
66
|
+
|
|
61
67
|
def init(
|
|
62
68
|
host: Optional[str] = None,
|
|
63
69
|
api_url: Optional[str] = None,
|
agenta/sdk/__init__.py
CHANGED
|
@@ -73,7 +73,7 @@ from agenta.sdk.decorators.running import (
|
|
|
73
73
|
)
|
|
74
74
|
from agenta.sdk.decorators.serving import route, app
|
|
75
75
|
from .tracing.conventions import Reference
|
|
76
|
-
from .agenta_init import
|
|
76
|
+
from .agenta_init import AgentaSingleton, init as _init
|
|
77
77
|
from .utils.costs import calculate_token_usage
|
|
78
78
|
from .managers.apps import AppManager
|
|
79
79
|
from .managers.vault import VaultManager
|
|
@@ -83,9 +83,7 @@ from .managers.variant import VariantManager
|
|
|
83
83
|
from .managers.deployment import DeploymentManager
|
|
84
84
|
from .managers import testsets as testsets
|
|
85
85
|
|
|
86
|
-
|
|
87
|
-
config = PreInitObject("agenta.config", Config)
|
|
88
|
-
DEFAULT_AGENTA_SINGLETON_INSTANCE = AgentaSingleton()
|
|
86
|
+
DEFAULT_AGENTA_SINGLETON_INSTANCE: AgentaSingleton = AgentaSingleton()
|
|
89
87
|
|
|
90
88
|
types = client_types
|
|
91
89
|
|
agenta/sdk/agenta_init.py
CHANGED
|
@@ -2,8 +2,7 @@ from importlib.metadata import version
|
|
|
2
2
|
from os import getenv
|
|
3
3
|
from typing import Any, Callable, Optional
|
|
4
4
|
|
|
5
|
-
import
|
|
6
|
-
import toml
|
|
5
|
+
import httpx
|
|
7
6
|
from agenta.client.client import AgentaApi, AsyncAgentaApi
|
|
8
7
|
from agenta.sdk.contexts.routing import RoutingContext
|
|
9
8
|
from agenta.sdk.tracing import Tracing
|
|
@@ -86,22 +85,13 @@ class AgentaSingleton:
|
|
|
86
85
|
|
|
87
86
|
log.info("Agenta - SDK ver: %s", version("agenta"))
|
|
88
87
|
|
|
89
|
-
|
|
90
|
-
if config_fname:
|
|
91
|
-
config = toml.load(config_fname)
|
|
92
|
-
|
|
93
|
-
_host = (
|
|
94
|
-
host
|
|
95
|
-
or getenv("AGENTA_HOST")
|
|
96
|
-
or config.get("host")
|
|
97
|
-
or "https://cloud.agenta.ai"
|
|
98
|
-
)
|
|
88
|
+
_host = host or getenv("AGENTA_HOST") or "https://cloud.agenta.ai"
|
|
99
89
|
|
|
100
90
|
_api_url = (
|
|
101
91
|
api_url
|
|
92
|
+
#
|
|
102
93
|
or getenv("AGENTA_API_INTERNAL_URL")
|
|
103
94
|
or getenv("AGENTA_API_URL")
|
|
104
|
-
or config.get("api_url")
|
|
105
95
|
or None # NO FALLBACK
|
|
106
96
|
)
|
|
107
97
|
|
|
@@ -127,29 +117,29 @@ class AgentaSingleton:
|
|
|
127
117
|
|
|
128
118
|
self.api_key = (
|
|
129
119
|
api_key
|
|
120
|
+
#
|
|
130
121
|
or getenv("AGENTA_API_KEY")
|
|
131
|
-
or config.get("api_key")
|
|
132
122
|
or None # NO FALLBACK
|
|
133
123
|
)
|
|
134
124
|
|
|
135
125
|
if self.api_key is None:
|
|
136
|
-
log.
|
|
137
|
-
"API key is required. Please set AGENTA_API_KEY environment variable or pass api_key parameter in ag.init()."
|
|
126
|
+
log.warning(
|
|
127
|
+
"API key is required (in most cases). Please set AGENTA_API_KEY environment variable or pass api_key parameter in ag.init()."
|
|
138
128
|
)
|
|
139
129
|
|
|
140
130
|
log.info("Agenta - API URL: %s", self.api_url)
|
|
141
131
|
|
|
142
132
|
self.scope_type = (
|
|
143
133
|
scope_type
|
|
134
|
+
#
|
|
144
135
|
or getenv("AGENTA_SCOPE_TYPE")
|
|
145
|
-
or config.get("scope_type")
|
|
146
136
|
or None # NO FALLBACK
|
|
147
137
|
)
|
|
148
138
|
|
|
149
139
|
self.scope_id = (
|
|
150
140
|
scope_id
|
|
141
|
+
#
|
|
151
142
|
or getenv("AGENTA_SCOPE_ID")
|
|
152
|
-
or config.get("scope_id")
|
|
153
143
|
or None # NO FALLBACK
|
|
154
144
|
)
|
|
155
145
|
|
|
@@ -173,11 +163,6 @@ class AgentaSingleton:
|
|
|
173
163
|
api_key=self.api_key if self.api_key else "",
|
|
174
164
|
)
|
|
175
165
|
|
|
176
|
-
self.config = Config(
|
|
177
|
-
host=self.host,
|
|
178
|
-
api_key=self.api_key,
|
|
179
|
-
)
|
|
180
|
-
|
|
181
166
|
# Reset cached scope info on re-init
|
|
182
167
|
self.organization_id = None
|
|
183
168
|
self.workspace_id = None
|
|
@@ -190,21 +175,21 @@ class AgentaSingleton:
|
|
|
190
175
|
and self.workspace_id is not None
|
|
191
176
|
and self.project_id is not None
|
|
192
177
|
):
|
|
193
|
-
return
|
|
178
|
+
return None
|
|
194
179
|
|
|
195
180
|
if self.api_url is None or self.api_key is None:
|
|
196
181
|
log.error("API URL or API key is not set. Please call ag.init() first.")
|
|
197
|
-
return
|
|
182
|
+
return None
|
|
198
183
|
|
|
199
184
|
try:
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
185
|
+
with httpx.Client() as client:
|
|
186
|
+
response = client.get(
|
|
187
|
+
f"{self.api_url}/projects/current",
|
|
188
|
+
headers={"Authorization": f"ApiKey {self.api_key}"},
|
|
189
|
+
timeout=10,
|
|
190
|
+
)
|
|
191
|
+
response.raise_for_status()
|
|
192
|
+
project_info = response.json()
|
|
208
193
|
|
|
209
194
|
if not project_info:
|
|
210
195
|
log.error(
|
|
@@ -226,7 +211,7 @@ class AgentaSingleton:
|
|
|
226
211
|
|
|
227
212
|
except Exception as e:
|
|
228
213
|
log.error(f"Failed to fetch scope information: {e}")
|
|
229
|
-
return
|
|
214
|
+
return None
|
|
230
215
|
|
|
231
216
|
if self.organization_id and self.workspace_id and self.project_id:
|
|
232
217
|
return (
|
|
@@ -238,50 +223,16 @@ class AgentaSingleton:
|
|
|
238
223
|
return None
|
|
239
224
|
|
|
240
225
|
|
|
241
|
-
class Config:
|
|
242
|
-
def __init__(
|
|
243
|
-
self,
|
|
244
|
-
**kwargs,
|
|
245
|
-
):
|
|
246
|
-
self.default_parameters = {**kwargs}
|
|
247
|
-
|
|
248
|
-
def set_default(self, **kwargs):
|
|
249
|
-
self.default_parameters.update(kwargs)
|
|
250
|
-
|
|
251
|
-
def get_default(self):
|
|
252
|
-
return self.default_parameters
|
|
253
|
-
|
|
254
|
-
def __getattr__(self, key):
|
|
255
|
-
context = RoutingContext.get()
|
|
256
|
-
|
|
257
|
-
parameters = context.parameters
|
|
258
|
-
|
|
259
|
-
if not parameters:
|
|
260
|
-
return None
|
|
261
|
-
|
|
262
|
-
if key in parameters:
|
|
263
|
-
value = parameters[key]
|
|
264
|
-
|
|
265
|
-
if isinstance(value, dict):
|
|
266
|
-
nested_config = Config()
|
|
267
|
-
nested_config.set_default(**value)
|
|
268
|
-
|
|
269
|
-
return nested_config
|
|
270
|
-
|
|
271
|
-
return value
|
|
272
|
-
|
|
273
|
-
return None
|
|
274
|
-
|
|
275
|
-
|
|
276
226
|
def init(
|
|
277
227
|
host: Optional[str] = None,
|
|
278
228
|
api_url: Optional[str] = None,
|
|
279
229
|
api_key: Optional[str] = None,
|
|
280
|
-
config_fname: Optional[str] = None,
|
|
281
230
|
redact: Optional[Callable[..., Any]] = None,
|
|
282
231
|
redact_on_error: Optional[bool] = True,
|
|
283
232
|
scope_type: Optional[str] = None,
|
|
284
233
|
scope_id: Optional[str] = None,
|
|
234
|
+
# DEPRECATED
|
|
235
|
+
config_fname: Optional[str] = None,
|
|
285
236
|
):
|
|
286
237
|
"""Main function to initialize the agenta sdk.
|
|
287
238
|
|
|
@@ -306,14 +257,10 @@ def init(
|
|
|
306
257
|
host=host,
|
|
307
258
|
api_url=api_url,
|
|
308
259
|
api_key=api_key,
|
|
309
|
-
config_fname=config_fname,
|
|
310
260
|
redact=redact,
|
|
311
261
|
redact_on_error=redact_on_error,
|
|
312
262
|
scope_type=scope_type,
|
|
313
263
|
scope_id=scope_id,
|
|
314
264
|
)
|
|
315
265
|
|
|
316
|
-
set_global(
|
|
317
|
-
config=singleton.config,
|
|
318
|
-
tracing=singleton.tracing,
|
|
319
|
-
)
|
|
266
|
+
set_global(tracing=singleton.tracing)
|
agenta/sdk/context/serving.py
CHANGED
|
@@ -9,6 +9,8 @@ from pydantic import BaseModel
|
|
|
9
9
|
class RoutingContext(BaseModel):
|
|
10
10
|
parameters: Optional[Dict[str, Any]] = None
|
|
11
11
|
secrets: Optional[List[Any]] = None
|
|
12
|
+
local_secrets: Optional[List[Any]] = None
|
|
13
|
+
vault_secrets: Optional[List[Any]] = None
|
|
12
14
|
mock: Optional[str] = None
|
|
13
15
|
|
|
14
16
|
@classmethod
|
agenta/sdk/contexts/routing.py
CHANGED
|
@@ -8,6 +8,8 @@ from pydantic import BaseModel
|
|
|
8
8
|
class RoutingContext(BaseModel):
|
|
9
9
|
parameters: Optional[dict] = None
|
|
10
10
|
secrets: Optional[list] = None
|
|
11
|
+
local_secrets: Optional[list] = None
|
|
12
|
+
vault_secrets: Optional[list] = None
|
|
11
13
|
mock: Optional[str] = None
|
|
12
14
|
|
|
13
15
|
@classmethod
|
agenta/sdk/contexts/running.py
CHANGED
|
@@ -2,7 +2,6 @@ from typing import Optional, Union, Callable
|
|
|
2
2
|
from contextvars import Token, ContextVar
|
|
3
3
|
from contextlib import contextmanager
|
|
4
4
|
|
|
5
|
-
|
|
6
5
|
from pydantic import BaseModel
|
|
7
6
|
|
|
8
7
|
from agenta.sdk.models.workflows import (
|
|
@@ -24,8 +23,10 @@ class RunningContext(BaseModel):
|
|
|
24
23
|
parameters: Optional[dict] = None
|
|
25
24
|
schemas: Optional[dict] = None
|
|
26
25
|
|
|
27
|
-
secrets: Optional[list] = None
|
|
28
26
|
credentials: Optional[str] = None
|
|
27
|
+
secrets: Optional[list] = None
|
|
28
|
+
local_secrets: Optional[list] = None
|
|
29
|
+
vault_secrets: Optional[list] = None
|
|
29
30
|
|
|
30
31
|
handler: Optional[Callable] = None
|
|
31
32
|
|
agenta/sdk/decorators/running.py
CHANGED
|
@@ -321,10 +321,14 @@ class workflow:
|
|
|
321
321
|
_tags = {**(self.tags or {}), **(request.tags or {})}
|
|
322
322
|
_meta = {**(self.meta or {}), **(request.meta or {})}
|
|
323
323
|
|
|
324
|
-
credentials =
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
324
|
+
credentials = (
|
|
325
|
+
credentials
|
|
326
|
+
or request.credentials
|
|
327
|
+
or (
|
|
328
|
+
f"ApiKey {ag.DEFAULT_AGENTA_SINGLETON_INSTANCE.api_key}"
|
|
329
|
+
if ag.DEFAULT_AGENTA_SINGLETON_INSTANCE.api_key
|
|
330
|
+
else None
|
|
331
|
+
)
|
|
328
332
|
)
|
|
329
333
|
|
|
330
334
|
with tracing_context_manager(TracingContext.get()):
|
agenta/sdk/decorators/serving.py
CHANGED
|
@@ -1,62 +1,81 @@
|
|
|
1
|
-
from
|
|
2
|
-
from functools import wraps
|
|
1
|
+
from typing import Type, Any, Callable, Dict, Optional, Tuple, List, TYPE_CHECKING
|
|
3
2
|
from inspect import (
|
|
4
|
-
Parameter,
|
|
5
|
-
Signature,
|
|
6
|
-
isasyncgen,
|
|
7
3
|
iscoroutinefunction,
|
|
8
4
|
isgenerator,
|
|
5
|
+
isasyncgen,
|
|
9
6
|
signature,
|
|
7
|
+
Signature,
|
|
8
|
+
Parameter,
|
|
10
9
|
)
|
|
11
|
-
from
|
|
10
|
+
from functools import wraps
|
|
12
11
|
from traceback import format_exception
|
|
13
|
-
from
|
|
12
|
+
from asyncio import sleep
|
|
14
13
|
from uuid import UUID
|
|
14
|
+
from pydantic import BaseModel, HttpUrl, ValidationError
|
|
15
|
+
from os import environ
|
|
16
|
+
|
|
17
|
+
if TYPE_CHECKING:
|
|
18
|
+
from fastapi import Request, HTTPException, Body
|
|
19
|
+
from starlette.responses import Response as StarletteResponse, StreamingResponse
|
|
20
|
+
else:
|
|
21
|
+
# Lazy imports - only loaded when @entrypoint or @route is used
|
|
22
|
+
Request = None
|
|
23
|
+
HTTPException = None
|
|
24
|
+
Body = None
|
|
15
25
|
|
|
16
|
-
import agenta as ag
|
|
17
26
|
from agenta.sdk.contexts.routing import (
|
|
18
|
-
RoutingContext,
|
|
19
27
|
routing_context_manager,
|
|
28
|
+
RoutingContext,
|
|
20
29
|
)
|
|
21
30
|
from agenta.sdk.contexts.tracing import (
|
|
22
|
-
TracingContext,
|
|
23
31
|
tracing_context_manager,
|
|
32
|
+
TracingContext,
|
|
24
33
|
)
|
|
25
|
-
from agenta.sdk.middleware.auth import AuthHTTPMiddleware
|
|
26
|
-
from agenta.sdk.middleware.config import ConfigMiddleware
|
|
27
|
-
from agenta.sdk.middleware.cors import CORSMiddleware
|
|
28
|
-
from agenta.sdk.middleware.inline import InlineMiddleware
|
|
29
|
-
from agenta.sdk.middleware.mock import MockMiddleware
|
|
30
|
-
from agenta.sdk.middleware.otel import OTelMiddleware
|
|
31
|
-
from agenta.sdk.middleware.vault import VaultMiddleware
|
|
32
34
|
from agenta.sdk.router import router
|
|
35
|
+
from agenta.sdk.utils.exceptions import suppress, display_exception
|
|
36
|
+
from agenta.sdk.utils.logging import get_module_logger
|
|
37
|
+
from agenta.sdk.utils.helpers import get_current_version
|
|
38
|
+
from agenta.sdk.utils.lazy import _load_fastapi, _load_starlette_responses
|
|
33
39
|
from agenta.sdk.types import (
|
|
34
|
-
BaseResponse,
|
|
35
40
|
MultipleChoice,
|
|
41
|
+
BaseResponse,
|
|
36
42
|
StreamResponse,
|
|
37
|
-
|
|
38
|
-
from agenta.sdk.utils.exceptions import display_exception, suppress
|
|
39
|
-
from agenta.sdk.utils.helpers import get_current_version
|
|
40
|
-
from agenta.sdk.utils.logging import get_module_logger
|
|
41
|
-
from fastapi import Body, FastAPI, HTTPException, Request
|
|
42
|
-
from pydantic import BaseModel, HttpUrl, ValidationError
|
|
43
|
-
from starlette.responses import (
|
|
44
|
-
Response as StarletteResponse,
|
|
45
|
-
)
|
|
46
|
-
from starlette.responses import (
|
|
47
|
-
StreamingResponse,
|
|
43
|
+
MCField,
|
|
48
44
|
)
|
|
49
45
|
|
|
46
|
+
import agenta as ag
|
|
47
|
+
|
|
50
48
|
log = get_module_logger(__name__)
|
|
51
49
|
|
|
52
50
|
AGENTA_RUNTIME_PREFIX = environ.get("AGENTA_RUNTIME_PREFIX", "")
|
|
53
51
|
|
|
54
|
-
app = FastAPI(
|
|
55
|
-
docs_url=f"{AGENTA_RUNTIME_PREFIX}/docs", # Swagger UI
|
|
56
|
-
openapi_url=f"{AGENTA_RUNTIME_PREFIX}/openapi.json", # OpenAPI schema
|
|
57
|
-
)
|
|
58
52
|
|
|
59
|
-
|
|
53
|
+
# Lazy FastAPI initialization
|
|
54
|
+
class _LazyApp:
|
|
55
|
+
"""Lazy wrapper for FastAPI app - only imported when accessed."""
|
|
56
|
+
|
|
57
|
+
_app = None
|
|
58
|
+
|
|
59
|
+
def _get_app(self):
|
|
60
|
+
if self._app is None:
|
|
61
|
+
fastapi = _load_fastapi()
|
|
62
|
+
from agenta.sdk.router import get_router
|
|
63
|
+
|
|
64
|
+
self._app = fastapi.FastAPI(
|
|
65
|
+
docs_url=f"{AGENTA_RUNTIME_PREFIX}/docs", # Swagger UI
|
|
66
|
+
openapi_url=f"{AGENTA_RUNTIME_PREFIX}/openapi.json", # OpenAPI schema
|
|
67
|
+
)
|
|
68
|
+
self._app.include_router(get_router(), prefix=AGENTA_RUNTIME_PREFIX)
|
|
69
|
+
return self._app
|
|
70
|
+
|
|
71
|
+
def __getattr__(self, name):
|
|
72
|
+
return getattr(self._get_app(), name)
|
|
73
|
+
|
|
74
|
+
async def __call__(self, scope, receive, send):
|
|
75
|
+
return await self._get_app()(scope, receive, send)
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
app = _LazyApp() # type: ignore
|
|
60
79
|
|
|
61
80
|
|
|
62
81
|
class PathValidator(BaseModel):
|
|
@@ -140,16 +159,32 @@ class entrypoint:
|
|
|
140
159
|
route_path: str = "",
|
|
141
160
|
config_schema: Optional[BaseModel] = None,
|
|
142
161
|
):
|
|
162
|
+
# Lazy import fastapi components - only loaded when decorator is used
|
|
163
|
+
fastapi = _load_fastapi()
|
|
164
|
+
|
|
143
165
|
self.func = func
|
|
144
166
|
self.route_path = route_path
|
|
145
167
|
self.config_schema = config_schema
|
|
146
168
|
|
|
169
|
+
# Store for use in methods
|
|
170
|
+
self._Request = fastapi.Request
|
|
171
|
+
self._HTTPException = fastapi.HTTPException
|
|
172
|
+
self._Body = fastapi.Body
|
|
173
|
+
|
|
147
174
|
signature_parameters = signature(func).parameters
|
|
148
175
|
config, default_parameters = self.parse_config()
|
|
149
176
|
|
|
150
177
|
### --- Middleware --- #
|
|
151
178
|
if not entrypoint._middleware:
|
|
152
179
|
entrypoint._middleware = True
|
|
180
|
+
from agenta.sdk.middleware.mock import MockMiddleware
|
|
181
|
+
from agenta.sdk.middleware.inline import InlineMiddleware
|
|
182
|
+
from agenta.sdk.middleware.vault import VaultMiddleware
|
|
183
|
+
from agenta.sdk.middleware.config import ConfigMiddleware
|
|
184
|
+
from agenta.sdk.middleware.otel import OTelMiddleware
|
|
185
|
+
from agenta.sdk.middleware.auth import AuthHTTPMiddleware
|
|
186
|
+
from agenta.sdk.middleware.cors import CORSMiddleware
|
|
187
|
+
|
|
153
188
|
app.add_middleware(MockMiddleware)
|
|
154
189
|
app.add_middleware(InlineMiddleware)
|
|
155
190
|
app.add_middleware(VaultMiddleware)
|
|
@@ -177,7 +212,7 @@ class entrypoint:
|
|
|
177
212
|
request.state.config["parameters"] is None
|
|
178
213
|
or request.state.config["references"] is None
|
|
179
214
|
):
|
|
180
|
-
raise
|
|
215
|
+
raise self._HTTPException(
|
|
181
216
|
status_code=400,
|
|
182
217
|
detail="Config not found based on provided references.",
|
|
183
218
|
)
|
|
@@ -318,12 +353,12 @@ class entrypoint:
|
|
|
318
353
|
|
|
319
354
|
async def execute_wrapper(
|
|
320
355
|
self,
|
|
321
|
-
request: Request,
|
|
356
|
+
request: "Request", # type: ignore
|
|
322
357
|
*args,
|
|
323
358
|
**kwargs,
|
|
324
359
|
):
|
|
325
360
|
if not request:
|
|
326
|
-
raise
|
|
361
|
+
raise self._HTTPException(status_code=500, detail="Missing 'request'.")
|
|
327
362
|
|
|
328
363
|
state = request.state
|
|
329
364
|
traceparent = state.otel.get("traceparent")
|
|
@@ -332,6 +367,8 @@ class entrypoint:
|
|
|
332
367
|
parameters = state.config.get("parameters")
|
|
333
368
|
references = state.config.get("references")
|
|
334
369
|
secrets = state.vault.get("secrets")
|
|
370
|
+
local_secrets = state.vault.get("local_secrets")
|
|
371
|
+
vault_secrets = state.vault.get("vault_secrets")
|
|
335
372
|
inline = state.inline
|
|
336
373
|
mock = state.mock
|
|
337
374
|
|
|
@@ -339,6 +376,8 @@ class entrypoint:
|
|
|
339
376
|
context=RoutingContext(
|
|
340
377
|
parameters=parameters,
|
|
341
378
|
secrets=secrets,
|
|
379
|
+
local_secrets=local_secrets,
|
|
380
|
+
vault_secrets=vault_secrets,
|
|
342
381
|
mock=mock,
|
|
343
382
|
)
|
|
344
383
|
):
|
|
@@ -368,6 +407,8 @@ class entrypoint:
|
|
|
368
407
|
result: Any,
|
|
369
408
|
inline: bool,
|
|
370
409
|
):
|
|
410
|
+
StarletteResponse, StreamingResponse = _load_starlette_responses()
|
|
411
|
+
|
|
371
412
|
data = None
|
|
372
413
|
content_type = "text/plain"
|
|
373
414
|
|
|
@@ -472,7 +513,7 @@ class entrypoint:
|
|
|
472
513
|
span_id,
|
|
473
514
|
) = await self.fetch_inline_trace(inline)
|
|
474
515
|
|
|
475
|
-
raise
|
|
516
|
+
raise self._HTTPException(
|
|
476
517
|
status_code=status_code,
|
|
477
518
|
detail=dict(
|
|
478
519
|
message=str(error),
|
|
@@ -584,7 +625,7 @@ class entrypoint:
|
|
|
584
625
|
Parameter(
|
|
585
626
|
"request",
|
|
586
627
|
kind=Parameter.POSITIONAL_OR_KEYWORD,
|
|
587
|
-
annotation=
|
|
628
|
+
annotation=self._Request,
|
|
588
629
|
),
|
|
589
630
|
*original_sig.parameters.values(),
|
|
590
631
|
]
|
|
@@ -647,7 +688,7 @@ class entrypoint:
|
|
|
647
688
|
name=self._config_key,
|
|
648
689
|
kind=Parameter.KEYWORD_ONLY,
|
|
649
690
|
annotation=type(config_instance), # Get the actual class type
|
|
650
|
-
default=
|
|
691
|
+
default=self._Body(config_instance), # Use the instance directly
|
|
651
692
|
)
|
|
652
693
|
)
|
|
653
694
|
|
|
@@ -661,7 +702,7 @@ class entrypoint:
|
|
|
661
702
|
Parameter(
|
|
662
703
|
name,
|
|
663
704
|
Parameter.KEYWORD_ONLY,
|
|
664
|
-
default=
|
|
705
|
+
default=self._Body(..., embed=True),
|
|
665
706
|
annotation=param.default.__class__.__bases__[
|
|
666
707
|
0
|
|
667
708
|
], # determines and get the base (parent/inheritance) type of the sdk-type at run-time. \
|
|
@@ -957,9 +957,10 @@ def parse_to_agenta_span_dto(
|
|
|
957
957
|
########################################
|
|
958
958
|
|
|
959
959
|
|
|
960
|
-
from litellm import cost_calculator
|
|
961
960
|
from opentelemetry.sdk.trace import ReadableSpan
|
|
962
961
|
|
|
962
|
+
from agenta.sdk.utils.lazy import _load_litellm
|
|
963
|
+
|
|
963
964
|
from agenta.sdk.types import AgentaNodeDto, AgentaNodesResponse
|
|
964
965
|
|
|
965
966
|
|
|
@@ -1120,6 +1121,12 @@ TYPES_WITH_COSTS = [
|
|
|
1120
1121
|
|
|
1121
1122
|
|
|
1122
1123
|
def calculate_costs(span_idx: Dict[str, SpanDTO]):
|
|
1124
|
+
litellm = _load_litellm()
|
|
1125
|
+
if not litellm:
|
|
1126
|
+
return
|
|
1127
|
+
|
|
1128
|
+
cost_calculator = litellm.cost_calculator
|
|
1129
|
+
|
|
1123
1130
|
for span in span_idx.values():
|
|
1124
1131
|
if (
|
|
1125
1132
|
span.node.type
|
|
@@ -126,10 +126,11 @@ async def _upsert_entities(
|
|
|
126
126
|
for testcases_data in simple_evaluation_data.testset_steps:
|
|
127
127
|
if isinstance(testcases_data, List):
|
|
128
128
|
if all(isinstance(step, Dict) for step in testcases_data):
|
|
129
|
-
|
|
129
|
+
created_revision = await acreate_testset(
|
|
130
130
|
data=testcases_data,
|
|
131
131
|
)
|
|
132
|
-
|
|
132
|
+
if created_revision and created_revision.id:
|
|
133
|
+
testset_steps[str(created_revision.id)] = "custom"
|
|
133
134
|
|
|
134
135
|
simple_evaluation_data.testset_steps = testset_steps
|
|
135
136
|
|
|
@@ -215,15 +216,16 @@ async def _retrieve_entities(
|
|
|
215
216
|
Dict[UUID, EvaluatorRevision],
|
|
216
217
|
]:
|
|
217
218
|
testset_revisions: Dict[UUID, TestsetRevision] = {}
|
|
218
|
-
|
|
219
|
-
# testset_revision = await retrieve_testset(
|
|
220
|
-
# testset_revision_id=testset_revision_id,
|
|
221
|
-
# )
|
|
222
|
-
for testset_id, origin in simple_evaluation_data.testset_steps.items():
|
|
219
|
+
for testset_ref, origin in simple_evaluation_data.testset_steps.items():
|
|
223
220
|
testset_revision = await aretrieve_testset(
|
|
224
|
-
|
|
221
|
+
testset_revision_id=testset_ref,
|
|
225
222
|
)
|
|
226
223
|
|
|
224
|
+
if not testset_revision or not testset_revision.id:
|
|
225
|
+
testset_revision = await aretrieve_testset(
|
|
226
|
+
testset_id=testset_ref,
|
|
227
|
+
)
|
|
228
|
+
|
|
227
229
|
if not testset_revision or not testset_revision.id:
|
|
228
230
|
continue
|
|
229
231
|
|
|
@@ -308,6 +310,32 @@ async def aevaluate(
|
|
|
308
310
|
"────────────────────────────────────────────────────────────────────────────"
|
|
309
311
|
)
|
|
310
312
|
|
|
313
|
+
# Normalize testset_steps to revision ids (no JIT transfers in backend)
|
|
314
|
+
if simple_evaluation_data.testset_steps and isinstance(
|
|
315
|
+
simple_evaluation_data.testset_steps, dict
|
|
316
|
+
):
|
|
317
|
+
normalized_testset_steps: Dict[str, Origin] = {}
|
|
318
|
+
for testset_id_str, origin in simple_evaluation_data.testset_steps.items():
|
|
319
|
+
try:
|
|
320
|
+
testset_uuid = UUID(str(testset_id_str))
|
|
321
|
+
except Exception:
|
|
322
|
+
continue
|
|
323
|
+
|
|
324
|
+
testset_revision = await aretrieve_testset(
|
|
325
|
+
testset_revision_id=testset_uuid,
|
|
326
|
+
)
|
|
327
|
+
|
|
328
|
+
if not testset_revision or not testset_revision.id:
|
|
329
|
+
# Fallback: treat as testset_id (latest revision)
|
|
330
|
+
testset_revision = await aretrieve_testset(
|
|
331
|
+
testset_id=testset_uuid,
|
|
332
|
+
)
|
|
333
|
+
|
|
334
|
+
if testset_revision and testset_revision.id:
|
|
335
|
+
normalized_testset_steps[str(testset_revision.id)] = origin
|
|
336
|
+
|
|
337
|
+
simple_evaluation_data.testset_steps = normalized_testset_steps
|
|
338
|
+
|
|
311
339
|
suffix = _timestamp_suffix()
|
|
312
340
|
name = f"{name}{suffix}"
|
|
313
341
|
|
agenta/sdk/evaluations/runs.py
CHANGED
agenta/sdk/litellm/mockllm.py
CHANGED
|
@@ -2,9 +2,8 @@ from typing import Optional, Protocol, Any
|
|
|
2
2
|
from os import environ
|
|
3
3
|
from contextlib import contextmanager
|
|
4
4
|
|
|
5
|
-
import litellm
|
|
6
|
-
|
|
7
5
|
from agenta.sdk.utils.logging import get_module_logger
|
|
6
|
+
from agenta.sdk.utils.lazy import _load_litellm
|
|
8
7
|
|
|
9
8
|
from agenta.sdk.litellm.mocks import MOCKS
|
|
10
9
|
from agenta.sdk.contexts.routing import RoutingContext
|
|
@@ -81,6 +80,7 @@ async def acompletion(*args, **kwargs):
|
|
|
81
80
|
|
|
82
81
|
return MOCKS[mock](*args, **kwargs)
|
|
83
82
|
|
|
83
|
+
litellm = _load_litellm(injected=globals().get("litellm"))
|
|
84
84
|
if not litellm:
|
|
85
85
|
raise ValueError("litellm not found")
|
|
86
86
|
|
agenta/sdk/managers/config.py
CHANGED
|
@@ -2,10 +2,10 @@ import json
|
|
|
2
2
|
from pathlib import Path
|
|
3
3
|
from typing import Optional, Type, TypeVar, Dict, Any, Union
|
|
4
4
|
|
|
5
|
-
import yaml
|
|
6
5
|
from pydantic import BaseModel
|
|
7
6
|
|
|
8
7
|
from agenta.sdk.utils.logging import get_module_logger
|
|
8
|
+
from agenta.sdk.utils.lazy import _load_yaml
|
|
9
9
|
from agenta.sdk.managers.shared import SharedManager
|
|
10
10
|
from agenta.sdk.contexts.routing import RoutingContext
|
|
11
11
|
|
|
@@ -174,6 +174,8 @@ class ConfigManager:
|
|
|
174
174
|
"""
|
|
175
175
|
file_path = Path(filename)
|
|
176
176
|
|
|
177
|
+
yaml = _load_yaml()
|
|
178
|
+
|
|
177
179
|
with open(file_path, "r", encoding="utf-8") as file:
|
|
178
180
|
parameters = yaml.safe_load(file)
|
|
179
181
|
|