diff --git a/CHANGELOG.md b/CHANGELOG.md index eda2b041..c45eb1ac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -41,6 +41,7 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) - Added 404 response to `/_search/scroll` ([#749](https://github.com/opensearch-project/opensearch-api-specification/pull/749)) - Added `node_failures` to `DELETE /_search/scroll` and `DELETE /_search/scroll/{scroll_id}` ([#749](https://github.com/opensearch-project/opensearch-api-specification/pull/749)) - Added `POST /_plugins/_ml/_train/{algorithm_name}`, `_predict/{algorithm_name}/{model_id}`, and `_train_predict/{algorithm_name}` ([#755](https://github.com/opensearch-project/opensearch-api-specification/pull/755)) +- Added `PUT /_plugins/_ml/model_groups/{model_group_id}`, `GET /_plugins/_ml/model_groups/_search`, and `POST /_plugins/_ml/model_groups/_search` ([#760](https://github.com/opensearch-project/opensearch-api-specification/pull/760)) ### 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 25ec908b..53c47a6e 100644 --- a/spec/namespaces/ml.yaml +++ b/spec/namespaces/ml.yaml @@ -24,6 +24,18 @@ paths: responses: '200': $ref: '#/components/responses/ml.get_model_group@200' + put: + operationId: ml.update_model_group.0 + x-operation-group: ml.update_model_group + x-version-added: '2.9' + description: Updates a model group. + parameters: + - $ref: '#/components/parameters/ml.update_model_group::path.model_group_id' + requestBody: + $ref: '#/components/requestBodies/ml.update_model_group' + responses: + '200': + $ref: '#/components/responses/ml.update_model_group@200' delete: operationId: ml.delete_model_group.0 x-operation-group: ml.delete_model_group @@ -33,6 +45,27 @@ paths: responses: '200': $ref: '#/components/responses/ml.delete_model_group@200' + /_plugins/_ml/model_groups/_search: + get: + operationId: ml.search_model_group.0 + x-operation-group: ml.search_model_group + x-version-added: '2.9' + description: Searches for model groups. + requestBody: + $ref: '#/components/requestBodies/ml.search_model_group' + responses: + '200': + $ref: '#/components/responses/ml.search_model_group@200' + post: + operationId: ml.search_model_group.1 + x-operation-group: ml.search_model_group + x-version-added: '2.9' + description: Searches for model groups. + requestBody: + $ref: '#/components/requestBodies/ml.search_model_group' + responses: + '200': + $ref: '#/components/responses/ml.search_model_group@200' /_plugins/_ml/models/_register: post: operationId: ml.register_model.0 @@ -207,6 +240,51 @@ components: description: The add all backend roles. required: - name + ml.update_model_group: + content: + application/json: + schema: + type: object + properties: + name: + type: string + description: The model group name. + description: + type: string + description: The model group description. + add_all_backend_roles: + type: boolean + description: Whether to include all backend roles. + model_access_name: + type: string + description: The model access name + backend_roles: + type: array + items: + type: string + description: The backend roles. + add_backend_roles: + type: array + items: + type: string + description: The backend roles to add. + ml.search_model_group: + content: + application/json: + schema: + type: object + properties: + query: + $ref: '../schemas/ml._common.yaml#/components/schemas/Query' + size: + type: integer + format: int64 + description: The number of model groups to return. + sort: + type: array + items: + $ref: '../schemas/ml._common.yaml#/components/schemas/Sort' + description: The sort order. ml.register_model: content: application/json: @@ -241,14 +319,16 @@ components: properties: query: type: object - # TODO: Define the query schema - description: The query. + $ref: '../schemas/ml._common.yaml#/components/schemas/Query' size: type: integer + format: int64 description: The number of models to return. - required: - - query - - size + sort: + type: array + items: + $ref: '../schemas/ml._common.yaml#/components/schemas/Sort' + description: The sort order. ml.predict: content: application/json: @@ -377,6 +457,16 @@ components: application/json: schema: $ref: '../schemas/ml._common.yaml#/components/schemas/ModelGroup' + ml.update_model_group@200: + content: + application/json: + schema: + $ref: '../schemas/ml._common.yaml#/components/schemas/UpdateModelGroupResponse' + ml.search_model_group@200: + content: + application/json: + schema: + $ref: '../schemas/ml._common.yaml#/components/schemas/SearchModelGroupsResponse' ml.delete_model_group@200: content: application/json: @@ -483,6 +573,12 @@ components: required: true schema: type: string + ml.update_model_group::path.model_group_id: + name: model_group_id + in: path + required: true + schema: + type: string ml.delete_model_group::path.model_group_id: name: model_group_id in: path diff --git a/spec/schemas/ml._common.yaml b/spec/schemas/ml._common.yaml index 0c482a35..f140881c 100644 --- a/spec/schemas/ml._common.yaml +++ b/spec/schemas/ml._common.yaml @@ -7,6 +7,8 @@ paths: {} components: schemas: SearchModelsResponse: + $ref: '#/components/schemas/SearchResponse' + SearchResponse: type: object properties: took: @@ -18,10 +20,10 @@ components: _shards: $ref: '_common.yaml#/components/schemas/ShardStatistics' hits: - $ref: '#/components/schemas/SearchModelsHits' + $ref: '#/components/schemas/SearchHits' required: - hits - SearchModelsHits: + SearchHits: type: object properties: total: @@ -29,7 +31,7 @@ components: hits: type: array items: - $ref: '#/components/schemas/SearchModelsHitsHit' + $ref: '#/components/schemas/SearchHitsHit' max_score: type: number format: float @@ -50,7 +52,7 @@ components: required: - relation - value - SearchModelsHitsHit: + SearchHitsHit: type: object properties: _version: @@ -115,6 +117,7 @@ components: - PARTIALLY_DEPLOYED - REGISTERED - REGISTERING + - UNDEPLOYED model_content_size_in_bytes: type: integer format: int64 @@ -171,6 +174,23 @@ components: url: type: string description: The model URL. + backend_roles: + type: array + items: + type: string + description: The backend roles. + owner: + $ref: '#/components/schemas/Owner' + access: + type: string + description: The model group access. + enum: + - private + - public + - restricted + latest_version: + type: integer + description: The latest version. ModelConfig: type: object properties: @@ -329,6 +349,14 @@ components: properties: bool: $ref: '#/components/schemas/BoolQuery' + match_all: + $ref: '#/components/schemas/MatchAllQuery' + term: + $ref: '#/components/schemas/Term' + MatchAllQuery: + type: object + description: The match all query. + properties: {} BoolQuery: type: object description: The Boolean query. @@ -338,12 +366,35 @@ components: description: Filter query that appears in matching documents. items: $ref: '#/components/schemas/Filter' + must: + type: array + description: Query that must appears in matching documents + items: + $ref: '#/components/schemas/Filter' + must_not: + description: Query that must not appears in matching documents. + $ref: '#/components/schemas/Filter' + should: + type: array + description: Query that should appear in matching documents. + items: + $ref: '#/components/schemas/Filter' Filter: type: object description: The filter element. properties: range: $ref: '#/components/schemas/Range' + nested: + $ref: '#/components/schemas/Nested' + exists: + $ref: '#/components/schemas/Exists' + term: + $ref: '#/components/schemas/Term' + terms: + $ref: '#/components/schemas/Term' + match: + $ref: '#/components/schemas/Match' Range: type: object description: The filter range. @@ -370,6 +421,150 @@ components: lt: type: number description: Less than. + Term: + type: object + description: Term to match the query. + properties: + algorithm: + $ref: '#/components/schemas/Algorithm' + _id: + type: array + items: + $ref: '_common.yaml#/components/schemas/Id' + model_id: + $ref: '_common.yaml#/components/schemas/Name' + owner.name.keyword: + $ref: '#/components/schemas/OwnerNameKeyword' + Algorithm: + type: object + description: The algorithm. + properties: + value: + type: string + description: The function name. + enum: + - AD_LIBSVM + - AGENT + - ANOMALY_LOCALIZATION + - BATCH_RCF + - CONNECTOR + - FIT_RCF + - KMEANS + - LINEAR_REGRESSION + - LOCAL_SAMPLE_CALCULATOR + - LOGISTIC_REGRESSION + - METRICS_CORRELATION + - QUESTION_ANSWERING + - RCF_SUMMARIZE + - REMOTE + - SAMPLE_ALGO + - SPARSE_ENCODING + - SPARSE_TOKENIZE + - TEXT_EMBEDDING + - TEXT_SIMILARITY + OwnerNameKeyword: + type: object + description: The owner name keyword. + properties: + value: + $ref: '_common.yaml#/components/schemas/FieldValue' + boost: + type: number + description: Adjust the relevance score of a match. + Nested: + type: object + description: The nested filter. + properties: + query: + $ref: '#/components/schemas/Query' + path: + $ref: '_common.yaml#/components/schemas/Field' + ignore_unmapped: + type: boolean + description: Whether to ignore unmapped fields. + score_mode: + type: string + description: The score mode. + enum: + - avg + - max + - min + - none + - sum + boost: + type: number + description: Adjust the relevance score of a match. + Exists: + type: object + description: The exists filter. + properties: + field: + $ref: '_common.yaml#/components/schemas/Field' + Sort: + type: object + description: Sort query. + properties: + algorithm: + $ref: '#/components/schemas/SortOrder' + auto_redeploy_retry_times: + $ref: '#/components/schemas/SortOrder' + chunk_number: + $ref: '#/components/schemas/SortOrder' + created_time: + $ref: '#/components/schemas/SortOrder' + current_worker_node_count: + $ref: '#/components/schemas/SortOrder' + deploy_to_all_nodes: + $ref: '#/components/schemas/SortOrder' + is_hidden: + $ref: '#/components/schemas/SortOrder' + last_registered_time: + $ref: '#/components/schemas/SortOrder' + last_updated_time: + $ref: '#/components/schemas/SortOrder' + model_content_hash_value: + $ref: '#/components/schemas/SortOrder' + model_content_size_in_bytes: + $ref: '#/components/schemas/SortOrder' + model_format: + $ref: '#/components/schemas/SortOrder' + model_group_id: + $ref: '#/components/schemas/SortOrder' + model_state: + $ref: '#/components/schemas/SortOrder' + model_version: + $ref: '#/components/schemas/SortOrder' + planning_worker_nodes: + $ref: '#/components/schemas/SortOrder' + planning_worker_node_count: + $ref: '#/components/schemas/SortOrder' + total_chunks: + $ref: '#/components/schemas/SortOrder' + _index: + $ref: '#/components/schemas/SortOrder' + _id: + $ref: '#/components/schemas/SortOrder' + _seq_no: + $ref: '#/components/schemas/SortOrder' + _score: + $ref: '#/components/schemas/SortOrder' + SortOrder: + type: object + description: The order of the sort. + properties: + order: + type: string + description: The order. + enum: + - asc + - desc + Match: + type: object + description: Match query. + properties: + description: + type: string + description: The description. TrainParameters: type: object properties: @@ -430,9 +625,15 @@ components: description: type: string description: The model group description. + owner: + $ref: '#/components/schemas/Owner' access: type: string description: The model group access. + enum: + - private + - public + - restricted created_time: type: integer format: int64 @@ -444,6 +645,39 @@ components: - description - latest_version - name + Owner: + type: object + properties: + name: + $ref: '_common.yaml#/components/schemas/Name' + backend_roles: + type: array + items: + type: string + description: The backend roles. + roles: + type: array + items: + type: string + description: The roles. + custom_attribute_names: + type: array + items: + type: string + description: The custom attribute names. + user_requested_tenant: + type: ['null', string] + description: The user requested tenant. + required: + - name + UpdateModelGroupResponse: + type: object + properties: + status: + type: string + description: The status. + SearchModelGroupsResponse: + $ref: '#/components/schemas/SearchResponse' Task: type: object properties: diff --git a/tests/plugins/ml/ml/model_groups/search.yaml b/tests/plugins/ml/ml/model_groups/search.yaml new file mode 100644 index 00000000..717b87a7 --- /dev/null +++ b/tests/plugins/ml/ml/model_groups/search.yaml @@ -0,0 +1,52 @@ +$schema: ../../../../../json_schemas/test_story.schema.yaml + +description: Test the search of model groups. +version: '>= 2.9' +prologues: + - 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 +epilogues: + - 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: Search model group. + path: /_plugins/_ml/model_groups/_search + method: GET + request: + payload: + query: + match_all: {} + size: 1000 + response: + status: 200 + payload: + hits: + hits: + - _score: 1 + - synopsis: Search model group with a model group ID. + path: /_plugins/_ml/model_groups/_search + method: POST + request: + payload: + query: + bool: + must: + - terms: + _id: + - ${create_model_group.test_model_group_id} + response: + status: 200 + payload: + hits: + hits: + - _score: 1 diff --git a/tests/plugins/ml/ml/model_groups/update.yaml b/tests/plugins/ml/ml/model_groups/update.yaml new file mode 100644 index 00000000..e9ef14a3 --- /dev/null +++ b/tests/plugins/ml/ml/model_groups/update.yaml @@ -0,0 +1,36 @@ +$schema: ../../../../../json_schemas/test_story.schema.yaml + +description: Test the creation of model groups. +version: '>= 2.9' +prologues: + - 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/model_groups/{model_group_id} + method: GET + parameters: + model_group_id: ${create_model_group.test_model_group_id} + status: [200, 404] +epilogues: + - 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: Update model group. + path: /_plugins/_ml/model_groups/{model_group_id} + method: PUT + parameters: + model_group_id: ${create_model_group.test_model_group_id} + request: + payload: + description: This is the updated description. + response: + status: 200