agenta 0.5.2__py3-none-any.whl → 0.5.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.

agenta/cli/helper.py CHANGED
@@ -8,42 +8,109 @@ from typing import Any, List, MutableMapping
8
8
  from agenta.client.api_models import AppVariant
9
9
 
10
10
 
11
- def get_api_key():
11
+ from typing import Any, Optional
12
+ from pathlib import Path
13
+ import toml
14
+
15
+
16
+ def get_global_config(var_name: str) -> Optional[Any]:
17
+ """
18
+ Get the value of a global configuration variable.
19
+
20
+ Args:
21
+ var_name: the name of the variable to get
22
+
23
+ Returns:
24
+ the value of the variable, or None if it doesn't exist
25
+ """
12
26
  agenta_dir = Path.home() / ".agenta"
13
- agenta_dir.mkdir(exist_ok=True)
14
- credentials_file = agenta_dir / "config.toml"
27
+ if not agenta_dir.exists():
28
+ return None
29
+ agenta_config_file = agenta_dir / "config.toml"
30
+ if not agenta_config_file.exists():
31
+ return None
32
+ global_config = toml.load(agenta_config_file)
33
+ if var_name not in global_config:
34
+ return None
35
+ return global_config[var_name]
36
+
37
+
38
+ def set_global_config(var_name: str, var_value: Any) -> None:
39
+ """
40
+ Set the value of a global configuration variable.
15
41
 
16
- if credentials_file.exists():
17
- config = toml.load(credentials_file)
18
- api_key = config.get("api_key", None)
42
+ Args:
43
+ var_name: the name of the variable to set
44
+ var_value: the value to set the variable to
45
+ """
46
+ agenta_dir = Path.home() / ".agenta"
47
+ if not agenta_dir.exists():
48
+ agenta_dir.mkdir(exist_ok=True)
49
+ agenta_config_file = agenta_dir / "config.toml"
50
+ if not agenta_config_file.exists():
51
+ config = {}
52
+ with agenta_config_file.open("w") as config_file:
53
+ toml.dump(config, config_file)
54
+ global_config = toml.load(agenta_config_file)
55
+ global_config[var_name] = var_value
56
+ with open(agenta_config_file, "w") as config_file:
57
+ toml.dump(global_config, config_file)
19
58
 
20
- if api_key:
21
- # API key exists in the config file, ask for confirmation
22
- confirm_api_key = questionary.confirm(
23
- f"API Key found: {api_key}\nDo you want to use this API Key?"
24
- ).ask()
25
59
 
26
- if confirm_api_key:
27
- return api_key
28
- elif confirm_api_key is None: # User pressed Ctrl+C
29
- sys.exit(0)
60
+ def get_api_key() -> str:
61
+ """
62
+ Retrieve or request the API key for accessing the Agenta platform.
63
+
64
+ This function first looks for an existing API key in the global config file.
65
+ If found, it prompts the user to confirm whether they'd like to use that key.
66
+ If not found, it asks the user to input a new key.
30
67
 
31
- api_key = questionary.text(
32
- "(You can get your API Key here: https://demo.agenta.ai/settings?tab=apiKeys) Please provide your API key:"
33
- ).ask()
68
+ Returns:
69
+ str: The API key to be used for accessing the Agenta platform.
34
70
 
71
+ Raises:
72
+ SystemExit: If the user cancels the input by pressing Ctrl+C.
73
+ """
74
+
75
+ api_key = get_global_config("api_key")
35
76
  if api_key:
36
- config = {"api_key": api_key}
37
- with open(credentials_file, "w") as config_file:
38
- toml.dump(config, config_file)
77
+ # API key exists in the config file, ask for confirmation
78
+ confirm_api_key = questionary.confirm(
79
+ f"API Key found: {api_key}\nDo you want to use this API Key?"
80
+ ).ask()
81
+
82
+ if confirm_api_key:
83
+ return api_key
84
+ elif confirm_api_key is None: # User pressed Ctrl+C
85
+ sys.exit(0)
86
+ else:
87
+ api_key = questionary.text(
88
+ "(You can get your API Key here: https://demo.agenta.ai/settings?tab=apiKeys) "
89
+ "Please provide your API key:"
90
+ ).ask()
39
91
 
