// Copyright 2024 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.

syntax = "proto3";

package google.cloud.aiplatform.v1;

import "google/api/annotations.proto";
import "google/api/client.proto";
import "google/api/field_behavior.proto";
import "google/api/resource.proto";
import "google/cloud/aiplatform/v1/operation.proto";
import "google/cloud/aiplatform/v1/study.proto";
import "google/longrunning/operations.proto";
import "google/protobuf/empty.proto";
import "google/protobuf/timestamp.proto";

option csharp_namespace = "Google.Cloud.AIPlatform.V1";
option go_package = "cloud.google.com/go/aiplatform/apiv1/aiplatformpb;aiplatformpb";
option java_multiple_files = true;
option java_outer_classname = "VizierServiceProto";
option java_package = "com.google.cloud.aiplatform.v1";
option php_namespace = "Google\\Cloud\\AIPlatform\\V1";
option ruby_package = "Google::Cloud::AIPlatform::V1";

// Vertex AI Vizier API.
//
// Vertex AI Vizier is a service to solve blackbox optimization problems,
// such as tuning machine learning hyperparameters and searching over deep
// learning architectures.
service VizierService {
  option (google.api.default_host) = "aiplatform.googleapis.com";
  option (google.api.oauth_scopes) =
      "https://www.googleapis.com/auth/cloud-platform";

  // Creates a Study. A resource name will be generated after creation of the
  // Study.
  rpc CreateStudy(CreateStudyRequest) returns (Study) {
    option (google.api.http) = {
      post: "/v1/{parent=projects/*/locations/*}/studies"
      body: "study"
    };
    option (google.api.method_signature) = "parent,study";
  }

  // Gets a Study by name.
  rpc GetStudy(GetStudyRequest) returns (Study) {
    option (google.api.http) = {
      get: "/v1/{name=projects/*/locations/*/studies/*}"
    };
    option (google.api.method_signature) = "name";
  }

  // Lists all the studies in a region for an associated project.
  rpc ListStudies(ListStudiesRequest) returns (ListStudiesResponse) {
    option (google.api.http) = {
      get: "/v1/{parent=projects/*/locations/*}/studies"
    };
    option (google.api.method_signature) = "parent";
  }

  // Deletes a Study.
  rpc DeleteStudy(DeleteStudyRequest) returns (google.protobuf.Empty) {
    option (google.api.http) = {
      delete: "/v1/{name=projects/*/locations/*/studies/*}"
    };
    option (google.api.method_signature) = "name";
  }

  // Looks a study up using the user-defined display_name field instead of the
  // fully qualified resource name.
  rpc LookupStudy(LookupStudyRequest) returns (Study) {
    option (google.api.http) = {
      post: "/v1/{parent=projects/*/locations/*}/studies:lookup"
      body: "*"
    };
    option (google.api.method_signature) = "parent";
  }

  // Adds one or more Trials to a Study, with parameter values
  // suggested by Vertex AI Vizier. Returns a long-running
  // operation associated with the generation of Trial suggestions.
  // When this long-running operation succeeds, it will contain
  // a
  // [SuggestTrialsResponse][google.cloud.aiplatform.v1.SuggestTrialsResponse].
  rpc SuggestTrials(SuggestTrialsRequest)
      returns (google.longrunning.Operation) {
    option (google.api.http) = {
      post: "/v1/{parent=projects/*/locations/*/studies/*}/trials:suggest"
      body: "*"
    };
    option (google.longrunning.operation_info) = {
      response_type: "SuggestTrialsResponse"
      metadata_type: "SuggestTrialsMetadata"
    };
  }

  // Adds a user provided Trial to a Study.
  rpc CreateTrial(CreateTrialRequest) returns (Trial) {
    option (google.api.http) = {
      post: "/v1/{parent=projects/*/locations/*/studies/*}/trials"
      body: "trial"
    };
    option (google.api.method_signature) = "parent,trial";
  }

  // Gets a Trial.
  rpc GetTrial(GetTrialRequest) returns (Trial) {
    option (google.api.http) = {
      get: "/v1/{name=projects/*/locations/*/studies/*/trials/*}"
    };
    option (google.api.method_signature) = "name";
  }

  // Lists the Trials associated with a Study.
  rpc ListTrials(ListTrialsRequest) returns (ListTrialsResponse) {
    option (google.api.http) = {
      get: "/v1/{parent=projects/*/locations/*/studies/*}/trials"
    };
    option (google.api.method_signature) = "parent";
  }

  // Adds a measurement of the objective metrics to a Trial. This measurement
  // is assumed to have been taken before the Trial is complete.
  rpc AddTrialMeasurement(AddTrialMeasurementRequest) returns (Trial) {
    option (google.api.http) = {
      post: "/v1/{trial_name=projects/*/locations/*/studies/*/trials/*}:addTrialMeasurement"
      body: "*"
    };
  }

  // Marks a Trial as complete.
  rpc CompleteTrial(CompleteTrialRequest) returns (Trial) {
    option (google.api.http) = {
      post: "/v1/{name=projects/*/locations/*/studies/*/trials/*}:complete"
      body: "*"
    };
  }

  // Deletes a Trial.
  rpc DeleteTrial(DeleteTrialRequest) returns (google.protobuf.Empty) {
    option (google.api.http) = {
      delete: "/v1/{name=projects/*/locations/*/studies/*/trials/*}"
    };
    option (google.api.method_signature) = "name";
  }

  // Checks  whether a Trial should stop or not. Returns a
  // long-running operation. When the operation is successful,
  // it will contain a
  // [CheckTrialEarlyStoppingStateResponse][google.cloud.aiplatform.v1.CheckTrialEarlyStoppingStateResponse].
  rpc CheckTrialEarlyStoppingState(CheckTrialEarlyStoppingStateRequest)
      returns (google.longrunning.Operation) {
    option (google.api.http) = {
      post: "/v1/{trial_name=projects/*/locations/*/studies/*/trials/*}:checkTrialEarlyStoppingState"
      body: "*"
    };
    option (google.longrunning.operation_info) = {
      response_type: "CheckTrialEarlyStoppingStateResponse"
      metadata_type: "CheckTrialEarlyStoppingStateMetatdata"
    };
  }

  // Stops a Trial.
  rpc StopTrial(StopTrialRequest) returns (Trial) {
    option (google.api.http) = {
      post: "/v1/{name=projects/*/locations/*/studies/*/trials/*}:stop"
      body: "*"
    };
  }

  // Lists the pareto-optimal Trials for multi-objective Study or the
  // optimal Trials for single-objective Study. The definition of
  // pareto-optimal can be checked in wiki page.
  // https://en.wikipedia.org/wiki/Pareto_efficiency
  rpc ListOptimalTrials(ListOptimalTrialsRequest)
      returns (ListOptimalTrialsResponse) {
    option (google.api.http) = {
      post: "/v1/{parent=projects/*/locations/*/studies/*}/trials:listOptimalTrials"
      body: "*"
    };
    option (google.api.method_signature) = "parent";
  }
}

