// 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.v1beta;

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/v1beta/answer.proto";
import "google/cloud/discoveryengine/v1beta/conversation.proto";
import "google/cloud/discoveryengine/v1beta/search_service.proto";
import "google/cloud/discoveryengine/v1beta/session.proto";
import "google/protobuf/empty.proto";
import "google/protobuf/field_mask.proto";

option csharp_namespace = "Google.Cloud.DiscoveryEngine.V1Beta";
option go_package = "cloud.google.com/go/discoveryengine/apiv1beta/discoveryenginepb;discoveryenginepb";
option java_multiple_files = true;
option java_outer_classname = "ConversationalSearchServiceProto";
option java_package = "com.google.cloud.discoveryengine.v1beta";
option objc_class_prefix = "DISCOVERYENGINE";
option php_namespace = "Google\\Cloud\\DiscoveryEngine\\V1beta";
option ruby_package = "Google::Cloud::DiscoveryEngine::V1beta";

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

  // Converses a conversation.
  rpc ConverseConversation(ConverseConversationRequest)
      returns (ConverseConversationResponse) {
    option (google.api.http) = {
      post: "/v1beta/{name=projects/*/locations/*/dataStores/*/conversations/*}:converse"
      body: "*"
      additional_bindings {
        post: "/v1beta/{name=projects/*/locations/*/collections/*/dataStores/*/conversations/*}:converse"
        body: "*"
      }
      additional_bindings {
        post: "/v1beta/{name=projects/*/locations/*/collections/*/engines/*/conversations/*}:converse"
        body: "*"
      }
    };
    option (google.api.method_signature) = "name,query";
  }

  // Creates a Conversation.
  //
  // If the [Conversation][google.cloud.discoveryengine.v1beta.Conversation] to
  // create already exists, an ALREADY_EXISTS error is returned.
  rpc CreateConversation(CreateConversationRequest) returns (Conversation) {
    option (google.api.http) = {
      post: "/v1beta/{parent=projects/*/locations/*/dataStores/*}/conversations"
      body: "conversation"
      additional_bindings {
        post: "/v1beta/{parent=projects/*/locations/*/collections/*/dataStores/*}/conversations"
        body: "conversation"
      }
      additional_bindings {
        post: "/v1beta/{parent=projects/*/locations/*/collections/*/engines/*}/conversations"
        body: "conversation"
      }
    };
    option (google.api.method_signature) = "parent,conversation";
  }

  // Deletes a Conversation.
  //
  // If the [Conversation][google.cloud.discoveryengine.v1beta.Conversation] to
  // delete does not exist, a NOT_FOUND error is returned.
  rpc DeleteConversation(DeleteConversationRequest)
      returns (google.protobuf.Empty) {
    option (google.api.http) = {
      delete: "/v1beta/{name=projects/*/locations/*/dataStores/*/conversations/*}"
      additional_bindings {
        delete: "/v1beta/{name=projects/*/locations/*/collections/*/dataStores/*/conversations/*}"
      }
      additional_bindings {
        delete: "/v1beta/{name=projects/*/locations/*/collections/*/engines/*/conversations/*}"
      }
    };
    option (google.api.method_signature) = "name";
  }

  // Updates a Conversation.
  //
  // [Conversation][google.cloud.discoveryengine.v1beta.Conversation] action
  // type cannot be changed. If the
  // [Conversation][google.cloud.discoveryengine.v1beta.Conversation] to update
  // does not exist, a NOT_FOUND error is returned.
  rpc UpdateConversation(UpdateConversationRequest) returns (Conversation) {
    option (google.api.http) = {
      patch: "/v1beta/{conversation.name=projects/*/locations/*/dataStores/*/conversations/*}"
      body: "conversation"
      additional_bindings {
        patch: "/v1beta/{conversation.name=projects/*/locations/*/collections/*/dataStores/*/conversations/*}"
        body: "conversation"
      }
      additional_bindings {
        patch: "/v1beta/{conversation.name=projects/*/locations/*/collections/*/engines/*/conversations/*}"
        body: "conversation"
      }
    };
    option (google.api.method_signature) = "conversation,update_mask";
  }

  // Gets a Conversation.
  rpc GetConversation(GetConversationRequest) returns (Conversation) {
    option (google.api.http) = {
      get: "/v1beta/{name=projects/*/locations/*/dataStores/*/conversations/*}"
      additional_bindings {
        get: "/v1beta/{name=projects/*/locations/*/collections/*/dataStores/*/conversations/*}"
      }
      additional_bindings {
        get: "/v1beta/{name=projects/*/locations/*/collections/*/engines/*/conversations/*}"
      }
    };
    option (google.api.method_signature) = "name";
  }

  // Lists all Conversations by their parent
  // [DataStore][google.cloud.discoveryengine.v1beta.DataStore].
  rpc ListConversations(ListConversationsRequest)
      returns (ListConversationsResponse) {
    option (google.api.http) = {
      get: "/v1beta/{parent=projects/*/locations/*/dataStores/*}/conversations"
      additional_bindings {
        get: "/v1beta/{parent=projects/*/locations/*/collections/*/dataStores/*}/conversations"
      }
      additional_bindings {
        get: "/v1beta/{parent=projects/*/locations/*/collections/*/engines/*}/conversations"
      }
    };
    option (google.api.method_signature) = "parent";
  }

  // Answer query method.
  rpc AnswerQuery(AnswerQueryRequest) returns (AnswerQueryResponse) {
    option (google.api.http) = {
      post: "/v1beta/{serving_config=projects/*/locations/*/dataStores/*/servingConfigs/*}:answer"
      body: "*"
      additional_bindings {
        post: "/v1beta/{serving_config=projects/*/locations/*/collections/*/dataStores/*/servingConfigs/*}:answer"
        body: "*"
      }
      additional_bindings {
        post: "/v1beta/{serving_config=projects/*/locations/*/collections/*/engines/*/servingConfigs/*}:answer"
        body: "*"
      }
    };
  }

  // Gets a Answer.
  rpc GetAnswer(GetAnswerRequest) returns (Answer) {
    option (google.api.http) = {
      get: "/v1beta/{name=projects/*/locations/*/dataStores/*/sessions/*/answers/*}"
      additional_bindings {
        get: "/v1beta/{name=projects/*/locations/*/collections/*/dataStores/*/sessions/*/answers/*}"
      }
      additional_bindings {
        get: "/v1beta/{name=projects/*/locations/*/collections/*/engines/*/sessions/*/answers/*}"
      }
    };
    option (google.api.method_signature) = "name";
  }

  // Creates a Session.
  //
  // If the [Session][google.cloud.discoveryengine.v1beta.Session] to create
  // already exists, an ALREADY_EXISTS error is returned.
  rpc CreateSession(CreateSessionRequest) returns (Session) {
    option (google.api.http) = {
      post: "/v1beta/{parent=projects/*/locations/*/dataStores/*}/sessions"
      body: "session"
      additional_bindings {
        post: "/v1beta/{parent=projects/*/locations/*/collections/*/dataStores/*}/sessions"
        body: "session"
      }
      additional_bindings {
        post: "/v1beta/{parent=projects/*/locations/*/collections/*/engines/*}/sessions"
        body: "session"
      }
    };
    option (google.api.method_signature) = "parent,session";
  }

  // Deletes a Session.
  //
  // If the [Session][google.cloud.discoveryengine.v1beta.Session] to delete
  // does not exist, a NOT_FOUND error is returned.
  rpc DeleteSession(DeleteSessionRequest) returns (google.protobuf.Empty) {
    option (google.api.http) = {
      delete: "/v1beta/{name=projects/*/locations/*/dataStores/*/sessions/*}"
      additional_bindings {
        delete: "/v1beta/{name=projects/*/locations/*/collections/*/dataStores/*/sessions/*}"
      }
      additional_bindings {
        delete: "/v1beta/{name=projects/*/locations/*/collections/*/engines/*/sessions/*}"
      }
    };
    option (google.api.method_signature) = "name";
  }

  // Updates a Session.
  //
  // [Session][google.cloud.discoveryengine.v1beta.Session] action type cannot
  // be changed. If the [Session][google.cloud.discoveryengine.v1beta.Session]
  // to update does not exist, a NOT_FOUND error is returned.
  rpc UpdateSession(UpdateSessionRequest) returns (Session) {
    option (google.api.http) = {
      patch: "/v1beta/{session.name=projects/*/locations/*/dataStores/*/sessions/*}"
      body: "session"
      additional_bindings {
        patch: "/v1beta/{session.name=projects/*/locations/*/collections/*/dataStores/*/sessions/*}"
        body: "session"
      }
      additional_bindings {
        patch: "/v1beta/{session.name=projects/*/locations/*/collections/*/engines/*/sessions/*}"
        body: "session"
      }
    };
    option (google.api.method_signature) = "session,update_mask";
  }

  // Gets a Session.
  rpc GetSession(GetSessionRequest) returns (Session) {
    option (google.api.http) = {
      get: "/v1beta/{name=projects/*/locations/*/dataStores/*/sessions/*}"
      additional_bindings {
        get: "/v1beta/{name=projects/*/locations/*/collections/*/dataStores/*/sessions/*}"
      }
      additional_bindings {
        get: "/v1beta/{name=projects/*/locations/*/collections/*/engines/*/sessions/*}"
      }
    };
    option (google.api.method_signature) = "name";
  }

  // Lists all Sessions by their parent
  // [DataStore][google.cloud.discoveryengine.v1beta.DataStore].
  rpc ListSessions(ListSessionsRequest) returns (ListSessionsResponse) {
    option (google.api.http) = {
      get: "/v1beta/{parent=projects/*/locations/*/dataStores/*}/sessions"
      additional_bindings {
        get: "/v1beta/{parent=projects/*/locations/*/collections/*/dataStores/*}/sessions"
      }
      additional_bindings {
        get: "/v1beta/{parent=projects/*/locations/*/collections/*/engines/*}/sessions"
      }
    };
    option (google.api.method_signature) = "parent";
  }
}

