agenta 0.51.2__py3-none-any.whl → 0.51.4__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.

@@ -1,8 +1,18 @@
1
1
  from typing import Callable, Optional, Any, Dict, List, Union
2
2
 
3
+ from opentelemetry import context as otel_context
4
+ from opentelemetry.context import attach, detach
5
+ from opentelemetry import trace
6
+
7
+
3
8
  from functools import wraps
4
9
  from itertools import chain
5
- from inspect import iscoroutinefunction, getfullargspec
10
+ from inspect import (
11
+ getfullargspec,
12
+ iscoroutinefunction,
13
+ isgeneratorfunction,
14
+ isasyncgenfunction,
15
+ )
6
16
 
7
17
  from opentelemetry import baggage
8
18
  from opentelemetry.context import attach, detach, get_current
@@ -31,6 +41,7 @@ class instrument: # pylint: disable=invalid-name
31
41
  redact: Optional[Callable[..., Any]] = None,
32
42
  redact_on_error: Optional[bool] = True,
33
43
  max_depth: Optional[int] = 2,
44
+ aggregate: Optional[Callable[[List[Any]], Any]] = None,
34
45
  # DEPRECATING
35
46
  kind: str = "task",
36
47
  spankind: Optional[str] = "TASK",
@@ -43,67 +54,213 @@ class instrument: # pylint: disable=invalid-name
43
54
  self.redact = redact
44
55
  self.redact_on_error = redact_on_error
45
56
  self.max_depth = max_depth
57
+ self.aggregate = aggregate
46
58
 
47
59
  def __call__(self, func: Callable[..., Any]):
48
60
  is_coroutine_function = iscoroutinefunction(func)
61
+ is_sync_generator = isgeneratorfunction(func)
62
+ is_async_generator = isasyncgenfunction(func)
49
63
 
50
- @wraps(func)
51
- async def awrapper(*args, **kwargs):
52
- async def aauto_instrumented(*args, **kwargs):
64
+ # ---- ASYNC GENERATOR ----
65
+ if is_async_generator:
66
+
67
+ @wraps(func)
68
+ def astream_wrapper(*args, **kwargs):
53
69
  self._parse_type_and_kind()
54
70
 
55
- token = self._attach_baggage()
71
+ captured_ctx = otel_context.get_current()
72
+ parent_ctx = trace.set_span_in_context(trace.get_current_span())
56
73
 
74
+ token = self._attach_baggage()
57
75
  ctx = self._get_traceparent()
58
76
 
59
- with ag.tracer.start_as_current_span(
60
- name=func.__name__,
61
- kind=self.kind,
62
- context=ctx,
63
- ):
64
- self._set_link()
77
+ agen = func(*args, **kwargs)
65
78
 
66
- self._pre_instrument(func, *args, **kwargs)
79
+ async def wrapped_generator():
80
+ token_ctx = otel_context.attach(captured_ctx)
67
81
 
68
- result = await func(*args, **kwargs)
82
+ try:
83
+ with ag.tracer.start_as_current_span(
84
+ name=func.__name__,
85
+ kind=self.kind,
86
+ context=parent_ctx or ctx,
87
+ ):
88
+ self._set_link()
89
+ self._pre_instrument(func, *args, **kwargs)
69
90
 
70
- self._post_instrument(result)
91
+ _result = []
71
92
 
72
- return result
93
+ try:
94
+ while True:
95
+ chunk = await agen.__anext__()
73
96
 
74
- self._detach_baggage(token)
97
+ _result.append(chunk)
98
+ yield chunk
75
99
 
76
- return await aauto_instrumented(*args, **kwargs)
100
+ except StopAsyncIteration:
101
+ pass
77
102
 
