Skip to content

Commit 6d9fa4a

Browse files
committed
Initial commit
Signed-off-by: Yash Pandit <yash.pandit@oracle.com>
1 parent 2a625ed commit 6d9fa4a

File tree

1 file changed

+173
-0
lines changed

1 file changed

+173
-0
lines changed

ads/model/model-description.py

Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
import json
2+
import ads.common
3+
import oci
4+
import pytz
5+
import datetime
6+
import os
7+
from oci.data_science.models import Metadata
8+
import ads
9+
10+
class ModelDescription:
11+
12+
region = ''
13+
14+
empty_json = {
15+
"version": "1.0",
16+
"type": "modelOSSReferenceDescription",
17+
"models": []
18+
}
19+
20+
def auth(self):
21+
authData = ads.common.auth.default_signer()
22+
signer = authData['signer']
23+
self.region = authData['config']['region']
24+
25+
# data science client
26+
self.data_science_client = oci.data_science.DataScienceClient({'region': self.region}, signer=signer)
27+
# oss client
28+
self.object_storage_client = oci.object_storage.ObjectStorageClient({'region': self.region}, signer = signer)
29+
30+
def __init__(self, model_ocid=None):
31+
32+
self.auth()
33+
34+
if model_ocid == None:
35+
# if no model given then start from scratch
36+
self.modelDescriptionJson = self.empty_json
37+
else:
38+
# if model given then get that as the starting reference point
39+
print("Getting model details from backend")
40+
destination_file_path = "downloaded_artifact.json"
41+
get_model_artifact_content_response = self.data_science_client.get_model_artifact_content(
42+
model_id=model_ocid,
43+
)
44+
try:
45+
with open(destination_file_path, "wb") as f:
46+
f.write(get_model_artifact_content_response.data.content)
47+
with open(destination_file_path, 'r') as f:
48+
self.modelDescriptionJson = json.load(f)
49+
except FileNotFoundError:
50+
print(f"File '{destination_file_path}' not found.")
51+
except IOError as e:
52+
print(f"Error reading or writing to file: {e}")
53+
except json.JSONDecodeError as e:
54+
print(f"Error decoding JSON: {e}")
55+
except Exception as e:
56+
print(f"An unexpected error occurred: {e}")
57+
58+
def add(self, namespace, bucket, prefix=None, files=None):
59+
# Remove if the model already exists
60+
self.remove(namespace, bucket, prefix)
61+
62+
def checkIfFileExists(fileName):
63+
isExists = False
64+
try:
65+
headResponse = self.object_storage_client.head_object(namespace, bucket, object_name=fileName)
66+
if headResponse.status == 200:
67+
isExists = True
68+
except Exception as e:
69+
if hasattr(e, 'status') and e.status == 404:
70+
print(f"File not found in bucket: {fileName}")
71+
else:
72+
print(f"An error occured: {e}")
73+
return isExists
74+
75+
# Function to un-paginate the api call with while loop
76+
def listObjectVersionsUnpaginated():
77+
objectStorageList = []
78+
has_next_page, opc_next_page = True, None
79+
while has_next_page:
80+
response = self.object_storage_client.list_object_versions(
81+
namespace_name=namespace,
82+
bucket_name=bucket,
83+
prefix=prefix,
84+
fields="name,size",
85+
page = opc_next_page
86+
)
87+
objectStorageList.extend(response.data.items)
88+
has_next_page = response.has_next_page
89+
opc_next_page = response.next_page
90+
return objectStorageList
91+
92+
# Fetch object details and put it into the objects variable
93+
objectStorageList = []
94+
if files == None:
95+
objectStorageList = listObjectVersionsUnpaginated()
96+
else:
97+
for fileName in files:
98+
if checkIfFileExists(fileName=fileName):
99+
objectStorageList.append(self.object_storage_client.list_object_versions(
100+
namespace_name=namespace,
101+
bucket_name=bucket,
102+
prefix=fileName,
103+
fields="name,size",
104+
).data.items[0])
105+
106+
objects = [{
107+
"name": obj.name,
108+
"version": obj.version_id,
109+
"sizeInBytes": obj.size
110+
} for obj in objectStorageList if obj.size > 0]
111+
112+
if len(objects) == 0:
113+
print("No files to add in the bucket: ", bucket, " with namespace: ", namespace, " and prefix: ", prefix, " file names: ", files)
114+
return
115+
116+
self.modelDescriptionJson['models'].append({
117+
"namespace": namespace,
118+
"bucketName": bucket,
119+
"prefix": prefix,
120+
"objects": objects
121+
})
122+
123+
def remove(self, namespace, bucket, prefix=None):
124+
def findModelIdx():
125+
for idx, model in enumerate(self.modelDescriptionJson['models']):
126+
if (model['namespace'], model['bucketName'], (model['prefix'] if ('prefix' in model) else None) ) == (namespace, bucket, prefix):
127+
return idx
128+
return -1
129+
130+
modelSearchIdx = findModelIdx()
131+
if modelSearchIdx == -1:
132+
return
133+
else:
134+
# model found case
135+
self.modelDescriptionJson['models'].pop(modelSearchIdx)
136+
137+
def show(self):
138+
print(json.dumps(self.modelDescriptionJson, indent=4))
139+
140+
def build(self):
141+
print("Building...")
142+
file_path = "resultModelDescription.json"
143+
try:
144+
with open(file_path, "w") as json_file:
145+
json.dump(self.modelDescriptionJson, json_file, indent=2)
146+
except IOError as e:
147+
print(f"Error writing to file '{file_path}': {e}") # Handle the exception accordingly, e.g., log the error, retry writing, etc.
148+
except Exception as e:
149+
print(f"An unexpected error occurred: {e}") # Handle other unexpected exceptions
150+
print("Model Artifact stored at location: 'resultModelDescription.json'")
151+
return os.path.abspath(file_path)
152+
153+
def save(self, project_ocid, compartment_ocid, display_name=None):
154+
display_name = 'Created by MMS SDK on ' + datetime.datetime.now(pytz.utc).strftime('%Y-%m-%d %H:%M:%S %Z') if (display_name == None) else display_name
155+
customMetadataList = [
156+
Metadata(key="modelDescription", value = "true")
157+
]
158+
model_details = oci.data_science.models.CreateModelDetails(
159+
compartment_id = compartment_ocid,
160+
project_id = project_ocid,
161+
display_name = display_name,
162+
custom_metadata_list = customMetadataList
163+
)
164+
print("Created model details")
165+
model = self.data_science_client.create_model(model_details)
166+
print("Created model")
167+
self.data_science_client.create_model_artifact(
168+
model.data.id,
169+
json.dumps(self.modelDescriptionJson),
170+
content_disposition='attachment; filename="modelDescription.json"'
171+
)
172+
print('Successfully created model with OCID: ', model.data.id)
173+
return model.data.id

0 commit comments

Comments
 (0)