Skip to content

Commit 10b9701

Browse files
committed
renamed lock to freeze, adjusted architecture of model data service
1 parent bd99599 commit 10b9701

File tree

10 files changed

+88
-94
lines changed

10 files changed

+88
-94
lines changed

adk/ADK.py

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,49 +2,54 @@
22
import json
33
import os
44
import sys
5+
import Algorithmia
56
from adk.io import create_exception, format_data, format_response
6-
from adk.manifest.manifest import Manifest
7+
from adk.manifest.modeldata import ModelData
78

89

910
class ADK(object):
10-
def __init__(self, apply_func, load_func=None, client=None, manifest_path="model_manifest.json.lock"):
11+
def __init__(self, apply_func, load_func=None, client=None):
1112
"""
1213
Creates the adk object
1314
:param apply_func: A required function that can have an arity of 1-2, depending on if loading occurs
1415
:param load_func: An optional supplier function used if load time events are required, if a model manifest is provided;
1516
the function may have a single `manifest` parameter to interact with the model manifest, otherwise must have no parameters.
1617
:param client: A Algorithmia Client instance that might be user defined,
1718
and is used for interacting with a model manifest file; if defined.
18-
:param manifest_path: A development / testing facing variable used to set the name and path
1919
"""
2020
self.FIFO_PATH = "/tmp/algoout"
21+
22+
if client:
23+
self.client = client
24+
else:
25+
self.client = Algorithmia.client()
26+
2127
apply_args, _, _, _, _, _, _ = inspect.getfullargspec(apply_func)
2228
self.apply_arity = len(apply_args)
2329
if load_func:
2430
load_args, _, _, _, _, _, _ = inspect.getfullargspec(load_func)
2531
self.load_arity = len(load_args)
26-
if self.load_arity > 2:
27-
raise Exception("load function may either have no parameters, or one parameter providing the manifest "
28-
"state.")
32+
if self.load_arity != 1:
33+
raise Exception("load function expects 1 parameter to be used to store algorithm state")
2934
self.load_func = load_func
3035
else:
3136
self.load_func = None
32-
if len(apply_args) > 2 or len(apply_args) == 0:
33-
raise Exception("apply function may have between 1 and 2 parameters, not {}".format(len(apply_args)))
3437
self.apply_func = apply_func
3538
self.is_local = not os.path.exists(self.FIFO_PATH)
3639
self.load_result = None
3740
self.loading_exception = None
38-
self.manifest = Manifest(client, manifest_path)
41+
self.manifest_path = "model_manifest.json.freeze"
42+
self.model_data = self.init_manifest(self.manifest_path)
43+
44+
def init_manifest(self, path):
45+
return ModelData(self.client, path)
3946

4047
def load(self):
4148
try:
42-
if self.manifest.available():
43-
self.manifest.initialize()
44-
if self.load_func and self.load_arity == 1:
45-
self.load_result = self.load_func(self.manifest)
46-
elif self.load_func:
47-
self.load_result = self.load_func()
49+
if self.model_data.available():
50+
self.model_data.initialize()
51+
if self.load_func:
52+
self.load_result = self.load_func(self.model_data)
4853
except Exception as e:
4954
self.loading_exception = e
5055
finally:

adk/manifest/manifest.py renamed to adk/manifest/modeldata.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,14 @@
44
from adk.manifest.classes import FileData
55

66

7-
class Manifest(object):
7+
class ModelData(object):
88
def __init__(self, client, model_manifest_path):
99
self.manifest_lock_path = model_manifest_path
1010
self.manifest_data = get_manifest(self.manifest_lock_path)
1111
self.client = client
1212
self.models = {}
13+
self.user_data = {}
14+
self.system_data = {}
1315

1416
def available(self):
1517
if self.manifest_data:
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"required_files": [{"name": "squeezenet", "source_uri": "data://AlgorithmiaSE/image_cassification_demo/squeezenet1_1-f364aa15.pth", "fail_on_tamper": true, "metadata": {"dataset_md5_checksum": "46a44d32d2c5c07f7f66324bef4c7266"}, "md5_checksum": "46a44d32d2c5c07f7f66324bef4c7266"}, {"name": "labels", "source_uri": "data://AlgorithmiaSE/image_cassification_demo/imagenet_class_index.json", "fail_on_tamper": true, "metadata": {"dataset_md5_checksum": "46a44d32d2c5c07f7f66324bef4c7266"}, "md5_checksum": "c2c37ea517e94d9795004a39431a14cb"}], "optional_files": [{"name": "mobilenet", "source_uri": "data://AlgorithmiaSE/image_cassification_demo/mobilenet_v2-b0353104.pth", "fail_on_tamper": false, "metadata": {"dataset_md5_checksum": "46a44d32d2c5c07f7f66324bef4c7266"}}], "timestamp": "1633450866.985464", "lock_checksum": "24f5eca888d87661ca6fc08042e40cb7"}