40
- return api_key
41
- elif api_key is None: # User pressed Ctrl+C
42
- sys.exit(0)
92
+ if api_key:
93
+ set_global_config("api_key", api_key)
94
+ elif api_key is None: # User pressed Ctrl+C
95
+ sys.exit(0)
96
+
97
+
98
+ def init_telemetry_config() -> None:
99
+ if (
100
+ get_global_config("telemetry_tracking_enabled") is None
101
+ or get_global_config("telemetry_api_key") is None
102
+ ):
103
+ set_global_config("telemetry_tracking_enabled", True)
104
+ set_global_config(
105
+ "telemetry_api_key", "phc_hmVSxIjTW1REBHXgj2aw4HW9X6CXb6FzerBgP9XenC7"
106
+ )
43
107
 
44
108
 
45
109
  def update_variants_from_backend(
46
- app_id: str, config: MutableMapping[str, Any], host: str, api_key: str = None
110
+ app_id: str,
111
+ config: MutableMapping[str, Any],
112
+ host: str,
113
+ api_key: str = None,
47
114
  ) -> MutableMapping[str, Any]:
48
115
  """Reads the list of variants from the backend and updates the config accordingly
49
116
 
@@ -0,0 +1,48 @@
1
+ # Stdlib Imports
2
+ import toml
3
+ from pathlib import Path
4
+
5
+ # Own Imports
6
+ from agenta.cli import helper
7
+
8
+ # Third party Imports
9
+ from posthog import Posthog
10
+
11
+
12
+ # Load telemetry configuration
13
+ helper.init_telemetry_config()
14
+
15
+
16
+ class EventTracking(Posthog):
17
+ _instance = None
18
+
19
+ def __new__(cls, *args, **kwargs):
20
+ if cls._instance is None:
21
+ cls._instance = super().__new__(cls)
22
+ return cls._instance
23
+
24
+ def __init__(self, api_key: str, host: str) -> None:
25
+ super(Posthog, self).__init__(api_key, host)
26
+
27
+ def capture_event(
28
+ self,
29
+ distinct_id: str,
30
+ event_name: str,
31
+ body: dict,
32
+ ) -> None:
33
+ """
34
+ Captures an event.
35
+
36
+ Args:
37
+ distinct_id (str): A unique identifier for the user or entity associated with the event.
38
+ event_name (str): The name of the event being captured.
39
+ body (dict): Contains the data associated with the event being captured.
40
+ """
41
+
42
+ self.capture(distinct_id, event_name, body)
43
+
44
+
45
+ # Initialize event tracking
46
+ event_track = EventTracking(
47
+ helper.get_global_config("telemetry_api_key"), "https://app.posthog.com"
48
+ )
@@ -1,7 +1,7 @@
1
1
  import re
2
2
  import sys
3
- from pathlib import Path
4
3
  from typing import List
4
+ from pathlib import Path
5
5
 
6
6
  from requests.exceptions import ConnectionError
7
7
 
@@ -10,12 +10,9 @@ import questionary
10
10
  import toml
11
11
  from agenta.cli import helper
12
12
  from agenta.client import client
13
+ from agenta.cli.telemetry import event_track
13
14
  from agenta.client.api_models import AppVariant, Image
14
- from agenta.docker.docker_utils import (
15
- build_and_upload_docker_image,
16
- build_tar_docker_container,
17
- )
18
- from docker.models.images import Image as DockerImage
15
+ from agenta.docker.docker_utils import build_tar_docker_container
19
16
 
20
17
 
21
18
  @click.group()
@@ -44,12 +41,15 @@ def add_variant(
44
41
  app_path = Path(app_folder)
45
42
  config_file = app_path / "config.toml"
46
43
  config = toml.load(config_file)
44
+
47
45
  app_name = config["app_name"]
48
46
  app_id = config["app_id"]
49
47
  api_key = config.get("api_key", None)
50
- base_name = file_name.removesuffix(".py")
48
+
51
49
  config_name = "default"
50
+ base_name = file_name.removesuffix(".py")
52
51
  variant_name = f"{base_name}.{config_name}"
52
+
53
53
  # check files in folder
54
54
  app_file = app_path / file_name
55
55
  if not app_file.exists():
@@ -104,7 +104,8 @@ def add_variant(
104
104
  try:
105
105
  click.echo(
106
106
  click.style(
107
- f"Preparing code base {base_name} into a tar file...", fg="bright_black"
107
+ f"Preparing code base {base_name} into a tar file...",
108
+ fg="bright_black",
108
109
  )
109
110
  )
110
111
  tar_path = build_tar_docker_container(folder=app_path, file_name=file_name)
@@ -149,7 +150,25 @@ def add_variant(
149
150
  else:
150
151
  click.echo(click.style(f"Error while adding variant: {ex}", fg="red"))
151
152
  return None
153
+
154
+ agenta_dir = Path.home() / ".agenta"
155
+ global_toml_file = toml.load(agenta_dir / "config.toml")
156
+ tracking_enabled: bool = global_toml_file["telemetry_tracking_enabled"]
152
157
  if overwrite:
158
+ # Track a deployment event
159
+ if tracking_enabled:
160
+ user_id = client.retrieve_user_id(host, api_key)
161
+ event_track.capture_event(
162
+ user_id,
163
+ "app_deployment",
164
+ body={
165
+ "app_id": app_id,
166
+ "deployed_by": user_id,
167
+ "environment": "CLI",
168
+ "version": "cloud" if api_key else "oss",
169
+ },
170
+ )
171
+
153
172
  click.echo(
154
173
  click.style(
155
174
  f"Variant {variant_name} for App {app_name} updated successfully 🎉",
@@ -158,6 +177,20 @@ def add_variant(
158
177
  )
159
178
  )
160
179
  else:
180
+ # Track a deployment event
181
+ if tracking_enabled:
182
+ user_id = client.retrieve_user_id(host, api_key)
183
+ event_track.capture_event(
184
+ user_id,
185
+ "app_deployment",
186
+ body={
187
+ "app_id": app_id,
188
+ "deployed_by": user_id,
189
+ "environment": "CLI",
190
+ "version": "cloud" if api_key else "oss",
191
+ },
192
+ )
193
+
161
194
  click.echo(
162
195
  click.style(
163
196
  f"Variant {variant_name} for App {app_name} added successfully to Agenta!",
@@ -184,7 +217,6 @@ def start_variant(variant_id: str, app_folder: str, host: str):
184
217
  app_folder = Path(app_folder)
185
218
  config_file = app_folder / "config.toml"
186
219
  config = toml.load(config_file)
187
- app_name = config["app_name"]
188
220
  api_key = config.get("api_key", None)
189
221
  app_id = config["app_id"]
190
222
 
agenta/client/client.py CHANGED
@@ -463,3 +463,30 @@ def validate_api_key(api_key: str, host: str) -> bool:
463
463
  return True
464
464
  except RequestException as e:
465
465
  raise APIRequestError(f"An error occurred while making the request: {e}")
466
+
467
+
468
+ def retrieve_user_id(host: str, api_key: Optional[str] = None) -> str:
469
+ """Retrieve user ID from the server.
470
+
471
+ Args:
472
+ host (str): The URL of the Agenta backend
473
+ api_key (str): The API key to validate with.
474
+
475
+ Returns:
476
+ str: the user ID
477
+ """
478
+
479
+ try:
480
+ response = requests.get(
481
+ f"{host}/{BACKEND_URL_SUFFIX}/profile/",
482
+ headers={"Authorization": api_key} if api_key is not None else None,
483
+ timeout=600,
484
+ )
485
+ if response.status_code != 200:
486
+ error_message = response.json().get("detail", "Unknown error")
487
+ raise APIRequestError(
488
+ f"Request to fetch_user_profile endpoint failed with status code {response.status_code}. Error message: {error_message}"
489
+ )
490
+ return response.json()["id"]
491
+ except RequestException as e:
492
+ raise APIRequestError(f"Request failed: {str(e)}")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: agenta
3
- Version: 0.5.2
3
+ Version: 0.5.4
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
@@ -19,6 +19,7 @@ Requires-Dist: docker (>=6.1.1,<7.0.0)
19
19
  Requires-Dist: fastapi (>=0.95.1,<0.96.0)
20
20
  Requires-Dist: importlib-metadata (>=6.7.0,<7.0.0)
21
21
  Requires-Dist: ipdb (>=0.13.13,<0.14.0)
22
+ Requires-Dist: posthog (>=3.0.2,<4.0.0)
22
23
  Requires-Dist: python-dotenv (>=1.0.0,<2.0.0)
23
24
  Requires-Dist: python-multipart (>=0.0.6,<0.0.7)
24
25
  Requires-Dist: questionary (>=1.10.0,<2.0.0)
@@ -1,11 +1,12 @@
1
1
  agenta/__init__.py,sha256=g757pwWie2vSuDQHmRqdgOGM2uF1m2t7nrZAYRZGzU0,375
2
- agenta/cli/helper.py,sha256=UL9CAD5Fc6xOKwGAFF1Xsmgm5SfcJisK-wMXq5h8P24,3953
2
+ agenta/cli/helper.py,sha256=qHDwZ23bm_gbvulDrlNcCEK3c4fzRycDZ_oJzBglflg,5945
3
3
  agenta/cli/main.py,sha256=7YAHzSuZP9nF7bQsrXFXLfg1rFDCFZTWQ5lIq--CP4s,6392
4
- agenta/cli/variant_commands.py,sha256=5HtmVhTZPhdnNCwY4yhztz1sATCf_2Y_gxQpEZzHh3w,14875
4
+ agenta/cli/telemetry.py,sha256=TiI4Nd1F1f1eSrs3fumDhcl8iu56aI4emyaGo5BQwMU,1165
5
+ agenta/cli/variant_commands.py,sha256=J1m1jpz82UEIDuK6zRQskRKDsvVWb1rxanJP6I98svs,15919
5
6
  agenta/client/Readme.md,sha256=umhMce1Gq_der9pH4M_pP4NQ8rHa3MENJLM9OrdUZ50,131
6
7
  agenta/client/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
8
  agenta/client/api_models.py,sha256=2mcG6jKAaJFmbxeCppt_5z66UnfrR4Vj3l8CJyTt4aM,599
8
- agenta/client/client.py,sha256=nsUrGzxoKC75olGzoZlsTXgt5a-vm8UXWq_Q7NF8XDU,16340
9
+ agenta/client/client.py,sha256=EnnAo53dhD4t4xSm4l29GeYXNXjHGzw7Bb9pLIHthYk,17258
9
10
  agenta/config.py,sha256=toEpBx8PjBC6P_22vLRlyMn0gu-P4CR0qPTgrUMFoiw,630
10
11
  agenta/config.toml,sha256=un4IS3NUcJczZS2LrjPCOShx8W9aw0XIoabZKfqZAWw,198
11
12
  agenta/docker/docker-assets/Dockerfile.template,sha256=KMQOmJ0F9zBY-1d5d4FZYIOnoTFGAJgqUwsAnIpDVak,285
@@ -36,7 +37,7 @@ agenta/templates/simple_prompt/app.py,sha256=kODgF6lhzsaJPdgL5b21bUki6jkvqjWZzWR
36
37
  agenta/templates/simple_prompt/env.example,sha256=g9AE5bYcGPpxawXMJ96gh8oenEPCHTabsiOnfQo3c5k,70
37
38
  agenta/templates/simple_prompt/requirements.txt,sha256=ywRglRy7pPkw8bljmMEJJ4aOOQKrt9FGKULZ-DGkoBU,23
38
39
  agenta/templates/simple_prompt/template.toml,sha256=DQBtRrF4GU8LBEXOZ-GGuINXMQDKGTEG5y37tnvIUIE,60
39
- agenta-0.5.2.dist-info/METADATA,sha256=MLcCPlLPy6Bu7yzDmE_LomlG-KvU4bCTYbEpU-RJesY,10002
40
- agenta-0.5.2.dist-info/WHEEL,sha256=d2fvjOD7sXsVzChCqf0Ty0JbHKBaLYwDbGQDwQTnJ50,88
41
- agenta-0.5.2.dist-info/entry_points.txt,sha256=PDiu8_8AsL7ibU9v4iNoOKR1S7F2rdxjlEprjM9QOgo,46
42
- agenta-0.5.2.dist-info/RECORD,,
40
+ agenta-0.5.4.dist-info/METADATA,sha256=gMf_vlP5nHTQ9dDbBUCoDBAIIOLGaQLWXB1V08B1kY4,10042
41
+ agenta-0.5.4.dist-info/WHEEL,sha256=d2fvjOD7sXsVzChCqf0Ty0JbHKBaLYwDbGQDwQTnJ50,88
42
+ agenta-0.5.4.dist-info/entry_points.txt,sha256=PDiu8_8AsL7ibU9v4iNoOKR1S7F2rdxjlEprjM9QOgo,46
43
+ agenta-0.5.4.dist-info/RECORD,,
File without changes