78
- @wraps(func)
79
- def wrapper(*args, **kwargs):
80
- def auto_instrumented(*args, **kwargs):
103
+ finally:
104
+ if self.aggregate:
105
+ result = self.aggregate(_result)
106
+ elif all(isinstance(r, str) for r in _result):
107
+ result = "".join(_result)
108
+ elif all(isinstance(r, bytes) for r in _result):
109
+ result = b"".join(_result)
110
+ else:
111
+ result = _result
112
+
113
+ self._post_instrument(result)
114
+
115
+ finally:
116
+ otel_context.detach(token_ctx)
117
+
118
+ self._detach_baggage(token)
119
+
120
+ return wrapped_generator()
121
+
122
+ return astream_wrapper
123
+
124
+ # ---- SYNC GENERATOR ----
125
+ if is_sync_generator:
126
+
127
+ @wraps(func)
128
+ def stream_wrapper(*args, **kwargs):
81
129
  self._parse_type_and_kind()
82
130
 
131
+ captured_ctx = otel_context.get_current()
132
+ parent_ctx = trace.set_span_in_context(trace.get_current_span())
133
+
83
134
  token = self._attach_baggage()
135
+ ctx = self._get_traceparent()
136
+
137
+ agen = func(*args, **kwargs)
138
+
139
+ def wrapped_generator():
140
+ token_ctx = otel_context.attach(captured_ctx)
141
+
142
+ try:
143
+ with ag.tracer.start_as_current_span(
144
+ name=func.__name__,
145
+ kind=self.kind,
146
+ context=parent_ctx or ctx,
147
+ ):
148
+ self._set_link()
149
+ self._pre_instrument(func, *args, **kwargs)
150
+
151
+ _result = []
152
+
153
+ gen_return = None
154
+ stop_iteration_raised = False
155
+
156
+ try:
157
+ while True:
158
+ try:
159
+ chunk = next(agen)
84
160
 
161
+ except StopIteration as e:
162
+ gen_return = e.value
163
+ stop_iteration_raised = True
164
+ break
165
+
166
+ _result.append(chunk)
167
+
168
+ yield chunk
169
+
170
+ finally:
171
+ if self.aggregate:
172
+ result = self.aggregate(_result)
173
+ elif all(isinstance(r, str) for r in _result):
174
+ result = "".join(_result)
175
+ elif all(isinstance(r, bytes) for r in _result):
176
+ result = b"".join(_result)
177
+ else:
178
+ result = _result
179
+
180
+ self._post_instrument(result)
181
+
182
+ return gen_return if stop_iteration_raised else None
183
+
184
+ finally:
185
+ otel_context.detach(token_ctx)
186
+
187
+ self._detach_baggage(token)
188
+
189
+ return wrapped_generator()
190
+
191
+ return stream_wrapper
192
+
193
+ # ---- ASYNC FUNCTION (non-generator) ----
194
+ if is_coroutine_function:
195
+
196
+ @wraps(func)
197
+ async def awrapper(*args, **kwargs):
198
+ self._parse_type_and_kind()
199
+
200
+ captured_ctx = otel_context.get_current()
201
+ parent_ctx = trace.set_span_in_context(trace.get_current_span())
202
+
203
+ token = self._attach_baggage()
85
204
  ctx = self._get_traceparent()
86
205
 
206
+ token_ctx = otel_context.attach(captured_ctx)
207
+
208
+ try:
209
+ with ag.tracer.start_as_current_span(
210
+ name=func.__name__,
211
+ kind=self.kind,
212
+ context=parent_ctx or ctx,
213
+ ):
214
+ self._set_link()
215
+ self._pre_instrument(func, *args, **kwargs)
216
+
217
+ result = await func(*args, **kwargs)
218
+
219
+ self._post_instrument(result)
220
+
221
+ finally:
222
+ otel_context.detach(token_ctx)
223
+
224
+ self._detach_baggage(token)
225
+
226
+ return result
227
+
228
+ return awrapper
229
+
230
+ # ---- SYNC FUNCTION (non-generator) ----
231
+ @wraps(func)
232
+ def wrapper(*args, **kwargs):
233
+ self._parse_type_and_kind()
234
+
235
+ captured_ctx = otel_context.get_current()
236
+ parent_ctx = trace.set_span_in_context(trace.get_current_span())
237
+
238
+ token = self._attach_baggage()
239
+ ctx = self._get_traceparent()
240
+
241
+ token_ctx = otel_context.attach(captured_ctx)
242
+
243
+ try:
87
244
  with ag.tracer.start_as_current_span(
88
245
  name=func.__name__,
89
246
  kind=self.kind,
90
- context=ctx,
247
+ context=parent_ctx or ctx,
91
248
  ):