tests/AdkTest.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
from adk import ADK
2+
3+
4+
class ADKTest(ADK):
5+
def __init__(self, apply_func, load_func=None, client=None, manifest_path="model_manifest.json.freeze"):
6+
super(ADKTest, self).__init__(apply_func, load_func, client)
7+
self.model_data = self.init_manifest(manifest_path)

tests/adk_algorithms.py

Lines changed: 18 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -14,45 +14,39 @@ def apply_binary(input):
1414
return bytes("hello " + input, encoding='utf8')
1515

1616

17-
def apply_input_or_context(input, globals=None):
18-
if isinstance(globals, dict):
19-
return globals
17+
def apply_input_or_context(input, model_data=None):
18+
if model_data:
19+
return model_data.user_data
2020
else:
2121
return "hello " + input
2222

2323

24-
def apply_successful_manifest_parsing(input, result):
25-
if result:
24+
def apply_successful_manifest_parsing(input, model_data):
25+
if model_data:
2626
return "all model files were successfully loaded"
2727
else:
2828
return "model files were not loaded correctly"
2929

3030

3131
# -- Loading functions --- #
32-
def loading_text():
33-
context = dict()
34-
context['message'] = 'This message was loaded prior to runtime'
35-
return context
32+
def loading_text(modelData):
33+
modelData.user_data['message'] = 'This message was loaded prior to runtime'
34+
return modelData
3635

3736

38-
def loading_exception():
37+
def loading_exception(modelData):
3938
raise Exception("This exception was thrown in loading")
4039

4140

42-
def loading_file_from_algorithmia():
43-
context = dict()
44-
client = Algorithmia.client()
45-
context['data_url'] = 'data://demo/collection/somefile.json'
46-
context['data'] = client.file(context['data_url']).getJson()
47-
return context
41+
def loading_file_from_algorithmia(modelData):
42+
modelData.user_data['data_url'] = 'data://demo/collection/somefile.json'
43+
modelData.user_data['data'] = modelData.client.file(modelData.user_data['data_url']).getJson()
44+
return modelData
4845

4946

50-
def loading_with_manifest(manifest):
51-
squeezenet_path = manifest.get_model("squeezenet")
52-
labels_path = manifest.get_model("labels")
47+
def loading_with_manifest(modelData):
48+
modelData.user_data["squeezenet"] = modelData.get_model("squeezenet")
49+
modelData.user_data['labels'] = modelData.get_model("labels")
5350
# optional model
54-
mobilenet_path = manifest.get_model("mobilenet")
55-
if os.path.exists(squeezenet_path) and os.path.exists(labels_path) and os.path.exists(mobilenet_path):
56-
return True
57-
else:
58-
return False
51+
modelData.user_data['mobilenet'] = modelData.get_model("mobilenet")
52+
return modelData

tests/manifests/good_model_manifest.json.lock

Lines changed: 0 additions & 34 deletions
This file was deleted.

tests/test_adk_local.py

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import json
22
import os
33
import unittest
4-
from adk import ADK
4+
from tests.AdkTest import ADKTest
55
from tests.adk_algorithms import *
66

77

@@ -14,21 +14,24 @@ def setUp(self):
1414
except:
1515
pass
1616

17-
def execute_example(self, input, apply, load=lambda: None):
18-
algo = ADK(apply, load)
17+
def execute_example(self, input, apply, load=None):
18+
if load:
19+
algo = ADKTest(apply, load)
20+
else:
21+
algo = ADKTest(apply)
1922
output = []
2023
algo.init(input, pprint=lambda x: output.append(x))
2124
return output[0]
2225

