agenta 0.14.14a1__py3-none-any.whl → 0.15.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.

@@ -1,4 +1,4 @@
1
- agenta/__init__.py,sha256=rCZ-mUOGnyKQpfWQFzXIEFX7KBlGC3qFMighdIVJgDc,610
1
+ agenta/__init__.py,sha256=O7kq034_S58b2yzrtR_m3Qd-0t7FAh9q7Z7_HsoD-9Y,796
2
2
  agenta/cli/evaluation_commands.py,sha256=fs6492tprPId9p8eGO02Xy-NCBm2RZNJLZWcUxugwd8,474
3
3
  agenta/cli/helper.py,sha256=vRxHyeNaltzNIGrfU2vO0H28_rXDzx9QqIZ_S-W6zL4,6212
4
4
  agenta/cli/main.py,sha256=Wz0ODhoeKK3Qg_CFUhu6D909szk05tc8ZVBB6H1-w7k,9763
@@ -10,7 +10,7 @@ agenta/client/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
10
  agenta/client/api.py,sha256=0u1vd7V2ctFEtY6KeGGiOeoDv6vyeit32u6c6BVyc4w,2434
11
11
  agenta/client/api_models.py,sha256=zebfE2-0-SW1SvzyarzmSJMXqyiCLKrX2sHpzoX-RnU,623
12
12
  agenta/client/backend/__init__.py,sha256=tkSqI-dciccMpM2diWMe7pF0SjsGXPV_kR-029xNN9w,3853
13
- agenta/client/backend/client.py,sha256=UvNYKUplPdK1AkFfRsOdyEI7hoTqNCtD_pKlkgtUGGo,73690
13
+ agenta/client/backend/client.py,sha256=LDuJbFQ9wnhBDeldrlJfOt2TsvO102fy1iKbQG4n_fE,73738
14
14
  agenta/client/backend/core/__init__.py,sha256=QJS3CJ2TYP2E1Tge0CS6Z7r8LTNzJHQVX1hD3558eP0,519
15
15
  agenta/client/backend/core/api_error.py,sha256=TtMtCdxXjd7Tasc9c8ooFg124nPrb2MXG-tKOXV4u9I,440
16
16
  agenta/client/backend/core/client_wrapper.py,sha256=kQEqxdm31r7V9x--mMliWOdMujD3dtPZyYBNzxgNdrs,972
@@ -54,7 +54,7 @@ agenta/client/backend/types/base_output.py,sha256=ynXhDBQKrkR6Lnkx-yv6Q8xW4wXmzX
54
54
  agenta/client/backend/types/body_import_testset.py,sha256=7dVF3mv3VO0Co8F0qxLAgu4jabqDPjebK4mYvcd_TuA,1061
55
55
  agenta/client/backend/types/config_db.py,sha256=P0cSYvVOn0ZxpYMIdvhWpQVjRuBS5APe6qlc69AXaF4,1028
56
56
  agenta/client/backend/types/create_app_output.py,sha256=pgnTnfZx35Q-8wZ1yTZBQ0ydYacGzFC9kyLug_UvymM,986
57
- agenta/client/backend/types/create_span.py,sha256=_3G4WUnmgXtTCkIJFpce-9PDh6KDDZ2YkvXVOE8GSx8,1793
57
+ agenta/client/backend/types/create_span.py,sha256=Ldb2zclVtVyBRKxM2Ap3YjE-FP3jbaOya96_ZsYw1cg,1794
58
58
  agenta/client/backend/types/create_trace_response.py,sha256=FO-Ii9JEn2AQ1nmZYmjnKRbACsNxRvY_-xn7Ys7Yo8A,1012
59
59
  agenta/client/backend/types/docker_env_vars.py,sha256=altCvA1k-zdAkKNYLwaCnmV48HZg9cwe2cHu_BGImac,986
60
60
  agenta/client/backend/types/environment_output.py,sha256=dl0GKodeqB7kWK5mH6Y4iBppkpwRzSTmtkXH1II4L6w,1257
@@ -119,26 +119,27 @@ agenta/client/client.py,sha256=DWOGS9A8u4wu28s9jGOR4eRhf7vo4zT7GyDvrIGu59Y,19648
119
119
  agenta/client/exceptions.py,sha256=cxLjjKvZKlUgBxt4Vn9J_SsezJPPNHvrZxnoq-D6zmw,94
