Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update Watson ML example to take output param path #3316

Merged
merged 4 commits into from
Mar 21, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 4 additions & 5 deletions components/ibm-components/watson/deploy/component.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,11 @@ implementation:
image: docker.io/aipipeline/wml-deploy:latest
command: ['python']
args: [
/app/wml-deploy.py,
-u, /app/wml-deploy.py,
--model-uid, {inputValue: model_uid},
--model-name, {inputValue: model_name},
--scoring-payload, {inputValue: scoring_payload},
--deployment-name, {inputValue: deployment_name}
--deployment-name, {inputValue: deployment_name},
--output-scoring-endpoint-path, {outputPath: scoring_endpoint},
--output-model-uid-path, {outputPath: model_uid}
]
fileOutputs:
scoring_endpoint: /tmp/scoring_endpoint
model_uid: /tmp/model_uid
13 changes: 7 additions & 6 deletions components/ibm-components/watson/deploy/src/wml-deploy.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ def getSecret(secret):
def deploy(args):
from watson_machine_learning_client import WatsonMachineLearningAPIClient
from minio import Minio
from pathlib import Path
import os
import re

Expand Down Expand Up @@ -85,12 +86,10 @@ def deploy(args):
result = 'Scoring payload is not provided'

print(result)
with open("/tmp/scoring_endpoint", "w") as f:
print(scoring_endpoint, file=f)
f.close()
with open("/tmp/model_uid", "w") as f:
print(model_uid, file=f)
f.close()
Path(args.output_scoring_endpoint_path).parent.mkdir(parents=True, exist_ok=True)
Path(args.output_scoring_endpoint_path).write_text(scoring_endpoint)
Path(args.output_model_uid_path).parent.mkdir(parents=True, exist_ok=True)
Path(args.output_model_uid_path).write_text(model_uid)


if __name__ == "__main__":
Expand All @@ -100,5 +99,7 @@ def deploy(args):
parser.add_argument('--model-uid', type=str, required=True)
parser.add_argument('--deployment-name', type=str)
parser.add_argument('--scoring-payload', type=str)
parser.add_argument('--output-scoring-endpoint-path', type=str, default='/tmp/scoring_endpoint')
parser.add_argument('--output-model-uid-path', type=str, default='/tmp/model_uid')
args = parser.parse_args()
deploy(args)
5 changes: 2 additions & 3 deletions components/ibm-components/watson/store/component.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,11 @@ implementation:
image: docker.io/aipipeline/wml-store:latest
command: ['python3']
args: [
/app/wml-store.py,
-u, /app/wml-store.py,
--run-uid, {inputValue: run_uid},
--model-name, {inputValue: model_name},
--framework, {inputValue: framework},
--framework-version, {inputValue: framework_version},
--runtime-version, {inputValue: runtime_version},
--output-model-uid-path, {outputPath: model_uid}
]
fileOutputs:
model_uid: /tmp/model_uid
18 changes: 12 additions & 6 deletions components/ibm-components/watson/store/src/wml-store.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@ def getSecret(secret):
f.close()
return res

def store(wml_model_name, run_uid, framework, framework_version, runtime_version):
def store(wml_model_name, run_uid, framework, framework_version, runtime_version, output_model_uid_path):
from watson_machine_learning_client import WatsonMachineLearningAPIClient
from pathlib import Path

