// Copyright 2025 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/feature_selector.proto";
import "google/cloud/aiplatform/v1/types.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 = "FeaturestoreOnlineServiceProto";
option java_package = "com.google.cloud.aiplatform.v1";
option php_namespace = "Google\\Cloud\\AIPlatform\\V1";
option ruby_package = "Google::Cloud::AIPlatform::V1";

// A service for serving online feature values.
service FeaturestoreOnlineServingService {
  option (google.api.default_host) = "aiplatform.googleapis.com";
  option (google.api.oauth_scopes) =
      "https://www.googleapis.com/auth/cloud-platform";

  // Reads Feature values of a specific entity of an EntityType. For reading
  // feature values of multiple entities of an EntityType, please use
  // StreamingReadFeatureValues.
  rpc ReadFeatureValues(ReadFeatureValuesRequest)
      returns (ReadFeatureValuesResponse) {
    option (google.api.http) = {
      post: "/v1/{entity_type=projects/*/locations/*/featurestores/*/entityTypes/*}:readFeatureValues"
      body: "*"
    };
    option (google.api.method_signature) = "entity_type";
  }

  // Reads Feature values for multiple entities. Depending on their size, data
  // for different entities may be broken
  // up across multiple responses.
  rpc StreamingReadFeatureValues(StreamingReadFeatureValuesRequest)
      returns (stream ReadFeatureValuesResponse) {
    option (google.api.http) = {
      post: "/v1/{entity_type=projects/*/locations/*/featurestores/*/entityTypes/*}:streamingReadFeatureValues"
      body: "*"
    };
    option (google.api.method_signature) = "entity_type";
  }

  // Writes Feature values of one or more entities of an EntityType.
  //
  // The Feature values are merged into existing entities if any. The Feature
  // values to be written must have timestamp within the online storage
  // retention.
  rpc WriteFeatureValues(WriteFeatureValuesRequest)
      returns (WriteFeatureValuesResponse) {
    option (google.api.http) = {
      post: "/v1/{entity_type=projects/*/locations/*/featurestores/*/entityTypes/*}:writeFeatureValues"
      body: "*"
    };
    option (google.api.method_signature) = "entity_type,payloads";
  }
}

// Request message for
// [FeaturestoreOnlineServingService.WriteFeatureValues][google.cloud.aiplatform.v1.FeaturestoreOnlineServingService.WriteFeatureValues].
message WriteFeatureValuesRequest {
  // Required. The resource name of the EntityType for the entities being
  // written. Value format:
  // `projects/{project}/locations/{location}/featurestores/
  // {featurestore}/entityTypes/{entityType}`. For example,
  // for a machine learning model predicting user clicks on a website, an
  // EntityType ID could be `user`.
  string entity_type = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "aiplatform.googleapis.com/EntityType"
    }
  ];

  // Required. The entities to be written. Up to 100,000 feature values can be
  // written across all `payloads`.
  repeated WriteFeatureValuesPayload payloads = 2
      [(google.api.field_behavior) = REQUIRED];
}

// Contains Feature values to be written for a specific entity.
message WriteFeatureValuesPayload {
  // Required. The ID of the entity.
  string entity_id = 1 [(google.api.field_behavior) = REQUIRED];

  // Required. Feature values to be written, mapping from Feature ID to value.
  // Up to 100,000 `feature_values` entries may be written across all payloads.
  // The feature generation time, aligned by days, must be no older than five
  // years (1825 days) and no later than one year (366 days) in the future.
  map<string, FeatureValue> feature_values = 2
      [(google.api.field_behavior) = REQUIRED];
}

// Response message for
// [FeaturestoreOnlineServingService.WriteFeatureValues][google.cloud.aiplatform.v1.FeaturestoreOnlineServingService.WriteFeatureValues].
message WriteFeatureValuesResponse {}

// Request message for
// [FeaturestoreOnlineServingService.ReadFeatureValues][google.cloud.aiplatform.v1.FeaturestoreOnlineServingService.ReadFeatureValues].
message ReadFeatureValuesRequest {
  // Required. The resource name of the EntityType for the entity being read.
  // Value format:
  // `projects/{project}/locations/{location}/featurestores/{featurestore}/entityTypes/{entityType}`.
  // For example, for a machine learning model predicting user clicks on a
  // website, an EntityType ID could be `user`.
  string entity_type = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "aiplatform.googleapis.com/EntityType"
    }
  ];

  // Required. ID for a specific entity. For example,
  // for a machine learning model predicting user clicks on a website, an entity
  // ID could be `user_123`.
  string entity_id = 2 [(google.api.field_behavior) = REQUIRED];

  // Required. Selector choosing Features of the target EntityType.
  FeatureSelector feature_selector = 3 [(google.api.field_behavior) = REQUIRED];
}

