diff --git a/CHANGELOG.md b/CHANGELOG.md index 89f69361..ac808f01 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -34,7 +34,7 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) - 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 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`, `POST /_plugins/_ml/models/_undeploy`, `POST /_plugins/_ml/models/_upload`,`POST /_plugins/_ml/models/{model_id}/_load`, and `POST /_plugins/_ml/models/meta` ([#733](https://github.com/opensearch-project/opensearch-api-specification/pull/733)) +- 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`, `POST /_plugins/_ml/models/_undeploy`, `POST /_plugins/_ml/models/_upload`,`POST /_plugins/_ml/models/{model_id}/_load`, `POST /_plugins/_ml/models/meta`, and `POST /_plugins/_ml/models/{model_id}/_predict` ([#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 8cecd7c8..ec8790a6 100644 --- a/spec/namespaces/ml.yaml +++ b/spec/namespaces/ml.yaml @@ -169,6 +169,18 @@ paths: responses: '200': $ref: '#/components/responses/ml.unload_model@200' + /_plugins/_ml/models/{model_id}/_predict: + post: + operationId: ml.predict_model.0 + x-operation-group: ml.predict_model + description: Predicts a model. + parameters: + - $ref: '#/components/parameters/ml.predict_model::path.model_id' + requestBody: + $ref: '#/components/requestBodies/ml.predict_model' + responses: + '200': + $ref: '#/components/responses/ml.predict_model@200' /_plugins/_ml/tasks/{task_id}: get: operationId: ml.get_task.0 @@ -444,6 +456,22 @@ components: $ref: '../schemas/_common.yaml#/components/schemas/Id' required: - model_ids + ml.predict_model: + content: + application/json: + schema: + type: object + properties: + query_text: + type: string + description: The query text. + text_docs: + type: array + items: + type: string + description: The text documents. + required: + - text_docs ml.create_connector: content: application/json: @@ -608,6 +636,11 @@ components: application/json: schema: $ref: '../schemas/ml._common.yaml#/components/schemas/UnloadModelResponse' + ml.predict_model@200: + content: + application/json: + schema: + $ref: '../schemas/ml._common.yaml#/components/schemas/PredictModelResponse' ml.delete_model@200: content: application/json: @@ -719,6 +752,12 @@ components: required: true schema: type: string + ml.predict_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 de1b7449..faa0da0c 100644 --- a/spec/schemas/ml._common.yaml +++ b/spec/schemas/ml._common.yaml @@ -439,6 +439,68 @@ components: UnloadModelNodeStats: type: object additionalProperties: true + PredictModelResponse: + type: object + properties: + inference_results: + type: array + items: + $ref: '#/components/schemas/PredictModelResult' + PredictModelResult: + type: object + properties: + output: + type: array + items: + $ref: '#/components/schemas/PredictModelOutput' + PredictModelOutput: + type: object + properties: + name: + type: string + description: The output name. + data_type: + type: string + description: The output data type. + enum: + - BOOLEAN + - FLOAT16 + - FLOAT32 + - FLOAT64 + - INT32 + - INT64 + - INT8 + - STRING + - UINT8 + - UNKNOWN + shape: + type: array + items: + type: integer + format: int64 + description: The output shape. + data: + type: array + items: + type: number + format: double + description: The output data. + byte_buffer: + $ref: '#/components/schemas/ByteBuffer' + required: + - data + ByteBuffer: + type: object + properties: + array: + type: string + description: The byte buffer array. + order: + type: string + description: The byte buffer order. + enum: + - BIG_ENDIAN + - LITTLE_ENDIAN Credential: type: object properties: diff --git a/tests/plugins/ml/models/metadata.yaml b/tests/plugins/ml/models/metadata.yaml index 49062cf6..2b875306 100644 --- a/tests/plugins/ml/models/metadata.yaml +++ b/tests/plugins/ml/models/metadata.yaml @@ -9,6 +9,12 @@ version: '>= 2.11' warnings: multiple-paths-detected: false prologues: + - path: /_cluster/settings + method: PUT + request: + payload: + persistent: + plugins.ml_commons.allow_registering_model_via_local_file: true - path: /_plugins/_ml/models/_register id: register_model method: POST diff --git a/tests/plugins/ml/models/predict.yaml b/tests/plugins/ml/models/predict.yaml new file mode 100644 index 00000000..d42080f7 --- /dev/null +++ b/tests/plugins/ml/models/predict.yaml @@ -0,0 +1,124 @@ +$schema: ../../../../json_schemas/test_story.schema.yaml + +description: Test the prediction of new data. +distributions: + excluded: + - amazon-managed + - amazon-serverless +warnings: + multiple-paths-detected: false +prologues: + - path: /_cluster/settings + method: PUT + request: + payload: + persistent: + plugins.ml_commons.only_run_on_ml_node: false + plugins.ml_commons.model_access_control_enabled: true + plugins.ml_commons.native_memory_threshold: 99 + - path: /_plugins/_ml/model_groups/_register + id: create_model_group + method: POST + request: + payload: + name: NLP_Group + description: Model group for NLP models. + output: + test_model_group_id: payload.model_group_id + - 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}/_undeploy + method: POST + parameters: + model_id: ${get_completed_register_model_task.model_id} + status: [200, 404] + - path: /_plugins/_ml/models/{model_id} + parameters: + model_id: ${get_completed_register_model_task.model_id} + method: DELETE + status: [200, 404] + - path: /_plugins/_ml/model_groups/{model_group_id} + method: DELETE + status: [200, 404] + parameters: + model_group_id: ${create_model_group.test_model_group_id} +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: Predict new data. + id: predict_data + path: /_plugins/_ml/models/{model_id}/_predict + method: POST + parameters: + model_id: ${get_completed_register_model_task.model_id} + request: + payload: + query_text: today is sunny + text_docs: + - how are you + - it is winter + - today is july fifth + - today is sunny + response: + status: 200 + payload: + inference_results: + - output: + - data: + - 101 + output: + prediction_results: payload.inference_results[0].output[0].data + - synopsis: Undeploy a model. + path: /_plugins/_ml/models/{model_id}/_undeploy + method: POST + parameters: + model_id: ${get_completed_register_model_task.model_id} + response: + status: 200 \ No newline at end of file