92
249
  self._set_link()
93
-
94
250
  self._pre_instrument(func, *args, **kwargs)
95
251
 
96
252
  result = func(*args, **kwargs)
97
253
 
98
254
  self._post_instrument(result)
99
255
 
100
- return result
256
+ finally:
257
+ otel_context.detach(token_ctx)
101
258
 
102
259
  self._detach_baggage(token)
103
260
 
104
- return auto_instrumented(*args, **kwargs)
261
+ return result
105
262
 
106
- return awrapper if is_coroutine_function else wrapper
263
+ return wrapper
107
264
 
108
265
  def _parse_type_and_kind(self):
109
266
  if not ag.tracing.get_current_span().is_recording():
@@ -8,10 +8,6 @@ from opentelemetry.sdk.trace.export import (
8
8
  SpanExporter,
9
9
  ReadableSpan,
10
10
  BatchSpanProcessor,
11
- _DEFAULT_MAX_QUEUE_SIZE,
12
- _DEFAULT_SCHEDULE_DELAY_MILLIS,
13
- _DEFAULT_MAX_EXPORT_BATCH_SIZE,
14
- _DEFAULT_EXPORT_TIMEOUT_MILLIS,
15
11
  )
16
12
 
17
13
  from agenta.sdk.utils.logging import get_module_logger
@@ -42,10 +38,10 @@ class TraceProcessor(SpanProcessor):
42
38
  if not self.inline:
43
39
  self._delegate = BatchSpanProcessor(
44
40
  span_exporter,
45
- max_queue_size or _DEFAULT_MAX_QUEUE_SIZE,
46
- schedule_delay_millis or _DEFAULT_SCHEDULE_DELAY_MILLIS,
47
- max_export_batch_size or _DEFAULT_MAX_EXPORT_BATCH_SIZE,
48
- export_timeout_millis or _DEFAULT_EXPORT_TIMEOUT_MILLIS,
41
+ max_queue_size,
42
+ schedule_delay_millis,
43
+ max_export_batch_size,
44
+ export_timeout_millis,
49
45
  )
50
46
  # --- DISTRIBUTED
51
47
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: agenta
3
- Version: 0.51.2
3
+ Version: 0.51.4
4
4
  Summary: The SDK for agenta is an open-source LLMOps platform.
5
5
  Keywords: LLMOps,LLM,evaluation,prompt engineering
6
6
  Author: Mahmoud Mabrouk
@@ -22,7 +22,7 @@ Requires-Dist: httpx (>=0.28.0)
22
22
  Requires-Dist: huggingface-hub (<0.31.0)
23
23
  Requires-Dist: importlib-metadata (>=8.0.0,<9.0)
24
24
  Requires-Dist: jinja2 (>=3.1.6,<4.0.0)
25
- Requires-Dist: litellm (>=1.75.9)
25
+ Requires-Dist: litellm (==1.76.0)
26
26
  Requires-Dist: openai (>=1.100.0)
27
27
  Requires-Dist: opentelemetry-api (>=1.27.0,<2.0.0)
28
28
  Requires-Dist: opentelemetry-exporter-otlp-proto-http (>=1.27.0,<2.0.0)
@@ -315,7 +315,7 @@ agenta/sdk/context/tracing.py,sha256=tM1T-HBt9D1qD8VsVKWlLe6MBRQrtHUA33E3KNM4GXQ
315
315
  agenta/sdk/decorators/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
316
316
  agenta/sdk/decorators/running.py,sha256=j077-4u4XytNV57g0UY8ddG_M2k99Q829yPejiuGeg8,4034
