// 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.discoveryengine.v1alpha;

import "google/api/field_behavior.proto";
import "google/api/resource.proto";
import "google/cloud/discoveryengine/v1alpha/common.proto";
import "google/cloud/discoveryengine/v1alpha/search_service.proto";
import "google/protobuf/timestamp.proto";

option csharp_namespace = "Google.Cloud.DiscoveryEngine.V1Alpha";
option go_package = "cloud.google.com/go/discoveryengine/apiv1alpha/discoveryenginepb;discoveryenginepb";
option java_multiple_files = true;
option java_outer_classname = "ServingConfigProto";
option java_package = "com.google.cloud.discoveryengine.v1alpha";
option objc_class_prefix = "DISCOVERYENGINE";
option php_namespace = "Google\\Cloud\\DiscoveryEngine\\V1alpha";
option ruby_package = "Google::Cloud::DiscoveryEngine::V1alpha";

// Configures metadata that is used to generate serving time results (e.g.
// search results or recommendation predictions).
// The ServingConfig is passed in the search and predict request and generates
// results.
message ServingConfig {
  option (google.api.resource) = {
    type: "discoveryengine.googleapis.com/ServingConfig"
    pattern: "projects/{project}/locations/{location}/dataStores/{data_store}/servingConfigs/{serving_config}"
    pattern: "projects/{project}/locations/{location}/collections/{collection}/dataStores/{data_store}/servingConfigs/{serving_config}"
    pattern: "projects/{project}/locations/{location}/collections/{collection}/engines/{engine}/servingConfigs/{serving_config}"
  };

  // Specifies the configurations needed for Media Discovery. Currently we
  // support:
  //
  // * `demote_content_watched`: Threshold for watched content demotion.
  // Customers can specify if using watched content demotion or use viewed
  // detail page. Using the content watched demotion, customers need to specify
  // the watched minutes or percentage exceeds the threshold, the content will
  // be demoted in the recommendation result.
  // * `promote_fresh_content`: cutoff days for fresh content promotion.
  // Customers can specify if using content freshness promotion. If the content
  // was published within the cutoff days, the content will be promoted in the
  // recommendation result.
  // Can only be set if
  // [SolutionType][google.cloud.discoveryengine.v1alpha.SolutionType] is
  // [SOLUTION_TYPE_RECOMMENDATION][google.cloud.discoveryengine.v1alpha.SolutionType.SOLUTION_TYPE_RECOMMENDATION].
  message MediaConfig {
    // Specify the threshold for demoting watched content, the threshold can be
    // either percentage or minutes value.
    // This must be set for `media-complete` event type.
    oneof demote_content_watched {
      // Specifies the content watched percentage threshold for demotion.
      // Threshold value must be between [0, 1.0] inclusive.
      float content_watched_percentage_threshold = 2;

      // Specifies the content watched minutes threshold for demotion.
      float content_watched_seconds_threshold = 5;
    }

    // Specifies the event type used for demoting recommendation result.
    // Currently supported values:
    //
    // * `view-item`: Item viewed.
    // * `media-play`: Start/resume watching a video, playing a song, etc.
    // * `media-complete`: Finished or stopped midway through a video, song,
    // etc.
    //
    // If unset, watch history demotion will not be applied. Content freshness
    // demotion will still be applied.
    string demotion_event_type = 1;

    // Specifies the content freshness used for recommendation result.
    // Contents will be demoted if contents were published for more than content
    // freshness cutoff days.
    int32 content_freshness_cutoff_days = 4;
  }

  // Specifies the configurations needed for Generic Discovery.Currently we
  // support:
  //
  // * `content_search_spec`: configuration for generic content search.
  message GenericConfig {
    // Specifies the expected behavior of content search.
    // Only valid for content-search enabled data store.
    SearchRequest.ContentSearchSpec content_search_spec = 1;
  }

  // Industry vertical specific config.
  oneof vertical_config {
    // The MediaConfig of the serving configuration.
    MediaConfig media_config = 7;

    // The GenericConfig of the serving configuration.
    GenericConfig generic_config = 10;
  }

  // Immutable. Fully qualified name
  // `projects/{project}/locations/{location}/collections/{collection_id}/engines/{engine_id}/servingConfigs/{serving_config_id}`
  string name = 1 [(google.api.field_behavior) = IMMUTABLE];

  // Required. The human readable serving config display name. Used in Discovery
  // UI.
  //
  // This field must be a UTF-8 encoded string with a length limit of 128
  // characters. Otherwise, an INVALID_ARGUMENT error is returned.
  string display_name = 2 [(google.api.field_behavior) = REQUIRED];

  // Required. Immutable. Specifies the solution type that a serving config can
  // be associated with.
  SolutionType solution_type = 3 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.field_behavior) = IMMUTABLE
  ];

  // The id of the model to use at serving time.
  // Currently only RecommendationModels are supported.
  // Can be changed but only to a compatible model (e.g.
  // others-you-may-like CTR to others-you-may-like CVR).
  //
  // Required when
  // [SolutionType][google.cloud.discoveryengine.v1alpha.SolutionType] is
  // [SOLUTION_TYPE_RECOMMENDATION][google.cloud.discoveryengine.v1alpha.SolutionType.SOLUTION_TYPE_RECOMMENDATION].
  string model_id = 4;

  // How much diversity to use in recommendation model results e.g.
  // `medium-diversity` or `high-diversity`. Currently supported values:
  //
  // * `no-diversity`
  // * `low-diversity`
  // * `medium-diversity`
  // * `high-diversity`
  // * `auto-diversity`
  //
  // If not specified, we choose default based on recommendation model
  // type. Default value: `no-diversity`.
  //
  // Can only be set if
  // [SolutionType][google.cloud.discoveryengine.v1alpha.SolutionType] is
  // [SOLUTION_TYPE_RECOMMENDATION][google.cloud.discoveryengine.v1alpha.SolutionType.SOLUTION_TYPE_RECOMMENDATION].
  string diversity_level = 5;

  // Bring your own embedding config. The config is used for search semantic
  // retrieval. The retrieval is based on the dot product of
  // [SearchRequest.EmbeddingSpec.EmbeddingVector.vector][google.cloud.discoveryengine.v1alpha.SearchRequest.EmbeddingSpec.EmbeddingVector.vector]
  // and the document embeddings that are provided by this EmbeddingConfig. If
  // [SearchRequest.EmbeddingSpec.EmbeddingVector.vector][google.cloud.discoveryengine.v1alpha.SearchRequest.EmbeddingSpec.EmbeddingVector.vector]
  // is provided, it overrides this
  // [ServingConfig.embedding_config][google.cloud.discoveryengine.v1alpha.ServingConfig.embedding_config].
  EmbeddingConfig embedding_config = 20;

  // The ranking expression controls the customized ranking on retrieval
  // documents. To leverage this, document embedding is required. The ranking
  // expression setting in ServingConfig applies to all search requests served
  // by the serving config. However, if
  // [SearchRequest.ranking_expression][google.cloud.discoveryengine.v1alpha.SearchRequest.ranking_expression]
  // is specified, it overrides the ServingConfig ranking expression.
  //
  // The ranking expression is a single function or multiple functions that are
  // joined by "+".
  //
  //   * ranking_expression = function, { " + ", function };
  //
  // Supported functions:
  //
  //   * double * relevance_score
  //   * double * dotProduct(embedding_field_path)
  //
  // Function variables:
  //
  //   * `relevance_score`: pre-defined keywords, used for measure relevance
  //   between query and document.
  //   * `embedding_field_path`: the document embedding field
  //   used with query embedding vector.
  //   * `dotProduct`: embedding function between embedding_field_path and query
  //   embedding vector.
  //
  //  Example ranking expression:
  //
  //    If document has an embedding field doc_embedding, the ranking expression
  //    could be `0.5 * relevance_score + 0.3 * dotProduct(doc_embedding)`.
  string ranking_expression = 21;

  // Guided search configs.
  GuidedSearchSpec guided_search_spec = 22;

  // Custom fine tuning configs.
  // If
  // [SearchRequest.custom_fine_tuning_spec][google.cloud.discoveryengine.v1alpha.SearchRequest.custom_fine_tuning_spec]
  // is set, it has higher priority than the configs set here.
  CustomFineTuningSpec custom_fine_tuning_spec = 24;

  // Output only. ServingConfig created timestamp.
  google.protobuf.Timestamp create_time = 8
      [(google.api.field_behavior) = OUTPUT_ONLY];

  // Output only. ServingConfig updated timestamp.
  google.protobuf.Timestamp update_time = 9
      [(google.api.field_behavior) = OUTPUT_ONLY];

  // Filter controls to use in serving path.
  // All triggered filter controls will be applied.
  // Filter controls must be in the same data store as the serving config.
  // Maximum of 20 filter controls.
  repeated string filter_control_ids = 11;

  // Boost controls to use in serving path.
  // All triggered boost controls will be applied.
  // Boost controls must be in the same data store as the serving config.
  // Maximum of 20 boost controls.
  repeated string boost_control_ids = 12;

  // IDs of the redirect controls. Only the first triggered redirect
  // action is applied, even if multiple apply. Maximum number of
  // specifications is 100.
  //
  // Can only be set if
  // [SolutionType][google.cloud.discoveryengine.v1alpha.SolutionType] is
  // [SOLUTION_TYPE_SEARCH][google.cloud.discoveryengine.v1alpha.SolutionType.SOLUTION_TYPE_SEARCH].
  repeated string redirect_control_ids = 14;

  // Condition synonyms specifications. If multiple synonyms conditions
  // match, all matching synonyms controls in the list will execute.
  // Maximum number of specifications is 100.
  //
  // Can only be set if
  // [SolutionType][google.cloud.discoveryengine.v1alpha.SolutionType] is
  // [SOLUTION_TYPE_SEARCH][google.cloud.discoveryengine.v1alpha.SolutionType.SOLUTION_TYPE_SEARCH].
  repeated string synonyms_control_ids = 15;

  // Condition oneway synonyms specifications. If multiple oneway synonyms
  // conditions match, all matching oneway synonyms controls in the list
  // will execute. Maximum number of specifications is 100.
  //
  // Can only be set if
  // [SolutionType][google.cloud.discoveryengine.v1alpha.SolutionType] is
  // [SOLUTION_TYPE_SEARCH][google.cloud.discoveryengine.v1alpha.SolutionType.SOLUTION_TYPE_SEARCH].
  repeated string oneway_synonyms_control_ids = 16;

  // Condition do not associate specifications. If multiple do not
  // associate conditions match, all matching do not associate controls in
  // the list will execute.
  // Order does not matter.
  // Maximum number of specifications is 100.
  //
  // Can only be set if
  // [SolutionType][google.cloud.discoveryengine.v1alpha.SolutionType] is
  // [SOLUTION_TYPE_SEARCH][google.cloud.discoveryengine.v1alpha.SolutionType.SOLUTION_TYPE_SEARCH].
  repeated string dissociate_control_ids = 17;

  // Condition replacement specifications.
  // Applied according to the order in the list.
  // A previously replaced term can not be re-replaced.
  // Maximum number of specifications is 100.
  //
  // Can only be set if
  // [SolutionType][google.cloud.discoveryengine.v1alpha.SolutionType] is
  // [SOLUTION_TYPE_SEARCH][google.cloud.discoveryengine.v1alpha.SolutionType.SOLUTION_TYPE_SEARCH].
  repeated string replacement_control_ids = 18;

  // Condition ignore specifications. If multiple ignore
  // conditions match, all matching ignore controls in the list will
  // execute.
  // Order does not matter.
  // Maximum number of specifications is 100.
  repeated string ignore_control_ids = 19;
}