120
120
  agenta/config.py,sha256=Id-Ie1yf9QRP1YPhRYaYSOruRe6RBrsCXkG9rAa-ZtA,732
121
121
  agenta/config.toml,sha256=ptE0P49bwsu3Luyn7OLFmk2buPhj5D-MA-O_ErOGoLg,223
122
- agenta/docker/docker-assets/Dockerfile.cloud.template,sha256=uJuXKvtkMY6f4KaOh3XE5pmuJR7mfZEXJk_8hj2uatc,386
122
+ agenta/docker/docker-assets/Dockerfile.cloud.template,sha256=Mn9g7bTQSnPXcCLZo-iVirV3cveCQHC_F7IECQufmME,389
123
123
  agenta/docker/docker-assets/Dockerfile.template,sha256=aVA_okx0xXalcTvdQGhSfzSjNpQZVoLJCGYA39-2Nwk,280
124
124
  agenta/docker/docker-assets/README.md,sha256=XHxwh2ks_ozrtAU7SLbL3J14SB2holG6buoTxwmMiZM,102
125
125
  agenta/docker/docker-assets/entrypoint.sh,sha256=29XK8VQjQsx4hN2j-4JDy-6kQb5y4LCqZEa7PD4eqCQ,74
126
126
  agenta/docker/docker-assets/lambda_function.py,sha256=h4UZSSfqwpfsCgERv6frqwm_4JrYu9rLz3I-LxCfeEg,83
127
127
  agenta/docker/docker-assets/main.py,sha256=7MI-21n81U7N7A0GxebNi0cmGWtJKcR2sPB6FcH2QfA,251
128
128
  agenta/docker/docker_utils.py,sha256=5uHMCzXkCvIsDdEiwbnnn97KkzsFbBvyMwogCsv_Z5U,3509
129
- agenta/sdk/__init__.py,sha256=jmeLRuXrew02ZruODZYIu4kpw0S8vV6JhMPQWFGtj30,648
130
- agenta/sdk/agenta_decorator.py,sha256=_WaU-KkqnGTQobobX0LU2QszS9RdR8oOgIFksd40wh0,20210
131
- agenta/sdk/agenta_init.py,sha256=wDfStpe8_3ZXRLtikarwDKI_VpA1YW4eIz_3fXq39is,9044
129
+ agenta/sdk/__init__.py,sha256=oHgl-qoEyi3d2VI_Kv-rIMSx9zgs6b5MP62PLq5GqYI,762
130
+ agenta/sdk/agenta_init.py,sha256=j7qwyDtXfLozWpnayJHPz2aQOzHSGvHo9V6s0FXeUe8,9937
132
131
  agenta/sdk/client.py,sha256=trKyBOYFZRk0v5Eptxvh87yPf50Y9CqY6Qgv4Fy-VH4,2142
133
132
  agenta/sdk/context.py,sha256=q-PxL05-I84puunUAs9LGsffEXcYhDxhQxjuOz2vK90,901
133
+ agenta/sdk/decorators/base.py,sha256=9aNdX5h8a2mFweuhdO-BQPwXGKY9ONPIdLRhSGAGMfY,217
134
+ agenta/sdk/decorators/llm_entrypoint.py,sha256=QjkpKEgsKzO83MNOb37MupwCX5hrm7_1-qbtbpqVMYM,19400
135
+ agenta/sdk/decorators/tracing.py,sha256=bC-YlPQUrHBEqvhLJxr63N0qlo1jvrbt7ro2AMGXXZw,3160
134
136
  agenta/sdk/router.py,sha256=0sbajvn5C7t18anH6yNo7-oYxldHnYfwcbmQnIXBePw,269
135
137
  agenta/sdk/tracing/context_manager.py,sha256=HskDaiORoOhjeN375gm05wYnieQzh5UnoIsnSAHkAyc,252
