From 7461899260b9ad74e1be2fe7786d1726b6757081 Mon Sep 17 00:00:00 2001 From: nirupa-kumar Date: Thu, 19 Jul 2018 07:16:57 -0700 Subject: [PATCH 01/15] Test push --- .../vision/samples/automl/DatasetApi.java | 347 ++++++++++++++++++ 1 file changed, 347 insertions(+) create mode 100644 vision/automl/src/main/java/com/google/cloud/vision/samples/automl/DatasetApi.java diff --git a/vision/automl/src/main/java/com/google/cloud/vision/samples/automl/DatasetApi.java b/vision/automl/src/main/java/com/google/cloud/vision/samples/automl/DatasetApi.java new file mode 100644 index 00000000000..c75d8b15e31 --- /dev/null +++ b/vision/automl/src/main/java/com/google/cloud/vision/samples/automl/DatasetApi.java @@ -0,0 +1,347 @@ +/* + * Copyright 2018 Google LLC. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.vision.samples.automl; + +// Imports the Google Cloud client library +import com.google.cloud.automl.v1beta1.AutoMlClient; +import com.google.cloud.automl.v1beta1.ClassificationProto.ClassificationType; +import com.google.cloud.automl.v1beta1.Dataset; +import com.google.cloud.automl.v1beta1.DatasetName; +import com.google.cloud.automl.v1beta1.GcsDestination; +import com.google.cloud.automl.v1beta1.GcsSource; +import com.google.cloud.automl.v1beta1.ImageClassificationDatasetMetadata; +import com.google.cloud.automl.v1beta1.InputConfig; +import com.google.cloud.automl.v1beta1.ListDatasetsRequest; +import com.google.cloud.automl.v1beta1.LocationName; + +import com.google.cloud.automl.v1beta1.OutputConfig; +import com.google.protobuf.Empty; +import java.io.IOException; +import java.io.PrintStream; + +import net.sourceforge.argparse4j.ArgumentParsers; +import net.sourceforge.argparse4j.inf.ArgumentParser; +import net.sourceforge.argparse4j.inf.ArgumentParserException; +import net.sourceforge.argparse4j.inf.Namespace; +import net.sourceforge.argparse4j.inf.Subparser; +import net.sourceforge.argparse4j.inf.Subparsers; + +/** + * Google Cloud AutoML Vision API sample application. Example usage: mvn package exec:java + * -Dexec.mainClass ='com.google.cloud.vision.samples.automl.DatasetAPI' -Dexec.args='create_dataset + * test_dataset' + */ +public class DatasetApi { + + // [START automl_vision_create_dataset] + + /** + * Demonstrates using the AutoML client to create a dataset + * + * @param projectId the Google Cloud Project ID. + * @param computeRegion the Region name. (e.g., "us-central1") + * @param datasetName the name of the dataset to be created. + * @param multiLabel the type of classification problem. Set to FALSE by default. + * @throws IOException on Input/Output errors. + */ + public static void createDataset( + String projectId, String computeRegion, String datasetName, Boolean multiLabel) + throws IOException { + // Instantiates a client + AutoMlClient client = AutoMlClient.create(); + + // Resource representing the Google Cloud Platform location + LocationName projectLocation = LocationName.of(projectId, computeRegion); + + // Classification type assigned based on multiLabel value. + ClassificationType classificationType = + multiLabel ? ClassificationType.MULTILABEL : ClassificationType.MULTICLASS; + + // Specify the image classification type for the dataset. + ImageClassificationDatasetMetadata imageClassificationDatasetMetadata = + ImageClassificationDatasetMetadata.newBuilder() + .setClassificationType(classificationType) + .build(); + + // Create a dataset with dataset name and set the dataset metadata. + Dataset myDataset = + Dataset.newBuilder() + .setDisplayName(datasetName) + .setImageClassificationDatasetMetadata(imageClassificationDatasetMetadata) + .build(); + + // Create dataset with the dataset metadata in the region. + Dataset dataset = client.createDataset(projectLocation, myDataset); + + // Display the dataset information + System.out.println(String.format("Dataset name: %s", dataset.getName())); + System.out.println( + String.format( + "Dataset id: %s", + dataset.getName().split("/")[dataset.getName().split("/").length - 1])); + System.out.println(String.format("Dataset display name: %s", dataset.getDisplayName())); + System.out.println("Image classification dataset specification:"); + System.out.print(String.format("\t%s", dataset.getImageClassificationDatasetMetadata())); + System.out.println(String.format("Dataset example count: %d", dataset.getExampleCount())); + System.out.println("Dataset create time:"); + System.out.println(String.format("\tseconds: %s", dataset.getCreateTime().getSeconds())); + System.out.println(String.format("\tnanos: %s", dataset.getCreateTime().getNanos())); + } + // [END automl_vision_create_dataset] + + // [START automl_vision_listdatasets] + /** + * Demonstrates using the AutoML client to list all datasets. + * + * @param projectId - Id of the project. + * @param computeRegion - Region name. + * @param filter - Filter expression. + * @throws IOException on Input/Output errors. + */ + public static void listDatasets(String projectId, String computeRegion, String filter) + throws IOException { + // Instantiates a client + AutoMlClient client = AutoMlClient.create(); + + // A resource that represents Google Cloud Platform location. + LocationName projectLocation = LocationName.of(projectId, computeRegion); + + // Build the List datasets request + ListDatasetsRequest request = + ListDatasetsRequest.newBuilder() + .setParent(projectLocation.toString()) + .setFilter(filter) + .build(); + + // List all the datasets available in the region by applying the filter. + System.out.println("List of datasets:"); + for (Dataset dataset : client.listDatasets(request).iterateAll()) { + // Display the dataset information + System.out.println(String.format("\nDataset name: %s", dataset.getName())); + System.out.println( + String.format( + "Dataset id: %s", + dataset.getName().split("/")[dataset.getName().split("/").length - 1])); + System.out.println(String.format("Dataset display name: %s", dataset.getDisplayName())); + System.out.println("Image classification dataset specification:"); + System.out.print(String.format("\t%s", dataset.getImageClassificationDatasetMetadata())); + System.out.println(String.format("Dataset example count: %d", dataset.getExampleCount())); + System.out.println("Dataset create time:"); + System.out.println(String.format("\tseconds: %s", dataset.getCreateTime().getSeconds())); + System.out.println(String.format("\tnanos: %s", dataset.getCreateTime().getNanos())); + } + } + // [END automl_vision_listdatasets] + + // [START automl_vision_getdataset] + /** + * Demonstrates using the AutoML client to get a dataset by ID. + * + * @param projectId - Id of the project. + * @param computeRegion - Region name. + * @param datasetId - Id of the dataset. + * @throws IOException on Input/Output errors. + */ + public static void getDataset(String projectId, String computeRegion, String datasetId) + throws IOException { + // Instantiates a client + AutoMlClient client = AutoMlClient.create(); + + // Get the complete path of the dataset. + DatasetName datasetFullId = DatasetName.of(projectId, computeRegion, datasetId); + + // Get all the information about a given dataset. + Dataset dataset = client.getDataset(datasetFullId); + + // Display the dataset information. + System.out.println(String.format("Dataset name: %s", dataset.getName())); + System.out.println( + String.format( + "Dataset id: %s", + dataset.getName().split("/")[dataset.getName().split("/").length - 1])); + System.out.println(String.format("Dataset display name: %s", dataset.getDisplayName())); + System.out.println("Image classification dataset specification:"); + System.out.print(String.format("\t%s", dataset.getImageClassificationDatasetMetadata())); + System.out.println(String.format("Dataset example count: %d", dataset.getExampleCount())); + System.out.println("Dataset create time:"); + System.out.println(String.format("\tseconds: %s", dataset.getCreateTime().getSeconds())); + System.out.println(String.format("\tnanos: %s", dataset.getCreateTime().getNanos())); + } + // [END automl_vision_getdataset] + + // [START automl_vision_importdata] + /** + * Demonstrates using the AutoML client to import labeled images. + * + * @param projectId - Id of the project. + * @param computeRegion - Region name. + * @param datasetId - Id of the dataset to which the training data will be imported. + * @param path - Google Cloud Storage URIs. Target files must be in AutoML vision CSV format. + * @throws Exception on AutoML Client errors + */ + public static void importData( + String projectId, String computeRegion, String datasetId, String path) throws Exception { + // Instantiates a client + AutoMlClient client = AutoMlClient.create(); + + // Get the complete path of the dataset. + DatasetName datasetFullId = DatasetName.of(projectId, computeRegion, datasetId); + + GcsSource.Builder gcsSource = GcsSource.newBuilder(); + + // Get multiple training data files to be imported + String[] inputUris = path.split(","); + for (String inputUri : inputUris) { + gcsSource.addInputUris(inputUri); + } + + // Import data + InputConfig inputConfig = InputConfig.newBuilder().setGcsSource(gcsSource).build(); + System.out.println("Processing import..."); + Empty response = client.importDataAsync(datasetFullId.toString(), inputConfig).get(); + System.out.println(String.format("Dataset imported. %s", response)); + } + // [END automl_vision_importdata] + + // [START automl_vision_exportdata] + /** + * Demonstrates using the AutoML client to export a dataset to a Google Cloud Storage bucket. + * + * @param projectId - Id of the project. + * @param computeRegion - Region name. + * @param datasetId - Id of the dataset. + * @param gcsUri - Destination URI (Google Cloud Storage) + * @throws Exception on AutoML Client errors + */ + public static void exportData( + String projectId, String computeRegion, String datasetId, String gcsUri) throws Exception { + // Instantiates a client + AutoMlClient client = AutoMlClient.create(); + + // Get the complete path of the dataset. + DatasetName datasetFullId = DatasetName.of(projectId, computeRegion, datasetId); + + // Set the output URI + GcsDestination gcsDestination = GcsDestination.newBuilder().setOutputUriPrefix(gcsUri).build(); + + // Export the dataset to the output URI. + OutputConfig outputConfig = OutputConfig.newBuilder().setGcsDestination(gcsDestination).build(); + System.out.println("Processing export..."); + + Empty response = client.exportDataAsync(datasetFullId, outputConfig).get(); + System.out.println(String.format("Dataset exported. %s", response)); + } + // [END automl_vision_exportdata] + + // [START automl_vision_deletedataset] + /** + * Delete a dataset. + * + * @param projectId - Id of the project. + * @param computeRegion - Region name. + * @param datasetId - Id of the dataset. + * @throws Exception on AutoML Client errors + */ + public static void deleteDataset(String projectId, String computeRegion, String datasetId) + throws Exception { + // Instantiates a client + AutoMlClient client = AutoMlClient.create(); + + // Get the complete path of the dataset. + DatasetName datasetFullId = DatasetName.of(projectId, computeRegion, datasetId); + + // Delete a dataset. + Empty response = client.deleteDatasetAsync(datasetFullId).get(); + + System.out.println(String.format("Dataset deleted. %s", response)); + } + // [END automl_vision_deleteDataset] + + public static void main(String[] args) throws Exception { + DatasetApi datasetApi = new DatasetApi(); + datasetApi.argsHelper(args, System.out); + } + + public static void argsHelper(String[] args, PrintStream out) throws Exception { + ArgumentParser parser = + ArgumentParsers.newFor("DatasetAPI") + .build() + .defaultHelp(true) + .description("Dataset API operations."); + Subparsers subparsers = parser.addSubparsers().dest("command"); + + Subparser createDatasetParser = subparsers.addParser("create_dataset"); + createDatasetParser.addArgument("datasetName"); + createDatasetParser + .addArgument("multiLabel") + .nargs("?") + .type(Boolean.class) + .choices(Boolean.FALSE, Boolean.TRUE) + .setDefault(Boolean.FALSE); + + Subparser listDatasetsParser = subparsers.addParser("list_datasets"); + listDatasetsParser + .addArgument("filter") + .nargs("?") + .setDefault("imageClassificationDatasetMetadata:*"); + + Subparser getDatasetParser = subparsers.addParser("get_dataset"); + getDatasetParser.addArgument("datasetId"); + + Subparser importDataParser = subparsers.addParser("import_data"); + importDataParser.addArgument("datasetId"); + importDataParser.addArgument("path"); + + Subparser exportDataParser = subparsers.addParser("export_data"); + exportDataParser.addArgument("datasetId"); + exportDataParser.addArgument("gcsUri"); + + Subparser deleteDatasetParser = subparsers.addParser("delete_dataset"); + deleteDatasetParser.addArgument("datasetId"); + + String projectId = System.getenv("PROJECT_ID"); + String computeRegion = System.getenv("REGION_NAME"); + + Namespace ns = null; + try { + ns = parser.parseArgs(args); + + if (ns.get("command").equals("create_dataset")) { + createDataset( + projectId, computeRegion, ns.getString("datasetName"), ns.getBoolean("multiLabel")); + } + if (ns.get("command").equals("list_datasets")) { + listDatasets(projectId, computeRegion, ns.getString("filter")); + } + if (ns.get("command").equals("get_dataset")) { + getDataset(projectId, computeRegion, ns.getString("datasetId")); + } + if (ns.get("command").equals("import_data")) { + importData(projectId, computeRegion, ns.getString("datasetId"), ns.getString("path")); + } + if (ns.get("command").equals("export_data")) { + exportData(projectId, computeRegion, ns.getString("datasetId"), ns.getString("gcsUri")); + } + if (ns.get("command").equals("delete_dataset")) { + deleteDataset(projectId, computeRegion, ns.getString("datasetId")); + } + + } catch (ArgumentParserException e) { + parser.handleError(e); + } + } +} From f4531a9f5daee44cb053e5e88b970044da1d0aa7 Mon Sep 17 00:00:00 2001 From: nirupa-kumar Date: Sat, 21 Jul 2018 16:49:35 -0700 Subject: [PATCH 02/15] Vision AutoML --- vision/automl/README.md | 87 ++++ vision/automl/pom.xml | 154 ++++++ vision/automl/resources/dandelion.jpg | Bin 0 -> 53485 bytes .../vision/samples/automl/DatasetApi.java | 80 +-- .../cloud/vision/samples/automl/ModelApi.java | 460 ++++++++++++++++++ .../vision/samples/automl/PredictionApi.java | 142 ++++++ .../vision/samples/automl/DatasetApiIT.java | 107 ++++ .../vision/samples/automl/ModelApiIT.java | 88 ++++ .../samples/automl/PredictionApiIT.java | 64 +++ 9 files changed, 1142 insertions(+), 40 deletions(-) create mode 100644 vision/automl/README.md create mode 100644 vision/automl/pom.xml create mode 100644 vision/automl/resources/dandelion.jpg create mode 100644 vision/automl/src/main/java/com/google/cloud/vision/samples/automl/ModelApi.java create mode 100644 vision/automl/src/main/java/com/google/cloud/vision/samples/automl/PredictionApi.java create mode 100644 vision/automl/src/test/java/com/google/cloud/vision/samples/automl/DatasetApiIT.java create mode 100644 vision/automl/src/test/java/com/google/cloud/vision/samples/automl/ModelApiIT.java create mode 100644 vision/automl/src/test/java/com/google/cloud/vision/samples/automl/PredictionApiIT.java diff --git a/vision/automl/README.md b/vision/automl/README.md new file mode 100644 index 00000000000..24a73c48ece --- /dev/null +++ b/vision/automl/README.md @@ -0,0 +1,87 @@ +# AutoML Sample + + +Open in Cloud Shell + +[Google Cloud Vision API][vision] provides feature detection for images. +This API is part of the larger collection of Cloud Machine Learning APIs. + +This sample Java application demonstrates how to access the Cloud Vision API +using the [Google Cloud Client Library for Java][google-cloud-java]. + +[vision]: https://cloud.google.com/vision/docs/ +[google-cloud-java]: https://github.com/GoogleCloudPlatform/google-cloud-java + +## Set the environment variables + +PROJECT_ID = [Id of the project] +REGION_NAME = [Region name] +## Build the sample + +Install [Maven](http://maven.apache.org/). + +Build your project with: + +``` +mvn clean package +``` + +### Dataset API + +#### Create a new dataset +``` +mvn exec:java -Dexec.mainClass="com.google.cloud.vision.samples.automl.DatasetApi" -Dexec.args="create_dataset test_dataset" +``` + +#### List datasets +``` +mvn exec:java -Dexec.mainClass="com.google.cloud.vision.samples.automl.DatasetApi" -Dexec.args="list_datasets" +``` + +#### Get dataset +``` +mvn exec:java -Dexec.mainClass="com.google.cloud.vision.samples.automl.DatasetApi" -Dexec.args="get_dataset [dataset-id]" +``` + +#### Import data +``` +mvn exec:java -Dexec.mainClass="com.google.cloud.vision.samples.automl.DatasetApi" -Dexec.args="import_data gs://java-docs-samples-testing/flower_traindata.csv" +``` + +### Model API + +#### Create Model +``` +mvn exec:java -Dexec.mainClass="com.google.cloud.vision.samples.automl.ModelApi" -Dexec.args="create_model test_model" +``` + +#### List Models +``` +mvn exec:java -Dexec.mainClass="com.google.cloud.vision.samples.automl.ModelApi" -Dexec.args="list_models" +``` + +#### Get Model +``` +mvn exec:java -Dexec.mainClass="com.google.cloud.vision.samples.automl.ModelApi" -Dexec.args="get_model [model-id]" +``` + +#### List Model Evaluations +``` +mvn exec:java -Dexec.mainClass="com.google.cloud.vision.samples.automl.ModelApi" -Dexec.args="list_model_evaluation [model-id]" +``` + +#### Get Model Evaluation +``` +mvn exec:java -Dexec.mainClass="com.google.cloud.vision.samples.automl.ModelApi" -Dexec.args="get_model_evaluation [model-id] [model-evaluation-id]" +``` + +#### Delete Model +``` +mvn exec:java-Dexec.mainClass="com.google.cloud.vision.samples.automl.ModeltApi" -Dexec.args="delete_model [model-id]" +``` +### Predict API + +``` +mvn exec:java -Dexec.mainClass="com.google.cloud.vision.samples.automl.PredictApi" -Dexec.args="predict [model-id] ./resources/dandelion.jpg 0.7" +``` + diff --git a/vision/automl/pom.xml b/vision/automl/pom.xml new file mode 100644 index 00000000000..5b5dd838624 --- /dev/null +++ b/vision/automl/pom.xml @@ -0,0 +1,154 @@ + + + 4.0.0 + com.example.vision + vision-automl + jar + + + + com.google.cloud.samples + shared-configuration + 1.0.9 + + + + 1.8 + 1.8 + UTF-8 + + + + + + com.google.cloud + google-cloud-automl + 0.55.0-beta + + + net.sourceforge.argparse4j + argparse4j + 0.8.1 + + + + + + junit + junit + 4.12 + test + + + + com.google.truth + truth + 0.41 + test + + + + + + DatasetApi + + + DatasetApi + + + + + + org.codehaus.mojo + exec-maven-plugin + 1.6.0 + + + + java + + + + + com.google.cloud.vision.samples.automl.DatasetApi + false + + + + + + + ModelApi + + + ModelApi + + + + + + org.codehaus.mojo + exec-maven-plugin + 1.6.0 + + + + java + + + + + com.google.cloud.vision.samples.automl.ModelApi + false + + + + + + + PredictApi + + + PredictApi + + + + + + org.codehaus.mojo + exec-maven-plugin + 1.6.0 + + + + java + + + + + com.google.cloud.vision.samples.automl.PredictApi + false + + + + + + + diff --git a/vision/automl/resources/dandelion.jpg b/vision/automl/resources/dandelion.jpg new file mode 100644 index 0000000000000000000000000000000000000000..326e4c1bf533799771a86daa32fe4acbd70285aa GIT binary patch literal 53485 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 {J6HT)NUt64jDrt|AY@zqNAdI*}N%BvD zp(4#61Ji9QNu`Pi9h8e&cgYICW@dU?h@1JvlVAjDsb;so#=Y)pDct$MCI4VThrR0K%NC zeq~&rY?{=9eDRfy`3DMjJ}oCc=fA1x+L5{nUI>?WkRtL@OM8h2hfbGB^PZUill1!L zrsUrN#D6E;g}PN2a+GC07~zm?J+Lqj{HBi2EL*YU;iawQj>ty1Uz0j_?VRWJ$)hEV z87ttMJYV5)iTHwZ94jiUap@sHG20?2{MhB&pdA35n_QsMT#!Zm&l8estAh4CHWCJ9 zQ;la}29x_&#^EvHz}-gmB_}U)70Y+RCtYy}?;@7U(%yJ&r)5_wrRBIF?ad?R>#_rZ zWxIVG|%#Dlr=7#O6JZTt-slF1u_%8zq$ zzYMU%kP)gDC^GvTp(T1_%K&18ozy|wkiDI)lH6WRX*z=#8q97Y4BIM3b$E6QjARbG zRn|$S=;MgmOYmGJ+BqPQK{OhbJRk{mDv&iHT`l{=`XrUMQ8b66B2yEzI$Xt#OSoZ; z_8y}+-=OJI+tUkbF3|q~3bm5zHHzjx8f3)z$g7XPynKo6oMC2&>{m|xiNQPM=8l_` zU9&~)$o$qn32pGJCc8od+RE7RM02DcQSzMhBig5{9l7W-SM6``$V1+cKC@&;D60zI{9-6VPfMm}0Sg zp{~j&GCGAJV{k!6&djGLZ?50YtH?n~F$;l)O)hjZZ?VY%y7b7v$gRPwlQ@q0z^njG z3yhn2(T&oRd%eM z0Osb~S{*d;!w=w#CA6{2xZ1Ads5j8+9SP-J&nyDMP#1)KDl$aL-xj*GN-*BEmK4vWNC?za5k*Kh6!#lc;=yz<_Q1>ujy4(U;~-Z|7-Gs+ zGMJ~=3R?+ulm!}0s^>TZJ7>FfuBgrQQ93X1+@_YEMU0M$Zk0RM(lCvwPq0>G0Qd*LSsS~p1bECP3p-eF!lH0yD?~POm8Ei1~3IzFTX%M$=e%d zqp1pZkx0RE%%|dhBM-wpqr}s^z8psokQ{BOV1c1dReZ>18)>LHr0Tzcr#eefBG%q8XggCb7h$?iXte>29(Im-G%@gclI8&Yij{Z zvY!Y85#5ag1`-iTWtNaPZo`uv#-XtP~CnUj#(j0{1k|isqGyYPxcLcACe=$*)kV;Og$(`de@bt0@@mzA+ zK;N^`jDdiDU{6!to)S+85WBI?7|_244`p%0Ay_X0f>0^L#6~t?+Bj}i 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 response = + client.createModelAsync(projectLocation, myModel); + + System.out.println( + String.format("Training operation name: %s", response.getInitialFuture().get().getName())); + System.out.println("Training started..."); + } + // [END automl_vision_create_model] + + // [START automl_vision_get_operation_status] + /** + * Demonstrates using the AutoML client to get operation status. + * + * @param operationFullId : Full name of a operation. For example, the name of your operation is + * projects/[projectId]/locations/us-central1/operations/[operationId]. + * @throws IOException on Input/Output errors. + */ + public static void getOperationStatus(String operationFullId) throws IOException { + AutoMlClient client = AutoMlClient.create(); + + // Get the latest state of a long-running operation. + Operation response = client.getOperationsClient().getOperation(operationFullId); + + System.out.println(String.format("Operation status: %s", response)); + } + // [END automl_vision_get_operation_status] + + // [START automl_vision_list_models] + /** + * Demonstrates using the AutoML client to list all models. + * + * @param projectId - Id of the project. + * @param computeRegion - Region name. + * @param filter - Filter expression. + * @throws IOException on Input/Output errors. + */ + public static void listModels(String projectId, String computeRegion, String filter) + throws IOException { + AutoMlClient client = AutoMlClient.create(); + + // A resource that represents Google Cloud Platform location. + LocationName projectLocation = LocationName.of(projectId, computeRegion); + + // Create list models request + ListModelsRequest listModlesRequest = + ListModelsRequest.newBuilder() + .setParent(projectLocation.toString()) + .setFilter(filter) + .build(); + + System.out.println("List of models:"); + for (Model model : client.listModels(listModlesRequest).iterateAll()) { + // Display the model information. + System.out.println(String.format("Model name: %s", model.getName())); + System.out.println( + String.format( + "Model id: %s", model.getName().split("/")[model.getName().split("/").length - 1])); + System.out.println(String.format("Model display name: %s", model.getDisplayName())); + System.out.println("Image classification model metadata:"); + System.out.println( + "Tranning budget: " + model.getImageClassificationModelMetadata().getTrainBudget()); + System.out.println( + "Tranning cost: " + model.getImageClassificationModelMetadata().getTrainCost()); + System.out.println( + String.format( + "Stop reason: %s", model.getImageClassificationModelMetadata().getStopReason())); + System.out.println( + String.format( + "Base model id: %s", model.getImageClassificationModelMetadata().getBaseModelId())); + System.out.println("Model create time:"); + System.out.println(String.format("\tseconds: %s", model.getCreateTime().getSeconds())); + System.out.println(String.format("\tnanos: %s", model.getCreateTime().getNanos())); + System.out.println(String.format("Model deployment state: %s", model.getDeploymentState())); + } + } + // [END automl_vision_list_models] + + // [START automl_vision_get_model] + /** + * Demonstrates using the AutoML client to get model details. + * + * @param projectId the Id of the project. + * @param computeRegion the Region name. + * @param modelId the Id of the model. + * @throws IOException on Input/Output errors. + */ + public static void getModel(String projectId, String computeRegion, String modelId) + throws IOException { + AutoMlClient client = AutoMlClient.create(); + + // Get the full path of the model. + ModelName modelFullId = ModelName.of(projectId, computeRegion, modelId); + + // Get complete detail of the model. + Model model = client.getModel(modelFullId); + + // Display the model information. + System.out.println(String.format("Model name: %s", model.getName())); + System.out.println( + String.format( + "Model id: %s", model.getName().split("/")[model.getName().split("/").length - 1])); + System.out.println(String.format("Model display name: %s", model.getDisplayName())); + System.out.println("Image classification model metadata:"); + System.out.println( + "Tranning budget: " + model.getImageClassificationModelMetadata().getTrainBudget()); + System.out.println( + "Tranning cost:" + model.getImageClassificationModelMetadata().getTrainCost()); + System.out.println( + String.format( + "Stop reason: %s", model.getImageClassificationModelMetadata().getStopReason())); + System.out.println( + String.format( + "Base model id: %s", model.getImageClassificationModelMetadata().getBaseModelId())); + System.out.println("Model create time:"); + System.out.println(String.format("\tseconds: %s", model.getCreateTime().getSeconds())); + System.out.println(String.format("\tnanos: %s", model.getCreateTime().getNanos())); + System.out.println(String.format("Model deployment state: %s", model.getDeploymentState())); + } + // [END automl_vision_get_model] + + // [START automl_vision_list_model_evaluations] + /** + * Demonstrates using the AutoML client to list model evaluations. + * + * @param projectId the Id of the project. + * @param computeRegion the Region name. + * @param modelId the Id of the model. + * @param filter the Filter expression. + * @throws IOException on Input/Output errors. + */ + public static void listModelEvaluations( + String projectId, String computeRegion, String modelId, String filter) throws IOException { + AutoMlClient client = AutoMlClient.create(); + + // Get the full path of the model. + ModelName modelFullId = ModelName.of(projectId, computeRegion, modelId); + + // Create list model evaluations request + ListModelEvaluationsRequest modelEvaluationsrequest = + ListModelEvaluationsRequest.newBuilder() + .setParent(modelFullId.toString()) + .setFilter(filter) + .build(); + + System.out.println("List of model evaluations:"); + // List all the model evaluations in the model by applying filter. + for (ModelEvaluation element : + client.listModelEvaluations(modelEvaluationsrequest).iterateAll()) { + System.out.println(element); + } + } + // [END automl_vision_list_model_evaluations] + + // [START automl_vision_get_model_evaluation] + /** + * Demonstrates using the AutoML client to get model evaluations. + * + * @param projectId the Id of the project. + * @param computeRegion the Region name. + * @param modelId the Id of the model. + * @param modelEvaluationId the Id of your model evaluation. + * @throws IOException on Input/Output errors. + */ + public static void getModelEvaluation( + String projectId, String computeRegion, String modelId, String modelEvaluationId) + throws IOException { + AutoMlClient client = AutoMlClient.create(); + + // Get the full path of the model evaluation. + ModelEvaluationName modelEvaluationFullId = + ModelEvaluationName.of(projectId, computeRegion, modelId, modelEvaluationId); + // Perform the AutoML Model request to get Model Evaluation information + ModelEvaluation response = client.getModelEvaluation(modelEvaluationFullId); + + System.out.println(response); + } + // [END automl_vision_get_model_evaluation] + + // [START automl_vision_display_evaluation] + /** + * Demonstrates using the AutoML client to display model evaluation. + * + * @param projectId the Id of the project. + * @param computeRegion the Region name. + * @param modelId the Id of the model. + * @param filter the Filter expression. + * @throws IOException on Input/Output errors. + */ + public static void displayEvaluation( + String projectId, String computeRegion, String modelId, String filter) throws IOException { + AutoMlClient client = AutoMlClient.create(); + + // Get the full path of the model. + ModelName modelFullId = ModelName.of(projectId, computeRegion, modelId); + + // List all the model evaluations in the model by applying filter. + ListModelEvaluationsRequest modelEvaluationsrequest = + ListModelEvaluationsRequest.newBuilder() + .setParent(modelFullId.toString()) + .setFilter(filter) + .build(); + + // Iterate through the results. + String modelEvaluationId = ""; + for (ModelEvaluation element : + client.listModelEvaluations(modelEvaluationsrequest).iterateAll()) { + if (element.getAnnotationSpecId() != null) { + modelEvaluationId = element.getName().split("/")[element.getName().split("/").length - 1]; + } + } + + // Resource name for the model evaluation. + ModelEvaluationName modelEvaluationFullId = + ModelEvaluationName.of(projectId, computeRegion, modelId, modelEvaluationId); + + // Get a model evaluation. + ModelEvaluation modelEvaluation = client.getModelEvaluation(modelEvaluationFullId); + + ClassificationEvaluationMetrics classMetrics = + modelEvaluation.getClassificationEvaluationMetrics(); + List confidenceMetricsEntries = + classMetrics.getConfidenceMetricsEntryList(); + + // Showing model score based on threshold of 0.5 + for (ConfidenceMetricsEntry confidenceMetricsEntry : confidenceMetricsEntries) { + if (confidenceMetricsEntry.getConfidenceThreshold() == 0.5) { + System.out.println("Precision and recall are based on a score threshold of 0.5"); + System.out.println( + String.format("Model Precision: %.2f ", confidenceMetricsEntry.getPrecision() * 100) + + '%'); + System.out.println( + String.format("Model Recall: %.2f ", confidenceMetricsEntry.getRecall() * 100) + '%'); + System.out.println( + String.format("Model F1 score: %.2f ", confidenceMetricsEntry.getF1Score() * 100) + + '%'); + System.out.println( + String.format( + "Model Precision@1: %.2f ", confidenceMetricsEntry.getPrecisionAt1() * 100) + + '%'); + System.out.println( + String.format("Model Recall@1: %.2f ", confidenceMetricsEntry.getRecallAt1() * 100) + + '%'); + System.out.println( + String.format("Model F1 score@1: %.2f ", confidenceMetricsEntry.getF1ScoreAt1() * 100) + + '%'); + } + } + } + // [END automl_vision_display_evaluation] + + // [START automl_vision_delete_model] + /** + * Demonstrates using the AutoML client to delete a model. + * + * @param projectId the Id of the project. + * @param computeRegion the Region name. + * @param modelId the Id of the model. + * @throws Exception on AutoML Client errors + */ + public static void deleteModel(String projectId, String computeRegion, String modelId) + throws InterruptedException, ExecutionException, IOException { + AutoMlClient client = AutoMlClient.create(); + + // Get the full path of the model. + ModelName modelFullId = ModelName.of(projectId, computeRegion, modelId); + + // Delete a model. + Empty response = client.deleteModelAsync(modelFullId).get(); + + System.out.println("Model deletion started..."); + } + // [END automl_vision_delete_model] + + public static void main(String[] args) + throws IOException, InterruptedException, ExecutionException { + ModelApi modelApi = new ModelApi(); + modelApi.argsHelper(args, System.out); + } + + public static void argsHelper(String[] args, PrintStream out) + throws IOException, InterruptedException, ExecutionException { + ArgumentParser parser = + ArgumentParsers.newFor("ModelApi") + .build() + .defaultHelp(true) + .description("Model API operations."); + Subparsers subparsers = parser.addSubparsers().dest("command"); + + Subparser createModelParser = subparsers.addParser("create_model"); + createModelParser.addArgument("datasetId"); + createModelParser.addArgument("modelName"); + createModelParser.addArgument("trainBudget"); + + Subparser listModelParser = subparsers.addParser("list_models"); + listModelParser + .addArgument("filter") + .nargs("?") + .setDefault("imageClassificationModelMetadata:*"); + + Subparser getModelParser = subparsers.addParser("get_model"); + getModelParser.addArgument("modelId"); + + Subparser listModelEvaluationsParser = subparsers.addParser("list_model_evaluations"); + listModelEvaluationsParser.addArgument("modelId"); + listModelEvaluationsParser.addArgument("filter").nargs("?").setDefault(""); + + Subparser getModelEvaluationParser = subparsers.addParser("get_model_evaluation"); + getModelEvaluationParser.addArgument("modelId"); + getModelEvaluationParser.addArgument("modelEvaluationId"); + + Subparser displayEvaluationParser = subparsers.addParser("display_evaluation"); + displayEvaluationParser.addArgument("modelId"); + displayEvaluationParser.addArgument("filter").nargs("?").setDefault(""); + + Subparser deleteModelParser = subparsers.addParser("delete_model"); + deleteModelParser.addArgument("modelId"); + + Subparser getOperationStatusParser = subparsers.addParser("get_operation_status"); + getOperationStatusParser.addArgument("operationFullId"); + + String projectId = System.getenv("PROJECT_ID"); + String computeRegion = System.getenv("REGION_NAME"); + + Namespace ns = null; + try { + ns = parser.parseArgs(args); + if (ns.get("command").equals("create_model")) { + createModel( + projectId, + computeRegion, + ns.getString("datasetId"), + ns.getString("modelName"), + ns.getString("trainBudget")); + } + if (ns.get("command").equals("list_models")) { + listModels(projectId, computeRegion, ns.getString("filter")); + } + if (ns.get("command").equals("get_model")) { + getModel(projectId, computeRegion, ns.getString("modelId")); + } + if (ns.get("command").equals("list_model_evaluations")) { + listModelEvaluations( + projectId, computeRegion, ns.getString("modelId"), ns.getString("filter")); + } + if (ns.get("command").equals("get_model_evaluation")) { + getModelEvaluation( + projectId, computeRegion, ns.getString("modelId"), ns.getString("modelEvaluationId")); + } + if (ns.get("command").equals("display_evaluation")) { + displayEvaluation( + projectId, computeRegion, ns.getString("modelId"), ns.getString("filter")); + } + if (ns.get("command").equals("delete_model")) { + deleteModel(projectId, computeRegion, ns.getString("modelId")); + } + if (ns.get("command").equals("get_operation_status")) { + getOperationStatus(ns.getString("operationFullId")); + } + } catch (ArgumentParserException e) { + parser.handleError(e); + } catch (Exception e) { + System.out.println("Exception in Model create caught"); + } + } +} diff --git a/vision/automl/src/main/java/com/google/cloud/vision/samples/automl/PredictionApi.java b/vision/automl/src/main/java/com/google/cloud/vision/samples/automl/PredictionApi.java new file mode 100644 index 00000000000..a6070ad31d9 --- /dev/null +++ b/vision/automl/src/main/java/com/google/cloud/vision/samples/automl/PredictionApi.java @@ -0,0 +1,142 @@ +/* + * Copyright 2018 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * This application demonstrates how to perform basic operations on prediction + * with the Google AutoML Vision API. + * + * For more information, the documentation at + * https://cloud.google.com/vision/automl/docs. + */ + +package com.google.cloud.vision.samples.automl; + +// Imports the Google Cloud client library +import com.google.cloud.automl.v1beta1.AnnotationPayload; +import com.google.cloud.automl.v1beta1.ExamplePayload; +import com.google.cloud.automl.v1beta1.Image; +import com.google.cloud.automl.v1beta1.ModelName; +import com.google.cloud.automl.v1beta1.PredictResponse; +import com.google.cloud.automl.v1beta1.PredictionServiceClient; +import com.google.protobuf.ByteString; + +import java.io.IOException; +import java.io.PrintStream; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.HashMap; +import java.util.Map; + +import net.sourceforge.argparse4j.ArgumentParsers; +import net.sourceforge.argparse4j.inf.ArgumentParser; +import net.sourceforge.argparse4j.inf.ArgumentParserException; +import net.sourceforge.argparse4j.inf.Namespace; +import net.sourceforge.argparse4j.inf.Subparser; +import net.sourceforge.argparse4j.inf.Subparsers; + +/** + * Google Cloud AutoML Vision API sample application. Example usage: mvn package exec:java + * -Dexec.mainClass ='com.google.cloud.vision.samples.automl.PredictionApi' -Dexec.args='predict + * [modelId] [path-to-image] [scoreThreshold]' + */ +public class PredictionApi { + + // [START automl_vision_predict] + + /** + * Demonstrates using the AutoML client to predict an image. + * + * @param projectId the Id of the project. + * @param computeRegion the Region name. + * @param modelId the Id of the model which will be used for text classification. + * @param filePath the Local text file path of the content to be classified. + * @param scoreThreshold the Confidence score. Only classifications with confidence score above + * scoreThreshold are displayed. + * @throws IOException on Input/Output errors. + */ + public static void predict( + String projectId, + String computeRegion, + String modelId, + String filePath, + String scoreThreshold) + throws IOException { + + // Create client for prediction service. + PredictionServiceClient predictionClient = PredictionServiceClient.create(); + + // Get the full path of the model. + ModelName name = ModelName.of(projectId, computeRegion, modelId); + + // Read the image and assign to payload. + ByteString content = ByteString.copyFrom(Files.readAllBytes(Paths.get(filePath))); + Image image = Image.newBuilder().setImageBytes(content).build(); + ExamplePayload examplePayload = ExamplePayload.newBuilder().setImage(image).build(); + + // Additional parameters that can be provided for prediction e.g. Score Threshold + Map params = new HashMap<>(); + if (scoreThreshold != null) { + params.put("scoreThreshold", scoreThreshold); + } + // Perform the AutoML Prediction request + PredictResponse response = predictionClient.predict(name, examplePayload, params); + + System.out.println("Prediction results:"); + for (AnnotationPayload annotationPayload : response.getPayloadList()) { + System.out.println("Predicted class name :" + annotationPayload.getDisplayName()); + System.out.println( + "Predicted class score :" + annotationPayload.getClassification().getScore()); + } + } + // [END automl_vision_predict] + + public static void main(String[] args) throws IOException { + PredictionApi predictionApi = new PredictionApi(); + predictionApi.argsHelper(args, System.out); + } + + public static void argsHelper(String[] args, PrintStream out) throws IOException { + ArgumentParser parser = + ArgumentParsers.newFor("PredictionApi") + .build() + .defaultHelp(true) + .description("Prediction API Operation"); + Subparsers subparsers = parser.addSubparsers().dest("command"); + + Subparser predictParser = subparsers.addParser("predict"); + predictParser.addArgument("modelId"); + predictParser.addArgument("filePath"); + predictParser.addArgument("scoreThreshold").nargs("?").type(String.class).setDefault(""); + + String projectId = System.getenv("PROJECT_ID"); + String computeRegion = System.getenv("REGION_NAME"); + + Namespace ns = null; + try { + ns = parser.parseArgs(args); + if (ns.get("command").equals("predict")) { + predict( + projectId, + computeRegion, + ns.getString("modelId"), + ns.getString("filePath"), + ns.getString("scoreThreshold")); + } + } catch (ArgumentParserException e) { + parser.handleError(e); + } + } +} diff --git a/vision/automl/src/test/java/com/google/cloud/vision/samples/automl/DatasetApiIT.java b/vision/automl/src/test/java/com/google/cloud/vision/samples/automl/DatasetApiIT.java new file mode 100644 index 00000000000..1a45326169a --- /dev/null +++ b/vision/automl/src/test/java/com/google/cloud/vision/samples/automl/DatasetApiIT.java @@ -0,0 +1,107 @@ +/* + * Copyright 2018 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.vision.samples.automl; + +import static com.google.common.truth.Truth.assertThat; +import static java.lang.Boolean.FALSE; + +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Tests for Automl vision "Dataset API" sample. */ +@RunWith(JUnit4.class) +@SuppressWarnings("checkstyle:abbreviationaswordinname") +public class DatasetApiIT { + + private static final String PROJECT_ID = "java-docs-samples-testing"; + private static final String BUCKET = PROJECT_ID + "-vcm"; + private static final String COMPUTE_REGION = "us-central1"; + private static final String DATASET_NAME = "test_dataset"; + private ByteArrayOutputStream bout; + private PrintStream out; + private DatasetApi app; + private String datasetId; + + @Before + public void setUp() { + bout = new ByteArrayOutputStream(); + out = new PrintStream(bout); + System.setOut(out); + } + + @After + public void tearDown() { + System.setOut(null); + } + + @Test + public void testCreateImportDeleteDataset() throws Exception { + // Act + DatasetApi.createDataset(PROJECT_ID, COMPUTE_REGION, DATASET_NAME, FALSE); + + // Assert + String got = bout.toString(); + datasetId = + bout.toString() + .split("\n")[0] + .split("/")[(bout.toString().split("\n")[0]).split("/").length - 1]; + assertThat(got).contains("Dataset id:"); + + // Act + DatasetApi.importData( + PROJECT_ID, COMPUTE_REGION, datasetId, "gs://" + BUCKET + "/flower_traindata.csv"); + + // Assert + got = bout.toString(); + assertThat(got).contains("Dataset id:"); + + // Act + DatasetApi.deleteDataset(PROJECT_ID, COMPUTE_REGION, datasetId); + + // Assert + got = bout.toString(); + assertThat(got).contains("Dataset deleted."); + } + + @Test + public void testListGetDatasets() throws Exception { + // Act + DatasetApi.listDatasets(PROJECT_ID, COMPUTE_REGION, "imageClassificationDatasetMetadata:*"); + + // Assert + String got = bout.toString(); + datasetId = + bout.toString() + .split("\n")[1] + .split("/")[(bout.toString().split("\n")[1]).split("/").length - 1]; + assertThat(got).contains("Dataset id:"); + + // Act + DatasetApi.getDataset(PROJECT_ID, COMPUTE_REGION, datasetId); + + // Assert + got = bout.toString(); + + assertThat(got).contains("Dataset id:"); + } +} diff --git a/vision/automl/src/test/java/com/google/cloud/vision/samples/automl/ModelApiIT.java b/vision/automl/src/test/java/com/google/cloud/vision/samples/automl/ModelApiIT.java new file mode 100644 index 00000000000..9dae82604a3 --- /dev/null +++ b/vision/automl/src/test/java/com/google/cloud/vision/samples/automl/ModelApiIT.java @@ -0,0 +1,88 @@ +/* + * Copyright 2018 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.vision.samples.automl; + +import static com.google.common.truth.Truth.assertThat; + +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Tests for vision "Model API" sample. */ +@RunWith(JUnit4.class) +@SuppressWarnings("checkstyle:abbreviationaswordinname") +public class ModelApiIT { + private static final String PROJECT_ID = "java-docs-samples-testing"; + private static final String COMPUTE_REGION = "us-central1"; + private ByteArrayOutputStream bout; + private PrintStream out; + private ModelApi app; + private String modelId; + private String modelEvaluationId; + + @Before + public void setUp() { + + bout = new ByteArrayOutputStream(); + out = new PrintStream(bout); + System.setOut(out); + } + + @After + public void tearDown() { + System.setOut(null); + } + + @Test + public void testModelApi() throws Exception { + // Act + ModelApi.listModels(PROJECT_ID, COMPUTE_REGION, ""); + + // Assert + String got = bout.toString(); + modelId = got.split("\n")[1].split("/")[got.split("\n")[1].split("/").length - 1]; + assertThat(got).contains("Model id:"); + + // Act + ModelApi.getModel(PROJECT_ID, COMPUTE_REGION, modelId); + + // Assert + got = bout.toString(); + assertThat(got).contains("Model name:"); + + // Act + ModelApi.listModelEvaluations(PROJECT_ID, COMPUTE_REGION, modelId, ""); + + // Assert + got = bout.toString(); + modelEvaluationId = got.split("List of model evaluations:")[1].split("\"")[1].split("/")[7]; + assertThat(got).contains("name:"); + + // Act + ModelApi.getModelEvaluation(PROJECT_ID, COMPUTE_REGION, modelId, modelEvaluationId); + + // Assert + got = bout.toString(); + assertThat(got).contains("name:"); + + } +} diff --git a/vision/automl/src/test/java/com/google/cloud/vision/samples/automl/PredictionApiIT.java b/vision/automl/src/test/java/com/google/cloud/vision/samples/automl/PredictionApiIT.java new file mode 100644 index 00000000000..db0e0401a01 --- /dev/null +++ b/vision/automl/src/test/java/com/google/cloud/vision/samples/automl/PredictionApiIT.java @@ -0,0 +1,64 @@ +/* + * Copyright 2018 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.vision.samples.automl; + +import static com.google.common.truth.Truth.assertThat; + +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Tests for vision "PredictionAPI" sample. */ +@RunWith(JUnit4.class) +@SuppressWarnings("checkstyle:abbreviationaswordinname") +public class PredictionApiIT { + private static final String COMPUTE_REGION = "us-central1"; + private static final String PROJECT_ID = "java-docs-samples-testing"; + private static final String modelId = "620201829169141520"; + private static final String filePath = "./resources/dandelion.jpg"; + private static final String scoreThreshold = "0.7"; + private ByteArrayOutputStream bout; + private PrintStream out; + private PredictionApi app; + + @Before + public void setUp() { + bout = new ByteArrayOutputStream(); + out = new PrintStream(bout); + System.setOut(out); + } + + @After + public void tearDown() { + System.setOut(null); + } + + @Test + public void testPredict() throws Exception { + // Act + PredictionApi.predict(PROJECT_ID, COMPUTE_REGION, modelId, filePath, scoreThreshold); + + // Assert + String got = bout.toString(); + assertThat(got).contains("dandelion"); + } +} From 96bdd4902f3b54c8d78ea941853e0eec24e42f71 Mon Sep 17 00:00:00 2001 From: nirupa-kumar Date: Sun, 22 Jul 2018 08:52:49 -0700 Subject: [PATCH 03/15] Vision AutoML updates + Translate AutoML --- translate/automl/README.md | 86 ++++++++++ translate/automl/pom.xml | 153 ++++++++++++++++++ translate/automl/resources/input.txt | 1 + .../cloud/vision/samples/automl/ModelApi.java | 22 ++- .../vision/samples/automl/PredictionApi.java | 2 +- 5 files changed, 251 insertions(+), 13 deletions(-) create mode 100644 translate/automl/README.md create mode 100644 translate/automl/pom.xml create mode 100644 translate/automl/resources/input.txt diff --git a/translate/automl/README.md b/translate/automl/README.md new file mode 100644 index 00000000000..83ccd3dc95e --- /dev/null +++ b/translate/automl/README.md @@ -0,0 +1,86 @@ +# AutoML Translate Sample + + +Open in Cloud Shell + +[Google Cloud Translate API][translate] provides feature AutoML. +This API is part of the larger collection of Cloud Machine Learning APIs. + +This sample Java application demonstrates how to access the Cloud Translate AutoML API +using the [Google Cloud Client Library for Java][google-cloud-java]. + +## Set the environment variables + +PROJECT_ID = [Id of the project] +REGION_NAME = [Region name] + +## Build the sample + +Install [Maven](http://maven.apache.org/). + +Build your project with: + +``` +mvn clean package +``` + +### Dataset API + +#### Create a new dataset +``` +mvn exec:java -Dexec.mainClass="com.google.cloud.translate.samples.DatasetApi" -Dexec.args="create_dataset test_dataset" +``` + +#### List datasets +``` +mvn exec:java -Dexec.mainClass="com.google.cloud.translate.samples.DatasetApi" -Dexec.args="list_datasets" +``` + +#### Get dataset +``` +mvn exec:java -Dexec.mainClass="com.google.cloud.translate.samples.DatasetApi" -Dexec.args="get_dataset [dataset-id]" +``` + +#### Import data +``` +mvn exec:java -Dexec.mainClass="com.google.cloud.translate.samples.DatasetApi" -Dexec.args="import_data gs://java-docs-samples-testing/flower_traindata.csv" +``` + +### Model API + +#### Create Model +``` +mvn exec:java -Dexec.mainClass="com.google.cloud.translate.samples.ModelApi" -Dexec.args="create_model test_model" +``` + +#### List Models +``` +mvn exec:java -Dexec.mainClass="com.google.cloud.translate.samples.ModelApi" -Dexec.args="list_models" +``` + +#### Get Model +``` +mvn exec:java -Dexec.mainClass="com.google.cloud.translate.samples.ModelApi" -Dexec.args="get_model [model-id]" +``` + +#### List Model Evaluations +``` +mvn exec:java -Dexec.mainClass="com.google.cloud.translate.samples.ModelApi" -Dexec.args="list_model_evaluation [model-id]" +``` + +#### Get Model Evaluation +``` +mvn exec:java -Dexec.mainClass="com.google.cloud.translate.samples.ModelApi" -Dexec.args="get_model_evaluation [model-id] [model-evaluation-id]" +``` + +#### Delete Model +``` +mvn exec:java-Dexec.mainClass="com.google.cloud.translate.samples.ModelApi" -Dexec.args="delete_model [model-id]" +``` +### Predict API + +``` +mvn exec:java -Dexec.mainClass="com.google.cloud.translate.samples.PredictApi" -Dexec.args="predict [model-id] ./resources/dandelion.jpg 0.7" +``` + + diff --git a/translate/automl/pom.xml b/translate/automl/pom.xml new file mode 100644 index 00000000000..488081b3fe2 --- /dev/null +++ b/translate/automl/pom.xml @@ -0,0 +1,153 @@ + + + 4.0.0 + com.google.cloud.translate.automl + translate-automl + jar + + + + com.google.cloud.samples + shared-configuration + 1.0.9 + + + + 1.8 + 1.8 + UTF-8 + + + + + + com.google.cloud + google-cloud-automl + 0.55.0-beta + + + net.sourceforge.argparse4j + argparse4j + 0.8.1 + + + + + + junit + junit + 4.12 + test + + + com.google.truth + truth + 0.41 + test + + + + + + DatasetApi + + + DatasetApi + + + + + + org.codehaus.mojo + exec-maven-plugin + 1.6.0 + + + + java + + + + + com.google.cloud.translate.automl.DatasetApi + false + + + + + + + ModelApi + + + ModelApi + + + + + + org.codehaus.mojo + exec-maven-plugin + 1.6.0 + + + + java + + + + + com.google.cloud.translate.automl.ModelApi + false + + + + + + + PredictionApi + + + PredictionApi + + + + + + org.codehaus.mojo + exec-maven-plugin + 1.6.0 + + + + java + + + + + com.google.cloud.translate.automl.PredictionApi + false + + + + + + + diff --git a/translate/automl/resources/input.txt b/translate/automl/resources/input.txt new file mode 100644 index 00000000000..5aecd6590fc --- /dev/null +++ b/translate/automl/resources/input.txt @@ -0,0 +1 @@ +Tell me how this ends \ No newline at end of file diff --git a/vision/automl/src/main/java/com/google/cloud/vision/samples/automl/ModelApi.java b/vision/automl/src/main/java/com/google/cloud/vision/samples/automl/ModelApi.java index bcf913e1c4d..22e653cdd0f 100644 --- a/vision/automl/src/main/java/com/google/cloud/vision/samples/automl/ModelApi.java +++ b/vision/automl/src/main/java/com/google/cloud/vision/samples/automl/ModelApi.java @@ -37,7 +37,7 @@ import java.io.IOException; import java.io.PrintStream; import java.util.List; -import java.util.concurrent.ExecutionException; + import net.sourceforge.argparse4j.ArgumentParsers; import net.sourceforge.argparse4j.inf.ArgumentParser; import net.sourceforge.argparse4j.inf.ArgumentParserException; @@ -106,7 +106,7 @@ public static void createModel( /** * Demonstrates using the AutoML client to get operation status. * - * @param operationFullId : Full name of a operation. For example, the name of your operation is + * @param operationFullId the complete name of a operation. For example, the name of your operation is * projects/[projectId]/locations/us-central1/operations/[operationId]. * @throws IOException on Input/Output errors. */ @@ -124,8 +124,8 @@ public static void getOperationStatus(String operationFullId) throws IOException /** * Demonstrates using the AutoML client to list all models. * - * @param projectId - Id of the project. - * @param computeRegion - Region name. + * @param projectId the Id of the project. + * @param computeRegion the Region name. * @param filter - Filter expression. * @throws IOException on Input/Output errors. */ @@ -137,14 +137,14 @@ public static void listModels(String projectId, String computeRegion, String fil LocationName projectLocation = LocationName.of(projectId, computeRegion); // Create list models request - ListModelsRequest listModlesRequest = + ListModelsRequest listModelsRequest = ListModelsRequest.newBuilder() .setParent(projectLocation.toString()) .setFilter(filter) .build(); System.out.println("List of models:"); - for (Model model : client.listModels(listModlesRequest).iterateAll()) { + for (Model model : client.listModels(listModelsRequest).iterateAll()) { // Display the model information. System.out.println(String.format("Model name: %s", model.getName())); System.out.println( @@ -278,7 +278,7 @@ public static void getModelEvaluation( * @param projectId the Id of the project. * @param computeRegion the Region name. * @param modelId the Id of the model. - * @param filter the Filter expression. + * @param filter the filter expression. * @throws IOException on Input/Output errors. */ public static void displayEvaluation( @@ -353,7 +353,7 @@ public static void displayEvaluation( * @throws Exception on AutoML Client errors */ public static void deleteModel(String projectId, String computeRegion, String modelId) - throws InterruptedException, ExecutionException, IOException { + throws Exception { AutoMlClient client = AutoMlClient.create(); // Get the full path of the model. @@ -367,13 +367,13 @@ public static void deleteModel(String projectId, String computeRegion, String mo // [END automl_vision_delete_model] public static void main(String[] args) - throws IOException, InterruptedException, ExecutionException { + throws Exception { ModelApi modelApi = new ModelApi(); modelApi.argsHelper(args, System.out); } public static void argsHelper(String[] args, PrintStream out) - throws IOException, InterruptedException, ExecutionException { + throws Exception { ArgumentParser parser = ArgumentParsers.newFor("ModelApi") .build() @@ -453,8 +453,6 @@ public static void argsHelper(String[] args, PrintStream out) } } catch (ArgumentParserException e) { parser.handleError(e); - } catch (Exception e) { - System.out.println("Exception in Model create caught"); } } } diff --git a/vision/automl/src/main/java/com/google/cloud/vision/samples/automl/PredictionApi.java b/vision/automl/src/main/java/com/google/cloud/vision/samples/automl/PredictionApi.java index a6070ad31d9..a76c3f40caf 100644 --- a/vision/automl/src/main/java/com/google/cloud/vision/samples/automl/PredictionApi.java +++ b/vision/automl/src/main/java/com/google/cloud/vision/samples/automl/PredictionApi.java @@ -75,7 +75,7 @@ public static void predict( String scoreThreshold) throws IOException { - // Create client for prediction service. + // Instantiate client for prediction service. PredictionServiceClient predictionClient = PredictionServiceClient.create(); // Get the full path of the model. From 0efcd8beaac14a85465753e0a630b7b3c776b31c Mon Sep 17 00:00:00 2001 From: nirupa-kumar Date: Sun, 22 Jul 2018 08:57:47 -0700 Subject: [PATCH 04/15] Translate README fixes --- translate/automl/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/translate/automl/README.md b/translate/automl/README.md index 83ccd3dc95e..e2248a17de7 100644 --- a/translate/automl/README.md +++ b/translate/automl/README.md @@ -43,7 +43,7 @@ mvn exec:java -Dexec.mainClass="com.google.cloud.translate.samples.DatasetApi" - #### Import data ``` -mvn exec:java -Dexec.mainClass="com.google.cloud.translate.samples.DatasetApi" -Dexec.args="import_data gs://java-docs-samples-testing/flower_traindata.csv" +mvn exec:java -Dexec.mainClass="com.google.cloud.translate.samples.DatasetApi" -Dexec.args="import_data gs://java-docs-samples-testing/en-ja.csv" ``` ### Model API @@ -80,7 +80,7 @@ mvn exec:java-Dexec.mainClass="com.google.cloud.translate.samples.ModelApi" -Dex ### Predict API ``` -mvn exec:java -Dexec.mainClass="com.google.cloud.translate.samples.PredictApi" -Dexec.args="predict [model-id] ./resources/dandelion.jpg 0.7" +mvn exec:java -Dexec.mainClass="com.google.cloud.translate.samples.PredictApi" -Dexec.args="predict [model-id] ./resources/input.txt" ``` From 9150076c37c2f8ca90b6e70acc60f105df1f6baa Mon Sep 17 00:00:00 2001 From: nirupa-kumar Date: Sun, 22 Jul 2018 09:09:24 -0700 Subject: [PATCH 05/15] Fixing Kokoro failure issue --- .../google/cloud/vision/samples/automl/ModelApi.java | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/vision/automl/src/main/java/com/google/cloud/vision/samples/automl/ModelApi.java b/vision/automl/src/main/java/com/google/cloud/vision/samples/automl/ModelApi.java index 22e653cdd0f..a0f6c7b002c 100644 --- a/vision/automl/src/main/java/com/google/cloud/vision/samples/automl/ModelApi.java +++ b/vision/automl/src/main/java/com/google/cloud/vision/samples/automl/ModelApi.java @@ -106,8 +106,8 @@ public static void createModel( /** * Demonstrates using the AutoML client to get operation status. * - * @param operationFullId the complete name of a operation. For example, the name of your operation is - * projects/[projectId]/locations/us-central1/operations/[operationId]. + * @param operationFullId the complete name of a operation. For example, the name of your + * operation is projects/[projectId]/locations/us-central1/operations/[operationId]. * @throws IOException on Input/Output errors. */ public static void getOperationStatus(String operationFullId) throws IOException { @@ -366,14 +366,12 @@ public static void deleteModel(String projectId, String computeRegion, String mo } // [END automl_vision_delete_model] - public static void main(String[] args) - throws Exception { + public static void main(String[] args) throws Exception { ModelApi modelApi = new ModelApi(); modelApi.argsHelper(args, System.out); } - public static void argsHelper(String[] args, PrintStream out) - throws Exception { + public static void argsHelper(String[] args, PrintStream out) throws Exception { ArgumentParser parser = ArgumentParsers.newFor("ModelApi") .build() From 3c7d7aa74f5986665cd063d21498d7d3e1e4d594 Mon Sep 17 00:00:00 2001 From: nirupa-kumar Date: Sun, 22 Jul 2018 15:18:24 -0700 Subject: [PATCH 06/15] Language AutoML --- language/automl/README.md | 88 ++++ language/automl/pom.xml | 154 +++++++ language/automl/resources/input.txt | 1 + .../cloud/language/samples/DatasetApi.java | 349 ++++++++++++++ .../cloud/language/samples/ModelApi.java | 428 ++++++++++++++++++ .../cloud/language/samples/PredictionApi.java | 121 +++++ .../cloud/language/samples/DatasetApiIT.java | 108 +++++ .../cloud/language/samples/ModelApiIT.java | 92 ++++ .../language/samples/PredictionApiIT.java | 63 +++ 9 files changed, 1404 insertions(+) create mode 100644 language/automl/README.md create mode 100644 language/automl/pom.xml create mode 100644 language/automl/resources/input.txt create mode 100644 language/automl/src/main/java/com/google/cloud/language/samples/DatasetApi.java create mode 100644 language/automl/src/main/java/com/google/cloud/language/samples/ModelApi.java create mode 100644 language/automl/src/main/java/com/google/cloud/language/samples/PredictionApi.java create mode 100644 language/automl/src/test/java/com/google/cloud/language/samples/DatasetApiIT.java create mode 100644 language/automl/src/test/java/com/google/cloud/language/samples/ModelApiIT.java create mode 100644 language/automl/src/test/java/com/google/cloud/language/samples/PredictionApiIT.java diff --git a/language/automl/README.md b/language/automl/README.md new file mode 100644 index 00000000000..97e17bee204 --- /dev/null +++ b/language/automl/README.md @@ -0,0 +1,88 @@ +# AutoML Sample + + +Open in Cloud Shell + +[Google Cloud Natural Language API][language] provides feature detection for images. +This API is part of the larger collection of Cloud Machine Learning APIs. + +This sample Java application demonstrates how to access the Cloud Natural Language AutoML API +using the [Google Cloud Client Library for Java][google-cloud-java]. + +[language]: https://cloud.google.com/language/docs/ +[google-cloud-java]: https://github.com/GoogleCloudPlatform/google-cloud-java + +## Set the environment variables + +PROJECT_ID = [Id of the project] +REGION_NAME = [Region name] + +## Build the sample + +Install [Maven](http://maven.apache.org/). + +Build your project with: + +``` +mvn clean package +``` + +### Dataset API + +#### Create a new dataset +``` +mvn exec:java -Dexec.mainClass="com.google.cloud.language.samples.DatasetApi" -Dexec.args="create_dataset test_dataset" +``` + +#### List datasets +``` +mvn exec:java -Dexec.mainClass="com.google.cloud.language.samples.DatasetApi" -Dexec.args="list_datasets" +``` + +#### Get dataset +``` +mvn exec:java -Dexec.mainClass="com.google.cloud.language.samples.DatasetApi" -Dexec.args="get_dataset [dataset-id]" +``` + +#### Import data +``` +mvn exec:java -Dexec.mainClass="com.google.cloud.language.samples.DatasetApi" -Dexec.args="import_data gs://java-docs-samples-testing/happiness.csv" +``` + +### Model API + +#### Create Model +``` +mvn exec:java -Dexec.mainClass="com.google.cloud.language.samples.ModelApi" -Dexec.args="create_model test_model" +``` + +#### List Models +``` +mvn exec:java -Dexec.mainClass="com.google.cloud.language.samples.ModelApi" -Dexec.args="list_models" +``` + +#### Get Model +``` +mvn exec:java -Dexec.mainClass="com.google.cloud.language.samples.ModelApi" -Dexec.args="get_model [model-id]" +``` + +#### List Model Evaluations +``` +mvn exec:java -Dexec.mainClass="com.google.cloud.language.samples.ModelApi" -Dexec.args="list_model_evaluation [model-id]" +``` + +#### Get Model Evaluation +``` +mvn exec:java -Dexec.mainClass="com.google.cloud.language.samples.ModelApi" -Dexec.args="get_model_evaluation [model-id] [model-evaluation-id]" +``` + +#### Delete Model +``` +mvn exec:java-Dexec.mainClass="com.google.cloud.language.samples.ModelApi" -Dexec.args="delete_model [model-id]" +``` +### Predict API + +``` +mvn exec:java -Dexec.mainClass="com.google.cloud.language.samples.PredictApi" -Dexec.args="predict [model-id] ./resources/input.txt" +``` + diff --git a/language/automl/pom.xml b/language/automl/pom.xml new file mode 100644 index 00000000000..66f481dcf40 --- /dev/null +++ b/language/automl/pom.xml @@ -0,0 +1,154 @@ + + + 4.0.0 + com.example.vision + language-automl + jar + + + + com.google.cloud.samples + shared-configuration + 1.0.9 + + + + 1.8 + 1.8 + UTF-8 + + + + + + com.google.cloud + google-cloud-automl + 0.55.1-beta + + + net.sourceforge.argparse4j + argparse4j + 0.8.1 + + + + + + junit + junit + 4.12 + test + + + + com.google.truth + truth + 0.41 + test + + + + + + DatasetApi + + + DatasetApi + + + + + + org.codehaus.mojo + exec-maven-plugin + 1.6.0 + + + + java + + + + + com.google.cloud.language.samples.DatasetApi + false + + + + + + + ModelApi + + + ModelApi + + + + + + org.codehaus.mojo + exec-maven-plugin + 1.6.0 + + + + java + + + + + com.google.cloud.language.samples.ModelApi + false + + + + + + + PredictApi + + + PredictApi + + + + + + org.codehaus.mojo + exec-maven-plugin + 1.6.0 + + + + java + + + + + com.google.cloud.language.samples.PredictionApi + false + + + + + + + diff --git a/language/automl/resources/input.txt b/language/automl/resources/input.txt new file mode 100644 index 00000000000..a711059ba58 --- /dev/null +++ b/language/automl/resources/input.txt @@ -0,0 +1 @@ +creamy, full-flavored, nutty, sweet \ No newline at end of file diff --git a/language/automl/src/main/java/com/google/cloud/language/samples/DatasetApi.java b/language/automl/src/main/java/com/google/cloud/language/samples/DatasetApi.java new file mode 100644 index 00000000000..d7aa610f589 --- /dev/null +++ b/language/automl/src/main/java/com/google/cloud/language/samples/DatasetApi.java @@ -0,0 +1,349 @@ +/* + * Copyright 2018 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.language.samples; + +// Imports the Google Cloud client library +import com.google.cloud.automl.v1beta1.AutoMlClient; +import com.google.cloud.automl.v1beta1.ClassificationProto.ClassificationType; +import com.google.cloud.automl.v1beta1.Dataset; +import com.google.cloud.automl.v1beta1.DatasetName; +import com.google.cloud.automl.v1beta1.GcsDestination; +import com.google.cloud.automl.v1beta1.GcsSource; +import com.google.cloud.automl.v1beta1.InputConfig; +import com.google.cloud.automl.v1beta1.ListDatasetsRequest; +import com.google.cloud.automl.v1beta1.LocationName; +import com.google.cloud.automl.v1beta1.OutputConfig; +import com.google.cloud.automl.v1beta1.TextClassificationDatasetMetadata; +import com.google.protobuf.Empty; + +import java.io.IOException; +import java.io.PrintStream; + +import net.sourceforge.argparse4j.ArgumentParsers; +import net.sourceforge.argparse4j.inf.ArgumentParser; +import net.sourceforge.argparse4j.inf.ArgumentParserException; +import net.sourceforge.argparse4j.inf.Namespace; +import net.sourceforge.argparse4j.inf.Subparser; +import net.sourceforge.argparse4j.inf.Subparsers; + +/** + * Google Cloud AutoML Natural Language API sample application. Example usage: mvn package exec:java + * -Dexec.mainClass ='com.google.cloud.vision.samples.automl.DatasetAPI' -Dexec.args='create_dataset + * test_dataset' + */ +public class DatasetApi { + + // [START automl_natural_language_create_dataset] + /** + * Demonstrates using the AutoML client to create a dataset + * + * @param projectId the Google Cloud Project ID. + * @param computeRegion the Region name. (e.g., "us-central1") + * @param datasetName the name of the dataset to be created. + * @param multiLabel the type of classification problem. Set to FALSE by default. False - + * MULTICLASS , True - MULTILABEL + * @throws IOException on Input/Output errors. + */ + public static void createDataset( + String projectId, String computeRegion, String datasetName, Boolean multiLabel) + throws IOException { + // Instantiates a client + AutoMlClient client = AutoMlClient.create(); + + // A resource that represents Google Cloud Platform location. + LocationName projectLocation = LocationName.of(projectId, computeRegion); + + // Classification type assigned based on multilabel value. + ClassificationType classificationType = + multiLabel ? ClassificationType.MULTILABEL : ClassificationType.MULTICLASS; + + // Specify the text classification type for the dataset. + TextClassificationDatasetMetadata textClassificationDatasetMetadata = + TextClassificationDatasetMetadata.newBuilder() + .setClassificationType(classificationType) + .build(); + + // Set dataset name and dataset metadata. + Dataset myDataset = + Dataset.newBuilder() + .setDisplayName(datasetName) + .setTextClassificationDatasetMetadata(textClassificationDatasetMetadata) + .build(); + + // Create a dataset with the dataset metadata in the region. + Dataset dataset = client.createDataset(projectLocation, myDataset); + + // Display the dataset information. + System.out.println(String.format("Dataset name: %s", dataset.getName())); + System.out.println( + String.format( + "Dataset id: %s", + dataset.getName().split("/")[dataset.getName().split("/").length - 1])); + System.out.println(String.format("Dataset display name: %s", dataset.getDisplayName())); + System.out.println("Text classification dataset metadata:"); + System.out.print(String.format("\t%s", dataset.getTextClassificationDatasetMetadata())); + System.out.println(String.format("Dataset example count: %d", dataset.getExampleCount())); + System.out.println("Dataset create time:"); + System.out.println(String.format("\tseconds: %s", dataset.getCreateTime().getSeconds())); + System.out.println(String.format("\tnanos: %s", dataset.getCreateTime().getNanos())); + } + // [END automl_natural_language_create_dataset] + + // [START automl_natural_language_list_datasets] + /** + * Demonstrates using the AutoML client to list all datasets. + * + * @param projectId the Id of the project. + * @param computeRegion the Region name. + * @param filter the Filter expression. + * @throws IOException on Input/Output errors. + */ + public static void listDatasets(String projectId, String computeRegion, String filter) + throws IOException { + // Instantiates a client + AutoMlClient client = AutoMlClient.create(); + + // A resource that represents Google Cloud Platform location. + LocationName projectLocation = LocationName.of(projectId, computeRegion); + + // Build the List datasets request + ListDatasetsRequest request = + ListDatasetsRequest.newBuilder() + .setParent(projectLocation.toString()) + .setFilter(filter) + .build(); + + // List all the datasets available in the region by applying filter. + System.out.println("List of datasets:"); + for (Dataset dataset : client.listDatasets(request).iterateAll()) { + // Display the dataset information. + System.out.println(String.format("\nDataset name: %s", dataset.getName())); + System.out.println( + String.format( + "Dataset id: %s", + dataset.getName().split("/")[dataset.getName().split("/").length - 1])); + System.out.println(String.format("Dataset display name: %s", dataset.getDisplayName())); + System.out.println("Text classification dataset metadata:"); + System.out.print(String.format("\t%s", dataset.getTextClassificationDatasetMetadata())); + System.out.println(String.format("Dataset example count: %d", dataset.getExampleCount())); + System.out.println("Dataset create time:"); + System.out.println(String.format("\tseconds: %s", dataset.getCreateTime().getSeconds())); + System.out.println(String.format("\tnanos: %s", dataset.getCreateTime().getNanos())); + } + } + // [END automl_natural_language_list_datasets] + + // [START automl_natural_language_get_dataset] + /** + * Demonstrates using the AutoML client to get a dataset by ID. + * + * @param projectId the Id of the project. + * @param computeRegion the Region name. + * @param datasetId the Id of the dataset. + * @throws IOException on Input/Output errors. + */ + public static void getDataset(String projectId, String computeRegion, String datasetId) + throws IOException { + // Instantiates a client + AutoMlClient client = AutoMlClient.create(); + + // Get the complete path of the dataset. + DatasetName datasetFullId = DatasetName.of(projectId, computeRegion, datasetId); + + // Get all the information about a given dataset. + Dataset dataset = client.getDataset(datasetFullId); + + // Display the dataset information. + System.out.println(String.format("Dataset name: %s", dataset.getName())); + System.out.println( + String.format( + "Dataset id: %s", + dataset.getName().split("/")[dataset.getName().split("/").length - 1])); + System.out.println(String.format("Dataset display name: %s", dataset.getDisplayName())); + System.out.println("Text classification dataset metadata:"); + System.out.print(String.format("\t%s", dataset.getTextClassificationDatasetMetadata())); + System.out.println(String.format("Dataset example count: %d", dataset.getExampleCount())); + System.out.println("Dataset create time:"); + System.out.println(String.format("\tseconds: %s", dataset.getCreateTime().getSeconds())); + System.out.println(String.format("\tnanos: %s", dataset.getCreateTime().getNanos())); + } + // [END automl_natural_language_get_dataset] + + // [START automl_natural_language_import_data] + /** + * Import labeled items. + * + * @param projectId - Id of the project. + * @param computeRegion - Region name. + * @param datasetId - Id of the dataset into which the training content are to be imported. + * @param path - Google Cloud Storage URIs. Target files must be in AutoML Natural Language CSV + * format. + * @throws Exception on AutoML Client errors + */ + public static void importData( + String projectId, String computeRegion, String datasetId, String path) throws Exception { + // Instantiates a client + AutoMlClient client = AutoMlClient.create(); + + // Get the complete path of the dataset. + DatasetName datasetFullId = DatasetName.of(projectId, computeRegion, datasetId); + + GcsSource.Builder gcsSource = GcsSource.newBuilder(); + + // Get multiple training data files to be imported + String[] inputUris = path.split(","); + for (String inputUri : inputUris) { + gcsSource.addInputUris(inputUri); + } + + // Import data from the input URI + InputConfig inputConfig = InputConfig.newBuilder().setGcsSource(gcsSource).build(); + System.out.println("Processing import..."); + + Empty response = client.importDataAsync(datasetFullId, inputConfig).get(); + System.out.println(String.format("Dataset imported. %s", response)); + } + // [END automl_natural_language_import_data] + + // [START automl_natural_language_export_data] + /** + * Demonstrates using the AutoML client to export a dataset to a Google Cloud Storage bucket. + * + * @param projectId the Id of the project. + * @param computeRegion the Region name. + * @param datasetId the Id of the dataset. + * @param gcsUri the Destination URI (Google Cloud Storage) + * @throws Exception on AutoML Client errors + */ + public static void exportData( + String projectId, String computeRegion, String datasetId, String gcsUri) throws Exception { + // Instantiates a client + AutoMlClient client = AutoMlClient.create(); + + // Get the complete path of the dataset. + DatasetName datasetFullId = DatasetName.of(projectId, computeRegion, datasetId); + + // Set the output URI. + GcsDestination gcsDestination = GcsDestination.newBuilder().setOutputUriPrefix(gcsUri).build(); + + // Export the data to the output URI. + OutputConfig outputConfig = OutputConfig.newBuilder().setGcsDestination(gcsDestination).build(); + System.out.println(String.format("Processing export...")); + + Empty response = client.exportDataAsync(datasetFullId, outputConfig).get(); + System.out.println(String.format("Dataset exported. %s", response)); + } + // [END automl_natural_language_export_data] + + // [START automl_natural_language_delete_dataset] + /** + * Delete a dataset. + * + * @param projectId the Id of the project. + * @param computeRegion the Region name. + * @param datasetId the Id of the dataset. + * @throws Exception on AutoML Client errors + */ + public static void deleteDataset(String projectId, String computeRegion, String datasetId) + throws Exception { + // Instantiates a client + AutoMlClient client = AutoMlClient.create(); + + // Get the complete path of the dataset. + DatasetName datasetFullId = DatasetName.of(projectId, computeRegion, datasetId); + + // Delete a dataset. + Empty response = client.deleteDatasetAsync(datasetFullId).get(); + + System.out.println(String.format("Dataset deleted. %s", response)); + } + // [END automl_natural_language_delete_dataset] + + public static void main(String[] args) throws Exception { + DatasetApi datasetApi = new DatasetApi(); + datasetApi.argsHelper(args, System.out); + } + + public static void argsHelper(String[] args, PrintStream out) throws Exception { + ArgumentParser parser = + ArgumentParsers.newFor("DatasetApi") + .build() + .defaultHelp(true) + .description("Dataset API operations."); + Subparsers subparsers = parser.addSubparsers().dest("command"); + + Subparser createDatasetParser = subparsers.addParser("create_dataset"); + createDatasetParser.addArgument("datasetName"); + createDatasetParser + .addArgument("multiLabel") + .nargs("?") + .type(Boolean.class) + .choices(Boolean.FALSE, Boolean.TRUE) + .setDefault("False"); + + Subparser listDatasetsParser = subparsers.addParser("list_datasets"); + listDatasetsParser + .addArgument("filter") + .nargs("?") + .setDefault("textClassificationDatasetMetadata:*"); + + Subparser getDatasetParser = subparsers.addParser("get_dataset"); + getDatasetParser.addArgument("datasetId"); + + Subparser importDataParser = subparsers.addParser("import_data"); + importDataParser.addArgument("datasetId"); + importDataParser.addArgument("path"); + + Subparser exportDataParser = subparsers.addParser("export_data"); + exportDataParser.addArgument("datasetId"); + exportDataParser.addArgument("outputUri"); + + Subparser deleteDatasetParser = subparsers.addParser("delete_dataset"); + deleteDatasetParser.addArgument("datasetId"); + + String projectId = System.getenv("PROJECT_ID"); + String computeRegion = System.getenv("REGION_NAME"); + + Namespace ns = null; + try { + ns = parser.parseArgs(args); + + if (ns.get("command").equals("create_dataset")) { + createDataset( + projectId, computeRegion, ns.getString("datasetName"), ns.getBoolean("multiLabel")); + } + if (ns.get("command").equals("list_datasets")) { + listDatasets(projectId, computeRegion, ns.getString("filter")); + } + if (ns.get("command").equals("get_dataset")) { + getDataset(projectId, computeRegion, ns.getString("datasetId")); + } + if (ns.get("command").equals("import_data")) { + importData(projectId, computeRegion, ns.getString("datasetId"), ns.getString("path")); + } + if (ns.get("command").equals("export_data")) { + exportData(projectId, computeRegion, ns.getString("datasetId"), ns.getString("outputUri")); + } + if (ns.get("command").equals("delete_dataset")) { + deleteDataset(projectId, computeRegion, ns.getString("datasetId")); + } + + } catch (ArgumentParserException e) { + parser.handleError(e); + } + } +} diff --git a/language/automl/src/main/java/com/google/cloud/language/samples/ModelApi.java b/language/automl/src/main/java/com/google/cloud/language/samples/ModelApi.java new file mode 100644 index 00000000000..16b4841f290 --- /dev/null +++ b/language/automl/src/main/java/com/google/cloud/language/samples/ModelApi.java @@ -0,0 +1,428 @@ +/* + * Copyright 2018 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.language.samples; + +// Imports the Google Cloud client library +import com.google.api.gax.longrunning.OperationFuture; +import com.google.cloud.automl.v1beta1.AutoMlClient; +import com.google.cloud.automl.v1beta1.ClassificationProto.ClassificationEvaluationMetrics; +import com.google.cloud.automl.v1beta1.ClassificationProto.ClassificationEvaluationMetrics.ConfidenceMetricsEntry; +import com.google.cloud.automl.v1beta1.ListModelEvaluationsRequest; +import com.google.cloud.automl.v1beta1.ListModelsRequest; +import com.google.cloud.automl.v1beta1.LocationName; +import com.google.cloud.automl.v1beta1.Model; +import com.google.cloud.automl.v1beta1.ModelEvaluation; +import com.google.cloud.automl.v1beta1.ModelEvaluationName; +import com.google.cloud.automl.v1beta1.ModelName; +import com.google.cloud.automl.v1beta1.OperationMetadata; + +import com.google.cloud.automl.v1beta1.TextClassificationModelMetadata; +import com.google.longrunning.Operation; +import com.google.protobuf.Empty; + +import java.io.IOException; +import java.io.PrintStream; +import java.util.List; +import java.util.concurrent.ExecutionException; +import net.sourceforge.argparse4j.ArgumentParsers; +import net.sourceforge.argparse4j.inf.ArgumentParser; +import net.sourceforge.argparse4j.inf.ArgumentParserException; +import net.sourceforge.argparse4j.inf.Namespace; +import net.sourceforge.argparse4j.inf.Subparser; +import net.sourceforge.argparse4j.inf.Subparsers; + +/** + * Google Cloud AutoML Natural Language API sample application. Example usage: mvn package exec:java + * -Dexec.mainClass ='com.google.cloud.vision.samples.automl.ModelApi' -Dexec.args='create_model + * [datasetId] test_model' + */ +public class ModelApi { + + // [START automl_natural_language_create_model] + /** + * Demonstrates using the AutoML client to create a model. + * + * @param projectId the Id of the project. + * @param computeRegion the Region name. + * @param dataSetId the Id of the dataset to which model is created. + * @param modelName the Name of the model. + * @throws Exception on AutoML Client errors + */ + public static void createModel( + String projectId, String computeRegion, String dataSetId, String modelName) + throws IOException, InterruptedException, ExecutionException { + + // Instantiates a client + AutoMlClient client = AutoMlClient.create(); + + // A resource that represents Google Cloud Platform location. + LocationName projectLocation = LocationName.of(projectId, computeRegion); + + // Set model meta data + TextClassificationModelMetadata textClassificationModelMetadata = + TextClassificationModelMetadata.newBuilder().build(); + + // Set model name, dataset and metadata. + Model myModel = + Model.newBuilder() + .setDisplayName(modelName) + .setDatasetId(dataSetId) + .setTextClassificationModelMetadata(textClassificationModelMetadata) + .build(); + + // Create a model with the model metadata in the region. + OperationFuture response = + client.createModelAsync(projectLocation, myModel); + + System.out.println( + String.format("Training operation name: %s", response.getInitialFuture().get().getName())); + System.out.println("Training started..."); + } + // [END automl_natural_language_create_model] + + // [START automl_natural_language_get_operation_status] + /** + * Demonstrates using the AutoML client to get operation status. + * + * @param operationFullId the complete name of a operation. For example, the name of your + * operation is projects/[projectId]/locations/us-central1/operations/[operationId]. + * @throws IOException on Input/Output errors. + */ + public static void getOperationStatus(String operationFullId) throws IOException { + // Instantiates a client + AutoMlClient client = AutoMlClient.create(); + + // Get the latest state of a long-running operation. + Operation response = client.getOperationsClient().getOperation(operationFullId); + + System.out.println(String.format("Operation status: %s", response)); + } + // [END automl_natural_language_get_operation_status] + + // [START automl_natural_language_list_models] + /** + * Demonstrates using the AutoML client to list all models. + * + * @param projectId the Id of the project. + * @param computeRegion the Region name. + * @param filter the filter expression. + * @throws IOException on Input/Output errors. + */ + public static void listModels(String projectId, String computeRegion, String filter) + throws IOException { + // Instantiates a client + AutoMlClient client = AutoMlClient.create(); + + // A resource that represents Google Cloud Platform location. + LocationName projectLocation = LocationName.of(projectId, computeRegion); + + // Create list models request. + ListModelsRequest listModlesRequest = + ListModelsRequest.newBuilder() + .setParent(projectLocation.toString()) + .setFilter(filter) + .build(); + + System.out.println("List of models:"); + for (Model model : client.listModels(listModlesRequest).iterateAll()) { + // Display the model information. + System.out.println(String.format("Model name: %s", model.getName())); + System.out.println( + String.format( + "Model id: %s", model.getName().split("/")[model.getName().split("/").length - 1])); + System.out.println(String.format("Model display name: %s", model.getDisplayName())); + System.out.println("Model create time:"); + System.out.println(String.format("\tseconds: %s", model.getCreateTime().getSeconds())); + System.out.println(String.format("\tnanos: %s", model.getCreateTime().getNanos())); + System.out.println(String.format("Model deployment state: %s", model.getDeploymentState())); + } + } + // [END automl_natural_language_list_models] + + // [START automl_natural_language_get_model] + /** + * Demonstrates using the AutoML client to get model details. + * + * @param projectId the Id of the project. + * @param computeRegion the Region name. + * @param modelId the Id of the model. + * @throws IOException on AutoML Client errors + */ + public static void getModel(String projectId, String computeRegion, String modelId) + throws IOException { + // Instantiates a client + AutoMlClient client = AutoMlClient.create(); + + // Get the full path of the model. + ModelName modelFullId = ModelName.of(projectId, computeRegion, modelId); + + // Get complete detail of the model. + Model model = client.getModel(modelFullId); + + // Display the model information. + System.out.println(String.format("Model name: %s", model.getName())); + System.out.println( + String.format( + "Model id: %s", model.getName().split("/")[model.getName().split("/").length - 1])); + System.out.println(String.format("Model display name: %s", model.getDisplayName())); + System.out.println("Model create time:"); + System.out.println(String.format("\tseconds: %s", model.getCreateTime().getSeconds())); + System.out.println(String.format("\tnanos: %s", model.getCreateTime().getNanos())); + System.out.println(String.format("Model deployment state: %s", model.getDeploymentState())); + } + // END automl_natural_language_get_model] + + // [START automl_natural_language_list_model_evaluations] + /** + * Demonstrates using the AutoML client to list model evaluations. + * + * @param projectId the Id of the project. + * @param computeRegion the Region name. + * @param modelId the Id of the model. + * @param filter the Filter expression. + * @throws IOException on Input/Output errors. + */ + public static void listModelEvaluations( + String projectId, String computeRegion, String modelId, String filter) throws IOException { + // Instantiates a client + AutoMlClient client = AutoMlClient.create(); + + // Get the full path of the model. + ModelName modelFullId = ModelName.of(projectId, computeRegion, modelId); + + // Create list model evaluations request. + ListModelEvaluationsRequest modelEvaluationsRequest = + ListModelEvaluationsRequest.newBuilder() + .setParent(modelFullId.toString()) + .setFilter(filter) + .build(); + + // List all the model evaluations in the model by applying filter. + for (ModelEvaluation element : + client.listModelEvaluations(modelEvaluationsRequest).iterateAll()) { + System.out.println(element); + } + } + // [END automl_natural_language_list_model_evaluations] + + // [START automl_natural_language_get_model_evaluation] + /** + * Demonstrates using the AutoML client to get model evaluations. + * + * @param projectId the Id of the project. + * @param computeRegion the Region name. + * @param modelId the Id of the model. + * @param modelEvaluationId the Id of your model evaluation. + * @throws IOException on Input/Output errors. + */ + public static void getModelEvaluation( + String projectId, String computeRegion, String modelId, String modelEvaluationId) + throws IOException { + // Instantiates a client + AutoMlClient client = AutoMlClient.create(); + + // Get the full path of the model evaluation. + ModelEvaluationName modelEvaluationFullId = + ModelEvaluationName.of(projectId, computeRegion, modelId, modelEvaluationId); + + // Get complete detail of the model evaluation. + ModelEvaluation response = client.getModelEvaluation(modelEvaluationFullId); + + System.out.println(response); + } + // [END automl_natural_language_get_model_evaluation] + + // [START automl_natural_language_display_evaluation] + /** + * Demonstrates using the AutoML client to display model evaluation. + * + * @param projectId the Id of the project. + * @param computeRegion the Region name. + * @param modelId the Id of the model. + * @param filter the Filter expression. + * @throws IOException on Input/Output errors. + */ + public static void displayEvaluation( + String projectId, String computeRegion, String modelId, String filter) throws IOException { + // Instantiates a client + AutoMlClient client = AutoMlClient.create(); + + // Get the full path of the model. + ModelName modelFullId = ModelName.of(projectId, computeRegion, modelId); + + // List all the model evaluations in the model by applying. + ListModelEvaluationsRequest modelEvaluationsrequest = + ListModelEvaluationsRequest.newBuilder() + .setParent(modelFullId.toString()) + .setFilter(filter) + .build(); + + // Iterate through the results. + String modelEvaluationId = ""; + for (ModelEvaluation element : + client.listModelEvaluations(modelEvaluationsrequest).iterateAll()) { + if (element.getAnnotationSpecId() != null) { + modelEvaluationId = element.getName().split("/")[element.getName().split("/").length - 1]; + } + } + + // Resource name for the model evaluation. + ModelEvaluationName modelEvaluationFullId = + ModelEvaluationName.of(projectId, computeRegion, modelId, modelEvaluationId); + + // Get a model evaluation. + ModelEvaluation modelEvaluation = client.getModelEvaluation(modelEvaluationFullId); + + ClassificationEvaluationMetrics classMetrics = + modelEvaluation.getClassificationEvaluationMetrics(); + List confidenceMetricsEntries = + classMetrics.getConfidenceMetricsEntryList(); + + // Showing model score based on threshold of 0.5 + for (ConfidenceMetricsEntry confidenceMetricsEntry : confidenceMetricsEntries) { + if (confidenceMetricsEntry.getConfidenceThreshold() == 0.5) { + System.out.println("Precision and recall are based on a score threshold of 0.5"); + System.out.println( + String.format("Model Precision: %.2f ", confidenceMetricsEntry.getPrecision() * 100) + + '%'); + System.out.println( + String.format("Model Recall: %.2f ", confidenceMetricsEntry.getRecall() * 100) + '%'); + System.out.println( + String.format("Model F1 Score: %.2f ", confidenceMetricsEntry.getF1Score() * 100) + + '%'); + System.out.println( + String.format( + "Model Precision@1: %.2f ", confidenceMetricsEntry.getPrecisionAt1() * 100) + + '%'); + System.out.println( + String.format("Model Recall@1: %.2f ", confidenceMetricsEntry.getRecallAt1() * 100) + + '%'); + System.out.println( + String.format("Model F1 Score@1: %.2f ", confidenceMetricsEntry.getF1ScoreAt1() * 100) + + '%'); + } + } + } + // [END automl_natural_language_display_evaluation] + + // [START automl_natural_language_delete_model] + /** + * Demonstrates using the AutoML client to delete a model. + * + * @param projectId the Id of the project. + * @param computeRegion the Region name. + * @param modelId the Id of the model. + * @throws Exception on AutoML Client errors + */ + public static void deleteModel(String projectId, String computeRegion, String modelId) + throws InterruptedException, ExecutionException, IOException { + // Instantiates a client + AutoMlClient client = AutoMlClient.create(); + + // Get the full path of the model. + ModelName modelFullId = ModelName.of(projectId, computeRegion, modelId); + + // Delete a model. + Empty response = client.deleteModelAsync(modelFullId).get(); + + System.out.println("Model deletion started..."); + } + // [END automl_natural_language_delete_model] + + public static void main(String[] args) throws Exception { + ModelApi modelApi = new ModelApi(); + modelApi.argsHelper(args, System.out); + } + + public static void argsHelper(String[] args, PrintStream out) throws Exception { + ArgumentParser parser = + ArgumentParsers.newFor("ModelApi") + .build() + .defaultHelp(true) + .description("Model API operations."); + Subparsers subparsers = parser.addSubparsers().dest("command"); + + Subparser createModelParser = subparsers.addParser("create_model"); + createModelParser.addArgument("datasetId"); + createModelParser.addArgument("modelName"); + + Subparser listModelsParser = subparsers.addParser("list_models"); + listModelsParser + .addArgument("filter") + .nargs("?") + .setDefault("textClassificationModelMetadata:*"); + + Subparser getModelParser = subparsers.addParser("get_model"); + getModelParser.addArgument("modelId"); + + Subparser listModelEvaluationsParser = subparsers.addParser("list_model_evaluations"); + listModelEvaluationsParser.addArgument("modelId"); + listModelEvaluationsParser.addArgument("filter").nargs("?").setDefault(""); + + Subparser getModelEvaluationParser = subparsers.addParser("get_model_evaluation"); + getModelEvaluationParser.addArgument("modelId"); + getModelEvaluationParser.addArgument("modelEvaluationId"); + + Subparser displayEvaluationParser = subparsers.addParser("display_evaluation"); + displayEvaluationParser.addArgument("modelId"); + displayEvaluationParser.addArgument("filter").nargs("?").setDefault(""); + + Subparser deleteModelParser = subparsers.addParser("delete_model"); + deleteModelParser.addArgument("modelId"); + + Subparser getOperationStatusParser = subparsers.addParser("get_operation_status"); + getOperationStatusParser.addArgument("operationFullId"); + + String projectId = System.getenv("PROJECT_ID"); + String computeRegion = System.getenv("REGION_NAME"); + + Namespace ns = null; + try { + ns = parser.parseArgs(args); + if (ns.get("command").equals("create_model")) { + createModel(projectId, computeRegion, ns.getString("datasetId"), ns.getString("modelName")); + } + if (ns.get("command").equals("list_models")) { + listModels(projectId, computeRegion, ns.getString("filter")); + } + if (ns.get("command").equals("get_model")) { + getModel(projectId, computeRegion, ns.getString("modelId")); + } + if (ns.get("command").equals("list_model_evaluations")) { + listModelEvaluations( + projectId, computeRegion, ns.getString("modelId"), ns.getString("filter")); + } + if (ns.get("command").equals("get_model_evaluation")) { + getModelEvaluation( + projectId, computeRegion, ns.getString("modelId"), ns.getString("modelEvaluationId")); + } + if (ns.get("command").equals("delete_model")) { + deleteModel(projectId, computeRegion, ns.getString("modelId")); + } + if (ns.get("command").equals("get_operation_status")) { + getOperationStatus(ns.getString("operationFullId")); + } + if (ns.get("command").equals("display_evaluation")) { + displayEvaluation( + projectId, computeRegion, ns.getString("modelId"), ns.getString("filter")); + } + + } catch (ArgumentParserException e) { + parser.handleError(e); + } + } +} diff --git a/language/automl/src/main/java/com/google/cloud/language/samples/PredictionApi.java b/language/automl/src/main/java/com/google/cloud/language/samples/PredictionApi.java new file mode 100644 index 00000000000..b374deded7e --- /dev/null +++ b/language/automl/src/main/java/com/google/cloud/language/samples/PredictionApi.java @@ -0,0 +1,121 @@ +/* + * Copyright 2018 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.language.samples; + +// Imports the Google Cloud client library +import com.google.cloud.automl.v1beta1.AnnotationPayload; +import com.google.cloud.automl.v1beta1.ExamplePayload; +import com.google.cloud.automl.v1beta1.ModelName; +import com.google.cloud.automl.v1beta1.PredictResponse; +import com.google.cloud.automl.v1beta1.PredictionServiceClient; +import com.google.cloud.automl.v1beta1.TextSnippet; + +import java.io.IOException; +import java.io.PrintStream; + +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.HashMap; +import java.util.Map; + +import net.sourceforge.argparse4j.ArgumentParsers; +import net.sourceforge.argparse4j.inf.ArgumentParser; +import net.sourceforge.argparse4j.inf.ArgumentParserException; +import net.sourceforge.argparse4j.inf.Namespace; +import net.sourceforge.argparse4j.inf.Subparser; +import net.sourceforge.argparse4j.inf.Subparsers; + +/** + * Google Cloud AutoML Natural Language API sample application. Example usage: mvn package exec:java + * -Dexec.mainClass ='com.google.cloud.vision.samples.automl.PredictionApi' -Dexec.args='predict + * [modelId] [path-to-text-file] [scoreThreshold]' + */ +public class PredictionApi { + + // [START automl_natural_language_predict] + /** + * Demonstrates using the AutoML client to classify the text content + * + * @param projectId the Id of the project. + * @param computeRegion the Region name. + * @param modelId the Id of the model which will be used for text classification. + * @param filePath the Local text file path of the content to be classified. + * @throws IOException on Input/Output errors. + */ + public static void predict( + String projectId, String computeRegion, String modelId, String filePath) throws IOException { + + // Create client for prediction service. + PredictionServiceClient predictionClient = PredictionServiceClient.create(); + + // Get full path of model + ModelName name = ModelName.of(projectId, computeRegion, modelId); + + // Read the file content for prediction. + String content = new String(Files.readAllBytes(Paths.get(filePath))); + + // Set the payload by giving the content and type of the file. + TextSnippet textSnippet = + TextSnippet.newBuilder().setContent(content).setMimeType("text/plain").build(); + ExamplePayload payload = ExamplePayload.newBuilder().setTextSnippet(textSnippet).build(); + + // params is additional domain-specific parameters. + // currently there is no additional parameters supported. + Map params = new HashMap(); + PredictResponse response = predictionClient.predict(name, payload, params); + + System.out.println("Prediction results:"); + for (AnnotationPayload annotationPayload : response.getPayloadList()) { + System.out.println("Predicted Class name :" + annotationPayload.getDisplayName()); + System.out.println( + "Predicted Class Score :" + annotationPayload.getClassification().getScore()); + } + } + // [END automl_natural_language_predict] + + public static void main(String[] args) throws IOException { + PredictionApi predictionApi = new PredictionApi(); + predictionApi.argsHelper(args, System.out); + } + + public static void argsHelper(String[] args, PrintStream out) throws IOException { + ArgumentParser parser = + ArgumentParsers.newFor("PredictionApi") + .build() + .defaultHelp(true) + .description("Prediction API Operation"); + Subparsers subparsers = parser.addSubparsers().dest("command"); + + Subparser predictParser = subparsers.addParser("predict"); + predictParser.addArgument("modelId"); + predictParser.addArgument("filePath"); + + String projectId = System.getenv("PROJECT_ID"); + String computeRegion = System.getenv("REGION_NAME"); + + Namespace ns = null; + try { + ns = parser.parseArgs(args); + if (ns.get("command").equals("predict")) { + predict(projectId, computeRegion, ns.getString("modelId"), ns.getString("filePath")); + } + + } catch (ArgumentParserException e) { + parser.handleError(e); + } + } +} diff --git a/language/automl/src/test/java/com/google/cloud/language/samples/DatasetApiIT.java b/language/automl/src/test/java/com/google/cloud/language/samples/DatasetApiIT.java new file mode 100644 index 00000000000..1b43dd04055 --- /dev/null +++ b/language/automl/src/test/java/com/google/cloud/language/samples/DatasetApiIT.java @@ -0,0 +1,108 @@ +/* + * Copyright 2018 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.language.samples; + +import static com.google.common.truth.Truth.assertThat; +import static java.lang.Boolean.FALSE; + +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Tests for Automl natural language "Dataset API" sample. */ +@RunWith(JUnit4.class) +@SuppressWarnings("checkstyle:abbreviationaswordinname") +public class DatasetApiIT { + + private static final String PROJECT_ID = "java-docs-samples-testing"; + private static final String BUCKET = PROJECT_ID + "-vcm"; + private static final String COMPUTE_REGION = "us-central1"; + private static final String DATASET_NAME = "test_dataset"; + private ByteArrayOutputStream bout; + private PrintStream out; + private DatasetApi app; + private String datasetId; + private String getdatasetId = "8477830379477056918"; + + @Before + public void setUp() { + bout = new ByteArrayOutputStream(); + out = new PrintStream(bout); + System.setOut(out); + } + + @After + public void tearDown() { + System.setOut(null); + } + + @Test + public void testCreateImportDeleteDataset() throws Exception { + // Act + DatasetApi.createDataset(PROJECT_ID, COMPUTE_REGION, DATASET_NAME, FALSE); + + // Assert + String got = bout.toString(); + datasetId = + bout.toString() + .split("\n")[0] + .split("/")[(bout.toString().split("\n")[0]).split("/").length - 1]; + assertThat(got).contains("Dataset id:"); + + // Act + DatasetApi.importData( + PROJECT_ID, COMPUTE_REGION, datasetId, "gs://" + BUCKET + "/happiness.csv"); + + // Assert + got = bout.toString(); + assertThat(got).contains("Dataset id:"); + + // Act + DatasetApi.deleteDataset(PROJECT_ID, COMPUTE_REGION, datasetId); + + // Assert + got = bout.toString(); + assertThat(got).contains("Dataset deleted."); + } + + @Test + public void testListDatasets() throws Exception { + // Act + DatasetApi.listDatasets(PROJECT_ID, COMPUTE_REGION, ""); + + // Assert + String got = bout.toString(); + assertThat(got).contains("Dataset id:"); + } + + @Test + public void testGetDataset() throws Exception { + + // Act + DatasetApi.getDataset(PROJECT_ID, COMPUTE_REGION, getdatasetId); + + // Assert + String got = bout.toString(); + + assertThat(got).contains("Dataset id:"); + } +} diff --git a/language/automl/src/test/java/com/google/cloud/language/samples/ModelApiIT.java b/language/automl/src/test/java/com/google/cloud/language/samples/ModelApiIT.java new file mode 100644 index 00000000000..c142c3ef5b2 --- /dev/null +++ b/language/automl/src/test/java/com/google/cloud/language/samples/ModelApiIT.java @@ -0,0 +1,92 @@ +/* + * Copyright 2018 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.language.samples; + +import static com.google.common.truth.Truth.assertThat; + +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Tests for vision "Model API" sample. */ +@RunWith(JUnit4.class) +@SuppressWarnings("checkstyle:abbreviationaswordinname") +public class ModelApiIT { + private static final String PROJECT_ID = "java-docs-samples-testing"; + private static final String COMPUTE_REGION = "us-central1"; + private ByteArrayOutputStream bout; + private PrintStream out; + private ModelApi app; + private String modelId; + private String modelIdGetevaluation = "342705131419266916"; + private String modelEvaluationId = "3666189665418739402"; + + @Before + public void setUp() { + + bout = new ByteArrayOutputStream(); + out = new PrintStream(bout); + System.setOut(out); + } + + @After + public void tearDown() { + System.setOut(null); + } + + @Test + public void testModelApi() throws Exception { + // Act + ModelApi.listModels(PROJECT_ID, COMPUTE_REGION, ""); + + // Assert + String got = bout.toString(); + modelId = got.split("\n")[1].split("/")[got.split("\n")[1].split("/").length - 1]; + assertThat(got).contains("Model id:"); + + // Act + ModelApi.getModel(PROJECT_ID, COMPUTE_REGION, modelId); + + // Assert + got = bout.toString(); + assertThat(got).contains("Model name:"); + + // Act + ModelApi.listModelEvaluations(PROJECT_ID, COMPUTE_REGION, modelId, ""); + + // Assert + got = bout.toString(); + assertThat(got).contains("name:"); + } + + @Test + public void testGetModelEvaluation() throws Exception { + + // Act + ModelApi.getModelEvaluation( + PROJECT_ID, COMPUTE_REGION, modelIdGetevaluation, modelEvaluationId); + + // Assert + String got = bout.toString(); + assertThat(got).contains("name:"); + } +} diff --git a/language/automl/src/test/java/com/google/cloud/language/samples/PredictionApiIT.java b/language/automl/src/test/java/com/google/cloud/language/samples/PredictionApiIT.java new file mode 100644 index 00000000000..3549eb244ee --- /dev/null +++ b/language/automl/src/test/java/com/google/cloud/language/samples/PredictionApiIT.java @@ -0,0 +1,63 @@ +/* + * Copyright 2018 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.language.samples; + +import static com.google.common.truth.Truth.assertThat; + +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Tests for vision "PredictionAPI" sample. */ +@RunWith(JUnit4.class) +@SuppressWarnings("checkstyle:abbreviationaswordinname") +public class PredictionApiIT { + private static final String COMPUTE_REGION = "us-central1"; + private static final String PROJECT_ID = "java-docs-samples-testing"; + private static final String modelId = "342705131419266916"; + private static final String filePath = "./resources/input.txt"; + private ByteArrayOutputStream bout; + private PrintStream out; + private PredictionApi app; + + @Before + public void setUp() { + bout = new ByteArrayOutputStream(); + out = new PrintStream(bout); + System.setOut(out); + } + + @After + public void tearDown() { + System.setOut(null); + } + + @Test + public void testPredict() throws Exception { + // Act + PredictionApi.predict(PROJECT_ID, COMPUTE_REGION, modelId, filePath); + + // Assert + String got = bout.toString(); + assertThat(got).contains("Prediction results:"); + } +} From a2a6d91ca1612985414baf1b49faf3a5c5061430 Mon Sep 17 00:00:00 2001 From: nirupa-kumar Date: Mon, 23 Jul 2018 15:25:26 -0700 Subject: [PATCH 07/15] Vision AutoML --- .../cloud/translate/automl/DatasetApiIT.java | 107 ++++++++++++++++++ .../cloud/translate/automl/ModelApiIT.java | 89 +++++++++++++++ .../translate/automl/PredictionApiIT.java | 64 +++++++++++ 3 files changed, 260 insertions(+) create mode 100644 translate/automl/src/test/java/com/google/cloud/translate/automl/DatasetApiIT.java create mode 100644 translate/automl/src/test/java/com/google/cloud/translate/automl/ModelApiIT.java create mode 100644 translate/automl/src/test/java/com/google/cloud/translate/automl/PredictionApiIT.java diff --git a/translate/automl/src/test/java/com/google/cloud/translate/automl/DatasetApiIT.java b/translate/automl/src/test/java/com/google/cloud/translate/automl/DatasetApiIT.java new file mode 100644 index 00000000000..7ceda3e4445 --- /dev/null +++ b/translate/automl/src/test/java/com/google/cloud/translate/automl/DatasetApiIT.java @@ -0,0 +1,107 @@ +/* + * Copyright 2018 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.translate.automl; + +import static com.google.common.truth.Truth.assertThat; +import static java.lang.Boolean.FALSE; + +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Tests for Automl translation "Dataset API" sample. */ +@RunWith(JUnit4.class) +@SuppressWarnings("checkstyle:abbreviationaswordinname") +public class DatasetApiIT { + + private static final String PROJECT_ID = "java-docs-samples-testing"; + private static final String BUCKET = PROJECT_ID + "-vcm"; + private static final String COMPUTE_REGION = "us-central1"; + private static final String DATASET_NAME = "test_dataset"; + private ByteArrayOutputStream bout; + private PrintStream out; + private DatasetApi app; + private String datasetId; + private String getdatasetId = "3946265060617537378"; + + @Before + public void setUp() { + bout = new ByteArrayOutputStream(); + out = new PrintStream(bout); + System.setOut(out); + } + + @After + public void tearDown() { + System.setOut(null); + } + + @Test + public void testCreateImportDeleteDataset() throws Exception { + // Act + DatasetApi.createDataset(PROJECT_ID, COMPUTE_REGION, DATASET_NAME, "en", "ja"); + + // Assert + String got = bout.toString(); + datasetId = + bout.toString() + .split("\n")[0] + .split("/")[(bout.toString().split("\n")[0]).split("/").length - 1]; + assertThat(got).contains("Dataset id:"); + + // Act + DatasetApi.importData(PROJECT_ID, COMPUTE_REGION, datasetId, "gs://" + BUCKET + "/en-ja.csv"); + + // Assert + got = bout.toString(); + assertThat(got).contains("Dataset id:"); + + // Act + DatasetApi.deleteDataset(PROJECT_ID, COMPUTE_REGION, datasetId); + + // Assert + got = bout.toString(); + assertThat(got).contains("Dataset deleted."); + } + + @Test + public void testListDataset() throws Exception { + // Act + DatasetApi.listDatasets(PROJECT_ID, COMPUTE_REGION, "translation_dataset_metadata:*"); + + // Assert + String got = bout.toString(); + assertThat(got).contains("Dataset id:"); + } + + @Test + public void testGetDataset() throws Exception { + + // Act + DatasetApi.getDataset(PROJECT_ID, COMPUTE_REGION, getdatasetId); + + // Assert + String got = bout.toString(); + + assertThat(got).contains("Dataset id:"); + } +} diff --git a/translate/automl/src/test/java/com/google/cloud/translate/automl/ModelApiIT.java b/translate/automl/src/test/java/com/google/cloud/translate/automl/ModelApiIT.java new file mode 100644 index 00000000000..0ebfeed339b --- /dev/null +++ b/translate/automl/src/test/java/com/google/cloud/translate/automl/ModelApiIT.java @@ -0,0 +1,89 @@ +/* + * Copyright 2018 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.translate.automl; + +import static com.google.common.truth.Truth.assertThat; + +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Tests for translation "Model API" sample. */ +@RunWith(JUnit4.class) +@SuppressWarnings("checkstyle:abbreviationaswordinname") +public class ModelApiIT { + private static final String PROJECT_ID = "java-docs-samples-testing"; + private static final String COMPUTE_REGION = "us-central1"; + private ByteArrayOutputStream bout; + private PrintStream out; + private ModelApi app; + private String modelId; + private String modelEvaluationId; + + @Before + public void setUp() { + + bout = new ByteArrayOutputStream(); + out = new PrintStream(bout); + System.setOut(out); + } + + @After + public void tearDown() { + System.setOut(null); + } + + @Test + public void testModelApi() throws Exception { + // Act + ModelApi.listModels(PROJECT_ID, COMPUTE_REGION, ""); + + // Assert + String got = bout.toString(); + modelId = got.split("\n")[1].split("/")[got.split("\n")[1].split("/").length - 1]; + assertThat(got).contains("Model id:"); + + // Act + ModelApi.getModel(PROJECT_ID, COMPUTE_REGION, modelId); + + // Assert + got = bout.toString(); + assertThat(got).contains("Model name:"); + + // Act + ModelApi.listModelEvaluations(PROJECT_ID, COMPUTE_REGION, modelId, ""); + + // Assert + got = bout.toString(); + modelEvaluationId = got.split("List of model evaluations:")[1].split("\"")[1].split("/")[7]; + assertThat(got).contains("name:"); + + // Act + ModelApi.getModelEvaluation(PROJECT_ID, COMPUTE_REGION, modelId, modelEvaluationId); + + // Assert + got = bout.toString(); + assertThat(got).contains("name:"); + + } +} + diff --git a/translate/automl/src/test/java/com/google/cloud/translate/automl/PredictionApiIT.java b/translate/automl/src/test/java/com/google/cloud/translate/automl/PredictionApiIT.java new file mode 100644 index 00000000000..962a0fd0802 --- /dev/null +++ b/translate/automl/src/test/java/com/google/cloud/translate/automl/PredictionApiIT.java @@ -0,0 +1,64 @@ +/* + * Copyright 2018 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.translate.automl; + +import static com.google.common.truth.Truth.assertThat; +import static java.lang.Boolean.FALSE; + +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Tests for translation "PredictionAPI" sample. */ +@RunWith(JUnit4.class) +@SuppressWarnings("checkstyle:abbreviationaswordinname") +public class PredictionApiIT { + private static final String COMPUTE_REGION = "us-central1"; + private static final String PROJECT_ID = "java-docs-samples-testing"; + private static final String modelId = "2188848820815848149"; + private static final String filePath = "./resources/input.txt"; + private ByteArrayOutputStream bout; + private PrintStream out; + private PredictionApi app; + + @Before + public void setUp() { + bout = new ByteArrayOutputStream(); + out = new PrintStream(bout); + System.setOut(out); + } + + @After + public void tearDown() { + System.setOut(null); + } + + @Test + public void testPredict() throws Exception { + // Act + PredictionApi.predict(PROJECT_ID, COMPUTE_REGION, modelId, filePath,FALSE); + + // Assert + String got = bout.toString(); + assertThat(got).contains("Translated Content"); + } +} From d9216d5f27d49e42bab2c980879ffc72a66616d6 Mon Sep 17 00:00:00 2001 From: nirupa-kumar Date: Mon, 23 Jul 2018 16:04:13 -0700 Subject: [PATCH 08/15] Translate AutoML files added --- .../cloud/translate/automl/DatasetApi.java | 314 ++++++++++++++++ .../cloud/translate/automl/ModelApi.java | 341 ++++++++++++++++++ .../cloud/translate/automl/PredictionApi.java | 140 +++++++ 3 files changed, 795 insertions(+) create mode 100644 translate/automl/src/main/java/com/google/cloud/translate/automl/DatasetApi.java create mode 100644 translate/automl/src/main/java/com/google/cloud/translate/automl/ModelApi.java create mode 100644 translate/automl/src/main/java/com/google/cloud/translate/automl/PredictionApi.java diff --git a/translate/automl/src/main/java/com/google/cloud/translate/automl/DatasetApi.java b/translate/automl/src/main/java/com/google/cloud/translate/automl/DatasetApi.java new file mode 100644 index 00000000000..03cc96aa45f --- /dev/null +++ b/translate/automl/src/main/java/com/google/cloud/translate/automl/DatasetApi.java @@ -0,0 +1,314 @@ +/* + * Copyright 2018 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.translate.automl; + +// Imports the Google Cloud client library +import com.google.cloud.automl.v1beta1.AutoMlClient; +import com.google.cloud.automl.v1beta1.Dataset; +import com.google.cloud.automl.v1beta1.DatasetName; +import com.google.cloud.automl.v1beta1.GcsSource; +import com.google.cloud.automl.v1beta1.GcsSource.Builder; +import com.google.cloud.automl.v1beta1.InputConfig; +import com.google.cloud.automl.v1beta1.ListDatasetsRequest; +import com.google.cloud.automl.v1beta1.LocationName; +import com.google.cloud.automl.v1beta1.TranslationDatasetMetadata; +import com.google.protobuf.Empty; + +import java.io.IOException; +import java.io.PrintStream; + +import net.sourceforge.argparse4j.ArgumentParsers; +import net.sourceforge.argparse4j.inf.ArgumentParser; +import net.sourceforge.argparse4j.inf.ArgumentParserException; +import net.sourceforge.argparse4j.inf.Namespace; +import net.sourceforge.argparse4j.inf.Subparser; +import net.sourceforge.argparse4j.inf.Subparsers; + +/** + * Google Cloud AutoML Translate API sample application. Example usage: mvn package exec:java + * -Dexec.mainClass ='com.google.cloud.translate.samples.DatasetAPI' -Dexec.args='create_dataset + * test_dataset' + */ +public class DatasetApi { + + // [START automl_translate_create_dataset] + /** + * Demonstrates using the AutoML client to create a dataset + * + * @param projectId the Google Cloud Project ID. + * @param computeRegion the Region name. (e.g., "us-central1"). + * @param datasetName the name of the dataset to be created. + * @param source the Source language + * @param target the Target language + * @throws IOException on Input/Output errors. + */ + public static void createDataset( + String projectId, String computeRegion, String datasetName, String source, String target) + throws IOException { + // Instantiates a client + AutoMlClient client = AutoMlClient.create(); + + // A resource that represents Google Cloud Platform location. + LocationName projectLocation = LocationName.of(projectId, computeRegion); + + // Specify the source and target language. + TranslationDatasetMetadata translationDatasetMetadata = + TranslationDatasetMetadata.newBuilder() + .setSourceLanguageCode(source) + .setTargetLanguageCode(target) + .build(); + + // Set dataset name and dataset metadata. + Dataset myDataset = + Dataset.newBuilder() + .setDisplayName(datasetName) + .setTranslationDatasetMetadata(translationDatasetMetadata) + .build(); + + // Create a dataset with the dataset metadata in the region. + Dataset dataset = client.createDataset(projectLocation, myDataset); + + // Display the dataset information. + System.out.println(String.format("Dataset name: %s", dataset.getName())); + System.out.println( + String.format( + "Dataset id: %s", + dataset.getName().split("/")[dataset.getName().split("/").length - 1])); + System.out.println(String.format("Dataset display name: %s", dataset.getDisplayName())); + System.out.println("Translation dataset Metadata:"); + System.out.println( + String.format( + "\tSource language code: %s", + dataset.getTranslationDatasetMetadata().getSourceLanguageCode())); + System.out.println( + String.format( + "\tTarget language code: %s", + dataset.getTranslationDatasetMetadata().getTargetLanguageCode())); + System.out.println("Dataset create time:"); + System.out.println(String.format("\tseconds: %s", dataset.getCreateTime().getSeconds())); + System.out.println(String.format("\tnanos: %s", dataset.getCreateTime().getNanos())); + } + // [END automl_translation_create_dataset] + + // [START automl_translation_list_datasets] + /** + * Demonstrates using the AutoML client to list all datasets. + * + * @param projectId the Google Cloud Project ID. + * @param computeRegion the Region name. (e.g., "us-central1"). + * @param filter the Filter expression. + * @throws Exception on AutoML Client errors + */ + public static void listDatasets(String projectId, String computeRegion, String filter) + throws IOException { + // Instantiates a client + AutoMlClient client = AutoMlClient.create(); + + // A resource that represents Google Cloud Platform location. + LocationName projectLocation = LocationName.of(projectId, computeRegion); + + ListDatasetsRequest request = + ListDatasetsRequest.newBuilder() + .setParent(projectLocation.toString()) + .setFilter(filter) + .build(); + + // List all the datasets available in the region by applying filter. + System.out.println("List of datasets:"); + for (Dataset dataset : client.listDatasets(request).iterateAll()) { + // Display the dataset information + System.out.println(String.format("\nDataset name: %s", dataset.getName())); + System.out.println( + String.format( + "Dataset id: %s", + dataset.getName().split("/")[dataset.getName().split("/").length - 1])); + System.out.println(String.format("Dataset display name: %s", dataset.getDisplayName())); + System.out.println("Translation dataset metadata:"); + System.out.println( + String.format( + "\tSource language code: %s", + dataset.getTranslationDatasetMetadata().getSourceLanguageCode())); + System.out.println( + String.format( + "\tTarget language code: %s", + dataset.getTranslationDatasetMetadata().getTargetLanguageCode())); + System.out.println("Dataset create time:"); + System.out.println(String.format("\tseconds: %s", dataset.getCreateTime().getSeconds())); + System.out.println(String.format("\tnanos: %s", dataset.getCreateTime().getNanos())); + } + } + // [END automl_translation_list_datasets] + + // [START automl_translation_get_dataset] + /** + * Demonstrates using the AutoML client to get a dataset by ID. + * + * @param projectId the Google Cloud Project ID. + * @param computeRegion the Region name. (e.g., "us-central1"). + * @param datasetId the Id of the dataset. + * @throws Exception on AutoML Client errors + */ + public static void getDataset(String projectId, String computeRegion, String datasetId) + throws Exception { + // Instantiates a client + AutoMlClient client = AutoMlClient.create(); + + // Get the complete path of the dataset. + DatasetName datasetFullId = DatasetName.of(projectId, computeRegion, datasetId); + + // Get all the information about a given dataset. + Dataset dataset = client.getDataset(datasetFullId); + + // Display the dataset information + System.out.println(String.format("Dataset name: %s", dataset.getName())); + System.out.println( + String.format( + "Dataset id: %s", + dataset.getName().split("/")[dataset.getName().split("/").length - 1])); + System.out.println(String.format("Dataset display name: %s", dataset.getDisplayName())); + System.out.println("Translation dataset metadata:"); + System.out.println( + String.format( + "\tSource language code: %s", + dataset.getTranslationDatasetMetadata().getSourceLanguageCode())); + System.out.println( + String.format( + "\tTarget language code: %s", + dataset.getTranslationDatasetMetadata().getTargetLanguageCode())); + System.out.println("Dataset create time:"); + System.out.println(String.format("\tseconds: %s", dataset.getCreateTime().getSeconds())); + System.out.println(String.format("\tnanos: %s", dataset.getCreateTime().getNanos())); + } + // [END automl_translation_get_dataset] + + // [START automl_translation_import_data] + /** + * Import sentence pairs to the dataset. + * + * @param projectId the Google Cloud Project ID. + * @param computeRegion the Region name. (e.g., "us-central1"). + * @param datasetId the Id of the dataset. + * @param path the remote Path of the training data csv file. + * @throws Exception on AutoML Client errors + */ + public static void importData( + String projectId, String computeRegion, String datasetId, String path) throws Exception { + // Instantiates a client + AutoMlClient client = AutoMlClient.create(); + + // Get the complete path of the dataset. + DatasetName datasetFullId = DatasetName.of(projectId, computeRegion, datasetId); + + Builder gcsSource = GcsSource.newBuilder(); + + // Get multiple Google Cloud Storage URIs to import data from + String[] inputUris = path.split(","); + for (String inputUri : inputUris) { + gcsSource.addInputUris(inputUri); + } + + // Import data from the input URI + InputConfig inputConfig = InputConfig.newBuilder().setGcsSource(gcsSource).build(); + System.out.println("Processing import..."); + + Empty response = client.importDataAsync(datasetFullId, inputConfig).get(); + System.out.println(String.format("Dataset imported. %s", response)); + } + // [END automl_translation_import_data] + + // [START automl_translation_delete_dataset] + /** + * Delete a dataset. + * + * @param projectId the Google Cloud Project ID. + * @param computeRegion the Region name. (e.g., "us-central1"). + * @param datasetId the Id of the dataset. + * @throws Exception on AutoML Client errors + */ + public static void deleteDataset(String projectId, String computeRegion, String datasetId) + throws Exception { + // Instantiates a client + AutoMlClient client = AutoMlClient.create(); + + // Get the full path of the dataset. + DatasetName datasetFullId = DatasetName.of(projectId, computeRegion, datasetId); + + // Delete a dataset. + Empty response = client.deleteDatasetAsync(datasetFullId).get(); + + System.out.println(String.format("Dataset deleted. %s", response)); + } + // [END automl_translation_delete_dataset] + + public static void main(String[] args) throws Exception { + DatasetApi datasetApi = new DatasetApi(); + datasetApi.argsHelper(args, System.out); + } + + public static void argsHelper(String[] args, PrintStream out) throws Exception { + ArgumentParser parser = ArgumentParsers.newFor("").build(); + Subparsers subparsers = parser.addSubparsers().dest("command"); + + Subparser createDatasetParser = subparsers.addParser("create_dataset"); + createDatasetParser.addArgument("datasetName"); + createDatasetParser.addArgument("source"); + createDatasetParser.addArgument("target"); + + Subparser listDatasetParser = subparsers.addParser("list_datasets"); + listDatasetParser.addArgument("filter").nargs("?").setDefault("translation_dataset_metadata:*"); + + Subparser getDatasetParser = subparsers.addParser("get_dataset"); + getDatasetParser.addArgument("datasetId"); + + Subparser importDataParser = subparsers.addParser("import_data"); + importDataParser.addArgument("datasetId"); + importDataParser.addArgument("path"); + + Subparser deleteDatasetParser = subparsers.addParser("delete_dataset"); + deleteDatasetParser.addArgument("datasetId"); + + String projectId = System.getenv("PROJECT_ID"); + String computeRegion = System.getenv("REGION_NAME"); + + Namespace ns = null; + try { + ns = parser.parseArgs(args); + if (ns.get("command").equals("create_dataset")) { + createDataset( + projectId, + computeRegion, + ns.getString("datasetName"), + ns.getString("source"), + ns.getString("target")); + } + if (ns.get("command").equals("list_datasets")) { + listDatasets(projectId, computeRegion, ns.getString("filter")); + } + if (ns.get("command").equals("get_dataset")) { + getDataset(projectId, computeRegion, ns.getString("datasetId")); + } + if (ns.get("command").equals("import_data")) { + importData(projectId, computeRegion, ns.getString("datasetId"), ns.getString("path")); + } + if (ns.get("command").equals("delete_dataset")) { + deleteDataset(projectId, computeRegion, ns.getString("datasetId")); + } + } catch (ArgumentParserException e) { + parser.handleError(e); + } + } +} diff --git a/translate/automl/src/main/java/com/google/cloud/translate/automl/ModelApi.java b/translate/automl/src/main/java/com/google/cloud/translate/automl/ModelApi.java new file mode 100644 index 00000000000..c720c3d5f40 --- /dev/null +++ b/translate/automl/src/main/java/com/google/cloud/translate/automl/ModelApi.java @@ -0,0 +1,341 @@ +/* + * Copyright 2018 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.translate.automl; + +// Imports the Google Cloud client library +import com.google.api.gax.longrunning.OperationFuture; +import com.google.cloud.automl.v1beta1.AutoMlClient; +import com.google.cloud.automl.v1beta1.ListModelEvaluationsRequest; +import com.google.cloud.automl.v1beta1.ListModelsRequest; +import com.google.cloud.automl.v1beta1.LocationName; +import com.google.cloud.automl.v1beta1.Model; +import com.google.cloud.automl.v1beta1.ModelEvaluation; +import com.google.cloud.automl.v1beta1.ModelEvaluationName; +import com.google.cloud.automl.v1beta1.ModelName; +import com.google.cloud.automl.v1beta1.OperationMetadata; +import com.google.cloud.automl.v1beta1.TranslationModelMetadata; +import com.google.longrunning.Operation; +import com.google.protobuf.Empty; + +import java.io.IOException; +import java.io.PrintStream; +import java.util.concurrent.ExecutionException; + +import net.sourceforge.argparse4j.ArgumentParsers; +import net.sourceforge.argparse4j.inf.ArgumentParser; +import net.sourceforge.argparse4j.inf.ArgumentParserException; +import net.sourceforge.argparse4j.inf.Namespace; +import net.sourceforge.argparse4j.inf.Subparser; +import net.sourceforge.argparse4j.inf.Subparsers; + +/** + * Google Cloud AutoML Translate API sample application. Example usage: mvn package exec:java + * -Dexec.mainClass ='com.example.translate.ModelApi' -Dexec.args='create_model [datasetId] + * test_model' + */ +public class ModelApi { + + // [START automl_translation_create_model] + /** + * Demonstrates using the AutoML client to create a model. + * + * @param projectId the Id of the project. + * @param computeRegion the Region name. + * @param dataSetId the Id of the dataset to which model is created. + * @param modelName the Name of the model. + * @throws Exception on AutoML Client errors + */ + public static void createModel( + String projectId, String computeRegion, String dataSetId, String modelName) throws Exception { + // Instantiates a client + AutoMlClient client = AutoMlClient.create(); + + // A resource that represents Google Cloud Platform location. + LocationName projectLocation = LocationName.of(projectId, computeRegion); + + // Set model metadata. + TranslationModelMetadata translationModelMetadata = + TranslationModelMetadata.newBuilder().setBaseModel("").build(); + + // Set model name, dataset and metadata. + Model myModel = + Model.newBuilder() + .setDisplayName(modelName) + .setDatasetId(dataSetId) + .setTranslationModelMetadata(translationModelMetadata) + .build(); + + // Create a model with the model metadata in the region. + OperationFuture response = + client.createModelAsync(projectLocation, myModel); + + System.out.println( + String.format("Training operation name: %s", response.getInitialFuture().get().getName())); + System.out.println("Training started..."); + } + // [END automl_translation_create_model] + + // [START automl_translation_list_models] + /** + * Demonstrates using the AutoML client to list all models. + * + * @param projectId the Id of the project. + * @param computeRegion the Region name. + * @param filter the filter expression. + * @throws IOException on Input/Output errors. + */ + public static void listModels(String projectId, String computeRegion, String filter) + throws IOException { + // Instantiates a client + AutoMlClient client = AutoMlClient.create(); + + // A resource that represents Google Cloud Platform location. + LocationName projectLocation = LocationName.of(projectId, computeRegion); + + // Create list models request. + ListModelsRequest listModlesRequest = + ListModelsRequest.newBuilder() + .setParent(projectLocation.toString()) + .setFilter(filter) + .build(); + + // List all the models available in the region by applying filter. + System.out.println("List of models:"); + for (Model model : client.listModels(listModlesRequest).iterateAll()) { + // Display the model information. + System.out.println(String.format("Model name: %s", model.getName())); + System.out.println( + String.format( + "Model id: %s", model.getName().split("/")[model.getName().split("/").length - 1])); + System.out.println(String.format("Model display name: %s", model.getDisplayName())); + System.out.println("Model create time:"); + System.out.println(String.format("\tseconds: %s", model.getCreateTime().getSeconds())); + System.out.println(String.format("\tnanos: %s", model.getCreateTime().getNanos())); + System.out.println(String.format("Model deployment state: %s", model.getDeploymentState())); + } + } + // [END automl_translation_list_models] + + // [START automl_translation_get_model] + /** + * Demonstrates using the AutoML client to get model details. + * + * @param projectId the Id of the project. + * @param computeRegion the Region name. + * @param modelId the Id of the model. + * @throws IOException on Input/Output errors. + */ + public static void getModel(String projectId, String computeRegion, String modelId) + throws IOException { + // Instantiates a client + AutoMlClient client = AutoMlClient.create(); + + // Get the full path of the model. + ModelName modelFullId = ModelName.of(projectId, computeRegion, modelId); + + // Get complete detail of the model. + Model model = client.getModel(modelFullId); + + // Display the model information. + System.out.println(String.format("Model name: %s", model.getName())); + System.out.println( + String.format( + "Model id: %s", model.getName().split("/")[model.getName().split("/").length - 1])); + System.out.println(String.format("Model display name: %s", model.getDisplayName())); + System.out.println("Model create time:"); + System.out.println(String.format("\tseconds: %s", model.getCreateTime().getSeconds())); + System.out.println(String.format("\tnanos: %s", model.getCreateTime().getNanos())); + System.out.println(String.format("Model deployment state: %s", model.getDeploymentState())); + } + // [END automl_translation_get_model] + + // [START automl_translation_list_model_evaluations] + /** + * Demonstrates using the AutoML client to list model evaluations. + * + * @param projectId the Id of the project. + * @param computeRegion the Region name. + * @param modelId the Id of the model. + * @param filter the filter expression. + * @throws IOException on Input/Output errors. + */ + public static void listModelEvaluations( + String projectId, String computeRegion, String modelId, String filter) throws IOException { + // Instantiates a client + AutoMlClient client = AutoMlClient.create(); + + // Get the full path of the model. + ModelName modelFullId = ModelName.of(projectId, computeRegion, modelId); + + // Create list model evaluations request + ListModelEvaluationsRequest modelEvaluationsrequest = + ListModelEvaluationsRequest.newBuilder() + .setParent(modelFullId.toString()) + .setFilter(filter) + .build(); + + // List all the model evaluations in the model by applying filter. + System.out.println("List of model evaluations:"); + for (ModelEvaluation element : + client.listModelEvaluations(modelEvaluationsrequest).iterateAll()) { + System.out.println(element); + } + } + // [END automl_translation_list_model_evaluations] + + // [START automl_translation_get_model_evaluation] + /** + * Demonstrates using the AutoML client to get model evaluations. + * + * @param projectId the Id of the project. + * @param computeRegion the Region name. + * @param modelId the Id of the model. + * @param modelEvaluationId the Id of your model evaluation. + * @throws IOException on Input/Output errors. + */ + public static void getModelEvaluation( + String projectId, String computeRegion, String modelId, String modelEvaluationId) + throws IOException { + // Instantiates a client + AutoMlClient client = AutoMlClient.create(); + + // Get the full path of the model evaluation. + ModelEvaluationName modelEvaluationFullId = + ModelEvaluationName.of(projectId, computeRegion, modelId, modelEvaluationId); + + // Get complete detail of the model evaluation. + ModelEvaluation response = client.getModelEvaluation(modelEvaluationFullId); + + System.out.println(response); + } + // [END automl_translation_get_model_evaluation] + + // [START automl_translation_delete_model] + /** + * Demonstrates using the AutoML client to delete a model. + * + * @param projectId the Id of the project. + * @param computeRegion the Region name. + * @param modelId the Id of the model. + * @throws Exception on AutoML Client errors + */ + public static void deleteModel(String projectId, String computeRegion, String modelId) + throws InterruptedException, ExecutionException, IOException { + // Instantiates a client + AutoMlClient client = AutoMlClient.create(); + + // Get the full path of the model. + ModelName modelFullId = ModelName.of(projectId, computeRegion, modelId); + + // Delete a model. + Empty response = client.deleteModelAsync(modelFullId).get(); + + System.out.println("Model deletion started..."); + } + // [END automl_translation_delete_model] + + // [START automl_translation_get_operation_status] + /** + * Demonstrates using the AutoML client to get operation status. + * + * @param operationFullId Full name of a operation. For example, the name of your operation is + * projects/[projectId]/locations/us-central1/operations/[operationId]. + * @throws IOException on Input/Output errors. + */ + private static void getOperationStatus(String operationFullId) throws IOException { + // Instantiates a client + AutoMlClient client = AutoMlClient.create(); + + // Get the latest state of a long-running operation. + Operation response = client.getOperationsClient().getOperation(operationFullId); + + System.out.println(String.format("Operation status: %s", response)); + } + // [END automl_translation_get_operation_status] + + public static void main(String[] args) throws Exception { + ModelApi modelApi = new ModelApi(); + modelApi.argsHelper(args, System.out); + } + + public static void argsHelper(String[] args, PrintStream out) throws Exception { + + ArgumentParser parser = + ArgumentParsers.newFor("ModelApi") + .build() + .defaultHelp(true) + .description("Model API operations"); + Subparsers subparsers = parser.addSubparsers().dest("command"); + + Subparser createModelParser = subparsers.addParser("create_model"); + createModelParser.addArgument("datasetId"); + createModelParser.addArgument("modelName"); + + Subparser listModelParser = subparsers.addParser("list_models"); + listModelParser.addArgument("filter").nargs("?").setDefault(""); + + Subparser getModelParser = subparsers.addParser("get_model"); + getModelParser.addArgument("modelId"); + + Subparser listModelEvaluationsParser = subparsers.addParser("list_model_evaluations"); + listModelEvaluationsParser.addArgument("modelId"); + listModelEvaluationsParser.addArgument("filter").nargs("?").setDefault(""); + + Subparser getModelEvaluationParser = subparsers.addParser("get_model_evaluation"); + getModelEvaluationParser.addArgument("modelId"); + getModelEvaluationParser.addArgument("modelEvaluationId"); + + Subparser deleteModelParser = subparsers.addParser("delete_model"); + deleteModelParser.addArgument("modelId"); + + Subparser getOperationStatusParser = subparsers.addParser("get_operation_status"); + getOperationStatusParser.addArgument("operationFullId"); + + String projectId = System.getenv("PROJECT_ID"); + String computeRegion = System.getenv("REGION_NAME"); + + Namespace ns = null; + try { + ns = parser.parseArgs(args); + if (ns.get("command").equals("create_model")) { + createModel(projectId, computeRegion, ns.getString("datasetId"), ns.getString("modelName")); + } + if (ns.get("command").equals("list_models")) { + listModels(projectId, computeRegion, ns.getString("filter")); + } + if (ns.get("command").equals("get_model")) { + getModel(projectId, computeRegion, ns.getString("modelId")); + } + if (ns.get("command").equals("list_model_evaluations")) { + listModelEvaluations( + projectId, computeRegion, ns.getString("modelId"), ns.getString("filter")); + } + if (ns.get("command").equals("get_model_evaluation")) { + getModelEvaluation( + projectId, computeRegion, ns.getString("modelId"), ns.getString("modelEvaluationId")); + } + if (ns.get("command").equals("delete_model")) { + deleteModel(projectId, computeRegion, ns.getString("modelId")); + } + if (ns.get("command").equals("get_operation_status")) { + getOperationStatus(ns.getString("operationFullId")); + } + } catch (ArgumentParserException e) { + parser.handleError(e); + } + } +} diff --git a/translate/automl/src/main/java/com/google/cloud/translate/automl/PredictionApi.java b/translate/automl/src/main/java/com/google/cloud/translate/automl/PredictionApi.java new file mode 100644 index 00000000000..d3b1170897f --- /dev/null +++ b/translate/automl/src/main/java/com/google/cloud/translate/automl/PredictionApi.java @@ -0,0 +1,140 @@ +/* + * Copyright 2018 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * This application demonstrates how to perform basic operations on prediction + * with the Google AutoML Vision API. + * + * For more information, the documentation at + * https://cloud.google.com/vision/automl/docs. + */ + +package com.google.cloud.translate.automl; + +// Imports the Google Cloud client library +import com.google.cloud.automl.v1beta1.ExamplePayload; +import com.google.cloud.automl.v1beta1.ModelName; +import com.google.cloud.automl.v1beta1.PredictResponse; +import com.google.cloud.automl.v1beta1.PredictionServiceClient; + +import com.google.cloud.automl.v1beta1.TextSnippet; +import java.io.IOException; +import java.io.PrintStream; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.HashMap; +import java.util.Map; + +import net.sourceforge.argparse4j.ArgumentParsers; +import net.sourceforge.argparse4j.inf.ArgumentParser; +import net.sourceforge.argparse4j.inf.ArgumentParserException; +import net.sourceforge.argparse4j.inf.Namespace; +import net.sourceforge.argparse4j.inf.Subparser; +import net.sourceforge.argparse4j.inf.Subparsers; + +/** + * Google Cloud AutoML Translate API sample application. Example usage: mvn package exec:java + * -Dexec.mainClass ='com.google.cloud.vision.samples.automl.PredictionApi' -Dexec.args='predict + * [modelId] [path-to-image] [scoreThreshold]' + */ +public class PredictionApi { + + // [START automl_translation_predict] + + /** + * Demonstrates using the AutoML client to predict an image. + * + * @param projectId the Id of the project. + * @param computeRegion the Region name. + * @param modelId the Id of the model which will be used for text classification. + * @param filePath the Local text file path of the content to be classified. + * @param translationAllowFallback set to true to use a Google translation. + * @throws IOException on Input/Output errors. + */ + public static void predict( + String projectId, + String computeRegion, + String modelId, + String filePath, + boolean translationAllowFallback) + throws IOException { + // Instantiate client for prediction service. + PredictionServiceClient predictionClient = PredictionServiceClient.create(); + + // Get the full path of the model. + ModelName name = ModelName.of(projectId, computeRegion, modelId); + + // Read the file content for translation. + String content = new String(Files.readAllBytes(Paths.get(filePath))); + + TextSnippet textSnippet = TextSnippet.newBuilder().setContent(content).build(); + + // Set the payload by giving the content of the file. + ExamplePayload payload = ExamplePayload.newBuilder().setTextSnippet(textSnippet).build(); + + // Additional parameters that can be provided for prediction + Map params = new HashMap<>(); + if (translationAllowFallback) { + params.put("translation_allow_fallback", "True");//Allow Google Translation Model + } + + PredictResponse response = predictionClient.predict(name, payload, params); + TextSnippet translatedContent = response.getPayload(0).getTranslation().getTranslatedContent(); + + System.out.println(String.format("Translated Content: %s", translatedContent.getContent())); + } + // [END automl_translation_predict] + + public static void main(String[] args) throws IOException { + PredictionApi predictApi = new PredictionApi(); + predictApi.argsHelper(args, System.out); + } + + public static void argsHelper(String[] args, PrintStream out) throws IOException { + ArgumentParser parser = ArgumentParsers.newFor("PredictionApi") + .build() + .defaultHelp(true) + .description("Prediction API Operation"); + Subparsers subparsers = parser.addSubparsers().dest("command"); + + Subparser predictParser = subparsers.addParser("predict"); + predictParser.addArgument("modelId"); + predictParser.addArgument("filePath"); + predictParser + .addArgument("translationAllowFallback") + .nargs("?") + .type(Boolean.class) + .setDefault(Boolean.FALSE); + + String projectId = System.getenv("PROJECT_ID"); + String computeRegion = System.getenv("REGION_NAME"); + + Namespace ns = null; + try { + ns = parser.parseArgs(args); + if (ns.get("command").equals("predict")) { + predict( + projectId, + computeRegion, + ns.getString("modelId"), + ns.getString("filePath"), + ns.getBoolean("translationAllowFallback")); + } + } catch (ArgumentParserException e) { + parser.handleError(e); + } + } +} From 4578cc5863371021306f9333c7b943df2199980d Mon Sep 17 00:00:00 2001 From: nirupa-kumar Date: Mon, 23 Jul 2018 16:25:35 -0700 Subject: [PATCH 09/15] Triggering tests --- .../java/com/google/cloud/translate/automl/DatasetApiIT.java | 1 - 1 file changed, 1 deletion(-) diff --git a/translate/automl/src/test/java/com/google/cloud/translate/automl/DatasetApiIT.java b/translate/automl/src/test/java/com/google/cloud/translate/automl/DatasetApiIT.java index 7ceda3e4445..1741fd70bde 100644 --- a/translate/automl/src/test/java/com/google/cloud/translate/automl/DatasetApiIT.java +++ b/translate/automl/src/test/java/com/google/cloud/translate/automl/DatasetApiIT.java @@ -17,7 +17,6 @@ package com.google.cloud.translate.automl; import static com.google.common.truth.Truth.assertThat; -import static java.lang.Boolean.FALSE; import java.io.ByteArrayOutputStream; import java.io.PrintStream; From 17f1b5df4eb57046010141f970006900034d76ea Mon Sep 17 00:00:00 2001 From: nirupa-kumar Date: Mon, 23 Jul 2018 16:42:52 -0700 Subject: [PATCH 10/15] Triggering tests --- .../java/com/google/cloud/language/samples/DatasetApiIT.java | 2 +- .../java/com/google/cloud/translate/automl/DatasetApiIT.java | 2 +- .../com/google/cloud/vision/samples/automl/DatasetApiIT.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/language/automl/src/test/java/com/google/cloud/language/samples/DatasetApiIT.java b/language/automl/src/test/java/com/google/cloud/language/samples/DatasetApiIT.java index 1b43dd04055..35f2dbf2f71 100644 --- a/language/automl/src/test/java/com/google/cloud/language/samples/DatasetApiIT.java +++ b/language/automl/src/test/java/com/google/cloud/language/samples/DatasetApiIT.java @@ -36,7 +36,7 @@ public class DatasetApiIT { private static final String PROJECT_ID = "java-docs-samples-testing"; private static final String BUCKET = PROJECT_ID + "-vcm"; private static final String COMPUTE_REGION = "us-central1"; - private static final String DATASET_NAME = "test_dataset"; + private static final String DATASET_NAME = "test_language_dataset"; private ByteArrayOutputStream bout; private PrintStream out; private DatasetApi app; diff --git a/translate/automl/src/test/java/com/google/cloud/translate/automl/DatasetApiIT.java b/translate/automl/src/test/java/com/google/cloud/translate/automl/DatasetApiIT.java index 1741fd70bde..2f47e55968a 100644 --- a/translate/automl/src/test/java/com/google/cloud/translate/automl/DatasetApiIT.java +++ b/translate/automl/src/test/java/com/google/cloud/translate/automl/DatasetApiIT.java @@ -35,7 +35,7 @@ public class DatasetApiIT { private static final String PROJECT_ID = "java-docs-samples-testing"; private static final String BUCKET = PROJECT_ID + "-vcm"; private static final String COMPUTE_REGION = "us-central1"; - private static final String DATASET_NAME = "test_dataset"; + private static final String DATASET_NAME = "test_translate_dataset"; private ByteArrayOutputStream bout; private PrintStream out; private DatasetApi app; diff --git a/vision/automl/src/test/java/com/google/cloud/vision/samples/automl/DatasetApiIT.java b/vision/automl/src/test/java/com/google/cloud/vision/samples/automl/DatasetApiIT.java index 1a45326169a..41cf9dec9a5 100644 --- a/vision/automl/src/test/java/com/google/cloud/vision/samples/automl/DatasetApiIT.java +++ b/vision/automl/src/test/java/com/google/cloud/vision/samples/automl/DatasetApiIT.java @@ -36,7 +36,7 @@ public class DatasetApiIT { private static final String PROJECT_ID = "java-docs-samples-testing"; private static final String BUCKET = PROJECT_ID + "-vcm"; private static final String COMPUTE_REGION = "us-central1"; - private static final String DATASET_NAME = "test_dataset"; + private static final String DATASET_NAME = "test_vision_dataset"; private ByteArrayOutputStream bout; private PrintStream out; private DatasetApi app; From 03db78e0c9634639807c85ccbe7f00e1ecf63b62 Mon Sep 17 00:00:00 2001 From: nirupa-kumar Date: Tue, 24 Jul 2018 09:12:27 -0700 Subject: [PATCH 11/15] Updates based on comments --- language/automl/README.md | 6 ++-- translate/automl/README.md | 7 ++-- .../cloud/translate/automl/PredictionApi.java | 36 +++++-------------- vision/automl/README.md | 10 +++--- 4 files changed, 22 insertions(+), 37 deletions(-) diff --git a/language/automl/README.md b/language/automl/README.md index 97e17bee204..dfaa84b790c 100644 --- a/language/automl/README.md +++ b/language/automl/README.md @@ -3,13 +3,13 @@ Open in Cloud Shell -[Google Cloud Natural Language API][language] provides feature detection for images. +[Google Cloud AutoML Natural Language API][language] provides feature detection for images. This API is part of the larger collection of Cloud Machine Learning APIs. This sample Java application demonstrates how to access the Cloud Natural Language AutoML API using the [Google Cloud Client Library for Java][google-cloud-java]. -[language]: https://cloud.google.com/language/docs/ +[language]: https://cloud.google.com/language/automl/docs/ [google-cloud-java]: https://github.com/GoogleCloudPlatform/google-cloud-java ## Set the environment variables @@ -46,7 +46,7 @@ mvn exec:java -Dexec.mainClass="com.google.cloud.language.samples.DatasetApi" -D #### Import data ``` -mvn exec:java -Dexec.mainClass="com.google.cloud.language.samples.DatasetApi" -Dexec.args="import_data gs://java-docs-samples-testing/happiness.csv" +mvn exec:java -Dexec.mainClass="com.google.cloud.language.samples.DatasetApi" -Dexec.args="import_data [dataset-id] gs://java-docs-samples-testing/happiness.csv" ``` ### Model API diff --git a/translate/automl/README.md b/translate/automl/README.md index e2248a17de7..d0416587814 100644 --- a/translate/automl/README.md +++ b/translate/automl/README.md @@ -3,12 +3,15 @@ Open in Cloud Shell -[Google Cloud Translate API][translate] provides feature AutoML. +[Google Cloud AutoML Translation API][translate] provides feature AutoML. This API is part of the larger collection of Cloud Machine Learning APIs. This sample Java application demonstrates how to access the Cloud Translate AutoML API using the [Google Cloud Client Library for Java][google-cloud-java]. +[translate]: https://cloud.google.com/translate/automl/docs/ +[google-cloud-java]: https://github.com/GoogleCloudPlatform/google-cloud-java + ## Set the environment variables PROJECT_ID = [Id of the project] @@ -43,7 +46,7 @@ mvn exec:java -Dexec.mainClass="com.google.cloud.translate.samples.DatasetApi" - #### Import data ``` -mvn exec:java -Dexec.mainClass="com.google.cloud.translate.samples.DatasetApi" -Dexec.args="import_data gs://java-docs-samples-testing/en-ja.csv" +mvn exec:java -Dexec.mainClass="com.google.cloud.translate.samples.DatasetApi" -Dexec.args="import_data [dataset-id] gs://java-docs-samples-testing/en-ja.csv" ``` ### Model API diff --git a/translate/automl/src/main/java/com/google/cloud/translate/automl/PredictionApi.java b/translate/automl/src/main/java/com/google/cloud/translate/automl/PredictionApi.java index d3b1170897f..38e68fb811a 100644 --- a/translate/automl/src/main/java/com/google/cloud/translate/automl/PredictionApi.java +++ b/translate/automl/src/main/java/com/google/cloud/translate/automl/PredictionApi.java @@ -47,8 +47,8 @@ /** * Google Cloud AutoML Translate API sample application. Example usage: mvn package exec:java - * -Dexec.mainClass ='com.google.cloud.vision.samples.automl.PredictionApi' -Dexec.args='predict - * [modelId] [path-to-image] [scoreThreshold]' + * -Dexec.mainClass ='com.google.cloud.translate.automl.PredictionApi' -Dexec.args='predict + * [modelId] [file-path]' */ public class PredictionApi { @@ -61,16 +61,10 @@ public class PredictionApi { * @param computeRegion the Region name. * @param modelId the Id of the model which will be used for text classification. * @param filePath the Local text file path of the content to be classified. - * @param translationAllowFallback set to true to use a Google translation. * @throws IOException on Input/Output errors. */ public static void predict( - String projectId, - String computeRegion, - String modelId, - String filePath, - boolean translationAllowFallback) - throws IOException { + String projectId, String computeRegion, String modelId, String filePath) throws IOException { // Instantiate client for prediction service. PredictionServiceClient predictionClient = PredictionServiceClient.create(); @@ -87,9 +81,6 @@ public static void predict( // Additional parameters that can be provided for prediction Map params = new HashMap<>(); - if (translationAllowFallback) { - params.put("translation_allow_fallback", "True");//Allow Google Translation Model - } PredictResponse response = predictionClient.predict(name, payload, params); TextSnippet translatedContent = response.getPayload(0).getTranslation().getTranslatedContent(); @@ -104,20 +95,16 @@ public static void main(String[] args) throws IOException { } public static void argsHelper(String[] args, PrintStream out) throws IOException { - ArgumentParser parser = ArgumentParsers.newFor("PredictionApi") - .build() - .defaultHelp(true) - .description("Prediction API Operation"); + ArgumentParser parser = + ArgumentParsers.newFor("PredictionApi") + .build() + .defaultHelp(true) + .description("Prediction API Operation"); Subparsers subparsers = parser.addSubparsers().dest("command"); Subparser predictParser = subparsers.addParser("predict"); predictParser.addArgument("modelId"); predictParser.addArgument("filePath"); - predictParser - .addArgument("translationAllowFallback") - .nargs("?") - .type(Boolean.class) - .setDefault(Boolean.FALSE); String projectId = System.getenv("PROJECT_ID"); String computeRegion = System.getenv("REGION_NAME"); @@ -126,12 +113,7 @@ public static void argsHelper(String[] args, PrintStream out) throws IOException try { ns = parser.parseArgs(args); if (ns.get("command").equals("predict")) { - predict( - projectId, - computeRegion, - ns.getString("modelId"), - ns.getString("filePath"), - ns.getBoolean("translationAllowFallback")); + predict(projectId, computeRegion, ns.getString("modelId"), ns.getString("filePath")); } } catch (ArgumentParserException e) { parser.handleError(e); diff --git a/vision/automl/README.md b/vision/automl/README.md index 24a73c48ece..67109fe0f4f 100644 --- a/vision/automl/README.md +++ b/vision/automl/README.md @@ -3,13 +3,13 @@ Open in Cloud Shell -[Google Cloud Vision API][vision] provides feature detection for images. +[Google Cloud AutoML Vision API][vision] provides feature detection for images. This API is part of the larger collection of Cloud Machine Learning APIs. This sample Java application demonstrates how to access the Cloud Vision API using the [Google Cloud Client Library for Java][google-cloud-java]. -[vision]: https://cloud.google.com/vision/docs/ +[vision]: https://cloud.google.com/vision/automl/docs/ [google-cloud-java]: https://github.com/GoogleCloudPlatform/google-cloud-java ## Set the environment variables @@ -45,14 +45,14 @@ mvn exec:java -Dexec.mainClass="com.google.cloud.vision.samples.automl.DatasetAp #### Import data ``` -mvn exec:java -Dexec.mainClass="com.google.cloud.vision.samples.automl.DatasetApi" -Dexec.args="import_data gs://java-docs-samples-testing/flower_traindata.csv" +mvn exec:java -Dexec.mainClass="com.google.cloud.vision.samples.automl.DatasetApi" -Dexec.args="import_data [dataset-id] gs://java-docs-samples-testing/flower_traindata.csv" ``` ### Model API #### Create Model ``` -mvn exec:java -Dexec.mainClass="com.google.cloud.vision.samples.automl.ModelApi" -Dexec.args="create_model test_model" +mvn exec:java -Dexec.mainClass="com.google.cloud.vision.samples.automl.ModelApi" -Dexec.args="create_model [dataset-id] test_model [training-budget] " ``` #### List Models @@ -77,7 +77,7 @@ mvn exec:java -Dexec.mainClass="com.google.cloud.vision.samples.automl.ModelApi" #### Delete Model ``` -mvn exec:java-Dexec.mainClass="com.google.cloud.vision.samples.automl.ModeltApi" -Dexec.args="delete_model [model-id]" +mvn exec:java-Dexec.mainClass="com.google.cloud.vision.samples.automl.ModelApi" -Dexec.args="delete_model [model-id]" ``` ### Predict API From 3c0941205567254b09c5fa564695d2f22bf7b79d Mon Sep 17 00:00:00 2001 From: nirupa-kumar Date: Tue, 24 Jul 2018 09:25:40 -0700 Subject: [PATCH 12/15] Updates after review comments --- .../com/google/cloud/vision/samples/automl/PredictionApi.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vision/automl/src/main/java/com/google/cloud/vision/samples/automl/PredictionApi.java b/vision/automl/src/main/java/com/google/cloud/vision/samples/automl/PredictionApi.java index a76c3f40caf..6a6a2b50460 100644 --- a/vision/automl/src/main/java/com/google/cloud/vision/samples/automl/PredictionApi.java +++ b/vision/automl/src/main/java/com/google/cloud/vision/samples/automl/PredictionApi.java @@ -89,7 +89,7 @@ public static void predict( // Additional parameters that can be provided for prediction e.g. Score Threshold Map params = new HashMap<>(); if (scoreThreshold != null) { - params.put("scoreThreshold", scoreThreshold); + params.put("score_threshold", scoreThreshold); } // Perform the AutoML Prediction request PredictResponse response = predictionClient.predict(name, examplePayload, params); From ef26399459a89f93ee195735c2a94ce1e2ed34a8 Mon Sep 17 00:00:00 2001 From: nirupa-kumar Date: Mon, 30 Jul 2018 14:44:38 -0700 Subject: [PATCH 13/15] Fixed build issue --- .../java/com/google/cloud/translate/automl/PredictionApiIT.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/translate/automl/src/test/java/com/google/cloud/translate/automl/PredictionApiIT.java b/translate/automl/src/test/java/com/google/cloud/translate/automl/PredictionApiIT.java index 962a0fd0802..611694ef874 100644 --- a/translate/automl/src/test/java/com/google/cloud/translate/automl/PredictionApiIT.java +++ b/translate/automl/src/test/java/com/google/cloud/translate/automl/PredictionApiIT.java @@ -55,7 +55,7 @@ public void tearDown() { @Test public void testPredict() throws Exception { // Act - PredictionApi.predict(PROJECT_ID, COMPUTE_REGION, modelId, filePath,FALSE); + PredictionApi.predict(PROJECT_ID, COMPUTE_REGION, modelId, filePath); // Assert String got = bout.toString(); From 2607c8566489a9c339ca031c1a14118653382ac4 Mon Sep 17 00:00:00 2001 From: nirupa-kumar Date: Tue, 31 Jul 2018 11:46:28 -0700 Subject: [PATCH 14/15] Fixed build issue --- translate/automl/pom.xml | 2 +- .../java/com/google/cloud/translate/automl/PredictionApiIT.java | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/translate/automl/pom.xml b/translate/automl/pom.xml index 488081b3fe2..833d477e4c1 100644 --- a/translate/automl/pom.xml +++ b/translate/automl/pom.xml @@ -1,5 +1,5 @@ 4.0.0 - com.example.vision + com.google.cloud.language.samples language-automl jar diff --git a/language/automl/src/main/java/com/google/cloud/language/samples/ModelApi.java b/language/automl/src/main/java/com/google/cloud/language/samples/ModelApi.java index 16b4841f290..e1ce03b6846 100644 --- a/language/automl/src/main/java/com/google/cloud/language/samples/ModelApi.java +++ b/language/automl/src/main/java/com/google/cloud/language/samples/ModelApi.java @@ -131,14 +131,14 @@ public static void listModels(String projectId, String computeRegion, String fil LocationName projectLocation = LocationName.of(projectId, computeRegion); // Create list models request. - ListModelsRequest listModlesRequest = + ListModelsRequest listModelsRequest = ListModelsRequest.newBuilder() .setParent(projectLocation.toString()) .setFilter(filter) .build(); System.out.println("List of models:"); - for (Model model : client.listModels(listModlesRequest).iterateAll()) { + for (Model model : client.listModels(listModelsRequest).iterateAll()) { // Display the model information. System.out.println(String.format("Model name: %s", model.getName())); System.out.println( diff --git a/language/automl/src/test/java/com/google/cloud/language/samples/DatasetApiIT.java b/language/automl/src/test/java/com/google/cloud/language/samples/DatasetApiIT.java index 35f2dbf2f71..793c64ed11f 100644 --- a/language/automl/src/test/java/com/google/cloud/language/samples/DatasetApiIT.java +++ b/language/automl/src/test/java/com/google/cloud/language/samples/DatasetApiIT.java @@ -34,7 +34,7 @@ public class DatasetApiIT { private static final String PROJECT_ID = "java-docs-samples-testing"; - private static final String BUCKET = PROJECT_ID + "-vcm"; + private static final String BUCKET = PROJECT_ID + "-lcm"; private static final String COMPUTE_REGION = "us-central1"; private static final String DATASET_NAME = "test_language_dataset"; private ByteArrayOutputStream bout; diff --git a/translate/automl/src/main/java/com/google/cloud/translate/automl/DatasetApi.java b/translate/automl/src/main/java/com/google/cloud/translate/automl/DatasetApi.java index 03cc96aa45f..e357f12e6b0 100644 --- a/translate/automl/src/main/java/com/google/cloud/translate/automl/DatasetApi.java +++ b/translate/automl/src/main/java/com/google/cloud/translate/automl/DatasetApi.java @@ -45,7 +45,7 @@ */ public class DatasetApi { - // [START automl_translate_create_dataset] + // [START automl_translation_create_dataset] /** * Demonstrates using the AutoML client to create a dataset * diff --git a/vision/automl/pom.xml b/vision/automl/pom.xml index 5b5dd838624..e2b8355a1d1 100644 --- a/vision/automl/pom.xml +++ b/vision/automl/pom.xml @@ -15,7 +15,7 @@ --> 4.0.0 - com.example.vision + com.example.vision.samples.automl vision-automl jar