agenta 0.5.2__tar.gz → 0.5.4__tar.gz
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-0.5.2 → agenta-0.5.4}/PKG-INFO +2 -1
- agenta-0.5.4/agenta/cli/helper.py +185 -0
- agenta-0.5.4/agenta/cli/telemetry.py +48 -0
- {agenta-0.5.2 → agenta-0.5.4}/agenta/cli/variant_commands.py +41 -9
- {agenta-0.5.2 → agenta-0.5.4}/agenta/client/client.py +27 -0
- {agenta-0.5.2 → agenta-0.5.4}/pyproject.toml +2 -1
- agenta-0.5.2/agenta/cli/helper.py +0 -118
- {agenta-0.5.2 → agenta-0.5.4}/README.md +0 -0
- {agenta-0.5.2 → agenta-0.5.4}/agenta/__init__.py +0 -0
- {agenta-0.5.2 → agenta-0.5.4}/agenta/cli/main.py +0 -0
- {agenta-0.5.2 → agenta-0.5.4}/agenta/client/Readme.md +0 -0
- {agenta-0.5.2 → agenta-0.5.4}/agenta/client/__init__.py +0 -0
- {agenta-0.5.2 → agenta-0.5.4}/agenta/client/api_models.py +0 -0
- {agenta-0.5.2 → agenta-0.5.4}/agenta/config.py +0 -0
- {agenta-0.5.2 → agenta-0.5.4}/agenta/config.toml +0 -0
- {agenta-0.5.2 → agenta-0.5.4}/agenta/docker/docker-assets/Dockerfile.template +0 -0
- {agenta-0.5.2 → agenta-0.5.4}/agenta/docker/docker-assets/README.md +0 -0
- {agenta-0.5.2 → agenta-0.5.4}/agenta/docker/docker-assets/entrypoint.sh +0 -0
- {agenta-0.5.2 → agenta-0.5.4}/agenta/docker/docker-assets/main.py +0 -0
- {agenta-0.5.2 → agenta-0.5.4}/agenta/docker/docker_utils.py +0 -0
- {agenta-0.5.2 → agenta-0.5.4}/agenta/sdk/__init__.py +0 -0
- {agenta-0.5.2 → agenta-0.5.4}/agenta/sdk/agenta_decorator.py +0 -0
- {agenta-0.5.2 → agenta-0.5.4}/agenta/sdk/agenta_init.py +0 -0
- {agenta-0.5.2 → agenta-0.5.4}/agenta/sdk/context.py +0 -0
- {agenta-0.5.2 → agenta-0.5.4}/agenta/sdk/router.py +0 -0
- {agenta-0.5.2 → agenta-0.5.4}/agenta/sdk/types.py +0 -0
- {agenta-0.5.2 → agenta-0.5.4}/agenta/sdk/utils/globals.py +0 -0
- {agenta-0.5.2 → agenta-0.5.4}/agenta/sdk/utils/preinit.py +0 -0
- {agenta-0.5.2 → agenta-0.5.4}/agenta/templates/compose_email/README.md +0 -0
- {agenta-0.5.2 → agenta-0.5.4}/agenta/templates/compose_email/app.py +0 -0
- {agenta-0.5.2 → agenta-0.5.4}/agenta/templates/compose_email/env.example +0 -0
- {agenta-0.5.2 → agenta-0.5.4}/agenta/templates/compose_email/requirements.txt +0 -0
- {agenta-0.5.2 → agenta-0.5.4}/agenta/templates/compose_email/template.toml +0 -0
- {agenta-0.5.2 → agenta-0.5.4}/agenta/templates/extract_data_to_json/README.md +0 -0
- {agenta-0.5.2 → agenta-0.5.4}/agenta/templates/extract_data_to_json/app.py +0 -0
- {agenta-0.5.2 → agenta-0.5.4}/agenta/templates/extract_data_to_json/env.example +0 -0
- {agenta-0.5.2 → agenta-0.5.4}/agenta/templates/extract_data_to_json/requirements.txt +0 -0
- {agenta-0.5.2 → agenta-0.5.4}/agenta/templates/extract_data_to_json/template.toml +0 -0
- {agenta-0.5.2 → agenta-0.5.4}/agenta/templates/simple_prompt/README.md +0 -0
- {agenta-0.5.2 → agenta-0.5.4}/agenta/templates/simple_prompt/app.py +0 -0
- {agenta-0.5.2 → agenta-0.5.4}/agenta/templates/simple_prompt/env.example +0 -0
- {agenta-0.5.2 → agenta-0.5.4}/agenta/templates/simple_prompt/requirements.txt +0 -0
- {agenta-0.5.2 → agenta-0.5.4}/agenta/templates/simple_prompt/template.toml +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: agenta
|
|
3
|
-
Version: 0.5.
|
|
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)
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
import toml
|
|
3
|
+
import click
|
|
4
|
+
import questionary
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from agenta.client import client
|
|
7
|
+
from typing import Any, List, MutableMapping
|
|
8
|
+
from agenta.client.api_models import AppVariant
|
|
9
|
+
|
|
10
|
+
|
|
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
|
+
"""
|
|
26
|
+
agenta_dir = Path.home() / ".agenta"
|
|
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.
|
|
41
|
+
|
|
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)
|
|
58
|
+
|
|
59
|
+
|
|
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.
|
|
67
|
+
|
|
68
|
+
Returns:
|
|
69
|
+
str: The API key to be used for accessing the Agenta platform.
|
|
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")
|
|
76
|
+
if api_key:
|
|
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()
|
|
91
|
+
|
|
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
|
+
)
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def update_variants_from_backend(
|
|
110
|
+
app_id: str,
|
|
111
|
+
config: MutableMapping[str, Any],
|
|
112
|
+
host: str,
|
|
113
|
+
api_key: str = None,
|
|
114
|
+
) -> MutableMapping[str, Any]:
|
|
115
|
+
"""Reads the list of variants from the backend and updates the config accordingly
|
|
116
|
+
|
|
117
|
+
Arguments:
|
|
118
|
+
app_id -- the app id
|
|
119
|
+
config -- the config loaded using toml.load
|
|
120
|
+
api_key -- the api key to use for authentication
|
|
121
|
+
|
|
122
|
+
Returns:
|
|
123
|
+
a new config object later to be saved using toml.dump(config, config_file.open('w'))
|
|
124
|
+
"""
|
|
125
|
+
|
|
126
|
+
try:
|
|
127
|
+
variants: List[AppVariant] = client.list_variants(app_id, host, api_key)
|
|
128
|
+
except Exception as ex:
|
|
129
|
+
raise ex
|
|
130
|
+
|
|
131
|
+
config["variants"] = [variant.variant_name for variant in variants]
|
|
132
|
+
config["variant_ids"] = [variant.variant_id for variant in variants]
|
|
133
|
+
return config
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
def update_config_from_backend(config_file: Path, host: str):
|
|
137
|
+
"""Updates the config file with new information from the backend
|
|
138
|
+
|
|
139
|
+
Arguments:
|
|
140
|
+
config_file -- the path to the config file
|
|
141
|
+
"""
|
|
142
|
+
assert config_file.exists(), "Config file does not exist!"
|
|
143
|
+
config = toml.load(config_file)
|
|
144
|
+
app_id = config["app_id"]
|
|
145
|
+
api_key = config.get("api_key", None)
|
|
146
|
+
if "variants" not in config:
|
|
147
|
+
config["variants"] = []
|
|
148
|
+
if "variant_ids" not in config:
|
|
149
|
+
config["variant_ids"] = []
|
|
150
|
+
config = update_variants_from_backend(app_id, config, host, api_key)
|
|
151
|
+
toml.dump(config, config_file.open("w"))
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
def display_app_variant(variant: AppVariant):
|
|
155
|
+
"""Prints a variant nicely in the terminal"""
|
|
156
|
+
click.echo(
|
|
157
|
+
click.style("App Name: ", bold=True, fg="green")
|
|
158
|
+
+ click.style(variant.app_name, fg="green")
|
|
159
|
+
)
|
|
160
|
+
click.echo(
|
|
161
|
+
click.style("Variant Name: ", bold=True, fg="blue")
|
|
162
|
+
+ click.style(variant.variant_name, fg="blue")
|
|
163
|
+
)
|
|
164
|
+
click.echo(click.style("Parameters: ", bold=True, fg="cyan"))
|
|
165
|
+
if variant.parameters:
|
|
166
|
+
for param, value in variant.parameters.items():
|
|
167
|
+
click.echo(
|
|
168
|
+
click.style(f" {param}: ", fg="cyan")
|
|
169
|
+
+ click.style(str(value), fg="cyan")
|
|
170
|
+
)
|
|
171
|
+
else:
|
|
172
|
+
click.echo(click.style(" Defaults from code", fg="cyan"))
|
|
173
|
+
if variant.previous_variant_name:
|
|
174
|
+
click.echo(
|
|
175
|
+
click.style("Template Variant Name: ", bold=True, fg="magenta")
|
|
176
|
+
+ click.style(variant.previous_variant_name, fg="magenta")
|
|
177
|
+
)
|
|
178
|
+
else:
|
|
179
|
+
click.echo(
|
|
180
|
+
click.style("Template Variant Name: ", bold=True, fg="magenta")
|
|
181
|
+
+ click.style("None", fg="magenta")
|
|
182
|
+
)
|
|
183
|
+
click.echo(
|
|
184
|
+
click.style("-" * 50, bold=True, fg="white")
|
|
185
|
+
) # a line for separating each variant
|
|
@@ -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
|
-
|
|
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...",
|
|
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
|
|
|
@@ -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
|
[tool.poetry]
|
|
2
2
|
name = "agenta"
|
|
3
|
-
version = "0.5.
|
|
3
|
+
version = "0.5.4"
|
|
4
4
|
description = "The SDK for agenta is an open-source LLMOps platform."
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
authors = ["Mahmoud Mabrouk <mahmoud@agenta.ai>"]
|
|
@@ -26,6 +26,7 @@ ipdb = "^0.13.13"
|
|
|
26
26
|
python-dotenv = "^1.0.0"
|
|
27
27
|
python-multipart = "^0.0.6"
|
|
28
28
|
importlib-metadata = "^6.7.0"
|
|
29
|
+
posthog = "^3.0.2"
|
|
29
30
|
|
|
30
31
|
[tool.poetry.dev-dependencies]
|
|
31
32
|
pytest = "^6.2"
|
|
@@ -1,118 +0,0 @@
|
|
|
1
|
-
import sys
|
|
2
|
-
import toml
|
|
3
|
-
import click
|
|
4
|
-
import questionary
|
|
5
|
-
from pathlib import Path
|
|
6
|
-
from agenta.client import client
|
|
7
|
-
from typing import Any, List, MutableMapping
|
|
8
|
-
from agenta.client.api_models import AppVariant
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
def get_api_key():
|
|
12
|
-
agenta_dir = Path.home() / ".agenta"
|
|
13
|
-
agenta_dir.mkdir(exist_ok=True)
|
|
14
|
-
credentials_file = agenta_dir / "config.toml"
|
|
15
|
-
|
|
16
|
-
if credentials_file.exists():
|
|
17
|
-
config = toml.load(credentials_file)
|
|
18
|
-
api_key = config.get("api_key", None)
|
|
19
|
-
|
|
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
|
-
|
|
26
|
-
if confirm_api_key:
|
|
27
|
-
return api_key
|
|
28
|
-
elif confirm_api_key is None: # User pressed Ctrl+C
|
|
29
|
-
sys.exit(0)
|
|
30
|
-
|
|
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()
|
|
34
|
-
|
|
35
|
-
if api_key:
|
|
36
|
-
config = {"api_key": api_key}
|
|
37
|
-
with open(credentials_file, "w") as config_file:
|
|
38
|
-
toml.dump(config, config_file)
|
|
39
|
-
|
|
40
|
-
return api_key
|
|
41
|
-
elif api_key is None: # User pressed Ctrl+C
|
|
42
|
-
sys.exit(0)
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
def update_variants_from_backend(
|
|
46
|
-
app_id: str, config: MutableMapping[str, Any], host: str, api_key: str = None
|
|
47
|
-
) -> MutableMapping[str, Any]:
|
|
48
|
-
"""Reads the list of variants from the backend and updates the config accordingly
|
|
49
|
-
|
|
50
|
-
Arguments:
|
|
51
|
-
app_id -- the app id
|
|
52
|
-
config -- the config loaded using toml.load
|
|
53
|
-
api_key -- the api key to use for authentication
|
|
54
|
-
|
|
55
|
-
Returns:
|
|
56
|
-
a new config object later to be saved using toml.dump(config, config_file.open('w'))
|
|
57
|
-
"""
|
|
58
|
-
|
|
59
|
-
try:
|
|
60
|
-
variants: List[AppVariant] = client.list_variants(app_id, host, api_key)
|
|
61
|
-
except Exception as ex:
|
|
62
|
-
raise ex
|
|
63
|
-
|
|
64
|
-
config["variants"] = [variant.variant_name for variant in variants]
|
|
65
|
-
config["variant_ids"] = [variant.variant_id for variant in variants]
|
|
66
|
-
return config
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
def update_config_from_backend(config_file: Path, host: str):
|
|
70
|
-
"""Updates the config file with new information from the backend
|
|
71
|
-
|
|
72
|
-
Arguments:
|
|
73
|
-
config_file -- the path to the config file
|
|
74
|
-
"""
|
|
75
|
-
assert config_file.exists(), "Config file does not exist!"
|
|
76
|
-
config = toml.load(config_file)
|
|
77
|
-
app_id = config["app_id"]
|
|
78
|
-
api_key = config.get("api_key", None)
|
|
79
|
-
if "variants" not in config:
|
|
80
|
-
config["variants"] = []
|
|
81
|
-
if "variant_ids" not in config:
|
|
82
|
-
config["variant_ids"] = []
|
|
83
|
-
config = update_variants_from_backend(app_id, config, host, api_key)
|
|
84
|
-
toml.dump(config, config_file.open("w"))
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
def display_app_variant(variant: AppVariant):
|
|
88
|
-
"""Prints a variant nicely in the terminal"""
|
|
89
|
-
click.echo(
|
|
90
|
-
click.style("App Name: ", bold=True, fg="green")
|
|
91
|
-
+ click.style(variant.app_name, fg="green")
|
|
92
|
-
)
|
|
93
|
-
click.echo(
|
|
94
|
-
click.style("Variant Name: ", bold=True, fg="blue")
|
|
95
|
-
+ click.style(variant.variant_name, fg="blue")
|
|
96
|
-
)
|
|
97
|
-
click.echo(click.style("Parameters: ", bold=True, fg="cyan"))
|
|
98
|
-
if variant.parameters:
|
|
99
|
-
for param, value in variant.parameters.items():
|
|
100
|
-
click.echo(
|
|
101
|
-
click.style(f" {param}: ", fg="cyan")
|
|
102
|
-
+ click.style(str(value), fg="cyan")
|
|
103
|
-
)
|
|
104
|
-
else:
|
|
105
|
-
click.echo(click.style(" Defaults from code", fg="cyan"))
|
|
106
|
-
if variant.previous_variant_name:
|
|
107
|
-
click.echo(
|
|
108
|
-
click.style("Template Variant Name: ", bold=True, fg="magenta")
|
|
109
|
-
+ click.style(variant.previous_variant_name, fg="magenta")
|
|
110
|
-
)
|
|
111
|
-
else:
|
|
112
|
-
click.echo(
|
|
113
|
-
click.style("Template Variant Name: ", bold=True, fg="magenta")
|
|
114
|
-
+ click.style("None", fg="magenta")
|
|
115
|
-
)
|
|
116
|
-
click.echo(
|
|
117
|
-
click.style("-" * 50, bold=True, fg="white")
|
|
118
|
-
) # a line for separating each variant
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|