Update trainingjob_controller.py, trainingjob_schema.py, test_trainingjob_controller.py, API_docs, and request.http to fully accommodate the training job creation API compatible with R1AP v8.0.
Issue-Id: AIMLFW-237
Change-Id: Iba9b70768aa33f1c3cd963128fe2d1b30217f325
Signed-off-by: yhm1620 <yhm1620@khu.ac.kr>
"header": [],
"body": {
"mode": "raw",
- "raw": "{\r\n\t\"modelId\": {\r\n \"modelname\":\"qoe11\",\r\n \"modelversion\":\"1\"\r\n },\r\n \"training_config\": {\r\n \"description\": \"trainingjob for testing\",\r\n \"dataPipeline\": {\r\n \"feature_group_name\": \"testing_influxdb_01\",\r\n \"query_filter\": \"\",\r\n \"arguments\": {\"epochs\": 1}\r\n },\r\n \"trainingPipeline\": {\r\n \"training_pipeline_name\": \"qoe_Pipeline_testing_1\", \r\n \"training_pipeline_version\": \"qoe_Pipeline_testing_1\", \r\n \"retraining_pipeline_name\":\"qoe_Pipeline_retrain\",\r\n \"retraining_pipeline_version\":\"2\"\r\n }\r\n },\r\n \"model_location\":\"\",\r\n \"training_dataset\": \"\",\r\n \"validation_dataset\": \"\",\r\n \"notification_url\": \"\",\r\n \"consumer_rapp_id\": \"\",\r\n \"producer_rapp_id\": \"\"\r\n}",
+ "raw": "{\r\n\t\"modelId\": {\r\n \"modelName\":\"qoe11\",\r\n \"modelVersion\":\"1\"\r\n },\r\n \"trainingConfig\": {\r\n \"description\": \"trainingjob for testing\",\r\n \"dataPipeline\": {\r\n \"feature_group_name\": \"testing_influxdb_01\",\r\n \"query_filter\": \"\",\r\n \"arguments\": {\"epochs\": 1}\r\n },\r\n \"trainingPipeline\": {\r\n \"training_pipeline_name\": \"qoe_Pipeline_testing_1\", \r\n \"training_pipeline_version\": \"qoe_Pipeline_testing_1\", \r\n \"retraining_pipeline_name\":\"qoe_Pipeline_retrain\",\r\n \"retraining_pipeline_version\":\"2\"\r\n }\r\n },\r\n \"modelLocation\":\"\",\r\n \"trainingDataset\": \"\",\r\n \"validationDataset\": \"\",\r\n \"notificationDestination\": \"\",\r\n \"consumerRAppId\": \"\",\r\n \"producerRAppId\": \"\"\r\n}",
"options": {
"raw": {
"language": "json"
ModelTrainingRequest:
type: object
required:
- - training_config
- - model_id
+ - trainingConfig
+ - modelId
properties:
- model_location:
+ modelLocation:
type: string
description: Path to the model location
- training_dataset:
+ trainingDataset:
type: string
description: Path to the training dataset
- validation_dataset:
+ validationDataset:
type: string
description: Path to the validation dataset
- training_config:
+ trainingConfig:
$ref: '#/definitions/TrainingConfig'
- notification_url:
+ notificationDestination:
type: string
description: Callback URL to notify after training or after any failure
- consumer_rapp_id:
+ consumerRAppId:
type: string
description: Consumer RAPP ID
- producer_rapp_id:
+ producerRAppId:
type: string
description: Producer RAPP ID
- model_id:
+ modelId:
$ref: '#/definitions/ModelID'
ModelID:
type: object
required:
- - modelname
- - modelversion
+ - modelName
+ - modelVersion
properties:
- modelname:
+ modelName:
type: string
- modelversion:
+ modelVersion:
type: string
- artifactversion:
+ artifactVersion:
type: string
TrainingConfig:
type: object
{
"modelId":{
- "modelname": "modeltest7",
- "modelversion": "1"
+ "modelName": "modeltest7",
+ "modelVersion": "1"
},
- "model_location": "",
- "training_config": {
+ "modelLocation": "",
+ "trainingConfig": {
"description": "trainingjob for testing",
"dataPipeline": {
"feature_group_name": "testing_influxdb_01",
"enable_versioning": false
}
},
- "training_dataset": "",
- "validation_dataset": "",
- "notification_url": "",
- "consumer_rapp_id": "",
- "producer_rapp_id": ""
+ "trainingDataset": "",
+ "validationDataset": "",
+ "notificationDestination": "",
+ "consumerRAppId": "",
+ "producerRAppId": ""
}
### tm: get pipelines
expected_data = {
"title": "Bad Request",
"status": 400,
- "detail": "The 'training_config' field is missing."
+ "detail": "The 'trainingConfig' field is missing."
}
trainingjob_req = {
"modelId": {
- "modelname": "modeltest",
- "modelversion": "1"
+ "modelName": "modeltest",
+ "modelVersion": "1"
}
}
response = self.client.post("/training-jobs", data=json.dumps(trainingjob_req),
expected_data = {
"title": "Bad Request",
"status": 400,
- "detail": "The provided 'training_config' is not valid."
+ "detail": "The provided 'trainingConfig' is not valid."
}
trainingjob_req = {
"modelId": {
- "modelname": "modeltest",
- "modelversion": "1"
+ "modelName": "modeltest",
+ "modelVersion": "1"
},
- "training_config": {
+ "trainingConfig": {
"description": "training job for testing"
}
}
}
trainingjob_req = {
"modelId": {
- "modelname": "test_model",
- "modelversion": "1"
+ "modelName": "test_model",
+ "modelVersion": "1"
},
- "model_location": "",
- "training_config": {
+ "modelLocation": "",
+ "trainingConfig": {
"description": "trainingjob for testing",
"dataPipeline": {
"feature_group_name": "testing_influxdb_03",
}
trainingjob_req = {
"modelId": {
- "modelname": "test_model",
- "modelversion": "1"
+ "modelName": "test_model",
+ "modelVersion": "1"
},
- "model_location": "",
- "training_config": {
+ "modelLocation": "",
+ "trainingConfig": {
"description": "trainingjob for testing",
"dataPipeline": {
"feature_group_name": "testing_influxdb_03",
request_json = request.get_json()
LOGGER.debug(f"Request for training job with JSON: {request_json}")
- if not check_key_in_dictionary(["training_config"], request_json):
- return ProblemDetails(400, "Bad Request", "The 'training_config' field is missing.").to_json()
- request_json['training_config'] = json.dumps(request_json["training_config"])
+ if not check_key_in_dictionary(["trainingConfig"], request_json):
+ return ProblemDetails(400, "Bad Request", "The 'trainingConfig' field is missing.").to_json()
+ request_json['trainingConfig'] = json.dumps(request_json["trainingConfig"])
trainingjob = trainingjob_schema.load(request_json)
- trainingConfig = trainingjob.training_config
- if not validateTrainingConfig(trainingConfig):
- return ProblemDetails(400, "Bad Request", "The provided 'training_config' is not valid.").to_json()
+ training_config = trainingjob.training_config
+ if not validateTrainingConfig(training_config):
+ return ProblemDetails(400, "Bad Request", "The provided 'trainingConfig' is not valid.").to_json()
model_id = trainingjob.modelId
registered_model_list = get_modelinfo_by_modelId_service(model_id.modelname, model_id.modelversion)
if registered_model_list is None:
LOGGER.error(f"Error creating training job: {str(e)}")
return ProblemDetails(500, "Internal Server Error", str(e)).to_json()
-
@training_job_controller.route('/training-jobs/', methods=['GET'])
def get_trainingjobs():
LOGGER.debug(f'Fetching all training jobs')
@pre_load
def processModelId(self, data, **kwargs):
- modelname = data['modelId']['modelname']
- modelversion = data['modelId']['modelversion']
+ modelname = data['modelId']['modelName']
+ modelversion = data['modelId']['modelVersion']
+
+ mapping = {
+ "modelLocation": "model_location",
+ "trainingConfig": "training_config",
+ "trainingDataset": "training_dataset",
+ "validationDataset": "validation_dataset",
+ "notificationDestination": "notification_url",
+ "consumerRAppId": "consumer_rapp_id",
+ "producerRAppId": "producer_rapp_id",
+ }
+ for src, dst in mapping.items():
+ if src in data and dst not in data:
+ data[dst] = data.pop(src)
modeldict = dict(modelname=modelname, modelversion=modelversion)
data['modelId'] = modeldict