Skip to content

Commit 5f65010

Browse files
authored
Merge pull request #16 from algorithmiaio/integrated-mlops-agent
ALGO-62 Integrated mlops agent
2 parents b1bd418 + a44964b commit 5f65010

File tree

6 files changed

+72
-11
lines changed

6 files changed

+72
-11
lines changed

adk/ADK.py

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,12 @@
33
import os
44
import sys
55
import Algorithmia
6+
import os
7+
import subprocess
8+
69
from adk.io import create_exception, format_data, format_response
710
from adk.modeldata import ModelData
11+
from adk.mlops import MLOps
812

913

1014
class ADK(object):
@@ -17,6 +21,7 @@ def __init__(self, apply_func, load_func=None, client=None):
1721
:param client: A Algorithmia Client instance that might be user defined,
1822
and is used for interacting with a model manifest file; if defined.
1923
"""
24+
self.mlops = None
2025
self.FIFO_PATH = "/tmp/algoout"
2126

2227
if client:
@@ -39,10 +44,8 @@ def __init__(self, apply_func, load_func=None, client=None):
3944
self.load_result = None
4045
self.loading_exception = None
4146
self.manifest_path = "model_manifest.json"
42-
self.model_data = self.init_manifest(self.manifest_path)
43-
44-
def init_manifest(self, path):
45-
return ModelData(self.client, path)
47+
self.mlops_path = "mlops.json"
48+
self.model_data = ModelData(self.client, self.manifest_path)
4649

4750
def load(self):
4851
try:
@@ -91,8 +94,18 @@ def write_to_pipe(self, payload, pprint=print):
9194
def process_local(self, local_payload, pprint):
9295
result = self.apply(local_payload)
9396
self.write_to_pipe(result, pprint=pprint)
97+
98+
def mlops_init(self):
99+
mlops_token = os.environ.get("DATAROBOT_MLOPS_API_TOKEN", None)
100+
if mlops_token:
101+
self.mlops = MLOps(mlops_token, self.mlops_path)
102+
self.mlops.init()
103+
else:
104+
raise Exception("'DATAROBOT_MLOPS_API_TOKEN' was not found, please set to use mlops.")
94105

95-
def init(self, local_payload=None, pprint=print):
106+
def init(self, local_payload=None, pprint=print, mlops=False):
107+
if mlops and not self.is_local:
108+
self.mlops_init()
96109
self.load()
97110
if self.is_local and local_payload is not None:
98111
if self.loading_exception:

adk/mlops.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import yaml
2+
import json
3+
import os
4+
import subprocess
5+
6+
7+
class MLOps(object):
8+
spool_dir = "/tmp/ta"
9+
agent_dir = "/opt/mlops-agent"
10+
mlops_dir_name = "datarobot_mlops_package-8.1.2"
11+
12+
def __init__(self, api_token, path):
13+
self.token = api_token
14+
if os.path.exists(path):
15+
with open(path) as f:
16+
mlops_config = json.load(f)
17+
else:
18+
raise Exception("'mlops.json' file does not exist, but mlops was requested.")
19+
if not os.path.exists(self.agent_dir):
20+
raise Exception("environment is not configured for mlops.\nPlease select a valid mlops enabled environment.")
21+
self.endpoint = mlops_config['datarobot_mlops_service_url']
22+
self.model_id = mlops_config['model_id']
23+
self.deployment_id = mlops_config['deployment_id']
24+
self.mlops_name = mlops_config.get('mlops_dir_name', 'datarobot_mlops_package-8.1.2')
25+
26+
def init(self):
27+
os.environ['MLOPS_DEPLOYMENT_ID'] = self.deployment_id
28+
os.environ['MLOPS_MODEL_ID'] = self.model_id
29+
os.environ['MLOPS_SPOOLER_TYPE'] = "FILESYSTEM"
30+
os.environ['MLOPS_FILESYSTEM_DIRECTORY'] = self.spool_dir
31+
32+
with open(f'{self.agent_dir}/{self.mlops_dir_name}/conf/mlops.agent.conf.yaml') as f:
33+
documents = yaml.load(f, Loader=yaml.FullLoader)
34+
documents['mlopsUrl'] = self.endpoint
35+
documents['apiToken'] = self.token
36+
with open(f'{self.agent_dir}/{self.mlops_dir_name}/conf/mlops.agent.conf.yaml', 'w') as f:
37+
yaml.dump(documents, f)
38+
39+
subprocess.call(f'{self.agent_dir}/{self.mlops_dir_name}/bin/start-agent.sh')
40+
check = subprocess.Popen([f'{self.agent_dir}/{self.mlops_dir_name}/bin/status-agent.sh'], stdout=subprocess.PIPE)
41+
output = check.stdout.readlines()[0]
42+
check.terminate()
43+
if b"DataRobot MLOps-Agent is running as a service." in output:
44+
return True
45+
else:
46+
raise Exception(output)

adk/modeldata.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -88,16 +88,16 @@ def find_optional_model(self, file_name):
8888
else:
8989
self.models[file_name] = FileData(real_hash, local_data_path)
9090

91-
9291
def get_manifest(self):
9392
if os.path.exists(self.manifest_frozen_path):
9493
with open(self.manifest_frozen_path) as f:
9594
manifest_data = json.load(f)
9695
if check_lock(manifest_data):
9796
return manifest_data
9897
else:
99-
raise Exception("Manifest FreezeFile Tamper Detected; please use the CLI and 'algo freeze' to rebuild your "
100-
"algorithm's freeze file.")
98+
raise Exception(
99+
"Manifest FreezeFile Tamper Detected; please use the CLI and 'algo freeze' to rebuild your "
100+
"algorithm's freeze file.")
101101
elif os.path.exists(self.manifest_reg_path):
102102
with open(self.manifest_reg_path) as f:
103103
manifest_data = json.load(f)

requirements.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
algorithmia>=1.7,<2
2-
six
2+
six
3+
pyaml>=21.10,<21.11

setup.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
author_email='support@algorithmia.com',
1515
packages=['adk'],
1616
install_requires=[
17+
'pyaml>=21.10,<21.11',
1718
'six',
1819
],
1920
include_package_data=True,

tests/AdkTest.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from adk import ADK
2-
2+
from adk.modeldata import ModelData
33

44
class ADKTest(ADK):
55
def __init__(self, apply_func, load_func=None, client=None, manifest_path="model_manifest.json.freeze"):
66
super(ADKTest, self).__init__(apply_func, load_func, client)
7-
self.model_data = self.init_manifest(manifest_path)
7+
self.model_data = ModelData(self.client, manifest_path)

0 commit comments

Comments
 (0)