// Request message for
// [ConversationalSearchService.ConverseConversation][google.cloud.discoveryengine.v1beta.ConversationalSearchService.ConverseConversation]
// method.
message ConverseConversationRequest {
  // Required. The resource name of the Conversation to get. Format:
  // `projects/{project}/locations/{location}/collections/{collection}/dataStores/{data_store_id}/conversations/{conversation_id}`.
  // Use
  // `projects/{project}/locations/{location}/collections/{collection}/dataStores/{data_store_id}/conversations/-`
  // to activate auto session mode, which automatically creates a new
  // conversation inside a ConverseConversation session.
  string name = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "discoveryengine.googleapis.com/Conversation"
    }
  ];

  // Required. Current user input.
  TextInput query = 2 [(google.api.field_behavior) = REQUIRED];

  // The resource name of the Serving Config to use. Format:
  // `projects/{project}/locations/{location}/collections/{collection}/dataStores/{data_store_id}/servingConfigs/{serving_config_id}`
  // If this is not set, the default serving config will be used.
  string serving_config = 3 [(google.api.resource_reference) = {
    type: "discoveryengine.googleapis.com/ServingConfig"
  }];

  // The conversation to be used by auto session only. The name field will be
  // ignored as we automatically assign new name for the conversation in auto
  // session.
  Conversation conversation = 5;

  // Whether to turn on safe search.
  bool safe_search = 6;

  // 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 = 7;

  // A specification for configuring the summary returned in the response.
  SearchRequest.ContentSearchSpec.SummarySpec summary_spec = 8;

  // 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. This will be used to filter search results
  // which may affect the summary response.
  //
  // 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 = 9;

  // Boost specification to boost certain documents in search results which may
  // affect the converse response. For more information on boosting, see
  // [Boosting](https://cloud.google.com/retail/docs/boosting#boost)
  SearchRequest.BoostSpec boost_spec = 10;
}

