vijil 0.1.16__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.
- vijil-0.1.16/PKG-INFO +15 -0
- vijil-0.1.16/pyproject.toml +21 -0
- vijil-0.1.16/vijil/__init__.py +0 -0
- vijil-0.1.16/vijil/__main__.py +4 -0
- vijil-0.1.16/vijil/cli.py +26 -0
- vijil-0.1.16/vijil/commands/authentication.py +31 -0
- vijil-0.1.16/vijil/commands/create.py +23 -0
- vijil-0.1.16/vijil/commands/delete.py +20 -0
- vijil-0.1.16/vijil/commands/describe.py +85 -0
- vijil-0.1.16/vijil/commands/download.py +28 -0
- vijil-0.1.16/vijil/commands/list.py +70 -0
- vijil-0.1.16/vijil/commands/start.py +40 -0
- vijil-0.1.16/vijil/commands/stop.py +32 -0
- vijil-0.1.16/vijil/evaluations/options.py +32 -0
- vijil-0.1.16/vijil/utils.py +42 -0
- vijil-0.1.16/vijil/vijilapi/api_handler.py +137 -0
- vijil-0.1.16/vijil/vijilapi/backup_api_handler.py +211 -0
- vijil-0.1.16/vijil/vijilapi/config_handler.py +34 -0
vijil-0.1.16/PKG-INFO
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: vijil
|
|
3
|
+
Version: 0.1.16
|
|
4
|
+
Summary: The official Python client for Vijil
|
|
5
|
+
Author: vijil
|
|
6
|
+
Author-email: contact@vijil.ai
|
|
7
|
+
Requires-Python: >=3.9,<4.0
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
12
|
+
Requires-Dist: click
|
|
13
|
+
Requires-Dist: python-dotenv (>=1.0.0,<2.0.0)
|
|
14
|
+
Requires-Dist: requests (>=2.26.0,<3.0.0)
|
|
15
|
+
Requires-Dist: tabulate
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
[tool.poetry]
|
|
2
|
+
name = "vijil"
|
|
3
|
+
version = "0.1.16"
|
|
4
|
+
description = "The official Python client for Vijil"
|
|
5
|
+
authors = [
|
|
6
|
+
"vijil <contact@vijil.ai>"
|
|
7
|
+
]
|
|
8
|
+
|
|
9
|
+
[tool.poetry.dependencies]
|
|
10
|
+
python = "^3.9"
|
|
11
|
+
requests = "^2.26.0"
|
|
12
|
+
python-dotenv = "^1.0.0"
|
|
13
|
+
click = "*"
|
|
14
|
+
tabulate = "*"
|
|
15
|
+
|
|
16
|
+
[build-system]
|
|
17
|
+
requires = ["poetry-core>=1.0.0"]
|
|
18
|
+
build-backend = "poetry.core.masonry.api"
|
|
19
|
+
|
|
20
|
+
[tool.poetry.scripts]
|
|
21
|
+
vijil = "vijil.cli:main"
|
|
File without changes
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import click
|
|
2
|
+
from vijil.commands.authentication import login, logout
|
|
3
|
+
from vijil.commands.create import create
|
|
4
|
+
from vijil.commands.describe import describe
|
|
5
|
+
from vijil.commands.download import download
|
|
6
|
+
from vijil.commands.start import start
|
|
7
|
+
from vijil.commands.stop import stop
|
|
8
|
+
from vijil.commands.delete import delete
|
|
9
|
+
from vijil.commands.list import list
|
|
10
|
+
|
|
11
|
+
@click.group()
|
|
12
|
+
def main():
|
|
13
|
+
"""VIJIL Command Line Interface"""
|
|
14
|
+
|
|
15
|
+
main.add_command(login)
|
|
16
|
+
main.add_command(logout)
|
|
17
|
+
main.add_command(start)
|
|
18
|
+
main.add_command(stop)
|
|
19
|
+
main.add_command(describe)
|
|
20
|
+
main.add_command(delete)
|
|
21
|
+
main.add_command(download)
|
|
22
|
+
main.add_command(list)
|
|
23
|
+
main.add_command(create)
|
|
24
|
+
|
|
25
|
+
if __name__ == '__main__':
|
|
26
|
+
main()
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import click
|
|
2
|
+
import requests
|
|
3
|
+
from vijil.vijilapi.api_handler import VIGIL_API_BASE_URL
|
|
4
|
+
from vijil.vijilapi.config_handler import remove_config, save_config
|
|
5
|
+
|
|
6
|
+
@click.argument('username')
|
|
7
|
+
@click.option('--token', prompt='Enter your token', hide_input=True)
|
|
8
|
+
@click.command()
|
|
9
|
+
def login(username, token):
|
|
10
|
+
"""[username]"""
|
|
11
|
+
click.echo(f"Verifying your credentials...")
|
|
12
|
+
verify_url = f"{VIGIL_API_BASE_URL}/tokens/verify"
|
|
13
|
+
data = {"username": username, "token": token}
|
|
14
|
+
|
|
15
|
+
try:
|
|
16
|
+
response = requests.post(verify_url, json=data)
|
|
17
|
+
response.raise_for_status()
|
|
18
|
+
|
|
19
|
+
if response.json().get("verify"):
|
|
20
|
+
save_config(username, token)
|
|
21
|
+
click.echo("Token verified.")
|
|
22
|
+
else:
|
|
23
|
+
click.echo("Token verification failed. Please try a different token.")
|
|
24
|
+
|
|
25
|
+
except requests.exceptions.RequestException as e:
|
|
26
|
+
click.echo(f"Error during API request: {e}")
|
|
27
|
+
|
|
28
|
+
@click.command()
|
|
29
|
+
def logout():
|
|
30
|
+
remove_config()
|
|
31
|
+
click.echo("Logout done")
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import click
|
|
2
|
+
from vijil.evaluations.options import MODEL_HUB_CHOICES, MODEL_TYPE_MAPPING
|
|
3
|
+
from vijil.vijilapi.api_handler import model_token_request
|
|
4
|
+
|
|
5
|
+
@click.group()
|
|
6
|
+
def create():
|
|
7
|
+
"""[token]"""
|
|
8
|
+
pass
|
|
9
|
+
|
|
10
|
+
@create.command()
|
|
11
|
+
@click.argument('source', type=click.Choice(MODEL_HUB_CHOICES))
|
|
12
|
+
@click.option('--name', prompt='Enter the name of token')
|
|
13
|
+
@click.option('--token', prompt='Enter the token')
|
|
14
|
+
@click.option('--is-primary', prompt='Do you want to make this token as the default?', type=click.Choice(['yes', 'no']))
|
|
15
|
+
def token(source, name, token, is_primary):
|
|
16
|
+
isPrimary = "true" if is_primary == 'yes' else "false"
|
|
17
|
+
try:
|
|
18
|
+
result = model_token_request(MODEL_TYPE_MAPPING.get(source), name, token, isPrimary)
|
|
19
|
+
if result:
|
|
20
|
+
click.echo(f"Successfully saved integration token.")
|
|
21
|
+
|
|
22
|
+
except ValueError as e:
|
|
23
|
+
click.echo(f"Error: {e}")
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import click
|
|
2
|
+
|
|
3
|
+
from vijil.vijilapi.api_handler import delete_job_request
|
|
4
|
+
|
|
5
|
+
@click.group()
|
|
6
|
+
def delete():
|
|
7
|
+
"""[evaluation]"""
|
|
8
|
+
pass
|
|
9
|
+
|
|
10
|
+
@delete.command()
|
|
11
|
+
@click.option('--id', prompt='Enter ID that you received while creating evaluation', type=str)
|
|
12
|
+
def evaluation(id):
|
|
13
|
+
click.echo(f"Deleting evaluation with ID: {id}")
|
|
14
|
+
try:
|
|
15
|
+
result = delete_job_request(id)
|
|
16
|
+
if result:
|
|
17
|
+
click.echo(f"{result.get('message')}")
|
|
18
|
+
|
|
19
|
+
except ValueError as e:
|
|
20
|
+
click.echo(f"Error: {e}")
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import time
|
|
2
|
+
import click
|
|
3
|
+
from vijil.utils import find_job_by_task_id, format_datetime
|
|
4
|
+
|
|
5
|
+
from vijil.vijilapi.api_handler import check_jobs_progress, job_status_request, list_job_request
|
|
6
|
+
|
|
7
|
+
@click.group()
|
|
8
|
+
def describe():
|
|
9
|
+
"""[evaluation | log]"""
|
|
10
|
+
pass
|
|
11
|
+
|
|
12
|
+
@describe.command()
|
|
13
|
+
@click.option('--id', prompt='Enter ID that you received while creating evaluation', type=str)
|
|
14
|
+
@click.option('--trail', is_flag=True, help='Print live logs for in-progress jobs')
|
|
15
|
+
def log(id, trail):
|
|
16
|
+
printed_lines = set()
|
|
17
|
+
try:
|
|
18
|
+
joblist = list_job_request()
|
|
19
|
+
matched_job = find_job_by_task_id(joblist, id)
|
|
20
|
+
if matched_job:
|
|
21
|
+
if matched_job.get('status') == 'In Progress':
|
|
22
|
+
if trail:
|
|
23
|
+
while True:
|
|
24
|
+
live_logs = check_jobs_progress(id)
|
|
25
|
+
for log in live_logs.get('progress'):
|
|
26
|
+
if log not in printed_lines:
|
|
27
|
+
print(log)
|
|
28
|
+
printed_lines.add(log)
|
|
29
|
+
time.sleep(5)
|
|
30
|
+
else:
|
|
31
|
+
print("Job is still in progress. Use --trail to get live logs.")
|
|
32
|
+
else:
|
|
33
|
+
result = [matched_job.get('job_result')] if matched_job.get('status') == "Stopped" else matched_job.get('output')
|
|
34
|
+
for item in result:
|
|
35
|
+
print(item)
|
|
36
|
+
else:
|
|
37
|
+
print("No matching job found.")
|
|
38
|
+
|
|
39
|
+
except ValueError as e:
|
|
40
|
+
error_detail = str(e)
|
|
41
|
+
if error_detail == "400: Job is already completed.":
|
|
42
|
+
joblist = list_job_request()
|
|
43
|
+
matched_job = find_job_by_task_id(joblist, id)
|
|
44
|
+
result = [matched_job.job_result] if matched_job.get('status') == "Stopped" else matched_job.get('output')
|
|
45
|
+
for item in result:
|
|
46
|
+
if item not in printed_lines:
|
|
47
|
+
print(log)
|
|
48
|
+
printed_lines.add(log)
|
|
49
|
+
else:
|
|
50
|
+
click.echo(f"Error: {error_detail}")
|
|
51
|
+
|
|
52
|
+
@describe.command()
|
|
53
|
+
@click.option('--id', prompt='Enter ID that you received while creating evaluation', type=str)
|
|
54
|
+
def evaluation(id):
|
|
55
|
+
click.echo(f"Getting job status for ID: {id}")
|
|
56
|
+
try:
|
|
57
|
+
result = job_status_request(id)
|
|
58
|
+
if "job_result" in result:
|
|
59
|
+
click.echo(f"Job Status: {result.get('status')}")
|
|
60
|
+
click.echo(f"Job Result: {result.get('job_result')}")
|
|
61
|
+
elif "status" in result:
|
|
62
|
+
click.echo(f"Job Status: {result.get('status')}")
|
|
63
|
+
elif isinstance(result, type([])) and len(result) > 0:
|
|
64
|
+
click.echo("-" * 60)
|
|
65
|
+
for job in result:
|
|
66
|
+
click.echo(f"Job ID: {job.get('job_id', '')}")
|
|
67
|
+
click.echo(f"Model Hub: {job.get('model_type', '')}")
|
|
68
|
+
click.echo(f"Model Name: {job.get('model_name', '')}")
|
|
69
|
+
click.echo(f"Probe Group: {job.get('probe_group', '')}")
|
|
70
|
+
click.echo("Probes:")
|
|
71
|
+
for probe in job.get('probe', []):
|
|
72
|
+
click.echo(f" - {probe}")
|
|
73
|
+
|
|
74
|
+
click.echo("Detectors:")
|
|
75
|
+
for detector in job.get('detector', []):
|
|
76
|
+
click.echo(f" - {detector}")
|
|
77
|
+
click.echo(f"Start Time: {format_datetime(job.get('start_time', ''))}")
|
|
78
|
+
click.echo(f"Report: {job.get('report', '')}")
|
|
79
|
+
click.echo(f"Hitlog: {job.get('hitlog', '')}")
|
|
80
|
+
click.echo("-" * 60)
|
|
81
|
+
else:
|
|
82
|
+
click.echo("No data found.")
|
|
83
|
+
|
|
84
|
+
except ValueError as e:
|
|
85
|
+
click.echo(f"Error: {e}")
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import click
|
|
2
|
+
|
|
3
|
+
from vijil.vijilapi.api_handler import download_report_request, job_status_request
|
|
4
|
+
|
|
5
|
+
@click.group()
|
|
6
|
+
def download():
|
|
7
|
+
"""[log]"""
|
|
8
|
+
pass
|
|
9
|
+
|
|
10
|
+
@download.command()
|
|
11
|
+
@click.argument("report_type", type=click.Choice(["full", "failure"]))
|
|
12
|
+
@click.option('--id', prompt='Enter ID that you received while creating evaluation', type=str)
|
|
13
|
+
def log(report_type, id):
|
|
14
|
+
"""[full | failure]"""
|
|
15
|
+
try:
|
|
16
|
+
result = job_status_request(id)
|
|
17
|
+
if isinstance(result, type([])) and len(result) > 0:
|
|
18
|
+
file_id = result[0].get("report" if report_type == "full" else "hitlog")
|
|
19
|
+
result = download_report_request(file_id)
|
|
20
|
+
if result:
|
|
21
|
+
click.echo(f"{result}")
|
|
22
|
+
else:
|
|
23
|
+
click.echo("No data found.")
|
|
24
|
+
else:
|
|
25
|
+
click.echo("No data found")
|
|
26
|
+
|
|
27
|
+
except ValueError as e:
|
|
28
|
+
click.echo(f"Error: {e}")
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import click
|
|
2
|
+
|
|
3
|
+
from tabulate import tabulate
|
|
4
|
+
from vijil.utils import format_datetime, get_dimensions_from_probe_groups
|
|
5
|
+
from vijil.vijilapi.api_handler import get_model_token_request, list_job_request
|
|
6
|
+
|
|
7
|
+
@click.group()
|
|
8
|
+
def list():
|
|
9
|
+
"""[evaluations | tokens]"""
|
|
10
|
+
pass
|
|
11
|
+
|
|
12
|
+
@list.command()
|
|
13
|
+
def tokens():
|
|
14
|
+
try:
|
|
15
|
+
result = get_model_token_request()
|
|
16
|
+
if len(result) > 0:
|
|
17
|
+
table_data = []
|
|
18
|
+
for token in result:
|
|
19
|
+
table_data.append([
|
|
20
|
+
token.get('name', ''),
|
|
21
|
+
token.get('type', ''),
|
|
22
|
+
token.get('token', ''),
|
|
23
|
+
token.get('isPrimary', '')
|
|
24
|
+
])
|
|
25
|
+
|
|
26
|
+
headers = ["Name", "Type", "Token", "isDefault"]
|
|
27
|
+
colalign = ['left'] * len(headers)
|
|
28
|
+
tablefmt = "heavy_grid"
|
|
29
|
+
maxcolwidths = [None, None, 50, None]
|
|
30
|
+
|
|
31
|
+
table = tabulate(table_data, headers=headers, tablefmt=tablefmt, colalign=colalign, maxcolwidths=maxcolwidths)
|
|
32
|
+
click.echo(table)
|
|
33
|
+
else:
|
|
34
|
+
click.echo("No tokens found.")
|
|
35
|
+
|
|
36
|
+
except ValueError as e:
|
|
37
|
+
click.echo(f"Error: {e}")
|
|
38
|
+
|
|
39
|
+
@list.command
|
|
40
|
+
def evaluations():
|
|
41
|
+
try:
|
|
42
|
+
result = list_job_request()
|
|
43
|
+
if len(result) > 0:
|
|
44
|
+
table_data = []
|
|
45
|
+
for job in result:
|
|
46
|
+
probe_groups_list = job.get('probe_group', '').split(",")
|
|
47
|
+
table_data.append([
|
|
48
|
+
job.get('id', ''),
|
|
49
|
+
job.get('model_type', ''),
|
|
50
|
+
job.get('model_name', ''),
|
|
51
|
+
"\n".join(get_dimensions_from_probe_groups(probe_groups_list)),
|
|
52
|
+
"\n".join(probe_groups_list),
|
|
53
|
+
job.get('status', ''),
|
|
54
|
+
job.get('job_result', ''),
|
|
55
|
+
format_datetime(job.get('start_time', '')),
|
|
56
|
+
format_datetime(job.get('end_time', ''))
|
|
57
|
+
])
|
|
58
|
+
|
|
59
|
+
headers = ["ID", "Model Hub", "Model Name", "Dimension", "Probe Group", "Status", "Output", "Start Time", "End Time"]
|
|
60
|
+
maxcolwidths = [None, 10, 25, None, None, None, 30, None, None]
|
|
61
|
+
|
|
62
|
+
colalign = ['left'] * len(headers)
|
|
63
|
+
tablefmt = "heavy_grid"
|
|
64
|
+
table = tabulate(table_data, headers=headers, tablefmt=tablefmt, colalign=colalign, maxcolwidths=maxcolwidths)
|
|
65
|
+
click.echo(table)
|
|
66
|
+
else:
|
|
67
|
+
click.echo("No jobs found.")
|
|
68
|
+
|
|
69
|
+
except ValueError as e:
|
|
70
|
+
click.echo(f"Error: {e}")
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import click
|
|
2
|
+
|
|
3
|
+
from vijil.evaluations.options import DTYPE_CHOICES, MODEL_HUB_CHOICES, PROBES_CHOICES, PROBES_DIMENSIONS_MAPPING
|
|
4
|
+
from vijil.utils import generate_default_job_name
|
|
5
|
+
from vijil.vijilapi.api_handler import get_headers, list_job_request, send_evaluation_request
|
|
6
|
+
|
|
7
|
+
@click.group()
|
|
8
|
+
def start():
|
|
9
|
+
"""[evaluation]"""
|
|
10
|
+
pass
|
|
11
|
+
|
|
12
|
+
@start.command()
|
|
13
|
+
@click.option('--model-hub', prompt='Choose the model hub', type=click.Choice(MODEL_HUB_CHOICES))
|
|
14
|
+
@click.option('--model-name', prompt='Enter the model name')
|
|
15
|
+
@click.option('--dimension', prompt='Choose the trust dimension', type=click.Choice(PROBES_CHOICES))
|
|
16
|
+
@click.option('--deployment-type', prompt='Choose the deployment type', type=click.Choice(DTYPE_CHOICES))
|
|
17
|
+
@click.option('--generations', default=1, prompt='Enter the number of generations', type=click.IntRange(1, 100))
|
|
18
|
+
@click.option('--token', default='', prompt='Enter the model token')
|
|
19
|
+
def evaluation(model_hub, model_name, dimension, deployment_type, generations, token):
|
|
20
|
+
try:
|
|
21
|
+
headers = get_headers()
|
|
22
|
+
if model_hub != 'huggingface' and deployment_type == 'local':
|
|
23
|
+
click.echo(f"Local deployment type is not allowed for model {model_hub}.")
|
|
24
|
+
return
|
|
25
|
+
|
|
26
|
+
# probes = PROBES_DIMENSIONS_MAPPING.get(dimension)
|
|
27
|
+
|
|
28
|
+
click.echo(f"Running evaluation for model hub: {model_hub}, model name: {model_name}")
|
|
29
|
+
|
|
30
|
+
job_name = generate_default_job_name(headers['username'], model_hub, model_name)
|
|
31
|
+
result = send_evaluation_request(model_hub, model_name, dimension, generations, job_name, deployment_type, token)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
if result.get("task_id"):
|
|
35
|
+
click.echo(f"Successfully created evaluation, check job status by ID: {result.get('task_id')}")
|
|
36
|
+
else:
|
|
37
|
+
click.echo(f"Response: {result}")
|
|
38
|
+
|
|
39
|
+
except ValueError as e:
|
|
40
|
+
click.echo(f"Error: {e}")
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import click
|
|
2
|
+
|
|
3
|
+
from vijil.vijilapi.api_handler import stop_all_job_request, stop_job_request
|
|
4
|
+
|
|
5
|
+
@click.group()
|
|
6
|
+
def stop():
|
|
7
|
+
"""[evaluation]"""
|
|
8
|
+
pass
|
|
9
|
+
|
|
10
|
+
@stop.command()
|
|
11
|
+
@click.option('--id', default='', help='Enter ID that you received while creating evaluation')
|
|
12
|
+
@click.option('-a', '--all', is_flag=True, help='Stop all running evaluations.')
|
|
13
|
+
def evaluation(id, all):
|
|
14
|
+
if all:
|
|
15
|
+
click.echo(f"Stopping all running evaluations.")
|
|
16
|
+
try:
|
|
17
|
+
result = stop_all_job_request()
|
|
18
|
+
if result.get("status"):
|
|
19
|
+
click.echo(f"Job Status: {result.get('status')}")
|
|
20
|
+
except ValueError as e:
|
|
21
|
+
click.echo(f"Error: {e}")
|
|
22
|
+
else:
|
|
23
|
+
if not id:
|
|
24
|
+
click.echo("Please provide the ID for stopping a specific job.")
|
|
25
|
+
return
|
|
26
|
+
click.echo(f"Stopping evaluation of ID: {id}")
|
|
27
|
+
try:
|
|
28
|
+
result = stop_job_request(id)
|
|
29
|
+
if result.get("status"):
|
|
30
|
+
click.echo(f"Job Status: {result.get('status')}")
|
|
31
|
+
except ValueError as e:
|
|
32
|
+
click.echo(f"Error: {e}")
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
MODEL_HUB_CHOICES = ['huggingface', 'replicate', 'octo', 'openai', 'together', 'anyscale', 'mistral']
|
|
2
|
+
MODEL_NAMES_MAPPING = {
|
|
3
|
+
'huggingface': ['gpt2', 'bigscience/bloom-560m', 'other'],
|
|
4
|
+
'replicate': ['replicate/llama-7b', 'replicate/llama-13b-lora', 'other'],
|
|
5
|
+
'octo': ['llama-2-7b-chat', 'other'],
|
|
6
|
+
}
|
|
7
|
+
PROBES_CHOICES = [
|
|
8
|
+
'Security', 'Toxicity', 'Hallucination',
|
|
9
|
+
'Ethics',"Privacy", "Stereotype",
|
|
10
|
+
"Fairness", "Robustness"
|
|
11
|
+
]
|
|
12
|
+
PROBES_DIMENSIONS_MAPPING = {
|
|
13
|
+
'security': 'dan,encoding,gcg,glitch,knownbadsignatures,replay,malwaregen,packagehallucination,promptinject,xss',
|
|
14
|
+
'toxicity': 'atkgen,continuation,realtoxicityprompts',
|
|
15
|
+
'hallucination': 'goodside,snowball,misleading,packagehallucination',
|
|
16
|
+
'ethics': 'lmrc,hendrycksethics',
|
|
17
|
+
'privacy': 'leakreplay,replay',
|
|
18
|
+
'stereotype': 'advstereo',
|
|
19
|
+
'fairness': 'adultdata,winobias',
|
|
20
|
+
'robustness': 'advglue'
|
|
21
|
+
}
|
|
22
|
+
DTYPE_CHOICES = ['private', 'public']
|
|
23
|
+
|
|
24
|
+
MODEL_TYPE_MAPPING = {
|
|
25
|
+
'huggingface': 'HF',
|
|
26
|
+
'replicate': 'Replicate',
|
|
27
|
+
'octo': 'Octo',
|
|
28
|
+
'openai': 'Open',
|
|
29
|
+
'together': 'together',
|
|
30
|
+
'anyscale': 'anyscale',
|
|
31
|
+
'mistral': 'mistral',
|
|
32
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
from collections import Counter
|
|
2
|
+
from datetime import datetime
|
|
3
|
+
|
|
4
|
+
from vijil.evaluations.options import PROBES_DIMENSIONS_MAPPING
|
|
5
|
+
|
|
6
|
+
def format_datetime(datetime_str):
|
|
7
|
+
"""Format datetime from API response."""
|
|
8
|
+
if datetime_str:
|
|
9
|
+
try:
|
|
10
|
+
dt = datetime.strptime(datetime_str, "%Y-%m-%d %H:%M:%S")
|
|
11
|
+
return dt.strftime("%Y/%m/%d %H:%M")
|
|
12
|
+
except ValueError:
|
|
13
|
+
return datetime_str
|
|
14
|
+
else:
|
|
15
|
+
return datetime_str
|
|
16
|
+
|
|
17
|
+
def find_job_by_task_id(job_list, target_task_id):
|
|
18
|
+
for job in job_list:
|
|
19
|
+
if job.get('id') == target_task_id:
|
|
20
|
+
return job
|
|
21
|
+
return None
|
|
22
|
+
|
|
23
|
+
def generate_default_job_name(username, model_hub, model_name):
|
|
24
|
+
current_date = datetime.now().strftime("%m%d%Y")
|
|
25
|
+
current_timestamp = datetime.now().strftime("%H%M%S")
|
|
26
|
+
job_name = '_'.join([username, model_hub, model_name, current_date, current_timestamp]).replace(" ", "")
|
|
27
|
+
return job_name
|
|
28
|
+
|
|
29
|
+
def get_dimensions_from_probe_groups(probe_groups):
|
|
30
|
+
# Cleaning up empty strings here
|
|
31
|
+
probe_groups = [i for i in probe_groups if i]
|
|
32
|
+
|
|
33
|
+
mapped_dimensions = []
|
|
34
|
+
|
|
35
|
+
for group in probe_groups:
|
|
36
|
+
for dimension, probes in PROBES_DIMENSIONS_MAPPING.items():
|
|
37
|
+
dimension = dimension.capitalize()
|
|
38
|
+
if group in probes and dimension not in mapped_dimensions:
|
|
39
|
+
mapped_dimensions.append(dimension)
|
|
40
|
+
continue
|
|
41
|
+
|
|
42
|
+
return sorted(mapped_dimensions)
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
# api_handler.py
|
|
2
|
+
import requests
|
|
3
|
+
import os
|
|
4
|
+
import logging
|
|
5
|
+
from .config_handler import load_config
|
|
6
|
+
|
|
7
|
+
# VIGIL_API_BASE_URL = "http://127.0.0.1:8000/api/v1"
|
|
8
|
+
# VIGIL_API_BASE_URL = "https://develop.vijil.ai/api/v1"
|
|
9
|
+
VIGIL_API_BASE_URL = "https://score.vijil.ai/api/v1"
|
|
10
|
+
|
|
11
|
+
# Set up logging
|
|
12
|
+
HIDDEN_DIR_NAME = ".vijil"
|
|
13
|
+
LOG_FILE_NAME = "vijil.log"
|
|
14
|
+
LOG_FILE_PATH = os.path.join(os.path.expanduser('~'), HIDDEN_DIR_NAME, LOG_FILE_NAME)
|
|
15
|
+
os.makedirs(os.path.dirname(LOG_FILE_PATH), exist_ok=True)
|
|
16
|
+
logging.basicConfig(level=logging.ERROR, filename=LOG_FILE_PATH, filemode='a',
|
|
17
|
+
format='%(asctime)s - %(levelname)s - %(message)s')
|
|
18
|
+
logger = logging.getLogger(__name__)
|
|
19
|
+
|
|
20
|
+
def get_headers():
|
|
21
|
+
username, token = load_config()
|
|
22
|
+
if not username or not token:
|
|
23
|
+
raise ValueError("To proceed, please log in by using the 'login' command..")
|
|
24
|
+
|
|
25
|
+
return {
|
|
26
|
+
"username": username,
|
|
27
|
+
"clitoken": token,
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
def make_api_request(endpoint, method="get", params=None, data=None):
|
|
31
|
+
url = f"{VIGIL_API_BASE_URL}/{endpoint}"
|
|
32
|
+
headers = get_headers()
|
|
33
|
+
|
|
34
|
+
try:
|
|
35
|
+
if method.lower() == "get":
|
|
36
|
+
response = requests.get(url, params=params, headers=headers)
|
|
37
|
+
|
|
38
|
+
elif method.lower() == "post":
|
|
39
|
+
response = requests.post(url, json=data, params=params, headers=headers)
|
|
40
|
+
else:
|
|
41
|
+
raise ValueError("Invalid HTTP method. Use 'get' or 'post'.")
|
|
42
|
+
|
|
43
|
+
response.raise_for_status()
|
|
44
|
+
return response.json()
|
|
45
|
+
|
|
46
|
+
except requests.exceptions.HTTPError as http_err:
|
|
47
|
+
error_detail = response.json()
|
|
48
|
+
logger.error(f"{error_detail}")
|
|
49
|
+
raise ValueError(f"{error_detail.get('detail')}")
|
|
50
|
+
except requests.exceptions.RequestException as req_err:
|
|
51
|
+
logger.error(f"Request error occurred: {req_err}")
|
|
52
|
+
raise ValueError(f"Error during file download: {req_err}")
|
|
53
|
+
except Exception as e:
|
|
54
|
+
logger.error(f"Error during API request: {e}")
|
|
55
|
+
raise ValueError(f"Something went wrong. Check the logs for details.")
|
|
56
|
+
|
|
57
|
+
def send_evaluation_request(model_type, model_name, dimension, generations, job_name, deployment_type, token):
|
|
58
|
+
endpoint = "evaluations/"
|
|
59
|
+
data = {
|
|
60
|
+
"model_type": model_type,
|
|
61
|
+
"model_name": model_name,
|
|
62
|
+
"dimensions": dimension,
|
|
63
|
+
"generations": generations,
|
|
64
|
+
"job_name": job_name,
|
|
65
|
+
"dType": deployment_type
|
|
66
|
+
}
|
|
67
|
+
if token != "":
|
|
68
|
+
data["token"] = token
|
|
69
|
+
return make_api_request(endpoint, method="post", data=data)
|
|
70
|
+
|
|
71
|
+
def job_status_request(id):
|
|
72
|
+
endpoint = "evaluations/job_status"
|
|
73
|
+
params = {"uid": id}
|
|
74
|
+
return make_api_request(endpoint, params=params)
|
|
75
|
+
|
|
76
|
+
def stop_job_request(id):
|
|
77
|
+
endpoint = "evaluations/stop"
|
|
78
|
+
params = {"uid": id}
|
|
79
|
+
return make_api_request(endpoint, method="post", params=params)
|
|
80
|
+
|
|
81
|
+
def stop_all_job_request():
|
|
82
|
+
endpoint = "evaluations/stopall"
|
|
83
|
+
return make_api_request(endpoint, method="post")
|
|
84
|
+
|
|
85
|
+
def delete_job_request(id):
|
|
86
|
+
endpoint = "evaluations/remove"
|
|
87
|
+
params = {"uid": id}
|
|
88
|
+
return make_api_request(endpoint, method="post", params=params)
|
|
89
|
+
|
|
90
|
+
def download_report_request(file_id):
|
|
91
|
+
try:
|
|
92
|
+
download_url = f"{VIGIL_API_BASE_URL}/evaluations/download_file?file_id={file_id}"
|
|
93
|
+
response = requests.get(download_url)
|
|
94
|
+
response.raise_for_status()
|
|
95
|
+
|
|
96
|
+
filename = response.headers.get('Content-Disposition', '').split('filename=')[1].strip('"')
|
|
97
|
+
|
|
98
|
+
with open(filename, 'wb') as file:
|
|
99
|
+
file.write(response.content)
|
|
100
|
+
|
|
101
|
+
return f"File downloaded successfully: {filename}"
|
|
102
|
+
|
|
103
|
+
except requests.exceptions.HTTPError as http_err:
|
|
104
|
+
error_detail = response.json()
|
|
105
|
+
logger.error(f"{error_detail}")
|
|
106
|
+
raise ValueError(f"{error_detail.get('detail')}")
|
|
107
|
+
except requests.exceptions.RequestException as req_err:
|
|
108
|
+
logger.error(f"Request error occurred: {req_err}")
|
|
109
|
+
raise ValueError(f"Error during file download: {req_err}")
|
|
110
|
+
|
|
111
|
+
def list_job_request():
|
|
112
|
+
endpoint = "jobs/"
|
|
113
|
+
return make_api_request(endpoint)
|
|
114
|
+
|
|
115
|
+
def get_job_detail_request(id):
|
|
116
|
+
endpoint = "jobs/detail"
|
|
117
|
+
params = {"job_id": id}
|
|
118
|
+
return make_api_request(endpoint, params=params)
|
|
119
|
+
|
|
120
|
+
def model_token_request(source, name, token, isPrimary):
|
|
121
|
+
endpoint = f"integrations/"
|
|
122
|
+
data = {
|
|
123
|
+
"token": token,
|
|
124
|
+
"name": name,
|
|
125
|
+
"type": source,
|
|
126
|
+
"isPrimary": isPrimary
|
|
127
|
+
}
|
|
128
|
+
return make_api_request(endpoint, method="post", data=data)
|
|
129
|
+
|
|
130
|
+
def get_model_token_request():
|
|
131
|
+
endpoint = "integrations/"
|
|
132
|
+
return make_api_request(endpoint)
|
|
133
|
+
|
|
134
|
+
def check_jobs_progress(id):
|
|
135
|
+
endpoint = "evaluations/job_progress"
|
|
136
|
+
params = {"uid": id}
|
|
137
|
+
return make_api_request(endpoint, method="get", params=params)
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
# api_handler.py
|
|
2
|
+
import requests
|
|
3
|
+
import logging
|
|
4
|
+
|
|
5
|
+
from .config_handler import load_config
|
|
6
|
+
|
|
7
|
+
VIGIL_API_BASE_URL = "http://127.0.0.1:8000/api/v1"
|
|
8
|
+
# VIGIL_API_BASE_URL = "http://dockder-test-alb-2018306447.us-west-2.elb.amazonaws.com/api/v1"
|
|
9
|
+
|
|
10
|
+
# Set up logging
|
|
11
|
+
logging.basicConfig(level=logging.ERROR, filename='vijil.log', filemode='w',
|
|
12
|
+
format='%(asctime)s - %(levelname)s - %(message)s')
|
|
13
|
+
logger = logging.getLogger(__name__)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def custom_headers():
|
|
18
|
+
"""Customize headers for display."""
|
|
19
|
+
return {
|
|
20
|
+
"job_id": "Job ID",
|
|
21
|
+
"task_id": "ID",
|
|
22
|
+
"model_type": "Model Type",
|
|
23
|
+
"model_name": "Model Name",
|
|
24
|
+
"probe_group": "Probe Group",
|
|
25
|
+
"status": "Status",
|
|
26
|
+
"job_result": "Result",
|
|
27
|
+
"start_time": "Start Time",
|
|
28
|
+
"end_time": "End Time",
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
def send_evaluation_request(model_type, model_name, probes, generations):
|
|
32
|
+
url = f"{VIGIL_API_BASE_URL}/evaluations/"
|
|
33
|
+
username, token = load_config()
|
|
34
|
+
|
|
35
|
+
if not username or not token:
|
|
36
|
+
raise ValueError("Username or token not found in configuration.")
|
|
37
|
+
|
|
38
|
+
headers = {
|
|
39
|
+
# "Authorization": f"Bearer {token}",
|
|
40
|
+
"username": username,
|
|
41
|
+
"clitoken": token,
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
data = {
|
|
45
|
+
"model_type": model_type,
|
|
46
|
+
"model_name": model_name,
|
|
47
|
+
"probes": probes,
|
|
48
|
+
"generations": generations,
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
try:
|
|
52
|
+
response = requests.post(url, json=data, headers=headers)
|
|
53
|
+
response.raise_for_status()
|
|
54
|
+
return response.json()
|
|
55
|
+
|
|
56
|
+
except Exception as e:
|
|
57
|
+
logger.error(f"Error during API request: {e}")
|
|
58
|
+
raise ValueError("An error occurred during the API request. Check the logs for details.")
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def job_status_request(id):
|
|
62
|
+
url = f"{VIGIL_API_BASE_URL}/evaluations/job_status"
|
|
63
|
+
username, token = load_config()
|
|
64
|
+
|
|
65
|
+
if not username or not token:
|
|
66
|
+
raise ValueError("Username or token not found in configuration.")
|
|
67
|
+
|
|
68
|
+
headers = {
|
|
69
|
+
"username": username,
|
|
70
|
+
"clitoken": token,
|
|
71
|
+
}
|
|
72
|
+
params = {"task_id": id}
|
|
73
|
+
try:
|
|
74
|
+
response = requests.get(url, params=params, headers=headers)
|
|
75
|
+
response.raise_for_status()
|
|
76
|
+
return response.json()
|
|
77
|
+
|
|
78
|
+
except Exception as e:
|
|
79
|
+
logger.error(f"Error during API request: {e}")
|
|
80
|
+
raise ValueError("An error occurred during the API request. Check the logs for details.")
|
|
81
|
+
|
|
82
|
+
def stop_job_request(id):
|
|
83
|
+
url = f"{VIGIL_API_BASE_URL}/evaluations/stop"
|
|
84
|
+
username, token = load_config()
|
|
85
|
+
|
|
86
|
+
if not username or not token:
|
|
87
|
+
raise ValueError("Username or token not found in configuration.")
|
|
88
|
+
|
|
89
|
+
headers = {
|
|
90
|
+
"username": username,
|
|
91
|
+
"clitoken": token,
|
|
92
|
+
}
|
|
93
|
+
params = {"task_id": id}
|
|
94
|
+
try:
|
|
95
|
+
response = requests.post(url, params=params, headers=headers)
|
|
96
|
+
response.raise_for_status()
|
|
97
|
+
return response.json()
|
|
98
|
+
|
|
99
|
+
except Exception as e:
|
|
100
|
+
logger.error(f"Error during API request: {e}")
|
|
101
|
+
raise ValueError("An error occurred during the API request. Check the logs for details.")
|
|
102
|
+
|
|
103
|
+
def stop_all_job_request():
|
|
104
|
+
url = f"{VIGIL_API_BASE_URL}/evaluations/stopall"
|
|
105
|
+
username, token = load_config()
|
|
106
|
+
|
|
107
|
+
if not username or not token:
|
|
108
|
+
raise ValueError("Username or token not found in configuration.")
|
|
109
|
+
|
|
110
|
+
headers = {
|
|
111
|
+
"username": username,
|
|
112
|
+
"clitoken": token,
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
try:
|
|
116
|
+
response = requests.post(url, headers=headers)
|
|
117
|
+
response.raise_for_status()
|
|
118
|
+
return response.json()
|
|
119
|
+
|
|
120
|
+
except Exception as e:
|
|
121
|
+
logger.error(f"Error during API request: {e}")
|
|
122
|
+
raise ValueError("An error occurred during the API request. Check the logs for details.")
|
|
123
|
+
|
|
124
|
+
def delete_job_request(id):
|
|
125
|
+
url = f"{VIGIL_API_BASE_URL}/evaluations/remove"
|
|
126
|
+
username, token = load_config()
|
|
127
|
+
|
|
128
|
+
if not username or not token:
|
|
129
|
+
raise ValueError("Username or token not found in configuration.")
|
|
130
|
+
|
|
131
|
+
headers = {
|
|
132
|
+
"username": username,
|
|
133
|
+
"clitoken": token,
|
|
134
|
+
}
|
|
135
|
+
params = {"task_id": id}
|
|
136
|
+
try:
|
|
137
|
+
response = requests.post(url, params=params, headers=headers)
|
|
138
|
+
response.raise_for_status()
|
|
139
|
+
return response.json()
|
|
140
|
+
|
|
141
|
+
except Exception as e:
|
|
142
|
+
logger.error(f"Error during API request: {e.detail}")
|
|
143
|
+
raise ValueError("An error occurred during the API request. Check the logs for details.")
|
|
144
|
+
|
|
145
|
+
def download_report_request(file_id):
|
|
146
|
+
|
|
147
|
+
try:
|
|
148
|
+
download_url = f"{VIGIL_API_BASE_URL}/evaluations/download_file?file_id={file_id}"
|
|
149
|
+
response = requests.get(download_url)
|
|
150
|
+
response.raise_for_status()
|
|
151
|
+
|
|
152
|
+
filename = response.headers.get('Content-Disposition', '').split('filename=')[1].strip('"')
|
|
153
|
+
|
|
154
|
+
with open(filename, 'wb') as file:
|
|
155
|
+
file.write(response.content)
|
|
156
|
+
|
|
157
|
+
return f"File downloaded successfully: {filename}"
|
|
158
|
+
|
|
159
|
+
except requests.exceptions.RequestException as e:
|
|
160
|
+
raise ValueError(f"Error during file download: {e}")
|
|
161
|
+
|
|
162
|
+
def list_job_request():
|
|
163
|
+
|
|
164
|
+
jobs_url = f"{VIGIL_API_BASE_URL}/jobs/"
|
|
165
|
+
try:
|
|
166
|
+
username, token = load_config()
|
|
167
|
+
|
|
168
|
+
if not username or not token:
|
|
169
|
+
raise ValueError("Username or token not found in configuration.")
|
|
170
|
+
|
|
171
|
+
headers = {
|
|
172
|
+
"username": username,
|
|
173
|
+
"clitoken": token,
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
response = requests.get(jobs_url, headers=headers)
|
|
177
|
+
response.raise_for_status()
|
|
178
|
+
jobs_data = response.json()
|
|
179
|
+
|
|
180
|
+
if not jobs_data:
|
|
181
|
+
return {
|
|
182
|
+
"message": "No jobs found."
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
return {
|
|
186
|
+
"table_data":jobs_data
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
except requests.exceptions.RequestException as e:
|
|
190
|
+
raise ValueError(f"Error fetching jobs: {e}")
|
|
191
|
+
|
|
192
|
+
def get_job_detail_request(id):
|
|
193
|
+
url = f"{VIGIL_API_BASE_URL}/jobs/detail"
|
|
194
|
+
username, token = load_config()
|
|
195
|
+
|
|
196
|
+
if not username or not token:
|
|
197
|
+
raise ValueError("Username or token not found in configuration.")
|
|
198
|
+
|
|
199
|
+
headers = {
|
|
200
|
+
"username": username,
|
|
201
|
+
"clitoken": token,
|
|
202
|
+
}
|
|
203
|
+
params = {"job_id": id}
|
|
204
|
+
try:
|
|
205
|
+
response = requests.get(url, params=params, headers=headers)
|
|
206
|
+
response.raise_for_status()
|
|
207
|
+
return response.json()
|
|
208
|
+
|
|
209
|
+
except Exception as e:
|
|
210
|
+
logger.error(f"Error during API request: {e}")
|
|
211
|
+
raise ValueError("An error occurred during the API request. Check the logs for details.")
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import json
|
|
3
|
+
from datetime import datetime, timedelta
|
|
4
|
+
|
|
5
|
+
HIDDEN_DIR_NAME = ".vijil"
|
|
6
|
+
CONFIG_FILE_NAME = "vijil_config.json"
|
|
7
|
+
CONFIG_FILE_PATH = os.path.join(os.path.expanduser('~'), HIDDEN_DIR_NAME, CONFIG_FILE_NAME)
|
|
8
|
+
|
|
9
|
+
def save_config(username, token):
|
|
10
|
+
config_data = {"username": username, "token": token, "timestamp": datetime.utcnow().isoformat()}
|
|
11
|
+
os.makedirs(os.path.dirname(CONFIG_FILE_PATH), exist_ok=True)
|
|
12
|
+
with open(CONFIG_FILE_PATH, 'w') as config_file:
|
|
13
|
+
json.dump(config_data, config_file)
|
|
14
|
+
|
|
15
|
+
def load_config():
|
|
16
|
+
try:
|
|
17
|
+
with open(CONFIG_FILE_PATH, 'r') as config_file:
|
|
18
|
+
config_data = json.load(config_file)
|
|
19
|
+
timestamp = datetime.fromisoformat(config_data.get("timestamp"))
|
|
20
|
+
expiration_time = timestamp + timedelta(days=2)
|
|
21
|
+
if datetime.utcnow() <= expiration_time:
|
|
22
|
+
return config_data.get("username"), config_data.get("token")
|
|
23
|
+
else:
|
|
24
|
+
remove_config()
|
|
25
|
+
return None, None
|
|
26
|
+
except (FileNotFoundError, json.JSONDecodeError, KeyError):
|
|
27
|
+
return None, None
|
|
28
|
+
|
|
29
|
+
def remove_config():
|
|
30
|
+
try:
|
|
31
|
+
os.remove(CONFIG_FILE_PATH)
|
|
32
|
+
return None
|
|
33
|
+
except FileNotFoundError:
|
|
34
|
+
pass
|