Skip to content
This repository was archived by the owner on Mar 17, 2024. It is now read-only.

Commit 9fe607b

Browse files
authored
Merge pull request #261 from scaleoutsystems/release/v0.6.0-1
Release/v0.6.0 1
2 parents 94f35fc + dbd4e0d commit 9fe607b

32 files changed

+745
-468
lines changed

components/studio/models/apps.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,6 @@
22

33

44
class ModelsConfig(AppConfig):
5+
default_auto_field = 'django.db.models.BigAutoField'
56
name = 'models'
6-
verbose_name = 'Scaleout Models'
7+
verbose_name = 'Studio Models'

components/studio/models/fixtures/object_type.json

Lines changed: 0 additions & 29 deletions
This file was deleted.
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
[
2+
{
3+
"model": "models.objecttype",
4+
"pk": 1,
5+
"fields": {
6+
"name": "Default Model",
7+
"slug": "default",
8+
"app_slug": "default-serve"
9+
}
10+
},
11+
{
12+
"model": "models.objecttype",
13+
"pk": 2,
14+
"fields": {
15+
"name": "Tensorflow Model",
16+
"slug": "tensorflow",
17+
"app_slug": "tensorflow-serve"
18+
}
19+
},
20+
{
21+
"model": "models.objecttype",
22+
"pk": 3,
23+
"fields": {
24+
"name": "PyTorch Model",
25+
"slug": "pytorch",
26+
"app_slug": "pytorch-serve"
27+
}
28+
},
29+
{
30+
"model": "models.objecttype",
31+
"pk": 4,
32+
"fields": {
33+
"name": "MLflow Model",
34+
"slug": "mlflow",
35+
"app_slug": "mlflow-serve"
36+
}
37+
},
38+
{
39+
"model": "models.objecttype",
40+
"pk": 5,
41+
"fields": {
42+
"name": "Python Model Deployment",
43+
"slug": "python",
44+
"app_slug": "fastapi-serve"
45+
}
46+
}
47+
]