317
317
  agenta/sdk/decorators/serving.py,sha256=jU8nP0btR4tytPkjiEmrmVSvShSSEFX7tKilHZfr-XE,26186
318
- agenta/sdk/decorators/tracing.py,sha256=Ug1ybanpW6CsvT41eh2wDrjNy81amDqGU0Yo2FN5sPk,10222
318
+ agenta/sdk/decorators/tracing.py,sha256=4QkOaQzRIkR9_OTMZ31rC2Ad3G7MZXIx7SoF194QwGM,15832
319
319
  agenta/sdk/litellm/__init__.py,sha256=Bpz1gfHQc0MN1yolWcjifLWznv6GjHggvRGQSpxpihM,37
320
320
  agenta/sdk/litellm/litellm.py,sha256=dCjw0H_jD3L3UQ3l9SbLm5dfeIGnel6dPtQYJ78beYM,10202
321
321
  agenta/sdk/litellm/mockllm.py,sha256=F10Sbj2V1Cihkg6bgHkIOuw8irYEYpIp47UsO8LGOeE,2322
@@ -345,7 +345,7 @@ agenta/sdk/tracing/attributes.py,sha256=DwjjOk3mGOvz0jYu8EYr3hhItvawK5GX80_Mfciq
345
345
  agenta/sdk/tracing/conventions.py,sha256=JBtznBXZ3aRkGKkLl7cPwdMNh3w1G-H2Ta2YrAxbr38,950
346
346
  agenta/sdk/tracing/exporters.py,sha256=b1Aq5AcQYnmAxapQMYpN_MfaLOG4IGTzlQw3PfBiKgI,3486
347
347
  agenta/sdk/tracing/inline.py,sha256=y2S_MGGqmXgyUgbkNNyrb8_X-QtGuDy8JwxlwWibIx8,31507
348
- agenta/sdk/tracing/processors.py,sha256=wZWF8vTEouhbGxbfPGXVQJI53CcXFByqxHiCSIzJV-4,5407
348
+ agenta/sdk/tracing/processors.py,sha256=ZE6baO2U3ER73rckvXhdbNmLgs3jn6le7iAUQc6osbY,5141
349
349
  agenta/sdk/tracing/propagation.py,sha256=EeOqDMqnh_MoEhGd1do_vy_tQBYUcoC8kpLqVoZeqg0,2561
350
350
  agenta/sdk/tracing/spans.py,sha256=nqUOjjirBxB8Eacv8Qj4Ra_6rknGi3lbJdNyKmk5ODQ,3707
351
351
  agenta/sdk/tracing/tracing.py,sha256=eqQLcvgmR6Tz0WSwLCERkGKiLzsKfDyR_ah-Tyz1qGE,9256
@@ -365,6 +365,6 @@ agenta/sdk/workflows/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hS
365
365
  agenta/sdk/workflows/registry.py,sha256=OucCfmhyEENAF5OwjRBLjbDIy3Qar-prFXLhKMU0BZA,944
366
366
  agenta/sdk/workflows/types.py,sha256=nklaaIrK0o5Nloy1l6hnPXjtN7H4-OUv0ivAUf278Og,11682
367
367
  agenta/sdk/workflows/utils.py,sha256=ILfY8DSBWLrdWIuKg6mq7rANwKiiY6sxEeFiBFhjLYM,413
368
- agenta-0.51.2.dist-info/METADATA,sha256=iSFL_mwtya1RW2QZauN4et_Xnd--hEmYTlj0n3zDuL8,31641
369
- agenta-0.51.2.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
370
- agenta-0.51.2.dist-info/RECORD,,
368
+ agenta-0.51.4.dist-info/METADATA,sha256=tsHuDehdC8pfhngzFsGDP4qX5nuKOOnXCcKx-4FfOgc,31641
369
+ agenta-0.51.4.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
370
+ agenta-0.51.4.dist-info/RECORD,,