agenta 0.15.0a0__py3-none-any.whl → 0.15.0a2__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.
- agenta/__init__.py +6 -3
- agenta/client/backend/client.py +8 -6
- agenta/client/backend/types/create_span.py +1 -1
- agenta/docker/docker-assets/Dockerfile.cloud.template +1 -1
- agenta/docker/docker_utils.py +1 -1
- agenta/sdk/__init__.py +6 -4
- agenta/sdk/agenta_init.py +81 -75
- agenta/sdk/decorators/base.py +10 -0
- agenta/sdk/decorators/llm_entrypoint.py +506 -0
- agenta/sdk/decorators/tracing.py +90 -0
- agenta/sdk/tracing/llm_tracing.py +116 -95
- agenta/sdk/tracing/tasks_manager.py +1 -3
- agenta/sdk/types.py +83 -65
- agenta/sdk/utils/globals.py +3 -1
- {agenta-0.15.0a0.dist-info → agenta-0.15.0a2.dist-info}/METADATA +3 -3
- {agenta-0.15.0a0.dist-info → agenta-0.15.0a2.dist-info}/RECORD +18 -17
- agenta/sdk/agenta_decorator.py +0 -570
- agenta/sdk/tracing/decorators.py +0 -41
- {agenta-0.15.0a0.dist-info → agenta-0.15.0a2.dist-info}/WHEEL +0 -0
- {agenta-0.15.0a0.dist-info → agenta-0.15.0a2.dist-info}/entry_points.txt +0 -0
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
# Stdlib Imports
|
|
2
|
+
import os
|
|
3
|
+
from threading import Lock
|
|
2
4
|
from datetime import datetime, timezone
|
|
3
5
|
from typing import Optional, Dict, Any, List, Union
|
|
4
6
|
|
|
@@ -13,34 +15,55 @@ from agenta.client.backend.types.create_span import CreateSpan, SpanKind, SpanSt
|
|
|
13
15
|
from bson.objectid import ObjectId
|
|
14
16
|
|
|
15
17
|
|
|
16
|
-
class
|
|
17
|
-
"""
|
|
18
|
+
class SingletonMeta(type):
|
|
19
|
+
"""
|
|
20
|
+
Thread-safe implementation of Singleton.
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
_instances = {} # type: ignore
|
|
24
|
+
|
|
25
|
+
# We need the lock mechanism to synchronize threads \
|
|
26
|
+
# during the initial access to the Singleton object.
|
|
27
|
+
_lock: Lock = Lock()
|
|
28
|
+
|
|
29
|
+
def __call__(cls, *args, **kwargs):
|
|
30
|
+
"""
|
|
31
|
+
Ensures that changes to the `__init__` arguments do not affect the
|
|
32
|
+
returned instance.
|
|
33
|
+
|
|
34
|
+
Uses a lock to make this method thread-safe. If an instance of the class
|
|
35
|
+
does not already exist, it creates one. Otherwise, it returns the
|
|
36
|
+
existing instance.
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
with cls._lock:
|
|
40
|
+
if cls not in cls._instances:
|
|
41
|
+
instance = super().__call__(*args, **kwargs)
|
|
42
|
+
cls._instances[cls] = instance
|
|
43
|
+
return cls._instances[cls]
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class Tracing(metaclass=SingletonMeta):
|
|
47
|
+
"""The `Tracing` class is an agent for LLM tracing with specific initialization arguments.
|
|
18
48
|
|
|
19
|
-
|
|
20
|
-
|
|
49
|
+
__init__ args:
|
|
50
|
+
host (str): The URL of the backend host
|
|
21
51
|
api_key (str): The API Key of the backend host
|
|
22
52
|
tasks_manager (TaskQueue): The tasks manager dedicated to handling asynchronous tasks
|
|
23
53
|
llm_logger (Logger): The logger associated with the LLM tracing
|
|
24
54
|
max_workers (int): The maximum number of workers to run tracing
|
|
25
55
|
"""
|
|
26
56
|
|
|
27
|
-
_instance = None
|
|
28
|
-
|
|
29
|
-
def __new__(cls, *args, **kwargs):
|
|
30
|
-
if not cls._instance:
|
|
31
|
-
cls._instance = super().__new__(cls)
|
|
32
|
-
return cls._instance
|
|
33
|
-
|
|
34
57
|
def __init__(
|
|
35
58
|
self,
|
|
36
|
-
|
|
59
|
+
host: str,
|
|
37
60
|
app_id: str,
|
|
38
|
-
variant_id: str,
|
|
61
|
+
variant_id: Optional[str] = None,
|
|
39
62
|
variant_name: Optional[str] = None,
|
|
40
63
|
api_key: Optional[str] = None,
|
|
41
64
|
max_workers: Optional[int] = None,
|
|
42
65
|
):
|
|
43
|
-
self.
|
|
66
|
+
self.host = host + "/api"
|
|
44
67
|
self.api_key = api_key if api_key is not None else ""
|
|
45
68
|
self.llm_logger = llm_logger
|
|
46
69
|
self.app_id = app_id
|
|
@@ -49,11 +72,13 @@ class Tracing(object):
|
|
|
49
72
|
self.tasks_manager = TaskQueue(
|
|
50
73
|
max_workers if max_workers else 4, logger=llm_logger
|
|
51
74
|
)
|
|
52
|
-
self.active_span =
|
|
53
|
-
self.
|
|
54
|
-
self.
|
|
55
|
-
self.recorded_spans: List[CreateSpan] = []
|
|
75
|
+
self.active_span: Optional[CreateSpan] = None
|
|
76
|
+
self.active_trace_id: Optional[str] = None
|
|
77
|
+
self.pending_spans: List[CreateSpan] = []
|
|
56
78
|
self.tags: List[str] = []
|
|
79
|
+
self.trace_config_cache: Dict[
|
|
80
|
+
str, Any
|
|
81
|
+
] = {} # used to save the trace configuration before starting the first span
|
|
57
82
|
self.span_dict: Dict[str, CreateSpan] = {} # type: ignore
|
|
58
83
|
|
|
59
84
|
@property
|
|
@@ -65,69 +90,37 @@ class Tracing(object):
|
|
|
65
90
|
"""
|
|
66
91
|
|
|
67
92
|
return AsyncAgentaApi(
|
|
68
|
-
base_url=self.
|
|
93
|
+
base_url=self.host, api_key=self.api_key, timeout=120 # type: ignore
|
|
69
94
|
).observability
|
|
70
95
|
|
|
71
96
|
def set_span_attribute(
|
|
72
|
-
self, parent_key: Optional[str] = None, attributes: Dict[str, Any] = {}
|
|
73
|
-
):
|
|
74
|
-
span = self.span_dict[self.active_span.id] # type: ignore
|
|
75
|
-
for key, value in attributes.items():
|
|
76
|
-
self.set_attribute(span.attributes, key, value, parent_key) # type: ignore
|
|
77
|
-
|
|
78
|
-
def set_attribute(
|
|
79
97
|
self,
|
|
80
|
-
|
|
81
|
-
key: str,
|
|
82
|
-
value: Any,
|
|
83
|
-
parent_key: Optional[str] = None,
|
|
98
|
+
attributes: Dict[str, Any] = {},
|
|
84
99
|
):
|
|
85
|
-
if
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
100
|
+
if (
|
|
101
|
+
self.active_span is None
|
|
102
|
+
): # This is the case where entrypoint wants to save the trace information but the parent span has not been initialized yet
|
|
103
|
+
for key, value in attributes.items():
|
|
104
|
+
self.trace_config_cache[key] = value
|
|
90
105
|
else:
|
|
91
|
-
|
|
106
|
+
for key, value in attributes.items():
|
|
107
|
+
self.active_span.attributes[key] = value
|
|
92
108
|
|
|
93
109
|
def set_trace_tags(self, tags: List[str]):
|
|
94
110
|
self.tags.extend(tags)
|
|
95
111
|
|
|
96
|
-
def start_parent_span(
|
|
97
|
-
self, name: str, inputs: Dict[str, Any], config: Dict[str, Any], **kwargs
|
|
98
|
-
):
|
|
99
|
-
trace_id = self._create_trace_id()
|
|
100
|
-
span_id = self._create_span_id()
|
|
101
|
-
self.llm_logger.info("Recording parent span...")
|
|
102
|
-
span = CreateSpan(
|
|
103
|
-
id=span_id,
|
|
104
|
-
app_id=self.app_id,
|
|
105
|
-
variant_id=self.variant_id,
|
|
106
|
-
variant_name=self.variant_name,
|
|
107
|
-
inputs=inputs,
|
|
108
|
-
name=name,
|
|
109
|
-
config=config,
|
|
110
|
-
environment=kwargs.get("environment"),
|
|
111
|
-
spankind=SpanKind.WORKFLOW.value,
|
|
112
|
-
status=SpanStatusCode.UNSET.value,
|
|
113
|
-
start_time=datetime.now(timezone.utc),
|
|
114
|
-
)
|
|
115
|
-
self.active_trace = span
|
|
116
|
-
self.recording_trace_id = trace_id
|
|
117
|
-
self.parent_span_id = span.id
|
|
118
|
-
self.llm_logger.info(
|
|
119
|
-
f"Recorded active_trace and setting parent_span_id: {span.id}"
|
|
120
|
-
)
|
|
121
|
-
|
|
122
112
|
def start_span(
|
|
123
113
|
self,
|
|
124
114
|
name: str,
|
|
125
115
|
spankind: str,
|
|
126
116
|
input: Dict[str, Any],
|
|
127
|
-
config: Dict[str, Any] =
|
|
117
|
+
config: Optional[Dict[str, Any]] = None,
|
|
118
|
+
**kwargs,
|
|
128
119
|
) -> CreateSpan:
|
|
129
120
|
span_id = self._create_span_id()
|
|
130
|
-
self.llm_logger.info(
|
|
121
|
+
self.llm_logger.info(
|
|
122
|
+
f"Recording {'parent' if spankind == 'workflow' else spankind} span..."
|
|
123
|
+
)
|
|
131
124
|
span = CreateSpan(
|
|
132
125
|
id=span_id,
|
|
133
126
|
inputs=input,
|
|
@@ -136,60 +129,88 @@ class Tracing(object):
|
|
|
136
129
|
variant_id=self.variant_id,
|
|
137
130
|
variant_name=self.variant_name,
|
|
138
131
|
config=config,
|
|
139
|
-
environment=self.active_trace.environment,
|
|
140
|
-
parent_span_id=self.parent_span_id,
|
|
141
132
|
spankind=spankind.upper(),
|
|
142
133
|
attributes={},
|
|
143
134
|
status=SpanStatusCode.UNSET.value,
|
|
144
135
|
start_time=datetime.now(timezone.utc),
|
|
136
|
+
outputs=None,
|
|
137
|
+
tags=None,
|
|
138
|
+
user=None,
|
|
139
|
+
end_time=None,
|
|
140
|
+
tokens=None,
|
|
141
|
+
cost=None,
|
|
142
|
+
token_consumption=None,
|
|
143
|
+
parent_span_id=None,
|
|
145
144
|
)
|
|
146
145
|
|
|
147
|
-
self.
|
|
146
|
+
if self.active_trace_id is None: # This is a parent span
|
|
147
|
+
self.active_trace_id = self._create_trace_id()
|
|
148
|
+
span.environment = (
|
|
149
|
+
self.trace_config_cache.get("environment")
|
|
150
|
+
if self.trace_config_cache is not None
|
|
151
|
+
else os.environ.get("environment", "unset")
|
|
152
|
+
)
|
|
153
|
+
span.config = (
|
|
154
|
+
self.trace_config_cache.get("config")
|
|
155
|
+
if not config and self.trace_config_cache is not None
|
|
156
|
+
else None
|
|
157
|
+
)
|
|
158
|
+
else:
|
|
159
|
+
span.parent_span_id = self.active_span.id
|
|
148
160
|
self.span_dict[span.id] = span
|
|
149
|
-
self.
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
)
|
|
161
|
+
self.active_span = span
|
|
162
|
+
|
|
163
|
+
self.llm_logger.info(f"Recorded span and setting parent_span_id: {span.id}")
|
|
153
164
|
return span
|
|
154
165
|
|
|
155
166
|
def update_span_status(self, span: CreateSpan, value: str):
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
)
|
|
167
|
+
span.status = value
|
|
168
|
+
|
|
169
|
+
def end_span(self, outputs: Dict[str, Any]):
|
|
170
|
+
"""
|
|
171
|
+
Ends the active span, if it is a parent span, ends the trace too.
|
|
172
|
+
"""
|
|
173
|
+
if self.active_span is None:
|
|
174
|
+
raise ValueError("There is no active span to end.")
|
|
175
|
+
self.active_span.end_time = datetime.now(timezone.utc)
|
|
176
|
+
self.active_span.outputs = [outputs.get("message", "")]
|
|
177
|
+
self.active_span.cost = outputs.get("cost", None)
|
|
178
|
+
self.active_span.tokens = outputs.get("usage", None)
|
|
167
179
|
|
|
168
180
|
# Push span to list of recorded spans
|
|
169
|
-
self.
|
|
181
|
+
self.pending_spans.append(self.active_span)
|
|
170
182
|
self.llm_logger.info(
|
|
171
|
-
f"Pushed {
|
|
183
|
+
f"Pushed {self.active_span.spankind} span {self.active_span.id} to recorded spans."
|
|
172
184
|
)
|
|
185
|
+
if self.active_span.parent_span_id is None:
|
|
186
|
+
self.end_trace(parent_span=self.active_span)
|
|
187
|
+
else:
|
|
188
|
+
self.active_span = self.span_dict[self.active_span.parent_span_id]
|
|
173
189
|
|
|
174
|
-
def
|
|
175
|
-
self.end_span(outputs=outputs, span=span, **kwargs)
|
|
190
|
+
def end_trace(self, parent_span: CreateSpan):
|
|
176
191
|
if self.api_key == "":
|
|
177
192
|
return
|
|
178
193
|
|
|
179
|
-
|
|
180
|
-
|
|
194
|
+
if not self.active_trace_id:
|
|
195
|
+
raise RuntimeError("No active trace to end.")
|
|
196
|
+
|
|
197
|
+
self.llm_logger.info("Preparing to send recorded spans for processing.")
|
|
198
|
+
self.llm_logger.info(f"Recorded spans => {len(self.pending_spans)}")
|
|
181
199
|
self.tasks_manager.add_task(
|
|
182
|
-
self.
|
|
200
|
+
self.active_trace_id,
|
|
183
201
|
"trace",
|
|
184
202
|
self.client.create_traces(
|
|
185
|
-
trace=self.
|
|
203
|
+
trace=self.active_trace_id, spans=self.pending_spans # type: ignore
|
|
186
204
|
),
|
|
187
205
|
self.client,
|
|
188
206
|
)
|
|
189
207
|
self.llm_logger.info(
|
|
190
|
-
f"Tracing for {
|
|
208
|
+
f"Tracing for {parent_span.id} recorded successfully and sent for processing."
|
|
191
209
|
)
|
|
192
|
-
self.
|
|
210
|
+
self._clear_pending_spans()
|
|
211
|
+
self.active_trace_id = None
|
|
212
|
+
self.active_span = None
|
|
213
|
+
self.trace_config_cache.clear()
|
|
193
214
|
|
|
194
215
|
def _create_trace_id(self) -> str:
|
|
195
216
|
"""Creates a unique mongo id for the trace object.
|
|
@@ -209,12 +230,12 @@ class Tracing(object):
|
|
|
209
230
|
|
|
210
231
|
return str(ObjectId())
|
|
211
232
|
|
|
212
|
-
def
|
|
233
|
+
def _clear_pending_spans(self) -> None:
|
|
213
234
|
"""
|
|
214
235
|
Clear the list of recorded spans to prepare for next batch processing.
|
|
215
236
|
"""
|
|
216
237
|
|
|
217
|
-
self.
|
|
238
|
+
self.pending_spans = []
|
|
218
239
|
self.llm_logger.info(
|
|
219
|
-
f"Cleared all recorded spans from batch: {self.
|
|
240
|
+
f"Cleared all recorded spans from batch: {self.pending_spans}"
|
|
220
241
|
)
|
|
@@ -106,9 +106,7 @@ class TaskQueue(object):
|
|
|
106
106
|
future.result()
|
|
107
107
|
except Exception as exc:
|
|
108
108
|
self._logger.error(f"Error running task: {str(exc)}")
|
|
109
|
-
self._logger.error(
|
|
110
|
-
f"Recording trace {task.coroutine_type} status to ERROR."
|
|
111
|
-
)
|
|
109
|
+
self._logger.error(f"Recording {task.coroutine_type} status to ERROR.")
|
|
112
110
|
break
|
|
113
111
|
finally:
|
|
114
112
|
self.tasks.task_done()
|
agenta/sdk/types.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import json
|
|
2
|
-
from typing import Dict, List, Optional
|
|
2
|
+
from typing import Any, Dict, List, Optional
|
|
3
3
|
|
|
4
|
-
from pydantic import
|
|
4
|
+
from pydantic import BaseModel, Extra, HttpUrl, Field
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
class InFile:
|
|
@@ -24,75 +24,87 @@ class FuncResponse(BaseModel):
|
|
|
24
24
|
|
|
25
25
|
|
|
26
26
|
class DictInput(dict):
|
|
27
|
-
def __new__(cls, default_keys
|
|
27
|
+
def __new__(cls, default_keys=None):
|
|
28
28
|
instance = super().__new__(cls, default_keys)
|
|
29
29
|
if default_keys is None:
|
|
30
30
|
default_keys = []
|
|
31
|
-
instance.data = [key for key in default_keys]
|
|
31
|
+
instance.data = [key for key in default_keys]
|
|
32
32
|
return instance
|
|
33
33
|
|
|
34
34
|
@classmethod
|
|
35
|
-
def
|
|
36
|
-
|
|
35
|
+
def __modify_schema__(cls, field_schema):
|
|
36
|
+
field_schema.update({"x-parameter": "dict"})
|
|
37
37
|
|
|
38
38
|
|
|
39
39
|
class TextParam(str):
|
|
40
40
|
@classmethod
|
|
41
|
-
def
|
|
42
|
-
|
|
41
|
+
def __modify_schema__(cls, field_schema):
|
|
42
|
+
field_schema.update({"x-parameter": "text"})
|
|
43
43
|
|
|
44
44
|
|
|
45
45
|
class BinaryParam(int):
|
|
46
46
|
def __new__(cls, value: bool = False):
|
|
47
47
|
instance = super().__new__(cls, int(value))
|
|
48
|
-
instance.default = value
|
|
48
|
+
instance.default = value
|
|
49
49
|
return instance
|
|
50
50
|
|
|
51
51
|
@classmethod
|
|
52
|
-
def
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
52
|
+
def __modify_schema__(cls, field_schema):
|
|
53
|
+
field_schema.update(
|
|
54
|
+
{
|
|
55
|
+
"x-parameter": "bool",
|
|
56
|
+
"type": "boolean",
|
|
57
|
+
}
|
|
58
|
+
)
|
|
57
59
|
|
|
58
60
|
|
|
59
61
|
class IntParam(int):
|
|
60
62
|
def __new__(cls, default: int = 6, minval: float = 1, maxval: float = 10):
|
|
61
63
|
instance = super().__new__(cls, default)
|
|
62
|
-
instance.minval = minval
|
|
63
|
-
instance.maxval = maxval
|
|
64
|
+
instance.minval = minval
|
|
65
|
+
instance.maxval = maxval
|
|
64
66
|
return instance
|
|
65
67
|
|
|
66
68
|
@classmethod
|
|
67
|
-
def
|
|
68
|
-
|
|
69
|
+
def __modify_schema__(cls, field_schema):
|
|
70
|
+
field_schema.update(
|
|
71
|
+
{
|
|
72
|
+
"x-parameter": "int",
|
|
73
|
+
"type": "integer",
|
|
74
|
+
"minimum": 1,
|
|
75
|
+
"maximum": 10,
|
|
76
|
+
}
|
|
77
|
+
)
|
|
69
78
|
|
|
70
79
|
|
|
71
80
|
class FloatParam(float):
|
|
72
81
|
def __new__(cls, default: float = 0.5, minval: float = 0.0, maxval: float = 1.0):
|
|
73
82
|
instance = super().__new__(cls, default)
|
|
74
|
-
instance.
|
|
75
|
-
instance.
|
|
76
|
-
instance.maxval = maxval # type: ignore
|
|
83
|
+
instance.minval = minval
|
|
84
|
+
instance.maxval = maxval
|
|
77
85
|
return instance
|
|
78
86
|
|
|
79
87
|
@classmethod
|
|
80
|
-
def
|
|
81
|
-
|
|
88
|
+
def __modify_schema__(cls, field_schema):
|
|
89
|
+
field_schema.update(
|
|
90
|
+
{
|
|
91
|
+
"x-parameter": "float",
|
|
92
|
+
"type": "number",
|
|
93
|
+
"minimum": 0.0,
|
|
94
|
+
"maximum": 1.0,
|
|
95
|
+
}
|
|
96
|
+
)
|
|
82
97
|
|
|
83
98
|
|
|
84
99
|
class MultipleChoiceParam(str):
|
|
85
|
-
def __new__(
|
|
86
|
-
|
|
87
|
-
):
|
|
88
|
-
if default is not None and type(default) is list:
|
|
100
|
+
def __new__(cls, default: str = None, choices: List[str] = None):
|
|
101
|
+
if type(default) is list:
|
|
89
102
|
raise ValueError(
|
|
90
103
|
"The order of the parameters for MultipleChoiceParam is wrong! It's MultipleChoiceParam(default, choices) and not the opposite"
|
|
91
104
|
)
|
|
92
|
-
|
|
93
|
-
if not default and choices is not None:
|
|
105
|
+
if default is None and choices:
|
|
94
106
|
# if a default value is not provided,
|
|
95
|
-
#
|
|
107
|
+
# uset the first value in the choices list
|
|
96
108
|
default = choices[0]
|
|
97
109
|
|
|
98
110
|
if default is None and not choices:
|
|
@@ -100,21 +112,23 @@ class MultipleChoiceParam(str):
|
|
|
100
112
|
raise ValueError("You must provide either a default value or choices")
|
|
101
113
|
|
|
102
114
|
instance = super().__new__(cls, default)
|
|
103
|
-
instance.choices = choices
|
|
104
|
-
instance.default = default
|
|
115
|
+
instance.choices = choices
|
|
116
|
+
instance.default = default
|
|
105
117
|
return instance
|
|
106
118
|
|
|
107
119
|
@classmethod
|
|
108
|
-
def
|
|
109
|
-
|
|
120
|
+
def __modify_schema__(cls, field_schema: dict[str, Any]):
|
|
121
|
+
field_schema.update(
|
|
122
|
+
{
|
|
123
|
+
"x-parameter": "choice",
|
|
124
|
+
"type": "string",
|
|
125
|
+
"enum": [],
|
|
126
|
+
}
|
|
127
|
+
)
|
|
110
128
|
|
|
111
129
|
|
|
112
130
|
class GroupedMultipleChoiceParam(str):
|
|
113
|
-
def __new__(
|
|
114
|
-
cls,
|
|
115
|
-
default: Optional[str] = None,
|
|
116
|
-
choices: Optional[Dict[str, List[str]]] = None,
|
|
117
|
-
):
|
|
131
|
+
def __new__(cls, default: str = None, choices: Dict[str, List[str]] = None):
|
|
118
132
|
if choices is None:
|
|
119
133
|
choices = {}
|
|
120
134
|
|
|
@@ -129,23 +143,31 @@ class GroupedMultipleChoiceParam(str):
|
|
|
129
143
|
)
|
|
130
144
|
|
|
131
145
|
if not default:
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
default = default_selected_choice[0]
|
|
146
|
+
for choices in choices.values():
|
|
147
|
+
if choices:
|
|
148
|
+
default = choices[0]
|
|
149
|
+
break
|
|
137
150
|
|
|
138
151
|
instance = super().__new__(cls, default)
|
|
139
|
-
instance.choices = choices
|
|
140
|
-
instance.default = default
|
|
152
|
+
instance.choices = choices
|
|
153
|
+
instance.default = default
|
|
141
154
|
return instance
|
|
142
155
|
|
|
143
156
|
@classmethod
|
|
144
|
-
def
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
157
|
+
def __modify_schema__(cls, field_schema: dict[str, Any], **kwargs):
|
|
158
|
+
choices = kwargs.get("choices", {})
|
|
159
|
+
field_schema.update(
|
|
160
|
+
{
|
|
161
|
+
"x-parameter": "grouped_choice",
|
|
162
|
+
"type": "string",
|
|
163
|
+
"choices": choices,
|
|
164
|
+
}
|
|
165
|
+
)
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
class Message(BaseModel):
|
|
169
|
+
role: str
|
|
170
|
+
content: str
|
|
149
171
|
|
|
150
172
|
|
|
151
173
|
class MessagesInput(list):
|
|
@@ -160,32 +182,28 @@ class MessagesInput(list):
|
|
|
160
182
|
|
|
161
183
|
"""
|
|
162
184
|
|
|
163
|
-
def __new__(cls, messages: List[Dict[str, str]] =
|
|
164
|
-
instance = super().__new__(cls)
|
|
165
|
-
instance.default = messages
|
|
185
|
+
def __new__(cls, messages: List[Dict[str, str]] = None):
|
|
186
|
+
instance = super().__new__(cls, messages)
|
|
187
|
+
instance.default = messages
|
|
166
188
|
return instance
|
|
167
189
|
|
|
168
190
|
@classmethod
|
|
169
|
-
def
|
|
170
|
-
|
|
191
|
+
def __modify_schema__(cls, field_schema: dict[str, Any]):
|
|
192
|
+
field_schema.update({"x-parameter": "messages", "type": "array"})
|
|
171
193
|
|
|
172
194
|
|
|
173
195
|
class FileInputURL(HttpUrl):
|
|
174
|
-
def __new__(cls, url: str):
|
|
175
|
-
instance = super().__new__(cls, url)
|
|
176
|
-
instance.default = url # type: ignore
|
|
177
|
-
return instance
|
|
178
|
-
|
|
179
196
|
@classmethod
|
|
180
|
-
def
|
|
181
|
-
|
|
197
|
+
def __modify_schema__(cls, field_schema: Dict[str, Any]) -> None:
|
|
198
|
+
field_schema.update({"x-parameter": "file_url", "type": "string"})
|
|
182
199
|
|
|
183
200
|
|
|
184
201
|
class Context(BaseModel):
|
|
185
|
-
|
|
202
|
+
class Config:
|
|
203
|
+
extra = Extra.allow
|
|
186
204
|
|
|
187
205
|
def to_json(self):
|
|
188
|
-
return self.
|
|
206
|
+
return self.json()
|
|
189
207
|
|
|
190
208
|
@classmethod
|
|
191
209
|
def from_json(cls, json_str: str):
|
agenta/sdk/utils/globals.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import agenta
|
|
2
2
|
|
|
3
3
|
|
|
4
|
-
def set_global(setup=None, config=None):
|
|
4
|
+
def set_global(setup=None, config=None, tracing=None):
|
|
5
5
|
"""Allows usage of agenta.config and agenta.setup in the user's code.
|
|
6
6
|
|
|
7
7
|
Args:
|
|
@@ -12,3 +12,5 @@ def set_global(setup=None, config=None):
|
|
|
12
12
|
agenta.setup = setup
|
|
13
13
|
if config is not None:
|
|
14
14
|
agenta.config = config
|
|
15
|
+
if tracing is not None:
|
|
16
|
+
agenta.tracing = tracing
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: agenta
|
|
3
|
-
Version: 0.15.
|
|
3
|
+
Version: 0.15.0a2
|
|
4
4
|
Summary: The SDK for agenta is an open-source LLMOps platform.
|
|
5
5
|
Home-page: https://agenta.ai
|
|
6
6
|
Keywords: LLMOps,LLM,evaluation,prompt engineering
|
|
@@ -18,12 +18,12 @@ Classifier: Topic :: Software Development :: Libraries
|
|
|
18
18
|
Requires-Dist: cachetools (>=5.3.3,<6.0.0)
|
|
19
19
|
Requires-Dist: click (>=8.1.3,<9.0.0)
|
|
20
20
|
Requires-Dist: docker (>=6.1.1,<8.0.0)
|
|
21
|
-
Requires-Dist: fastapi (>=0.
|
|
21
|
+
Requires-Dist: fastapi (>=0.96.1)
|
|
22
22
|
Requires-Dist: httpx (>=0.24,<0.28)
|
|
23
23
|
Requires-Dist: importlib-metadata (>=6.7,<8.0)
|
|
24
24
|
Requires-Dist: ipdb (>=0.13)
|
|
25
25
|
Requires-Dist: posthog (>=3.1.0,<4.0.0)
|
|
26
|
-
Requires-Dist: pydantic (
|
|
26
|
+
Requires-Dist: pydantic (==1.10.13)
|
|
27
27
|
Requires-Dist: pymongo (>=4.6.3,<5.0.0)
|
|
28
28
|
Requires-Dist: python-dotenv (>=1.0.0,<2.0.0)
|
|
29
29
|
Requires-Dist: python-multipart (>=0.0.6,<0.0.10)
|