agenta 0.36.2__py3-none-any.whl → 0.36.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.

Files changed (209) hide show
  1. agenta/__init__.py +5 -5
  2. agenta/client/Readme.md +3 -3
  3. agenta/client/__init__.py +294 -0
  4. agenta/client/client.py +3192 -466
  5. agenta/sdk/__init__.py +5 -5
  6. agenta/sdk/agenta_init.py +28 -54
  7. agenta/sdk/client.py +1 -1
  8. agenta/sdk/managers/shared.py +3 -3
  9. agenta/sdk/middleware/auth.py +18 -9
  10. agenta/sdk/middleware/config.py +0 -2
  11. agenta/sdk/middleware/vault.py +3 -3
  12. agenta/sdk/types.py +2 -2
  13. {agenta-0.36.2.dist-info → agenta-0.36.4.dist-info}/METADATA +1 -2
  14. agenta-0.36.4.dist-info/RECORD +236 -0
  15. agenta/cli/helper.py +0 -202
  16. agenta/cli/main.py +0 -229
  17. agenta/cli/telemetry.py +0 -50
  18. agenta/cli/variant_commands.py +0 -526
  19. agenta/cli/variant_configs.py +0 -49
  20. agenta/client/api.py +0 -74
  21. agenta/client/api_models.py +0 -34
  22. agenta/client/backend/__init__.py +0 -294
  23. agenta/client/backend/client.py +0 -3289
  24. agenta/client/exceptions.py +0 -2
  25. agenta/docker/docker-assets/Dockerfile.cloud.template +0 -9
  26. agenta/docker/docker-assets/Dockerfile.oss.template +0 -13
  27. agenta/docker/docker-assets/Dockerfile.template +0 -13
  28. agenta/docker/docker-assets/README.md +0 -1
  29. agenta/docker/docker-assets/entrypoint.sh +0 -7
  30. agenta/docker/docker-assets/lambda_function.py +0 -6
  31. agenta/docker/docker-assets/main.py +0 -13
  32. agenta/docker/docker_utils.py +0 -100
  33. agenta-0.36.2.dist-info/RECORD +0 -255
  34. agenta-0.36.2.dist-info/entry_points.txt +0 -3
  35. /agenta/client/{backend/access_control → access_control}/__init__.py +0 -0
  36. /agenta/client/{backend/access_control → access_control}/client.py +0 -0
  37. /agenta/client/{backend/admin → admin}/__init__.py +0 -0
  38. /agenta/client/{backend/admin → admin}/client.py +0 -0
  39. /agenta/client/{backend/apps → apps}/__init__.py +0 -0
  40. /agenta/client/{backend/apps → apps}/client.py +0 -0
  41. /agenta/client/{backend/bases → bases}/__init__.py +0 -0
  42. /agenta/client/{backend/bases → bases}/client.py +0 -0
  43. /agenta/client/{backend/configs → configs}/__init__.py +0 -0
  44. /agenta/client/{backend/configs → configs}/client.py +0 -0
  45. /agenta/client/{backend/containers → containers}/__init__.py +0 -0
  46. /agenta/client/{backend/containers → containers}/client.py +0 -0
  47. /agenta/client/{backend/containers → containers}/types/__init__.py +0 -0
  48. /agenta/client/{backend/containers → containers}/types/container_templates_response.py +0 -0
  49. /agenta/client/{backend/core → core}/__init__.py +0 -0
  50. /agenta/client/{backend/core → core}/api_error.py +0 -0
  51. /agenta/client/{backend/core → core}/client_wrapper.py +0 -0
  52. /agenta/client/{backend/core → core}/datetime_utils.py +0 -0
  53. /agenta/client/{backend/core → core}/file.py +0 -0
  54. /agenta/client/{backend/core → core}/http_client.py +0 -0
  55. /agenta/client/{backend/core → core}/jsonable_encoder.py +0 -0
  56. /agenta/client/{backend/core → core}/pydantic_utilities.py +0 -0
  57. /agenta/client/{backend/core → core}/query_encoder.py +0 -0
  58. /agenta/client/{backend/core → core}/remove_none_from_dict.py +0 -0
  59. /agenta/client/{backend/core → core}/request_options.py +0 -0
  60. /agenta/client/{backend/core → core}/serialization.py +0 -0
  61. /agenta/client/{backend/environments → environments}/__init__.py +0 -0
  62. /agenta/client/{backend/environments → environments}/client.py +0 -0
  63. /agenta/client/{backend/errors → errors}/__init__.py +0 -0
  64. /agenta/client/{backend/errors → errors}/unprocessable_entity_error.py +0 -0
  65. /agenta/client/{backend/evaluations → evaluations}/__init__.py +0 -0
  66. /agenta/client/{backend/evaluations → evaluations}/client.py +0 -0
  67. /agenta/client/{backend/evaluators → evaluators}/__init__.py +0 -0
  68. /agenta/client/{backend/evaluators → evaluators}/client.py +0 -0
  69. /agenta/client/{backend/human_evaluations → human_evaluations}/__init__.py +0 -0
  70. /agenta/client/{backend/human_evaluations → human_evaluations}/client.py +0 -0
  71. /agenta/client/{backend/observability → observability}/__init__.py +0 -0
  72. /agenta/client/{backend/observability → observability}/client.py +0 -0
  73. /agenta/client/{backend/observability → observability}/types/__init__.py +0 -0
  74. /agenta/client/{backend/observability → observability}/types/format.py +0 -0
  75. /agenta/client/{backend/observability → observability}/types/query_analytics_response.py +0 -0
  76. /agenta/client/{backend/observability → observability}/types/query_traces_response.py +0 -0
  77. /agenta/client/{backend/scopes → scopes}/__init__.py +0 -0
  78. /agenta/client/{backend/scopes → scopes}/client.py +0 -0
  79. /agenta/client/{backend/testsets → testsets}/__init__.py +0 -0
  80. /agenta/client/{backend/testsets → testsets}/client.py +0 -0
  81. /agenta/client/{backend/types → types}/__init__.py +0 -0
  82. /agenta/client/{backend/types → types}/account_response.py +0 -0
  83. /agenta/client/{backend/types → types}/agenta_node_dto.py +0 -0
  84. /agenta/client/{backend/types → types}/agenta_node_dto_nodes_value.py +0 -0
  85. /agenta/client/{backend/types → types}/agenta_nodes_response.py +0 -0
  86. /agenta/client/{backend/types → types}/agenta_root_dto.py +0 -0
  87. /agenta/client/{backend/types → types}/agenta_roots_response.py +0 -0
  88. /agenta/client/{backend/types → types}/agenta_tree_dto.py +0 -0
  89. /agenta/client/{backend/types → types}/agenta_trees_response.py +0 -0
  90. /agenta/client/{backend/types → types}/aggregated_result.py +0 -0
  91. /agenta/client/{backend/types → types}/aggregated_result_evaluator_config.py +0 -0
  92. /agenta/client/{backend/types → types}/analytics_response.py +0 -0
  93. /agenta/client/{backend/types → types}/app.py +0 -0
  94. /agenta/client/{backend/types → types}/app_variant_response.py +0 -0
  95. /agenta/client/{backend/types → types}/app_variant_revision.py +0 -0
  96. /agenta/client/{backend/types → types}/base_output.py +0 -0
  97. /agenta/client/{backend/types → types}/body_import_testset.py +0 -0
  98. /agenta/client/{backend/types → types}/bucket_dto.py +0 -0
  99. /agenta/client/{backend/types → types}/collect_status_response.py +0 -0
  100. /agenta/client/{backend/types → types}/config_db.py +0 -0
  101. /agenta/client/{backend/types → types}/config_dto.py +0 -0
  102. /agenta/client/{backend/types → types}/config_response_model.py +0 -0
  103. /agenta/client/{backend/types → types}/correct_answer.py +0 -0
  104. /agenta/client/{backend/types → types}/create_app_output.py +0 -0
  105. /agenta/client/{backend/types → types}/delete_evaluation.py +0 -0
  106. /agenta/client/{backend/types → types}/docker_env_vars.py +0 -0
  107. /agenta/client/{backend/types → types}/environment_output.py +0 -0
  108. /agenta/client/{backend/types → types}/environment_output_extended.py +0 -0
  109. /agenta/client/{backend/types → types}/environment_revision.py +0 -0
  110. /agenta/client/{backend/types → types}/error.py +0 -0
  111. /agenta/client/{backend/types → types}/evaluation.py +0 -0
  112. /agenta/client/{backend/types → types}/evaluation_scenario.py +0 -0
  113. /agenta/client/{backend/types → types}/evaluation_scenario_input.py +0 -0
  114. /agenta/client/{backend/types → types}/evaluation_scenario_output.py +0 -0
  115. /agenta/client/{backend/types → types}/evaluation_scenario_result.py +0 -0
  116. /agenta/client/{backend/types → types}/evaluation_status_enum.py +0 -0
  117. /agenta/client/{backend/types → types}/evaluation_type.py +0 -0
  118. /agenta/client/{backend/types → types}/evaluator.py +0 -0
  119. /agenta/client/{backend/types → types}/evaluator_config.py +0 -0
  120. /agenta/client/{backend/types → types}/evaluator_mapping_output_interface.py +0 -0
  121. /agenta/client/{backend/types → types}/evaluator_output_interface.py +0 -0
  122. /agenta/client/{backend/types → types}/exception_dto.py +0 -0
  123. /agenta/client/{backend/types → types}/get_config_response.py +0 -0
  124. /agenta/client/{backend/types → types}/header_dto.py +0 -0
  125. /agenta/client/{backend/types → types}/http_validation_error.py +0 -0
  126. /agenta/client/{backend/types → types}/human_evaluation.py +0 -0
  127. /agenta/client/{backend/types → types}/human_evaluation_scenario.py +0 -0
  128. /agenta/client/{backend/types → types}/human_evaluation_scenario_input.py +0 -0
  129. /agenta/client/{backend/types → types}/human_evaluation_scenario_output.py +0 -0
  130. /agenta/client/{backend/types → types}/image.py +0 -0
  131. /agenta/client/{backend/types → types}/invite_request.py +0 -0
  132. /agenta/client/{backend/types → types}/legacy_analytics_response.py +0 -0
  133. /agenta/client/{backend/types → types}/legacy_data_point.py +0 -0
  134. /agenta/client/{backend/types → types}/legacy_scope_request.py +0 -0
  135. /agenta/client/{backend/types → types}/legacy_scopes_response.py +0 -0
  136. /agenta/client/{backend/types → types}/legacy_user_request.py +0 -0
  137. /agenta/client/{backend/types → types}/legacy_user_response.py +0 -0
  138. /agenta/client/{backend/types → types}/lifecycle_dto.py +0 -0
  139. /agenta/client/{backend/types → types}/link_dto.py +0 -0
  140. /agenta/client/{backend/types → types}/list_api_keys_response.py +0 -0
  141. /agenta/client/{backend/types → types}/llm_run_rate_limit.py +0 -0
  142. /agenta/client/{backend/types → types}/metrics_dto.py +0 -0
  143. /agenta/client/{backend/types → types}/new_testset.py +0 -0
  144. /agenta/client/{backend/types → types}/node_dto.py +0 -0
  145. /agenta/client/{backend/types → types}/node_type.py +0 -0
  146. /agenta/client/{backend/types → types}/o_tel_context_dto.py +0 -0
  147. /agenta/client/{backend/types → types}/o_tel_event_dto.py +0 -0
  148. /agenta/client/{backend/types → types}/o_tel_extra_dto.py +0 -0
  149. /agenta/client/{backend/types → types}/o_tel_link_dto.py +0 -0
  150. /agenta/client/{backend/types → types}/o_tel_span_dto.py +0 -0
  151. /agenta/client/{backend/types → types}/o_tel_span_kind.py +0 -0
  152. /agenta/client/{backend/types → types}/o_tel_spans_response.py +0 -0
  153. /agenta/client/{backend/types → types}/o_tel_status_code.py +0 -0
  154. /agenta/client/{backend/types → types}/organization.py +0 -0
  155. /agenta/client/{backend/types → types}/organization_membership_request.py +0 -0
  156. /agenta/client/{backend/types → types}/organization_output.py +0 -0
  157. /agenta/client/{backend/types → types}/organization_request.py +0 -0
  158. /agenta/client/{backend/types → types}/parent_dto.py +0 -0
  159. /agenta/client/{backend/types → types}/permission.py +0 -0
  160. /agenta/client/{backend/types → types}/project_membership_request.py +0 -0
  161. /agenta/client/{backend/types → types}/project_request.py +0 -0
  162. /agenta/client/{backend/types → types}/project_scope.py +0 -0
  163. /agenta/client/{backend/types → types}/projects_response.py +0 -0
  164. /agenta/client/{backend/types → types}/provider_key_dto.py +0 -0
  165. /agenta/client/{backend/types → types}/provider_kind.py +0 -0
  166. /agenta/client/{backend/types → types}/reference.py +0 -0
  167. /agenta/client/{backend/types → types}/reference_dto.py +0 -0
  168. /agenta/client/{backend/types → types}/reference_request_model.py +0 -0
  169. /agenta/client/{backend/types → types}/result.py +0 -0
  170. /agenta/client/{backend/types → types}/role.py +0 -0
  171. /agenta/client/{backend/types → types}/root_dto.py +0 -0
  172. /agenta/client/{backend/types → types}/scopes_response_model.py +0 -0
  173. /agenta/client/{backend/types → types}/score.py +0 -0
  174. /agenta/client/{backend/types → types}/secret_dto.py +0 -0
  175. /agenta/client/{backend/types → types}/secret_kind.py +0 -0
  176. /agenta/client/{backend/types → types}/secret_response_dto.py +0 -0
  177. /agenta/client/{backend/types → types}/simple_evaluation_output.py +0 -0
  178. /agenta/client/{backend/types → types}/span_dto.py +0 -0
  179. /agenta/client/{backend/types → types}/span_dto_nodes_value.py +0 -0
  180. /agenta/client/{backend/types → types}/status_code.py +0 -0
  181. /agenta/client/{backend/types → types}/status_dto.py +0 -0
  182. /agenta/client/{backend/types → types}/template.py +0 -0
  183. /agenta/client/{backend/types → types}/template_image_info.py +0 -0
  184. /agenta/client/{backend/types → types}/test_set_output_response.py +0 -0
  185. /agenta/client/{backend/types → types}/test_set_simple_response.py +0 -0
  186. /agenta/client/{backend/types → types}/time_dto.py +0 -0
  187. /agenta/client/{backend/types → types}/tree_dto.py +0 -0
  188. /agenta/client/{backend/types → types}/tree_type.py +0 -0
  189. /agenta/client/{backend/types → types}/update_app_output.py +0 -0
  190. /agenta/client/{backend/types → types}/uri.py +0 -0
  191. /agenta/client/{backend/types → types}/user_request.py +0 -0
  192. /agenta/client/{backend/types → types}/validation_error.py +0 -0
  193. /agenta/client/{backend/types → types}/validation_error_loc_item.py +0 -0
  194. /agenta/client/{backend/types → types}/variant_action.py +0 -0
  195. /agenta/client/{backend/types → types}/variant_action_enum.py +0 -0
  196. /agenta/client/{backend/types → types}/workspace_member_response.py +0 -0
  197. /agenta/client/{backend/types → types}/workspace_membership_request.py +0 -0
  198. /agenta/client/{backend/types → types}/workspace_permission.py +0 -0
  199. /agenta/client/{backend/types → types}/workspace_request.py +0 -0
  200. /agenta/client/{backend/types → types}/workspace_response.py +0 -0
  201. /agenta/client/{backend/types → types}/workspace_role.py +0 -0
  202. /agenta/client/{backend/types → types}/workspace_role_response.py +0 -0
  203. /agenta/client/{backend/variants → variants}/__init__.py +0 -0
  204. /agenta/client/{backend/variants → variants}/client.py +0 -0
  205. /agenta/client/{backend/variants → variants}/types/__init__.py +0 -0
  206. /agenta/client/{backend/variants → variants}/types/add_variant_from_base_and_config_response.py +0 -0
  207. /agenta/client/{backend/vault → vault}/__init__.py +0 -0
  208. /agenta/client/{backend/vault → vault}/client.py +0 -0
  209. {agenta-0.36.2.dist-info → agenta-0.36.4.dist-info}/WHEEL +0 -0