components/studio/models/forms.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,9 @@
55
class ModelForm(forms.ModelForm):
66
class Meta:
77
model = Model
8-
fields = ('uid', 'name', 'description', 'url', 'project')
9-
widgets = {
10-
'uid': forms.HiddenInput(),
11-
'project': forms.HiddenInput()
8+
fields = ('name', 'description', 'release_type', 'version', 'access', 'path')
9+
labels = {
10+
'path': ('Current folder name of your trained model*'),
1211
}
1312

1413
class ModelLogForm(forms.ModelForm):

components/studio/models/helpers.py

Lines changed: 94 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,9 @@
11
from .models import Model
22
from minio import Minio
3-
import s3fs
43
from portal.models import PublicModelObject, PublishedModel
54

6-
def get_download_url(model_id):
7-
model = Model.objects.get(pk=model_id)
8-
bucket = model.bucket
9-
path = model.path
10-
uid = model.uid
11-
12-
minio_host = model.s3.host
13-
minio_access_key = model.s3.access_key
14-
minio_secret_key = model.s3.secret_key
15-
minio_region = model.s3.region
16-
17-
download_url = ""
18-
try:
19-
client = Minio(
20-
minio_host,
21-
access_key=minio_access_key,
22-
secret_key=minio_secret_key,
23-
region=minio_region,
24-
)
25-
26-
download_url = client.presigned_get_object(bucket, path + uid)
27-
except Exception as e:
28-
print(e)
29-
30-
return download_url
5+
import io
6+
import s3fs
317

328
def add_pmo_to_publish(mdl, pmodel):
339
print(mdl.name)
@@ -63,4 +39,95 @@ def add_pmo_to_publish(mdl, pmodel):
6339
print(err)
6440

6541
print("Created public model object")
66-
pmodel.model_obj.add(pmo)
42+
pmodel.model_obj.add(pmo)
43+
44+
45+
def get_download_url(model_id):
46+
model = Model.objects.get(pk=model_id)
47+
bucket = model.bucket
48+
path = model.path
49+
uid = model.uid
50+
51+
minio_host = model.s3.host
52+
minio_access_key = model.s3.access_key
53+
minio_secret_key = model.s3.secret_key
54+
minio_region = model.s3.region
55+
56+
download_url = ""
57+
try:
58+
client = Minio(
59+
minio_host,
60+
access_key=minio_access_key,
61+
secret_key=minio_secret_key,
62+
region=minio_region,
63+
)
64+
65+
download_url = client.presigned_get_object(bucket, path + uid)
66+
except Exception as e:
67+
print(e)
68+
69+
return download_url
70+
71+
72+
# This Method use Minio Python API to create a minio client and connect it to a minio server instance
73+
def create_client(S3_storage, secure_mode=True):
74+
try:
75+
access_key = S3_storage.access_key
76+
except Exception:
77+
print("No access key could be found with the current S3 storage instance: {}".format(S3_storage))
78+
return []
79+
try:
80+
secret_key = S3_storage.secret_key
81+
except Exception:
82+
print("No secret key could be found with the current S3 storage instance: {}".format(S3_storage))
83+
return []
84+
85+
# API connection does not want scheme in the minio URL
86+
# Yet we need the URL to have the scheme included when some app charts use the minio client mc
87+
if 'http://' in S3_storage.host:
88+
minio_url = S3_storage.host.replace('http://', '')
89+
elif 'https://' in S3_storage.host:
90+
minio_url = S3_storage.host.replace('https://', '')
91+
else:
92+
minio_url = S3_storage.host
93+
94+
if not secure_mode:
95+
client = Minio(minio_url, access_key=access_key, secret_key=secret_key, secure=secure_mode)
96+
else:
97+
client = Minio(minio_url, access_key=access_key, secret_key=secret_key)
98+
99+
return client
100+
101+
102+
# This Method use Minio Python API to save an artificat into a running minio server instance
103+
def set_artifact(artifact_name, artifact_file, bucket, S3_storage, is_file=False, secure_mode=True):
104+
""" Instance must be a byte-like object. """
105+
client = create_client(S3_storage, secure_mode)
106+
107+
try:
108+
found = client.bucket_exists(bucket)
109+
except Exception as err:
110+
print('EXCEPTION LOG: Client could not verify if bucket exists')
111+
return False
112+
113+
if not found:
114+
try:
115+
client.make_bucket(bucket)
116+
except Exception as err:
117+
print('Bucket does not exist, and failed to create bucket.')
118+
return False
119+
120+
if is_file == True:
121+
try:
122+
client.fput_object(bucket, artifact_name, artifact_file)
123+
except Exception as e:
124+
print('Client method fput_object failed')
125+
return False
126+
else:
127+
try:
128+
client.put_object(bucket, artifact_name, io.BytesIO(artifact_file), len(artifact_file))
129+
except Exception as e:
130+
print('Client method put_object failed')
131+
return False
132+
133+
return True
Lines changed: 65 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,97 @@
1-
# Generated by Django 2.2.13 on 2020-08-31 08:56
1+
# Generated by Django 4.0 on 2021-12-13 08:51
22

33
from django.db import migrations, models
4-
import django.db.models.deletion
54
import django.db.models.manager
5+
import tagulous.models.models
66

77

88
class Migration(migrations.Migration):
99

1010
initial = True
1111

1212
dependencies = [
13-
('projects', '0001_initial'),
13+
('apps', '0001_initial'),
1414
]
1515

1616
operations = [
17+
migrations.CreateModel(
18+
name='Metadata',
19+
fields=[
20+
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
21+
('run_id', models.CharField(max_length=32)),
22+
('trained_model', models.CharField(default='', max_length=32)),
23+
('project', models.CharField(default='', max_length=255)),
24+
('model_details', models.TextField(blank=True)),
25+
('parameters', models.TextField(blank=True)),
26+
('metrics', models.TextField(blank=True)),
27+
],
28+
),
1729
migrations.CreateModel(
1830
name='Model',
1931
fields=[
20-
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
32+
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
2133
('uid', models.CharField(max_length=255)),
2234
('name', models.CharField(max_length=255)),
2335
('version', models.CharField(max_length=255)),
2436
('release_type', models.CharField(max_length=255)),
2537
('description', models.CharField(blank=True, max_length=255, null=True)),
38+
('model_card', models.TextField(blank=True, null=True)),
2639
('access', models.CharField(choices=[('PR', 'Private'), ('LI', 'Limited'), ('PU', 'Public')], default='PR', max_length=2)),
2740
('resource', models.URLField(blank=True, max_length=2048, null=True)),
2841
('url', models.URLField(blank=True, max_length=512, null=True)),
42+
('bucket', models.CharField(blank=True, default='models', max_length=200, null=True)),
43+
('path', models.CharField(blank=True, default='', max_length=200, null=True)),
2944
('uploaded_at', models.DateTimeField(auto_now_add=True)),
3045
('status', models.CharField(choices=[('CR', 'Created'), ('DP', 'Deployed'), ('AR', 'Archived')], default='CR', max_length=2)),
31-
('project', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='model_owner', to='projects.Project')),
46+
('model_card_headline', models.ImageField(blank=True, default=None, null=True, upload_to='models/image')),
3247
],
33-
options={
34-
'unique_together': {('name', 'version', 'project')},
35-
},
3648
managers=[
3749
('objects_version', django.db.models.manager.Manager()),
3850
],
3951
),
52+
migrations.CreateModel(
53+
name='Tagulous_Model_tags',
54+
fields=[
55+
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
56+
('name', models.CharField(max_length=255, unique=True)),
57+
('slug', models.SlugField()),
58+
('count', models.IntegerField(default=0, help_text='Internal counter of how many times this tag is in use')),
59+
('protected', models.BooleanField(default=False, help_text='Will not be deleted when the count reaches 0')),
60+
],
61+
options={
62+
'ordering': ('name',),
63+
'abstract': False,
64+
'unique_together': {('slug',)},
65+
},
66+
bases=(tagulous.models.models.BaseTagModel, models.Model),
67+
),
68+
migrations.CreateModel(
69+
name='ObjectType',
70+
fields=[
71+
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
72+
('name', models.CharField(blank=True, default='Model', max_length=100, null=True)),
73+
('slug', models.CharField(blank=True, default='model', max_length=100, null=True)),
74+
('apps', models.ManyToManyField(blank=True, to='apps.Apps')),
75+
],
76+
),
77+
migrations.CreateModel(
78+
name='ModelLog',
79+
fields=[
80+
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
81+
('run_id', models.CharField(max_length=32)),
82+
('trained_model', models.CharField(default='', max_length=32)),
83+
('project', models.CharField(default='', max_length=255)),
84+
('training_started_at', models.CharField(max_length=255)),
85+
('execution_time', models.CharField(default='', max_length=255)),
86+
('code_version', models.CharField(default='', max_length=255)),
87+
('current_git_repo', models.CharField(default='', max_length=255)),
88+
('latest_git_commit', models.CharField(default='', max_length=255)),
89+
('system_details', models.TextField(blank=True)),
90+
('cpu_details', models.TextField(blank=True)),
91+
('training_status', models.CharField(choices=[('ST', 'Started'), ('DO', 'Done'), ('FA', 'Failed')], default='ST', max_length=2)),
92+
],
93+
options={
94+
'unique_together': {('run_id', 'trained_model')},
95+
},
96+
),
4097
]
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# Generated by Django 4.0 on 2021-12-13 08:51
2+
3+
from django.db import migrations, models
4+
import django.db.models.deletion
5+
import tagulous.models.fields
6+
7+
8+
class Migration(migrations.Migration):
9+
10+
initial = True
11+
12+
dependencies = [
13+
('models', '0001_initial'),
14+
('projects', '0001_initial'),
15+
]
16+
17+
operations = [
18+
migrations.AddField(
19+
model_name='model',
20+
name='docker_image',
21+
field=models.OneToOneField(blank=True, default=None, null=True, on_delete=django.db.models.deletion.CASCADE, to='projects.environment'),
22+
),
23+
migrations.AddField(
24+
model_name='model',
25+
name='object_type',
26+
field=models.ManyToManyField(blank=True, to='models.ObjectType'),
27+
),
28+
migrations.AddField(
29+
model_name='model',
30+
name='project',
31+
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='model_owner', to='projects.project'),
32+
),
33+
migrations.AddField(
34+
model_name='model',
35+
name='s3',
36+
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='projects.s3'),
37+
),
38+
migrations.AddField(
39+
model_name='model',
40+
name='tags',
41+
field=tagulous.models.fields.TagField(_set_tag_meta=True, help_text='Enter a comma-separated tag string', to='models.Tagulous_Model_tags'),
42+
),
43+
migrations.AlterUniqueTogether(
44+
name='metadata',
45+
unique_together={('run_id', 'trained_model')},
46+
),
47+
migrations.AlterUniqueTogether(
48+
name='model',
49+
unique_together={('name', 'version', 'project')},
50+
),
51+
]

0 commit comments

Comments
 (0)