// Response message for
// [ConversationalSearchService.ConverseConversation][google.cloud.discoveryengine.v1beta.ConversationalSearchService.ConverseConversation]
// method.
message ConverseConversationResponse {
  // Answer to the current query.
  Reply reply = 1;

  // Updated conversation including the answer.
  Conversation conversation = 2;

  // Suggested related questions.
  repeated string related_questions = 6;

  // Search Results.
  repeated SearchResponse.SearchResult search_results = 3;
}

// Request for CreateConversation method.
message CreateConversationRequest {
  // Required. Full resource name of parent data store. Format:
  // `projects/{project}/locations/{location}/collections/{collection}/dataStores/{data_store_id}`
  string parent = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "discoveryengine.googleapis.com/DataStore"
    }
  ];

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

// Request for UpdateConversation method.
message UpdateConversationRequest {
  // Required. The Conversation to update.
  Conversation conversation = 1 [(google.api.field_behavior) = REQUIRED];

  // Indicates which fields in the provided
  // [Conversation][google.cloud.discoveryengine.v1beta.Conversation] to update.
  // The following are NOT supported:
  //
  // * [Conversation.name][google.cloud.discoveryengine.v1beta.Conversation.name]
  //
  // If not set or empty, all supported fields are updated.
  google.protobuf.FieldMask update_mask = 2;
}

