From adbce63fe5bfc7dd5c24aa88f835ef6fa4995b5a Mon Sep 17 00:00:00 2001 From: Jeff Omhover Date: Mon, 7 Nov 2022 08:36:00 -0800 Subject: [PATCH 01/34] copy cli ds code into sdk --- .../environments/inference/conda_env.yml | 24 ++ .../environments/training/Dockerfile | 7 + .../environments/training/requirements.txt | 18 ++ .../data-science/src/summarization/compare.py | 88 ++++++ .../data-science/src/summarization/prepare.py | 151 ++++++++++ .../src/summarization/register.py | 82 ++++++ .../data-science/src/summarization/run.py | 269 ++++++++++++++++++ .../data-science/src/summarization/score.py | 44 +++ .../data/nlp-summarization-request.json | 3 + 9 files changed, 686 insertions(+) create mode 100644 nlp/python-sdk/data-science/environments/inference/conda_env.yml create mode 100644 nlp/python-sdk/data-science/environments/training/Dockerfile create mode 100644 nlp/python-sdk/data-science/environments/training/requirements.txt create mode 100644 nlp/python-sdk/data-science/src/summarization/compare.py create mode 100644 nlp/python-sdk/data-science/src/summarization/prepare.py create mode 100644 nlp/python-sdk/data-science/src/summarization/register.py create mode 100644 nlp/python-sdk/data-science/src/summarization/run.py create mode 100644 nlp/python-sdk/data-science/src/summarization/score.py create mode 100644 nlp/python-sdk/data/nlp-summarization-request.json diff --git a/nlp/python-sdk/data-science/environments/inference/conda_env.yml b/nlp/python-sdk/data-science/environments/inference/conda_env.yml new file mode 100644 index 0000000..506e979 --- /dev/null +++ b/nlp/python-sdk/data-science/environments/inference/conda_env.yml @@ -0,0 +1,24 @@ +name: nlp_inference_conda_env +channels: + - pytorch + - anaconda + - defaults + - conda-forge +dependencies: + - python=3.8 + - pip=21.2.4 + - pytorch=1.10.0 + - torchvision=0.11.1 + - torchaudio=0.10.0 + - cudatoolkit=11.1.1 + - nvidia-apex=0.1.0 + - gxx_linux-64=8.5.0 + - pip: + - azureml-defaults==1.39.0 + - azureml-mlflow==1.39.0 + - azureml-telemetry==1.39.0 + - azureml-train-core==1.39.0 + - mlflow==1.24.0 + - transformers==4.17.0 + - 'inference-schema[numpy-support]==1.3.0' + - applicationinsights==0.11.10 diff --git a/nlp/python-sdk/data-science/environments/training/Dockerfile b/nlp/python-sdk/data-science/environments/training/Dockerfile new file mode 100644 index 0000000..0be3e7a --- /dev/null +++ b/nlp/python-sdk/data-science/environments/training/Dockerfile @@ -0,0 +1,7 @@ +# check release notes https://docs.nvidia.com/deeplearning/frameworks/pytorch-release-notes/index.html +FROM nvcr.io/nvidia/pytorch:22.04-py3 + +# Install dependencies missing in this container +# NOTE: container already has matplotlib==3.5.1 tqdm==4.62.0 +COPY requirements.txt ./ +RUN pip install -r requirements.txt diff --git a/nlp/python-sdk/data-science/environments/training/requirements.txt b/nlp/python-sdk/data-science/environments/training/requirements.txt new file mode 100644 index 0000000..7446a74 --- /dev/null +++ b/nlp/python-sdk/data-science/environments/training/requirements.txt @@ -0,0 +1,18 @@ +# data science requirements +# torchvision==0.12.0 +# torch==1.11.0 +pytorch_lightning==1.6.4 +transformers==4.18.0 +datasets==2.3.2 +rouge_score==0.0.4 +sentencepiece==0.1.96 + +# for metrics reporting/plotting +mlflow==1.25.1 +azureml-mlflow==1.41.0 +# matplotlib==3.5.2 +# tqdm==4.64.0 +psutil==5.9.0 + +# for unit testing +pytest==7.1.2 diff --git a/nlp/python-sdk/data-science/src/summarization/compare.py b/nlp/python-sdk/data-science/src/summarization/compare.py new file mode 100644 index 0000000..51e7b19 --- /dev/null +++ b/nlp/python-sdk/data-science/src/summarization/compare.py @@ -0,0 +1,88 @@ +import os +import argparse +import logging +import mlflow +import json +from distutils.util import strtobool + +def main(): + """Main function of the script.""" + # initialize root logger + logger = logging.getLogger() + logger.setLevel(logging.INFO) + console_handler = logging.StreamHandler() + formatter = logging.Formatter( + "%(asctime)s : %(levelname)s : %(name)s : %(message)s" + ) + console_handler.setFormatter(formatter) + logger.addHandler(console_handler) + + # input and output arguments + parser = argparse.ArgumentParser() + parser.add_argument( + "--baseline_metrics", + type=str, + required=True, + help="path to baseline metrics folder containing all_results.json", + ) + parser.add_argument( + "--candidate_metrics", + type=str, + required=True, + help="path to candidate metrics folder containing all_results.json", + ) + parser.add_argument( + "--reference_metric", + type=str, + default="predict_rougeLsum", + help="name of reference metric for shipping flag (default: predict_rougeLsum)", + ) + parser.add_argument( + "--force_comparison", type=strtobool, default=False, help="set to True to bypass comparison and set --deploy_flag to True" + ) + parser.add_argument( + "--deploy_flag", type=str, help="a deploy flag whether to deploy or not" + ) + + args = parser.parse_args() + + # Start Logging + mlflow.start_run() + + logger.info(f"Running with arguments: {args}") + + # open metrics on both sides + with open(os.path.join(args.baseline_metrics, "all_results.json")) as in_file: + baseline_metrics = json.loads(in_file.read()) + with open(os.path.join(args.candidate_metrics, "all_results.json")) as in_file: + candidate_metrics = json.loads(in_file.read()) + + # should we ship or not? + if args.force_comparison: + deploy_flag = True + else: + deploy_flag = ( + candidate_metrics[args.reference_metric] + > baseline_metrics[args.reference_metric] + ) + + logger.info("baseline_metrics[{}]={}, candidate_metrics[{}]={}, deploy_flag={} (force_comparison={})".format( + args.reference_metric, + baseline_metrics[args.reference_metric], + args.reference_metric, + candidate_metrics[args.reference_metric], + deploy_flag, + args.force_comparison + )) + + # save deploy_flag as a file + os.makedirs(args.deploy_flag, exist_ok=True) + with open(os.path.join(args.deploy_flag, "deploy_flag"), "w") as out_file: + out_file.write("%d" % int(deploy_flag)) + + # Stop Logging + mlflow.end_run() + + +if __name__ == "__main__": + main() diff --git a/nlp/python-sdk/data-science/src/summarization/prepare.py b/nlp/python-sdk/data-science/src/summarization/prepare.py new file mode 100644 index 0000000..042e0c7 --- /dev/null +++ b/nlp/python-sdk/data-science/src/summarization/prepare.py @@ -0,0 +1,151 @@ +""" +This scripts prepares a HuggingFace dataset to be used +for fine-tuning. It encodes the train/val/test tests and +outputs as JSONL files. +""" +import os +import argparse +import logging +from datasets import load_dataset, DatasetDict +from transformers import AutoTokenizer +import mlflow + + +def main(): + """Main function of the script.""" + # initialize root logger + logger = logging.getLogger() + logger.setLevel(logging.INFO) + console_handler = logging.StreamHandler() + formatter = logging.Formatter( + "%(asctime)s : %(levelname)s : %(name)s : %(message)s" + ) + console_handler.setFormatter(formatter) + logger.addHandler(console_handler) + + # input and output arguments + parser = argparse.ArgumentParser() + parser.add_argument( + "--dataset_name", type=str, help="name of dataset or path to input dataset_name" + ) + parser.add_argument( + "--dataset_config", type=str, help="config for huggingface dataset" + ) + parser.add_argument("--text_column", type=str, help="name of text_column") + parser.add_argument("--summary_column", type=str, help="name of summary_column") + parser.add_argument( + "--max_input_length", type=int, default=512, help="max_input_length" + ) + parser.add_argument( + "--max_target_length", type=int, default=40, help="max_target_length" + ) + parser.add_argument( + "--padding", type=str, default="max_length", help="padding type" + ) + parser.add_argument( + "--model_arch", + type=str, + help="name of the model to prepare for in HF model library", + ) + parser.add_argument( + "--limit_samples", type=int, default=-1, help="sample size from input dataset" + ) + parser.add_argument("--encodings", type=str, help="path to tokenized dataset") + parser.add_argument( + "--source_prefix", + type=str, + help="A prefix to add before every source text (useful for T5 models).", + ) + + args = parser.parse_args() + + # Start Logging + mlflow.start_run() + + logger.info(f"Running with arguments: {args}") + + # get tokenizer ready + tokenizer = AutoTokenizer.from_pretrained(args.model_arch) + logger.info(f"tokenizer: {tokenizer}") + + prefix = args.source_prefix if args.source_prefix is not None else "" + if args.source_prefix is None and "t5" in args.model_arch.lower(): + logger.warning( + "You're running a t5 model but didn't provide a source prefix, which is the expected, e.g. with " + "`--source_prefix 'summarize: ' `" + ) + + # Load HuggingFace dataset + raw_dataset = load_dataset(args.dataset_name, args.dataset_config) + + logger.info(f"raw dataset length: {raw_dataset.num_rows}") + mlflow.log_metric("train_samples", raw_dataset["train"].shape[0]) + mlflow.log_metric("test_samples", raw_dataset["test"].shape[0]) + mlflow.log_metric("validation_samples", raw_dataset["validation"].shape[0]) + + if args.limit_samples > 0: + sample_sizes = { + k: min(len(raw_dataset[k]), args.limit_samples) for k in raw_dataset.keys() + } + raw_dataset = DatasetDict( + { + k: raw_dataset[k].select([i for i in range(sample_sizes[k])]) + for k in raw_dataset.keys() + } + ) + logger.info("sampled raw dataset:") + logger.info(raw_dataset.num_rows) + + def preprocess_function(examples): + # remove pairs where at least one record is None + + inputs, targets = [], [] + for i in range(len(examples[args.text_column])): + if ( + examples[args.text_column][i] is not None + and examples[args.summary_column][i] is not None + ): + inputs.append(examples[args.text_column][i]) + targets.append(examples[args.summary_column][i]) + + inputs = [prefix + inp for inp in inputs] + model_inputs = tokenizer( + inputs, + max_length=args.max_input_length, + padding=args.padding, + truncation=True, + ) + # Set up the tokenizer for targets + with tokenizer.as_target_tokenizer(): + labels = tokenizer( + examples[args.summary_column], + max_length=args.max_target_length, + padding=args.padding, + truncation=True, + ) + + # replace all tokenizer.pad_token_id in the labels by -100 to ignore padding in the loss. + if args.padding == "max_length": + labels["input_ids"] = [ + [(l if l != tokenizer.pad_token_id else -100) for l in label] + for label in labels["input_ids"] + ] + model_inputs["labels"] = labels["input_ids"] + return model_inputs + + preprocessed_datasets = raw_dataset.map(preprocess_function, batched=True) + logger.info(f"preprocessed_datasets: {preprocessed_datasets}") + + output_path = os.path.join(args.encodings) + os.makedirs(output_path, exist_ok=True) + + preprocessed_datasets.save_to_disk(output_path) + + logger.info(f"tokenized data is saved to {output_path}") + + # Stop Logging + mlflow.end_run() + + +if __name__ == "__main__": + main() diff --git a/nlp/python-sdk/data-science/src/summarization/register.py b/nlp/python-sdk/data-science/src/summarization/register.py new file mode 100644 index 0000000..5b6b750 --- /dev/null +++ b/nlp/python-sdk/data-science/src/summarization/register.py @@ -0,0 +1,82 @@ +from azureml.core import Run +from azureml.core.model import Model + +import os +import argparse +import logging +import mlflow + + +def main(): + """Main function of the script.""" + # initialize root logger + logger = logging.getLogger() + logger.setLevel(logging.INFO) + console_handler = logging.StreamHandler() + formatter = logging.Formatter( + "%(asctime)s : %(levelname)s : %(name)s : %(message)s" + ) + console_handler.setFormatter(formatter) + logger.addHandler(console_handler) + + # input and output arguments + parser = argparse.ArgumentParser() + parser.add_argument( + "--model_folder", + type=str, + required=True, + help="folder containing model", + ) + parser.add_argument( + "--register_as", + type=str, + required=True, + help="name to use for model registration in AzureML", + ) + parser.add_argument( + "--deploy_flag", type=str, required=True, help="a deploy flag whether to deploy or not" + ) + + args = parser.parse_args() + logger.info(f"Running with arguments: {args}") + + # Start Logging + mlflow.start_run() + + if os.path.isfile(args.deploy_flag): + deploy_flag_file_path = args.deploy_flag + else: + deploy_flag_file_path = os.path.join(args.deploy_flag, "deploy_flag") + + logger.info(f"Opening deploy_flag file from {deploy_flag_file_path}") + with open(deploy_flag_file_path, 'rb') as in_file: + deploy_flag = bool(int(in_file.read())) + + if deploy_flag: + logger.info(f"Deploy flag is True, registering model as {args.register_as}...") + run = Run.get_context() + + # if we're running locally, except + if run.__class__.__name__ == "_OfflineRun": + raise Exception("You can't run this script locally, you will need to run it as an AzureML job.") + + _ = Model.register( + run.experiment.workspace, + model_name=args.register_as, + model_path=args.model_folder, + tags={ + "type": "huggingface", + "task": "summarization" + }, + description="Huggingface model finetuned for summarization", + ) + else: + logger.info(f"Deploy flag is False, pass.") + + # Stop Logging + mlflow.end_run() + + +if __name__ == "__main__": + main() + diff --git a/nlp/python-sdk/data-science/src/summarization/run.py b/nlp/python-sdk/data-science/src/summarization/run.py new file mode 100644 index 0000000..1edb323 --- /dev/null +++ b/nlp/python-sdk/data-science/src/summarization/run.py @@ -0,0 +1,269 @@ +import logging +import os +from datasets import load_metric, load_from_disk +from transformers import ( + AutoModelForSeq2SeqLM, + AutoTokenizer, + DataCollatorForSeq2Seq, + Seq2SeqTrainingArguments, + Seq2SeqTrainer, + HfArgumentParser, + IntervalStrategy, +) +from transformers.trainer_callback import TrainerCallback + +import torch +import nltk +from dataclasses import dataclass, field +from typing import Optional +import numpy as np +import mlflow +from pynvml import * +import time + + +# Input arguments are set with dataclass. Huggingface library stores the default training args in TrainingArguments dataclass +# user args are also defined in dataclasses, we will then load arguments from a tuple of user defined and built-in dataclasses. +@dataclass +class DataArgs: + # Inputs + preprocessed_datasets: str = field( + default=None, metadata={"help": "path to preprocesed datasets"} + ) + + # Processing parameters + max_target_length: Optional[int] = field( + default=128, + metadata={"help": "maxi sequence length for target text after tokenization."}, + ) + limit_samples: Optional[int] = field( + default=-1, + metadata={"help": "limit the number of samples for faster run."}, + ) + + +@dataclass +class ModelArgs: + model_name: Optional[str] = field(default=None, metadata={"help": "model name"}) + model_path: Optional[str] = field( + default=None, metadata={"help": "path to existing model file to load"} + ) + model_output: Optional[str] = field( + default=None, metadata={"help": "path to save the model"} + ) + + +nltk.download("punkt") + + +def print_gpu_utilization(): + nvmlInit() + handle = nvmlDeviceGetHandleByIndex(0) + info = nvmlDeviceGetMemoryInfo(handle) + print(f"GPU memory occupied: {info.used//1024**2} MB.") + + +def print_summary(result): + print(f"Time: {result.metrics['train_runtime']:.2f}") + print(f"Samples/second: {result.metrics['train_samples_per_second']:.2f}") + print_gpu_utilization() + + +def postprocess_text(preds, labels): + """Postprocess output for computing metrics""" + preds = [pred.strip() for pred in preds] + labels = [label.strip() for label in labels] + + # rougeLSum expects newline after each sentence + preds = ["\n".join(nltk.sent_tokenize(pred)) for pred in preds] + labels = ["\n".join(nltk.sent_tokenize(label)) for label in labels] + + return preds, labels + + +def compute_metrics(eval_preds, tokenizer, metric): + """Compute metric based on predictions from evaluation""" + preds, labels = eval_preds + if isinstance(preds, tuple): + preds = preds[0] + decoded_preds = tokenizer.batch_decode(preds, skip_special_tokens=True) + + # Replace -100 in the labels as we can't decode them. + labels = np.where(labels != -100, labels, tokenizer.pad_token_id) + decoded_labels = tokenizer.batch_decode(labels, skip_special_tokens=True) + + # Some simple post-processing + decoded_preds, decoded_labels = postprocess_text(decoded_preds, decoded_labels) + + result = metric.compute( + predictions=decoded_preds, references=decoded_labels, use_stemmer=True + ) + # Extract a few results from ROUGE + result = {key: value.mid.fmeasure * 100 for key, value in result.items()} + + prediction_lens = [ + np.count_nonzero(pred != tokenizer.pad_token_id) for pred in preds + ] + result["gen_len"] = np.mean(prediction_lens) + result = {k: round(v, 4) for k, v in result.items()} + return result + + +class CustomCallback(TrainerCallback): + """A [`TrainerCallback`] that sends the logs to [AzureML](https://pypi.org/project/azureml-sdk/). + + This is a hotfix for the issue raised here: + https://github.com/huggingface/transformers/issues/18870 + """ + def on_log(self, args, state, control, logs=None, **kwargs): + if state.is_world_process_zero: + metrics = {} + for k, v in logs.items(): + if isinstance(v, (int, float)): + metrics[k] = v + mlflow.log_metrics(metrics=metrics, step=state.global_step) + + +def main(): + # Setup logging + logger = logging.getLogger() + logger.setLevel(logging.INFO) + console_handler = logging.StreamHandler() + formatter = logging.Formatter( + "%(asctime)s : %(levelname)s : %(name)s : %(message)s" + ) + console_handler.setFormatter(formatter) + logger.addHandler(console_handler) + + # initialize the mlflow session + mlflow.start_run() + + parser = HfArgumentParser((ModelArgs, DataArgs, Seq2SeqTrainingArguments)) + model_args, data_args, training_args = parser.parse_args_into_dataclasses() + logger.info(f"Running with arguments: {model_args}, {data_args}, {training_args}") + + # Check if this is the main node + is_this_main_node = int(os.environ.get("RANK", "0")) == 0 + if is_this_main_node: + logger.info("This is the main Node") + + input_datasets = load_from_disk(data_args.preprocessed_datasets) + logger.info(f"preprocessed dataset is loaded") + + if model_args.model_path: + logger.info("using a saved model") + model = AutoModelForSeq2SeqLM.from_pretrained(model_args.model_path) + tokenizer = AutoTokenizer.from_pretrained(model_args.model_path) + else: + logger.info("using a model from model library") + model = AutoModelForSeq2SeqLM.from_pretrained(model_args.model_name) + tokenizer = AutoTokenizer.from_pretrained(model_args.model_name) + + # Artificially limit the number of samples (for testing) + if training_args.do_train: # if using --do-train from Seq2SeqTrainingArguments + if data_args.limit_samples > 0: + max_train_samples = min(len(input_datasets["train"]), data_args.limit_samples) + train_dataset = input_datasets["train"].select(range(max_train_samples)) + logger.info(f"train: making a {max_train_samples} sample of the data") + else: + train_dataset = input_datasets["train"] + + if training_args.do_eval: + if data_args.limit_samples > 0: + max_eval_samples = min( + len(input_datasets["validation"]), data_args.limit_samples + ) + eval_dataset = input_datasets["validation"].select(range(max_eval_samples)) + logger.info(f"eval: making a {max_eval_samples} sample of the data") + else: + eval_dataset = input_datasets["validation"] + + if training_args.do_predict: + if data_args.limit_samples > 0: + max_predict_samples = min( + len(input_datasets["test"]), data_args.limit_samples + ) + predict_dataset = input_datasets["test"].select(range(max_predict_samples)) + logger.info(f"predict: making a {max_predict_samples} sample of the data") + else: + predict_dataset = input_datasets["test"] + + # Data collator + label_pad_token_id = -100 + + data_collator = DataCollatorForSeq2Seq( + tokenizer, + model=model, + label_pad_token_id=label_pad_token_id, + ) + + # Metric + metric = load_metric("rouge") + + if training_args.do_train: + logging_steps = len(train_dataset) // training_args.per_device_train_batch_size + training_args.logging_steps = logging_steps + #training_args.output_dir = "outputs" + training_args.save_strategy = "epoch" + training_args.evaluation_strategy = IntervalStrategy.EPOCH + training_args.predict_with_generate = True + training_args.report_to = [] # use our own callback + logger.info(f"training args: {training_args}") + + # Initialize our Trainer + trainer = Seq2SeqTrainer( + model=model, + args=training_args, + train_dataset=train_dataset if training_args.do_train else None, + eval_dataset=eval_dataset if training_args.do_eval else None, + tokenizer=tokenizer, + data_collator=data_collator, + compute_metrics=lambda preds : compute_metrics(preds, tokenizer, metric), + callbacks=[CustomCallback] + ) + + # Start the actual training (to include evaluation use --do-eval) + if training_args.do_train: + logger.info("Start training") + start = time.time() + train_result = trainer.train() + + mlflow.log_metric( + "time/epoch", (time.time() - start) / 60 / training_args.num_train_epochs + ) + logger.info( + "training is done" + ) # Only print gpu utilization if gpu is available + if torch.cuda.is_available(): + print_summary(train_result) + + # Save the model as an output + if model_args.model_output and is_this_main_node: + logger.info(f"Saving the model at {model_args.model_output}") + os.makedirs(model_args.model_output, exist_ok=True) + trainer.save_model(model_args.model_output) + + # Just run the predictions + if training_args.do_predict: + logger.info("*** Predict ***") + max_length = ( + training_args.generation_max_length + if training_args.generation_max_length is not None + else data_args.max_target_length + ) + + predict_results = trainer.predict( + predict_dataset, metric_key_prefix="predict", max_length=max_length + ) + metrics = predict_results.metrics + metrics["predict_samples"] = len(predict_dataset) + + trainer.log_metrics("predict", metrics) + trainer.save_metrics("predict", metrics) + + # Stop Logging + mlflow.end_run() + + +if __name__ == "__main__": + main() diff --git a/nlp/python-sdk/data-science/src/summarization/score.py b/nlp/python-sdk/data-science/src/summarization/score.py new file mode 100644 index 0000000..267b635 --- /dev/null +++ b/nlp/python-sdk/data-science/src/summarization/score.py @@ -0,0 +1,44 @@ +import os +import logging +import json +from transformers import ( + AutoModelForSeq2SeqLM, + AutoTokenizer, +) + +def init(): + """ + This function is called when the container is initialized/started, typically after create/update of the deployment. + You can write the logic here to perform init operations like caching the model in memory + """ + global model, tokenizer + # AZUREML_MODEL_DIR is an environment variable created during deployment. + # It is the path to the model folder (./azureml-models/$MODEL_NAME/$VERSION) + model_path = os.path.join(os.getenv("AZUREML_MODEL_DIR"), os.listdir(os.getenv("AZUREML_MODEL_DIR"))[0]) + print("model_path") + print(os.listdir(model_path)) + model = AutoModelForSeq2SeqLM.from_pretrained(model_path) + tokenizer = AutoTokenizer.from_pretrained(model_path) + print("Init complete") + + +def run(raw_data): + global model, tokenizer + """ + This function is called for every invocation of the endpoint to perform the actual scoring/prediction. + In the example we extract the data from the json input and call the scikit-learn model's predict() + method and return the result back + """ + logging.info("Request received") + article = json.loads(raw_data)["data"] + if "t5" in model.config.architectures[0].lower(): + article= "summarize:" + article + + inputs = tokenizer(article, return_tensors="pt", max_length=512, truncation=True) + outputs = model.generate( + inputs["input_ids"], max_length=150, min_length=40, length_penalty=2.0, num_beams=4, early_stopping=True + ) + result = tokenizer.decode(outputs[0]) + print(result) + logging.info("Request processed") + return result diff --git a/nlp/python-sdk/data/nlp-summarization-request.json b/nlp/python-sdk/data/nlp-summarization-request.json new file mode 100644 index 0000000..cef4760 --- /dev/null +++ b/nlp/python-sdk/data/nlp-summarization-request.json @@ -0,0 +1,3 @@ +{ + "data":"Los Angeles (CNN) -- A medical doctor in Vancouver, British Columbia, said Thursday that California arson suspect Harry Burkhart suffered from severe mental illness in 2010, when she examined him as part of a team of doctors. Dr. Blaga Stancheva, a family physician and specialist in obstetrics, said both Burkhart and his mother, Dorothee, were her patients in Vancouver while both were applying for refugee status in Canada. \\\"I was asked to diagnose and treat Harry to support a claim explaining why he was unable to show up in a small-claims court case,\\\" Stancheva told CNN in a phone interview. She declined to cite the case or Burkhart\\'s role in it. Stancheva said she and other doctors including a psychiatrist diagnosed Burkhart with \\\"autism, severe anxiety, post-traumatic stress disorder and depression.\\\" The diagnosis was spelled out in a letter she wrote for the small-claims court case, Stancheva said. Stancheva, citing doctor-patient confidentiality, would not elaborate further, nor would she identify the psychiatrist involved in the diagnosis. Burkhart, a 24-year-old German national, has been charged with 37 counts of arson following a string of 52 fires in Los Angeles. The charges are in connection with arson fires at 12 locations scattered through Hollywood, West Hollywood and Sherman Oaks, according to authorities. Stancheva said the refugee applications by Burkhart and his mother were denied by the Canadian government, and she has not seen Burkhart since early March of 2010. \\\"I was shocked and dismayed at what happened in Los Angeles, and it appears he was not being treated for his depression,\\\" she said. Burkhart was in court on Wednesday for a preliminary hearing. Prosecutors said his \\\"rage against Americans,\\\" triggered by his mother\\'s arrest last week, motivated his \\\"campaign of terror\\\" with dozens of fires in Hollywood and nearby communities. Burkhart kept his eyes closed and remained limp during most of his hearing, requiring sheriff\\'s deputies to hold him up. The district attorney called his courtroom behavior \\\"very bizarre.\\\" \\\"This defendant has engaged in a protracted campaign in which he has set, the people believe, upwards of 52 arson fires in what essentially amounts to a campaign of terror against this community,\\\" Los Angeles County Deputy District Attorney Sean Carney said. \\\"The people believe he has engaged in this conduct because he has a hatred for Americans.\\\" Carney told the court Burkhart would flee the country if he was allowed out of jail on bond, but Los Angeles Superior Court Judge Upinder Kalra said he had no choice but to set bail. To go free while awaiting trial, Burkhart must post a $2.85 million bond and surrender his German passport. It was revealed that Burkhart is also under investigation for arson and fraud in relation to a fire in Neukirchen, near Frankfurt, Germany. The worst arson sprees in the city\\'s history began last Friday morning with a car fire in Hollywood that spread to apartments above a garage, but no new fires have happened since Burkhart was arrested Monday, Los Angeles District Attorney Steve Cooley said. No one was hurt in the fires, but property damage costs are likely to reach $3 million, authorities said. Cooley called it \\\"almost attempted murder,\\\" because people were sleeping in apartments above where Burkhart allegedly set cars on fire with incendiary devices placed under their engines. The criminal complaint filed Wednesday also alleged that the fires were \\\"caused by use of a device designed to accelerate the fire,\\\" Cooley said. \\\"If found true, the allegation could mean additional custody time for the defendant.\\\" \\\"In numerous instances, the cars were parked in carports, resulting in the fires spreading to the adjacent occupied apartment buildings,\\\" a sworn affidavit from a Los Angeles arson investigator said. \\\"The vast majority of these fires occurred late at night when the occupants of the apartment buildings were asleep.\\\" Investigator Edward Nordskog\\'s affidavit detailed Burkhart\\'s behavior a day before the fires began, when he was in a federal courtroom during extradition proceedings for his mother. \\\"While in the audience, the defendant (Burkhart) began yelling in an angry manner, \\'F--k all Americans.\\' The defendant also attempted to communicate with his mother who was in custody. Shortly thereafter, the defendant was ejected from the courtroom by Deputy U.S. Marshals,\\\" Nordskog wrote. Dorothee Burkhart was arrested a day before on an international arrest warrant issued by a district court in Frankfurt, Germany, said federal court spokesman Gunther Meilinger. The 53-year-old German woman is wanted on 16 counts of fraud and three counts of embezzlement, he said. The charges include an allegation that she failed to pay for a breast enhancement operation performed on her in 2004, Meilinger said. Most of the German charges, however, stem from phony real estate deals that Dorothee Burkhart allegedly conducted between 2000 and 2006. \\\"It is my opinion that the defendant\\'s criminal spree was motivated by his rage against Americans and that by setting these fires the defendant intended to harm and terrorize as many residents of the city and county of Los Angeles as possible,\\\" Nordskog wrote. A search of Burkhart\\'s Hollywood apartment found newspaper clippings about the Los Angeles fires and articles from Germany reporting similar car fires in Frankfurt, Germany in September, 2011, the investigator said. \\\"It is my opinion based on my experience that it is highly likely the defendant has a history of setting arson fires in Germany before he came to the United States,\\\" Nordskog wrote. Burkhart\\'s mother is scheduled for another extradition hearing Friday, while he is due back in court for arraignment on January 24. Meanwhile, both Burkharts are housed in a Los Angeles jail." +} From 13373be0fc10ab3136c524efee1c0d7efd8347f3 Mon Sep 17 00:00:00 2001 From: Jeff Omhover Date: Tue, 8 Nov 2022 12:46:23 -0800 Subject: [PATCH 02/34] register env script --- nlp/python-sdk/mlops/azureml/register-env.py | 116 +++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 nlp/python-sdk/mlops/azureml/register-env.py diff --git a/nlp/python-sdk/mlops/azureml/register-env.py b/nlp/python-sdk/mlops/azureml/register-env.py new file mode 100644 index 0000000..557c423 --- /dev/null +++ b/nlp/python-sdk/mlops/azureml/register-env.py @@ -0,0 +1,116 @@ +"""MLOps v2 NLP Python SDK register environment script.""" +import os +import argparse +import traceback + +# Azure ML sdk v2 imports +from azure.identity import DefaultAzureCredential, InteractiveBrowserCredential +from azure.ai.ml import MLClient +from azure.ai.ml.entities import Environment, BuildContext +from azure.core.exceptions import ResourceExistsError + +def get_config_parger(parser: argparse.ArgumentParser = None): + """Builds the argument parser for the script.""" + if parser is None: + parser = argparse.ArgumentParser(description=__doc__) + + parser.add_argument( + "--subscription_id", + type=str, + required=True, + help="Subscription ID", + ) + parser.add_argument( + "--resource_group", + type=str, + required=True, + help="Resource group name", + ) + parser.add_argument( + "--workspace_name", + type=str, + required=True, + help="Workspace name", + ) + parser.add_argument( + "--exists_ok", + default=False, + action="store_true", + help="if True, will not fail if environment already exists", + ) + + parser.add_argument( + "--environment_name", + default="nlp_summarization_train", + type=str, + ) + parser.add_argument( + "--environment_version", + default="mlopsv2-july2022", + type=str, + ) + parser.add_argument( + "--environment_context_path", + default=os.path.join(os.path.dirname(__file__), "..", "..", "data-science", "environments", "training"), + type=str, + ) + return parser + + +def connect_to_aml(args): + """Connect to Azure ML workspace using provided cli arguments.""" + try: + credential = DefaultAzureCredential() + # Check if given credential can get token successfully. + credential.get_token("https://management.azure.com/.default") + except Exception as ex: + # Fall back to InteractiveBrowserCredential in case DefaultAzureCredential not work + credential = InteractiveBrowserCredential() + + # Get a handle to workspace + try: + # ml_client to connect using local config.json + ML_CLIENT = MLClient.from_config(credential=credential) + + except Exception as ex: + print( + "Could not find config.json, using config.yaml refs to Azure ML workspace instead." + ) + + # tries to connect using cli args if provided else using config.yaml + ml_client = MLClient( + subscription_id=args.subscription_id, + resource_group_name=args.resource_group, + workspace_name=args.workspace_name, + credential=credential, + ) + return ml_client + + +def main(): + """Main entry point for the script.""" + parser = get_config_parger() + args, _ = parser.parse_known_args() + ml_client = connect_to_aml(args) + + custom_env = Environment( + name=args.environment_name, + build=BuildContext(path=args.environment_context_path), + tags={"project": "mlopsv2", "url": "https://github.com/Azure/mlops-v2"}, + version=args.environment_version, + ) + + try: + custom_env_create_job = ml_client.environments.create_or_update(custom_env) + print( + f"Environment with name {custom_env_create_job.name} is registered to workspace, the environment version is {custom_env_create_job.version}" + ) + except ResourceExistsError as ex: + print(f"Failed to create environment: {traceback.format_exc()}") + if not args.exists_ok: + raise + + + +if __name__ == "__main__": + main() From daed1746895bff0688d8f5faf648fc412aeffd61 Mon Sep 17 00:00:00 2001 From: Jeff Omhover Date: Tue, 8 Nov 2022 12:55:12 -0800 Subject: [PATCH 03/34] linting --- nlp/python-sdk/mlops/azureml/register-env.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/nlp/python-sdk/mlops/azureml/register-env.py b/nlp/python-sdk/mlops/azureml/register-env.py index 557c423..7580a69 100644 --- a/nlp/python-sdk/mlops/azureml/register-env.py +++ b/nlp/python-sdk/mlops/azureml/register-env.py @@ -9,6 +9,7 @@ from azure.ai.ml import MLClient from azure.ai.ml.entities import Environment, BuildContext from azure.core.exceptions import ResourceExistsError + def get_config_parger(parser: argparse.ArgumentParser = None): """Builds the argument parser for the script.""" if parser is None: @@ -51,7 +52,14 @@ def get_config_parger(parser: argparse.ArgumentParser = None): ) parser.add_argument( "--environment_context_path", - default=os.path.join(os.path.dirname(__file__), "..", "..", "data-science", "environments", "training"), + default=os.path.join( + os.path.dirname(__file__), + "..", + "..", + "data-science", + "environments", + "training", + ), type=str, ) return parser @@ -111,6 +119,5 @@ def main(): raise - if __name__ == "__main__": main() From 88e2ffc01682e92523177cf3560e3ac96ff5cf18 Mon Sep 17 00:00:00 2001 From: Jeff Omhover Date: Tue, 8 Nov 2022 13:55:19 -0800 Subject: [PATCH 04/34] add pipeline submission scrit --- .../mlops/azureml/pipeline-train.py | 405 ++++++++++++++++++ 1 file changed, 405 insertions(+) create mode 100644 nlp/python-sdk/mlops/azureml/pipeline-train.py diff --git a/nlp/python-sdk/mlops/azureml/pipeline-train.py b/nlp/python-sdk/mlops/azureml/pipeline-train.py new file mode 100644 index 0000000..451bfd8 --- /dev/null +++ b/nlp/python-sdk/mlops/azureml/pipeline-train.py @@ -0,0 +1,405 @@ +"""MLOps v2 NLP Python SDK training submission script.""" +import os +import argparse +import traceback +import time + +# Azure ML sdk v2 imports +from azure.identity import DefaultAzureCredential, InteractiveBrowserCredential +from azure.ai.ml import MLClient +from azure.ai.ml import command +from azure.ai.ml import Input, Output +from azure.ai.ml.constants import AssetTypes +from azure.ai.ml.dsl import pipeline +from azure.ai.ml import load_component +from azure.ai.ml.entities import Environment +from azure.ai.ml import dsl, Input, Output + + +def get_config_parger(parser: argparse.ArgumentParser = None): + """Builds the argument parser for the script.""" + if parser is None: + parser = argparse.ArgumentParser(description=__doc__) + + group = parser.add_argument_group("Azure ML references") + group.add_argument( + "--subscription_id", + type=str, + required=True, + help="Subscription ID", + ) + group.add_argument( + "--resource_group", + type=str, + required=True, + help="Resource group name", + ) + group.add_argument( + "--workspace_name", + type=str, + required=True, + help="Workspace name", + ) + group.add_argument( + "--experiment_name", + type=str, + required=True, + default="nlp_summarization_train", + help="Experiment name", + ) + parser.add_argument( + "--wait", + default=False, + action="store_true", + help="wait for the job to finish", + ) + + group = parser.add_argument_group("Training parameters") + group.add_argument( + "--limit_samples", + type=int, + default=1000, + ) + group.add_argument( + "--pretrained_model_name", + type=str, + default="t5-small", + ) + group.add_argument( + "--num_train_epochs", + type=int, + default=5, + ) + group.add_argument( + "--batch_size", + type=int, + default=8, + ) + group.add_argument( + "--learning_rate", + type=float, + default=0.00005, + ) + group.add_argument( + "--model_registration_name", + type=str, + default="pubmed-summarization", + ) + + group = parser.add_argument_group("Compute parameters") + group.add_argument( + "--cpu_compute", + type=str, + default="cpu-cluster", + ) + group.add_argument( + "--cpu_compute_large", + type=str, + default="cpu-cluster-lg", + ) + group.add_argument( + "--gpu_compute", + type=str, + default="gpu-cluster", + ) + group.add_argument( + "--training_nodes", + type=int, + default=1, + ) + group.add_argument( + "--gpus_per_node", + type=int, + default=1, + ) + + return parser + + +def connect_to_aml(args): + """Connect to Azure ML workspace using provided cli arguments.""" + try: + credential = DefaultAzureCredential() + # Check if given credential can get token successfully. + credential.get_token("https://management.azure.com/.default") + except Exception as ex: + # Fall back to InteractiveBrowserCredential in case DefaultAzureCredential not work + credential = InteractiveBrowserCredential() + + # Get a handle to workspace + try: + # ml_client to connect using local config.json + ML_CLIENT = MLClient.from_config(credential=credential) + + except Exception as ex: + print( + "Could not find config.json, using config.yaml refs to Azure ML workspace instead." + ) + + # tries to connect using cli args if provided else using config.yaml + ml_client = MLClient( + subscription_id=args.subscription_id, + resource_group_name=args.resource_group, + workspace_name=args.workspace_name, + credential=credential, + ) + return ml_client + + +def build_components(args): + """Builds the components for the pipeline.""" + DATA_SCIENCE_FOLDER = os.path.join( + os.path.dirname(os.path.abspath(__file__)), "..", "..", "data-science", "src" + ) + + prep_finetuning_dataset = command( + name="prep_finetuning_dataset", + display_name="Prepare dataset for training", + inputs={ + "dataset_name": Input(type="string"), + "dataset_config": Input(type="string"), + "text_column": Input(type="string"), + "summary_column": Input(type="string"), + "limit_samples": Input(type="integer"), + "max_input_length": Input(type="integer"), + "max_target_length": Input(type="integer"), + "padding": Input(type="string"), + "pretrained_model_name": Input(type="string"), + }, + outputs=dict( + encodings=Output(type="uri_folder", mode="rw_mount"), + ), + code=DATA_SCIENCE_FOLDER, + command="""python summarization/prepare.py \ + --dataset_name ${{inputs.dataset_name}} \ + --dataset_config ${{inputs.dataset_config}} \ + --text_column ${{inputs.text_column}} \ + --summary_column ${{inputs.summary_column}} \ + --limit_samples ${{inputs.limit_samples}} \ + --model_arch ${{inputs.pretrained_model_name}} \ + --max_input_length ${{inputs.max_input_length}} \ + --max_target_length ${{inputs.max_target_length}} \ + --padding ${{inputs.padding}} \ + --encodings ${{outputs.encodings}}\ + """, + environment="nlp_summarization_train@latest", + ) + + finetune_model = command( + name="finetune_model", + display_name="Fine-tune summarization model", + inputs={ + "preprocessed_datasets": Input(type="uri_folder"), + "pretrained_model_name": Input(type="string"), + "limit_samples": Input(type="integer"), + "learning_rate": Input(type="number"), + "num_train_epochs": Input(type="integer"), + "per_device_train_batch_size": Input(type="integer"), + "per_device_eval_batch_size": Input(type="integer"), + }, + outputs=dict( + finetuned_model=Output(type="uri_folder", mode="rw_mount"), + ), + code=DATA_SCIENCE_FOLDER, + command="""python summarization/run.py \ + --preprocessed_datasets ${{inputs.preprocessed_datasets}} \ + --learning_rate ${{inputs.learning_rate}} \ + --per_device_train_batch_size ${{inputs.per_device_train_batch_size}} \ + --per_device_eval_batch_size ${{inputs.per_device_eval_batch_size}} \ + --limit_samples ${{inputs.limit_samples}} \ + --model_name ${{inputs.pretrained_model_name}} \ + --model_output ${{outputs.finetuned_model}}\ + --output_dir outputs \ + --num_train_epochs ${{inputs.num_train_epochs}} \ + --do_train --do_eval \ + """, + environment="nlp_summarization_train@latest", + distribution={ + "type": "PyTorch", + # set process count to the number of gpus on the node + "process_count_per_instance": args.gpus_per_node, + }, + # set instance count to the number of nodes you want to use + instance_count=args.training_nodes, + ) + + evaluate_model = command( + name="evaluate_model", + display_name="Run eval on a model", + inputs={ + "preprocessed_datasets": Input(type="uri_folder"), + "model_path": Input(type="uri_folder", optional=True), + "model_name": Input(type="string", optional=True), + "limit_samples": Input(type="integer"), + "max_target_length": Input(type="integer"), + }, + outputs=dict( + metrics=Output(type="uri_folder", mode="rw_mount"), + ), + code=DATA_SCIENCE_FOLDER, + command="""python summarization/run.py \ + --preprocessed_datasets ${{inputs.preprocessed_datasets}} \ + --limit_samples ${{inputs.limit_samples}} \ + --output_dir ${{outputs.metrics}} \ + $[[--model_path ${{inputs.model_path}}]] \ + $[[--model_name ${{inputs.model_name}}]] \ + --max_target_length ${{inputs.max_target_length}} \ + --do_predict \ + """, + environment="nlp_summarization_train@latest", + ) + + compare_models = command( + name="compare_models", + display_name="Compare finetuned to baseline", + inputs={ + "baseline_metrics": Input(type="uri_folder"), + "candidate_metrics": Input(type="uri_folder"), + "reference_metric": Input(type="string"), + }, + outputs=dict( + deploy_flag=Output(type="uri_folder", mode="rw_mount"), + ), + code=DATA_SCIENCE_FOLDER, + command="""python summarization/compare.py \ + --baseline_metrics ${{inputs.baseline_metrics}} \ + --candidate_metrics ${{inputs.candidate_metrics}} \ + --reference_metric ${{inputs.reference_metric}} \ + --deploy_flag ${{outputs.deploy_flag}} \ + --force_comparison True\ + """, + environment="AzureML-sklearn-1.0-ubuntu20.04-py38-cpu@latest", + ) + + register_model = command( + name="register_model", + display_name="Register model", + inputs={ + "model": Input(type="uri_folder"), + "deploy_flag": Input(type="uri_folder"), + "model_registration_name": Input(type="string"), + }, + code=DATA_SCIENCE_FOLDER, + command="""python summarization/register.py \ + --model_folder ${{inputs.model}} \ + --deploy_flag ${{inputs.deploy_flag}} \ + --register_as ${{inputs.model_registration_name}} \ + """, + environment="AzureML-sklearn-1.0-ubuntu20.04-py38-cpu@latest", + ) + + return { + "prep_finetuning_dataset": prep_finetuning_dataset, + "finetune_model": finetune_model, + "evaluate_model": evaluate_model, + "compare_models": compare_models, + "register_model": register_model, + } + + +def main(): + """Main entry point for the script.""" + parser = get_config_parger() + args, _ = parser.parse_known_args() + ml_client = connect_to_aml(args) + + # get components from build function + components_dict = build_components(args) + prep_finetuning_dataset = components_dict["prep_finetuning_dataset"] + finetune_model = components_dict["finetune_model"] + evaluate_model = components_dict["evaluate_model"] + compare_models = components_dict["compare_models"] + register_model = components_dict["register_model"] + + # build the pipeline using Azure ML SDK v2 + @dsl.pipeline( + name="NLP Training Pipeline", + description="NLP Training Pipeline", + ) + def nlp_training_pipeline( + limit_samples: int, + pretrained_model_name: str, + num_train_epochs: int, + batch_size: int, + learning_rate: float, + model_registration_name: str, + ): + prep_finetuning_dataset_step = prep_finetuning_dataset( + dataset_name="ccdv/pubmed-summarization", + dataset_config="section", + text_column="article", + summary_column="abstract", + limit_samples=limit_samples, + max_input_length=512, + max_target_length=40, + padding="max_length", + pretrained_model_name=pretrained_model_name, + ) + prep_finetuning_dataset_step.compute = args.cpu_compute_large + + finetune_model_step = finetune_model( + preprocessed_datasets=prep_finetuning_dataset_step.outputs.encodings, + pretrained_model_name=pretrained_model_name, + limit_samples=limit_samples, + learning_rate=learning_rate, + num_train_epochs=num_train_epochs, + per_device_train_batch_size=batch_size, + per_device_eval_batch_size=batch_size, + ) + finetune_model_step.compute = args.gpu_compute + + evaluate_finetuned_model_step = evaluate_model( + preprocessed_datasets=prep_finetuning_dataset_step.outputs.encodings, + model_path=finetune_model_step.outputs.finetuned_model, + limit_samples=limit_samples, + max_target_length=40, + ) + evaluate_finetuned_model_step.compute = args.gpu_compute + + evaluate_baseline_model_step = evaluate_model( + preprocessed_datasets=prep_finetuning_dataset_step.outputs.encodings, + model_name=pretrained_model_name, + limit_samples=limit_samples, + max_target_length=40, + ) + evaluate_baseline_model_step.compute = args.gpu_compute + + compare_models_step = compare_models( + baseline_metrics=evaluate_finetuned_model_step.outputs.metrics, + candidate_metrics=evaluate_baseline_model_step.outputs.metrics, + reference_metric="predict_rougeLsum", + ) + compare_models_step.compute = args.cpu_compute + + register_model_step = register_model( + model=finetune_model_step.outputs.finetuned_model, + deploy_flag=compare_models_step.outputs.deploy_flag, + model_registration_name=model_registration_name, + ) + register_model_step.compute = args.cpu_compute + + # instanciates the job + pipeline_job = nlp_training_pipeline( + limit_samples=args.limit_samples, + pretrained_model_name=args.pretrained_model_name, + num_train_epochs=args.num_train_epochs, + batch_size=args.batch_size, + learning_rate=args.learning_rate, + model_registration_name=args.model_registration_name, + ) + + # submits the job + print("Submitting the pipeline job to your AzureML workspace...") + pipeline_job = ml_client.jobs.create_or_update( + pipeline_job, experiment_name=args.experiment_name + ) + + print("The url to see your live job running is returned by the sdk:") + print(pipeline_job.services["Studio"].endpoint) + + if args.wait: + ml_client.jobs.stream(pipeline_job.name) + + +if __name__ == "__main__": + main() From 57a7faf866483f3cc6d1b51bf258054c28fc3657 Mon Sep 17 00:00:00 2001 From: Jeff Omhover Date: Wed, 9 Nov 2022 09:47:39 -0800 Subject: [PATCH 05/34] move code to right folder post merge --- .../data-science/environments/inference/conda_env.yml | 0 .../data-science/environments/training/Dockerfile | 0 .../data-science/environments/training/requirements.txt | 0 .../data-science/src/summarization/compare.py | 0 .../data-science/src/summarization/prepare.py | 0 .../data-science/src/summarization/register.py | 0 .../data-science/src/summarization/run.py | 0 .../data-science/src/summarization/score.py | 0 .../data/nlp-summarization-request.json | 0 nlp/{python-sdk => python-sdk-v2}/mlops/azureml/pipeline-train.py | 0 nlp/{python-sdk => python-sdk-v2}/mlops/azureml/register-env.py | 0 11 files changed, 0 insertions(+), 0 deletions(-) rename nlp/{python-sdk => python-sdk-v2}/data-science/environments/inference/conda_env.yml (100%) rename nlp/{python-sdk => python-sdk-v2}/data-science/environments/training/Dockerfile (100%) rename nlp/{python-sdk => python-sdk-v2}/data-science/environments/training/requirements.txt (100%) rename nlp/{python-sdk => python-sdk-v2}/data-science/src/summarization/compare.py (100%) rename nlp/{python-sdk => python-sdk-v2}/data-science/src/summarization/prepare.py (100%) rename nlp/{python-sdk => python-sdk-v2}/data-science/src/summarization/register.py (100%) rename nlp/{python-sdk => python-sdk-v2}/data-science/src/summarization/run.py (100%) rename nlp/{python-sdk => python-sdk-v2}/data-science/src/summarization/score.py (100%) rename nlp/{python-sdk => python-sdk-v2}/data/nlp-summarization-request.json (100%) rename nlp/{python-sdk => python-sdk-v2}/mlops/azureml/pipeline-train.py (100%) rename nlp/{python-sdk => python-sdk-v2}/mlops/azureml/register-env.py (100%) diff --git a/nlp/python-sdk/data-science/environments/inference/conda_env.yml b/nlp/python-sdk-v2/data-science/environments/inference/conda_env.yml similarity index 100% rename from nlp/python-sdk/data-science/environments/inference/conda_env.yml rename to nlp/python-sdk-v2/data-science/environments/inference/conda_env.yml diff --git a/nlp/python-sdk/data-science/environments/training/Dockerfile b/nlp/python-sdk-v2/data-science/environments/training/Dockerfile similarity index 100% rename from nlp/python-sdk/data-science/environments/training/Dockerfile rename to nlp/python-sdk-v2/data-science/environments/training/Dockerfile diff --git a/nlp/python-sdk/data-science/environments/training/requirements.txt b/nlp/python-sdk-v2/data-science/environments/training/requirements.txt similarity index 100% rename from nlp/python-sdk/data-science/environments/training/requirements.txt rename to nlp/python-sdk-v2/data-science/environments/training/requirements.txt diff --git a/nlp/python-sdk/data-science/src/summarization/compare.py b/nlp/python-sdk-v2/data-science/src/summarization/compare.py similarity index 100% rename from nlp/python-sdk/data-science/src/summarization/compare.py rename to nlp/python-sdk-v2/data-science/src/summarization/compare.py diff --git a/nlp/python-sdk/data-science/src/summarization/prepare.py b/nlp/python-sdk-v2/data-science/src/summarization/prepare.py similarity index 100% rename from nlp/python-sdk/data-science/src/summarization/prepare.py rename to nlp/python-sdk-v2/data-science/src/summarization/prepare.py diff --git a/nlp/python-sdk/data-science/src/summarization/register.py b/nlp/python-sdk-v2/data-science/src/summarization/register.py similarity index 100% rename from nlp/python-sdk/data-science/src/summarization/register.py rename to nlp/python-sdk-v2/data-science/src/summarization/register.py diff --git a/nlp/python-sdk/data-science/src/summarization/run.py b/nlp/python-sdk-v2/data-science/src/summarization/run.py similarity index 100% rename from nlp/python-sdk/data-science/src/summarization/run.py rename to nlp/python-sdk-v2/data-science/src/summarization/run.py diff --git a/nlp/python-sdk/data-science/src/summarization/score.py b/nlp/python-sdk-v2/data-science/src/summarization/score.py similarity index 100% rename from nlp/python-sdk/data-science/src/summarization/score.py rename to nlp/python-sdk-v2/data-science/src/summarization/score.py diff --git a/nlp/python-sdk/data/nlp-summarization-request.json b/nlp/python-sdk-v2/data/nlp-summarization-request.json similarity index 100% rename from nlp/python-sdk/data/nlp-summarization-request.json rename to nlp/python-sdk-v2/data/nlp-summarization-request.json diff --git a/nlp/python-sdk/mlops/azureml/pipeline-train.py b/nlp/python-sdk-v2/mlops/azureml/pipeline-train.py similarity index 100% rename from nlp/python-sdk/mlops/azureml/pipeline-train.py rename to nlp/python-sdk-v2/mlops/azureml/pipeline-train.py diff --git a/nlp/python-sdk/mlops/azureml/register-env.py b/nlp/python-sdk-v2/mlops/azureml/register-env.py similarity index 100% rename from nlp/python-sdk/mlops/azureml/register-env.py rename to nlp/python-sdk-v2/mlops/azureml/register-env.py From 463b234344b34f98a374aefedf8960f169e12ab5 Mon Sep 17 00:00:00 2001 From: Jeff Omhover Date: Wed, 9 Nov 2022 09:58:04 -0800 Subject: [PATCH 06/34] resolve alerts --- nlp/python-sdk-v2/mlops/azureml/pipeline-train.py | 8 +------- nlp/python-sdk-v2/mlops/azureml/register-env.py | 2 +- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/nlp/python-sdk-v2/mlops/azureml/pipeline-train.py b/nlp/python-sdk-v2/mlops/azureml/pipeline-train.py index 451bfd8..293f3b3 100644 --- a/nlp/python-sdk-v2/mlops/azureml/pipeline-train.py +++ b/nlp/python-sdk-v2/mlops/azureml/pipeline-train.py @@ -1,18 +1,12 @@ """MLOps v2 NLP Python SDK training submission script.""" import os import argparse -import traceback -import time # Azure ML sdk v2 imports from azure.identity import DefaultAzureCredential, InteractiveBrowserCredential from azure.ai.ml import MLClient from azure.ai.ml import command from azure.ai.ml import Input, Output -from azure.ai.ml.constants import AssetTypes -from azure.ai.ml.dsl import pipeline -from azure.ai.ml import load_component -from azure.ai.ml.entities import Environment from azure.ai.ml import dsl, Input, Output @@ -129,7 +123,7 @@ def connect_to_aml(args): # Get a handle to workspace try: # ml_client to connect using local config.json - ML_CLIENT = MLClient.from_config(credential=credential) + ml_client = MLClient.from_config(credential=credential) except Exception as ex: print( diff --git a/nlp/python-sdk-v2/mlops/azureml/register-env.py b/nlp/python-sdk-v2/mlops/azureml/register-env.py index 7580a69..d469752 100644 --- a/nlp/python-sdk-v2/mlops/azureml/register-env.py +++ b/nlp/python-sdk-v2/mlops/azureml/register-env.py @@ -78,7 +78,7 @@ def connect_to_aml(args): # Get a handle to workspace try: # ml_client to connect using local config.json - ML_CLIENT = MLClient.from_config(credential=credential) + ml_client = MLClient.from_config(credential=credential) except Exception as ex: print( From 640c0a60d5d861817053385461ad03ba6931ed2a Mon Sep 17 00:00:00 2001 From: Jose Medina Gomez Date: Thu, 10 Nov 2022 15:10:14 -0500 Subject: [PATCH 07/34] initial ADO pipeline forlder creation for SDK --- .../deploy-model-training-pipeline.yml | 73 +++++++++++++++++++ .../deploy-online-endpoint-pipeline.yml | 61 ++++++++++++++++ 2 files changed, 134 insertions(+) create mode 100644 nlp/python-sdk-v2/mlops/devops-pipelines/deploy-model-training-pipeline.yml create mode 100644 nlp/python-sdk-v2/mlops/devops-pipelines/deploy-online-endpoint-pipeline.yml diff --git a/nlp/python-sdk-v2/mlops/devops-pipelines/deploy-model-training-pipeline.yml b/nlp/python-sdk-v2/mlops/devops-pipelines/deploy-model-training-pipeline.yml new file mode 100644 index 0000000..3b09fe5 --- /dev/null +++ b/nlp/python-sdk-v2/mlops/devops-pipelines/deploy-model-training-pipeline.yml @@ -0,0 +1,73 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. + +variables: +- ${{ if eq(variables['Build.SourceBranchName'], 'main') }}: + # 'main' branch: PRD environment + - template: ../../config-infra-prod.yml +- ${{ if ne(variables['Build.SourceBranchName'], 'main') }}: + # 'develop' or feature branches: DEV environment + - template: ../../config-infra-dev.yml +- name: version + value: aml-cli-v2 + + +trigger: +- none + +pool: + vmImage: ubuntu-20.04 + + +resources: + repositories: + - repository: mlops-templates # Template Repo + name: Azure/mlops-templates # need to change org name from "Azure" to your own org + endpoint: github-connection # need to set up and hardcode + type: github + ref: main + +stages: +- stage: DeployTrainingPipeline + displayName: Deploy Training Pipeline + jobs: + - job: DeployTrainingPipeline + steps: + - checkout: self + path: s/ + - checkout: mlops-templates + path: s/templates/ + - template: templates/${{ variables.version }}/install-az-cli.yml@mlops-templates + - template: templates/${{ variables.version }}/install-aml-cli.yml@mlops-templates + - template: templates/${{ variables.version }}/connect-to-workspace.yml@mlops-templates + - template: templates/${{ variables.version }}/create-compute.yml@mlops-templates + parameters: + cluster_name: cpu-cluster + size: STANDARD_DS3_V2 + min_instances: 0 + max_instances: 1 + cluster_tier: dedicated + - template: templates/${{ variables.version }}/create-compute.yml@mlops-templates + parameters: + cluster_name: cpu-cluster-lg + size: Standard_D14_v2 + min_instances: 0 + max_instances: 1 + cluster_tier: dedicated + - template: templates/${{ variables.version }}/create-compute.yml@mlops-templates + parameters: + cluster_name: gpu-cluster + size: Standard_NV6 + min_instances: 0 + max_instances: 1 + cluster_tier: dedicated + - template: templates/${{ variables.version }}/register-environment.yml@mlops-templates + parameters: + build_type: conda + environment_name: nlp_summarization_train + environment_file: mlops/azureml/train/train-env.yml + - template: templates/${{ variables.version }}/run-pipeline.yml@mlops-templates + parameters: + pipeline_file: mlops/azureml/train/pipeline.yml + experiment_name: $(environment)_nlp_summarization_$(Build.SourceBranchName) + display_name: $(environment)_nlp_summarization_$(Build.BuildID) diff --git a/nlp/python-sdk-v2/mlops/devops-pipelines/deploy-online-endpoint-pipeline.yml b/nlp/python-sdk-v2/mlops/devops-pipelines/deploy-online-endpoint-pipeline.yml new file mode 100644 index 0000000..2cc4a5b --- /dev/null +++ b/nlp/python-sdk-v2/mlops/devops-pipelines/deploy-online-endpoint-pipeline.yml @@ -0,0 +1,61 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. + +variables: +- ${{ if eq(variables['Build.SourceBranchName'], 'main') }}: + # 'main' branch: PRD environment + - template: ../../config-infra-prod.yml +- ${{ if ne(variables['Build.SourceBranchName'], 'main') }}: + # 'develop' or feature branches: DEV environment + - template: ../../config-infra-dev.yml +- name: version + value: aml-cli-v2 +- name: endpoint_name + value: nlp-online-$(namespace)$(postfix)$(environment) +- name: endpoint_type + value: online + + +trigger: +- none + +pool: + vmImage: ubuntu-20.04 + + +resources: + repositories: + - repository: mlops-templates # Template Repo + name: Azure/mlops-templates # need to change org name from "Azure" to your own org + endpoint: github-connection # need to set up and hardcode + type: github + ref: main + +stages: +- stage: CreateOnlineEndpoint + displayName: Create/Update Online Endpoint + jobs: + - job: DeployOnlineEndpoint + steps: + - checkout: self + path: s/ + - checkout: mlops-templates + path: s/templates/ + - template: templates/${{ variables.version }}/install-az-cli.yml@mlops-templates + - template: templates/${{ variables.version }}/install-aml-cli.yml@mlops-templates + - template: templates/${{ variables.version }}/connect-to-workspace.yml@mlops-templates + - template: templates/${{ variables.version }}/create-endpoint.yml@mlops-templates + parameters: + endpoint_file: mlops/azureml/deploy/online/online-endpoint.yml + - template: templates/${{ variables.version }}/create-deployment.yml@mlops-templates + parameters: + deployment_name: nlp-summarization-online-dp + deployment_file: mlops/azureml/deploy/online/online-deployment.yml + - template: templates/${{ variables.version }}/allocate-traffic.yml@mlops-templates + parameters: + traffic_allocation: nlp-summarization-online-dp=100 + - template: templates/${{ variables.version }}/test-deployment.yml@mlops-templates + parameters: + deployment_name: nlp-summarization-online-dp + sample_request: data/nlp-summarization-request.json + request_type: json From c3f819a95f23ec9275e016f07f330e8f6d366cd3 Mon Sep 17 00:00:00 2001 From: jomedinagomez Date: Thu, 10 Nov 2022 15:17:29 -0500 Subject: [PATCH 08/34] modified_filename for pipeline modified_filename --- .../mlops/devops-pipelines/deploy-model-training-pipeline.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nlp/python-sdk-v2/mlops/devops-pipelines/deploy-model-training-pipeline.yml b/nlp/python-sdk-v2/mlops/devops-pipelines/deploy-model-training-pipeline.yml index 3b09fe5..a38e99b 100644 --- a/nlp/python-sdk-v2/mlops/devops-pipelines/deploy-model-training-pipeline.yml +++ b/nlp/python-sdk-v2/mlops/devops-pipelines/deploy-model-training-pipeline.yml @@ -68,6 +68,6 @@ stages: environment_file: mlops/azureml/train/train-env.yml - template: templates/${{ variables.version }}/run-pipeline.yml@mlops-templates parameters: - pipeline_file: mlops/azureml/train/pipeline.yml + pipeline_file: mlops/azureml/train/pipeline-train.py experiment_name: $(environment)_nlp_summarization_$(Build.SourceBranchName) - display_name: $(environment)_nlp_summarization_$(Build.BuildID) + display_name: $(environment)_nlp_summarization_$(Build.BuildID) \ No newline at end of file From 55553e341cf905ac15ba4ae819ff4823835a3303 Mon Sep 17 00:00:00 2001 From: jomedinagomez Date: Thu, 10 Nov 2022 15:20:26 -0500 Subject: [PATCH 09/34] modifying value for version --- .../mlops/devops-pipelines/deploy-model-training-pipeline.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nlp/python-sdk-v2/mlops/devops-pipelines/deploy-model-training-pipeline.yml b/nlp/python-sdk-v2/mlops/devops-pipelines/deploy-model-training-pipeline.yml index a38e99b..8f386bd 100644 --- a/nlp/python-sdk-v2/mlops/devops-pipelines/deploy-model-training-pipeline.yml +++ b/nlp/python-sdk-v2/mlops/devops-pipelines/deploy-model-training-pipeline.yml @@ -9,7 +9,7 @@ variables: # 'develop' or feature branches: DEV environment - template: ../../config-infra-dev.yml - name: version - value: aml-cli-v2 + value: python-sdk trigger: From 6e72bf3a6d5b23deac6e4d61fc0a677a41555e3b Mon Sep 17 00:00:00 2001 From: jomedinagomez Date: Thu, 10 Nov 2022 15:25:46 -0500 Subject: [PATCH 10/34] adding additional references --- .../devops-pipelines/deploy-model-training-pipeline.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/nlp/python-sdk-v2/mlops/devops-pipelines/deploy-model-training-pipeline.yml b/nlp/python-sdk-v2/mlops/devops-pipelines/deploy-model-training-pipeline.yml index 8f386bd..3a3cc63 100644 --- a/nlp/python-sdk-v2/mlops/devops-pipelines/deploy-model-training-pipeline.yml +++ b/nlp/python-sdk-v2/mlops/devops-pipelines/deploy-model-training-pipeline.yml @@ -9,7 +9,7 @@ variables: # 'develop' or feature branches: DEV environment - template: ../../config-infra-dev.yml - name: version - value: python-sdk + value: python-sdk-v2 trigger: @@ -22,10 +22,10 @@ pool: resources: repositories: - repository: mlops-templates # Template Repo - name: Azure/mlops-templates # need to change org name from "Azure" to your own org + name: jomedinagomez/mlops-templates # need to change org name from "Azure" to your own org endpoint: github-connection # need to set up and hardcode type: github - ref: main + ref: main-dec31 stages: - stage: DeployTrainingPipeline From 8265c2da1f77856dab3621933b5ad971a4f3bf13 Mon Sep 17 00:00:00 2001 From: jomedinagomez Date: Thu, 10 Nov 2022 16:46:40 -0500 Subject: [PATCH 11/34] Create train-env.yml --- nlp/python-sdk-v2/mlops/azureml/train-env.yml | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 nlp/python-sdk-v2/mlops/azureml/train-env.yml diff --git a/nlp/python-sdk-v2/mlops/azureml/train-env.yml b/nlp/python-sdk-v2/mlops/azureml/train-env.yml new file mode 100644 index 0000000..fce1dd6 --- /dev/null +++ b/nlp/python-sdk-v2/mlops/azureml/train-env.yml @@ -0,0 +1,6 @@ + +$schema: https://azuremlschemas.azureedge.net/latest/environment.schema.json +name: nlp_summarization_train +version: mlopsv2-july2022 +build: + path: ../../../data-science/environments/training/ From fbd6227848373b86e94bb96358e108757d63c254 Mon Sep 17 00:00:00 2001 From: jomedinagomez Date: Thu, 10 Nov 2022 16:56:11 -0500 Subject: [PATCH 12/34] Update deploy-model-training-pipeline.yml --- .../mlops/devops-pipelines/deploy-model-training-pipeline.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nlp/python-sdk-v2/mlops/devops-pipelines/deploy-model-training-pipeline.yml b/nlp/python-sdk-v2/mlops/devops-pipelines/deploy-model-training-pipeline.yml index 3a3cc63..e9f665b 100644 --- a/nlp/python-sdk-v2/mlops/devops-pipelines/deploy-model-training-pipeline.yml +++ b/nlp/python-sdk-v2/mlops/devops-pipelines/deploy-model-training-pipeline.yml @@ -25,7 +25,7 @@ resources: name: jomedinagomez/mlops-templates # need to change org name from "Azure" to your own org endpoint: github-connection # need to set up and hardcode type: github - ref: main-dec31 + ref: nlp-dec31 stages: - stage: DeployTrainingPipeline From cc2eba43e400e276498e3fe303b2b9c2f1f0030c Mon Sep 17 00:00:00 2001 From: jomedinagomez Date: Thu, 10 Nov 2022 21:10:04 -0500 Subject: [PATCH 13/34] Update pipeline-train.py --- .../mlops/azureml/pipeline-train.py | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/nlp/python-sdk-v2/mlops/azureml/pipeline-train.py b/nlp/python-sdk-v2/mlops/azureml/pipeline-train.py index 293f3b3..c328a81 100644 --- a/nlp/python-sdk-v2/mlops/azureml/pipeline-train.py +++ b/nlp/python-sdk-v2/mlops/azureml/pipeline-train.py @@ -19,19 +19,19 @@ def get_config_parger(parser: argparse.ArgumentParser = None): group.add_argument( "--subscription_id", type=str, - required=True, + required=False, help="Subscription ID", ) group.add_argument( "--resource_group", type=str, - required=True, + required=False, help="Resource group name", ) group.add_argument( "--workspace_name", type=str, - required=True, + required=False, help="Workspace name", ) group.add_argument( @@ -129,14 +129,6 @@ def connect_to_aml(args): print( "Could not find config.json, using config.yaml refs to Azure ML workspace instead." ) - - # tries to connect using cli args if provided else using config.yaml - ml_client = MLClient( - subscription_id=args.subscription_id, - resource_group_name=args.resource_group, - workspace_name=args.workspace_name, - credential=credential, - ) return ml_client @@ -396,4 +388,4 @@ def main(): if __name__ == "__main__": - main() + main() \ No newline at end of file From c73e8f471f96a4d000f0efee8eaaa77a27ac0ab3 Mon Sep 17 00:00:00 2001 From: jomedinagomez Date: Thu, 10 Nov 2022 21:11:43 -0500 Subject: [PATCH 14/34] Update deploy-model-training-pipeline.yml --- .../mlops/devops-pipelines/deploy-model-training-pipeline.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/nlp/python-sdk-v2/mlops/devops-pipelines/deploy-model-training-pipeline.yml b/nlp/python-sdk-v2/mlops/devops-pipelines/deploy-model-training-pipeline.yml index e9f665b..bfb21f8 100644 --- a/nlp/python-sdk-v2/mlops/devops-pipelines/deploy-model-training-pipeline.yml +++ b/nlp/python-sdk-v2/mlops/devops-pipelines/deploy-model-training-pipeline.yml @@ -69,5 +69,4 @@ stages: - template: templates/${{ variables.version }}/run-pipeline.yml@mlops-templates parameters: pipeline_file: mlops/azureml/train/pipeline-train.py - experiment_name: $(environment)_nlp_summarization_$(Build.SourceBranchName) - display_name: $(environment)_nlp_summarization_$(Build.BuildID) \ No newline at end of file + experiment_name: $(environment)_nlp_summarization_$(Build.SourceBranchName) \ No newline at end of file From 7e228ba9c25773072beed2c25274210db6dedbd4 Mon Sep 17 00:00:00 2001 From: jomedinagomez Date: Thu, 10 Nov 2022 21:59:17 -0500 Subject: [PATCH 15/34] adding train subfolder to azureml --- nlp/python-sdk-v2/mlops/azureml/{ => train}/pipeline-train.py | 0 nlp/python-sdk-v2/mlops/azureml/{ => train}/register-env.py | 0 nlp/python-sdk-v2/mlops/azureml/{ => train}/train-env.yml | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename nlp/python-sdk-v2/mlops/azureml/{ => train}/pipeline-train.py (100%) rename nlp/python-sdk-v2/mlops/azureml/{ => train}/register-env.py (100%) rename nlp/python-sdk-v2/mlops/azureml/{ => train}/train-env.yml (100%) diff --git a/nlp/python-sdk-v2/mlops/azureml/pipeline-train.py b/nlp/python-sdk-v2/mlops/azureml/train/pipeline-train.py similarity index 100% rename from nlp/python-sdk-v2/mlops/azureml/pipeline-train.py rename to nlp/python-sdk-v2/mlops/azureml/train/pipeline-train.py diff --git a/nlp/python-sdk-v2/mlops/azureml/register-env.py b/nlp/python-sdk-v2/mlops/azureml/train/register-env.py similarity index 100% rename from nlp/python-sdk-v2/mlops/azureml/register-env.py rename to nlp/python-sdk-v2/mlops/azureml/train/register-env.py diff --git a/nlp/python-sdk-v2/mlops/azureml/train-env.yml b/nlp/python-sdk-v2/mlops/azureml/train/train-env.yml similarity index 100% rename from nlp/python-sdk-v2/mlops/azureml/train-env.yml rename to nlp/python-sdk-v2/mlops/azureml/train/train-env.yml From 58d4cdeb5bcc732f2720ab1170e58319337a6269 Mon Sep 17 00:00:00 2001 From: jomedinagomez Date: Thu, 10 Nov 2022 22:09:56 -0500 Subject: [PATCH 16/34] Update requirements.txt --- .../data-science/environments/training/requirements.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/nlp/python-sdk-v2/data-science/environments/training/requirements.txt b/nlp/python-sdk-v2/data-science/environments/training/requirements.txt index 7446a74..0a825e1 100644 --- a/nlp/python-sdk-v2/data-science/environments/training/requirements.txt +++ b/nlp/python-sdk-v2/data-science/environments/training/requirements.txt @@ -16,3 +16,6 @@ psutil==5.9.0 # for unit testing pytest==7.1.2 + +# for azure ml SDK v2 +azure-ai-ml==1.1.0 \ No newline at end of file From 54a7c9849ee1525cd826a3345bc3ea653585cbba Mon Sep 17 00:00:00 2001 From: jomedinagomez Date: Fri, 11 Nov 2022 01:16:19 -0500 Subject: [PATCH 17/34] using original pipeline-train.py --- .../mlops/azureml/train/pipeline-train.py | 14 +++++++++++--- .../deploy-model-training-pipeline.yml | 5 ++++- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/nlp/python-sdk-v2/mlops/azureml/train/pipeline-train.py b/nlp/python-sdk-v2/mlops/azureml/train/pipeline-train.py index c328a81..02dd68a 100644 --- a/nlp/python-sdk-v2/mlops/azureml/train/pipeline-train.py +++ b/nlp/python-sdk-v2/mlops/azureml/train/pipeline-train.py @@ -19,19 +19,19 @@ def get_config_parger(parser: argparse.ArgumentParser = None): group.add_argument( "--subscription_id", type=str, - required=False, + required=True, help="Subscription ID", ) group.add_argument( "--resource_group", type=str, - required=False, + required=True, help="Resource group name", ) group.add_argument( "--workspace_name", type=str, - required=False, + required=True, help="Workspace name", ) group.add_argument( @@ -129,6 +129,14 @@ def connect_to_aml(args): print( "Could not find config.json, using config.yaml refs to Azure ML workspace instead." ) + + # tries to connect using cli args if provided else using config.yaml + ml_client = MLClient( + subscription_id=args.subscription_id, + resource_group_name=args.resource_group, + workspace_name=args.workspace_name, + credential=credential, + ) return ml_client diff --git a/nlp/python-sdk-v2/mlops/devops-pipelines/deploy-model-training-pipeline.yml b/nlp/python-sdk-v2/mlops/devops-pipelines/deploy-model-training-pipeline.yml index bfb21f8..075ebee 100644 --- a/nlp/python-sdk-v2/mlops/devops-pipelines/deploy-model-training-pipeline.yml +++ b/nlp/python-sdk-v2/mlops/devops-pipelines/deploy-model-training-pipeline.yml @@ -69,4 +69,7 @@ stages: - template: templates/${{ variables.version }}/run-pipeline.yml@mlops-templates parameters: pipeline_file: mlops/azureml/train/pipeline-train.py - experiment_name: $(environment)_nlp_summarization_$(Build.SourceBranchName) \ No newline at end of file + experiment_name: $(environment)_nlp_summarization_$(Build.SourceBranchName) + resource_group: $(resource_group) + workspace_name: $(aml_workspace) + subscription_id: $(ado_service_connection_aml_ws) \ No newline at end of file From 257421b71898c13135b36f1c26e6671a036af63f Mon Sep 17 00:00:00 2001 From: jomedinagomez Date: Fri, 11 Nov 2022 01:46:47 -0500 Subject: [PATCH 18/34] Update deploy-model-training-pipeline.yml --- .../devops-pipelines/deploy-model-training-pipeline.yml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/nlp/python-sdk-v2/mlops/devops-pipelines/deploy-model-training-pipeline.yml b/nlp/python-sdk-v2/mlops/devops-pipelines/deploy-model-training-pipeline.yml index 075ebee..bfb21f8 100644 --- a/nlp/python-sdk-v2/mlops/devops-pipelines/deploy-model-training-pipeline.yml +++ b/nlp/python-sdk-v2/mlops/devops-pipelines/deploy-model-training-pipeline.yml @@ -69,7 +69,4 @@ stages: - template: templates/${{ variables.version }}/run-pipeline.yml@mlops-templates parameters: pipeline_file: mlops/azureml/train/pipeline-train.py - experiment_name: $(environment)_nlp_summarization_$(Build.SourceBranchName) - resource_group: $(resource_group) - workspace_name: $(aml_workspace) - subscription_id: $(ado_service_connection_aml_ws) \ No newline at end of file + experiment_name: $(environment)_nlp_summarization_$(Build.SourceBranchName) \ No newline at end of file From 8b3774f1f82623209e5d2acb502bdc30aefe5bc5 Mon Sep 17 00:00:00 2001 From: jomedinagomez Date: Fri, 11 Nov 2022 09:49:55 -0500 Subject: [PATCH 19/34] adding new reference to src Adjusting code to find src directory because created a new folder for train under azureml --- nlp/python-sdk-v2/mlops/azureml/train/pipeline-train.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nlp/python-sdk-v2/mlops/azureml/train/pipeline-train.py b/nlp/python-sdk-v2/mlops/azureml/train/pipeline-train.py index 02dd68a..b980cd2 100644 --- a/nlp/python-sdk-v2/mlops/azureml/train/pipeline-train.py +++ b/nlp/python-sdk-v2/mlops/azureml/train/pipeline-train.py @@ -143,7 +143,7 @@ def connect_to_aml(args): def build_components(args): """Builds the components for the pipeline.""" DATA_SCIENCE_FOLDER = os.path.join( - os.path.dirname(os.path.abspath(__file__)), "..", "..", "data-science", "src" + os.path.dirname(os.path.abspath(__file__)), "..","..", "..", "data-science", "src" ) prep_finetuning_dataset = command( From 64ff3185d2bd15537a0eb41e8734ad6e08e483f2 Mon Sep 17 00:00:00 2001 From: jomedinagomez Date: Wed, 30 Nov 2022 08:46:28 -0500 Subject: [PATCH 20/34] Update pipeline-train.py --- .../mlops/azureml/train/pipeline-train.py | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/nlp/python-sdk-v2/mlops/azureml/train/pipeline-train.py b/nlp/python-sdk-v2/mlops/azureml/train/pipeline-train.py index b980cd2..28198ec 100644 --- a/nlp/python-sdk-v2/mlops/azureml/train/pipeline-train.py +++ b/nlp/python-sdk-v2/mlops/azureml/train/pipeline-train.py @@ -8,6 +8,7 @@ from azure.ai.ml import MLClient from azure.ai.ml import command from azure.ai.ml import Input, Output from azure.ai.ml import dsl, Input, Output +import json def get_config_parger(parser: argparse.ArgumentParser = None): @@ -16,22 +17,28 @@ def get_config_parger(parser: argparse.ArgumentParser = None): parser = argparse.ArgumentParser(description=__doc__) group = parser.add_argument_group("Azure ML references") + group.add_argument( + "--config_location", + type=str, + required=False, + help="Subscription ID", + ) group.add_argument( "--subscription_id", type=str, - required=True, + required=False, help="Subscription ID", ) group.add_argument( "--resource_group", type=str, - required=True, + required=False, help="Resource group name", ) group.add_argument( "--workspace_name", type=str, - required=True, + required=False, help="Workspace name", ) group.add_argument( @@ -123,7 +130,7 @@ def connect_to_aml(args): # Get a handle to workspace try: # ml_client to connect using local config.json - ml_client = MLClient.from_config(credential=credential) + ml_client = ml_client = MLClient.from_config(credential, path='config.json') except Exception as ex: print( From 07b7c918a85a6a942416893a648a46df6dcbacab Mon Sep 17 00:00:00 2001 From: jomedinagomez Date: Wed, 30 Nov 2022 09:25:31 -0500 Subject: [PATCH 21/34] Update deploy-model-training-pipeline.yml --- .../devops-pipelines/deploy-model-training-pipeline.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/nlp/python-sdk-v2/mlops/devops-pipelines/deploy-model-training-pipeline.yml b/nlp/python-sdk-v2/mlops/devops-pipelines/deploy-model-training-pipeline.yml index bfb21f8..900e3c6 100644 --- a/nlp/python-sdk-v2/mlops/devops-pipelines/deploy-model-training-pipeline.yml +++ b/nlp/python-sdk-v2/mlops/devops-pipelines/deploy-model-training-pipeline.yml @@ -37,9 +37,9 @@ stages: path: s/ - checkout: mlops-templates path: s/templates/ - - template: templates/${{ variables.version }}/install-az-cli.yml@mlops-templates - - template: templates/${{ variables.version }}/install-aml-cli.yml@mlops-templates - - template: templates/${{ variables.version }}/connect-to-workspace.yml@mlops-templates + - template: templates/aml-cli-v2/install-az-cli.yml@mlops-templates + - template: templates/aml-cli-v2/install-aml-cli.yml@mlops-templates + - template: templates/aml-cli-v2/connect-to-workspace.yml@mlops-templates - template: templates/${{ variables.version }}/create-compute.yml@mlops-templates parameters: cluster_name: cpu-cluster From 16dc0616776052d47b6299c7cc33869352974c63 Mon Sep 17 00:00:00 2001 From: jomedinagomez Date: Wed, 30 Nov 2022 09:39:41 -0500 Subject: [PATCH 22/34] Update pipeline-train.py --- nlp/python-sdk-v2/mlops/azureml/train/pipeline-train.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/nlp/python-sdk-v2/mlops/azureml/train/pipeline-train.py b/nlp/python-sdk-v2/mlops/azureml/train/pipeline-train.py index 28198ec..bc39bc3 100644 --- a/nlp/python-sdk-v2/mlops/azureml/train/pipeline-train.py +++ b/nlp/python-sdk-v2/mlops/azureml/train/pipeline-train.py @@ -8,8 +8,6 @@ from azure.ai.ml import MLClient from azure.ai.ml import command from azure.ai.ml import Input, Output from azure.ai.ml import dsl, Input, Output -import json - def get_config_parger(parser: argparse.ArgumentParser = None): """Builds the argument parser for the script.""" From b20d7dab3a8db6d59e9a2a9eeeb812794eeaa824 Mon Sep 17 00:00:00 2001 From: jomedinagomez Date: Wed, 30 Nov 2022 11:25:12 -0500 Subject: [PATCH 23/34] Update requirements.txt --- .../environments/training/requirements.txt | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/nlp/aml-cli-v2/data-science/environments/training/requirements.txt b/nlp/aml-cli-v2/data-science/environments/training/requirements.txt index 7446a74..d2760ad 100644 --- a/nlp/aml-cli-v2/data-science/environments/training/requirements.txt +++ b/nlp/aml-cli-v2/data-science/environments/training/requirements.txt @@ -16,3 +16,13 @@ psutil==5.9.0 # for unit testing pytest==7.1.2 + +# for azure ml SDK v2 +azure-ai-ml==1.1.0 +azure-common==1.1.28 +azure-core==1.26.1 +azure-identity==1.10.0 +azure-mgmt-core==1.3.0 +azure-storage-blob==12.14.1 +azure-storage-file-datalake==12.9.1 +azure-storage-file-share==12.7.0 \ No newline at end of file From 287c701754d8b87311e634d322e01ff29bfa67e2 Mon Sep 17 00:00:00 2001 From: jomedinagomez Date: Wed, 30 Nov 2022 13:53:59 -0500 Subject: [PATCH 24/34] Delete register-env.py --- .../mlops/azureml/train/register-env.py | 123 ------------------ 1 file changed, 123 deletions(-) delete mode 100644 nlp/python-sdk-v2/mlops/azureml/train/register-env.py diff --git a/nlp/python-sdk-v2/mlops/azureml/train/register-env.py b/nlp/python-sdk-v2/mlops/azureml/train/register-env.py deleted file mode 100644 index d469752..0000000 --- a/nlp/python-sdk-v2/mlops/azureml/train/register-env.py +++ /dev/null @@ -1,123 +0,0 @@ -"""MLOps v2 NLP Python SDK register environment script.""" -import os -import argparse -import traceback - -# Azure ML sdk v2 imports -from azure.identity import DefaultAzureCredential, InteractiveBrowserCredential -from azure.ai.ml import MLClient -from azure.ai.ml.entities import Environment, BuildContext -from azure.core.exceptions import ResourceExistsError - - -def get_config_parger(parser: argparse.ArgumentParser = None): - """Builds the argument parser for the script.""" - if parser is None: - parser = argparse.ArgumentParser(description=__doc__) - - parser.add_argument( - "--subscription_id", - type=str, - required=True, - help="Subscription ID", - ) - parser.add_argument( - "--resource_group", - type=str, - required=True, - help="Resource group name", - ) - parser.add_argument( - "--workspace_name", - type=str, - required=True, - help="Workspace name", - ) - parser.add_argument( - "--exists_ok", - default=False, - action="store_true", - help="if True, will not fail if environment already exists", - ) - - parser.add_argument( - "--environment_name", - default="nlp_summarization_train", - type=str, - ) - parser.add_argument( - "--environment_version", - default="mlopsv2-july2022", - type=str, - ) - parser.add_argument( - "--environment_context_path", - default=os.path.join( - os.path.dirname(__file__), - "..", - "..", - "data-science", - "environments", - "training", - ), - type=str, - ) - return parser - - -def connect_to_aml(args): - """Connect to Azure ML workspace using provided cli arguments.""" - try: - credential = DefaultAzureCredential() - # Check if given credential can get token successfully. - credential.get_token("https://management.azure.com/.default") - except Exception as ex: - # Fall back to InteractiveBrowserCredential in case DefaultAzureCredential not work - credential = InteractiveBrowserCredential() - - # Get a handle to workspace - try: - # ml_client to connect using local config.json - ml_client = MLClient.from_config(credential=credential) - - except Exception as ex: - print( - "Could not find config.json, using config.yaml refs to Azure ML workspace instead." - ) - - # tries to connect using cli args if provided else using config.yaml - ml_client = MLClient( - subscription_id=args.subscription_id, - resource_group_name=args.resource_group, - workspace_name=args.workspace_name, - credential=credential, - ) - return ml_client - - -def main(): - """Main entry point for the script.""" - parser = get_config_parger() - args, _ = parser.parse_known_args() - ml_client = connect_to_aml(args) - - custom_env = Environment( - name=args.environment_name, - build=BuildContext(path=args.environment_context_path), - tags={"project": "mlopsv2", "url": "https://github.com/Azure/mlops-v2"}, - version=args.environment_version, - ) - - try: - custom_env_create_job = ml_client.environments.create_or_update(custom_env) - print( - f"Environment with name {custom_env_create_job.name} is registered to workspace, the environment version is {custom_env_create_job.version}" - ) - except ResourceExistsError as ex: - print(f"Failed to create environment: {traceback.format_exc()}") - if not args.exists_ok: - raise - - -if __name__ == "__main__": - main() From 4d25f840e33d801038e0fdc621053f630381517a Mon Sep 17 00:00:00 2001 From: jomedinagomez Date: Thu, 1 Dec 2022 09:49:56 -0500 Subject: [PATCH 25/34] Update deploy-model-training-pipeline.yml --- .../mlops/devops-pipelines/deploy-model-training-pipeline.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nlp/python-sdk-v2/mlops/devops-pipelines/deploy-model-training-pipeline.yml b/nlp/python-sdk-v2/mlops/devops-pipelines/deploy-model-training-pipeline.yml index 900e3c6..1a871e9 100644 --- a/nlp/python-sdk-v2/mlops/devops-pipelines/deploy-model-training-pipeline.yml +++ b/nlp/python-sdk-v2/mlops/devops-pipelines/deploy-model-training-pipeline.yml @@ -22,10 +22,10 @@ pool: resources: repositories: - repository: mlops-templates # Template Repo - name: jomedinagomez/mlops-templates # need to change org name from "Azure" to your own org + name: Azure/mlops-templates # need to change org name from "Azure" to your own org endpoint: github-connection # need to set up and hardcode type: github - ref: nlp-dec31 + ref: main-dec31 #use in reference stages: - stage: DeployTrainingPipeline From 0e57a42e8758c7268adb2bd6974c3d0c953e1073 Mon Sep 17 00:00:00 2001 From: jomedinagomez Date: Thu, 1 Dec 2022 10:50:15 -0500 Subject: [PATCH 26/34] Update deploy-model-training-pipeline.yml --- .../devops-pipelines/deploy-model-training-pipeline.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/nlp/python-sdk-v2/mlops/devops-pipelines/deploy-model-training-pipeline.yml b/nlp/python-sdk-v2/mlops/devops-pipelines/deploy-model-training-pipeline.yml index 1a871e9..ddbf41f 100644 --- a/nlp/python-sdk-v2/mlops/devops-pipelines/deploy-model-training-pipeline.yml +++ b/nlp/python-sdk-v2/mlops/devops-pipelines/deploy-model-training-pipeline.yml @@ -25,7 +25,7 @@ resources: name: Azure/mlops-templates # need to change org name from "Azure" to your own org endpoint: github-connection # need to set up and hardcode type: github - ref: main-dec31 #use in reference + ref: main-dec31 stages: - stage: DeployTrainingPipeline @@ -63,9 +63,8 @@ stages: cluster_tier: dedicated - template: templates/${{ variables.version }}/register-environment.yml@mlops-templates parameters: - build_type: conda + build_type: docker environment_name: nlp_summarization_train - environment_file: mlops/azureml/train/train-env.yml - template: templates/${{ variables.version }}/run-pipeline.yml@mlops-templates parameters: pipeline_file: mlops/azureml/train/pipeline-train.py From 70694f9dfedd96e23829c64e3a2d7ec43d84213f Mon Sep 17 00:00:00 2001 From: jomedinagomez Date: Thu, 1 Dec 2022 10:51:34 -0500 Subject: [PATCH 27/34] Delete deploy-online-endpoint-pipeline.yml --- .../deploy-online-endpoint-pipeline.yml | 61 ------------------- 1 file changed, 61 deletions(-) delete mode 100644 nlp/python-sdk-v2/mlops/devops-pipelines/deploy-online-endpoint-pipeline.yml diff --git a/nlp/python-sdk-v2/mlops/devops-pipelines/deploy-online-endpoint-pipeline.yml b/nlp/python-sdk-v2/mlops/devops-pipelines/deploy-online-endpoint-pipeline.yml deleted file mode 100644 index 2cc4a5b..0000000 --- a/nlp/python-sdk-v2/mlops/devops-pipelines/deploy-online-endpoint-pipeline.yml +++ /dev/null @@ -1,61 +0,0 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. - -variables: -- ${{ if eq(variables['Build.SourceBranchName'], 'main') }}: - # 'main' branch: PRD environment - - template: ../../config-infra-prod.yml -- ${{ if ne(variables['Build.SourceBranchName'], 'main') }}: - # 'develop' or feature branches: DEV environment - - template: ../../config-infra-dev.yml -- name: version - value: aml-cli-v2 -- name: endpoint_name - value: nlp-online-$(namespace)$(postfix)$(environment) -- name: endpoint_type - value: online - - -trigger: -- none - -pool: - vmImage: ubuntu-20.04 - - -resources: - repositories: - - repository: mlops-templates # Template Repo - name: Azure/mlops-templates # need to change org name from "Azure" to your own org - endpoint: github-connection # need to set up and hardcode - type: github - ref: main - -stages: -- stage: CreateOnlineEndpoint - displayName: Create/Update Online Endpoint - jobs: - - job: DeployOnlineEndpoint - steps: - - checkout: self - path: s/ - - checkout: mlops-templates - path: s/templates/ - - template: templates/${{ variables.version }}/install-az-cli.yml@mlops-templates - - template: templates/${{ variables.version }}/install-aml-cli.yml@mlops-templates - - template: templates/${{ variables.version }}/connect-to-workspace.yml@mlops-templates - - template: templates/${{ variables.version }}/create-endpoint.yml@mlops-templates - parameters: - endpoint_file: mlops/azureml/deploy/online/online-endpoint.yml - - template: templates/${{ variables.version }}/create-deployment.yml@mlops-templates - parameters: - deployment_name: nlp-summarization-online-dp - deployment_file: mlops/azureml/deploy/online/online-deployment.yml - - template: templates/${{ variables.version }}/allocate-traffic.yml@mlops-templates - parameters: - traffic_allocation: nlp-summarization-online-dp=100 - - template: templates/${{ variables.version }}/test-deployment.yml@mlops-templates - parameters: - deployment_name: nlp-summarization-online-dp - sample_request: data/nlp-summarization-request.json - request_type: json From f24b2072e00e1b0205ee34c3e3ae344b3af59cbf Mon Sep 17 00:00:00 2001 From: Jeff Omhover Date: Thu, 1 Dec 2022 12:04:35 -0800 Subject: [PATCH 28/34] fix variable --- nlp/python-sdk-v2/mlops/azureml/train/pipeline-train.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nlp/python-sdk-v2/mlops/azureml/train/pipeline-train.py b/nlp/python-sdk-v2/mlops/azureml/train/pipeline-train.py index bc39bc3..e34d0c0 100644 --- a/nlp/python-sdk-v2/mlops/azureml/train/pipeline-train.py +++ b/nlp/python-sdk-v2/mlops/azureml/train/pipeline-train.py @@ -128,7 +128,7 @@ def connect_to_aml(args): # Get a handle to workspace try: # ml_client to connect using local config.json - ml_client = ml_client = MLClient.from_config(credential, path='config.json') + ml_client = MLClient.from_config(credential, path='config.json') except Exception as ex: print( From 20a044b07864a14a7433f9db4571a8a76290a960 Mon Sep 17 00:00:00 2001 From: Cindy Weng <8880364+cindyweng@users.noreply.github.com> Date: Thu, 8 Dec 2022 10:12:55 +0000 Subject: [PATCH 29/34] Delete train-env.yml --- nlp/python-sdk-v2/mlops/azureml/train/train-env.yml | 6 ------ 1 file changed, 6 deletions(-) delete mode 100644 nlp/python-sdk-v2/mlops/azureml/train/train-env.yml diff --git a/nlp/python-sdk-v2/mlops/azureml/train/train-env.yml b/nlp/python-sdk-v2/mlops/azureml/train/train-env.yml deleted file mode 100644 index fce1dd6..0000000 --- a/nlp/python-sdk-v2/mlops/azureml/train/train-env.yml +++ /dev/null @@ -1,6 +0,0 @@ - -$schema: https://azuremlschemas.azureedge.net/latest/environment.schema.json -name: nlp_summarization_train -version: mlopsv2-july2022 -build: - path: ../../../data-science/environments/training/ From 3564c3d9ae1d502d5e8bf9dba773b73ba5ecd939 Mon Sep 17 00:00:00 2001 From: Cindy Weng <8880364+cindyweng@users.noreply.github.com> Date: Thu, 8 Dec 2022 10:20:30 +0000 Subject: [PATCH 30/34] Update deploy-model-training-pipeline.yml --- .../devops-pipelines/deploy-model-training-pipeline.yml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/nlp/python-sdk-v2/mlops/devops-pipelines/deploy-model-training-pipeline.yml b/nlp/python-sdk-v2/mlops/devops-pipelines/deploy-model-training-pipeline.yml index ddbf41f..cd05fd7 100644 --- a/nlp/python-sdk-v2/mlops/devops-pipelines/deploy-model-training-pipeline.yml +++ b/nlp/python-sdk-v2/mlops/devops-pipelines/deploy-model-training-pipeline.yml @@ -25,7 +25,7 @@ resources: name: Azure/mlops-templates # need to change org name from "Azure" to your own org endpoint: github-connection # need to set up and hardcode type: github - ref: main-dec31 + ref: feature/nlp-sdkv2 stages: - stage: DeployTrainingPipeline @@ -39,6 +39,7 @@ stages: path: s/templates/ - template: templates/aml-cli-v2/install-az-cli.yml@mlops-templates - template: templates/aml-cli-v2/install-aml-cli.yml@mlops-templates + - template: templates/aml-cli-v2/install-requirements.yml@mlops-templates - template: templates/aml-cli-v2/connect-to-workspace.yml@mlops-templates - template: templates/${{ variables.version }}/create-compute.yml@mlops-templates parameters: @@ -65,7 +66,8 @@ stages: parameters: build_type: docker environment_name: nlp_summarization_train + environment_path: data-science/environments/training - template: templates/${{ variables.version }}/run-pipeline.yml@mlops-templates parameters: - pipeline_file: mlops/azureml/train/pipeline-train.py - experiment_name: $(environment)_nlp_summarization_$(Build.SourceBranchName) \ No newline at end of file + pipeline_path: mlops/azureml/train/pipeline-train.py + experiment_name: $(environment)_nlp_summarization_$(Build.SourceBranchName) From 3574faa0b843174a71168af9459aad345df2a0d7 Mon Sep 17 00:00:00 2001 From: Cindy Weng <8880364+cindyweng@users.noreply.github.com> Date: Thu, 8 Dec 2022 11:20:31 +0000 Subject: [PATCH 31/34] Update pipeline-train.py --- nlp/python-sdk-v2/mlops/azureml/train/pipeline-train.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/nlp/python-sdk-v2/mlops/azureml/train/pipeline-train.py b/nlp/python-sdk-v2/mlops/azureml/train/pipeline-train.py index e34d0c0..955bef4 100644 --- a/nlp/python-sdk-v2/mlops/azureml/train/pipeline-train.py +++ b/nlp/python-sdk-v2/mlops/azureml/train/pipeline-train.py @@ -39,8 +39,9 @@ def get_config_parger(parser: argparse.ArgumentParser = None): required=False, help="Workspace name", ) + # Experiment Name group.add_argument( - "--experiment_name", + "--n", type=str, required=True, default="nlp_summarization_train", @@ -390,7 +391,7 @@ def main(): # submits the job print("Submitting the pipeline job to your AzureML workspace...") pipeline_job = ml_client.jobs.create_or_update( - pipeline_job, experiment_name=args.experiment_name + pipeline_job, experiment_name=args.n ) print("The url to see your live job running is returned by the sdk:") @@ -401,4 +402,4 @@ def main(): if __name__ == "__main__": - main() \ No newline at end of file + main() From de7240acaf5f7cd68f54ef47da8681bd568c7564 Mon Sep 17 00:00:00 2001 From: Cindy Weng <8880364+cindyweng@users.noreply.github.com> Date: Thu, 8 Dec 2022 11:21:08 +0000 Subject: [PATCH 32/34] Delete placeholder.md --- nlp/python-sdk-v2/placeholder.md | 1 - 1 file changed, 1 deletion(-) delete mode 100644 nlp/python-sdk-v2/placeholder.md diff --git a/nlp/python-sdk-v2/placeholder.md b/nlp/python-sdk-v2/placeholder.md deleted file mode 100644 index a02e803..0000000 --- a/nlp/python-sdk-v2/placeholder.md +++ /dev/null @@ -1 +0,0 @@ -# placeholder for sdk-v2 implementation of nlp \ No newline at end of file From 24d2326bb81f5da3c45d3807aae068c9092b4d1c Mon Sep 17 00:00:00 2001 From: Cindy Weng <8880364+cindyweng@users.noreply.github.com> Date: Thu, 8 Dec 2022 11:34:03 +0000 Subject: [PATCH 33/34] Update pipeline-train.py --- nlp/python-sdk-v2/mlops/azureml/train/pipeline-train.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nlp/python-sdk-v2/mlops/azureml/train/pipeline-train.py b/nlp/python-sdk-v2/mlops/azureml/train/pipeline-train.py index 955bef4..de03206 100644 --- a/nlp/python-sdk-v2/mlops/azureml/train/pipeline-train.py +++ b/nlp/python-sdk-v2/mlops/azureml/train/pipeline-train.py @@ -41,7 +41,7 @@ def get_config_parger(parser: argparse.ArgumentParser = None): ) # Experiment Name group.add_argument( - "--n", + "-n", type=str, required=True, default="nlp_summarization_train", From d313155dce8ecc0c3f43c812d12887da954bb8ad Mon Sep 17 00:00:00 2001 From: Cindy Weng <8880364+cindyweng@users.noreply.github.com> Date: Thu, 8 Dec 2022 11:41:45 +0000 Subject: [PATCH 34/34] updated branch ref --- .../mlops/devops-pipelines/deploy-model-training-pipeline.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nlp/python-sdk-v2/mlops/devops-pipelines/deploy-model-training-pipeline.yml b/nlp/python-sdk-v2/mlops/devops-pipelines/deploy-model-training-pipeline.yml index cd05fd7..64bea56 100644 --- a/nlp/python-sdk-v2/mlops/devops-pipelines/deploy-model-training-pipeline.yml +++ b/nlp/python-sdk-v2/mlops/devops-pipelines/deploy-model-training-pipeline.yml @@ -25,7 +25,7 @@ resources: name: Azure/mlops-templates # need to change org name from "Azure" to your own org endpoint: github-connection # need to set up and hardcode type: github - ref: feature/nlp-sdkv2 + ref: main-dec31 stages: - stage: DeployTrainingPipeline