agenta 0.70.1__py3-none-any.whl → 0.75.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- agenta/__init__.py +9 -3
- agenta/sdk/__init__.py +2 -4
- agenta/sdk/agenta_init.py +22 -75
- agenta/sdk/assets.py +57 -0
- agenta/sdk/context/serving.py +2 -0
- agenta/sdk/contexts/routing.py +2 -0
- agenta/sdk/contexts/running.py +3 -2
- agenta/sdk/decorators/running.py +8 -4
- agenta/sdk/decorators/serving.py +65 -26
- agenta/sdk/decorators/tracing.py +51 -30
- agenta/sdk/engines/tracing/inline.py +8 -1
- agenta/sdk/engines/tracing/processors.py +23 -12
- agenta/sdk/evaluations/preview/evaluate.py +36 -8
- agenta/sdk/evaluations/runs.py +2 -1
- agenta/sdk/litellm/mockllm.py +2 -2
- agenta/sdk/managers/config.py +3 -1
- agenta/sdk/managers/secrets.py +25 -8
- agenta/sdk/managers/testsets.py +143 -227
- agenta/sdk/middleware/config.py +3 -1
- agenta/sdk/middleware/otel.py +3 -1
- agenta/sdk/middleware/vault.py +33 -18
- agenta/sdk/middlewares/routing/otel.py +1 -1
- agenta/sdk/middlewares/running/vault.py +33 -17
- agenta/sdk/router.py +30 -5
- agenta/sdk/tracing/inline.py +8 -1
- agenta/sdk/tracing/processors.py +8 -3
- agenta/sdk/tracing/propagation.py +9 -12
- agenta/sdk/types.py +19 -21
- agenta/sdk/utils/client.py +10 -9
- agenta/sdk/utils/lazy.py +253 -0
- agenta/sdk/workflows/builtin.py +2 -0
- agenta/sdk/workflows/configurations.py +1 -0
- agenta/sdk/workflows/handlers.py +236 -81
- agenta/sdk/workflows/interfaces.py +47 -0
- agenta/sdk/workflows/runners/base.py +6 -2
- agenta/sdk/workflows/runners/daytona.py +250 -131
- agenta/sdk/workflows/runners/local.py +22 -56
- agenta/sdk/workflows/runners/registry.py +1 -1
- agenta/sdk/workflows/sandbox.py +17 -5
- agenta/sdk/workflows/templates.py +81 -0
- agenta/sdk/workflows/utils.py +6 -0
- {agenta-0.70.1.dist-info → agenta-0.75.0.dist-info}/METADATA +4 -8
- {agenta-0.70.1.dist-info → agenta-0.75.0.dist-info}/RECORD +44 -44
- agenta/config.py +0 -25
- agenta/config.toml +0 -4
- {agenta-0.70.1.dist-info → agenta-0.75.0.dist-info}/WHEEL +0 -0
|
@@ -36,7 +36,7 @@ _CACHE_ENABLED = (
|
|
|
36
36
|
_cache = TTLLRUCache()
|
|
37
37
|
|
|
38
38
|
|
|
39
|
-
async def get_secrets(api_url, credentials) -> list:
|
|
39
|
+
async def get_secrets(api_url, credentials) -> tuple[list, list, list]:
|
|
40
40
|
headers = None
|
|
41
41
|
if credentials:
|
|
42
42
|
headers = {"Authorization": credentials}
|
|
@@ -53,8 +53,13 @@ async def get_secrets(api_url, credentials) -> list:
|
|
|
53
53
|
|
|
54
54
|
if secrets_cache:
|
|
55
55
|
secrets = secrets_cache.get("secrets")
|
|
56
|
+
vault_secrets = secrets_cache.get("vault_secrets")
|
|
57
|
+
local_secrets = secrets_cache.get("local_secrets")
|
|
56
58
|
|
|
57
|
-
|
|
59
|
+
if vault_secrets is None or local_secrets is None:
|
|
60
|
+
return secrets, [], []
|
|
61
|
+
|
|
62
|
+
return secrets, vault_secrets, local_secrets
|
|
58
63
|
|
|
59
64
|
local_secrets: List[Dict[str, Any]] = []
|
|
60
65
|
|
|
@@ -76,7 +81,7 @@ async def get_secrets(api_url, credentials) -> list:
|
|
|
76
81
|
)
|
|
77
82
|
|
|
78
83
|
local_secrets.append(secret.model_dump())
|
|
79
|
-
except: # pylint: disable=bare-except
|
|
84
|
+
except Exception: # pylint: disable=bare-except
|
|
80
85
|
display_exception("Vault: Local Secrets Exception")
|
|
81
86
|
|
|
82
87
|
vault_secrets: List[Dict[str, Any]] = []
|
|
@@ -93,32 +98,38 @@ async def get_secrets(api_url, credentials) -> list:
|
|
|
93
98
|
|
|
94
99
|
else:
|
|
95
100
|
vault_secrets = response.json()
|
|
96
|
-
except: # pylint: disable=bare-except
|
|
101
|
+
except Exception: # pylint: disable=bare-except
|
|
97
102
|
display_exception("Vault: Vault Secrets Exception")
|
|
98
103
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
custom_secrets = []
|
|
104
|
+
local_standard = {}
|
|
105
|
+
vault_standard = {}
|
|
106
|
+
vault_custom = []
|
|
103
107
|
|
|
104
108
|
if local_secrets:
|
|
105
109
|
for secret in local_secrets:
|
|
106
|
-
|
|
110
|
+
local_standard[secret["data"]["kind"]] = secret # type: ignore
|
|
107
111
|
|
|
108
112
|
if vault_secrets:
|
|
109
113
|
for secret in vault_secrets:
|
|
110
114
|
if secret["kind"] == "provider_key": # type: ignore
|
|
111
|
-
|
|
115
|
+
vault_standard[secret["data"]["kind"]] = secret # type: ignore
|
|
112
116
|
elif secret["kind"] == "custom_provider": # type: ignore
|
|
113
|
-
|
|
117
|
+
vault_custom.append(secret)
|
|
114
118
|
|
|
115
|
-
|
|
119
|
+
combined_standard = {**local_standard, **vault_standard}
|
|
120
|
+
combined_vault = list(vault_standard.values()) + vault_custom
|
|
121
|
+
secrets = list(combined_standard.values()) + vault_custom
|
|
116
122
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
123
|
+
_cache.put(
|
|
124
|
+
_hash,
|
|
125
|
+
{
|
|
126
|
+
"secrets": secrets,
|
|
127
|
+
"vault_secrets": combined_vault,
|
|
128
|
+
"local_secrets": local_secrets,
|
|
129
|
+
},
|
|
130
|
+
)
|
|
120
131
|
|
|
121
|
-
return secrets
|
|
132
|
+
return secrets, combined_vault, local_secrets
|
|
122
133
|
|
|
123
134
|
|
|
124
135
|
class VaultMiddleware:
|
|
@@ -133,8 +144,13 @@ class VaultMiddleware:
|
|
|
133
144
|
ctx = RunningContext.get()
|
|
134
145
|
credentials = ctx.credentials
|
|
135
146
|
|
|
136
|
-
secrets = await get_secrets(
|
|
147
|
+
secrets, vault_secrets, local_secrets = await get_secrets(
|
|
148
|
+
api_url,
|
|
149
|
+
credentials,
|
|
150
|
+
)
|
|
137
151
|
|
|
138
152
|
ctx.secrets = secrets
|
|
153
|
+
ctx.vault_secrets = vault_secrets
|
|
154
|
+
ctx.local_secrets = local_secrets
|
|
139
155
|
|
|
140
156
|
return await call_next(request)
|
agenta/sdk/router.py
CHANGED
|
@@ -1,8 +1,33 @@
|
|
|
1
|
-
from
|
|
1
|
+
from typing import TYPE_CHECKING, Optional
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
if TYPE_CHECKING:
|
|
4
|
+
from fastapi import APIRouter
|
|
4
5
|
|
|
6
|
+
from agenta.sdk.utils.lazy import _load_fastapi
|
|
5
7
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
8
|
+
_router: Optional["APIRouter"] = None
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class _LazyRouter:
|
|
12
|
+
def __getattr__(self, name):
|
|
13
|
+
return getattr(get_router(), name)
|
|
14
|
+
|
|
15
|
+
def __call__(self, *args, **kwargs):
|
|
16
|
+
return get_router()(*args, **kwargs)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def get_router() -> "APIRouter":
|
|
20
|
+
global _router # pylint: disable=global-statement
|
|
21
|
+
|
|
22
|
+
if _router is None:
|
|
23
|
+
fastapi = _load_fastapi()
|
|
24
|
+
_router = fastapi.APIRouter()
|
|
25
|
+
|
|
26
|
+
@_router.get("/health")
|
|
27
|
+
def health():
|
|
28
|
+
return {"status": "ok"}
|
|
29
|
+
|
|
30
|
+
return _router
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
router = _LazyRouter()
|
agenta/sdk/tracing/inline.py
CHANGED
|
@@ -949,9 +949,10 @@ def parse_to_agenta_span_dto(
|
|
|
949
949
|
########################################
|
|
950
950
|
|
|
951
951
|
|
|
952
|
-
from litellm import cost_calculator
|
|
953
952
|
from opentelemetry.sdk.trace import ReadableSpan
|
|
954
953
|
|
|
954
|
+
from agenta.sdk.utils.lazy import _load_litellm
|
|
955
|
+
|
|
955
956
|
from agenta.sdk.types import AgentaNodeDto, AgentaNodesResponse
|
|
956
957
|
|
|
957
958
|
|
|
@@ -1112,6 +1113,12 @@ TYPES_WITH_COSTS = [
|
|
|
1112
1113
|
|
|
1113
1114
|
|
|
1114
1115
|
def calculate_costs(span_idx: Dict[str, SpanDTO]):
|
|
1116
|
+
litellm = _load_litellm()
|
|
1117
|
+
if not litellm:
|
|
1118
|
+
return
|
|
1119
|
+
|
|
1120
|
+
cost_calculator = litellm.cost_calculator
|
|
1121
|
+
|
|
1115
1122
|
for span in span_idx.values():
|
|
1116
1123
|
if (
|
|
1117
1124
|
span.node.type
|
agenta/sdk/tracing/processors.py
CHANGED
|
@@ -1,13 +1,16 @@
|
|
|
1
|
-
from typing import Optional, Dict, List
|
|
2
1
|
from threading import Lock
|
|
2
|
+
from typing import Dict, List, Optional
|
|
3
3
|
|
|
4
|
+
|
|
5
|
+
from agenta.sdk.contexts.tracing import TracingContext
|
|
6
|
+
from agenta.sdk.utils.logging import get_module_logger
|
|
4
7
|
from opentelemetry.baggage import get_all as get_baggage
|
|
5
8
|
from opentelemetry.context import Context
|
|
6
9
|
from opentelemetry.sdk.trace import Span, SpanProcessor
|
|
7
10
|
from opentelemetry.sdk.trace.export import (
|
|
8
|
-
SpanExporter,
|
|
9
|
-
ReadableSpan,
|
|
10
11
|
BatchSpanProcessor,
|
|
12
|
+
ReadableSpan,
|
|
13
|
+
SpanExporter,
|
|
11
14
|
)
|
|
12
15
|
from opentelemetry.trace import SpanContext
|
|
13
16
|
|
|
@@ -88,6 +91,8 @@ class TraceProcessor(SpanProcessor):
|
|
|
88
91
|
if isinstance(ref, dict):
|
|
89
92
|
for field, val in ref.items():
|
|
90
93
|
span.set_attribute(f"{key}.{field}", str(val))
|
|
94
|
+
elif isinstance(ref, (str, bool, int, float, bytes)):
|
|
95
|
+
span.set_attribute(key, ref)
|
|
91
96
|
else:
|
|
92
97
|
# Not a reference - only set if it's a valid attribute type
|
|
93
98
|
if isinstance(value, (str, bool, int, float, bytes)):
|
|
@@ -1,14 +1,10 @@
|
|
|
1
|
-
from typing import
|
|
1
|
+
from typing import Any, Dict, Optional, Tuple
|
|
2
2
|
|
|
3
|
-
from
|
|
4
|
-
from opentelemetry.baggage.propagation import W3CBaggagePropagator
|
|
5
|
-
from opentelemetry.trace.propagation.tracecontext import TraceContextTextMapPropagator
|
|
3
|
+
from agenta.sdk.contexts.tracing import TracingContext
|
|
6
4
|
from opentelemetry.baggage import set_baggage
|
|
5
|
+
from opentelemetry.baggage.propagation import W3CBaggagePropagator
|
|
7
6
|
from opentelemetry.context import get_current
|
|
8
|
-
|
|
9
|
-
from agenta.sdk.contexts.tracing import TracingContext
|
|
10
|
-
|
|
11
|
-
import agenta as ag
|
|
7
|
+
from opentelemetry.trace.propagation.tracecontext import TraceContextTextMapPropagator
|
|
12
8
|
|
|
13
9
|
|
|
14
10
|
def extract(
|
|
@@ -47,11 +43,12 @@ def extract(
|
|
|
47
43
|
baggage = {}
|
|
48
44
|
|
|
49
45
|
try:
|
|
50
|
-
|
|
51
|
-
|
|
46
|
+
raw_baggage = (
|
|
47
|
+
headers.get("Baggage") # Uppercase
|
|
52
48
|
or headers.get("baggage") # Lowercase
|
|
53
|
-
or ""
|
|
54
|
-
|
|
49
|
+
or ""
|
|
50
|
+
)
|
|
51
|
+
_carrier = {"baggage": raw_baggage}
|
|
55
52
|
|
|
56
53
|
_context = W3CBaggagePropagator().extract(_carrier)
|
|
57
54
|
|
agenta/sdk/types.py
CHANGED
|
@@ -8,7 +8,7 @@ from pydantic import BaseModel, Field, model_validator, AliasChoices
|
|
|
8
8
|
from starlette.responses import StreamingResponse
|
|
9
9
|
|
|
10
10
|
|
|
11
|
-
from agenta.sdk.assets import supported_llm_models
|
|
11
|
+
from agenta.sdk.assets import supported_llm_models, model_metadata
|
|
12
12
|
from agenta.client.backend.types import AgentaNodesResponse, AgentaNodeDto
|
|
13
13
|
|
|
14
14
|
|
|
@@ -23,7 +23,11 @@ def MCField( # pylint: disable=invalid-name
|
|
|
23
23
|
) -> Field:
|
|
24
24
|
# Pydantic 2.12+ no longer allows post-creation mutation of field properties
|
|
25
25
|
if isinstance(choices, dict):
|
|
26
|
-
json_extra = {
|
|
26
|
+
json_extra = {
|
|
27
|
+
"choices": choices,
|
|
28
|
+
"x-parameter": "grouped_choice",
|
|
29
|
+
"x-model-metadata": model_metadata,
|
|
30
|
+
}
|
|
27
31
|
elif isinstance(choices, list):
|
|
28
32
|
json_extra = {"choices": choices, "x-parameter": "choice"}
|
|
29
33
|
else:
|
|
@@ -492,17 +496,11 @@ class TemplateFormatError(PromptTemplateError):
|
|
|
492
496
|
super().__init__(message)
|
|
493
497
|
|
|
494
498
|
|
|
495
|
-
import json
|
|
496
499
|
import re
|
|
497
500
|
from typing import Any, Dict, Iterable, Tuple, Optional
|
|
498
501
|
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
import jsonpath # ✅ use module API
|
|
502
|
-
from jsonpath import JSONPointer # pointer class is fine to use
|
|
503
|
-
except Exception:
|
|
504
|
-
jsonpath = None
|
|
505
|
-
JSONPointer = None
|
|
502
|
+
from agenta.sdk.utils.lazy import _load_jinja2, _load_jsonpath
|
|
503
|
+
|
|
506
504
|
|
|
507
505
|
# ========= Scheme detection =========
|
|
508
506
|
|
|
@@ -545,7 +543,8 @@ def resolve_dot_notation(expr: str, data: dict) -> object:
|
|
|
545
543
|
|
|
546
544
|
|
|
547
545
|
def resolve_json_path(expr: str, data: dict) -> object:
|
|
548
|
-
|
|
546
|
+
json_path, _ = _load_jsonpath()
|
|
547
|
+
if json_path is None:
|
|
549
548
|
raise ImportError("python-jsonpath is required for json-path ($...)")
|
|
550
549
|
|
|
551
550
|
if not (expr == "$" or expr.startswith("$.") or expr.startswith("$[")):
|
|
@@ -555,15 +554,16 @@ def resolve_json_path(expr: str, data: dict) -> object:
|
|
|
555
554
|
)
|
|
556
555
|
|
|
557
556
|
# Use package-level APIf
|
|
558
|
-
results =
|
|
557
|
+
results = json_path.findall(expr, data) # always returns a list
|
|
559
558
|
return results[0] if len(results) == 1 else results
|
|
560
559
|
|
|
561
560
|
|
|
562
561
|
def resolve_json_pointer(expr: str, data: Dict[str, Any]) -> Any:
|
|
563
562
|
"""Resolve a JSON Pointer; returns a single value."""
|
|
564
|
-
|
|
563
|
+
_, json_pointer = _load_jsonpath()
|
|
564
|
+
if json_pointer is None:
|
|
565
565
|
raise ImportError("python-jsonpath is required for json-pointer (/...)")
|
|
566
|
-
return
|
|
566
|
+
return json_pointer(expr).resolve(data)
|
|
567
567
|
|
|
568
568
|
|
|
569
569
|
def resolve_any(expr: str, data: Dict[str, Any]) -> Any:
|
|
@@ -631,12 +631,10 @@ def compute_truly_unreplaced(original: set, rendered: str) -> set:
|
|
|
631
631
|
|
|
632
632
|
def missing_lib_hints(unreplaced: set) -> Optional[str]:
|
|
633
633
|
"""Suggest installing python-jsonpath if placeholders indicate json-path or json-pointer usage."""
|
|
634
|
-
if any(expr.startswith("$") or expr.startswith("/") for expr in unreplaced)
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
"Install python-jsonpath to enable json-path ($...) and json-pointer (/...)"
|
|
639
|
-
)
|
|
634
|
+
if any(expr.startswith("$") or expr.startswith("/") for expr in unreplaced):
|
|
635
|
+
json_path, json_pointer = _load_jsonpath()
|
|
636
|
+
if json_path is None or json_pointer is None:
|
|
637
|
+
return "Install python-jsonpath to enable json-path ($...) and json-pointer (/...)"
|
|
640
638
|
return None
|
|
641
639
|
|
|
642
640
|
|
|
@@ -688,7 +686,7 @@ class PromptTemplate(BaseModel):
|
|
|
688
686
|
return content.format(**kwargs)
|
|
689
687
|
|
|
690
688
|
elif self.template_format == "jinja2":
|
|
691
|
-
|
|
689
|
+
Template, TemplateError = _load_jinja2()
|
|
692
690
|
|
|
693
691
|
try:
|
|
694
692
|
return Template(content).render(**kwargs)
|
agenta/sdk/utils/client.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import httpx
|
|
2
2
|
|
|
3
3
|
BASE_TIMEOUT = 10
|
|
4
4
|
|
|
@@ -11,7 +11,7 @@ log = get_module_logger(__name__)
|
|
|
11
11
|
|
|
12
12
|
def authed_api():
|
|
13
13
|
"""
|
|
14
|
-
Preconfigured
|
|
14
|
+
Preconfigured httpx client for authenticated endpoints (supports all methods).
|
|
15
15
|
"""
|
|
16
16
|
|
|
17
17
|
api_url = ag.DEFAULT_AGENTA_SINGLETON_INSTANCE.api_url
|
|
@@ -27,12 +27,13 @@ def authed_api():
|
|
|
27
27
|
headers = kwargs.pop("headers", {})
|
|
28
28
|
headers.setdefault("Authorization", f"ApiKey {api_key}")
|
|
29
29
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
30
|
+
with httpx.Client() as client:
|
|
31
|
+
return client.request(
|
|
32
|
+
method=method,
|
|
33
|
+
url=url,
|
|
34
|
+
headers=headers,
|
|
35
|
+
timeout=BASE_TIMEOUT,
|
|
36
|
+
**kwargs,
|
|
37
|
+
)
|
|
37
38
|
|
|
38
39
|
return _request
|
agenta/sdk/utils/lazy.py
ADDED
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
from typing import Any, Callable, Optional, Protocol, Tuple, TYPE_CHECKING
|
|
2
|
+
|
|
3
|
+
if TYPE_CHECKING:
|
|
4
|
+
from daytona import (
|
|
5
|
+
CreateSandboxFromSnapshotParams,
|
|
6
|
+
Daytona,
|
|
7
|
+
DaytonaConfig,
|
|
8
|
+
Sandbox,
|
|
9
|
+
)
|
|
10
|
+
from fastapi import APIRouter, Body, FastAPI, HTTPException, Request
|
|
11
|
+
from jinja2 import Template, TemplateError
|
|
12
|
+
from openai import AsyncOpenAI, OpenAIError
|
|
13
|
+
from starlette.responses import Response as StarletteResponse, StreamingResponse
|
|
14
|
+
from jsonpath import JSONPointer
|
|
15
|
+
import jsonpath as jsonpath_module
|
|
16
|
+
import yaml as yaml_module
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class _JsonpathModule(Protocol):
|
|
20
|
+
findall: Callable[..., Any]
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class _LitellmModule(Protocol):
|
|
24
|
+
cost_calculator: Any
|
|
25
|
+
acompletion: Callable[..., Any]
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class _FastAPIModule(Protocol):
|
|
29
|
+
FastAPI: type["FastAPI"]
|
|
30
|
+
APIRouter: type["APIRouter"]
|
|
31
|
+
Request: type["Request"]
|
|
32
|
+
HTTPException: type["HTTPException"]
|
|
33
|
+
Body: Any
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class _YamlModule(Protocol):
|
|
37
|
+
def safe_load(self, *args: Any, **kwargs: Any) -> Any: ...
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
_litellm_module: Optional[_LitellmModule] = None
|
|
41
|
+
_litellm_checked = False
|
|
42
|
+
|
|
43
|
+
_jsonpath_module: Optional[_JsonpathModule] = None
|
|
44
|
+
_jsonpath_pointer: Optional[type["JSONPointer"]] = None
|
|
45
|
+
_jsonpath_checked = False
|
|
46
|
+
|
|
47
|
+
_openai_cached: Optional[Tuple[type["AsyncOpenAI"], type["OpenAIError"]]] = None
|
|
48
|
+
_openai_checked = False
|
|
49
|
+
|
|
50
|
+
_yaml_module: Optional[_YamlModule] = None
|
|
51
|
+
_yaml_checked = False
|
|
52
|
+
|
|
53
|
+
_jinja_cached: Optional[Tuple[type["Template"], type["TemplateError"]]] = None
|
|
54
|
+
_jinja_checked = False
|
|
55
|
+
|
|
56
|
+
_fastapi_module: Optional[_FastAPIModule] = None
|
|
57
|
+
_fastapi_checked = False
|
|
58
|
+
|
|
59
|
+
_starlette_responses_cached: Optional[
|
|
60
|
+
Tuple[type["StarletteResponse"], type["StreamingResponse"]]
|
|
61
|
+
] = None
|
|
62
|
+
_starlette_responses_checked = False
|
|
63
|
+
|
|
64
|
+
_daytona_cached: Optional[
|
|
65
|
+
Tuple[
|
|
66
|
+
type["Daytona"],
|
|
67
|
+
type["DaytonaConfig"],
|
|
68
|
+
type["Sandbox"],
|
|
69
|
+
type["CreateSandboxFromSnapshotParams"],
|
|
70
|
+
]
|
|
71
|
+
] = None
|
|
72
|
+
_daytona_checked = False
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def _load_litellm(
|
|
76
|
+
injected: Optional[_LitellmModule] = None,
|
|
77
|
+
) -> Optional[_LitellmModule]:
|
|
78
|
+
global _litellm_module, _litellm_checked # pylint: disable=global-statement
|
|
79
|
+
|
|
80
|
+
if _litellm_checked:
|
|
81
|
+
return _litellm_module
|
|
82
|
+
|
|
83
|
+
if injected is not None:
|
|
84
|
+
_litellm_checked = True
|
|
85
|
+
_litellm_module = injected
|
|
86
|
+
return _litellm_module
|
|
87
|
+
|
|
88
|
+
_litellm_checked = True
|
|
89
|
+
try:
|
|
90
|
+
import litellm as _litellm
|
|
91
|
+
except Exception:
|
|
92
|
+
_litellm_module = None
|
|
93
|
+
else:
|
|
94
|
+
_litellm_module = _litellm
|
|
95
|
+
|
|
96
|
+
return _litellm_module
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def _load_jsonpath() -> Tuple[Optional[_JsonpathModule], Optional[type["JSONPointer"]]]:
|
|
100
|
+
global _jsonpath_module, _jsonpath_pointer, _jsonpath_checked # pylint: disable=global-statement
|
|
101
|
+
|
|
102
|
+
if _jsonpath_checked:
|
|
103
|
+
return _jsonpath_module, _jsonpath_pointer
|
|
104
|
+
|
|
105
|
+
_jsonpath_checked = True
|
|
106
|
+
try:
|
|
107
|
+
import jsonpath as _jsonpath
|
|
108
|
+
from jsonpath import JSONPointer as _JSONPointer
|
|
109
|
+
except Exception:
|
|
110
|
+
_jsonpath_module = None
|
|
111
|
+
_jsonpath_pointer = None
|
|
112
|
+
else:
|
|
113
|
+
_jsonpath_module = _jsonpath
|
|
114
|
+
_jsonpath_pointer = _JSONPointer
|
|
115
|
+
|
|
116
|
+
return _jsonpath_module, _jsonpath_pointer
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def _load_openai() -> Tuple[type["AsyncOpenAI"], type["OpenAIError"]]:
|
|
120
|
+
global _openai_cached, _openai_checked # pylint: disable=global-statement
|
|
121
|
+
|
|
122
|
+
if _openai_checked:
|
|
123
|
+
if _openai_cached is None:
|
|
124
|
+
raise ImportError(
|
|
125
|
+
"openai is required for semantic similarity evaluation. "
|
|
126
|
+
"Install it with `pip install openai`."
|
|
127
|
+
)
|
|
128
|
+
return _openai_cached
|
|
129
|
+
|
|
130
|
+
_openai_checked = True
|
|
131
|
+
try:
|
|
132
|
+
from openai import AsyncOpenAI, OpenAIError
|
|
133
|
+
except Exception as exc:
|
|
134
|
+
_openai_cached = None
|
|
135
|
+
raise ImportError(
|
|
136
|
+
"openai is required for semantic similarity evaluation. "
|
|
137
|
+
"Install it with `pip install openai`."
|
|
138
|
+
) from exc
|
|
139
|
+
|
|
140
|
+
_openai_cached = (AsyncOpenAI, OpenAIError)
|
|
141
|
+
return _openai_cached
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
def _load_yaml() -> _YamlModule:
|
|
145
|
+
global _yaml_module, _yaml_checked # pylint: disable=global-statement
|
|
146
|
+
|
|
147
|
+
if _yaml_checked:
|
|
148
|
+
if _yaml_module is None:
|
|
149
|
+
raise ImportError("pyyaml is required to load YAML configs.")
|
|
150
|
+
return _yaml_module
|
|
151
|
+
|
|
152
|
+
_yaml_checked = True
|
|
153
|
+
try:
|
|
154
|
+
import yaml as _yaml
|
|
155
|
+
except Exception as exc:
|
|
156
|
+
_yaml_module = None
|
|
157
|
+
raise ImportError("pyyaml is required to load YAML configs.") from exc
|
|
158
|
+
|
|
159
|
+
_yaml_module = _yaml
|
|
160
|
+
return _yaml_module
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
def _load_jinja2() -> Tuple[type["Template"], type["TemplateError"]]:
|
|
164
|
+
global _jinja_cached, _jinja_checked # pylint: disable=global-statement
|
|
165
|
+
|
|
166
|
+
if _jinja_checked:
|
|
167
|
+
if _jinja_cached is None:
|
|
168
|
+
raise ImportError("jinja2 is required for jinja2 template rendering.")
|
|
169
|
+
return _jinja_cached
|
|
170
|
+
|
|
171
|
+
_jinja_checked = True
|
|
172
|
+
try:
|
|
173
|
+
from jinja2 import Template, TemplateError
|
|
174
|
+
except Exception as exc:
|
|
175
|
+
_jinja_cached = None
|
|
176
|
+
raise ImportError("jinja2 is required for jinja2 template rendering.") from exc
|
|
177
|
+
|
|
178
|
+
_jinja_cached = (Template, TemplateError)
|
|
179
|
+
return _jinja_cached
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
def _load_fastapi() -> _FastAPIModule:
|
|
183
|
+
global _fastapi_module, _fastapi_checked # pylint: disable=global-statement
|
|
184
|
+
|
|
185
|
+
if _fastapi_checked:
|
|
186
|
+
if _fastapi_module is None:
|
|
187
|
+
raise ImportError("fastapi is required for serving routes.")
|
|
188
|
+
return _fastapi_module
|
|
189
|
+
|
|
190
|
+
_fastapi_checked = True
|
|
191
|
+
try:
|
|
192
|
+
import fastapi as _fastapi
|
|
193
|
+
except Exception as exc:
|
|
194
|
+
_fastapi_module = None
|
|
195
|
+
raise ImportError("fastapi is required for serving routes.") from exc
|
|
196
|
+
|
|
197
|
+
_fastapi_module = _fastapi
|
|
198
|
+
return _fastapi_module
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
def _load_starlette_responses() -> Tuple[
|
|
202
|
+
type["StarletteResponse"], type["StreamingResponse"]
|
|
203
|
+
]:
|
|
204
|
+
global _starlette_responses_cached, _starlette_responses_checked # pylint: disable=global-statement
|
|
205
|
+
|
|
206
|
+
if _starlette_responses_checked:
|
|
207
|
+
if _starlette_responses_cached is None:
|
|
208
|
+
raise ImportError("starlette is required for response handling.")
|
|
209
|
+
return _starlette_responses_cached
|
|
210
|
+
|
|
211
|
+
_starlette_responses_checked = True
|
|
212
|
+
try:
|
|
213
|
+
from starlette.responses import Response as StarletteResponse, StreamingResponse
|
|
214
|
+
except Exception as exc:
|
|
215
|
+
_starlette_responses_cached = None
|
|
216
|
+
raise ImportError("starlette is required for response handling.") from exc
|
|
217
|
+
|
|
218
|
+
_starlette_responses_cached = (StarletteResponse, StreamingResponse)
|
|
219
|
+
return _starlette_responses_cached
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
def _load_daytona() -> Tuple[
|
|
223
|
+
type["Daytona"],
|
|
224
|
+
type["DaytonaConfig"],
|
|
225
|
+
type["Sandbox"],
|
|
226
|
+
type["CreateSandboxFromSnapshotParams"],
|
|
227
|
+
]:
|
|
228
|
+
global _daytona_cached, _daytona_checked # pylint: disable=global-statement
|
|
229
|
+
|
|
230
|
+
if _daytona_checked:
|
|
231
|
+
if _daytona_cached is None:
|
|
232
|
+
raise ImportError("daytona is required for Daytona sandbox execution.")
|
|
233
|
+
return _daytona_cached
|
|
234
|
+
|
|
235
|
+
_daytona_checked = True
|
|
236
|
+
try:
|
|
237
|
+
from daytona import (
|
|
238
|
+
Daytona,
|
|
239
|
+
DaytonaConfig,
|
|
240
|
+
Sandbox,
|
|
241
|
+
CreateSandboxFromSnapshotParams,
|
|
242
|
+
)
|
|
243
|
+
except Exception as exc:
|
|
244
|
+
_daytona_cached = None
|
|
245
|
+
raise ImportError("daytona is required for Daytona sandbox execution.") from exc
|
|
246
|
+
|
|
247
|
+
_daytona_cached = (
|
|
248
|
+
Daytona,
|
|
249
|
+
DaytonaConfig,
|
|
250
|
+
Sandbox,
|
|
251
|
+
CreateSandboxFromSnapshotParams,
|
|
252
|
+
)
|
|
253
|
+
return _daytona_cached
|
agenta/sdk/workflows/builtin.py
CHANGED
|
@@ -166,11 +166,13 @@ def auto_custom_code_run(
|
|
|
166
166
|
#
|
|
167
167
|
correct_answer_key: Optional[str] = "correct_answer",
|
|
168
168
|
threshold: Optional[float] = 0.5,
|
|
169
|
+
runtime: Optional[str] = "python",
|
|
169
170
|
) -> Workflow:
|
|
170
171
|
parameters = dict(
|
|
171
172
|
code=code,
|
|
172
173
|
correct_answer_key=correct_answer_key,
|
|
173
174
|
threshold=threshold,
|
|
175
|
+
runtime=runtime,
|
|
174
176
|
)
|
|
175
177
|
|
|
176
178
|
return evaluator(
|
|
@@ -5,6 +5,7 @@ echo_v0_configuration = WorkflowServiceConfiguration()
|
|
|
5
5
|
auto_exact_match_v0_configuration = WorkflowServiceConfiguration()
|
|
6
6
|
auto_regex_test_v0_configuration = WorkflowServiceConfiguration()
|
|
7
7
|
field_match_test_v0_configuration = WorkflowServiceConfiguration()
|
|
8
|
+
json_multi_field_match_v0_configuration = WorkflowServiceConfiguration()
|
|
8
9
|
auto_webhook_test_v0_configuration = WorkflowServiceConfiguration()
|
|
9
10
|
auto_custom_code_run_v0_configuration = WorkflowServiceConfiguration()
|
|
10
11
|
auto_ai_critique_v0_configuration = WorkflowServiceConfiguration()
|