# retrieve credentials
wml_url = getSecret("/app/secrets/wml_url")
Expand All @@ -42,7 +43,7 @@ def store(wml_model_name, run_uid, framework, framework_version, runtime_version
# store the model
meta_props_tf = {
client.repository.ModelMetaNames.NAME: wml_model_name,
client.repository.ModelMetaNames.RUNTIME_UID : runtime_uid,
client.repository.ModelMetaNames.RUNTIME_UID: runtime_uid,
client.repository.ModelMetaNames.TYPE: runtime_type
}

Expand All @@ -51,9 +52,8 @@ def store(wml_model_name, run_uid, framework, framework_version, runtime_version
model_uid = client.repository.get_model_uid(model_details)
print("model_uid: ", model_uid)

with open("/tmp/model_uid", "w") as f:
f.write(model_uid)
f.close()
Path(output_model_uid_path).parent.mkdir(parents=True, exist_ok=True)
Path(output_model_uid_path).write_text(model_uid)

import time
time.sleep(120)
Expand All @@ -66,5 +66,11 @@ def store(wml_model_name, run_uid, framework, framework_version, runtime_version
parser.add_argument('--framework', type=str, required=True)
parser.add_argument('--framework-version', type=str, required=True)
parser.add_argument('--runtime-version', type=str, required=True)
parser.add_argument('--output-model-uid-path', type=str, default='/tmp/model_uid')
args = parser.parse_args()
store(args.model_name, args.run_uid, args.framework, args.framework_version, args.runtime_version)
store(args.model_name,
args.run_uid,
args.framework,
args.framework_version,
args.runtime_version,
args.output_model_uid_path)
9 changes: 4 additions & 5 deletions components/ibm-components/watson/train/component.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ implementation:
image: docker.io/aipipeline/wml-train:latest
command: ['python3']
args: [
/app/wml-train.py,
-u, /app/wml-train.py,
--config, {inputValue: config},
--train-code, {inputValue: train_code},
--execution-command, {inputValue: execution_command},
Expand All @@ -48,8 +48,7 @@ implementation:
--run-name, {inputValue: run_name},
--author-name, {inputValue: author_name},
--compute-name, {inputValue: compute_name},
--compute-nodes,{inputValue: compute_nodes}
--compute-nodes,{inputValue: compute_nodes},
--output-run-uid-path, {outputPath: run_uid},
--output-training-uid-path, {outputPath: training_uid}
]
fileOutputs:
run_uid: /tmp/run_uid
training_uid: /tmp/training_uid
23 changes: 16 additions & 7 deletions components/ibm-components/watson/train/src/wml-train.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ def train(args):
from watson_machine_learning_client import WatsonMachineLearningAPIClient
from minio import Minio
from urllib.parse import urlsplit
from pathlib import Path
import os,time

wml_train_code = args.train_code
Expand Down Expand Up @@ -82,6 +83,14 @@ def train(args):
client.runtimes.LibraryMetaNames.FILEPATH: model_code,
client.runtimes.LibraryMetaNames.PLATFORM: {"name": wml_framework_name, "versions": [wml_framework_version]}
}
# check exisiting library
library_details = client.runtimes.get_library_details()
for library_detail in library_details['resources']:
if library_detail['entity']['name'] == wml_run_definition:
# Delete library if exist because we cannot update model_code
uid = client.runtimes.get_library_uid(library_detail)
client.repository.delete(uid)
break
custom_library_details = client.runtimes.store_library(lib_meta)
custom_library_uid = client.runtimes.get_library_uid(custom_library_details)

Expand Down Expand Up @@ -175,18 +184,16 @@ def train(args):
status = client.training.get_status(run_uid)
print(status)

with open("/tmp/run_uid", "w") as f:
f.write(run_uid)
f.close()
Path(args.output_run_uid_path).parent.mkdir(parents=True, exist_ok=True)
Path(args.output_run_uid_path).write_text(run_uid)

# Get training details
training_details = client.training.get_details(run_uid)
print("training_details", training_details)

with open("/tmp/training_uid", "w") as f:
training_uid = training_uid = training_details['entity']['results_reference']['location']['training']
f.write(training_uid)
f.close()
training_uid = training_details['entity']['results_reference']['location']['training']
Path(args.output_training_uid_path).parent.mkdir(parents=True, exist_ok=True)
Path(args.output_training_uid_path).write_text(training_uid)

if __name__ == "__main__":
import argparse
Expand All @@ -203,6 +210,8 @@ def train(args):
parser.add_argument('--config', type=str, default="secret_name")
parser.add_argument('--compute-name', type=str)
parser.add_argument('--compute-nodes', type=str)
parser.add_argument('--output-run-uid-path', type=str, default="/tmp/run_uid")
parser.add_argument('--output-training-uid-path', type=str, default="/tmp/training_uid")
args = parser.parse_args()
# Check secret name is not empty
if (not args.config):
Expand Down
20 changes: 16 additions & 4 deletions samples/contrib/ibm-samples/watson/watson_train_serve_pipeline.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,26 @@
import kfp
from kfp import components
from kfp import dsl
import ai_pipeline_params as params

secret_name = 'kfp-creds'
configuration_op = components.load_component_from_url('https://raw.githubusercontent.com/kubeflow/pipelines/master/components/ibm-components/commons/config/component.yaml')
train_op = components.load_component_from_url('https://raw.githubusercontent.com/kubeflow/pipelines/master/components/ibm-components/watson/train/component.yaml')
store_op = components.load_component_from_url('https://raw.githubusercontent.com/kubeflow/pipelines/master/components/ibm-components/watson/store/component.yaml')
deploy_op = components.load_component_from_url('https://raw.githubusercontent.com/kubeflow/pipelines/master/components/ibm-components/watson/deploy/component.yaml')

# Helper function for secret mount and image pull policy
def use_ai_pipeline_params(secret_name, secret_volume_mount_path='/app/secrets', image_pull_policy='IfNotPresent'):
def _use_ai_pipeline_params(task):
from kubernetes import client as k8s_client
task = task.add_volume(k8s_client.V1Volume(name=secret_name, # secret_name as volume name
secret=k8s_client.V1SecretVolumeSource(secret_name=secret_name)))
task.container.add_volume_mount(k8s_client.V1VolumeMount(mount_path=secret_volume_mount_path,
name=secret_name))
task.container.set_image_pull_policy(image_pull_policy)
return task
return _use_ai_pipeline_params


# create pipelines

@dsl.pipeline(
Expand Down Expand Up @@ -66,7 +78,7 @@ def kfp_wml_pipeline(
run_name=run_name,
compute_name=compute_name,
compute_nodes=compute_nodes
).apply(params.use_ai_pipeline_params(secret_name)).set_image_pull_policy('Always')
).apply(use_ai_pipeline_params(secret_name, image_pull_policy='Always'))

# op3 - this operation stores the model trained above
wml_store = store_op(
Expand All @@ -75,14 +87,14 @@ def kfp_wml_pipeline(
framework=framework,
framework_version=framework_version,
runtime_version=runtime_version
).apply(params.use_ai_pipeline_params(secret_name)).set_image_pull_policy('Always')
).apply(use_ai_pipeline_params(secret_name, image_pull_policy='Always'))

# op4 - this operation deploys the model to a web service and run scoring with the payload in the cloud object store
wml_deploy = deploy_op(
wml_store.output,
model_name,
scoring_payload
).apply(params.use_ai_pipeline_params(secret_name)).set_image_pull_policy('Always')
).apply(use_ai_pipeline_params(secret_name, image_pull_policy='Always'))

if __name__ == '__main__':
# compile the pipeline
Expand Down