diff --git a/CHANGELOG.md b/CHANGELOG.md index e60688b27..1dcbf5597 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,8 +8,9 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) - Added class docs generator ([#96](https://github.com/opensearch-project/opensearch-php/pull/96)) - Added support for Amazon OpenSearch Serverless SigV4 signing ([#119](https://github.com/opensearch-project/opensearch-php/pull/119)) - Added `includePortInHostHeader` option to `ClientBuilder::fromConfig` ([#118](https://github.com/opensearch-project/opensearch-php/pull/118)) -- Added the `RefreshSearchAnalyzers` endpoint ([[#152](https://github.com/opensearch-project/opensearch-php/issues/152)) +- Added the `RefreshSearchAnalyzers` endpoint ([[#152](https://github.com/opensearch-project/opensearch-php/issues/152)) - Added support for `format` parameter to specify the sql response format ([#161](https://github.com/opensearch-project/opensearch-php/pull/161)) +- Added ml commons model, model group and connector APIs ([#170](https://github.com/opensearch-project/opensearch-php/pull/170)) ### Changed @@ -30,4 +31,4 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) ### Security -[Unreleased]: https://github.com/opensearch-project/opensearch-php/compare/2.0...HEAD \ No newline at end of file +[Unreleased]: https://github.com/opensearch-project/opensearch-php/compare/2.0...HEAD diff --git a/USER_GUIDE.md b/USER_GUIDE.md index 4bdbfc993..b43e9a7cf 100644 --- a/USER_GUIDE.md +++ b/USER_GUIDE.md @@ -24,7 +24,7 @@ class MyOpenSearchClass public function __construct() { - //simple Setup + // Simple Setup $this->client = OpenSearch\ClientBuilder::fromConfig([ 'hosts' => [ 'https://localhost:9200' @@ -66,7 +66,7 @@ class MyOpenSearchClass var_dump($this->client->info()); } - // Create a document + // Create a document public function create() { $time = time(); @@ -259,7 +259,7 @@ class MyOpenSearchClass ]); var_dump($docs['hits']['total']['value'] > 0); } - + public function searchByPointInTime() { $result = $this->client->createPointInTime([ @@ -267,7 +267,7 @@ class MyOpenSearchClass 'keep_alive' => '10m' ]); $pitId = $result['pit_id']; - + // Get first page of results in Point-in-Time $result = $this->client->search([ 'body' => [ @@ -283,7 +283,7 @@ class MyOpenSearchClass ] ]); var_dump($result['hits']['total']['value'] > 0); - + $last = end($result['hits']['hits']); $lastSort = $last['sort'] ?? null; @@ -303,7 +303,7 @@ class MyOpenSearchClass ] ]); var_dump($result['hits']['total']['value'] > 0); - + // Close Point-in-Time $result = $this->client->deletePointInTime([ 'body' => [ @@ -405,15 +405,15 @@ $client = (new \OpenSearch\ClientBuilder()) ->setSigV4Region('us-east-2') ->setSigV4Service('es') - + // Default credential provider. ->setSigV4CredentialProvider(true) - + ->setSigV4CredentialProvider([ 'key' => 'awskeyid', 'secret' => 'awssecretkey', ]) - + ->build(); ``` @@ -426,15 +426,15 @@ $client = (new \OpenSearch\ClientBuilder()) ->setSigV4Region('us-east-2') ->setSigV4Service('aoss') - + // Default credential provider. ->setSigV4CredentialProvider(true) - + ->setSigV4CredentialProvider([ 'key' => 'awskeyid', 'secret' => 'awssecretkey', ]) - + ->build(); ``` @@ -481,7 +481,7 @@ $client = (new \OpenSearch\ClientBuilder()) ## Disabling Port Modification To prevent port modifications, include the `includePortInHostHeader` option into `ClientBuilder::fromConfig`. -This will ensure that the port from the supplied URL is unchanged. +This will ensure that the port from the supplied URL is unchanged. The following example will force port `9100` usage. @@ -501,3 +501,7 @@ $client = \OpenSearch\ClientBuilder::fromConfig($config); ... ``` + +## Advanced Features + +* [ML Commons](guides/ml-commons.md) diff --git a/guides/ml-commons.md b/guides/ml-commons.md new file mode 100644 index 000000000..ed3cb4891 --- /dev/null +++ b/guides/ml-commons.md @@ -0,0 +1,71 @@ +# Machine Learning Example Usage + +Walks through the process of setting up a model to generate +vector embeddings from OpenAI on AWS managed Opensearch. + +### Prerequisites + +* This example assumes you are using the AWS managed OpenSearch + service. See [The ml commons documentation](https://github.com/opensearch-project/ml-commons/blob/main/docs/remote_inference_blueprints/openai_connector_embedding_blueprint.md) for more examples and further information. +* You will need an API key from OpenAI. [Sign up](https://platform.openai.com/signup) +* The API key must be stored in [AWS Secrets Manager](https://aws.amazon.com/secrets-manager/) + +```php +ml()->registerModelGroup([ + 'body' => [ + 'name' => 'openai_model_group', + 'description' => 'Group containing models for OpenAI', + ], +]); + +# Create the connector. +$connectorResponse = $client->ml()->createConnector([ + 'body' => [ + 'name' => "Open AI Embedding Connector", + 'description' => "Creates a connector to Open AI's embedding endpoint", + 'version' => 1, + 'protocol' => 'http', + 'parameters' => ['model' => 'text-embedding-ada-002'], + 'credential' => [ + "secretArn" => '', + "roleArn" => '', + ] + 'actions' => [ + [ + 'action_type' => 'predict', + 'method' => 'POST', + 'url' => 'https://api.openai.com/v1/embeddings', + 'headers' => [ + 'Authorization': 'Bearer ${credential.secretArn.}' + ], + 'request_body' => "{ \"input\": \${parameters.input}, \"model\": \"\${parameters.model}\" }", + 'pre_process_function' => "connector.pre_process.openai.embedding", + 'post_process_function' => "connector.post_process.openai.embedding", + ], + ], + ], +]); + +# Register the model. +$registerModelResponse = $client->ml()->registerModel([ + 'body' => [ + 'name' => 'OpenAI embedding model', + 'function_name' => 'remote', + 'model_group_id' => $modelGroupResponse['model_group_id'], + 'description' => 'Model for retrieving vector embeddings from OpenAI', + 'connector_id' => $connectorResponse['connector_id'], + ], +]); + +# Monitor the state of the register model task. +$taskResponse = $client->ml()->getTask(['id' => $registerModelResponse['task_id']]); + +assert($taskResponse['state'] === 'COMPLETED'); + +# Finally deploy the model. You will now be able to generate vector +# embeddings from OpenSearch (via OpenAI). +$client->ml()->deployModel(['id' => $taskResponse['model_id']]); +``` diff --git a/src/OpenSearch/Client.php b/src/OpenSearch/Client.php index ed3f618db..abb889340 100644 --- a/src/OpenSearch/Client.php +++ b/src/OpenSearch/Client.php @@ -29,6 +29,7 @@ use OpenSearch\Common\Exceptions\TransportException; use OpenSearch\Endpoints\AbstractEndpoint; use OpenSearch\Namespaces\AbstractNamespace; +use OpenSearch\Namespaces\MachineLearningNamespace; use OpenSearch\Namespaces\NamespaceBuilderInterface; use OpenSearch\Namespaces\BooleanRequestWrapper; use OpenSearch\Namespaces\CatNamespace; @@ -153,6 +154,11 @@ class Client */ protected $sql; + /** + * @var MachineLearningNamespace + */ + protected $ml; + /** * Client constructor * @@ -179,6 +185,7 @@ public function __construct(Transport $transport, callable $endpoint, array $reg $this->security = new SecurityNamespace($transport, $endpoint); $this->ssl = new SslNamespace($transport, $endpoint); $this->sql = new SqlNamespace($transport, $endpoint); + $this->ml = new MachineLearningNamespace($transport, $endpoint); $this->registeredNamespaces = $registeredNamespaces; } @@ -1348,6 +1355,11 @@ public function sql(): SqlNamespace return $this->sql; } + public function ml(): MachineLearningNamespace + { + return $this->ml; + } + /** * Catchall for registered namespaces * diff --git a/src/OpenSearch/Endpoints/MachineLearning/Connectors/CreateConnector.php b/src/OpenSearch/Endpoints/MachineLearning/Connectors/CreateConnector.php new file mode 100644 index 000000000..4bd4d6adf --- /dev/null +++ b/src/OpenSearch/Endpoints/MachineLearning/Connectors/CreateConnector.php @@ -0,0 +1,43 @@ +id) { + return "/_plugins/_ml/connectors/$this->id"; + } + + throw new RuntimeException( + 'id is required for delete' + ); + + } + + /** + * @return string + */ + public function getMethod(): string + { + return 'DELETE'; + } +} diff --git a/src/OpenSearch/Endpoints/MachineLearning/Connectors/GetConnector.php b/src/OpenSearch/Endpoints/MachineLearning/Connectors/GetConnector.php new file mode 100644 index 000000000..fef1aa17a --- /dev/null +++ b/src/OpenSearch/Endpoints/MachineLearning/Connectors/GetConnector.php @@ -0,0 +1,51 @@ +id) { + return "/_plugins/_ml/connectors/$this->id"; + } + + throw new RuntimeException( + 'id is required for get' + ); + + } + + /** + * @return string + */ + public function getMethod(): string + { + return 'GET'; + } +} diff --git a/src/OpenSearch/Endpoints/MachineLearning/Connectors/GetConnectors.php b/src/OpenSearch/Endpoints/MachineLearning/Connectors/GetConnectors.php new file mode 100644 index 000000000..e5e5d698b --- /dev/null +++ b/src/OpenSearch/Endpoints/MachineLearning/Connectors/GetConnectors.php @@ -0,0 +1,43 @@ +id) { + return "/_plugins/_ml/model_groups/$this->id"; + } + + throw new RuntimeException( + 'id is required for delete' + ); + + } + + /** + * @return string + */ + public function getMethod(): string + { + return 'DELETE'; + } +} diff --git a/src/OpenSearch/Endpoints/MachineLearning/ModelGroups/GetModelGroups.php b/src/OpenSearch/Endpoints/MachineLearning/ModelGroups/GetModelGroups.php new file mode 100644 index 000000000..0dd03bbc2 --- /dev/null +++ b/src/OpenSearch/Endpoints/MachineLearning/ModelGroups/GetModelGroups.php @@ -0,0 +1,43 @@ +id) { + return "/_plugins/_ml/model_groups/$this->id"; + } + + throw new RuntimeException( + 'id is required for update' + ); + } + + /** + * @return string + */ + public function getMethod(): string + { + return 'PUT'; + } +} diff --git a/src/OpenSearch/Endpoints/MachineLearning/Models/DeleteModel.php b/src/OpenSearch/Endpoints/MachineLearning/Models/DeleteModel.php new file mode 100644 index 000000000..d4810d7af --- /dev/null +++ b/src/OpenSearch/Endpoints/MachineLearning/Models/DeleteModel.php @@ -0,0 +1,51 @@ +id) { + return "/_plugins/_ml/models/$this->id"; + } + + throw new RuntimeException( + 'id is required for delete' + ); + + } + + /** + * @return string + */ + public function getMethod(): string + { + return 'DELETE'; + } +} diff --git a/src/OpenSearch/Endpoints/MachineLearning/Models/DeployModel.php b/src/OpenSearch/Endpoints/MachineLearning/Models/DeployModel.php new file mode 100644 index 000000000..48bfede19 --- /dev/null +++ b/src/OpenSearch/Endpoints/MachineLearning/Models/DeployModel.php @@ -0,0 +1,51 @@ +id) { + return "/_plugins/_ml/models/$this->id/_deploy"; + } + + throw new RuntimeException( + 'id is required for deploy' + ); + + } + + /** + * @return string + */ + public function getMethod(): string + { + return 'POST'; + } +} diff --git a/src/OpenSearch/Endpoints/MachineLearning/Models/GetModel.php b/src/OpenSearch/Endpoints/MachineLearning/Models/GetModel.php new file mode 100644 index 000000000..f2c333d93 --- /dev/null +++ b/src/OpenSearch/Endpoints/MachineLearning/Models/GetModel.php @@ -0,0 +1,51 @@ +id) { + return "/_plugins/_ml/models/$this->id"; + } + + throw new RuntimeException( + 'id is required for get' + ); + + } + + /** + * @return string + */ + public function getMethod(): string + { + return 'GET'; + } +} diff --git a/src/OpenSearch/Endpoints/MachineLearning/Models/GetModels.php b/src/OpenSearch/Endpoints/MachineLearning/Models/GetModels.php new file mode 100644 index 000000000..7f714ec45 --- /dev/null +++ b/src/OpenSearch/Endpoints/MachineLearning/Models/GetModels.php @@ -0,0 +1,43 @@ +id) { + return "/_plugins/_ml/models/$this->id/_predict"; + } + + throw new RuntimeException( + 'id is required for predict' + ); + + } + + /** + * @return string + */ + public function getMethod(): string + { + return 'POST'; + } +} diff --git a/src/OpenSearch/Endpoints/MachineLearning/Models/RegisterModel.php b/src/OpenSearch/Endpoints/MachineLearning/Models/RegisterModel.php new file mode 100644 index 000000000..aa9c11058 --- /dev/null +++ b/src/OpenSearch/Endpoints/MachineLearning/Models/RegisterModel.php @@ -0,0 +1,43 @@ +id) { + return "/_plugins/_ml/models/$this->id/_undeploy"; + } + + throw new RuntimeException( + 'id is required for undeploy' + ); + + } + + /** + * @return string + */ + public function getMethod(): string + { + return 'POST'; + } +} diff --git a/src/OpenSearch/Endpoints/MachineLearning/Tasks/GetTask.php b/src/OpenSearch/Endpoints/MachineLearning/Tasks/GetTask.php new file mode 100644 index 000000000..833d88ef5 --- /dev/null +++ b/src/OpenSearch/Endpoints/MachineLearning/Tasks/GetTask.php @@ -0,0 +1,51 @@ +id) { + return "/_plugins/_ml/tasks/$this->id"; + } + + throw new RuntimeException( + 'id is required for get' + ); + + } + + /** + * @return string + */ + public function getMethod(): string + { + return 'GET'; + } +} diff --git a/src/OpenSearch/Namespaces/MachineLearningNamespace.php b/src/OpenSearch/Namespaces/MachineLearningNamespace.php new file mode 100644 index 000000000..d4989b6aa --- /dev/null +++ b/src/OpenSearch/Namespaces/MachineLearningNamespace.php @@ -0,0 +1,371 @@ +extractArgument($params, 'body'); + $endpointBuilder = $this->endpoints; + $endpoint = $endpointBuilder('MachineLearning\Connectors\CreateConnector'); + $endpoint->setParams($params); + $endpoint->setBody($body); + + return $this->performRequest($endpoint); + } + + /** + * $params['id'] = (string) The id of the connector (Required) + * + * @param array $params Associative array of parameters + * + * @return array + * The response. + */ + public function getConnector(array $params = []): array + { + $id = $this->extractArgument($params, 'id'); + $endpointBuilder = $this->endpoints; + $endpoint = $endpointBuilder('MachineLearning\Connectors\GetConnector'); + $endpoint->setParams($params); + $endpoint->setId($id); + + return $this->performRequest($endpoint); + } + + /** + * $params['body'] = (string) The body of the request + * + * @param array $params Associative array of parameters + * + * @return array + * The response. + */ + public function getConnectors(array $params = []): array + { + if (!isset($params['body'])) { + $params['body'] = [ + 'query' => [ + 'match_all' => new \StdClass(), + ], + 'size' => 1000, + ]; + } + $body = $this->extractArgument($params, 'body'); + $endpointBuilder = $this->endpoints; + $endpoint = $endpointBuilder('MachineLearning\Connectors\GetConnectors'); + $endpoint->setBody($body); + + return $this->performRequest($endpoint); + } + + /** + * $params['id'] = (string) The id of the connector (Required) + * + * @param array $params Associative array of parameters + * + * @return array + * The response. + */ + public function deleteConnector(array $params = []): array + { + $id = $this->extractArgument($params, 'id'); + $endpointBuilder = $this->endpoints; + $endpoint = $endpointBuilder('MachineLearning\Connectors\DeleteConnector'); + $endpoint->setParams($params); + $endpoint->setId($id); + + return $this->performRequest($endpoint); + } + + /** + * $params['body'] = (string) The body of the request (Required) + * + * @param array $params Associative array of parameters + * + * @return array + * The response. + */ + public function registerModelGroup(array $params = []): array + { + $body = $this->extractArgument($params, 'body'); + $endpointBuilder = $this->endpoints; + $endpoint = $endpointBuilder('MachineLearning\ModelGroups\RegisterModelGroup'); + $endpoint->setParams($params); + $endpoint->setBody($body); + + return $this->performRequest($endpoint); + } + + /** + * $params['body'] = (string) The body of the request + * + * @param array $params Associative array of parameters + * + * @return array + * The response. + */ + public function getModelGroups(array $params = []): array + { + if (!isset($params['body'])) { + $params['body'] = [ + 'query' => [ + 'match_all' => new \StdClass(), + ], + 'size' => 1000, + ]; + } + $body = $this->extractArgument($params, 'body'); + $endpointBuilder = $this->endpoints; + $endpoint = $endpointBuilder('MachineLearning\ModelGroups\GetModelGroups'); + $endpoint->setBody($body); + + return $this->performRequest($endpoint); + } + + /** + * $params['id'] = (string) The id of the model group (Required) + * $params['body'] = (array) The body of the request (Required) + * + * @param array $params Associative array of parameters + * + * @return array + * The response. + */ + public function updateModelGroup(array $params = []): array + { + $id = $this->extractArgument($params, 'id'); + $body = $this->extractArgument($params, 'body'); + $endpointBuilder = $this->endpoints; + $endpoint = $endpointBuilder('MachineLearning\ModelGroups\UpdateModelGroup'); + $endpoint->setParams($params); + $endpoint->setBody($body); + $endpoint->setId($id); + + return $this->performRequest($endpoint); + } + + /** + * $params['id'] = (string) The id of the model group (Required) + * + * @param array $params Associative array of parameters + * + * @return array + * The response. + */ + public function deleteModelGroup(array $params = []): array + { + $id = $this->extractArgument($params, 'id'); + $endpointBuilder = $this->endpoints; + $endpoint = $endpointBuilder('MachineLearning\ModelGroups\DeleteModelGroup'); + $endpoint->setParams($params); + $endpoint->setId($id); + + return $this->performRequest($endpoint); + } + + /** + * $params['body'] = (string) The body of the request (Required) + * + * @param array $params Associative array of parameters + * + * @return array + * The response. + */ + public function registerModel(array $params = []): array + { + $body = $this->extractArgument($params, 'body'); + $endpointBuilder = $this->endpoints; + $endpoint = $endpointBuilder('MachineLearning\Models\RegisterModel'); + $endpoint->setParams($params); + $endpoint->setBody($body); + + return $this->performRequest($endpoint); + } + + /** + * $params['id'] = (string) The id of the model (Required) + * + * @param array $params Associative array of parameters + * + * @return array + * The response. + */ + public function getModel(array $params = []): array + { + $id = $this->extractArgument($params, 'id'); + $endpointBuilder = $this->endpoints; + $endpoint = $endpointBuilder('MachineLearning\Models\GetModel'); + $endpoint->setParams($params); + $endpoint->setId($id); + + return $this->performRequest($endpoint); + } + + /** + * $params['body'] = (array) The body of the request + * + * @param array $params Associative array of parameters + * + * @return array + * The response. + */ + public function getModels(array $params = []): array + { + if (!isset($params['body'])) { + $params['body'] = [ + 'query' => [ + 'match_all' => new \StdClass(), + ], + 'size' => 1000, + ]; + } + $body = $this->extractArgument($params, 'body'); + $endpointBuilder = $this->endpoints; + $endpoint = $endpointBuilder('MachineLearning\Models\GetModels'); + $endpoint->setParams($params); + $endpoint->setBody($body); + + return $this->performRequest($endpoint); + } + + /** + * $params['id'] = (string) The id of the model (Required) + * $params['body'] = (string) The body of the request + * + * @param array $params Associative array of parameters + * + * @return array + * The response. + */ + public function deployModel(array $params = []): array + { + $id = $this->extractArgument($params, 'id'); + $body = $this->extractArgument($params, 'body'); + $endpointBuilder = $this->endpoints; + $endpoint = $endpointBuilder('MachineLearning\Models\DeployModel'); + $endpoint->setParams($params); + $endpoint->setId($id); + if ($body) { + $endpoint->setBody($body); + } + + return $this->performRequest($endpoint); + } + + /** + * $params['id'] = (string) The id of the model (Required) + * $params['body'] = (string) The body of the request + * + * @param array $params Associative array of parameters + * + * @return array + * The response. + */ + public function undeployModel(array $params = []): array + { + $id = $this->extractArgument($params, 'id'); + $body = $this->extractArgument($params, 'body'); + $endpointBuilder = $this->endpoints; + $endpoint = $endpointBuilder('MachineLearning\Models\UndeployModel'); + $endpoint->setParams($params); + $endpoint->setId($id); + if ($body) { + $endpoint->setBody($body); + } + + return $this->performRequest($endpoint); + } + + /** + * $params['id'] = (string) The id of the model (Required) + * + * @param array $params Associative array of parameters + * + * @return array + * The response. + */ + public function deleteModel(array $params = []): array + { + $id = $this->extractArgument($params, 'id'); + $endpointBuilder = $this->endpoints; + $endpoint = $endpointBuilder('MachineLearning\Models\DeleteModel'); + $endpoint->setParams($params); + $endpoint->setId($id); + + return $this->performRequest($endpoint); + } + + /** + * $params['id'] = (string) The id of the model (Required) + * $params['body'] = (string) The body of the request + * + * @param array $params Associative array of parameters + * + * @return array + * The response. + */ + public function predict(array $params = []): array + { + $id = $this->extractArgument($params, 'id'); + $body = $this->extractArgument($params, 'body'); + $endpointBuilder = $this->endpoints; + $endpoint = $endpointBuilder('MachineLearning\Models\Predict'); + $endpoint->setParams($params); + $endpoint->setId($id); + $endpoint->setBody($body); + + return $this->performRequest($endpoint); + } + + /** + * $params['id'] = (string) The id of the task (Required) + * + * @param array $params Associative array of parameters + * + * @return array + * The response. + */ + public function getTask(array $params = []): array + { + $id = $this->extractArgument($params, 'id'); + $endpointBuilder = $this->endpoints; + $endpoint = $endpointBuilder('MachineLearning\Tasks\GetTask'); + $endpoint->setParams($params); + $endpoint->setId($id); + + return $this->performRequest($endpoint); + } + +} diff --git a/tests/Namespaces/MachineLearningNamespaceTest.php b/tests/Namespaces/MachineLearningNamespaceTest.php new file mode 100644 index 000000000..4b83a3d1c --- /dev/null +++ b/tests/Namespaces/MachineLearningNamespaceTest.php @@ -0,0 +1,414 @@ +createMock(Transport::class); + + $transport->method('performRequest') + ->with('POST', '/_plugins/_ml/connectors/_create', [], [ + 'foo' => 'bar', + ]); + + $transport->method('resultOrFuture') + ->willReturn([]); + + (new MachineLearningNamespace($transport, $func))->createConnector([ + 'body' => [ + 'foo' => 'bar', + ], + ]); + } + + public function testGetConnector(): void + { + + $func = static function () { + return new GetConnector(); + }; + + $transport = $this->createMock(Transport::class); + + $transport->method('performRequest') + ->with('GET', '/_plugins/_ml/connectors/foobar', [], null); + + $transport->method('resultOrFuture') + ->willReturn([]); + + (new MachineLearningNamespace($transport, $func))->getConnector([ + 'id' => 'foobar' + ]); + } + + public function testGetConnectors(): void + { + + $func = static function () { + return new GetConnectors(); + }; + + $transport = $this->createMock(Transport::class); + + $transport->method('performRequest') + ->with('POST', '/_plugins/_ml/connectors/_search', [], [ + 'query' => [ + 'match_all' => new \StdClass(), + ], + 'size' => 1000, + ]); + + $transport->method('resultOrFuture') + ->willReturn([]); + + (new MachineLearningNamespace($transport, $func))->getConnectors([ + 'body' => [ + 'query' => [ + 'match_all' => new \StdClass(), + ], + 'size' => 1000, + ], + ]); + } + + public function testDeleteConnector(): void + { + + $func = static function () { + return new DeleteConnector(); + }; + + $transport = $this->createMock(Transport::class); + + $transport->method('performRequest') + ->with('DELETE', '/_plugins/_ml/connectors/foobar', [], null); + + $transport->method('resultOrFuture') + ->willReturn([]); + + (new MachineLearningNamespace($transport, $func))->deleteConnector([ + 'id' => 'foobar' + ]); + } + + public function testRegisterModelGroup(): void + { + + $func = static function () { + return new RegisterModelGroup(); + }; + + $transport = $this->createMock(Transport::class); + + $transport->method('performRequest') + ->with('POST', '/_plugins/_ml/model_groups/_register', [], [ + 'foo' => 'bar', + ]); + + $transport->method('resultOrFuture') + ->willReturn([]); + + (new MachineLearningNamespace($transport, $func))->registerModelGroup([ + 'body' => [ + 'foo' => 'bar', + ], + ]); + } + + public function testGetModelGroups(): void + { + + $func = static function () { + return new GetModelGroups(); + }; + + $transport = $this->createMock(Transport::class); + + $transport->method('performRequest') + ->with('POST', '/_plugins/_ml/model_groups/_search', [], [ + 'query' => [ + 'match_all' => new \StdClass(), + ], + 'size' => 1000, + ]); + + $transport->method('resultOrFuture') + ->willReturn([]); + + (new MachineLearningNamespace($transport, $func))->getModelGroups([ + 'body' => [ + 'query' => [ + 'match_all' => new \StdClass(), + ], + 'size' => 1000, + ], + ]); + } + + public function testUpdateModelGroup(): void + { + + $func = static function () { + return new UpdateModelGroup(); + }; + + $transport = $this->createMock(Transport::class); + + $transport->method('performRequest') + ->with('PUT', '/_plugins/_ml/model_groups/foobar', [], [ + 'query' => [ + 'match_all' => new \StdClass(), + ], + 'size' => 1000, + ]); + + $transport->method('resultOrFuture') + ->willReturn([]); + + (new MachineLearningNamespace($transport, $func))->updateModelGroup([ + 'id' => 'foobar', + 'body' => [ + 'query' => [ + 'match_all' => new \StdClass(), + ], + 'size' => 1000, + ], + ]); + } + + public function testDeleteModelGroup(): void + { + + $func = static function () { + return new DeleteModelGroup(); + }; + + $transport = $this->createMock(Transport::class); + + $transport->method('performRequest') + ->with('DELETE', '/_plugins/_ml/model_groups/foobar', [], null); + + $transport->method('resultOrFuture') + ->willReturn([]); + + (new MachineLearningNamespace($transport, $func))->deleteModelGroup([ + 'id' => 'foobar' + ]); + } + + public function testRegisterModel(): void + { + + $func = static function () { + return new RegisterModel(); + }; + + $transport = $this->createMock(Transport::class); + + $transport->method('performRequest') + ->with('POST', '/_plugins/_ml/models/_register', [], [ + 'foo' => 'bar', + ]); + + $transport->method('resultOrFuture') + ->willReturn([]); + + (new MachineLearningNamespace($transport, $func))->registerModel([ + 'body' => [ + 'foo' => 'bar', + ], + ]); + } + + public function testGetModel(): void + { + + $func = static function () { + return new GetModel(); + }; + + $transport = $this->createMock(Transport::class); + + $transport->method('performRequest') + ->with('GET', '/_plugins/_ml/models/foobar', [], null); + + $transport->method('resultOrFuture') + ->willReturn([]); + + (new MachineLearningNamespace($transport, $func))->getModel([ + 'id' => 'foobar', + ]); + } + + public function testGetModels(): void + { + + $func = static function () { + return new GetModels(); + }; + + $transport = $this->createMock(Transport::class); + + $transport->method('performRequest') + ->with('POST', '/_plugins/_ml/models/_search', [], [ + 'query' => [ + 'match_all' => new \StdClass(), + ], + 'size' => 1000, + ]); + + $transport->method('resultOrFuture') + ->willReturn([]); + + (new MachineLearningNamespace($transport, $func))->getModels([ + 'body' => [ + 'query' => [ + 'match_all' => new \StdClass(), + ], + 'size' => 1000, + ], + ]); + } + + public function testDeployModel(): void + { + + $func = static function () { + return new DeployModel(); + }; + + $transport = $this->createMock(Transport::class); + + $transport->method('performRequest') + ->with('POST', '/_plugins/_ml/models/foobar/_deploy', [], null); + + $transport->method('resultOrFuture') + ->willReturn([]); + + (new MachineLearningNamespace($transport, $func))->deployModel([ + 'id' => 'foobar', + ]); + } + + public function testUnDeployModel(): void + { + + $func = static function () { + return new UndeployModel(); + }; + + $transport = $this->createMock(Transport::class); + + $transport->method('performRequest') + ->with('POST', '/_plugins/_ml/models/foobar/_undeploy', [], null); + + $transport->method('resultOrFuture') + ->willReturn([]); + + (new MachineLearningNamespace($transport, $func))->undeployModel([ + 'id' => 'foobar', + ]); + } + + public function testDeleteModel(): void + { + + $func = static function () { + return new DeleteModel(); + }; + + $transport = $this->createMock(Transport::class); + + $transport->method('performRequest') + ->with('DELETE', '/_plugins/_ml/models/foobar', [], null); + + $transport->method('resultOrFuture') + ->willReturn([]); + + (new MachineLearningNamespace($transport, $func))->deleteModel([ + 'id' => 'foobar', + ]); + } + + public function testPredict(): void + { + + $func = static function () { + return new Predict(); + }; + + $transport = $this->createMock(Transport::class); + + $transport->method('performRequest') + ->with('POST', '/_plugins/_ml/models/foobar/_predict', [], [ + 'foo' => 'bar', + ]); + + $transport->method('resultOrFuture') + ->willReturn([]); + + (new MachineLearningNamespace($transport, $func))->predict([ + 'id' => 'foobar', + 'body' => [ + 'foo' => 'bar', + ] + ]); + } + + public function testGetTask(): void + { + + $func = static function () { + return new GetTask(); + }; + + $transport = $this->createMock(Transport::class); + + $transport->method('performRequest') + ->with('GET', '/_plugins/_ml/tasks/foobar', [], null); + + $transport->method('resultOrFuture') + ->willReturn([]); + + (new MachineLearningNamespace($transport, $func))->getTask([ + 'id' => 'foobar', + ]); + } +}