agenta 0.27.0__py3-none-any.whl → 0.27.0a1__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.

Files changed (68) hide show
  1. agenta/__init__.py +3 -22
  2. agenta/cli/helper.py +1 -5
  3. agenta/client/backend/__init__.py +0 -14
  4. agenta/client/backend/apps/client.py +20 -28
  5. agenta/client/backend/client.py +2 -25
  6. agenta/client/backend/containers/client.py +1 -5
  7. agenta/client/backend/core/__init__.py +1 -2
  8. agenta/client/backend/core/client_wrapper.py +6 -6
  9. agenta/client/backend/core/file.py +11 -33
  10. agenta/client/backend/core/http_client.py +18 -24
  11. agenta/client/backend/core/pydantic_utilities.py +29 -144
  12. agenta/client/backend/core/request_options.py +0 -3
  13. agenta/client/backend/core/serialization.py +42 -139
  14. agenta/client/backend/evaluations/client.py +2 -7
  15. agenta/client/backend/evaluators/client.py +1 -349
  16. agenta/client/backend/observability/client.py +2 -11
  17. agenta/client/backend/testsets/client.py +10 -10
  18. agenta/client/backend/types/__init__.py +0 -14
  19. agenta/client/backend/types/app.py +0 -1
  20. agenta/client/backend/types/app_variant_response.py +1 -3
  21. agenta/client/backend/types/create_span.py +2 -3
  22. agenta/client/backend/types/environment_output.py +0 -1
  23. agenta/client/backend/types/environment_output_extended.py +0 -1
  24. agenta/client/backend/types/evaluation.py +2 -1
  25. agenta/client/backend/types/evaluator.py +0 -2
  26. agenta/client/backend/types/evaluator_config.py +0 -1
  27. agenta/client/backend/types/human_evaluation.py +2 -1
  28. agenta/client/backend/types/llm_tokens.py +2 -2
  29. agenta/client/backend/types/span.py +0 -1
  30. agenta/client/backend/types/span_detail.py +1 -7
  31. agenta/client/backend/types/test_set_output_response.py +2 -5
  32. agenta/client/backend/types/trace_detail.py +1 -7
  33. agenta/client/backend/types/with_pagination.py +2 -4
  34. agenta/client/backend/variants/client.py +273 -1566
  35. agenta/docker/docker-assets/Dockerfile.cloud.template +1 -1
  36. agenta/sdk/__init__.py +5 -20
  37. agenta/sdk/agenta_init.py +26 -30
  38. agenta/sdk/config_manager.py +205 -0
  39. agenta/sdk/context/routing.py +5 -6
  40. agenta/sdk/decorators/routing.py +135 -142
  41. agenta/sdk/decorators/tracing.py +245 -206
  42. agenta/sdk/litellm/litellm.py +36 -47
  43. agenta/sdk/tracing/attributes.py +2 -7
  44. agenta/sdk/tracing/context.py +2 -5
  45. agenta/sdk/tracing/conventions.py +8 -10
  46. agenta/sdk/tracing/exporters.py +6 -15
  47. agenta/sdk/tracing/inline.py +98 -70
  48. agenta/sdk/tracing/processors.py +14 -55
  49. agenta/sdk/tracing/spans.py +4 -16
  50. agenta/sdk/tracing/tracing.py +50 -54
  51. agenta/sdk/types.py +2 -61
  52. agenta/sdk/utils/exceptions.py +1 -31
  53. {agenta-0.27.0.dist-info → agenta-0.27.0a1.dist-info}/METADATA +1 -1
  54. {agenta-0.27.0.dist-info → agenta-0.27.0a1.dist-info}/RECORD +56 -67
  55. agenta/client/backend/types/config_dto.py +0 -32
  56. agenta/client/backend/types/config_response_model.py +0 -32
  57. agenta/client/backend/types/evaluator_mapping_output_interface.py +0 -21
  58. agenta/client/backend/types/evaluator_output_interface.py +0 -21
  59. agenta/client/backend/types/lifecycle_dto.py +0 -24
  60. agenta/client/backend/types/reference_dto.py +0 -23
  61. agenta/client/backend/types/reference_request_model.py +0 -23
  62. agenta/sdk/managers/__init__.py +0 -6
  63. agenta/sdk/managers/config.py +0 -318
  64. agenta/sdk/managers/deployment.py +0 -45
  65. agenta/sdk/managers/shared.py +0 -639
  66. agenta/sdk/managers/variant.py +0 -182
  67. {agenta-0.27.0.dist-info → agenta-0.27.0a1.dist-info}/WHEEL +0 -0
  68. {agenta-0.27.0.dist-info → agenta-0.27.0a1.dist-info}/entry_points.txt +0 -0