// Request for DeleteConversation method.
message DeleteConversationRequest {
  // Required. The resource name of the Conversation to delete. Format:
  // `projects/{project}/locations/{location}/collections/{collection}/dataStores/{data_store_id}/conversations/{conversation_id}`
  string name = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "discoveryengine.googleapis.com/Conversation"
    }
  ];
}

// Request for GetConversation method.
message GetConversationRequest {
  // Required. The resource name of the Conversation to get. Format:
  // `projects/{project}/locations/{location}/collections/{collection}/dataStores/{data_store_id}/conversations/{conversation_id}`
  string name = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "discoveryengine.googleapis.com/Conversation"
    }
  ];
}

// Request for ListConversations method.
message ListConversationsRequest {
  // Required. The data store resource name. Format:
  // `projects/{project}/locations/{location}/collections/{collection}/dataStores/{data_store_id}`
  string parent = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "discoveryengine.googleapis.com/DataStore"
    }
  ];

  // Maximum number of results to return. If unspecified, defaults
  // to 50. Max allowed value is 1000.
  int32 page_size = 2;

  // A page token, received from a previous `ListConversations` call.
  // Provide this to retrieve the subsequent page.
  string page_token = 3;

  // A filter to apply on the list results. The supported features are:
  // user_pseudo_id, state.
  //
  // Example:
  // "user_pseudo_id = some_id"
  string filter = 4;

  // A comma-separated list of fields to order by, sorted in ascending order.
  // Use "desc" after a field name for descending.
  // Supported fields:
  //   * `update_time`
  //   * `create_time`
  //   * `conversation_name`
  //
  // Example:
  // "update_time desc"
  // "create_time"
  string order_by = 5;
}

// Response for ListConversations method.
message ListConversationsResponse {
  // All the Conversations for a given data store.
  repeated Conversation conversations = 1;

  // Pagination token, if not returned indicates the last page.
  string next_page_token = 2;
}

// Request message for
// [ConversationalSearchService.AnswerQuery][google.cloud.discoveryengine.v1beta.ConversationalSearchService.AnswerQuery]
// method.
message AnswerQueryRequest {
  // Safety specification.
  message SafetySpec {
    // Enable the safety filtering on the answer response. It is false by
    // default.
    bool enable = 1;
  }

  // Related questions specification.
  message RelatedQuestionsSpec {
    // Enable related questions feature if true.
    bool enable = 1;
  }

  // Grounding specification.
  message GroundingSpec {
    // Level to filter based on answer grounding.
    enum FilteringLevel {
      // Default is no filter
      FILTERING_LEVEL_UNSPECIFIED = 0;

      // Filter answers based on a low threshold.
      FILTERING_LEVEL_LOW = 1;

      // Filter answers based on a high threshold.
      FILTERING_LEVEL_HIGH = 2;
    }

    // Optional. Specifies whether to include grounding_supports in the answer.
    // The default value is `false`.
    //
    // When this field is set to `true`, returned answer will have
    // `grounding_score` and will contain GroundingSupports for each claim.
    bool include_grounding_supports = 2
        [(google.api.field_behavior) = OPTIONAL];

    // Optional. Specifies whether to enable the filtering based on grounding
    // score and at what level.
    FilteringLevel filtering_level = 3 [(google.api.field_behavior) = OPTIONAL];
  }

  // Answer generation specification.
  message AnswerGenerationSpec {
    // Answer Generation Model specification.
    message ModelSpec {
      // Model version. If not set, it will use the default stable model.
      // Allowed values are: stable, preview.
      string model_version = 1;
    }

    // Answer generation prompt specification.
    message PromptSpec {
      // Customized preamble.
      string preamble = 1;
    }

    // Answer generation model specification.
    ModelSpec model_spec = 1;

    // Answer generation prompt specification.
    PromptSpec prompt_spec = 2;

    // Specifies whether to include citation metadata in the answer. The default
    // value is `false`.
    bool include_citations = 3;

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

    // Specifies whether to filter out adversarial queries. The default value
    // is `false`.
    //
    // Google employs search-query classification to detect adversarial
    // queries. No answer 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 answers for adversarial queries and return
    // fallback messages instead.
    bool ignore_adversarial_query = 5;

    // Specifies whether to filter out queries that are not answer-seeking.
    // The default value is `false`.
    //
    // Google employs search-query classification to detect answer-seeking
    // queries. No answer is returned if the search query is classified as a
    // non-answer seeking query. If this field is set to `true`, we skip
    // generating answers for non-answer seeking queries and return
    // fallback messages instead.
    bool ignore_non_answer_seeking_query = 6;

    // Specifies whether to filter out queries that have low relevance.
    //
    // If this field is set to `false`, all search results are used regardless
    // of relevance to generate answers. If set to `true` or unset, the behavior
    // will be determined automatically by the service.
    optional bool ignore_low_relevant_content = 7;

    // 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 = 8
        [(google.api.field_behavior) = OPTIONAL];
  }

  // Search specification.
  message SearchSpec {
    // Search parameters.
    message SearchParams {
      // Number of search results to return.
      // The default value is 10.
      int32 max_return_results = 1;

      // 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. This will be used to filter
      // search results which may affect the Answer response.
      //
      // 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 customers 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 = 2;

      // Boost specification to boost certain documents in search results which
      // may affect the answer query response. For more information on boosting,
      // see [Boosting](https://cloud.google.com/retail/docs/boosting#boost)
      SearchRequest.BoostSpec boost_spec = 3;

      // The order in which documents are returned. Documents can be ordered
      // by a field in an
      // [Document][google.cloud.discoveryengine.v1beta.Document] object. Leave
      // it unset if ordered by relevance. `order_by` expression is
      // case-sensitive. For more information on ordering, see
      // [Ordering](https://cloud.google.com/retail/docs/filter-and-order#order)
      //
      // If this field is unrecognizable, an `INVALID_ARGUMENT` is returned.
      string order_by = 4;

      // Specifies the search result mode. If unspecified, the
      // search result mode defaults to `DOCUMENTS`.
      // See [parse and chunk
      // documents](https://cloud.google.com/generative-ai-app-builder/docs/parse-chunk-documents)
      SearchRequest.ContentSearchSpec.SearchResultMode search_result_mode = 5;

      // Specs defining dataStores to filter on in a search call and
      // configurations for those dataStores. This is only considered for
      // engines with multiple dataStores use case. For single dataStore within
      // an engine, they should use the specs at the top level.
      repeated SearchRequest.DataStoreSpec data_store_specs = 7;

      // Optional. Specification to enable natural language understanding
      // capabilities for search requests.
      SearchRequest.NaturalLanguageQueryUnderstandingSpec
          natural_language_query_understanding_spec = 8
          [(google.api.field_behavior) = OPTIONAL];
    }

    // Search result list.
    message SearchResultList {
      // Search result.
      message SearchResult {
        // Unstructured document information.
        message UnstructuredDocumentInfo {
          // Document context.
          message DocumentContext {
            // Page identifier.
            string page_identifier = 1;

            // Document content to be used for answer generation.
            string content = 2;
          }

          // Extractive segment.
          // [Guide](https://cloud.google.com/generative-ai-app-builder/docs/snippets#extractive-segments)
          // Answer generation will only use it if document_contexts is empty.
          // This is supposed to be shorter snippets.
          message ExtractiveSegment {
            // Page identifier.
            string page_identifier = 1;

            // Extractive segment content.
            string content = 2;
          }

          // Extractive answer.
          // [Guide](https://cloud.google.com/generative-ai-app-builder/docs/snippets#get-answers)
          message ExtractiveAnswer {
            // Page identifier.
            string page_identifier = 1;

            // Extractive answer content.
            string content = 2;
          }

          // Document resource name.
          string document = 1 [(google.api.resource_reference) = {
            type: "discoveryengine.googleapis.com/Document"
          }];

          // URI for the document.
          string uri = 2;

          // Title.
          string title = 3;

          // List of document contexts. The content will be used for Answer
          // Generation. This is supposed to be the main content of the document
          // that can be long and comprehensive.
          repeated DocumentContext document_contexts = 4;

          // List of extractive segments.
          repeated ExtractiveSegment extractive_segments = 5;

          // Deprecated: This field is deprecated and will have no effect on
          // the Answer generation.
          // Please use document_contexts and extractive_segments fields.
          // List of extractive answers.
          repeated ExtractiveAnswer extractive_answers = 6 [deprecated = true];
        }

        // Chunk information.
        message ChunkInfo {
          // Document metadata contains the information of the document of the
          // current chunk.
          message DocumentMetadata {
            // Uri of the document.
            string uri = 1;

            // Title of the document.
            string title = 2;
          }

          // Chunk resource name.
          string chunk = 1 [(google.api.resource_reference) = {
            type: "discoveryengine.googleapis.com/Chunk"
          }];

          // Chunk textual content.
          string content = 2;

          // Metadata of the document from the current chunk.
          DocumentMetadata document_metadata = 4;
        }

        // Search result content.
        oneof content {
          // Unstructured document information.
          UnstructuredDocumentInfo unstructured_document_info = 1;

          // Chunk information.
          ChunkInfo chunk_info = 2;
        }
      }

      // Search results.
      repeated SearchResult search_results = 1;
    }

    // Search parameters to control the search behavior.
    // Or provide search result list to generate answer.
    oneof input {
      // Search parameters.
      SearchParams search_params = 1;

      // Search result list.
      SearchResultList search_result_list = 2;
    }
  }

  // Query understanding specification.
  message QueryUnderstandingSpec {
    // Query classification specification.
    message QueryClassificationSpec {
      // Query classification types.
      enum Type {
        // Unspecified query classification type.
        TYPE_UNSPECIFIED = 0;

        // Adversarial query classification type.
        ADVERSARIAL_QUERY = 1;

        // Non-answer-seeking query classification type, for chit chat.
        NON_ANSWER_SEEKING_QUERY = 2;

        // Jail-breaking query classification type.
        JAIL_BREAKING_QUERY = 3;

        // Non-answer-seeking query classification type, for no clear intent.
        NON_ANSWER_SEEKING_QUERY_V2 = 4;
      }

      // Enabled query classification types.
      repeated Type types = 1;
    }

    // Query rephraser specification.
    message QueryRephraserSpec {
      // Disable query rephraser.
      bool disable = 1;

      // Max rephrase steps.
      // The max number is 5 steps.
      // If not set or set to < 1, it will be set to 1 by default.
      int32 max_rephrase_steps = 2;
    }

    // Query classification specification.
    QueryClassificationSpec query_classification_spec = 1;

    // Query rephraser specification.
    QueryRephraserSpec query_rephraser_spec = 2;
  }

  // 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/*/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"
    }
  ];

  // Required. Current user query.
  Query query = 2 [(google.api.field_behavior) = REQUIRED];

  // The session resource name. Not required.
  //
  // When session field is not set, the API is in sessionless mode.
  //
  // We support auto session mode: users can use the wildcard symbol `-` as
  // session ID.  A new ID will be automatically generated and assigned.
  string session = 3 [(google.api.resource_reference) = {
    type: "discoveryengine.googleapis.com/Session"
  }];

  // Model specification.
  SafetySpec safety_spec = 4;

  // Related questions specification.
  RelatedQuestionsSpec related_questions_spec = 5;

  // Optional. Grounding specification.
  GroundingSpec grounding_spec = 6 [(google.api.field_behavior) = OPTIONAL];

  // Answer generation specification.
  AnswerGenerationSpec answer_generation_spec = 7;

  // Search specification.
  SearchSpec search_spec = 8;

  // Query understanding specification.
  QueryUnderstandingSpec query_understanding_spec = 9;

  // Deprecated: This field is deprecated. Streaming Answer API will be
  // supported.
  //
  // Asynchronous mode control.
  //
  // If enabled, the response will be returned with answer/session resource
  // name without final answer. The API users need to do the polling to get
  // the latest status of answer/session by calling
  // [ConversationalSearchService.GetAnswer][google.cloud.discoveryengine.v1beta.ConversationalSearchService.GetAnswer]
  // or
  // [ConversationalSearchService.GetSession][google.cloud.discoveryengine.v1beta.ConversationalSearchService.GetSession]
  // method.
  bool asynchronous_mode = 10 [deprecated = true];

  // 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`.
  //
  // 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 = 12;

  // 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 = 13;
}

// Response message for
// [ConversationalSearchService.AnswerQuery][google.cloud.discoveryengine.v1beta.ConversationalSearchService.AnswerQuery]
// method.
message AnswerQueryResponse {
  // Answer resource object.
  // If
  // [AnswerQueryRequest.QueryUnderstandingSpec.QueryRephraserSpec.max_rephrase_steps][google.cloud.discoveryengine.v1beta.AnswerQueryRequest.QueryUnderstandingSpec.QueryRephraserSpec.max_rephrase_steps]
  // is greater than 1, use
  // [Answer.name][google.cloud.discoveryengine.v1beta.Answer.name] to fetch
  // answer information using
  // [ConversationalSearchService.GetAnswer][google.cloud.discoveryengine.v1beta.ConversationalSearchService.GetAnswer]
  // API.
  Answer answer = 1;

  // Session resource object.
  // It will be only available when session field is set and valid in the
  // [AnswerQueryRequest][google.cloud.discoveryengine.v1beta.AnswerQueryRequest]
  // request.
  Session session = 2;

  // A global unique ID used for logging.
  string answer_query_token = 3;
}

// Request for GetAnswer method.
message GetAnswerRequest {
  // Required. The resource name of the Answer to get. Format:
  // `projects/{project}/locations/{location}/collections/{collection}/engines/{engine_id}/sessions/{session_id}/answers/{answer_id}`
  string name = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "discoveryengine.googleapis.com/Answer"
    }
  ];
}

// Request for CreateSession method.
message CreateSessionRequest {
  // Required. Full resource name of parent data store. Format:
  // `projects/{project}/locations/{location}/collections/{collection}/dataStores/{data_store_id}`
  string parent = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "discoveryengine.googleapis.com/DataStore"
    }
  ];

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

// Request for UpdateSession method.
message UpdateSessionRequest {
  // Required. The Session to update.
  Session session = 1 [(google.api.field_behavior) = REQUIRED];

  // Indicates which fields in the provided
  // [Session][google.cloud.discoveryengine.v1beta.Session] to update. The
  // following are NOT supported:
  //
  // * [Session.name][google.cloud.discoveryengine.v1beta.Session.name]
  //
  // If not set or empty, all supported fields are updated.
  google.protobuf.FieldMask update_mask = 2;
}

// Request for DeleteSession method.
message DeleteSessionRequest {
  // Required. The resource name of the Session to delete. Format:
  // `projects/{project}/locations/{location}/collections/{collection}/dataStores/{data_store_id}/sessions/{session_id}`
  string name = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "discoveryengine.googleapis.com/Session"
    }
  ];
}

// Request for GetSession method.
message GetSessionRequest {
  // Required. The resource name of the Session to get. Format:
  // `projects/{project}/locations/{location}/collections/{collection}/dataStores/{data_store_id}/sessions/{session_id}`
  string name = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "discoveryengine.googleapis.com/Session"
    }
  ];

  // Optional. If set to true, the full session including all answer details
  // will be returned.
  bool include_answer_details = 2 [(google.api.field_behavior) = OPTIONAL];
}

// Request for ListSessions method.
message ListSessionsRequest {
  // Required. The data store resource name. Format:
  // `projects/{project}/locations/{location}/collections/{collection}/dataStores/{data_store_id}`
  string parent = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "discoveryengine.googleapis.com/DataStore"
    }
  ];

  // Maximum number of results to return. If unspecified, defaults
  // to 50. Max allowed value is 1000.
  int32 page_size = 2;

  // A page token, received from a previous `ListSessions` call.
  // Provide this to retrieve the subsequent page.
  string page_token = 3;

  // A comma-separated list of fields to filter by, in EBNF grammar.
  // The supported fields are:
  // * `user_pseudo_id`
  // * `state`
  // * `display_name`
  // * `starred`
  // * `is_pinned`
  // * `labels`
  // * `create_time`
  // * `update_time`
  //
  // Examples:
  // "user_pseudo_id = some_id"
  // "display_name = \"some_name\""
  // "starred = true"
  // "is_pinned=true AND (NOT labels:hidden)"
  // "create_time > \"1970-01-01T12:00:00Z\""
  string filter = 4;

  // A comma-separated list of fields to order by, sorted in ascending order.
  // Use "desc" after a field name for descending.
  // Supported fields:
  //
  //   * `update_time`
  //   * `create_time`
  //   * `session_name`
  //   * `is_pinned`
  //
  // Example:
  //
  // * "update_time desc"
  // * "create_time"
  // * "is_pinned desc,update_time desc": list sessions by is_pinned first, then
  //    by update_time.
  string order_by = 5;
}

// Response for ListSessions method.
message ListSessionsResponse {
  // All the Sessions for a given data store.
  repeated Session sessions = 1;

  // Pagination token, if not returned indicates the last page.
  string next_page_token = 2;
}