@@ -1,526 +0,0 @@
1
- import os
2
- import re
3
- import sys
4
- from typing import List
5
- from pathlib import Path
6
-
7
- from requests.exceptions import ConnectionError
8
-
9
- import click
10
- import questionary
11
- import toml
12
-
13
- from agenta.cli import helper
14
- from agenta.cli.telemetry import event_track
15
- from agenta.client.backend.client import AgentaApi
16
- from agenta.client.api import add_variant_to_server
17
- from agenta.client.api_models import AppVariant, Image
18
- from agenta.docker.docker_utils import build_tar_docker_container
19
- from agenta.client.backend.types.variant_action import VariantAction
20
-
21
-
22
- BACKEND_URL_SUFFIX = os.environ.get("BACKEND_URL_SUFFIX", "api")
23
-
24
-
25
- @click.group()
26
- def variant():
27
- """Commands for variants"""
28
- pass
29
-
30
-
31
- def add_variant(
32
- app_folder: str, file_name: str, host: str, overwrite: bool, config_name="default"
33
- ) -> str:
34
- """
35
- Adds a variant to the backend. Sends the code as a tar to the backend, which then containerizes it and adds it to the backend store.
36
- The app variant name to be added is
37
- {file_name.removesuffix(".py")}.{config_name}
38
- Args:
39
- variant_name: the name of the variant
40
- app_folder: the folder of the app
41
- file_name: the name of the file to run.
42
- config_name: the name of the config to use for now it is always default
43
- Returns:
44
- the name of the code base and variant(useful for serve)
45
- """
46
-
47
- app_path = Path(app_folder)
48
- config_file = app_path / "config.toml"
49
- config = toml.load(config_file)
50
-
51
- app_name = config["app_name"]
52
- app_id = config["app_id"]
53
- api_key = config.get("api_key", "")
54
-
55
- config_name = "default"
56
- base_name = file_name.removesuffix(".py")
57
- variant_name = f"{base_name}.{config_name}"
58
-
59
- # check files in folder
60
- app_file = app_path / file_name
61
- if not app_file.exists():
62
- click.echo(
63
- click.style(
64
- f"No {file_name} exists! Please make sure you are in the right directory",
65
- fg="red",
66
- )
67
- )
68
- return None
69
-
70
- env_file = app_path / ".env"
71
- if not env_file.exists():
72
- continue_without_env = questionary.confirm(
73
- "No .env file found! Are you sure you handled the API keys needed in your application?\n Do you want to continue without it?"
74
- ).ask()
75
- if not continue_without_env:
76
- click.echo("Operation cancelled.")
77
- sys.exit(0)
78
-
79
- requirements_file = app_path / "requirements.txt"
80
- if not requirements_file.exists():
81
- continue_without_requirements = questionary.confirm(
82
- "No requirements.txt file found! Are you sure you do not need it in your application?\n Do you want to continue without it?"
83
- ).ask()
84
- if not continue_without_requirements:
85
- click.echo("Operation cancelled.")
86
- sys.exit(0)
87
-
88
- # Validate variant name
89
- if not re.match("^[a-zA-Z0-9_]+$", base_name):
90
- click.echo(
91
- click.style(
92
- "Invalid input. Please use only alphanumeric characters without spaces in the filename.",
93
- fg="red",
94
- )
95
- )
96
- sys.exit(0)
97
-
98
- # update the config file with the variant names from the backend
99
- variant_name = f"{base_name}.{config_name}"
100
-
101
- client = AgentaApi(
102
- base_url=f"{host}/{BACKEND_URL_SUFFIX}",
103
- api_key=api_key,
104
- )
105
-
106
- if variant_name in config["variants"] and not overwrite:
107
- if not overwrite:
108
- overwrite = questionary.confirm(
109
- "This variant already exists. Do you want to overwrite it?"
110
- ).ask()
111
- if not overwrite:
112
- click.echo("Operation cancelled.")
113
- return
114
-
115
- try:
116
- click.echo(
117
- click.style(
118
- f"Preparing code base {base_name} into a tar file...",
119
- fg="bright_black",
120
- )
121
- )
122
- tar_path = build_tar_docker_container(folder=app_path, file_name=file_name)
123
-
124
- click.echo(
125
- click.style(
126
- f"Building code base {base_name} for {variant_name} into a docker image...",
127
- fg="bright_black",
128
- )
129
- )
130
- with tar_path.open("rb") as tar_file:
131
- built_image: Image = client.containers.build_image(
132
- app_id=app_id,
133
- base_name=base_name,
134
- tar_file=tar_file,
135
- )
136
- image = Image(**built_image.dict())
137
- if tar_path.exists():
138
- tar_path.unlink()
139
-
140
- except Exception as ex:
141
- click.echo(click.style(f"Error while building image: {ex}", fg="red"))
142
- raise
143
- try:
144
- if overwrite:
145
- click.echo(
146
- click.style(
147
- f"Updating {base_name} to server...",
148
- fg="bright_black",
149
- )
150
- )
151
- variant_id = config["variant_ids"][config["variants"].index(variant_name)]
152
- client.variants.update_variant_image(
153
- variant_id=variant_id,
154
- docker_id=image.docker_id,
155
- tags=image.tags,
156
- type=image.type,
157
- ) # this automatically restarts
158
- else:
159
- click.echo(click.style(f"Adding {variant_name} to server...", fg="yellow"))
160
- response = add_variant_to_server(
161
- app_id,
162
- base_name,
163
- image,
164
- f"{host}/{BACKEND_URL_SUFFIX}",
165
- api_key,
166
- )
167
- variant_id = response["variant_id"]
168
- config["variants"].append(variant_name)
169
- config["variant_ids"].append(variant_id)
170
- except Exception as ex:
171
- if overwrite:
172
- click.echo(click.style(f"Error while updating variant: {ex}", fg="red"))
173
- else:
174
- click.echo(click.style(f"Error while adding variant: {ex}", fg="red"))
175
- raise
176
-
177
- agenta_dir = Path.home() / ".agenta"
178
- global_toml_file = toml.load(agenta_dir / "config.toml")
179
- tracking_enabled: bool = global_toml_file["telemetry_tracking_enabled"]
180
- if overwrite:
181
- # Track a deployment event
182
- if tracking_enabled:
183
- get_user_id = client.fetch_user_profile()
184
- user_id = get_user_id["id"]
185
- event_track.capture_event(
186
- "app_deployment",
187
- body={
188
- "app_id": app_id,
189
- "deployed_by": user_id,
190
- "environment": "CLI",
191
- "version": "cloud" if api_key else "oss",
192
- },
193
- )
194
-
195
- click.echo(
196
- click.style(
197
- f"Variant {variant_name} for App {app_name} updated successfully 🎉",
198
- bold=True,
199
- fg="green",
200
- )
201
- )
202
- else:
203
- # Track a deployment event
204
- if tracking_enabled:
205
- get_user_id = client.fetch_user_profile()
206
- user_id = get_user_id["id"]
207
- event_track.capture_event(
208
- "app_deployment",
209
- body={
210
- "app_id": app_id,
211
- "deployed_by": user_id,
212
- "environment": "CLI",
213
- "version": "cloud" if api_key else "oss",
214
- },
215
- )
216
-
217
- click.echo(
218
- click.style(
219
- f"Variant {variant_name} for App {app_name} added successfully to Agenta!",
220
- fg="green",
221
- )
222
- )
223
- # Last step us to save the config file
224
- toml.dump(config, config_file.open("w"))
225
- if overwrite:
226
- # In the case we are overwriting, don't return anything. Otherwise the command server would attempt to start the container which would result in an error!!!
227
- # TODO: Improve this stupid design
228
- return None
229
- else:
230
- return variant_id
231
-
232
-
233
- def start_variant(variant_id: str, app_folder: str, host: str):
234
- """
235
- Starts a container for an existing variant
236
- Args:
237
- variant_name: the name of the variant
238
- app_folder: the folder of the app
239
- """
240
- app_folder = Path(app_folder)
241
- config_file = app_folder / "config.toml"
242
- config = toml.load(config_file)
243
- app_id = config["app_id"]
244
- api_key = config.get("api_key", "")
245
-
246
- if len(config["variants"]) == 0:
247
- click.echo("No variants found. Please add a variant first.")
248
- return
249
-
250
- if variant_id:
251
- if variant_id not in config["variant_ids"]:
252
- click.echo(
253
- click.style(
254
- f"Variant {variant_id} not found in backend. Maybe you removed it in the webUI?",
255
- fg="red",
256
- )
257
- )
258
- return
259
- else:
260
- variant_name = questionary.select(
261
- "Please choose a variant", choices=config["variants"]
262
- ).ask()
263
- variant_id = config["variant_ids"][config["variants"].index(variant_name)]
264
-
265
- client = AgentaApi(
266
- base_url=f"{host}/{BACKEND_URL_SUFFIX}",
267
- api_key=api_key,
268
- )
269
-
270
- variant = client.variants.start_variant(
271
- variant_id=variant_id,
272
- action=VariantAction(action="START"),
273
- )
274
- endpoint = variant.uri
275
- click.echo("\n" + click.style("Congratulations! 🎉", bold=True, fg="green"))
276
- click.echo(
277
- click.style("Your app has been deployed locally as an API. 🚀", fg="cyan")
278
- + click.style(" You can access it here: ", fg="white")
279
- + click.style(f"{endpoint}/", bold=True, fg="yellow")
280
- )
281
-
282
- click.echo(
283
- click.style("\nRead the API documentation. 📚", fg="cyan")
284
- + click.style(" It's available at: ", fg="white")
285
- + click.style(f"{endpoint}/docs", bold=True, fg="yellow")
286
- )
287
-
288
- webui_host = "http://localhost" if host == "localhost" else host
289
- click.echo(
290
- click.style(
291
- "\nStart experimenting with your app in the playground. 🎮",
292
- fg="cyan",
293
- )
294
- + click.style(" Go to: ", fg="white")
295
- + click.style(f"{webui_host}/apps/{app_id}/playground", bold=True, fg="yellow")
296
- + "\n"
297
- )
298
-
299
-
300
- def remove_variant(variant_name: str, app_folder: str, host: str):
301
- """
302
- Removes a variant from the server
303
- Args:
304
- variant_name: the name of the variant
305
- app_folder: the folder of the app
306
- """
307
- config_file = Path(app_folder) / "config.toml"
308
- config = toml.load(config_file)
309
- app_name = config["app_name"]
310
- api_key = config.get("api_key", "")
311
-
312
- if not config["variants"]:
313
- click.echo(
314
- click.style(
315
- f"No variants found for app {app_name}. Make sure you have deployed at least one variant.",
316
- fg="red",
317
- )
318
- )
319
- return
320
-
321
- if variant_name:
322
- if variant_name not in config["variants"]:
323
- click.echo(
324
- click.style(
325
- f"Variant {variant_name} not found in backend. Maybe you already removed it in the webUI?",
326
- fg="red",
327
- )
328
- )
329
- return
330
- else:
331
- variant_name = questionary.select(
332
- "Please choose a variant", choices=config["variants"]
333
- ).ask()
334
- variant_id = config["variant_ids"][config["variants"].index(variant_name)]
335
-
336
- client = AgentaApi(
337
- base_url=f"{host}/{BACKEND_URL_SUFFIX}",
338
- api_key=api_key,
339
- )
340
-
341
- try:
342
- client.variants.remove_variant(variant_id=variant_id)
343
- except Exception as ex:
344
- click.echo(
345
- click.style(
346
- f"Error while removing variant {variant_name} for App {app_name} from the backend",
347
- fg="red",
348
- )
349
- )
350
- click.echo(click.style(f"Error message: {ex}", fg="red"))
351
- return
352
-
353
- click.echo(
354
- click.style(
355
- f"Variant {variant_name} for App {app_name} removed successfully from Agenta!",
356
- fg="green",
357
- )
358
- )
359
-
360
-
361
- def list_variants(app_folder: str, host: str):
362
- """List available variants for an app and print them to the console
363
-
364
- Arguments:
365
- app_folder -- _description_
366
- """
367
- config_file = Path(app_folder) / "config.toml"
368
- config = toml.load(config_file)
369
- app_name = config["app_name"]
370
- app_id = config["app_id"]
371
- api_key = config.get("api_key", "")
372
- variants = []
373
-
374
- client = AgentaApi(
375
- base_url=f"{host}/{BACKEND_URL_SUFFIX}",
376
- api_key=api_key,
377
- )
378
-
379
- try:
380
- variants: List[AppVariant] = client.apps.list_app_variants(app_id=app_id)
381
- except Exception as ex:
382
- raise ex
383
-
384
- if variants:
385
- for variant in variants:
386
- helper.display_app_variant(variant)
387
- else:
388
- click.echo(click.style(f"No variants found for app {app_name}", fg="red"))
389
-
390
-
391
- def config_check(app_folder: str):
392
- """Check the config file and update it from the backend
393
-
394
- Arguments:
395
- app_folder -- the app folder
396
- """
397
-
398
- click.echo(click.style("\nChecking and updating config file...", fg="bright_black"))
399
- app_folder = Path(app_folder)
400
- config_file = app_folder / "config.toml"
401
- if not config_file.exists():
402
- click.echo(
403
- click.style(
404
- f"Config file not found in {app_folder}. Make sure you are in the right folder and that you have run agenta init first.",
405
- fg="red",
406
- )
407
- )
408
- return
409
- host = get_host(app_folder) # TODO: Refactor the whole config thing
410
- helper.update_config_from_backend(config_file, host=host)
411
-
412
-
413
- def get_host(app_folder: str) -> str:
414
- """Fetches the host from the config"""
415
- app_folder = Path(app_folder)
416
- config_file = app_folder / "config.toml"
417
- config = toml.load(config_file)
418
- if "backend_host" not in config:
419
- host = "http://localhost"
420
- else:
421
- host = config["backend_host"]
422
- return host
423
-
424
-
425
- @variant.command(name="remove")
426
- @click.option("--app_folder", default=".")
427
- @click.option("--variant_name", default="")
428
- def remove_variant_cli(variant_name: str, app_folder: str):
429
- """Remove an existing variant."""
430
-
431
- try:
432
- config_check(app_folder)
433
- remove_variant(
434
- variant_name=variant_name,
435
- app_folder=app_folder,
436
- host=get_host(app_folder),
437
- )
438
- except Exception as ex:
439
- click.echo(click.style(f"Error while removing variant: {ex}", fg="red"))
440
-
441
-
442
- @variant.command(
443
- name="serve",
444
- context_settings=dict(
445
- ignore_unknown_options=True,
446
- allow_extra_args=True,
447
- ),
448
- )
449
- @click.option("--app_folder", default=".")
450
- @click.option("--file_name", default=None, help="The name of the file to run")
451
- @click.option(
452
- "--overwrite",
453
- is_flag=True,
454
- help="Overwrite the existing variant if it exists",
455
- )
456
- @click.pass_context
457
- def serve_cli(ctx, app_folder: str, file_name: str, overwrite: bool):
458
- """Adds a variant to the web UI and serves the API locally."""
459
-
460
- if not file_name:
461
- if ctx.args:
462
- file_name = ctx.args[0]
463
- else:
464
- error_msg = "To serve variant, kindly provide the filename and run:\n"
465
- error_msg += ">>> agenta variant serve --file_name <filename>.py\n"
466
- error_msg += "or\n"
467
- error_msg += ">>> agenta variant serve <filename>.py"
468
- click.echo(click.style(f"{error_msg}", fg="red"))
469
- sys.exit(1)
470
-
471
- try:
472
- config_check(app_folder)
473
- except Exception as e:
474
- click.echo(click.style("Failed during configuration check.", fg="red"))
475
- click.echo(click.style(f"Error message: {str(e)}", fg="red"))
476
- sys.exit(1)
477
-
478
- try:
479
- host = get_host(app_folder)
480
- except Exception as e:
481
- click.echo(click.style("Failed to retrieve the host.", fg="red"))
482
- click.echo(click.style(f"Error message: {str(e)}", fg="red"))
483
- sys.exit(1)
484
-
485
- try:
486
- api_key = helper.get_global_config("api_key")
487
- except Exception as e:
488
- click.echo(click.style("Failed to retrieve the api key.", fg="red"))
489
- click.echo(click.style(f"Error message: {str(e)}", fg="red"))
490
- sys.exit(1)
491
-
492
- try:
493
- variant_id = add_variant(
494
- app_folder=app_folder, file_name=file_name, host=host, overwrite=overwrite
495
- )
496
- except Exception as e:
497
- click.echo(click.style("Failed to add variant.", fg="red"))
498
- click.echo(click.style(f"Error message: {str(e)}", fg="red"))
499
- sys.exit(1)
500
-
501
- if variant_id:
502
- try:
503
- start_variant(variant_id=variant_id, app_folder=app_folder, host=host)
504
- except ConnectionError:
505
- error_msg = "Failed to connect to Agenta backend. Here's how you can solve the issue:\n"
506
- error_msg += "- First, please ensure that the backend service is running and accessible.\n"
507
- error_msg += (
508
- "- Second, try restarting the containers (if using Docker Compose)."
509
- )
510
- click.echo(click.style(f"{error_msg}", fg="red"))
511
- sys.exit(1)
512
- except Exception as e:
513
- click.echo(click.style("Failed to start container with LLM app.", fg="red"))
514
- click.echo(click.style(f"Error message: {str(e)}", fg="red"))
515
- sys.exit(1)
516
-
517
-
518
- @variant.command(name="list")
519
- @click.option("--app_folder", default=".")
520
- def list_variants_cli(app_folder: str):
521
- """List the variants in the backend"""
522
- try:
523
- config_check(app_folder)
524
- list_variants(app_folder=app_folder, host=get_host(app_folder))
525
- except Exception as ex:
526
- click.echo(click.style(f"Error while listing variants: {ex}", fg="red"))
@@ -1,49 +0,0 @@
1
- import click
2
- from agenta.cli import helper
3
-
4
-
5
- @click.group()
6
- def config():
7
- """Commands for variants configurations"""
8
- pass
9
-
10
-
11
- def update_backend_host(backend_host: str):
12
- """Check the config file and update the backend URL
13
-
14
- Arguments:
15
- app_folder -- the app folder
16
- backend_host -- the backend host
17
- """
18
-
19
- click.echo(
20
- click.style("\nChecking and updating global backend host...", fg="bright_black")
21
- )
22
- helper.set_global_config("host", backend_host)
23
-
24
-
25
- @config.command(
26
- name="set-host",
27
- context_settings=dict(
28
- ignore_unknown_options=True,
29
- allow_extra_args=True,
30
- ),
31
- )
32
- @click.option(
33
- "--backend_host", default=None, help="The URL of the backend host to use."
34
- )
35
- @click.pass_context
36
- def set_config_url(ctx, backend_host: str):
37
- """Set the backend URL in the app configuration"""
38
-
39
- try:
40
- if not backend_host:
41
- if ctx.args:
42
- backend_host = ctx.args[0]
43
- else:
44
- click.echo(click.style("Backend host URL not specified", fg="red"))
45
-
46
- update_backend_host(backend_host)
47
- click.echo(click.style("Backend host updated successfully! 🎉\n"))
48
- except Exception as ex:
49
- click.echo(click.style(f"Error updating backend host: {ex}", fg="red"))
agenta/client/api.py DELETED
@@ -1,74 +0,0 @@
1
- import os
2
- import toml
3
- import time
4
- import click
5
- from typing import Dict
6
- from pathlib import Path
7
- from agenta.client.backend import client
8
- from agenta.client.api_models import Image
9
- from requests.exceptions import RequestException
10
- from agenta.client.backend.client import AgentaApi
11
- from agenta.client.exceptions import APIRequestError
12
-
13
-
14
- def add_variant_to_server(
15
- app_id: str,
16
- base_name: str,
17
- image: Image,
18
- backend_url: str,
19
- api_key: str,
20
- retries=10,
21
- backoff_factor=1,
22
- ) -> Dict:
23
- """
24
- Adds a variant to the server with a retry mechanism and a single-line loading state.
25
-
26
- Args:
27
- app_id (str): The ID of the app to add the variant to.
28
- base_name (str): The base name for the variant.
29
- image (Image): The image to use for the variant.
30
- retries (int): Number of times to retry the request.
31
- backoff_factor (float): Factor to determine the delay between retries (exponential backoff).
32
-
33
- Returns:
34
- dict: The JSON response from the server.
35
-
36
- Raises:
37
- APIRequestError: If the request to the server fails after retrying.
38
- """
39
-
40
- click.echo(
41
- click.style("Waiting for the variant to be ready", fg="yellow"), nl=False
42
- )
43
-
44
- client = AgentaApi(
45
- base_url=backend_url,
46
- api_key=api_key,
47
- )
48
- for attempt in range(retries):
49
- try:
50
- response = client.apps.add_variant_from_image(
51
- app_id=app_id,
52
- variant_name=f"{base_name.lower()}.default",
53
- base_name=base_name,
54
- config_name="default",
55
- docker_id=image.docker_id,
56
- tags=image.tags,
57
- )
58
- click.echo(click.style("\nVariant added successfully!", fg="green"))
59
- return response
60
- except RequestException as e:
61
- if attempt < retries - 1:
62
- click.echo(click.style(".", fg="yellow"), nl=False)
63
- time.sleep(backoff_factor * (2**attempt))
64
- else:
65
- raise APIRequestError(
66
- click.style(
67
- f"\nRequest to app_variant endpoint failed with status code {response.status_code} and error message: {e}.",
68
- fg="red",
69
- )
70
- )
71
- except Exception as e:
72
- raise APIRequestError(
73
- click.style(f"\nAn unexpected error occurred: {e}", fg="red")
74
- )
@@ -1,34 +0,0 @@
1
- from pydantic import BaseModel
2
- from typing import List, Optional, Dict, Any
3
-
4
-
5
- class AppVariant(BaseModel):
6
- app_id: str
7
- app_name: str
8
- variant_name: str
9
- variant_id: str
10
- parameters: Optional[Dict[str, Any]]
11
- previous_variant_name: Optional[str]
12
- base_name: Optional[str]
13
- config_name: Optional[str]
14
-
15
-
16
- class Variant(BaseModel):
17
- variant_id: str
18
-
19
-
20
- class Image(BaseModel):
21
- type: Optional[str]
22
- docker_id: str
23
- tags: str
24
-
25
-
26
- class URI(BaseModel):
27
- uri: str
28
-
29
-
30
- class VariantConfigPayload(BaseModel):
31
- base_id: str
32
- config_name: str
33
- parameters: Dict[str, Any]
34
- overwrite: bool