// Request message for
// [VizierService.GetStudy][google.cloud.aiplatform.v1.VizierService.GetStudy].
message GetStudyRequest {
  // Required. The name of the Study resource.
  // Format: `projects/{project}/locations/{location}/studies/{study}`
  string name = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "aiplatform.googleapis.com/Study"
    }
  ];
}

// Request message for
// [VizierService.CreateStudy][google.cloud.aiplatform.v1.VizierService.CreateStudy].
message CreateStudyRequest {
  // Required. The resource name of the Location to create the CustomJob in.
  // Format: `projects/{project}/locations/{location}`
  string parent = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "locations.googleapis.com/Location"
    }
  ];

  // Required. The Study configuration used to create the Study.
  Study study = 2 [(google.api.field_behavior) = REQUIRED];
}

// Request message for
// [VizierService.ListStudies][google.cloud.aiplatform.v1.VizierService.ListStudies].
message ListStudiesRequest {
  // Required. The resource name of the Location to list the Study from.
  // Format: `projects/{project}/locations/{location}`
  string parent = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "locations.googleapis.com/Location"
    }
  ];

  // Optional. A page token to request the next page of results.
  // If unspecified, there are no subsequent pages.
  string page_token = 2 [(google.api.field_behavior) = OPTIONAL];

  // Optional. The maximum number of studies to return per "page" of results.
  // If unspecified, service will pick an appropriate default.
  int32 page_size = 3 [(google.api.field_behavior) = OPTIONAL];
}