23-
def execute_manifest_example(self, input, apply, load, manifest_path="manifests/good_model_manifest.json.lock"):
26+
def execute_manifest_example(self, input, apply, load, manifest_path="manifests/good_model_manifest.json.freeze"):
2427
client = Algorithmia.client()
25-
algo = ADK(apply, load, manifest_path=manifest_path, client=client)
28+
algo = ADKTest(apply, load, manifest_path=manifest_path, client=client)
2629
output = []
2730
algo.init(input, pprint=lambda x: output.append(x))
2831
return output[0]
2932

3033
def execute_without_load(self, input, apply):
31-
algo = ADK(apply)
34+
algo = ADKTest(apply)
3235
output = []
3336
algo.init(input, pprint=lambda x: output.append(x))
3437
return output[0]
@@ -128,7 +131,7 @@ def test_manifest_file_success(self):
128131
actual_output = json.loads(self.execute_manifest_example(input, apply_successful_manifest_parsing,
129132
loading_with_manifest,
130133
manifest_path="tests/manifests/good_model_manifest"
131-
".json.lock"))
134+
".json.freeze"))
132135
self.assertEqual(expected_output, actual_output)
133136

134137
def test_manifest_file_tampered(self):
@@ -142,7 +145,7 @@ def test_manifest_file_tampered(self):
142145
actual_output = json.loads(self.execute_manifest_example(input, apply_successful_manifest_parsing,
143146
loading_with_manifest,
144147
manifest_path="tests/manifests/bad_model_manifest"
145-
".json.lock"))
148+
".json.freeze"))
146149
self.assertEqual(expected_output, actual_output)
147150

148151

tests/test_adk_remote.py

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import json
33
import unittest
44
import os
5-
from adk import ADK
5+
from tests.AdkTest import ADKTest
66
import base64
77
from tests.adk_algorithms import *
88

@@ -43,30 +43,32 @@ def open_pipe(self):
4343
if os.name == "posix":
4444
self.fifo_pipe = os.open(self.fifo_pipe_path, os.O_RDONLY | os.O_NONBLOCK)
4545

46-
def execute_example(self, input, apply, load=lambda: None):
46+
def execute_example(self, input, apply, load=None):
4747
self.open_pipe()
48-
algo = ADK(apply, load)
48+
algo = ADKTest(apply, load)
4949
sys.stdin = input
5050
algo.init()
5151
output = self.read_in()
5252
return output
5353

5454
def execute_without_load(self, input, apply):
5555
self.open_pipe()
56-
algo = ADK(apply)
56+
algo = ADKTest(apply)
5757
sys.stdin = input
5858
algo.init()
5959
output = self.read_in()
6060
return output
6161

62-
def execute_example_local(self, input, apply, load=lambda: None):
63-
algo = ADK(apply, load)
64-
output = algo.init(input, pprint=lambda x: x)
62+
def execute_manifest_example(self, input, apply, load, manifest_path):
63+
client = Algorithmia.client()
64+
self.open_pipe()
65+
algo = ADKTest(apply, load, manifest_path=manifest_path, client=client)
66+
sys.stdin = input
67+
algo.init()
68+
output = self.read_in()
6569
return output
6670

67-
68-
69-
# ----- Tests ----- #
71+
# ----- Tests ----- #
7072

7173
def test_basic(self):
7274
input = {'content_type': 'json', 'data': 'Algorithmia'}
@@ -92,7 +94,6 @@ def test_basic_2(self):
9294
actual_output = self.execute_without_load(input, apply_basic)
9395
self.assertEqual(expected_output, actual_output)
9496

95-
9697
def test_algorithm_loading_basic(self):
9798
input = {'content_type': 'json', 'data': 'ignore me'}
9899
expected_output = {'metadata':
@@ -160,6 +161,21 @@ def test_binary_data(self):
160161
actual_output = self.execute_without_load(input, apply_binary)
161162
self.assertEqual(expected_output, actual_output)
162163

164+
def test_manifest_file_success(self):
165+
input = {'content_type': 'json', 'data': 'Algorithmia'}
166+
expected_output = {'metadata':
167+
{
168+
'content_type': 'text'
169+
},
170+
'result': "all model files were successfully loaded"
171+
}
172+
input = [str(json.dumps(input))]
173+
actual_output = self.execute_manifest_example(input, apply_successful_manifest_parsing,
174+
loading_with_manifest,
175+
manifest_path="tests/manifests/good_model_manifest"
176+
".json.freeze")
177+
self.assertEqual(expected_output, actual_output)
178+
163179

164180
def run_test():
165-
unittest.main()
181+
unittest.main()

0 commit comments

Comments
 (0)