136
- agenta/sdk/tracing/decorators.py,sha256=ujtU8gf3GDoHYuLTfEYK_2eIYZ-1oX5dpv02Mf4l_II,1191
137
- agenta/sdk/tracing/llm_tracing.py,sha256=UiotJ56EFA3VPt7LREkcK2w51D9-0T1QNvBy4zNWEdY,7348
138
- agenta/sdk/tracing/logger.py,sha256=4zG9c51p8xPdKA5SL8MOgBfkpCnBSuV6JfWiXO0A7oc,473
139
- agenta/sdk/tracing/tasks_manager.py,sha256=XVGBEOwmHa6KcCC0PApk0_bZ0Ilk2ESuduNObB1rw2s,3792
140
- agenta/sdk/types.py,sha256=_rE1lPBlhwwwzPeSaPJYVaZSOg6l4alGBL8aufI8LJM,5711
141
- agenta/sdk/utils/globals.py,sha256=lpgflY8xovZJtHfJf41dbNCZGwx07YNkG9ldruv6xoI,360
138
+ agenta/sdk/tracing/llm_tracing.py,sha256=PmMYQ5N8atYut85Rk2hZ1jmvSF80Duuy6Clf7URcTCA,8193
139
+ agenta/sdk/tracing/logger.py,sha256=GfH7V-jBHcn7h5dbdrnkDMe_ml3wkXFBeoQiqR4KVRc,474
140
+ agenta/sdk/tracing/tasks_manager.py,sha256=ROrWIaqS2J2HHiJtRWiHKlLY8CCsqToP5VeXu7mamck,3748
141
+ agenta/sdk/types.py,sha256=pjVThuJ9iGbWnwmDmKJnG8S6Q_wHe1fRtMS6jknYSJM,5881
142
+ agenta/sdk/utils/globals.py,sha256=JmhJcCOSbwvjQ6GDyUc2_SYR27DZk7YcrRH80ktHHOM,435
142
143
  agenta/sdk/utils/helper/openai_cost.py,sha256=1VkgvucDnNZm1pTfcVLz9icWunntp1d7zwMmnviy3Uw,5877
143
144
  agenta/sdk/utils/preinit.py,sha256=YlJL7RLfel0R7DFp-jK7OV-z4ZIQJM0oupYlk7g8b5o,1278
144
145
  agenta/templates/compose_email/README.md,sha256=ss7vZPpI1Hg0VmYtFliwq_r5LnqbCy_S5OQDXg8UoIA,308
@@ -156,7 +157,7 @@ agenta/templates/simple_prompt/app.py,sha256=kODgF6lhzsaJPdgL5b21bUki6jkvqjWZzWR
156
157
  agenta/templates/simple_prompt/env.example,sha256=g9AE5bYcGPpxawXMJ96gh8oenEPCHTabsiOnfQo3c5k,70
157
158
  agenta/templates/simple_prompt/requirements.txt,sha256=ywRglRy7pPkw8bljmMEJJ4aOOQKrt9FGKULZ-DGkoBU,23
158
159
  agenta/templates/simple_prompt/template.toml,sha256=DQBtRrF4GU8LBEXOZ-GGuINXMQDKGTEG5y37tnvIUIE,60