// Response message for
// [VizierService.ListStudies][google.cloud.aiplatform.v1.VizierService.ListStudies].
message ListStudiesResponse {
  // The studies associated with the project.
  repeated Study studies = 1;

  // Passes this token as the `page_token` field of the request for a
  // subsequent call.
  // If this field is omitted, there are no subsequent pages.
  string next_page_token = 2;
}

// Request message for
// [VizierService.DeleteStudy][google.cloud.aiplatform.v1.VizierService.DeleteStudy].
message DeleteStudyRequest {
  // Required. The name of the Study resource to be deleted.
  // Format: `projects/{project}/locations/{location}/studies/{study}`
  string name = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "aiplatform.googleapis.com/Study"
    }
  ];
}

// Request message for
// [VizierService.LookupStudy][google.cloud.aiplatform.v1.VizierService.LookupStudy].
message LookupStudyRequest {
  // Required. The resource name of the Location to get the Study from.
  // Format: `projects/{project}/locations/{location}`
  string parent = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "locations.googleapis.com/Location"
    }
  ];

  // Required. The user-defined display name of the Study
  string display_name = 2 [(google.api.field_behavior) = REQUIRED];
}

// Request message for
// [VizierService.SuggestTrials][google.cloud.aiplatform.v1.VizierService.SuggestTrials].
message SuggestTrialsRequest {
  // Required. The project and location that the Study belongs to.
  // Format: `projects/{project}/locations/{location}/studies/{study}`
  string parent = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "aiplatform.googleapis.com/Study"
    }
  ];

  // Required. The number of suggestions requested. It must be positive.
  int32 suggestion_count = 2 [(google.api.field_behavior) = REQUIRED];

  // Required. The identifier of the client that is requesting the suggestion.
  //
  // If multiple SuggestTrialsRequests have the same `client_id`,
  // the service will return the identical suggested Trial if the Trial is
  // pending, and provide a new Trial if the last suggested Trial was completed.
  string client_id = 3 [(google.api.field_behavior) = REQUIRED];

  // Optional. This allows you to specify the "context" for a Trial; a context
  // is a slice (a subspace) of the search space.
  //
  // Typical uses for contexts:
  // 1) You are using Vizier to tune a server for best performance, but there's
  //   a strong weekly cycle.  The context specifies the day-of-week.
  //   This allows Tuesday to generalize from Wednesday without assuming that
  //   everything is identical.
  // 2) Imagine you're optimizing some medical treatment for people.
  //   As they walk in the door, you know certain facts about them
  //   (e.g. sex, weight, height, blood-pressure).  Put that information in the
  //   context, and Vizier will adapt its suggestions to the patient.
  // 3) You want to do a fair A/B test efficiently.  Specify the "A" and "B"
  //   conditions as contexts, and Vizier will generalize between "A" and "B"
  //   conditions.  If they are similar, this will allow Vizier to converge
  //   to the optimum faster than if "A" and "B" were separate Studies.
  //   NOTE: You can also enter contexts as REQUESTED Trials, e.g. via the
  //   CreateTrial() RPC; that's the asynchronous option where you don't need a
  //   close association between contexts and suggestions.
  //
  // NOTE: All the Parameters you set in a context MUST be defined in the
  //   Study.
  // NOTE: You must supply 0 or $suggestion_count contexts.
  //   If you don't supply any contexts, Vizier will make suggestions
  //   from the full search space specified in the StudySpec; if you supply
  //   a full set of context, each suggestion will match the corresponding
  //   context.
  // NOTE: A Context with no features set matches anything, and allows
  //   suggestions from the full search space.
  // NOTE: Contexts MUST lie within the search space specified in the
  //   StudySpec.  It's an error if they don't.
  // NOTE: Contexts preferentially match ACTIVE then REQUESTED trials before
  //   new suggestions are generated.
  // NOTE: Generation of suggestions involves a match between a Context and
  //   (optionally) a REQUESTED trial; if that match is not fully specified, a
  //   suggestion will be geneated in the merged subspace.
  repeated TrialContext contexts = 4 [(google.api.field_behavior) = OPTIONAL];
}

// Response message for
// [VizierService.SuggestTrials][google.cloud.aiplatform.v1.VizierService.SuggestTrials].
message SuggestTrialsResponse {
  // A list of Trials.
  repeated Trial trials = 1;

  // The state of the Study.
  Study.State study_state = 2;

  // The time at which the operation was started.
  google.protobuf.Timestamp start_time = 3;

  // The time at which operation processing completed.
  google.protobuf.Timestamp end_time = 4;
}

// Details of operations that perform Trials suggestion.
message SuggestTrialsMetadata {
  // Operation metadata for suggesting Trials.
  GenericOperationMetadata generic_metadata = 1;

  // The identifier of the client that is requesting the suggestion.
  //
  // If multiple SuggestTrialsRequests have the same `client_id`,
  // the service will return the identical suggested Trial if the Trial is
  // pending, and provide a new Trial if the last suggested Trial was completed.
  string client_id = 2;
}

// Request message for
// [VizierService.CreateTrial][google.cloud.aiplatform.v1.VizierService.CreateTrial].
message CreateTrialRequest {
  // Required. The resource name of the Study to create the Trial in.
  // Format: `projects/{project}/locations/{location}/studies/{study}`
  string parent = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "aiplatform.googleapis.com/Study"
    }
  ];

  // Required. The Trial to create.
  Trial trial = 2 [(google.api.field_behavior) = REQUIRED];
}

// Request message for
// [VizierService.GetTrial][google.cloud.aiplatform.v1.VizierService.GetTrial].
message GetTrialRequest {
  // Required. The name of the Trial resource.
  // Format:
  // `projects/{project}/locations/{location}/studies/{study}/trials/{trial}`
  string name = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "aiplatform.googleapis.com/Trial"
    }
  ];
}

// Request message for
// [VizierService.ListTrials][google.cloud.aiplatform.v1.VizierService.ListTrials].
message ListTrialsRequest {
  // Required. The resource name of the Study to list the Trial from.
  // Format: `projects/{project}/locations/{location}/studies/{study}`
  string parent = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "aiplatform.googleapis.com/Study"
    }
  ];

  // Optional. A page token to request the next page of results.
  // If unspecified, there are no subsequent pages.
  string page_token = 2 [(google.api.field_behavior) = OPTIONAL];

  // Optional. The number of Trials to retrieve per "page" of results.
  // If unspecified, the service will pick an appropriate default.
  int32 page_size = 3 [(google.api.field_behavior) = OPTIONAL];
}

// Response message for
// [VizierService.ListTrials][google.cloud.aiplatform.v1.VizierService.ListTrials].
message ListTrialsResponse {
  // The Trials associated with the Study.
  repeated Trial trials = 1;

  // Pass this token as the `page_token` field of the request for a
  // subsequent call.
  // If this field is omitted, there are no subsequent pages.
  string next_page_token = 2;
}