@@ -1,4 +1,4 @@
1
- FROM public.ecr.aws/h3w6n5z0/agentaai/lambda_templates_public:main
1
+ FROM public.ecr.aws/s2t9a1r1/agentaai/lambda_templates_public:main
2
2
 
3
3
  COPY requirements.txt ${LAMBDA_TASK_ROOT}
4
4
  RUN pip install --no-cache-dir --disable-pip-version-check -U agenta
agenta/sdk/__init__.py CHANGED
@@ -1,9 +1,6 @@
1
1
  from typing import Optional
2
2
 
3
3
  from .utils.preinit import PreInitObject # always the first import!
4
-
5
- import agenta.client.backend.types as client_types # pylint: disable=wrong-import-order
6
-
7
4
  from .types import (
8
5
  DictInput,
9
6
  MultipleChoice,
@@ -16,7 +13,6 @@ from .types import (
16
13
  MessagesInput,
17
14
  FileInputURL,
18
15
  BinaryParam,
19
- Prompt,
20
16
  )
21
17
 
22
18
  from .tracing import Tracing, get_tracer
@@ -25,19 +21,12 @@ from .tracing.conventions import Reference
25
21
  from .decorators.routing import entrypoint, app, route
26
22
  from .agenta_init import Config, AgentaSingleton, init as _init
27
23
  from .utils.costs import calculate_token_usage
28
- from .managers.config import ConfigManager
29
- from .managers.variant import VariantManager
30
- from .managers.deployment import DeploymentManager
24
+ from .config_manager import ConfigManager
31
25
 
32
26
  config = PreInitObject("agenta.config", Config)
33
27
  DEFAULT_AGENTA_SINGLETON_INSTANCE = AgentaSingleton()
34
-
35
- types = client_types
36
-
37
- api = None
38
- async_api = None
39
-
40
28
  tracing = DEFAULT_AGENTA_SINGLETON_INSTANCE.tracing # type: ignore
29
+
41
30
  tracer = get_tracer(tracing)
42
31
 
43
32
 
@@ -47,18 +36,14 @@ def init(
47
36
  api_key: Optional[str] = None,
48
37
  config_fname: Optional[str] = None,
49
38
  ):
50
- global api, async_api, tracing, tracer
39
+ global tracing
40
+ global tracer
51
41
 
52
42
  _init(
53
43
  host=host,
44
+ app_id=app_id,
54
45
  api_key=api_key,
55
46
  config_fname=config_fname,
56
- # DEPRECATING
57
- app_id=app_id,
58
47
  )
59
48
 
60
- api = DEFAULT_AGENTA_SINGLETON_INSTANCE.api # type: ignore
61
- async_api = DEFAULT_AGENTA_SINGLETON_INSTANCE.async_api # type: ignore
62
-
63
- tracing = DEFAULT_AGENTA_SINGLETON_INSTANCE.tracing # type: ignore
64
49
  tracer = get_tracer(tracing)
agenta/sdk/agenta_init.py CHANGED
@@ -6,7 +6,7 @@ from importlib.metadata import version
6
6
 
7
7
  from agenta.sdk.utils.logging import log
8
8
  from agenta.sdk.utils.globals import set_global
9
- from agenta.client.backend.client import AgentaApi, AsyncAgentaApi
9
+ from agenta.client.backend.client import AgentaApi
10
10
  from agenta.sdk.tracing import Tracing
11
11
  from agenta.client.exceptions import APIRequestError
12
12
 
@@ -22,9 +22,6 @@ class AgentaSingleton:
22
22
  config = None
23
23
  tracing = None
24
24
 
25
- api = None
26
- async_api = None
27
-
28
25
  def __new__(cls):
29
26
  if not cls._instance:
30
27
  cls._instance = super(AgentaSingleton, cls).__new__(cls)
@@ -34,13 +31,17 @@ class AgentaSingleton:
34
31
  self,
35
32
  *,
36
33
  host: Optional[str] = None,
34
+ project_id: Optional[str] = None,
37
35
  api_key: Optional[str] = None,
38
36
  config_fname: Optional[str] = None,
39
- # DEPRECATING
37
+ #
40
38
  app_id: Optional[str] = None,
41
39
  ) -> None:
42
- """
43
- Main function to initialize the singleton.
40
+ log.info(f"---------------------------")
41
+ log.info(f"Agenta SDK - using version: {version('agenta')}")
42
+ log.info(f"---------------------------")
43
+
44
+ """Main function to initialize the singleton.
44
45
 
45
46
  Initializes the singleton with the given `app_id`, `host`, and `api_key`. The order of precedence for these variables is:
46
47
  1. Explicit argument provided in the function call.
@@ -62,10 +63,6 @@ class AgentaSingleton:
62
63
  ValueError: If `app_id` is not specified either as an argument, in the config file, or in the environment variables.
63
64
  """
64
65
 
65
- log.info("---------------------------")
66
- log.info("Agenta SDK - using version: %s", version("agenta"))
67
- log.info("---------------------------")
68
-
69
66
  config = {}
70
67
  if config_fname:
71
68
  config = toml.load(config_fname)
@@ -79,38 +76,35 @@ class AgentaSingleton:
79
76
  )
80
77
 
81
78
  self.app_id = app_id or config.get("app_id") or os.environ.get("AGENTA_APP_ID")
82
- # if not self.app_id:
83
- # raise ValueError(
84
- # "App ID must be specified. You can provide it in one of the following ways:\n"
85
- # "1. As an argument when calling ag.init(app_id='your_app_id').\n"
86
- # "2. In the configuration file specified by config_fname.\n"
87
- # "3. As an environment variable 'AGENTA_APP_ID'."
88
- # )
79
+ if not self.app_id:
80
+ raise ValueError(
81
+ "App ID must be specified. You can provide it in one of the following ways:\n"
82
+ "1. As an argument when calling ag.init(app_id='your_app_id').\n"
83
+ "2. In the configuration file specified by config_fname.\n"
84
+ "3. As an environment variable 'AGENTA_APP_ID'."
85
+ )
86
+
87
+ self.project_id = (
88
+ project_id
89
+ or os.environ.get("AGENTA_PROJECT_ID")
90
+ or config.get("project_id")
91
+ )
89
92
 
90
93
  self.api_key = (
91
94
  api_key or os.environ.get("AGENTA_API_KEY") or config.get("api_key")
92
95
  )
93
96
 
94
97
  self.tracing = Tracing(
95
- url=f"{self.host}/api/observability/v1/otlp/traces", # type: ignore
98
+ url=f"{self.host}/api/observability/v1/traces", # type: ignore
96
99
  )
97
100
 
98
101
  self.tracing.configure(
102
+ project_id=self.project_id,
99
103
  api_key=self.api_key,
100
- # DEPRECATING
104
+ # DEPRECATED
101
105
  app_id=self.app_id,
102
106
  )
103
107
 
104
- self.api = AgentaApi(
105
- base_url=self.host + "/api",
106
- api_key=api_key if api_key else "",
107
- )
108
-
109
- self.async_api = AsyncAgentaApi(
110
- base_url=self.host + "/api",
111
- api_key=api_key if api_key else "",
112
- )
113
-
114
108
  self.base_id = os.environ.get("AGENTA_BASE_ID")
115
109
 
116
110
  self.config = Config(
@@ -258,6 +252,7 @@ class Config:
258
252
 
259
253
  def init(
260
254
  host: Optional[str] = None,
255
+ project_id: Optional[str] = None,
261
256
  api_key: Optional[str] = None,
262
257
  config_fname: Optional[str] = None,
263
258
  # DEPRECATED
@@ -289,6 +284,7 @@ def init(
289
284
 
290
285
  singleton.init(
291
286
  host=host,
287
+ project_id=project_id,
292
288
  api_key=api_key,
293
289
  config_fname=config_fname,
294
290
  # DEPRECATED
@@ -0,0 +1,205 @@
1
+ import json
2
+ import logging
3
+ from pathlib import Path
4
+ from typing import Optional, Type, TypeVar
5
+
6
+ import yaml
7
+ from pydantic import BaseModel, ValidationError
8
+
9
+ from agenta.client.backend.client import AgentaApi
10
+ from agenta.sdk.context.routing import routing_context
11
+
12
+ from . import AgentaSingleton
13
+
14
+ T = TypeVar("T", bound=BaseModel)
15
+
16
+ logger = logging.getLogger(__name__)
17
+ singleton = AgentaSingleton()
18
+
19
+ AVAILABLE_ENVIRONMENTS = ["development", "production", "staging"]
20
+
21
+
22
+ class ConfigManager:
23
+ client = None
24
+
25
+ @staticmethod
26
+ def get_from_route(schema: Type[T]) -> T:
27
+ """
28
+ Retrieves the configuration from the route context and returns a config object.
29
+
30
+ This method checks the route context for configuration information and returns
31
+ an instance of the specified schema based on the available context data.
32
+
33
+ Args:
34
+ schema (Type[T]): A Pydantic model class that defines the structure of the configuration.
35
+
36
+ Returns:
37
+ T: An instance of the specified schema populated with the configuration data.
38
+
39
+ Raises:
40
+ ValueError: If conflicting configuration sources are provided or if no valid
41
+ configuration source is found in the context.
42
+
43
+ Note:
44
+ The method prioritizes the inputs in the following way:
45
+ 1. 'config' (i.e. when called explicitly from the playground)
46
+ 2. 'environment'
47
+ 3. 'variant'
48
+ Only one of these should be provided.
49
+ """
50
+ context = routing_context.get()
51
+ if ("config" in context and context["config"]) and (
52
+ ("environment" in context and context["environment"])
53
+ or ("variant" in context and context["variant"])
54
+ ):
55
+ raise ValueError(
56
+ "Either config, environment or variant must be provided. Not both."
57
+ )
58
+ if "config" in context and context["config"]:
59
+ return schema(**context["config"])
60
+ elif "environment" in context and context["environment"]:
61
+ return ConfigManager.get_from_registry(
62
+ schema, environment=context["environment"]
63
+ )
64
+ elif "variant" in context and context["variant"]:
65
+ return ConfigManager.get_from_registry(schema, variant=context["variant"])
66
+ else:
67
+ raise ValueError("Either config, environment or variant must be provided")
68
+
69
+ @staticmethod
70
+ def get_from_registry(
71
+ schema: Type[T],
72
+ environment: Optional[str] = None,
73
+ version: Optional[str] = None,
74
+ variant: Optional[str] = None,
75
+ ) -> T:
76
+ """
77
+ Pulls the parameters for the app variant from the server and returns a config object.
78
+
79
+ This method retrieves the configuration from the backend server based on the provided
80
+ environment or variant. It then validates and returns the configuration as an instance
81
+ of the specified schema.
82
+
83
+ Args:
84
+ schema (Type[T]): A Pydantic model class that defines the structure of the configuration.
85
+ environment (Optional[str]): The environment name to fetch the configuration for.
86
+ Must be one of "development", "production", or "staging".
87
+ version (Optional[str]): Currently not implemented. Will raise NotImplementedError if provided.
88
+ variant (Optional[str]): The variant name to fetch the configuration for.
89
+
90
+ Returns:
91
+ T: An instance of the specified schema populated with the configuration data.
92
+
93
+ Raises:
94
+ ValueError: If neither environment nor variant is provided.
95
+ NotImplementedError: If a specific version is requested (not yet implemented).
96
+ ValidationError: If the retrieved configuration data doesn't match the schema.
97
+ Exception: For any other errors during the process (e.g., API communication issues).
98
+
99
+ Note:
100
+ Either environment or variant must be provided, but not both.
101
+ """
102
+ if not ConfigManager.client:
103
+ try:
104
+ ConfigManager.client = AgentaApi(
105
+ base_url=singleton.host + "/api",
106
+ api_key=singleton.api_key if singleton.api_key else "",
107
+ )
108
+ except Exception as ex:
109
+ logger.error(
110
+ "Failed to initialize Agenta client with error: %s", str(ex)
111
+ )
112
+ raise
113
+ if not environment and not variant:
114
+ raise ValueError("Either environment or variant must be provided")
115
+ try:
116
+ if environment:
117
+ if version:
118
+ raise NotImplementedError(
119
+ "Getting config for a specific version is not implemented yet."
120
+ )
121
+ else:
122
+ assert (
123
+ environment in AVAILABLE_ENVIRONMENTS
124
+ ), f"Environment must be in {AVAILABLE_ENVIRONMENTS}"
125
+ config = ConfigManager.client.configs.get_config(
126
+ base_id=singleton.base_id, environment_name=environment
127
+ )
128
+ elif variant:
129
+ config = ConfigManager.client.configs.get_config(
130
+ base_id=singleton.base_id, config_name=variant
131
+ )
132
+ except Exception as ex:
133
+ logger.error(
134
+ "Failed to pull the configuration from the server with error: %s",
135
+ str(ex),
136
+ )
137
+
138
+ try:
139
+ result = schema(**config.parameters)
140
+ except ValidationError as ex:
141
+ logger.error("Failed to validate the configuration with error: %s", str(ex))
142
+ raise
143
+ return result
144
+
145
+ @staticmethod
146
+ def get_from_yaml(filename: str, schema: Type[T]) -> T:
147
+ """
148
+ Loads configuration from a YAML file and returns a config object.
149
+
150
+ Args:
151
+ filename (str): The name of the YAML file to load.
152
+ schema (Type[T]): A Pydantic model class that defines the structure of the configuration.
153
+
154
+ Returns:
155
+ T: An instance of the specified schema populated with the configuration data.
156
+
157
+ Raises:
158
+ FileNotFoundError: If the specified file doesn't exist.
159
+ ValidationError: If the loaded configuration data doesn't match the schema.
160
+ """
161
+ file_path = Path(filename)
162
+ if not file_path.exists():
163
+ raise FileNotFoundError(f"Config file not found: {filename}")
164
+
165
+ with open(file_path, "r") as file:
166
+ config_data = yaml.safe_load(file)
167
+
168
+ try:
169
+ return schema(**config_data)
170
+ except ValidationError as ex:
171
+ logger.error(
172
+ f"Failed to validate the configuration from {filename} with error: {str(ex)}"
173
+ )
174
+ raise
175
+
176
+ @staticmethod
177
+ def get_from_json(filename: str, schema: Type[T]) -> T:
178
+ """
179
+ Loads configuration from a JSON file and returns a config object.
180
+
181
+ Args:
182
+ filename (str): The name of the JSON file to load.
183
+ schema (Type[T]): A Pydantic model class that defines the structure of the configuration.
184
+
185
+ Returns:
186
+ T: An instance of the specified schema populated with the configuration data.
187
+
188
+ Raises:
189
+ FileNotFoundError: If the specified file doesn't exist.
190
+ ValidationError: If the loaded configuration data doesn't match the schema.
191
+ """
192
+ file_path = Path(filename)
193
+ if not file_path.exists():
194
+ raise FileNotFoundError(f"Config file not found: {filename}")
195
+
196
+ with open(file_path, "r") as file:
197
+ config_data = json.load(file)
198
+
199
+ try:
200
+ return schema(**config_data)
201
+ except ValidationError as ex:
202
+ logger.error(
203
+ f"Failed to validate the configuration from {filename} with error: {str(ex)}"
204
+ )
205
+ raise
@@ -7,17 +7,16 @@ routing_context = ContextVar("routing_context", default={})
7
7
 
8
8
  @contextmanager
9
9
  def routing_context_manager(
10
- *,
11
10
  config: Optional[Dict[str, Any]] = None,
12
- application: Optional[Dict[str, Any]] = None,
13
- variant: Optional[Dict[str, Any]] = None,
14
- environment: Optional[Dict[str, Any]] = None,
11
+ environment: Optional[str] = None,
12
+ version: Optional[str] = None,
13
+ variant: Optional[str] = None,
15
14
  ):
16
15
  context = {
17
16
  "config": config,
18
- "application": application,
19
- "variant": variant,
20
17
  "environment": environment,
18
+ "version": version,
19
+ "variant": variant,
21
20
  }
22
21
  token = routing_context.set(context)
23
22
  try: