// Copyright 2026 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.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/discoveryengine/v1/chunk.proto";
import "google/cloud/discoveryengine/v1/common.proto";
import "google/cloud/discoveryengine/v1/document.proto";
import "google/protobuf/struct.proto";

option csharp_namespace = "Google.Cloud.DiscoveryEngine.V1";
option go_package = "cloud.google.com/go/discoveryengine/apiv1/discoveryenginepb;discoveryenginepb";
option java_multiple_files = true;
option java_outer_classname = "SearchServiceProto";
option java_package = "com.google.cloud.discoveryengine.v1";
option objc_class_prefix = "DISCOVERYENGINE";
option php_namespace = "Google\\Cloud\\DiscoveryEngine\\V1";
option ruby_package = "Google::Cloud::DiscoveryEngine::V1";

// Service for search.
service SearchService {
  option (google.api.default_host) = "discoveryengine.googleapis.com";
  option (google.api.oauth_scopes) =
      "https://www.googleapis.com/auth/cloud-platform";

  // Performs a search.
  rpc Search(SearchRequest) returns (SearchResponse) {
    option (google.api.http) = {
      post: "/v1/{serving_config=projects/*/locations/*/dataStores/*/servingConfigs/*}:search"
      body: "*"
      additional_bindings {
        post: "/v1/{serving_config=projects/*/locations/*/collections/*/dataStores/*/servingConfigs/*}:search"
        body: "*"
      }
      additional_bindings {
        post: "/v1/{serving_config=projects/*/locations/*/collections/*/engines/*/servingConfigs/*}:search"
        body: "*"
      }
    };
  }

  // Performs a search. Similar to the
  // [SearchService.Search][google.cloud.discoveryengine.v1.SearchService.Search]
  // method, but a lite version that allows API key for authentication, where
  // OAuth and IAM checks are not required.
  //
  // Only public website search is supported by this method. If data stores and
  // engines not associated with public website search are specified, a
  // `FAILED_PRECONDITION` error is returned.
  //
  // This method can be used for easy onboarding without having to implement an
  // authentication backend. However, it is strongly recommended to use
  // [SearchService.Search][google.cloud.discoveryengine.v1.SearchService.Search]
  // instead with required OAuth and IAM checks to provide better data security.
  rpc SearchLite(SearchRequest) returns (SearchResponse) {
    option (google.api.http) = {
      post: "/v1/{serving_config=projects/*/locations/*/dataStores/*/servingConfigs/*}:searchLite"
      body: "*"
      additional_bindings {
        post: "/v1/{serving_config=projects/*/locations/*/collections/*/dataStores/*/servingConfigs/*}:searchLite"
        body: "*"
      }
      additional_bindings {
        post: "/v1/{serving_config=projects/*/locations/*/collections/*/engines/*/servingConfigs/*}:searchLite"
        body: "*"
      }
    };
  }
}

// Request message for
// [SearchService.Search][google.cloud.discoveryengine.v1.SearchService.Search]
// method.
message SearchRequest {
  // Specifies the image query input.
  message ImageQuery {
    oneof image {
      // Base64 encoded image bytes. Supported image formats: JPEG, PNG, and
      // BMP.
      string image_bytes = 1;
    }
  }

  // A struct to define data stores to filter on in a search call and
  // configurations for those data stores. Otherwise, an `INVALID_ARGUMENT`
  // error is returned.
  message DataStoreSpec {
    // Required. Full resource name of
    // [DataStore][google.cloud.discoveryengine.v1.DataStore], such as
    // `projects/{project}/locations/{location}/collections/{collection_id}/dataStores/{data_store_id}`.
    // The path must include the project number, project id is not supported for
    // this field.
    string data_store = 1 [
      (google.api.field_behavior) = REQUIRED,
      (google.api.resource_reference) = {
        type: "discoveryengine.googleapis.com/DataStore"
      }
    ];

    // Optional. Filter specification to filter documents in the data store
    // specified by data_store field. For more information on filtering, see
    // [Filtering](https://cloud.google.com/generative-ai-app-builder/docs/filter-search-metadata)
    string filter = 5 [(google.api.field_behavior) = OPTIONAL];

    // Optional. Boost specification to boost certain documents.
    // For more information on boosting, see
    // [Boosting](https://cloud.google.com/generative-ai-app-builder/docs/boost-search-results)
    BoostSpec boost_spec = 6 [(google.api.field_behavior) = OPTIONAL];

    // Optional. Custom search operators which if specified will be used to
    // filter results from workspace data stores. For more information on custom
    // search operators, see
    // [SearchOperators](https://support.google.com/cloudsearch/answer/6172299).
    string custom_search_operators = 7 [(google.api.field_behavior) = OPTIONAL];
  }

  // A facet specification to perform faceted search.
  message FacetSpec {
    // Specifies how a facet is computed.
    message FacetKey {
      // Required. Supported textual and numerical facet keys in
      // [Document][google.cloud.discoveryengine.v1.Document] object, over which
      // the facet values are computed. Facet key is case-sensitive.
      string key = 1 [(google.api.field_behavior) = REQUIRED];

      // Set only if values should be bucketed into intervals. Must be set
      // for facets with numerical values. Must not be set for facet with text
      // values. Maximum number of intervals is 30.
      repeated Interval intervals = 2;

      // Only get facet for the given restricted values. Only supported on
      // textual fields. For example, suppose "category" has three values
      // "Action > 2022", "Action > 2021" and "Sci-Fi > 2022". If set
      // "restricted_values" to "Action > 2022", the "category" facet only
      // contains "Action > 2022". Only supported on textual fields. Maximum
      // is 10.
      repeated string restricted_values = 3;

      // Only get facet values that start with the given string prefix. For
      // example, suppose "category" has three values "Action > 2022",
      // "Action > 2021" and "Sci-Fi > 2022". If set "prefixes" to "Action", the
      // "category" facet only contains "Action > 2022" and "Action > 2021".
      // Only supported on textual fields. Maximum is 10.
      repeated string prefixes = 4;

      // Only get facet values that contain the given strings. For example,
      // suppose "category" has three values "Action > 2022",
      // "Action > 2021" and "Sci-Fi > 2022". If set "contains" to "2022", the
      // "category" facet only contains "Action > 2022" and "Sci-Fi > 2022".
      // Only supported on textual fields. Maximum is 10.
      repeated string contains = 5;

      // True to make facet keys case insensitive when getting faceting
      // values with prefixes or contains; false otherwise.
      bool case_insensitive = 6;

      // The order in which documents are returned.
      //
      // Allowed values are:
      //
      // * "count desc", which means order by
      // [SearchResponse.Facet.values.count][google.cloud.discoveryengine.v1.SearchResponse.Facet.FacetValue.count]
      // descending.
      //
      // * "value desc", which means order by
      // [SearchResponse.Facet.values.value][google.cloud.discoveryengine.v1.SearchResponse.Facet.FacetValue.value]
      // descending.
      //   Only applies to textual facets.
      //
      // If not set, textual values are sorted in [natural
      // order](https://en.wikipedia.org/wiki/Natural_sort_order); numerical
      // intervals are sorted in the order given by
      // [FacetSpec.FacetKey.intervals][google.cloud.discoveryengine.v1.SearchRequest.FacetSpec.FacetKey.intervals].
      string order_by = 7;
    }

    // Required. The facet key specification.
    FacetKey facet_key = 1 [(google.api.field_behavior) = REQUIRED];

    // Maximum facet values that are returned for this facet. If
    // unspecified, defaults to 20. The maximum allowed value is 300. Values
    // above 300 are coerced to 300.
    // For aggregation in healthcare search, when the [FacetKey.key] is
    // "healthcare_aggregation_key", the limit will be overridden to
    // 10,000 internally, regardless of the value set here.
    //
    // If this field is negative, an  `INVALID_ARGUMENT`  is returned.
    int32 limit = 2;

    // List of keys to exclude when faceting.
    //
    // By default,
    // [FacetKey.key][google.cloud.discoveryengine.v1.SearchRequest.FacetSpec.FacetKey.key]
    // is not excluded from the filter unless it is listed in this field.
    //
    // Listing a facet key in this field allows its values to appear as facet
    // results, even when they are filtered out of search results. Using this
    // field does not affect what search results are returned.
    //
    // For example, suppose there are 100 documents with the color facet "Red"
    // and 200 documents with the color facet "Blue". A query containing the
    // filter "color:ANY("Red")" and having "color" as
    // [FacetKey.key][google.cloud.discoveryengine.v1.SearchRequest.FacetSpec.FacetKey.key]
    // would by default return only "Red" documents in the search results, and
    // also return "Red" with count 100 as the only color facet. Although there
    // are also blue documents available, "Blue" would not be shown as an
    // available facet value.
    //
    // If "color" is listed in "excludedFilterKeys", then the query returns the
    // facet values "Red" with count 100 and "Blue" with count 200, because the
    // "color" key is now excluded from the filter. Because this field doesn't
    // affect search results, the search results are still correctly filtered to
    // return only "Red" documents.
    //
    // A maximum of 100 values are allowed. Otherwise, an  `INVALID_ARGUMENT`
    // error is returned.
    repeated string excluded_filter_keys = 3;

    // Enables dynamic position for this facet. If set to true, the position of
    // this facet among all facets in the response is determined automatically.
    // If dynamic facets are enabled, it is ordered together.
    // If set to false, the position of this facet in the
    // response is the same as in the request, and it is ranked before
    // the facets with dynamic position enable and all dynamic facets.
    //
    // For example, you may always want to have rating facet returned in
    // the response, but it's not necessarily to always display the rating facet
    // at the top. In that case, you can set enable_dynamic_position to true so
    // that the position of rating facet in response is determined
    // automatically.
    //
    // Another example, assuming you have the following facets in the request:
    //
    // * "rating", enable_dynamic_position = true
    //
    // * "price", enable_dynamic_position = false
    //
    // * "brands", enable_dynamic_position = false
    //
    // And also you have a dynamic facets enabled, which generates a facet
    // `gender`. Then the final order of the facets in the response can be
    // ("price", "brands", "rating", "gender") or ("price", "brands", "gender",
    // "rating") depends on how API orders "gender" and "rating" facets.
    // However, notice that "price" and "brands" are always
    // ranked at first and second position because their enable_dynamic_position
    // is false.
    bool enable_dynamic_position = 4;
  }

  // Boost specification to boost certain documents.
  message BoostSpec {
    // Boost applies to documents which match a condition.
    message ConditionBoostSpec {
      // Specification for custom ranking based on customer specified attribute
      // value. It provides more controls for customized ranking than the simple
      // (condition, boost) combination above.
      message BoostControlSpec {
        // The control points used to define the curve. The curve defined
        // through these control points can only be monotonically increasing
        // or decreasing(constant values are acceptable).
        message ControlPoint {
          // Can be one of:
          // 1. The numerical field value.
          // 2. The duration spec for freshness:
          // The value must be formatted as an XSD `dayTimeDuration` value (a
          // restricted subset of an ISO 8601 duration value). The pattern for
          // this is: `[nD][T[nH][nM][nS]]`.
          string attribute_value = 1;

          // The value between -1 to 1 by which to boost the score if the
          // attribute_value evaluates to the value specified above.
          float boost_amount = 2;
        }

        // The attribute(or function) for which the custom ranking is to be
        // applied.
        enum AttributeType {
          // Unspecified AttributeType.
          ATTRIBUTE_TYPE_UNSPECIFIED = 0;

          // The value of the numerical field will be used to dynamically update
          // the boost amount. In this case, the attribute_value (the x value)
          // of the control point will be the actual value of the numerical
          // field for which the boost_amount is specified.
          NUMERICAL = 1;

          // For the freshness use case the attribute value will be the duration
          // between the current time and the date in the datetime field
          // specified. The value must be formatted as an XSD `dayTimeDuration`
          // value (a restricted subset of an ISO 8601 duration value). The
          // pattern for this is: `[nD][T[nH][nM][nS]]`.
          // For example, `5D`, `3DT12H30M`, `T24H`.
          FRESHNESS = 2;
        }

        // The interpolation type to be applied. Default will be linear
        // (Piecewise Linear).
        enum InterpolationType {
          // Interpolation type is unspecified. In this case, it defaults to
          // Linear.
          INTERPOLATION_TYPE_UNSPECIFIED = 0;

          // Piecewise linear interpolation will be applied.
          LINEAR = 1;
        }

        // The name of the field whose value will be used to determine the
        // boost amount.
        string field_name = 1;

        // The attribute type to be used to determine the boost amount. The
        // attribute value can be derived from the field value of the specified
        // field_name. In the case of numerical it is straightforward i.e.
        // attribute_value = numerical_field_value. In the case of freshness
        // however, attribute_value = (time.now() - datetime_field_value).
        AttributeType attribute_type = 2;

        // The interpolation type to be applied to connect the control points
        // listed below.
        InterpolationType interpolation_type = 3;

        // The control points used to define the curve. The monotonic function
        // (defined through the interpolation_type above) passes through the
        // control points listed here.
        repeated ControlPoint control_points = 4;
      }

      // An expression which specifies a boost condition. The syntax and
      // supported fields are the same as a filter expression. See
      // [SearchRequest.filter][google.cloud.discoveryengine.v1.SearchRequest.filter]
      // for detail syntax and limitations.
      //
      // Examples:
      //
      // * To boost documents with document ID "doc_1" or "doc_2", and
      // color "Red" or "Blue":
      // `(document_id: ANY("doc_1", "doc_2")) AND (color: ANY("Red", "Blue"))`
      string condition = 1;

      // Strength of the condition boost, which should be in [-1, 1]. Negative
      // boost means demotion. Default is 0.0.
      //
      // Setting to 1.0 gives the document a big promotion. However, it does
      // not necessarily mean that the boosted document will be the top result
      // at all times, nor that other documents will be excluded. Results
      // could still be shown even when none of them matches the condition.
      // And results that are significantly more relevant to the search query
      // can still trump your heavily favored but irrelevant documents.
      //
      // Setting to -1.0 gives the document a big demotion. However, results
      // that are deeply relevant might still be shown. The document will have
      // an upstream battle to get a fairly high ranking, but it is not
      // blocked out completely.
      //
      // Setting to 0.0 means no boost applied. The boosting condition is
      // ignored. Only one of the (condition, boost) combination or the
      // boost_control_spec below are set. If both are set then the global boost
      // is ignored and the more fine-grained boost_control_spec is applied.
      float boost = 2;

      // Complex specification for custom ranking based on customer defined
      // attribute value.
      BoostControlSpec boost_control_spec = 3;
    }

    // Condition boost specifications. If a document matches multiple conditions
    // in the specifications, boost scores from these specifications are all
    // applied and combined in a non-linear way. Maximum number of
    // specifications is 20.
    repeated ConditionBoostSpec condition_boost_specs = 1;
  }

  // Specification to determine under which conditions query expansion should
  // occur.
  message QueryExpansionSpec {
    // Enum describing under which condition query expansion should occur.
    enum Condition {
      // Unspecified query expansion condition. In this case, server behavior
      // defaults to
      // [Condition.DISABLED][google.cloud.discoveryengine.v1.SearchRequest.QueryExpansionSpec.Condition.DISABLED].
      CONDITION_UNSPECIFIED = 0;

      // Disabled query expansion. Only the exact search query is used, even if
      // [SearchResponse.total_size][google.cloud.discoveryengine.v1.SearchResponse.total_size]
      // is zero.
      DISABLED = 1;

      // Automatic query expansion built by the Search API.
      AUTO = 2;
    }

    // The condition under which query expansion should occur. Default to
    // [Condition.DISABLED][google.cloud.discoveryengine.v1.SearchRequest.QueryExpansionSpec.Condition.DISABLED].
    Condition condition = 1;

    // Whether to pin unexpanded results. If this field is set to true,
    // unexpanded products are always at the top of the search results, followed
    // by the expanded results.
    bool pin_unexpanded_results = 2;
  }

  // The specification for query spell correction.
  message SpellCorrectionSpec {
    // Enum describing under which mode spell correction should occur.
    enum Mode {
      // Unspecified spell correction mode. In this case, server behavior
      // defaults to
      // [Mode.AUTO][google.cloud.discoveryengine.v1.SearchRequest.SpellCorrectionSpec.Mode.AUTO].
      MODE_UNSPECIFIED = 0;

      // Search API tries to find a spelling suggestion. If a suggestion is
      // found, it is put in the
      // [SearchResponse.corrected_query][google.cloud.discoveryengine.v1.SearchResponse.corrected_query].
      // The spelling suggestion won't be used as the search query.
      SUGGESTION_ONLY = 1;

      // Automatic spell correction built by the Search API. Search will
      // be based on the corrected query if found.
      AUTO = 2;
    }

    // The mode under which spell correction
    // replaces the original search query. Defaults to
    // [Mode.AUTO][google.cloud.discoveryengine.v1.SearchRequest.SpellCorrectionSpec.Mode.AUTO].
    Mode mode = 1;
  }

  // A specification for configuring the behavior of content search.
  message ContentSearchSpec {
    // A specification for configuring snippets in a search response.
    message SnippetSpec {
      // [DEPRECATED] This field is deprecated. To control snippet return, use
      // `return_snippet` field. For backwards compatibility, we will return
      // snippet if max_snippet_count > 0.
      int32 max_snippet_count = 1 [deprecated = true];

      // [DEPRECATED] This field is deprecated and will have no affect on the
      // snippet.
      bool reference_only = 2 [deprecated = true];

      // If `true`, then return snippet. If no snippet can be generated, we
      // return "No snippet is available for this page." A `snippet_status` with
      // `SUCCESS` or `NO_SNIPPET_AVAILABLE` will also be returned.
      bool return_snippet = 3;
    }

    // A specification for configuring a summary returned in a search
    // response.
    message SummarySpec {
      // Specification of the prompt to use with the model.
      message ModelPromptSpec {
        // Text at the beginning of the prompt that instructs the assistant.
        // Examples are available in the user guide.
        string preamble = 1;
      }

      // Specification of the model.
      message ModelSpec {
        // The model version used to generate the summary.
        //
        // Supported values are:
        //
        // * `stable`: string. Default value when no value is specified. Uses a
        //    generally available, fine-tuned model. For more information, see
        //    [Answer generation model versions and
        //    lifecycle](https://cloud.google.com/generative-ai-app-builder/docs/answer-generation-models).
        // * `preview`: string. (Public preview) Uses a preview model. For more
        //    information, see
        //    [Answer generation model versions and
        //    lifecycle](https://cloud.google.com/generative-ai-app-builder/docs/answer-generation-models).
        string version = 1;
      }

      // The number of top results to generate the summary from. If the number
      // of results returned is less than `summaryResultCount`, the summary is
      // generated from all of the results.
      //
      // At most 10 results for documents mode, or 50 for chunks mode, can be
      // used to generate a summary. The chunks mode is used when
      // [SearchRequest.ContentSearchSpec.search_result_mode][google.cloud.discoveryengine.v1.SearchRequest.ContentSearchSpec.search_result_mode]
      // is set to
      // [CHUNKS][google.cloud.discoveryengine.v1.SearchRequest.ContentSearchSpec.SearchResultMode.CHUNKS].
      int32 summary_result_count = 1;

      // Specifies whether to include citations in the summary. The default
      // value is `false`.
      //
      // When this field is set to `true`, summaries include in-line citation
      // numbers.
      //
      // Example summary including citations:
      //
      // BigQuery is Google Cloud's fully managed and completely serverless
      // enterprise data warehouse [1]. BigQuery supports all data types, works
      // across clouds, and has built-in machine learning and business
      // intelligence, all within a unified platform [2, 3].
      //
      // The citation numbers refer to the returned search results and are
      // 1-indexed. For example, [1] means that the sentence is attributed to
      // the first search result. [2, 3] means that the sentence is attributed
      // to both the second and third search results.
      bool include_citations = 2;

      // Specifies whether to filter out adversarial queries. The default value
      // is `false`.
      //
      // Google employs search-query classification to detect adversarial
      // queries. No summary is returned if the search query is classified as an
      // adversarial query. For example, a user might ask a question regarding
      // negative comments about the company or submit a query designed to
      // generate unsafe, policy-violating output. If this field is set to
      // `true`, we skip generating summaries for adversarial queries and return
      // fallback messages instead.
      bool ignore_adversarial_query = 3;

      // Specifies whether to filter out queries that are not summary-seeking.
      // The default value is `false`.
      //
      // Google employs search-query classification to detect summary-seeking
      // queries. No summary is returned if the search query is classified as a
      // non-summary seeking query. For example, `why is the sky blue` and `Who
      // is the best soccer player in the world?` are summary-seeking queries,
      // but `SFO airport` and `world cup 2026` are not. They are most likely
      // navigational queries. If this field is set to `true`, we skip
      // generating summaries for non-summary seeking queries and return
      // fallback messages instead.
      bool ignore_non_summary_seeking_query = 4;

      // Specifies whether to filter out queries that have low relevance. The
      // default value is `false`.
      //
      // If this field is set to `false`, all search results are used regardless
      // of relevance to generate answers. If set to `true`, only queries with
      // high relevance search results will generate answers.
      bool ignore_low_relevant_content = 9;

      // Optional. Specifies whether to filter out jail-breaking queries. The
      // default value is `false`.
      //
      // Google employs search-query classification to detect jail-breaking
      // queries. No summary is returned if the search query is classified as a
      // jail-breaking query. A user might add instructions to the query to
      // change the tone, style, language, content of the answer, or ask the
      // model to act as a different entity, e.g. "Reply in the tone of a
      // competing company's CEO". If this field is set to `true`, we skip
      // generating summaries for jail-breaking queries and return fallback
      // messages instead.
      bool ignore_jail_breaking_query = 10
          [(google.api.field_behavior) = OPTIONAL];

      // If specified, the spec will be used to modify the prompt provided to
      // the LLM.
      ModelPromptSpec model_prompt_spec = 5;

      // Language code for Summary. Use language tags defined by
      // [BCP47](https://www.rfc-editor.org/rfc/bcp/bcp47.txt).
      // Note: This is an experimental feature.
      string language_code = 6;

      // If specified, the spec will be used to modify the model specification
      // provided to the LLM.
      ModelSpec model_spec = 7;

      // If true, answer will be generated from most relevant chunks from top
      // search results. This feature will improve summary quality.
      // Note that with this feature enabled, not all top search results
      // will be referenced and included in the reference list, so the citation
      // source index only points to the search results listed in the reference
      // list.
      bool use_semantic_chunks = 8;
    }

    // A specification for configuring the extractive content in a search
    // response.
    message ExtractiveContentSpec {
      // The maximum number of extractive answers returned in each search
      // result.
      //
      // An extractive answer is a verbatim answer extracted from the original
      // document, which provides a precise and contextually relevant answer to
      // the search query.
      //
      // If the number of matching answers is less than the
      // `max_extractive_answer_count`, return all of the answers. Otherwise,
      // return the `max_extractive_answer_count`.
      //
      // At most five answers are returned for each
      // [SearchResult][google.cloud.discoveryengine.v1.SearchResponse.SearchResult].
      int32 max_extractive_answer_count = 1;

      // The max number of extractive segments returned in each search result.
      // Only applied if the
      // [DataStore][google.cloud.discoveryengine.v1.DataStore] is set to
      // [DataStore.ContentConfig.CONTENT_REQUIRED][google.cloud.discoveryengine.v1.DataStore.ContentConfig.CONTENT_REQUIRED]
      // or
      // [DataStore.solution_types][google.cloud.discoveryengine.v1.DataStore.solution_types]
      // is
      // [SOLUTION_TYPE_CHAT][google.cloud.discoveryengine.v1.SolutionType.SOLUTION_TYPE_CHAT].
      //
      // An extractive segment is a text segment extracted from the original
      // document that is relevant to the search query, and, in general, more
      // verbose than an extractive answer. The segment could then be used as
      // input for LLMs to generate summaries and answers.
      //
      // If the number of matching segments is less than
      // `max_extractive_segment_count`, return all of the segments. Otherwise,
      // return the `max_extractive_segment_count`.
      int32 max_extractive_segment_count = 2;

      // Specifies whether to return the confidence score from the extractive
      // segments in each search result. This feature is available only for new
      // or allowlisted data stores. To allowlist your data store,
      // contact your Customer Engineer. The default value is `false`.
      bool return_extractive_segment_score = 3;

      // Specifies whether to also include the adjacent from each selected
      // segments.
      // Return at most `num_previous_segments` segments before each selected
      // segments.
      int32 num_previous_segments = 4;

      // Return at most `num_next_segments` segments after each selected
      // segments.
      int32 num_next_segments = 5;
    }

    // Specifies the chunk spec to be returned from the search response.
    // Only available if the
    // [SearchRequest.ContentSearchSpec.search_result_mode][google.cloud.discoveryengine.v1.SearchRequest.ContentSearchSpec.search_result_mode]
    // is set to
    // [CHUNKS][google.cloud.discoveryengine.v1.SearchRequest.ContentSearchSpec.SearchResultMode.CHUNKS]
    message ChunkSpec {
      // The number of previous chunks to be returned of the current chunk. The
      // maximum allowed value is 3.
      // If not specified, no previous chunks will be returned.
      int32 num_previous_chunks = 1;

      // The number of next chunks to be returned of the current chunk. The
      // maximum allowed value is 3.
      // If not specified, no next chunks will be returned.
      int32 num_next_chunks = 2;
    }

    // Specifies the search result mode. If unspecified, the
    // search result mode defaults to `DOCUMENTS`.
    enum SearchResultMode {
      // Default value.
      SEARCH_RESULT_MODE_UNSPECIFIED = 0;

      // Returns documents in the search result.
      DOCUMENTS = 1;

      // Returns chunks in the search result. Only available if the
      // [DocumentProcessingConfig.chunking_config][google.cloud.discoveryengine.v1.DocumentProcessingConfig.chunking_config]
      // is specified.
      CHUNKS = 2;
    }

    // If `snippetSpec` is not specified, snippets are not included in the
    // search response.
    SnippetSpec snippet_spec = 1;

    // If `summarySpec` is not specified, summaries are not included in the
    // search response.
    SummarySpec summary_spec = 2;

    // If there is no extractive_content_spec provided, there will be no
    // extractive answer in the search response.
    ExtractiveContentSpec extractive_content_spec = 3;

    // Specifies the search result mode. If unspecified, the
    // search result mode defaults to `DOCUMENTS`.
    SearchResultMode search_result_mode = 4;

    // Specifies the chunk spec to be returned from the search response.
    // Only available if the
    // [SearchRequest.ContentSearchSpec.search_result_mode][google.cloud.discoveryengine.v1.SearchRequest.ContentSearchSpec.search_result_mode]
    // is set to
    // [CHUNKS][google.cloud.discoveryengine.v1.SearchRequest.ContentSearchSpec.SearchResultMode.CHUNKS]
    ChunkSpec chunk_spec = 5;
  }

  // Specification to enable natural language understanding capabilities for
  // search requests.
  message NaturalLanguageQueryUnderstandingSpec {
    // Enum describing under which condition filter extraction should occur.
    enum FilterExtractionCondition {
      // Server behavior defaults to `DISABLED`.
      CONDITION_UNSPECIFIED = 0;

      // Disables NL filter extraction.
      DISABLED = 1;

      // Enables NL filter extraction.
      ENABLED = 2;
    }

    // Enum describing how extracted filters are applied to the search.
    enum ExtractedFilterBehavior {
      // `EXTRACTED_FILTER_BEHAVIOR_UNSPECIFIED` will use the default behavior
      // for extracted filters. For single datastore search, the default is to
      // apply as hard filters. For multi-datastore search, the default is to
      // apply as soft boosts.
      EXTRACTED_FILTER_BEHAVIOR_UNSPECIFIED = 0;

      // Applies all extracted filters as hard filters on the results. Results
      // that do not pass the extracted filters will not be returned in the
      // result set.
      HARD_FILTER = 1;

      // Applies all extracted filters as soft boosts. Results that pass the
      // filters will be boosted up to higher ranks in the result set.
      SOFT_BOOST = 2;
    }

    // The condition under which filter extraction should occur.
    // Server behavior defaults to `DISABLED`.
    FilterExtractionCondition filter_extraction_condition = 1;

    // Field names used for location-based filtering, where geolocation filters
    // are detected in natural language search queries.
    // Only valid when the FilterExtractionCondition is set to `ENABLED`.
    //
    // If this field is set, it overrides the field names set in
    // [ServingConfig.geo_search_query_detection_field_names][google.cloud.discoveryengine.v1.ServingConfig.geo_search_query_detection_field_names].
    repeated string geo_search_query_detection_field_names = 2;

    // Optional. Controls behavior of how extracted filters are applied to the
    // search. The default behavior depends on the request. For single datastore
    // structured search, the default is `HARD_FILTER`. For multi-datastore
    // search, the default behavior is `SOFT_BOOST`.
    // Location-based filters are always applied as hard filters, and the
    // `SOFT_BOOST` setting will not affect them.
    // This field is only used if
    // [SearchRequest.NaturalLanguageQueryUnderstandingSpec.FilterExtractionCondition][google.cloud.discoveryengine.v1.SearchRequest.NaturalLanguageQueryUnderstandingSpec.FilterExtractionCondition]
    // is set to
    // [FilterExtractionCondition.ENABLED][google.cloud.discoveryengine.v1.SearchRequest.NaturalLanguageQueryUnderstandingSpec.FilterExtractionCondition.ENABLED].
    ExtractedFilterBehavior extracted_filter_behavior = 3
        [(google.api.field_behavior) = OPTIONAL];

    // Optional. Allowlist of fields that can be used for natural language
    // filter extraction. By default, if this is unspecified, all indexable
    // fields are eligible for natural language filter extraction (but are not
    // guaranteed to be used). If any fields are specified in
    // allowed_field_names, only the fields that are both marked as indexable in
    // the schema and specified in the allowlist will be eligible for natural
    // language filter extraction. Note: for multi-datastore search, this is not
    // yet supported, and will be ignored.
    repeated string allowed_field_names = 4
        [(google.api.field_behavior) = OPTIONAL];
  }

  // Specification for search as you type in search requests.
  message SearchAsYouTypeSpec {
    // Enum describing under which condition search as you type should occur.
    enum Condition {
      // Server behavior defaults to
      // [Condition.DISABLED][google.cloud.discoveryengine.v1.SearchRequest.SearchAsYouTypeSpec.Condition.DISABLED].
      CONDITION_UNSPECIFIED = 0;

      // Disables Search As You Type.
      DISABLED = 1;

      // Enables Search As You Type.
      ENABLED = 2;

      // Automatic switching between search-as-you-type and standard search
      // modes, ideal for single-API implementations (e.g., debouncing).
      AUTO = 3;
    }

    // The condition under which search as you type should occur.
    // Default to
    // [Condition.DISABLED][google.cloud.discoveryengine.v1.SearchRequest.SearchAsYouTypeSpec.Condition.DISABLED].
    Condition condition = 1;
  }

  // Specifies features for display, like match highlighting.
  message DisplaySpec {
    // Enum describing under which condition match highlighting should occur.
    enum MatchHighlightingCondition {
      // Server behavior is the same as `MATCH_HIGHLIGHTING_DISABLED`.
      MATCH_HIGHLIGHTING_CONDITION_UNSPECIFIED = 0;

      // Disables match highlighting on all documents.
      MATCH_HIGHLIGHTING_DISABLED = 1;

      // Enables match highlighting on all documents.
      MATCH_HIGHLIGHTING_ENABLED = 2;
    }

    // The condition under which match highlighting should occur.
    MatchHighlightingCondition match_highlighting_condition = 1;
  }

  // Specification for crowding. Crowding improves the diversity of search
  // results by limiting the number of results that share the same field value.
  // For example, crowding on the color field with a max_count of 3 and mode
  // DROP_CROWDED_RESULTS will return at most 3 results with the same color
  // across all pages.
  message CrowdingSpec {
    // Enum describing the mode to use for documents that are crowded away.
    // They can be dropped or demoted to the later pages.
    enum Mode {
      // Unspecified crowding mode. In this case, server behavior defaults to
      // [Mode.DROP_CROWDED_RESULTS][google.cloud.discoveryengine.v1.SearchRequest.CrowdingSpec.Mode.DROP_CROWDED_RESULTS].
      MODE_UNSPECIFIED = 0;

      // Drop crowded results.
      DROP_CROWDED_RESULTS = 1;

      // Demote crowded results to the later pages.
      DEMOTE_CROWDED_RESULTS_TO_END = 2;
    }

    // The field to use for crowding. Documents can be crowded by a field in the
    // [Document][google.cloud.discoveryengine.v1.Document] object. Crowding
    // field is case sensitive.
    string field = 1;

    // The maximum number of documents to keep per value of the field. Once
    // there are at least max_count previous results which contain the same
    // value for the given field (according to the order specified in
    // `order_by`), later results with the same value are "crowded away".
    // If not specified, the default value is 1.
    int32 max_count = 2;

    // Mode to use for documents that are crowded away.
    Mode mode = 3;
  }

  // Session specification.
  //
  // Multi-turn Search feature is currently at private GA stage. Please use
  // v1alpha or v1beta version instead before we launch this feature to public
  // GA. Or ask for allowlisting through Google Support team.
  message SessionSpec {
    // If set, the search result gets stored to the "turn" specified by this
    // query ID.
    //
    // Example: Let's say the session looks like this:
    //   session {
    //     name: ".../sessions/xxx"
    //     turns {
    //       query { text: "What is foo?" query_id: ".../questions/yyy" }
    //       answer: "Foo is ..."
    //     }
    //     turns {
    //       query { text: "How about bar then?" query_id: ".../questions/zzz" }
    //     }
    //   }
    //
    // The user can call /search API with a request like this:
    //
    //    session: ".../sessions/xxx"
    //    session_spec { query_id: ".../questions/zzz" }
    //
    // Then, the API stores the search result, associated with the last turn.
    // The stored search result can be used by a subsequent /answer API call
    // (with the session ID and the query ID specified). Also, it is possible
    // to call /search and /answer in parallel with the same session ID & query
    // ID.
    string query_id = 1;

    // The number of top search results to persist. The persisted search results
    // can be used for the subsequent /answer api call.
    //
    // This field is similar to the `summary_result_count` field in
    // [SearchRequest.ContentSearchSpec.SummarySpec.summary_result_count][google.cloud.discoveryengine.v1.SearchRequest.ContentSearchSpec.SummarySpec.summary_result_count].
    //
    // At most 10 results for documents mode, or 50 for chunks mode.
    optional int32 search_result_persistence_count = 2;
  }

  // The specification for returning the document relevance score.
  message RelevanceScoreSpec {
    // Optional. Whether to return the relevance score for search results.
    // The higher the score, the more relevant the document is to the query.
    bool return_relevance_score = 1 [(google.api.field_behavior) = OPTIONAL];
  }

  // The backend to use for the ranking expression evaluation.
  enum RankingExpressionBackend {
    // Default option for unspecified/unknown values.
    RANKING_EXPRESSION_BACKEND_UNSPECIFIED = 0;

    // Deprecated: Use `RANK_BY_EMBEDDING` instead.
    // Ranking by custom embedding model, the default way to evaluate the
    // ranking expression. Legacy enum option, `RANK_BY_EMBEDDING` should be
    // used instead.
    BYOE = 1 [deprecated = true];

    // Deprecated: Use `RANK_BY_FORMULA` instead.
    // Ranking by custom formula. Legacy enum option, `RANK_BY_FORMULA` should
    // be used instead.
    CLEARBOX = 2 [deprecated = true];

    // Ranking by custom embedding model, the default way to evaluate the
    // ranking expression.
    RANK_BY_EMBEDDING = 3;

    // Ranking by custom formula.
    RANK_BY_FORMULA = 4;
  }

  // The relevance threshold of the search results. The higher relevance
  // threshold is, the higher relevant results are shown and the less number of
  // results are returned.
  enum RelevanceThreshold {
    // Default value. In this case, server behavior defaults to Google defined
    // threshold.
    RELEVANCE_THRESHOLD_UNSPECIFIED = 0;

    // Lowest relevance threshold.
    LOWEST = 1;

    // Low relevance threshold.
    LOW = 2;

    // Medium relevance threshold.
    MEDIUM = 3;

    // High relevance threshold.
    HIGH = 4;
  }

  // Required. The resource name of the Search serving config, such as
  // `projects/*/locations/global/collections/default_collection/engines/*/servingConfigs/default_serving_config`,
  // or
  // `projects/*/locations/global/collections/default_collection/dataStores/default_data_store/servingConfigs/default_serving_config`.
  // This field is used to identify the serving configuration name, set
  // of models used to make the search.
  string serving_config = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "discoveryengine.googleapis.com/ServingConfig"
    }
  ];

  // The branch resource name, such as
  // `projects/*/locations/global/collections/default_collection/dataStores/default_data_store/branches/0`.
  //
  // Use `default_branch` as the branch ID or leave this field empty, to search
  // documents under the default branch.
  string branch = 2 [(google.api.resource_reference) = {
    type: "discoveryengine.googleapis.com/Branch"
  }];

  // Raw search query.
  string query = 3;

  // Optional. The categories associated with a category page. Must be set for
  // category navigation queries to achieve good search quality. The format
  // should be the same as
  // [PageInfo.page_category][google.cloud.discoveryengine.v1.PageInfo.page_category].
  // This field is the equivalent of the query for browse (navigation) queries.
  // It's used by the browse model when the query is empty.
  //
  // If the field is empty, it will not be used by the browse model.
  // If the field contains more than one element, only the first element will
  // be used.
  //
  // To represent full path of a category, use '>' character to separate
  // different hierarchies. If '>' is part of the category name, replace it with
  // other character(s).
  // For example, `Graphics Cards > RTX>4090 > Founders Edition` where "RTX >
  // 4090" represents one level, can be rewritten as `Graphics Cards > RTX_4090
  // > Founders Edition`
  repeated string page_categories = 63 [(google.api.field_behavior) = OPTIONAL];

  // Raw image query.
  ImageQuery image_query = 19;

  // Maximum number of [Document][google.cloud.discoveryengine.v1.Document]s to
  // return. The maximum allowed value depends on the data type. Values above
  // the maximum value are coerced to the maximum value.
  //
  // * Websites with basic indexing: Default `10`, Maximum `25`.
  // * Websites with advanced indexing: Default `25`, Maximum `50`.
  // * Other: Default `50`, Maximum `100`.
  //
  // If this field is negative, an  `INVALID_ARGUMENT` is returned.
  int32 page_size = 4;

  // A page token received from a previous
  // [SearchService.Search][google.cloud.discoveryengine.v1.SearchService.Search]
  // call. Provide this to retrieve the subsequent page.
  //
  // When paginating, all other parameters provided to
  // [SearchService.Search][google.cloud.discoveryengine.v1.SearchService.Search]
  // must match the call that provided the page token. Otherwise, an
  //  `INVALID_ARGUMENT`  error is returned.
  string page_token = 5;

  // A 0-indexed integer that specifies the current offset (that is, starting
  // result location, amongst the
  // [Document][google.cloud.discoveryengine.v1.Document]s deemed by the API as
  // relevant) in search results. This field is only considered if
  // [page_token][google.cloud.discoveryengine.v1.SearchRequest.page_token] is
  // unset.
  //
  // If this field is negative, an  `INVALID_ARGUMENT`  is returned.
  //
  // A large offset may be capped to a reasonable threshold.
  int32 offset = 6;

  // The maximum number of results to return for OneBox.
  // This applies to each OneBox type individually.
  // Default number is 10.
  int32 one_box_page_size = 47;

  // Specifications that define the specific
  // [DataStore][google.cloud.discoveryengine.v1.DataStore]s to be searched,
  // along with configurations for those data stores. This is only considered
  // for [Engine][google.cloud.discoveryengine.v1.Engine]s with multiple data
  // stores. For engines with a single data store, the specs directly under
  // [SearchRequest][google.cloud.discoveryengine.v1.SearchRequest] should be
  // used.
  repeated DataStoreSpec data_store_specs = 32;

  // The filter syntax consists of an expression language for constructing a
  // predicate from one or more fields of the documents being filtered. Filter
  // expression is case-sensitive.
  //
  // If this field is unrecognizable, an  `INVALID_ARGUMENT`  is returned.
  //
  // Filtering in Vertex AI Search is done by mapping the LHS filter key to a
  // key property defined in the Vertex AI Search backend -- this mapping is
  // defined by the customer in their schema. For example a media customer might
  // have a field 'name' in their schema. In this case the filter would look
  // like this: filter --> name:'ANY("king kong")'
  //
  // For more information about filtering including syntax and filter
  // operators, see
  // [Filter](https://cloud.google.com/generative-ai-app-builder/docs/filter-search-metadata)
  string filter = 7;

  // The default filter that is applied when a user performs a search without
  // checking any filters on the search page.
  //
  // The filter applied to every search request when quality improvement such as
  // query expansion is needed. In the case a query does not have a sufficient
  // amount of results this filter will be used to determine whether or not to
  // enable the query expansion flow. The original filter will still be used for
  // the query expanded search.
  // This field is strongly recommended to achieve high search quality.
  //
  // For more information about filter syntax, see
  // [SearchRequest.filter][google.cloud.discoveryengine.v1.SearchRequest.filter].
  string canonical_filter = 29;

  // The order in which documents are returned. Documents can be ordered by
  // a field in an [Document][google.cloud.discoveryengine.v1.Document] object.
  // Leave it unset if ordered by relevance. `order_by` expression is
  // case-sensitive.
  //
  // For more information on ordering the website search results, see
  // [Order web search
  // results](https://cloud.google.com/generative-ai-app-builder/docs/order-web-search-results).
  // For more information on ordering the healthcare search results, see
  // [Order healthcare search
  // results](https://cloud.google.com/generative-ai-app-builder/docs/order-hc-results).
  // If this field is unrecognizable, an `INVALID_ARGUMENT` is returned.
  string order_by = 8;

  // Information about the end user.
  // Highly recommended for analytics and personalization.
  // [UserInfo.user_agent][google.cloud.discoveryengine.v1.UserInfo.user_agent]
  // is used to deduce `device_type` for analytics.
  UserInfo user_info = 21;

  // The BCP-47 language code, such as "en-US" or "sr-Latn". For more
  // information, see [Standard
  // fields](https://cloud.google.com/apis/design/standard_fields). This field
  // helps to better interpret the query. If a value isn't specified, the query
  // language code is automatically detected, which may not be accurate.
  string language_code = 35;

  // Facet specifications for faceted search. If empty, no facets are returned.
  //
  // A maximum of 100 values are allowed. Otherwise, an  `INVALID_ARGUMENT`
  // error is returned.
  repeated FacetSpec facet_specs = 9;

  // Boost specification to boost certain documents.
  // For more information on boosting, see
  // [Boosting](https://cloud.google.com/generative-ai-app-builder/docs/boost-search-results)
  BoostSpec boost_spec = 10;

  // Additional search parameters.
  //
  // For public website search only, supported values are:
  //
  // * `user_country_code`: string. Default empty. If set to non-empty, results
  //    are restricted or boosted based on the location provided.
  //    For example, `user_country_code: "au"`
  //
  //    For available codes see [Country
  //    Codes](https://developers.google.com/custom-search/docs/json_api_reference#countryCodes)
  //
  // * `search_type`: double. Default empty. Enables non-webpage searching
  //    depending on the value. The only valid non-default value is 1,
  //    which enables image searching.
  //    For example, `search_type: 1`
  map<string, google.protobuf.Value> params = 11;

  // The query expansion specification that specifies the conditions under which
  // query expansion occurs.
  QueryExpansionSpec query_expansion_spec = 13;

  // The spell correction specification that specifies the mode under
  // which spell correction takes effect.
  SpellCorrectionSpec spell_correction_spec = 14;

  // Optional. A unique identifier for tracking visitors. For example, this
  // could be implemented with an HTTP cookie, which should be able to uniquely
  // identify a visitor on a single device. This unique identifier should not
  // change if the visitor logs in or out of the website.
  //
  // This field should NOT have a fixed value such as `unknown_visitor`.
  //
  // This should be the same identifier as
  // [UserEvent.user_pseudo_id][google.cloud.discoveryengine.v1.UserEvent.user_pseudo_id]
  // and
  // [CompleteQueryRequest.user_pseudo_id][google.cloud.discoveryengine.v1.CompleteQueryRequest.user_pseudo_id]
  //
  // The field must be a UTF-8 encoded string with a length limit of 128
  // characters. Otherwise, an  `INVALID_ARGUMENT`  error is returned.
  string user_pseudo_id = 15 [(google.api.field_behavior) = OPTIONAL];

  // A specification for configuring the behavior of content search.
  ContentSearchSpec content_search_spec = 24;

  // Optional. The ranking expression controls the customized ranking on
  // retrieval documents. This overrides
  // [ServingConfig.ranking_expression][google.cloud.discoveryengine.v1.ServingConfig.ranking_expression].
  // The syntax and supported features depend on the
  // `ranking_expression_backend` value. If `ranking_expression_backend` is not
  // provided, it defaults to `RANK_BY_EMBEDDING`.
  //
  // If
  // [ranking_expression_backend][google.cloud.discoveryengine.v1.SearchRequest.ranking_expression_backend]
  // is not provided or set to `RANK_BY_EMBEDDING`, it should be 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)`.
  //
  // If
  // [ranking_expression_backend][google.cloud.discoveryengine.v1.SearchRequest.ranking_expression_backend]
  // is set to `RANK_BY_FORMULA`, the following expression types (and
  // combinations of those chained using + or
  // * operators) are supported:
  //
  //   * `double`
  //   * `signal`
  //   * `log(signal)`
  //   * `exp(signal)`
  //   * `rr(signal, double > 0)`  -- reciprocal rank transformation with second
  //   argument being a denominator constant.
  //   * `is_nan(signal)` -- returns 0 if signal is NaN, 1 otherwise.
  //   * `fill_nan(signal1, signal2 | double)` -- if signal1 is NaN, returns
  //   signal2 | double, else returns signal1.
  //
  //   Here are a few examples of ranking formulas that use the supported
  //   ranking expression types:
  //
  //   - `0.2 * semantic_similarity_score + 0.8 * log(keyword_similarity_score)`
  //   -- mostly rank by the logarithm of `keyword_similarity_score` with slight
  //   `semantic_smilarity_score` adjustment.
  //   - `0.2 * exp(fill_nan(semantic_similarity_score, 0)) + 0.3 *
  //   is_nan(keyword_similarity_score)` -- rank by the exponent of
  //   `semantic_similarity_score` filling the value with 0 if it's NaN, also
  //   add constant 0.3 adjustment to the final score if
  //   `semantic_similarity_score` is NaN.
  //   - `0.2 * rr(semantic_similarity_score, 16) + 0.8 *
  //   rr(keyword_similarity_score, 16)` -- mostly rank by the reciprocal rank
  //   of `keyword_similarity_score` with slight adjustment of reciprocal rank
  //   of `semantic_smilarity_score`.
  //
  // The following signals are supported:
  //
  //   * `semantic_similarity_score`: semantic similarity adjustment that is
  //   calculated using the embeddings generated by a proprietary Google model.
  //   This score determines how semantically similar a search query is to a
  //   document.
  //   * `keyword_similarity_score`: keyword match adjustment uses the Best
  //   Match 25 (BM25) ranking function. This score is calculated using a
  //   probabilistic model to estimate the probability that a document is
  //   relevant to a given query.
  //   * `relevance_score`: semantic relevance adjustment that uses a
  //   proprietary Google model to determine the meaning and intent behind a
  //   user's query in context with the content in the documents.
  //   * `pctr_rank`: predicted conversion rate adjustment as a rank use
  //   predicted Click-through rate (pCTR) to gauge the relevance and
  //   attractiveness of a search result from a user's perspective. A higher
  //   pCTR suggests that the result is more likely to satisfy the user's query
  //   and intent, making it a valuable signal for ranking.
  //   * `freshness_rank`: freshness adjustment as a rank
  //   * `document_age`: The time in hours elapsed since the document was last
  //   updated, a floating-point number (e.g., 0.25 means 15 minutes).
  //   * `topicality_rank`: topicality adjustment as a rank. Uses proprietary
  //   Google model to determine the keyword-based overlap between the query and
  //   the document.
  //   * `base_rank`: the default rank of the result
  string ranking_expression = 26 [(google.api.field_behavior) = OPTIONAL];

  // Optional. The backend to use for the ranking expression evaluation.
  RankingExpressionBackend ranking_expression_backend = 53
      [(google.api.field_behavior) = OPTIONAL];

  // Whether to turn on safe search. This is only supported for
  // website search.
  bool safe_search = 20;

  // The user labels applied to a resource must meet the following requirements:
  //
  // * Each resource can have multiple labels, up to a maximum of 64.
  // * Each label must be a key-value pair.
  // * Keys have a minimum length of 1 character and a maximum length of 63
  //   characters and cannot be empty. Values can be empty and have a maximum
  //   length of 63 characters.
  // * Keys and values can contain only lowercase letters, numeric characters,
  //   underscores, and dashes. All characters must use UTF-8 encoding, and
  //   international characters are allowed.
  // * The key portion of a label must be unique. However, you can use the same
  //   key with multiple resources.
  // * Keys must start with a lowercase letter or international character.
  //
  // See [Google Cloud
  // Document](https://cloud.google.com/resource-manager/docs/creating-managing-labels#requirements)
  // for more details.
  map<string, string> user_labels = 22;

  // Optional. Config for natural language query understanding capabilities,
  // such as extracting structured field filters from the query. Refer to [this
  // documentation](https://cloud.google.com/generative-ai-app-builder/docs/natural-language-queries)
  // for more information.
  // If `naturalLanguageQueryUnderstandingSpec` is not specified, no additional
  // natural language query understanding will be done.
  NaturalLanguageQueryUnderstandingSpec
      natural_language_query_understanding_spec = 28
      [(google.api.field_behavior) = OPTIONAL];

  // Search as you type configuration. Only supported for the
  // [IndustryVertical.MEDIA][google.cloud.discoveryengine.v1.IndustryVertical.MEDIA]
  // vertical.
  SearchAsYouTypeSpec search_as_you_type_spec = 31;

  // Optional. Config for display feature, like match highlighting on search
  // results.
  DisplaySpec display_spec = 38 [(google.api.field_behavior) = OPTIONAL];

  // Optional. Crowding specifications for improving result diversity.
  // If multiple CrowdingSpecs are specified, crowding will be evaluated on
  // each unique combination of the `field` values, and max_count will be the
  // maximum value of `max_count` across all CrowdingSpecs.
  // For example, if the first CrowdingSpec has `field` = "color" and
  // `max_count` = 3, and the second CrowdingSpec has `field` = "size" and
  // `max_count` = 2, then after 3 documents that share the same color AND size
  // have been returned, subsequent ones should be
  // removed or demoted.
  repeated CrowdingSpec crowding_specs = 40
      [(google.api.field_behavior) = OPTIONAL];

  // The session resource name. Optional.
  //
  // Session allows users to do multi-turn /search API calls or coordination
  // between /search API calls and /answer API calls.
  //
  // Example #1 (multi-turn /search API calls):
  //   Call /search API with the session ID generated in the first call.
  //   Here, the previous search query gets considered in query
  //   standing. I.e., if the first query is "How did Alphabet do in 2022?"
  //   and the current query is "How about 2023?", the current query will
  //   be interpreted as "How did Alphabet do in 2023?".
  //
  // Example #2 (coordination between /search API calls and /answer API calls):
  //   Call /answer API with the session ID generated in the first call.
  //   Here, the answer generation happens in the context of the search
  //   results from the first search call.
  //
  // Multi-turn Search feature is currently at private GA stage. Please use
  // v1alpha or v1beta version instead before we launch this feature to public
  // GA. Or ask for allowlisting through Google Support team.
  string session = 41 [(google.api.resource_reference) = {
    type: "discoveryengine.googleapis.com/Session"
  }];

  // Session specification.
  //
  // Can be used only when `session` is set.
  SessionSpec session_spec = 42;

  // The global relevance threshold of the search results.
  //
  // Defaults to Google defined threshold, leveraging a balance of
  // precision and recall to deliver both highly accurate results and
  // comprehensive coverage of relevant information.
  //
  // If more granular relevance filtering is required, use the
  // `relevance_filter_spec` instead.
  //
  // This feature is not supported for healthcare search.
  RelevanceThreshold relevance_threshold = 44;

  // Optional. The specification for returning the relevance score.
  RelevanceScoreSpec relevance_score_spec = 52
      [(google.api.field_behavior) = OPTIONAL];
}

// Response message for
// [SearchService.Search][google.cloud.discoveryengine.v1.SearchService.Search]
// method.
message SearchResponse {
  // Represents the search results.
  message SearchResult {
    // A set of ranking signals.
    message RankSignals {
      // Custom clearbox signal represented by name and value pair.
      message CustomSignal {
        // Optional. Name of the signal.
        string name = 1 [(google.api.field_behavior) = OPTIONAL];

        // Optional. Float value representing the ranking signal (e.g. 1.25 for
        // BM25).
        float value = 2 [(google.api.field_behavior) = OPTIONAL];
      }

      // Optional. Keyword matching adjustment.
      optional float keyword_similarity_score = 1
          [(google.api.field_behavior) = OPTIONAL];

      // Optional. Semantic relevance adjustment.
      optional float relevance_score = 2
          [(google.api.field_behavior) = OPTIONAL];

      // Optional. Semantic similarity adjustment.
      optional float semantic_similarity_score = 3
          [(google.api.field_behavior) = OPTIONAL];

      // Optional. Predicted conversion rate adjustment as a rank.
      optional float pctr_rank = 4 [(google.api.field_behavior) = OPTIONAL];

      // Optional. Topicality adjustment as a rank.
      optional float topicality_rank = 6
          [(google.api.field_behavior) = OPTIONAL];

      // Optional. Age of the document in hours.
      optional float document_age = 7 [(google.api.field_behavior) = OPTIONAL];

      // Optional. Combined custom boosts for a doc.
      optional float boosting_factor = 8
          [(google.api.field_behavior) = OPTIONAL];

      // Optional. The default rank of the result.
      float default_rank = 32 [(google.api.field_behavior) = OPTIONAL];

      // Optional. A list of custom clearbox signals.
      repeated CustomSignal custom_signals = 33
          [(google.api.field_behavior) = OPTIONAL];
    }

    // [Document.id][google.cloud.discoveryengine.v1.Document.id] of the
    // searched [Document][google.cloud.discoveryengine.v1.Document].
    string id = 1;

    // The document data snippet in the search response. Only fields that are
    // marked as `retrievable` are populated.
    Document document = 2;

    // The chunk data in the search response if the
    // [SearchRequest.ContentSearchSpec.search_result_mode][google.cloud.discoveryengine.v1.SearchRequest.ContentSearchSpec.search_result_mode]
    // is set to
    // [CHUNKS][google.cloud.discoveryengine.v1.SearchRequest.ContentSearchSpec.SearchResultMode.CHUNKS].
    Chunk chunk = 18;

    // Output only. Google provided available scores.
    map<string, DoubleList> model_scores = 4
        [(google.api.field_behavior) = OUTPUT_ONLY];

    // Optional. A set of ranking signals associated with the result.
    RankSignals rank_signals = 7 [(google.api.field_behavior) = OPTIONAL];
  }

  // A facet result.
  message Facet {
    // A facet value which contains value names and their count.
    message FacetValue {
      // A facet value which contains values.
      oneof facet_value {
        // Text value of a facet, such as "Black" for facet "colors".
        string value = 1;

        // Interval value for a facet, such as [10, 20) for facet "price". It
        // matches
        // [SearchRequest.FacetSpec.FacetKey.intervals][google.cloud.discoveryengine.v1.SearchRequest.FacetSpec.FacetKey.intervals].
        Interval interval = 2;
      }

      // Number of items that have this facet value.
      int64 count = 3;
    }

    // The key for this facet. For example, `"colors"` or `"price"`. It matches
    // [SearchRequest.FacetSpec.FacetKey.key][google.cloud.discoveryengine.v1.SearchRequest.FacetSpec.FacetKey.key].
    string key = 1;

    // The facet values for this field.
    repeated FacetValue values = 2;

    // Whether the facet is dynamically generated.
    bool dynamic_facet = 3;
  }

  // Summary of the top N search results specified by the summary spec.
  message Summary {
    // Safety Attribute categories and their associated confidence scores.
    message SafetyAttributes {
      // The display names of Safety Attribute categories associated with the
      // generated content. Order matches the Scores.
      repeated string categories = 1;

      // The confidence scores of the each category, higher
      // value means higher confidence. Order matches the Categories.
      repeated float scores = 2;
    }

    // Citation metadata.
    message CitationMetadata {
      // Citations for segments.
      repeated Citation citations = 1;
    }

    // Citation info for a segment.
    message Citation {
      // Index indicates the start of the segment, measured in bytes/unicode.
      int64 start_index = 1;

      // End of the attributed segment, exclusive.
      int64 end_index = 2;

      // Citation sources for the attributed segment.
      repeated CitationSource sources = 3;
    }

    // Citation source.
    message CitationSource {
      // Document reference index from SummaryWithMetadata.references.
      // It is 0-indexed and the value will be zero if the reference_index is
      // not set explicitly.
      int64 reference_index = 4;
    }

    // Document reference.
    message Reference {
      // Chunk content.
      message ChunkContent {
        // Chunk textual content.
        string content = 1;

        // Page identifier.
        string page_identifier = 2;
      }

      // Title of the document.
      string title = 1;

      // Required.
      // [Document.name][google.cloud.discoveryengine.v1.Document.name] of the
      // document. Full resource name of the referenced document, in the format
      // `projects/*/locations/*/collections/*/dataStores/*/branches/*/documents/*`.
      string document = 2 [
        (google.api.field_behavior) = REQUIRED,
        (google.api.resource_reference) = {
          type: "discoveryengine.googleapis.com/Document"
        }
      ];

      // Cloud Storage or HTTP uri for the document.
      string uri = 3;

      // List of cited chunk contents derived from document content.
      repeated ChunkContent chunk_contents = 4;
    }

    // Summary with metadata information.
    message SummaryWithMetadata {
      // Summary text with no citation information.
      string summary = 1;

      // Citation metadata for given summary.
      CitationMetadata citation_metadata = 2;

      // Document References.
      repeated Reference references = 3;
    }

    // An Enum for summary-skipped reasons.
    enum SummarySkippedReason {
      // Default value. The summary skipped reason is not specified.
      SUMMARY_SKIPPED_REASON_UNSPECIFIED = 0;

      // The adversarial query ignored case.
      //
      // Only used when
      // [SummarySpec.ignore_adversarial_query][google.cloud.discoveryengine.v1.SearchRequest.ContentSearchSpec.SummarySpec.ignore_adversarial_query]
      // is set to `true`.
      ADVERSARIAL_QUERY_IGNORED = 1;

      // The non-summary seeking query ignored case.
      //
      // Google skips the summary if the query is chit chat.
      // Only used when
      // [SummarySpec.ignore_non_summary_seeking_query][google.cloud.discoveryengine.v1.SearchRequest.ContentSearchSpec.SummarySpec.ignore_non_summary_seeking_query]
      // is set to `true`.
      NON_SUMMARY_SEEKING_QUERY_IGNORED = 2;

      // The out-of-domain query ignored case.
      //
      // Google skips the summary if there are no high-relevance search results.
      // For example, the data store contains facts about company A but the
      // user query is asking questions about company B.
      OUT_OF_DOMAIN_QUERY_IGNORED = 3;

      // The potential policy violation case.
      //
      // Google skips the summary if there is a potential policy violation
      // detected. This includes content that may be violent or toxic.
      POTENTIAL_POLICY_VIOLATION = 4;

      // The LLM addon not enabled case.
      //
      // Google skips the summary if the LLM addon is not enabled.
      LLM_ADDON_NOT_ENABLED = 5;

      // The no relevant content case.
      //
      // Google skips the summary if there is no relevant content in the
      // retrieved search results.
      NO_RELEVANT_CONTENT = 6;

      // The jail-breaking query ignored case.
      //
      // For example, "Reply in the tone of a competing company's CEO".
      // Only used when
      // [SearchRequest.ContentSearchSpec.SummarySpec.ignore_jail_breaking_query]
      // is set to `true`.
      JAIL_BREAKING_QUERY_IGNORED = 7;

      // The customer policy violation case.
      //
      // Google skips the summary if there is a customer policy violation
      // detected. The policy is defined by the customer.
      CUSTOMER_POLICY_VIOLATION = 8;

      // The non-answer seeking query ignored case.
      //
      // Google skips the summary if the query doesn't have clear intent.
      // Only used when
      // [SearchRequest.ContentSearchSpec.SummarySpec.ignore_non_answer_seeking_query]
      // is set to `true`.
      NON_SUMMARY_SEEKING_QUERY_IGNORED_V2 = 9;

      // The time out case.
      //
      // Google skips the summary if the time out.
      TIME_OUT = 10;
    }

    // The summary content.
    string summary_text = 1;

    // Additional summary-skipped reasons. This provides the reason for ignored
    // cases. If nothing is skipped, this field is not set.
    repeated SummarySkippedReason summary_skipped_reasons = 2;

    // A collection of Safety Attribute categories and their associated
    // confidence scores.
    SafetyAttributes safety_attributes = 3;

    // Summary with metadata information.
    SummaryWithMetadata summary_with_metadata = 4;
  }

  // Information describing query expansion including whether expansion has
  // occurred.
  message QueryExpansionInfo {
    // Bool describing whether query expansion has occurred.
    bool expanded_query = 1;

    // Number of pinned results. This field will only be set when expansion
    // happens and
    // [SearchRequest.QueryExpansionSpec.pin_unexpanded_results][google.cloud.discoveryengine.v1.SearchRequest.QueryExpansionSpec.pin_unexpanded_results]
    // is set to true.
    int64 pinned_result_count = 2;
  }

  // Information describing what natural language understanding was
  // done on the input query.
  message NaturalLanguageQueryUnderstandingInfo {
    // The filters that were extracted from the input query represented in a
    // structured form.
    message StructuredExtractedFilter {
      // Constraint expression of a string field.
      message StringConstraint {
        // Name of the string field as defined in the schema.
        string field_name = 1;

        // Values of the string field. The record will only be returned if the
        // field value matches one of the values specified here.
        repeated string values = 2;

        // Identifies the keywords within the search query that match a filter.
        string query_segment = 3;
      }

      // Constraint expression of a number field. Example: price < 100.
      message NumberConstraint {
        // The comparison operation that was performed.
        enum Comparison {
          // Undefined comparison operator.
          COMPARISON_UNSPECIFIED = 0;

          // Denotes equality `=` operator.
          EQUALS = 1;

          // Denotes less than or equal to `<=` operator.
          LESS_THAN_EQUALS = 2;

          // Denotes less than `<` operator.
          LESS_THAN = 3;

          // Denotes greater than or equal to `>=` operator.
          GREATER_THAN_EQUALS = 4;

          // Denotes greater than `>` operator.
          GREATER_THAN = 5;
        }

        // Name of the numerical field as defined in the schema.
        string field_name = 1;

        // The comparison operation performed between the field value and the
        // value specified in the constraint.
        Comparison comparison = 2;

        // The value specified in the numerical constraint.
        double value = 3;

        // Identifies the keywords within the search query that match a filter.
        string query_segment = 4;
      }

      // Constraint of a geolocation field.
      // Name of the geolocation field as defined in the schema.
      message GeolocationConstraint {
        // The name of the geolocation field as defined in the schema.
        string field_name = 1;

        // The reference address that was inferred from the input query. The
        // proximity of the reference address to the geolocation field will be
        // used to filter the results.
        string address = 2;

        // The latitude of the geolocation inferred from the input query.
        double latitude = 4;

        // The longitude of the geolocation inferred from the input query.
        double longitude = 5;

        // The radius in meters around the address. The record is returned if
        // the location of the geolocation field is within the radius.
        float radius_in_meters = 3;
      }

      // Logical `And` operator.
      message AndExpression {
        // The expressions that were ANDed together.
        repeated Expression expressions = 1;
      }

      // Logical `Or` operator.
      message OrExpression {
        // The expressions that were ORed together.
        repeated Expression expressions = 1;
      }

      // The expression denoting the filter that was extracted from the input
      // query.
      message Expression {
        // The expression type.
        oneof expr {
          // String constraint expression.
          StringConstraint string_constraint = 1;

          // Numerical constraint expression.
          NumberConstraint number_constraint = 2;

          // Geolocation constraint expression.
          GeolocationConstraint geolocation_constraint = 3;

          // Logical "And" compound operator connecting multiple expressions.
          AndExpression and_expr = 4;

          // Logical "Or" compound operator connecting multiple expressions.
          OrExpression or_expr = 5;
        }
      }

      // The expression denoting the filter that was extracted from the input
      // query in a structured form. It can be a simple expression denoting a
      // single string, numerical or geolocation constraint or a compound
      // expression which is a combination of multiple expressions connected
      // using logical (OR and AND) operators.
      Expression expression = 1;
    }

    // The filters that were extracted from the input query.
    string extracted_filters = 1;

    // Rewritten input query minus the extracted filters.
    string rewritten_query = 2;

    // The classified intents from the input query.
    repeated string classified_intents = 5;

    // The filters that were extracted from the input query represented in a
    // structured form.
    StructuredExtractedFilter structured_extracted_filter = 3;
  }

  // Information about the session.
  message SessionInfo {
    // Name of the session.
    // If the auto-session mode is used (when
    // [SearchRequest.session][google.cloud.discoveryengine.v1.SearchRequest.session]
    // ends with "-"), this field holds the newly generated session name.
    string name = 1;

    // Query ID that corresponds to this search API call.
    // One session can have multiple turns, each with a unique query ID.
    //
    // By specifying the session name and this query ID in the Answer API call,
    // the answer generation happens in the context of the search results from
    // this search call.
    string query_id = 2;
  }

  // Semantic state of the search response.
  enum SemanticState {
    // Default value. Should not be used.
    SEMANTIC_STATE_UNSPECIFIED = 0;

    // Semantic search was disabled for this search response.
    DISABLED = 1;

    // Semantic search was enabled for this search response.
    ENABLED = 2;
  }

  // A list of matched documents. The order represents the ranking.
  repeated SearchResult results = 1;

  // Results of facets requested by user.
  repeated Facet facets = 2;

  // The estimated total count of matched items irrespective of pagination. The
  // count of [results][google.cloud.discoveryengine.v1.SearchResponse.results]
  // returned by pagination may be less than the
  // [total_size][google.cloud.discoveryengine.v1.SearchResponse.total_size]
  // that matches.
  int32 total_size = 3;

  // A unique search token. This should be included in the
  // [UserEvent][google.cloud.discoveryengine.v1.UserEvent] logs resulting from
  // this search, which enables accurate attribution of search model
  // performance. This also helps to identify a request during the customer
  // support scenarios.
  string attribution_token = 4;

  // The URI of a customer-defined redirect page. If redirect action is
  // triggered, no search is performed, and only
  // [redirect_uri][google.cloud.discoveryengine.v1.SearchResponse.redirect_uri]
  // and
  // [attribution_token][google.cloud.discoveryengine.v1.SearchResponse.attribution_token]
  // are set in the response.
  string redirect_uri = 12;

  // A token that can be sent as
  // [SearchRequest.page_token][google.cloud.discoveryengine.v1.SearchRequest.page_token]
  // to retrieve the next page. If this field is omitted, there are no
  // subsequent pages.
  string next_page_token = 5;

  // Contains the spell corrected query, if found. If the spell correction type
  // is AUTOMATIC, then the search results are based on corrected_query.
  // Otherwise the original query is used for search.
  string corrected_query = 7;

  // A summary as part of the search results.
  // This field is only returned if
  // [SearchRequest.ContentSearchSpec.summary_spec][google.cloud.discoveryengine.v1.SearchRequest.ContentSearchSpec.summary_spec]
  // is set.
  Summary summary = 9;

  // Query expansion information for the returned results.
  QueryExpansionInfo query_expansion_info = 14;

  // Output only. Natural language query understanding information for the
  // returned results.
  NaturalLanguageQueryUnderstandingInfo
      natural_language_query_understanding_info = 15
      [(google.api.field_behavior) = OUTPUT_ONLY];

  // Session information.
  //
  // Only set if
  // [SearchRequest.session][google.cloud.discoveryengine.v1.SearchRequest.session]
  // is provided. See its description for more details.
  SessionInfo session_info = 19;

  // Promotions for site search.
  repeated SearchLinkPromotion search_link_promotions = 23;

  // Output only. Indicates the semantic state of the search response.
  SemanticState semantic_state = 36 [(google.api.field_behavior) = OUTPUT_ONLY];
}
