agenta 0.26.0__py3-none-any.whl → 0.27.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.

Potentially problematic release.


This version of agenta might be problematic. Click here for more details.

Files changed (85) hide show
  1. agenta/__init__.py +29 -10
  2. agenta/cli/helper.py +5 -1
  3. agenta/client/backend/__init__.py +14 -0
  4. agenta/client/backend/apps/client.py +28 -20
  5. agenta/client/backend/client.py +47 -16
  6. agenta/client/backend/containers/client.py +5 -1
  7. agenta/client/backend/core/__init__.py +2 -1
  8. agenta/client/backend/core/client_wrapper.py +6 -6
  9. agenta/client/backend/core/file.py +33 -11
  10. agenta/client/backend/core/http_client.py +45 -31
  11. agenta/client/backend/core/pydantic_utilities.py +144 -29
  12. agenta/client/backend/core/request_options.py +3 -0
  13. agenta/client/backend/core/serialization.py +139 -42
  14. agenta/client/backend/evaluations/client.py +7 -2
  15. agenta/client/backend/evaluators/client.py +349 -1
  16. agenta/client/backend/observability/client.py +11 -2
  17. agenta/client/backend/testsets/client.py +10 -10
  18. agenta/client/backend/types/__init__.py +14 -0
  19. agenta/client/backend/types/app.py +1 -0
  20. agenta/client/backend/types/app_variant_response.py +3 -1
  21. agenta/client/backend/types/config_dto.py +32 -0
  22. agenta/client/backend/types/config_response_model.py +32 -0
  23. agenta/client/backend/types/create_span.py +3 -2
  24. agenta/client/backend/types/environment_output.py +1 -0
  25. agenta/client/backend/types/environment_output_extended.py +1 -0
  26. agenta/client/backend/types/evaluation.py +1 -2
  27. agenta/client/backend/types/evaluator.py +2 -0
  28. agenta/client/backend/types/evaluator_config.py +1 -0
  29. agenta/client/backend/types/evaluator_mapping_output_interface.py +21 -0
  30. agenta/client/backend/types/evaluator_output_interface.py +21 -0
  31. agenta/client/backend/types/human_evaluation.py +1 -2
  32. agenta/client/backend/types/lifecycle_dto.py +24 -0
  33. agenta/client/backend/types/llm_tokens.py +2 -2
  34. agenta/client/backend/types/reference_dto.py +23 -0
  35. agenta/client/backend/types/reference_request_model.py +23 -0
  36. agenta/client/backend/types/span.py +1 -0
  37. agenta/client/backend/types/span_detail.py +7 -1
  38. agenta/client/backend/types/test_set_output_response.py +5 -2
  39. agenta/client/backend/types/trace_detail.py +7 -1
  40. agenta/client/backend/types/with_pagination.py +4 -2
  41. agenta/client/backend/variants/client.py +1565 -272
  42. agenta/docker/docker-assets/Dockerfile.cloud.template +1 -1
  43. agenta/sdk/__init__.py +44 -7
  44. agenta/sdk/agenta_init.py +85 -33
  45. agenta/sdk/context/__init__.py +0 -0
  46. agenta/sdk/context/routing.py +26 -0
  47. agenta/sdk/context/tracing.py +3 -0
  48. agenta/sdk/decorators/__init__.py +0 -0
  49. agenta/sdk/decorators/{llm_entrypoint.py → routing.py} +216 -191
  50. agenta/sdk/decorators/tracing.py +218 -99
  51. agenta/sdk/litellm/__init__.py +1 -0
  52. agenta/sdk/litellm/litellm.py +288 -0
  53. agenta/sdk/managers/__init__.py +6 -0
  54. agenta/sdk/managers/config.py +318 -0
  55. agenta/sdk/managers/deployment.py +45 -0
  56. agenta/sdk/managers/shared.py +639 -0
  57. agenta/sdk/managers/variant.py +182 -0
  58. agenta/sdk/router.py +0 -7
  59. agenta/sdk/tracing/__init__.py +1 -0
  60. agenta/sdk/tracing/attributes.py +141 -0
  61. agenta/sdk/tracing/context.py +24 -0
  62. agenta/sdk/tracing/conventions.py +49 -0
  63. agenta/sdk/tracing/exporters.py +65 -0
  64. agenta/sdk/tracing/inline.py +1252 -0
  65. agenta/sdk/tracing/processors.py +117 -0
  66. agenta/sdk/tracing/spans.py +136 -0
  67. agenta/sdk/tracing/tracing.py +233 -0
  68. agenta/sdk/types.py +49 -2
  69. agenta/sdk/utils/{helper/openai_cost.py → costs.py} +3 -0
  70. agenta/sdk/utils/debug.py +5 -5
  71. agenta/sdk/utils/exceptions.py +52 -0
  72. agenta/sdk/utils/globals.py +3 -5
  73. agenta/sdk/{tracing/logger.py → utils/logging.py} +3 -5
  74. agenta/sdk/utils/singleton.py +13 -0
  75. {agenta-0.26.0.dist-info → agenta-0.27.0.dist-info}/METADATA +5 -1
  76. {agenta-0.26.0.dist-info → agenta-0.27.0.dist-info}/RECORD +78 -57
  77. agenta/sdk/config_manager.py +0 -205
  78. agenta/sdk/context.py +0 -41
  79. agenta/sdk/decorators/base.py +0 -10
  80. agenta/sdk/tracing/callbacks.py +0 -187
  81. agenta/sdk/tracing/llm_tracing.py +0 -617
  82. agenta/sdk/tracing/tasks_manager.py +0 -129
  83. agenta/sdk/tracing/tracing_context.py +0 -27
  84. {agenta-0.26.0.dist-info → agenta-0.27.0.dist-info}/WHEEL +0 -0
  85. {agenta-0.26.0.dist-info → agenta-0.27.0.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,117 @@
1
+ from typing import Optional, Dict, List
2
+
3
+ from opentelemetry.context import Context
4
+ from opentelemetry.sdk.trace import Span
5
+ from opentelemetry.sdk.trace.export import (
6
+ SpanExporter,
7
+ ReadableSpan,
8
+ BatchSpanProcessor,
9
+ _DEFAULT_MAX_QUEUE_SIZE,
10
+ _DEFAULT_MAX_EXPORT_BATCH_SIZE,
11
+ )
12
+
13
+ from agenta.sdk.utils.logging import log
14
+
15
+ # LOAD CONTEXT, HERE
16
+
17
+
18
+ class TraceProcessor(BatchSpanProcessor):
19
+ def __init__(
20
+ self,
21
+ span_exporter: SpanExporter,
22
+ references: Dict[str, str] = None,
23
+ max_queue_size: int = None,
24
+ schedule_delay_millis: float = None,
25
+ max_export_batch_size: int = None,
26
+ export_timeout_millis: float = None,
27
+ ):
28
+ super().__init__(
29
+ span_exporter,
30
+ _DEFAULT_MAX_QUEUE_SIZE,
31
+ 12 * 60 * 60 * 1000, # 12 hours
32
+ _DEFAULT_MAX_EXPORT_BATCH_SIZE,
33
+ 500, # < 1 second (0.5 seconds)
34
+ )
35
+
36
+ self._registry = dict()
37
+ self._exporter = span_exporter
38
+ self.references = references or dict()
39
+ self.spans: Dict[int, List[ReadableSpan]] = dict()
40
+
41
+ def on_start(
42
+ self,
43
+ span: Span,
44
+ parent_context: Optional[Context] = None,
45
+ ) -> None:
46
+ # ADD LINKS FROM CONTEXT, HERE
47
+
48
+ for key in self.references.keys():
49
+ span.set_attribute(f"ag.refs.{key}", self.references[key])
50
+
51
+ if span.context.trace_id not in self._registry:
52
+ self._registry[span.context.trace_id] = dict()
53
+
54
+ self._registry[span.context.trace_id][span.context.span_id] = True
55
+
56
+ def on_end(
57
+ self,
58
+ span: ReadableSpan,
59
+ ):
60
+ if self.done:
61
+ return
62
+
63
+ if span.context.trace_id not in self.spans:
64
+ self.spans[span.context.trace_id] = list()
65
+
66
+ self.spans[span.context.trace_id].append(span)
67
+
68
+ del self._registry[span.context.trace_id][span.context.span_id]
69
+
70
+ if len(self._registry[span.context.trace_id]) == 0:
71
+ self.export(span.context.trace_id)
72
+
73
+ def export(
74
+ self,
75
+ trace_id: int,
76
+ ):
77
+ spans = self.spans[trace_id]
78
+
79
+ for span in spans:
80
+ self.queue.appendleft(span)
81
+
82
+ with self.condition:
83
+ self.condition.notify()
84
+
85
+ del self.spans[trace_id]
86
+
87
+ def force_flush(
88
+ self,
89
+ timeout_millis: int = None,
90
+ ) -> bool:
91
+ ret = super().force_flush(timeout_millis)
92
+
93
+ if not ret:
94
+ log.error("--------------------------------------------")
95
+ log.error("Agenta SDK - skipping export due to timeout.")
96
+ log.error("--------------------------------------------")
97
+
98
+ def is_ready(
99
+ self,
100
+ trace_id: Optional[int] = None,
101
+ ) -> bool:
102
+ is_ready = True
103
+
104
+ try:
105
+ is_ready = self._exporter.is_ready(trace_id)
106
+ except: # pylint: disable=bare-except
107
+ pass
108
+
109
+ return is_ready
110
+
111
+ def fetch(
112
+ self,
113
+ trace_id: Optional[int] = None,
114
+ ) -> Dict[str, ReadableSpan]:
115
+ trace = self._exporter.fetch(trace_id) # type: ignore
116
+
117
+ return trace
@@ -0,0 +1,136 @@
1
+ from typing import Optional, Union, Any, Dict
2
+
3
+ from opentelemetry.trace import SpanContext
4
+ from opentelemetry.trace.status import Status, StatusCode
5
+ from opentelemetry.sdk.trace import Span
6
+
7
+ from agenta.sdk.tracing.attributes import serialize
8
+
9
+
10
+ class CustomSpan(Span): # INHERITANCE FOR TYPING ONLY
11
+ def __init__(
12
+ self,
13
+ span: Span,
14
+ ) -> None:
15
+ super().__init__( # INHERITANCE FOR TYPING ONLY
16
+ name=span.name,
17
+ context=span.context,
18
+ parent=span.parent,
19
+ sampler=span._sampler,
20
+ trace_config=span._trace_config,
21
+ resource=span.resource,
22
+ attributes=span.attributes,
23
+ events=span.events,
24
+ links=span.links,
25
+ kind=span.kind,
26
+ span_processor=span._span_processor,
27
+ instrumentation_info=span.instrumentation_info,
28
+ record_exception=span._record_exception,
29
+ set_status_on_exception=span._set_status_on_exception,
30
+ limits=span._limits,
31
+ instrumentation_scope=span.instrumentation_scope,
32
+ )
33
+
34
+ self._span = span
35
+
36
+ ## --- PROXY METHODS --- ##
37
+
38
+ def get_span_context(self):
39
+ return self._span.get_span_context()
40
+
41
+ def is_recording(self) -> bool:
42
+ return self._span.is_recording()
43
+
44
+ def update_name(
45
+ self,
46
+ name: str,
47
+ ) -> None:
48
+ self._span.update_name(name)
49
+
50
+ def set_status(
51
+ self,
52
+ status: Union[Status, StatusCode],
53
+ description: Optional[str] = None,
54
+ ) -> None:
55
+ self._span.set_status(
56
+ status=status,
57
+ description=description,
58
+ )
59
+
60
+ def end(self) -> None:
61
+ self._span.end()
62
+
63
+ ## --- CUSTOM METHODS W/ ATTRIBUTES SERALIZATION --- ##
64
+
65
+ def set_attributes(
66
+ self,
67
+ attributes: Dict[str, Any],
68
+ namespace: Optional[str] = None,
69
+ max_depth: Optional[int] = None,
70
+ ) -> None:
71
+ self._span.set_attributes(
72
+ attributes=serialize(
73
+ namespace=namespace,
74
+ attributes=attributes,
75
+ max_depth=max_depth,
76
+ )
77
+ )
78
+
79
+ def set_attribute(
80
+ self,
81
+ key: str,
82
+ value: Any,
83
+ namespace: Optional[str] = None,
84
+ ) -> None:
85
+ self.set_attributes(
86
+ attributes={key: value},
87
+ namespace=namespace,
88
+ )
89
+
90
+ def add_event(
91
+ self,
92
+ name: str,
93
+ attributes: Optional[Dict[str, Any]] = None,
94
+ timestamp: Optional[int] = None,
95
+ namespace: Optional[str] = None,
96
+ ) -> None:
97
+ self._span.add_event(
98
+ name=name,
99
+ attributes=serialize(
100
+ namespace=namespace,
101
+ attributes=attributes,
102
+ ),
103
+ timestamp=timestamp,
104
+ )
105
+
106
+ def add_link(
107
+ self,
108
+ context: SpanContext,
109
+ attributes: Optional[Dict[str, Any]] = None,
110
+ namespace: Optional[str] = None,
111
+ ) -> None:
112
+ self._span.add_link(
113
+ context=context,
114
+ attributes=serialize(
115
+ namespace=namespace,
116
+ attributes=attributes,
117
+ ),
118
+ )
119
+
120
+ def record_exception(
121
+ self,
122
+ exception: BaseException,
123
+ attributes: Optional[Dict[str, Any]] = None,
124
+ timestamp: Optional[int] = None,
125
+ escaped: bool = False,
126
+ namespace: Optional[str] = None,
127
+ ) -> None:
128
+ self._span.record_exception(
129
+ exception=exception,
130
+ attributes=serialize(
131
+ namespace=namespace,
132
+ attributes=attributes,
133
+ ),
134
+ timestamp=timestamp,
135
+ escaped=escaped,
136
+ )
@@ -0,0 +1,233 @@
1
+ from typing import Optional, Any, Dict
2
+ from enum import Enum
3
+
4
+ from httpx import get as check
5
+
6
+ from opentelemetry.trace import (
7
+ get_current_span,
8
+ set_tracer_provider,
9
+ get_tracer_provider,
10
+ Status,
11
+ StatusCode,
12
+ )
13
+ from opentelemetry.sdk.trace import Span, Tracer, TracerProvider
14
+ from opentelemetry.sdk.resources import Resource
15
+
16
+ from agenta.sdk.utils.singleton import Singleton
17
+ from agenta.sdk.utils.exceptions import suppress
18
+ from agenta.sdk.utils.logging import log
19
+ from agenta.sdk.tracing.processors import TraceProcessor
20
+ from agenta.sdk.tracing.exporters import InlineExporter, OTLPExporter
21
+ from agenta.sdk.tracing.spans import CustomSpan
22
+ from agenta.sdk.tracing.inline import parse_inline_trace
23
+ from agenta.sdk.tracing.conventions import Reference, is_valid_attribute_key
24
+
25
+
26
+ class Tracing(metaclass=Singleton):
27
+ VERSION = "0.1.0"
28
+
29
+ Status = Status
30
+ StatusCode = StatusCode
31
+
32
+ def __init__(
33
+ self,
34
+ url: str,
35
+ ) -> None:
36
+ # ENDPOINT (OTLP)
37
+ self.otlp_url = url
38
+ # HEADERS (OTLP)
39
+ self.headers: Dict[str, str] = dict()
40
+ # REFERENCES
41
+ self.references: Dict[str, str] = dict()
42
+
43
+ # TRACER PROVIDER
44
+ self.tracer_provider: Optional[TracerProvider] = None
45
+ # TRACE PROCESSORS -- INLINE
46
+ self.inline: Optional[TraceProcessor] = None
47
+ # TRACER
48
+ self.tracer: Optional[Tracer] = None
49
+ # INLINE SPANS for INLINE TRACES (INLINE PROCESSOR)
50
+ self.inline_spans: Dict[str, Any] = dict()
51
+
52
+ # PUBLIC
53
+
54
+ def configure(
55
+ self,
56
+ api_key: Optional[str] = None,
57
+ # DEPRECATING
58
+ app_id: Optional[str] = None,
59
+ ):
60
+ # HEADERS (OTLP)
61
+ if api_key:
62
+ self.headers["Authorization"] = api_key
63
+ # REFERENCES
64
+ if app_id:
65
+ self.references["application.id"] = app_id
66
+
67
+ # TRACER PROVIDER
68
+ self.tracer_provider = TracerProvider(
69
+ resource=Resource(attributes={"service.name": "agenta-sdk"})
70
+ )
71
+ # TRACE PROCESSORS -- INLINE
72
+ self.inline = TraceProcessor(
73
+ InlineExporter(
74
+ registry=self.inline_spans,
75
+ ),
76
+ references=self.references,
77
+ )
78
+ self.tracer_provider.add_span_processor(self.inline)
79
+ # TRACE PROCESSORS -- OTLP
80
+ try:
81
+ log.info("--------------------------------------------")
82
+ log.info(
83
+ "Agenta SDK - connecting to otlp receiver at: %s",
84
+ self.otlp_url,
85
+ )
86
+ log.info("--------------------------------------------")
87
+
88
+ check(
89
+ self.otlp_url,
90
+ headers=self.headers,
91
+ timeout=1,
92
+ )
93
+
94
+ _otlp = TraceProcessor(
95
+ OTLPExporter(
96
+ endpoint=self.otlp_url,
97
+ headers=self.headers,
98
+ ),
99
+ references=self.references,
100
+ )
101
+
102
+ self.tracer_provider.add_span_processor(_otlp)
103
+
104
+ log.info("Success: traces will be exported.")
105
+ log.info("--------------------------------------------")
106
+
107
+ except: # pylint: disable=bare-except
108
+ log.warning("Failure: traces will not be exported.")
109
+ log.warning("--------------------------------------------")
110
+
111
+ # GLOBAL TRACER PROVIDER -- INSTRUMENTATION LIBRARIES
112
+ set_tracer_provider(self.tracer_provider)
113
+ # TRACER
114
+ self.tracer: Tracer = self.tracer_provider.get_tracer("agenta.tracer")
115
+
116
+ def get_current_span(self):
117
+ _span = None
118
+
119
+ with suppress():
120
+ _span = get_current_span()
121
+
122
+ if _span.is_recording():
123
+ return CustomSpan(_span)
124
+
125
+ return _span
126
+
127
+ def store_internals(
128
+ self,
129
+ attributes: Dict[str, Any],
130
+ span: Optional[Span] = None,
131
+ ):
132
+ with suppress():
133
+ if span is None:
134
+ span = self.get_current_span()
135
+
136
+ span.set_attributes(
137
+ attributes={"internals": attributes},
138
+ namespace="data",
139
+ )
140
+
141
+ def store_refs(
142
+ self,
143
+ refs: Dict[str, str],
144
+ span: Optional[Span] = None,
145
+ ):
146
+ with suppress():
147
+ if span is None:
148
+ span = self.get_current_span()
149
+
150
+ for key in refs.keys():
151
+ if key in [_.value for _ in Reference.__members__.values()]:
152
+ # ADD REFERENCE TO THIS SPAN
153
+ span.set_attribute(
154
+ key.value if isinstance(key, Enum) else key,
155
+ refs[key],
156
+ namespace="refs",
157
+ )
158
+
159
+ # AND TO ALL SPANS CREATED AFTER THIS ONE
160
+ self.references[key] = refs[key]
161
+ # TODO: THIS SHOULD BE REPLACED BY A TRACE CONTEXT !!!
162
+
163
+ def store_meta(
164
+ self,
165
+ meta: Dict[str, Any],
166
+ span: Optional[Span] = None,
167
+ ):
168
+ with suppress():
169
+ if span is None:
170
+ span = self.get_current_span()
171
+
172
+ for key in meta.keys():
173
+ if is_valid_attribute_key(key):
174
+ span.set_attribute(
175
+ key,
176
+ meta[key],
177
+ namespace="meta",
178
+ )
179
+
180
+ def store_metrics(
181
+ self,
182
+ metrics: Dict[str, Any],
183
+ span: Optional[Span] = None,
184
+ ):
185
+ with suppress():
186
+ if span is None:
187
+ span = self.get_current_span()
188
+
189
+ for key in metrics.keys():
190
+ if is_valid_attribute_key(key):
191
+ span.set_attribute(
192
+ key,
193
+ metrics[key],
194
+ namespace="metrics",
195
+ )
196
+
197
+ def is_inline_trace_ready(
198
+ self,
199
+ trace_id: Optional[int] = None,
200
+ ) -> bool:
201
+ is_ready = True
202
+
203
+ with suppress():
204
+ if trace_id is not None:
205
+ is_ready = self.inline.is_ready(trace_id)
206
+
207
+ return is_ready
208
+
209
+ def get_inline_trace(
210
+ self,
211
+ trace_id: Optional[int] = None,
212
+ ) -> Dict[str, Any]:
213
+ _inline_trace = {}
214
+
215
+ with suppress():
216
+ is_ready = self.inline.is_ready(trace_id)
217
+
218
+ if is_ready is True:
219
+ otel_spans = self.inline.fetch(trace_id)
220
+
221
+ if otel_spans:
222
+ _inline_trace = parse_inline_trace(otel_spans)
223
+
224
+ return _inline_trace
225
+
226
+
227
+ def get_tracer(
228
+ tracing: Tracing,
229
+ ) -> Tracer:
230
+ if tracing is None or tracing.tracer is None or tracing.tracer_provider is None:
231
+ return get_tracer_provider().get_tracer("default.tracer")
232
+
233
+ return tracing.tracer
agenta/sdk/types.py CHANGED
@@ -1,9 +1,8 @@
1
1
  import json
2
+ from dataclasses import dataclass
2
3
  from typing import Dict, List, Optional, Any, Union
3
4
 
4
5
  from pydantic import ConfigDict, BaseModel, HttpUrl
5
- from dataclasses import dataclass
6
- from typing import Union
7
6
 
8
7
 
9
8
  @dataclass
@@ -198,3 +197,51 @@ class Context(BaseModel):
198
197
  def from_json(cls, json_str: str):
199
198
  data = json.loads(json_str)
200
199
  return cls(**data)
200
+
201
+
202
+ class ReferencesResponse(BaseModel):
203
+ app_id: Optional[str] = None
204
+ app_slug: Optional[str] = None
205
+ variant_id: Optional[str] = None
206
+ variant_slug: Optional[str] = None
207
+ variant_version: Optional[int] = None
208
+ environment_id: Optional[str] = None
209
+ environment_slug: Optional[str] = None
210
+ environment_version: Optional[int] = None
211
+
212
+ def __str__(self):
213
+ return str(self.model_dump(exclude_none=True))
214
+
215
+
216
+ class LifecyclesResponse(ReferencesResponse):
217
+ committed_at: Optional[str] = None
218
+ committed_by: Optional[str] = None
219
+ committed_by_id: Optional[str] = None
220
+ deployed_at: Optional[str] = None
221
+ deployed_by: Optional[str] = None
222
+ deployed_by_id: Optional[str] = None
223
+
224
+ def __str__(self):
225
+ return self.model_dump_json(indent=4)
226
+
227
+ def __repr__(self):
228
+ return self.__str__()
229
+
230
+
231
+ class ConfigurationResponse(LifecyclesResponse):
232
+ params: Dict[str, Any]
233
+
234
+
235
+ class DeploymentResponse(LifecyclesResponse):
236
+ pass
237
+
238
+
239
+ class Prompt(BaseModel):
240
+ temperature: float
241
+ model: str
242
+ max_tokens: int
243
+ prompt_system: str
244
+ prompt_user: str
245
+ top_p: float
246
+ frequency_penalty: float
247
+ presence_penalty: float
@@ -49,6 +49,9 @@ MODEL_COST_PER_1K_TOKENS = {
49
49
  "gpt-35-turbo-16k-completion": 0.004,
50
50
  "gpt-35-turbo-16k-0613-completion": 0.004,
51
51
  # Others
52
+ "text-embedding-ada-002": 0.1,
53
+ "text-ada-002": 0.1,
54
+ "adav2": 0.1,
52
55
  "text-ada-001": 0.0004,
53
56
  "ada": 0.0004,
54
57
  "text-babbage-001": 0.0005,
agenta/sdk/utils/debug.py CHANGED
@@ -1,7 +1,7 @@
1
1
  from inspect import iscoroutinefunction
2
2
  from functools import wraps
3
3
 
4
- from agenta.sdk.tracing.logger import llm_logger as logging
4
+ from agenta.sdk.utils.logging import log
5
5
 
6
6
  DEBUG = False
7
7
  SHIFT = 7
@@ -14,7 +14,7 @@ def debug(shift=1, req=False, res=False, chars=[">", "<"]):
14
14
  @wraps(f)
15
15
  async def async_log_wrapper(*args, **kwargs):
16
16
  if DEBUG:
17
- logging.debug(
17
+ log.debug(
18
18
  " ".join(
19
19
  [
20
20
  chars[0] * shift + " " * (SHIFT - shift),
@@ -26,7 +26,7 @@ def debug(shift=1, req=False, res=False, chars=[">", "<"]):
26
26
  )
27
27
  result = await f(*args, **kwargs)
28
28
  if DEBUG:
29
- logging.debug(
29
+ log.debug(
30
30
  " ".join(
31
31
  [
32
32
  chars[1] * shift + " " * (SHIFT - shift),
@@ -40,7 +40,7 @@ def debug(shift=1, req=False, res=False, chars=[">", "<"]):
40
40
  @wraps(f)
41
41
  def log_wrapper(*args, **kwargs):
42
42
  if DEBUG:
43
- logging.debug(
43
+ log.debug(
44
44
  " ".join(
45
45
  [
46
46
  chars[0] * shift + " " * (SHIFT - shift),
@@ -52,7 +52,7 @@ def debug(shift=1, req=False, res=False, chars=[">", "<"]):
52
52
  )
53
53
  result = f(*args, **kwargs)
54
54
  if DEBUG:
55
- logging.debug(
55
+ log.debug(
56
56
  " ".join(
57
57
  [
58
58
  chars[1] * shift + " " * (SHIFT - shift),
@@ -0,0 +1,52 @@
1
+ from contextlib import AbstractContextManager
2
+ from traceback import format_exc
3
+ from functools import wraps
4
+ from inspect import iscoroutinefunction
5
+
6
+ from agenta.sdk.utils.logging import log
7
+
8
+
9
+ class suppress(AbstractContextManager): # pylint: disable=invalid-name
10
+ def __init__(self):
11
+ pass
12
+
13
+ def __enter__(self):
14
+ pass
15
+
16
+ def __exit__(self, exc_type, exc_value, exc_tb):
17
+ if exc_type is None:
18
+ return True
19
+ else:
20
+ log.error("-------------------------------------------------")
21
+ log.error("Agenta SDK - suppressing tracing exception below:")
22
+ log.error("-------------------------------------------------")
23
+ log.error(format_exc().strip("\n"))
24
+ log.error("-------------------------------------------------")
25
+ return True
26
+
27
+
28
+ def handle_exceptions():
29
+ def decorator(func):
30
+ is_coroutine_function = iscoroutinefunction(func)
31
+
32
+ @wraps(func)
33
+ async def async_wrapper(*args, **kwargs):
34
+ try:
35
+ return await func(*args, **kwargs)
36
+ except Exception as e:
37
+ log.error("--- HANDLING EXCEPTION ---")
38
+ log.error("--------------------------")
39
+ raise e
40
+
41
+ @wraps(func)
42
+ def sync_wrapper(*args, **kwargs):
43
+ try:
44
+ return func(*args, **kwargs)
45
+ except Exception as e:
46
+ log.error("--- HANDLING EXCEPTION ---")
47
+ log.error("--------------------------")
48
+ raise e
49
+
50
+ return async_wrapper if is_coroutine_function else sync_wrapper
51
+
52
+ return decorator
@@ -1,15 +1,13 @@
1
1
  import agenta
2
2
 
3
3
 
4
- def set_global(setup=None, config=None, tracing=None):
5
- """Allows usage of agenta.config and agenta.setup in the user's code.
4
+ def set_global(config=None, tracing=None):
5
+ """Allows usage of agenta.config and agenta.tracing in the user's code.
6
6
 
7
7
  Args:
8
- setup: _description_. Defaults to None.
9
8
  config: _description_. Defaults to None.
9
+ tracing: _description_. Defaults to None.
10
10
  """
11
- if setup is not None:
12
- agenta.setup = setup
13
11
  if config is not None:
14
12
  agenta.config = config
15
13
  if tracing is not None:
@@ -1,12 +1,11 @@
1
1
  import logging
2
2
 
3
3
 
4
- class LLMLogger:
5
- def __init__(self, name="LLMLogger", level=logging.DEBUG):
4
+ class Logger:
5
+ def __init__(self, name="agenta.logger", level=logging.DEBUG):
6
6
  self.logger = logging.getLogger(name)
7
7
  self.logger.setLevel(level)
8
8
 
9
- # Add a stream logger to view the logs in the console
10
9
  console_handler = logging.StreamHandler()
11
10
  self.logger.addHandler(console_handler)
12
11
 
@@ -15,5 +14,4 @@ class LLMLogger:
15
14
  return self.logger
16
15
 
17
16
 
18
- # Initialize llm logger
19
- llm_logger = LLMLogger().log
17
+ log = Logger().log