// Response message for
// [FeaturestoreOnlineServingService.ReadFeatureValues][google.cloud.aiplatform.v1.FeaturestoreOnlineServingService.ReadFeatureValues].
message ReadFeatureValuesResponse {
  // Metadata for requested Features.
  message FeatureDescriptor {
    // Feature ID.
    string id = 1;
  }

  // Response header with metadata for the requested
  // [ReadFeatureValuesRequest.entity_type][google.cloud.aiplatform.v1.ReadFeatureValuesRequest.entity_type]
  // and Features.
  message Header {
    // The resource name of the EntityType from the
    // [ReadFeatureValuesRequest][google.cloud.aiplatform.v1.ReadFeatureValuesRequest].
    // Value format:
    // `projects/{project}/locations/{location}/featurestores/{featurestore}/entityTypes/{entityType}`.
    string entity_type = 1 [(google.api.resource_reference) = {
      type: "aiplatform.googleapis.com/EntityType"
    }];

    // List of Feature metadata corresponding to each piece of
    // [ReadFeatureValuesResponse.EntityView.data][google.cloud.aiplatform.v1.ReadFeatureValuesResponse.EntityView.data].
    repeated FeatureDescriptor feature_descriptors = 2;
  }

  // Entity view with Feature values.
  message EntityView {
    // Container to hold value(s), successive in time, for one Feature from the
    // request.
    message Data {
      oneof data {
        // Feature value if a single value is requested.
        FeatureValue value = 1;

        // Feature values list if values, successive in time, are requested.
        // If the requested number of values is greater than the number of
        // existing Feature values, nonexistent values are omitted instead of
        // being returned as empty.
        FeatureValueList values = 2;
      }
    }

    // ID of the requested entity.
    string entity_id = 1;

    // Each piece of data holds the k
    // requested values for one requested Feature. If no values
    // for the requested Feature exist, the corresponding cell will be empty.
    // This has the same size and is in the same order as the features from the
    // header
    // [ReadFeatureValuesResponse.header][google.cloud.aiplatform.v1.ReadFeatureValuesResponse.header].
    repeated Data data = 2;
  }

  // Response header.
  Header header = 1;

  // Entity view with Feature values. This may be the entity in the
  // Featurestore if values for all Features were requested, or a projection
  // of the entity in the Featurestore if values for only some Features were
  // requested.
  EntityView entity_view = 2;
}

// Request message for
// [FeaturestoreOnlineServingService.StreamingReadFeatureValues][google.cloud.aiplatform.v1.FeaturestoreOnlineServingService.StreamingReadFeatureValues].
message StreamingReadFeatureValuesRequest {
  // Required. The resource name of the entities' type.
  // Value format:
  // `projects/{project}/locations/{location}/featurestores/{featurestore}/entityTypes/{entityType}`.
  // For example,
  // for a machine learning model predicting user clicks on a website, an
  // EntityType ID could be `user`.
  string entity_type = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "aiplatform.googleapis.com/EntityType"
    }
  ];

  // Required. IDs of entities to read Feature values of. The maximum number of
  // IDs is 100. For example, for a machine learning model predicting user
  // clicks on a website, an entity ID could be `user_123`.
  repeated string entity_ids = 2 [(google.api.field_behavior) = REQUIRED];

  // Required. Selector choosing Features of the target EntityType. Feature IDs
  // will be deduplicated.
  FeatureSelector feature_selector = 3 [(google.api.field_behavior) = REQUIRED];
}

// Value for a feature.
message FeatureValue {
  // Metadata of feature value.
  message Metadata {
    // Feature generation timestamp. Typically, it is provided by user at
    // feature ingestion time. If not, feature store
    // will use the system timestamp when the data is ingested into feature
    // store.
    //
    // Legacy Feature Store: For streaming ingestion, the time, aligned by days,
    // must be no older than five years (1825 days) and no later than one year
    // (366 days) in the future.
    google.protobuf.Timestamp generate_time = 1;
  }

  // Value for the feature.
  oneof value {
    // Bool type feature value.
    bool bool_value = 1;

    // Double type feature value.
    double double_value = 2;

    // Int64 feature value.
    int64 int64_value = 5;

    // String feature value.
    string string_value = 6;

    // A list of bool type feature value.
    BoolArray bool_array_value = 7;

    // A list of double type feature value.
    DoubleArray double_array_value = 8;

    // A list of int64 type feature value.
    Int64Array int64_array_value = 11;

    // A list of string type feature value.
    StringArray string_array_value = 12;

    // Bytes feature value.
    bytes bytes_value = 13;

    // A struct type feature value.
    StructValue struct_value = 15;
  }

  // Metadata of feature value.
  Metadata metadata = 14;
}

// Struct (or object) type feature value.
message StructValue {
  // A list of field values.
  repeated StructFieldValue values = 1;
}

// One field of a Struct (or object) type feature value.
message StructFieldValue {
  // Name of the field in the struct feature.
  string name = 1;

  // The value for this field.
  FeatureValue value = 2;
}

// Container for list of values.
message FeatureValueList {
  // A list of feature values. All of them should be the same data type.
  repeated FeatureValue values = 1;
}
