From 0cc17c248926733d91fdaf0f8b16f6a3e27f8ab1 Mon Sep 17 00:00:00 2001 From: Nathalie Jonathan Date: Mon, 16 Dec 2024 17:45:38 -0800 Subject: [PATCH] Added ML Model APIs (undeploy, unload), moved test for search model to models/search.yaml, resolved conflicts and updated CHANGELOG Signed-off-by: Nathalie Jonathan --- CHANGELOG.md | 3 +- spec/namespaces/ml.yaml | 80 ++++++++++++++++++- spec/schemas/ml._common.yaml | 15 ++++ tests/plugins/ml/ml/models.yaml | 16 +--- tests/plugins/ml/models/search.yaml | 34 ++++++++ .../ml/models/undeploy_specific_models.yaml | 77 ++++++++++++++++++ tests/plugins/ml/models/unload.yaml | 74 +++++++++++++++++ .../ml/models/unload_specific_models.yaml | 76 ++++++++++++++++++ 8 files changed, 357 insertions(+), 18 deletions(-) create mode 100644 tests/plugins/ml/models/search.yaml create mode 100644 tests/plugins/ml/models/undeploy_specific_models.yaml create mode 100644 tests/plugins/ml/models/unload.yaml create mode 100644 tests/plugins/ml/models/unload_specific_models.yaml diff --git a/CHANGELOG.md b/CHANGELOG.md index be50b800..4df039f3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -33,7 +33,8 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) - Added response schema for `PUT` and `DELETE /_plugins/_transform/{id}` ([#722](https://github.com/opensearch-project/opensearch-api-specification/pull/716)) - Added response schema for `GET /_plugins/_knn/warmup/{index}` ([#717](https://github.com/opensearch-project/opensearch-api-specification/pull/717)) - Added support for multiple test verbs ([#724](https://github.com/opensearch-project/opensearch-api-specification/pull/724)) -- Added ML Model APIs `GET /_plugins/_ml/models/{}`, `POST /_plugins/_ml/models/_search`, and `PUT /_plugins/_ml/models/{}` to the spec along with the tests. +- Added support for using a certificate and key in tests ([#731](https://github.com/opensearch-project/opensearch-api-specification/pull/731)) +- Added `GET /_plugins/_ml/models/{model_id}`, `POST /_plugins/_ml/models/_search`, `PUT /_plugins/_ml/models/{model_id}`, `POST /_plugins/_ml/models/{model_id}/_unload`, `POST /_plugins/_ml/models/_unload`, and `POST /_plugins/_ml/models/_undeploy` ([#733](https://github.com/opensearch-project/opensearch-api-specification/pull/733)) ### Removed - Removed unsupported `_common.mapping:SourceField`'s `mode` field and associated `_common.mapping:SourceFieldMode` enum ([#652](https://github.com/opensearch-project/opensearch-api-specification/pull/652)) diff --git a/spec/namespaces/ml.yaml b/spec/namespaces/ml.yaml index 1148c496..aa576e78 100644 --- a/spec/namespaces/ml.yaml +++ b/spec/namespaces/ml.yaml @@ -93,6 +93,40 @@ paths: responses: '200': $ref: '#/components/responses/ml.undeploy_model@200' + /_plugins/_ml/models/_undeploy: + post: + operationId: ml.undeploy_model.1 + x-operation-group: ml.undeploy_model + description: Undeploys a model. + requestBody: + $ref: '#/components/requestBodies/ml.undeploy_model' + responses: + '200': + $ref: '#/components/responses/ml.undeploy_model@200' + /_plugins/_ml/models/{model_id}/_unload: + post: + operationId: ml.unload_model.0 + x-operation-group: ml.unload_model + deprecated: true + x-version-deprecated: 2.7.0 + x-deprecation-message: Use `undeploy_model` instead. + parameters: + - $ref: '#/components/parameters/ml.unload_model::path.model_id' + responses: + '200': + $ref: '#/components/responses/ml.unload_model@200' + /_plugins/_ml/models/_unload: + post: + operationId: ml.unload_model.1 + x-operation-group: ml.unload_model + deprecated: true + x-version-deprecated: 2.7.0 + x-deprecation-message: Use `undeploy_model` instead. + requestBody: + $ref: '#/components/requestBodies/ml.unload_model' + responses: + '200': + $ref: '#/components/responses/ml.unload_model@200' /_plugins/_ml/tasks/{task_id}: get: operationId: ml.get_task.0 @@ -123,7 +157,7 @@ paths: '200': $ref: '#/components/responses/ml.search_models@200' post: - operationId: ml.search_models.0 + operationId: ml.search_models.1 x-operation-group: ml.search_models description: Searches for models. requestBody: @@ -222,7 +256,6 @@ components: type: string description: The ID of the model group to which to register the model. required: - - model_format - name - version ml.search_models: @@ -271,6 +304,38 @@ components: interface: type: object description: The model interface. + ml.undeploy_model: + content: + application/json: + schema: + type: object + properties: + node_ids: + type: array + items: + $ref: '_common.yaml#/components/schemas/Id' + model_ids: + type: array + items: + $ref: '_common.yaml#/components/schemas/Id' + required: + - model_ids + ml.unload_model: + content: + application/json: + schema: + type: object + properties: + node_ids: + type: array + items: + $ref: '_common.yaml#/components/schemas/Id' + model_ids: + type: array + items: + $ref: '_common.yaml#/components/schemas/Id' + required: + - model_ids ml.create_connector: content: application/json: @@ -379,6 +444,11 @@ components: application/json: schema: $ref: '../schemas/ml._common.yaml#/components/schemas/UndeployModelResponse' + ml.unload_model@200: + content: + application/json: + schema: + $ref: '../schemas/ml._common.yaml#/components/schemas/UnloadModelResponse' ml.delete_model@200: content: application/json: @@ -478,6 +548,12 @@ components: required: true schema: type: string + ml.unload_model::path.model_id: + name: model_id + in: path + required: true + schema: + type: string ml.delete_task::path.task_id: name: task_id in: path diff --git a/spec/schemas/ml._common.yaml b/spec/schemas/ml._common.yaml index 3f1ac996..de1b7449 100644 --- a/spec/schemas/ml._common.yaml +++ b/spec/schemas/ml._common.yaml @@ -115,6 +115,7 @@ components: - PARTIALLY_DEPLOYED - REGISTERED - REGISTERING + - UNDEPLOYED model_content_size_in_bytes: type: integer format: int64 @@ -256,6 +257,7 @@ components: - PARTIALLY_DEPLOYED - REGISTERED - REGISTERING + - UNDEPLOYED model_content_size_in_bytes: type: integer format: int64 @@ -424,6 +426,19 @@ components: UndeployModelNodeStats: type: object additionalProperties: true + UnloadModelResponse: + type: object + additionalProperties: + title: nodes + $ref: '#/components/schemas/UnloadModelNode' + UnloadModelNode: + type: object + properties: + stats: + $ref: '#/components/schemas/UnloadModelNodeStats' + UnloadModelNodeStats: + type: object + additionalProperties: true Credential: type: object properties: diff --git a/tests/plugins/ml/ml/models.yaml b/tests/plugins/ml/ml/models.yaml index 9d2b539e..7258c5d0 100644 --- a/tests/plugins/ml/ml/models.yaml +++ b/tests/plugins/ml/ml/models.yaml @@ -51,20 +51,6 @@ chapters: hits: hits: - _score: 1 - - synopsis: Search model. - path: /_plugins/_ml/models/_search - method: POST - request: - payload: - query: - match_all: {} - size: 1000 - response: - status: 200 - payload: - hits: - hits: - - _score: 1 - synopsis: Get model. path: /_plugins/_ml/models/{model_id} method: GET @@ -79,7 +65,7 @@ chapters: model_id: ${get_completed_task.model_id} request: payload: - name: updated_name + name: updated response: status: 200 - synopsis: Delete model. diff --git a/tests/plugins/ml/models/search.yaml b/tests/plugins/ml/models/search.yaml new file mode 100644 index 00000000..98d79fa5 --- /dev/null +++ b/tests/plugins/ml/models/search.yaml @@ -0,0 +1,34 @@ +$schema: ../../../../json_schemas/test_story.schema.yaml + +description: Test the search of models. +distributions: + excluded: + - amazon-managed + - amazon-serverless +version: '>= 2.11' +prologues: + - path: /_plugins/_ml/models/_register + id: register_model + method: POST + request: + payload: + name: huggingface/sentence-transformers/msmarco-distilbert-base-tas-b + version: 1.0.1 + model_format: TORCH_SCRIPT + output: + task_id: payload.task_id +chapters: + - synopsis: Search model. + path: /_plugins/_ml/models/_search + method: POST + request: + payload: + query: + match_all: {} + size: 1000 + response: + status: 200 + payload: + hits: + hits: + - _score: 1 \ No newline at end of file diff --git a/tests/plugins/ml/models/undeploy_specific_models.yaml b/tests/plugins/ml/models/undeploy_specific_models.yaml new file mode 100644 index 00000000..77d43fe6 --- /dev/null +++ b/tests/plugins/ml/models/undeploy_specific_models.yaml @@ -0,0 +1,77 @@ +$schema: ../../../../json_schemas/test_story.schema.yaml + +description: Test the undeployment of specific models from specific nodes. +distributions: + excluded: + - amazon-managed + - amazon-serverless +version: '>= 2.11' +warnings: + multiple-paths-detected: false +prologues: + - path: /_plugins/_ml/models/_register + id: register_model + method: POST + request: + payload: + name: huggingface/sentence-transformers/msmarco-distilbert-base-tas-b + version: 1.0.1 + model_format: TORCH_SCRIPT + output: + task_id: payload.task_id +epilogues: + - path: /_plugins/_ml/models/{model_id} + parameters: + model_id: ${get_completed_register_model_task.model_id} + method: DELETE + status: [200, 404] +chapters: + - synopsis: Wait to get completed task. + id: get_completed_register_model_task + path: /_plugins/_ml/tasks/{task_id} + method: GET + parameters: + task_id: ${register_model.task_id} + response: + status: 200 + payload: + state: COMPLETED + output: + model_id: payload.model_id + retry: + count: 3 + wait: 10000 + - synopsis: Deploy a model. + id: deploy_model + path: /_plugins/_ml/models/{model_id}/_deploy + method: POST + parameters: + model_id: ${get_completed_register_model_task.model_id} + output: + task_id: payload.task_id + response: + status: 200 + - synopsis: Wait to get completed task. + id: get_completed_deploy_model_task + path: /_plugins/_ml/tasks/{task_id} + method: GET + parameters: + task_id: ${deploy_model.task_id} + response: + status: 200 + payload: + state: COMPLETED + output: + model_id: payload.model_id + retry: + count: 3 + wait: 10000 + - synopsis: Undeploy a model. + path: /_plugins/_ml/models/_undeploy + method: POST + request: + payload: + model_ids: + - ${get_completed_register_model_task.model_id} + response: + status: 200 diff --git a/tests/plugins/ml/models/unload.yaml b/tests/plugins/ml/models/unload.yaml new file mode 100644 index 00000000..4e6d6bcc --- /dev/null +++ b/tests/plugins/ml/models/unload.yaml @@ -0,0 +1,74 @@ +$schema: ../../../../json_schemas/test_story.schema.yaml + +description: Test the unload (deprecated) of a model from all ML nodes. +distributions: + excluded: + - amazon-managed + - amazon-serverless +warnings: + multiple-paths-detected: false +prologues: + - path: /_plugins/_ml/models/_register + id: register_model + method: POST + request: + payload: + name: huggingface/sentence-transformers/msmarco-distilbert-base-tas-b + version: 1.0.1 + model_format: TORCH_SCRIPT + output: + task_id: payload.task_id +epilogues: + - path: /_plugins/_ml/models/{model_id} + parameters: + model_id: ${get_completed_register_model_task.model_id} + method: DELETE + status: [200, 404] +chapters: + - synopsis: Wait to get completed task. + id: get_completed_register_model_task + path: /_plugins/_ml/tasks/{task_id} + method: GET + parameters: + task_id: ${register_model.task_id} + response: + status: 200 + payload: + state: COMPLETED + output: + model_id: payload.model_id + retry: + count: 3 + wait: 10000 + - synopsis: Deploy a model. + id: deploy_model + path: /_plugins/_ml/models/{model_id}/_deploy + method: POST + parameters: + model_id: ${get_completed_register_model_task.model_id} + output: + task_id: payload.task_id + response: + status: 200 + - synopsis: Wait to get completed task. + id: get_completed_deploy_model_task + path: /_plugins/_ml/tasks/{task_id} + method: GET + parameters: + task_id: ${deploy_model.task_id} + response: + status: 200 + payload: + state: COMPLETED + output: + model_id: payload.model_id + retry: + count: 3 + wait: 10000 + - synopsis: Unload a model. + path: /_plugins/_ml/models/{model_id}/_unload + method: POST + parameters: + model_id: ${get_completed_register_model_task.model_id} + response: + status: 200 \ No newline at end of file diff --git a/tests/plugins/ml/models/unload_specific_models.yaml b/tests/plugins/ml/models/unload_specific_models.yaml new file mode 100644 index 00000000..81bae92b --- /dev/null +++ b/tests/plugins/ml/models/unload_specific_models.yaml @@ -0,0 +1,76 @@ +$schema: ../../../../json_schemas/test_story.schema.yaml + +description: Test the unload (deprecated) of specific models from specific nodes. +distributions: + excluded: + - amazon-managed + - amazon-serverless +warnings: + multiple-paths-detected: false +prologues: + - path: /_plugins/_ml/models/_register + id: register_model + method: POST + request: + payload: + name: huggingface/sentence-transformers/msmarco-distilbert-base-tas-b + version: 1.0.1 + model_format: TORCH_SCRIPT + output: + task_id: payload.task_id +epilogues: + - path: /_plugins/_ml/models/{model_id} + parameters: + model_id: ${get_completed_register_model_task.model_id} + method: DELETE + status: [200, 404] +chapters: + - synopsis: Wait to get completed task. + id: get_completed_register_model_task + path: /_plugins/_ml/tasks/{task_id} + method: GET + parameters: + task_id: ${register_model.task_id} + response: + status: 200 + payload: + state: COMPLETED + output: + model_id: payload.model_id + retry: + count: 3 + wait: 10000 + - synopsis: Deploy a model. + id: deploy_model + path: /_plugins/_ml/models/{model_id}/_deploy + method: POST + parameters: + model_id: ${get_completed_register_model_task.model_id} + output: + task_id: payload.task_id + response: + status: 200 + - synopsis: Wait to get completed task. + id: get_completed_deploy_model_task + path: /_plugins/_ml/tasks/{task_id} + method: GET + parameters: + task_id: ${deploy_model.task_id} + response: + status: 200 + payload: + state: COMPLETED + output: + model_id: payload.model_id + retry: + count: 3 + wait: 10000 + - synopsis: Unload a model. + path: /_plugins/_ml/models/_unload + method: POST + request: + payload: + model_ids: + - ${get_completed_register_model_task.model_id} + response: + status: 200