159
- agenta-0.14.14a1.dist-info/METADATA,sha256=aMxaPsly0zf4DgPxBGjbMedvu46XlblNCX2N4elXV3g,26481
160
- agenta-0.14.14a1.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
161
- agenta-0.14.14a1.dist-info/entry_points.txt,sha256=PDiu8_8AsL7ibU9v4iNoOKR1S7F2rdxjlEprjM9QOgo,46
162
- agenta-0.14.14a1.dist-info/RECORD,,
160
+ agenta-0.15.0.dist-info/METADATA,sha256=fw71SzzTzKG1bcyoCV78EtObsmPtFUsUmFcAZQ6HtA4,26463
161
+ agenta-0.15.0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
162
+ agenta-0.15.0.dist-info/entry_points.txt,sha256=PDiu8_8AsL7ibU9v4iNoOKR1S7F2rdxjlEprjM9QOgo,46
163
+ agenta-0.15.0.dist-info/RECORD,,
@@ -1,570 +0,0 @@
1
- """The code for the Agenta SDK"""
2
-
3
- import os
4
- import sys
5
- import time
6
- import inspect
7
- import argparse
8
- import asyncio
9
- import traceback
10
- import functools
11
- from pathlib import Path
12
- from tempfile import NamedTemporaryFile
13
- from typing import Any, Callable, Dict, Optional, Tuple, List
14
-
15
- from fastapi.middleware.cors import CORSMiddleware
16
- from fastapi import Body, FastAPI, UploadFile, HTTPException
17
-
18
- import agenta
19
- from .context import save_context
20
- from .router import router as router
21
- from .types import (
22
- Context,
23
- DictInput,
24
- FloatParam,
25
- InFile,
26
- IntParam,
27
- MultipleChoiceParam,
28
- GroupedMultipleChoiceParam,
29
- TextParam,
30
- MessagesInput,
31
- FileInputURL,
32
- FuncResponse,
33
- BinaryParam,
34
- )
35
-
36
- app = FastAPI()
37
-
38
- origins = [
39
- "*",
40
- ]
41
-
42
- app.add_middleware(
43
- CORSMiddleware,
44
- allow_origins=origins,
45
- allow_credentials=True,
46
- allow_methods=["*"],
47
- allow_headers=["*"],
48
- )
49
-
50
- app.include_router(router, prefix="")
51
-
52
-
53
- def ingest_file(upfile: UploadFile):
54
- temp_file = NamedTemporaryFile(delete=False)
55
- temp_file.write(upfile.file.read())
56
- temp_file.close()
57
- return InFile(file_name=upfile.filename, file_path=temp_file.name)
58
-
59
-
60
- def entrypoint(func: Callable[..., Any]):
61
- """
62
- Decorator to wrap a function for HTTP POST and terminal exposure.
63
-
64
- Args:
65
- func: Function to wrap.
66
-
67
- Returns:
68
- Wrapped function for HTTP POST and terminal.
69
- """
70
-
71
- endpoint_name = "generate"
72
- func_signature = inspect.signature(func)
73
- config_params = agenta.config.all()
74
- ingestible_files = extract_ingestible_files(func_signature)
75
-
76
- # Initialize tracing
77
- tracing = agenta.llm_tracing()
78
-
79
- @functools.wraps(func)
80
- async def wrapper(*args, **kwargs) -> Any:
81
- func_params, api_config_params = split_kwargs(kwargs, config_params)
82
-
83
- # Start tracing
84
- tracing.start_parent_span(
85
- name=func.__name__,
86
- inputs=func_params,
87
- config=config_params,
88
- environment="playground", # type: ignore #NOTE: wrapper is only called in playground
89
- )
90
-
91
- # Ingest files, prepare configurations and run llm app
92
- ingest_files(func_params, ingestible_files)
93
- agenta.config.set(**api_config_params)
94
- llm_result = await execute_function(
95
- func, *args, params=func_params, config_params=config_params
96
- )
97
-
98
- # End trace recording
99
- tracing.end_recording(
100
- outputs=llm_result.model_dump(),
101
- span=tracing.active_trace, # type: ignore
102
- )
103
- return llm_result
104
-
105
- @functools.wraps(func)
106
- async def wrapper_deployed(*args, **kwargs) -> Any:
107
- func_params = {
108
- k: v for k, v in kwargs.items() if k not in ["config", "environment"]
109
- }
110
- if "environment" in kwargs and kwargs["environment"] is not None:
111
- agenta.config.pull(environment_name=kwargs["environment"])
112
- elif "config" in kwargs and kwargs["config"] is not None:
113
- agenta.config.pull(config_name=kwargs["config"])
114
- else:
115
- agenta.config.pull(config_name="default")
116
-
117
- config = agenta.config.all()
118
-
119
- # Start tracing
120
- tracing.start_parent_span(
121
- name=func.__name__,
122
- inputs=func_params,
123
- config=config,
124
- environment=kwargs["environment"], # type: ignore #NOTE: wrapper is only called in playground
125
- )
126
-
127
- llm_result = await execute_function(
128
- func, *args, params=func_params, config_params=config_params
129
- )
130
-
131
- # End trace recording
132
- tracing.end_recording(
133
- outputs=llm_result.model_dump(),
134
- span=tracing.active_trace, # type: ignore
135
- )
136
- return llm_result
137
-
138
- update_function_signature(wrapper, func_signature, config_params, ingestible_files)
139
- route = f"/{endpoint_name}"
140
- app.post(route, response_model=FuncResponse)(wrapper)
141
-
142
- update_deployed_function_signature(
143
- wrapper_deployed,
144
- func_signature,
145
- ingestible_files,
146
- )
147
-
148
- route_deployed = f"/{endpoint_name}_deployed"
149
- app.post(route_deployed, response_model=FuncResponse)(wrapper_deployed)
150
- override_schema(
151
- openapi_schema=app.openapi(),
152
- func_name=func.__name__,
153
- endpoint=endpoint_name,
154
- params={**config_params, **func_signature.parameters},
155
- )
156
-
157
- if is_main_script(func):
158
- handle_terminal_run(
159
- func,
160
- func_signature.parameters, # type: ignore
161
- config_params,
162
- ingestible_files,
163
- )
164
-
165
-
166
- def extract_ingestible_files(
167
- func_signature: inspect.Signature,
168
- ) -> Dict[str, inspect.Parameter]:
169
- """Extract parameters annotated as InFile from function signature."""
170
-
171
- return {
172
- name: param
173
- for name, param in func_signature.parameters.items()
174
- if param.annotation is InFile
175
- }
176
-
177
-
178
- def split_kwargs(
179
- kwargs: Dict[str, Any], config_params: Dict[str, Any]
180
- ) -> Tuple[Dict[str, Any], Dict[str, Any]]:
181
- """Split keyword arguments into function parameters and API configuration parameters."""
182
-
183
- func_params = {k: v for k, v in kwargs.items() if k not in config_params}
184
- api_config_params = {k: v for k, v in kwargs.items() if k in config_params}
185
- return func_params, api_config_params
186
-
187
-
188
- def ingest_files(
189
- func_params: Dict[str, Any], ingestible_files: Dict[str, inspect.Parameter]
190
- ) -> None:
191
- """Ingest files specified in function parameters."""
192
-
193
- for name in ingestible_files:
194
- if name in func_params and func_params[name] is not None:
195
- func_params[name] = ingest_file(func_params[name])
196
-
197
-
198
- async def execute_function(func: Callable[..., Any], *args, **func_params):
199
- """Execute the function and handle any exceptions."""
200
-
201
- try:
202
- """Note: The following block is for backward compatibility.
203
- It allows functions to work seamlessly whether they are synchronous or asynchronous.
204
- For synchronous functions, it calls them directly, while for asynchronous functions,
205
- it awaits their execution.
206
- """
207
- is_coroutine_function = inspect.iscoroutinefunction(func)
208
- start_time = time.perf_counter()
209
- if is_coroutine_function:
210
- result = await func(*args, **func_params["params"])
211
- else:
212
- result = func(*args, **func_params["params"])
213
-
214
- end_time = time.perf_counter()
215
- latency = end_time - start_time
216
-
217
- if isinstance(result, Context):
218
- save_context(result)
219
- if isinstance(result, Dict):
220
- return FuncResponse(**result, latency=round(latency, 4))
221
- if isinstance(result, str):
222
- return FuncResponse(message=result, latency=round(latency, 4)) # type: ignore
223
- except Exception as e:
224
- handle_exception(e)
225
- return FuncResponse(message="Unexpected error occurred", latency=0) # type: ignore
226
-
227
-
228
- def handle_exception(e: Exception):
229
- """Handle exceptions."""
230
-
231
- status_code: int = e.status_code if hasattr(e, "status_code") else 500
232
- traceback_str = traceback.format_exception(e, value=e, tb=e.__traceback__) # type: ignore
233
- raise HTTPException(
234
- status_code=status_code,
235
- detail={"error": str(e), "traceback": "".join(traceback_str)},
236
- )
237
-
238
-
239
- def update_wrapper_signature(wrapper: Callable[..., Any], updated_params: List):
240
- """
241
- Updates the signature of a wrapper function with a new list of parameters.
242
-
243
- Args:
244
- wrapper (callable): A callable object, such as a function or a method, that requires a signature update.
245
- updated_params (List[inspect.Parameter]): A list of `inspect.Parameter` objects representing the updated parameters
246
- for the wrapper function.
247
- """
248
-
249
- wrapper_signature = inspect.signature(wrapper)
250
- wrapper_signature = wrapper_signature.replace(parameters=updated_params)
251
- wrapper.__signature__ = wrapper_signature # type: ignore
252
-
253
-
254
- def update_function_signature(
255
- wrapper: Callable[..., Any],
256
- func_signature: inspect.Signature,
257
- config_params: Dict[str, Any],
258
- ingestible_files: Dict[str, inspect.Parameter],
259
- ) -> None:
260
- """Update the function signature to include new parameters."""
261
-
262
- updated_params: List[inspect.Parameter] = []
263
- add_config_params_to_parser(updated_params, config_params)
264
- add_func_params_to_parser(updated_params, func_signature, ingestible_files)
265
- update_wrapper_signature(wrapper, updated_params)
266
-
267
-
268
- def update_deployed_function_signature(
269
- wrapper: Callable[..., Any],
270
- func_signature: inspect.Signature,
271
- ingestible_files: Dict[str, inspect.Parameter],
272
- ) -> None:
273
- """Update the function signature to include new parameters."""
274
- updated_params: List[inspect.Parameter] = []
275
- add_func_params_to_parser(updated_params, func_signature, ingestible_files)
276
- for param in [
277
- "config",
278
- "environment",
279
- ]: # we add the config and environment parameters
280
- updated_params.append(
281
- inspect.Parameter(
282
- param,
283
- inspect.Parameter.KEYWORD_ONLY,
284
- default=Body(None),
285
- annotation=str,
286
- )
287
- )
288
- update_wrapper_signature(wrapper, updated_params)
289
-
290
-
291
- def add_config_params_to_parser(
292
- updated_params: list, config_params: Dict[str, Any]
293
- ) -> None:
294
- """Add configuration parameters to function signature."""
295
- for name, param in config_params.items():
296
- assert (
297
- len(param.__class__.__bases__) == 1
298
- ), f"Inherited standard type of {param.__class__} needs to be one."
299
- updated_params.append(
300
- inspect.Parameter(
301
- name,
302
- inspect.Parameter.KEYWORD_ONLY,
303
- default=Body(param),
304
- annotation=param.__class__.__bases__[
305
- 0
306
- ], # determines and get the base (parent/inheritance) type of the sdk-type at run-time. \
307
- # E.g __class__ is ag.MessagesInput() and accessing it parent type will return (<class 'list'>,), \
308
- # thus, why we are accessing the first item.
309
- )
310
- )
311
-
312
-
313
- def add_func_params_to_parser(
314
- updated_params: list,
315
- func_signature: inspect.Signature,
316
- ingestible_files: Dict[str, inspect.Parameter],
317
- ) -> None:
318
- """Add function parameters to function signature."""
319
- for name, param in func_signature.parameters.items():
320
- if name in ingestible_files:
321
- updated_params.append(
322
- inspect.Parameter(name, param.kind, annotation=UploadFile)
323
- )
324
- else:
325
- assert (
326
- len(param.default.__class__.__bases__) == 1
327
- ), f"Inherited standard type of {param.default.__class__} needs to be one."
328
- updated_params.append(
329
- inspect.Parameter(
330
- name,
331
- inspect.Parameter.KEYWORD_ONLY,
332
- default=Body(param.default),
333
- annotation=param.default.__class__.__bases__[
334
- 0
335
- ], # determines and get the base (parent/inheritance) type of the sdk-type at run-time. \
336
- # E.g __class__ is ag.MessagesInput() and accessing it parent type will return (<class 'list'>,), \
337
- # thus, why we are accessing the first item.
338
- )
339
- )
340
-
341
-
342
- def is_main_script(func: Callable) -> bool:
343
- """
344
- Check if the script containing the function is the main script being run.
345
-
346
- Args:
347
- func (Callable): The function object to check.
348
-
349
- Returns:
350
- bool: True if the script containing the function is the main script, False otherwise.
351
-
352
- Example:
353
- if is_main_script(my_function):
354
- print("This is the main script.")
355
- """
356
- return (
357
- os.path.splitext(os.path.basename(sys.argv[0]))[0]
358
- == os.path.splitext(os.path.basename(inspect.getfile(func)))[0]
359
- )
360
-
361
-
362
- def handle_terminal_run(
363
- func: Callable,
364
- func_params: Dict[str, Any],
365
- config_params: Dict[str, Any],
366
- ingestible_files: Dict,
367
- ) -> None:
368
- """
369
- Parses command line arguments and sets configuration when script is run from the terminal.
370
-
371
- Args:
372
- func_params (dict): A dictionary containing the function parameters and their annotations.
373
- config_params (dict): A dictionary containing the configuration parameters.
374
-
375
- Example:
376
- handle_terminal_run(func_params=inspect.signature(my_function).parameters, config_params=config.all())
377
- """
378
-
379
- # For required parameters, we add them as arguments
380
- parser = argparse.ArgumentParser()
381
- for name, param in func_params.items():
382
- if name in ingestible_files:
383
- parser.add_argument(name, type=str)
384
- else:
385
- parser.add_argument(name, type=param.annotation)
386
-
387
- for name, param in config_params.items():
388
- if type(param) is MultipleChoiceParam:
389
- parser.add_argument(
390
- f"--{name}",
391
- type=str,
392
- default=param.default, # type: ignore
393
- choices=param.choices, # type: ignore
394
- )
395
- else:
396
- parser.add_argument(
397
- f"--{name}",
398
- type=type(param),
399
- default=param,
400
- )
401
-
402
- args = parser.parse_args()
403
-
404
- # split the arg list into the arg in the app_param and
405
- # the args from the sig.parameter
406
- args_config_params = {k: v for k, v in vars(args).items() if k in config_params}
407
- args_func_params = {k: v for k, v in vars(args).items() if k not in config_params}
408
- for name in ingestible_files:
409
- args_func_params[name] = InFile(
410
- file_name=Path(args_func_params[name]).stem,
411
- file_path=args_func_params[name],
412
- )
413
- agenta.config.set(**args_config_params)
414
-
415
- loop = asyncio.get_event_loop()
416
- result = loop.run_until_complete(
417
- execute_function(
418
- func, **{"params": args_func_params, "config_params": args_config_params}
419
- )
420
- )
421
- print(result)
422
-
423
-
424
- def override_schema(openapi_schema: dict, func_name: str, endpoint: str, params: dict):
425
- """
426
- Overrides the default openai schema generated by fastapi with additional information about:
427
- - The choices available for each MultipleChoiceParam instance
428
- - The min and max values for each FloatParam instance
429
- - The min and max values for each IntParam instance
430
- - The default value for DictInput instance
431
- - The default value for MessagesParam instance
432
- - The default value for FileInputURL instance
433
- - The default value for BinaryParam instance
434
- - ... [PLEASE ADD AT EACH CHANGE]
435
-
436
- Args:
437
- openapi_schema (dict): The openapi schema generated by fastapi
438
- func_name (str): The name of the function to override
439
- endpoint (str): The name of the endpoint to override
440
- params (dict(param_name, param_val)): The dictionary of the parameters for the function
441
- """
442
-
443
- def find_in_schema(
444
- schema_type_properties: dict, schema: dict, param_name: str, xparam: str
445
- ):
446
- """Finds a parameter in the schema based on its name and x-parameter value"""
447
- for _, value in schema.items():
448
- value_title_lower = str(value.get("title")).lower()
449
- value_title = (
450
- "_".join(value_title_lower.split())
451
- if len(value_title_lower.split()) >= 2
452
- else value_title_lower
453
- )
454
-
455
- if (
456
- isinstance(value, dict)
457
- and schema_type_properties.get("x-parameter") == xparam
458
- and value_title == param_name
459
- ):
460
- # this will update the default type schema with the properties gotten
461
- # from the schema type (param_val) __schema_properties__ classmethod
462
- for type_key, type_value in schema_type_properties.items():
463
- # BEFORE:
464
- # value = {'temperature': {'title': 'Temperature'}}
465
- value[type_key] = type_value
466
- # AFTER:
467
- # value = {'temperature': { "type": "number", "title": "Temperature", "x-parameter": "float" }}
468
- return value
469
-
470
- schema_to_override = openapi_schema["components"]["schemas"][
471
- f"Body_{func_name}_{endpoint}_post"
472
- ]["properties"]
473
- for param_name, param_val in params.items():
474
- if isinstance(param_val, GroupedMultipleChoiceParam):
475
- subschema = find_in_schema(
476
- param_val.__schema_type_properties__(),
477
- schema_to_override,
478
- param_name,
479
- "grouped_choice",
480
- )
481
- assert (
482
- subschema
483
- ), f"GroupedMultipleChoiceParam '{param_name}' is in the parameters but could not be found in the openapi.json"
484
- subschema["choices"] = param_val.choices # type: ignore
485
- subschema["default"] = param_val.default # type: ignore
486
- if isinstance(param_val, MultipleChoiceParam):
487
- subschema = find_in_schema(
488
- param_val.__schema_type_properties__(),
489
- schema_to_override,
490
- param_name,
491
- "choice",
492
- )
493
- default = str(param_val)
494
- param_choices = param_val.choices # type: ignore
495
- choices = (
496
- [default] + param_choices
497
- if param_val not in param_choices
498
- else param_choices
499
- )
500
- subschema["enum"] = choices
501
- subschema["default"] = default if default in param_choices else choices[0]
502
- if isinstance(param_val, FloatParam):
503
- subschema = find_in_schema(
504
- param_val.__schema_type_properties__(),
505
- schema_to_override,
506
- param_name,
507
- "float",
508
- )
509
- subschema["minimum"] = param_val.minval # type: ignore
510
- subschema["maximum"] = param_val.maxval # type: ignore
511
- subschema["default"] = param_val
512
- if isinstance(param_val, IntParam):
513
- subschema = find_in_schema(
514
- param_val.__schema_type_properties__(),
515
- schema_to_override,
516
- param_name,
517
- "int",
518
- )
519
- subschema["minimum"] = param_val.minval # type: ignore
520
- subschema["maximum"] = param_val.maxval # type: ignore
521
- subschema["default"] = param_val
522
- if (
523
- isinstance(param_val, inspect.Parameter)
524
- and param_val.annotation is DictInput
525
- ):
526
- subschema = find_in_schema(
527
- param_val.annotation.__schema_type_properties__(),
528
- schema_to_override,
529
- param_name,
530
- "dict",
531
- )
532
- subschema["default"] = param_val.default["default_keys"]
533
- if isinstance(param_val, TextParam):
534
- subschema = find_in_schema(
535
- param_val.__schema_type_properties__(),
536
- schema_to_override,
537
- param_name,
538
- "text",
539
- )
540
- subschema["default"] = param_val
541
- if (
542
- isinstance(param_val, inspect.Parameter)
543
- and param_val.annotation is MessagesInput
544
- ):
545
- subschema = find_in_schema(
546
- param_val.annotation.__schema_type_properties__(),
547
- schema_to_override,
548
- param_name,
549
- "messages",
550
- )
551
- subschema["default"] = param_val.default
552
- if (
553
- isinstance(param_val, inspect.Parameter)
554
- and param_val.annotation is FileInputURL
555
- ):
556
- subschema = find_in_schema(
557
- param_val.annotation.__schema_type_properties__(),
558
- schema_to_override,
559
- param_name,
560
- "file_url",
561
- )
562
- subschema["default"] = "https://example.com"
563
- if isinstance(param_val, BinaryParam):
564
- subschema = find_in_schema(
565
- param_val.__schema_type_properties__(),
566
- schema_to_override,
567
- param_name,
568
- "bool",
569
- )
570
- subschema["default"] = param_val.default # type: ignore
@@ -1,41 +0,0 @@
1
- # Stdlib Imports
2
- import inspect
3
- from functools import wraps
4
-
5
- # Own Imports
6
- import agenta as ag
7
-
8
-
9
- def span(type: str):
10
- """Decorator to automatically start and end spans."""
11
-
12
- tracing = ag.llm_tracing()
13
-
14
- def decorator(func):
15
- @wraps(func)
16
- async def wrapper(*args, **kwargs):
17
- result = None
18
- span = tracing.start_span(
19
- name=func.__name__,
20
- input=kwargs,
21
- spankind=type,
22
- )
23
- try:
24
- is_coroutine_function = inspect.iscoroutinefunction(func)
25
- if is_coroutine_function:
26
- result = await func(*args, **kwargs)
27
- else:
28
- result = func(*args, **kwargs)
29
- tracing.update_span_status(span=span, value="OK")
30
- except Exception as e:
31
- result = str(e)
32
- tracing.update_span_status(span=span, value="ERROR")
33
- finally:
34
- if not isinstance(result, dict):
35
- result = {"message": result}
36
- tracing.end_span(outputs=result, span=span)
37
- return result
38
-
39
- return wrapper
40
-
41
- return decorator