agenta 0.15.0a0__py3-none-any.whl → 0.15.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.
- agenta/__init__.py +6 -3
- agenta/client/backend/client.py +8 -6
- agenta/client/backend/types/create_span.py +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 +112 -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.0a1.dist-info}/METADATA +3 -3
- {agenta-0.15.0a0.dist-info → agenta-0.15.0a1.dist-info}/RECORD +17 -16
- agenta/sdk/agenta_decorator.py +0 -570
- agenta/sdk/tracing/decorators.py +0 -41
- {agenta-0.15.0a0.dist-info → agenta-0.15.0a1.dist-info}/WHEEL +0 -0
- {agenta-0.15.0a0.dist-info → agenta-0.15.0a1.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,11 @@ 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[str, Any] = {} # used to save the trace configuration before starting the first span
|
|
57
80
|
self.span_dict: Dict[str, CreateSpan] = {} # type: ignore
|
|
58
81
|
|
|
59
82
|
@property
|
|
@@ -65,69 +88,35 @@ class Tracing(object):
|
|
|
65
88
|
"""
|
|
66
89
|
|
|
67
90
|
return AsyncAgentaApi(
|
|
68
|
-
base_url=self.
|
|
91
|
+
base_url=self.host, api_key=self.api_key, timeout=120 # type: ignore
|
|
69
92
|
).observability
|
|
70
93
|
|
|
71
94
|
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
95
|
self,
|
|
80
|
-
|
|
81
|
-
key: str,
|
|
82
|
-
value: Any,
|
|
83
|
-
parent_key: Optional[str] = None,
|
|
96
|
+
attributes: Dict[str, Any] = {},
|
|
84
97
|
):
|
|
85
|
-
if
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
span_attributes[parent_key] = {}
|
|
89
|
-
span_attributes[parent_key][key] = value
|
|
98
|
+
if self.active_span is None: # This is the case where entrypoint wants to save the trace information but the parent span has not been initialized yet
|
|
99
|
+
for key, value in attributes.items():
|
|
100
|
+
self.trace_config_cache[key] = value
|
|
90
101
|
else:
|
|
91
|
-
|
|
102
|
+
for key, value in attributes.items():
|
|
103
|
+
self.active_span.attributes[key] = value
|
|
92
104
|
|
|
93
105
|
def set_trace_tags(self, tags: List[str]):
|
|
94
106
|
self.tags.extend(tags)
|
|
95
107
|
|
|
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
108
|
def start_span(
|
|
123
109
|
self,
|
|
124
110
|
name: str,
|
|
125
111
|
spankind: str,
|
|
126
112
|
input: Dict[str, Any],
|
|
127
|
-
config: Dict[str, Any] =
|
|
113
|
+
config: Optional[Dict[str, Any]] = None,
|
|
114
|
+
**kwargs,
|
|
128
115
|
) -> CreateSpan:
|
|
129
116
|
span_id = self._create_span_id()
|
|
130
|
-
self.llm_logger.info(
|
|
117
|
+
self.llm_logger.info(
|
|
118
|
+
f"Recording {'parent' if spankind == 'workflow' else spankind} span..."
|
|
119
|
+
)
|
|
131
120
|
span = CreateSpan(
|
|
132
121
|
id=span_id,
|
|
133
122
|
inputs=input,
|
|
@@ -136,60 +125,88 @@ class Tracing(object):
|
|
|
136
125
|
variant_id=self.variant_id,
|
|
137
126
|
variant_name=self.variant_name,
|
|
138
127
|
config=config,
|
|
139
|
-
environment=self.active_trace.environment,
|
|
140
|
-
parent_span_id=self.parent_span_id,
|
|
141
128
|
spankind=spankind.upper(),
|
|
142
129
|
attributes={},
|
|
143
130
|
status=SpanStatusCode.UNSET.value,
|
|
144
131
|
start_time=datetime.now(timezone.utc),
|
|
132
|
+
outputs=None,
|
|
133
|
+
tags=None,
|
|
134
|
+
user=None,
|
|
135
|
+
end_time=None,
|
|
136
|
+
tokens=None,
|
|
137
|
+
cost=None,
|
|
138
|
+
token_consumption=None,
|
|
139
|
+
parent_span_id=None,
|
|
145
140
|
)
|
|
146
141
|
|
|
147
|
-
self.
|
|
142
|
+
if self.active_trace_id is None: # This is a parent span
|
|
143
|
+
self.active_trace_id = self._create_trace_id()
|
|
144
|
+
span.environment = (
|
|
145
|
+
self.trace_config_cache.get("environment")
|
|
146
|
+
if self.trace_config_cache is not None
|
|
147
|
+
else os.environ.get("environment", "unset")
|
|
148
|
+
)
|
|
149
|
+
span.config = (
|
|
150
|
+
self.trace_config_cache.get("config")
|
|
151
|
+
if not config and self.trace_config_cache is not None
|
|
152
|
+
else None
|
|
153
|
+
)
|
|
154
|
+
else:
|
|
155
|
+
span.parent_span_id = self.active_span.id
|
|
148
156
|
self.span_dict[span.id] = span
|
|
149
|
-
self.
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
)
|
|
157
|
+
self.active_span = span
|
|
158
|
+
|
|
159
|
+
self.llm_logger.info(f"Recorded span and setting parent_span_id: {span.id}")
|
|
153
160
|
return span
|
|
154
161
|
|
|
155
162
|
def update_span_status(self, span: CreateSpan, value: str):
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
)
|
|
163
|
+
span.status = value
|
|
164
|
+
|
|
165
|
+
def end_span(self, outputs: Dict[str, Any]):
|
|
166
|
+
"""
|
|
167
|
+
Ends the active span, if it is a parent span, ends the trace too.
|
|
168
|
+
"""
|
|
169
|
+
if self.active_span is None:
|
|
170
|
+
raise ValueError("There is no active span to end.")
|
|
171
|
+
self.active_span.end_time = datetime.now(timezone.utc)
|
|
172
|
+
self.active_span.outputs = [outputs.get("message", "")]
|
|
173
|
+
self.active_span.cost = outputs.get("cost", None)
|
|
174
|
+
self.active_span.tokens = outputs.get("usage", None)
|
|
167
175
|
|
|
168
176
|
# Push span to list of recorded spans
|
|
169
|
-
self.
|
|
177
|
+
self.pending_spans.append(self.active_span)
|
|
170
178
|
self.llm_logger.info(
|
|
171
|
-
f"Pushed {
|
|
179
|
+
f"Pushed {self.active_span.spankind} span {self.active_span.id} to recorded spans."
|
|
172
180
|
)
|
|
181
|
+
if self.active_span.parent_span_id is None:
|
|
182
|
+
self.end_trace(parent_span=self.active_span)
|
|
183
|
+
else:
|
|
184
|
+
self.active_span = self.span_dict[self.active_span.parent_span_id]
|
|
173
185
|
|
|
174
|
-
def
|
|
175
|
-
self.end_span(outputs=outputs, span=span, **kwargs)
|
|
186
|
+
def end_trace(self, parent_span: CreateSpan):
|
|
176
187
|
if self.api_key == "":
|
|
177
188
|
return
|
|
178
189
|
|
|
179
|
-
|
|
180
|
-
|
|
190
|
+
if not self.active_trace_id:
|
|
191
|
+
raise RuntimeError("No active trace to end.")
|
|
192
|
+
|
|
193
|
+
self.llm_logger.info("Preparing to send recorded spans for processing.")
|
|
194
|
+
self.llm_logger.info(f"Recorded spans => {len(self.pending_spans)}")
|
|
181
195
|
self.tasks_manager.add_task(
|
|
182
|
-
self.
|
|
196
|
+
self.active_trace_id,
|
|
183
197
|
"trace",
|
|
184
198
|
self.client.create_traces(
|
|
185
|
-
trace=self.
|
|
199
|
+
trace=self.active_trace_id, spans=self.pending_spans # type: ignore
|
|
186
200
|
),
|
|
187
201
|
self.client,
|
|
188
202
|
)
|
|
189
203
|
self.llm_logger.info(
|
|
190
|
-
f"Tracing for {
|
|
204
|
+
f"Tracing for {parent_span.id} recorded successfully and sent for processing."
|
|
191
205
|
)
|
|
192
|
-
self.
|
|
206
|
+
self._clear_pending_spans()
|
|
207
|
+
self.active_trace_id = None
|
|
208
|
+
self.active_span = None
|
|
209
|
+
self.trace_config_cache.clear()
|
|
193
210
|
|
|
194
211
|
def _create_trace_id(self) -> str:
|
|
195
212
|
"""Creates a unique mongo id for the trace object.
|
|
@@ -209,12 +226,12 @@ class Tracing(object):
|
|
|
209
226
|
|
|
210
227
|
return str(ObjectId())
|
|
211
228
|
|
|
212
|
-
def
|
|
229
|
+
def _clear_pending_spans(self) -> None:
|
|
213
230
|
"""
|
|
214
231
|
Clear the list of recorded spans to prepare for next batch processing.
|
|
215
232
|
"""
|
|
216
233
|
|
|
217
|
-
self.
|
|
234
|
+
self.pending_spans = []
|
|
218
235
|
self.llm_logger.info(
|
|
219
|
-
f"Cleared all recorded spans from batch: {self.
|
|
236
|
+
f"Cleared all recorded spans from batch: {self.pending_spans}"
|
|
220
237
|
)
|
|
@@ -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.0a1
|
|
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)
|