// Request message for
// [VizierService.AddTrialMeasurement][google.cloud.aiplatform.v1.VizierService.AddTrialMeasurement].
message AddTrialMeasurementRequest {
  // Required. The name of the trial to add measurement.
  // Format:
  // `projects/{project}/locations/{location}/studies/{study}/trials/{trial}`
  string trial_name = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "aiplatform.googleapis.com/Trial"
    }
  ];

  // Required. The measurement to be added to a Trial.
  Measurement measurement = 3 [(google.api.field_behavior) = REQUIRED];
}

// Request message for
// [VizierService.CompleteTrial][google.cloud.aiplatform.v1.VizierService.CompleteTrial].
message CompleteTrialRequest {
  // Required. The Trial's name.
  // Format:
  // `projects/{project}/locations/{location}/studies/{study}/trials/{trial}`
  string name = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "aiplatform.googleapis.com/Trial"
    }
  ];

  // Optional. If provided, it will be used as the completed Trial's
  // final_measurement; Otherwise, the service will auto-select a
  // previously reported measurement as the final-measurement
  Measurement final_measurement = 2 [(google.api.field_behavior) = OPTIONAL];

  // Optional. True if the Trial cannot be run with the given Parameter, and
  // final_measurement will be ignored.
  bool trial_infeasible = 3 [(google.api.field_behavior) = OPTIONAL];

  // Optional. A human readable reason why the trial was infeasible. This should
  // only be provided if `trial_infeasible` is true.
  string infeasible_reason = 4 [(google.api.field_behavior) = OPTIONAL];
}

// Request message for
// [VizierService.DeleteTrial][google.cloud.aiplatform.v1.VizierService.DeleteTrial].
message DeleteTrialRequest {
  // Required. The Trial's name.
  // Format:
  // `projects/{project}/locations/{location}/studies/{study}/trials/{trial}`
  string name = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "aiplatform.googleapis.com/Trial"
    }
  ];
}

// Request message for
// [VizierService.CheckTrialEarlyStoppingState][google.cloud.aiplatform.v1.VizierService.CheckTrialEarlyStoppingState].
message CheckTrialEarlyStoppingStateRequest {
  // Required. The Trial's name.
  // Format:
  // `projects/{project}/locations/{location}/studies/{study}/trials/{trial}`
  string trial_name = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "aiplatform.googleapis.com/Trial"
    }
  ];
}

// Response message for
// [VizierService.CheckTrialEarlyStoppingState][google.cloud.aiplatform.v1.VizierService.CheckTrialEarlyStoppingState].
message CheckTrialEarlyStoppingStateResponse {
  // True if the Trial should stop.
  bool should_stop = 1;
}

// This message will be placed in the metadata field of a
// google.longrunning.Operation associated with a CheckTrialEarlyStoppingState
// request.
message CheckTrialEarlyStoppingStateMetatdata {
  // Operation metadata for suggesting Trials.
  GenericOperationMetadata generic_metadata = 1;

  // The name of the Study that the Trial belongs to.
  string study = 2;

  // The Trial name.
  string trial = 3;
}

// Request message for
// [VizierService.StopTrial][google.cloud.aiplatform.v1.VizierService.StopTrial].
message StopTrialRequest {
  // Required. The Trial's name.
  // Format:
  // `projects/{project}/locations/{location}/studies/{study}/trials/{trial}`
  string name = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "aiplatform.googleapis.com/Trial"
    }
  ];
}

// Request message for
// [VizierService.ListOptimalTrials][google.cloud.aiplatform.v1.VizierService.ListOptimalTrials].
message ListOptimalTrialsRequest {
  // Required. The name of the Study that the optimal Trial belongs to.
  string parent = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "aiplatform.googleapis.com/Study"
    }
  ];
}

// Response message for
// [VizierService.ListOptimalTrials][google.cloud.aiplatform.v1.VizierService.ListOptimalTrials].
message ListOptimalTrialsResponse {
  // The pareto-optimal Trials for multiple objective Study or the
  // optimal trial for single objective Study. The definition of
  // pareto-optimal can be checked in wiki page.
  // https://en.wikipedia.org/wiki/Pareto_efficiency
  repeated Trial optimal_trials = 1;
}
