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

import "google/api/field_behavior.proto";
import "google/api/resource.proto";
import "google/cloud/discoveryengine/v1/safety.proto";
import "google/protobuf/struct.proto";
import "google/protobuf/timestamp.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 = "AnswerProto";
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";

// Defines an answer.
message Answer {
  option (google.api.resource) = {
    type: "discoveryengine.googleapis.com/Answer"
    pattern: "projects/{project}/locations/{location}/dataStores/{data_store}/sessions/{session}/answers/{answer}"
    pattern: "projects/{project}/locations/{location}/collections/{collection}/dataStores/{data_store}/sessions/{session}/answers/{answer}"
    pattern: "projects/{project}/locations/{location}/collections/{collection}/engines/{engine}/sessions/{session}/answers/{answer}"
  };

  // Citation info for a segment.
  message Citation {
    // Index indicates the start of the segment, measured in bytes (UTF-8
    // unicode). If there are multi-byte characters,such as non-ASCII
    // characters, the index measurement is longer than the string length.
    int64 start_index = 1;

    // End of the attributed segment, exclusive. Measured in bytes (UTF-8
    // unicode). If there are multi-byte characters,such as non-ASCII
    // characters, the index measurement is longer than the string length.
    int64 end_index = 2;

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

  // Citation source.
  message CitationSource {
    // ID of the citation source.
    string reference_id = 1;
  }

  // Grounding support for a claim in `answer_text`.
  message GroundingSupport {
    // Required. Index indicates the start of the claim, measured in bytes
    // (UTF-8 unicode).
    int64 start_index = 1 [(google.api.field_behavior) = REQUIRED];

    // Required. End of the claim, exclusive.
    int64 end_index = 2 [(google.api.field_behavior) = REQUIRED];

    // A score in the range of [0, 1] describing how grounded is a specific
    // claim by the references.
    // Higher value means that the claim is better supported by the reference
    // chunks.
    optional double grounding_score = 3;

    // Indicates that this claim required grounding check. When the
    // system decided this claim didn't require attribution/grounding check,
    // this field is set to false. In that case, no grounding check was
    // done for the claim and therefore `grounding_score`, `sources` is not
    // returned.
    optional bool grounding_check_required = 4;

    // Optional. Citation sources for the claim.
    repeated CitationSource sources = 5
        [(google.api.field_behavior) = OPTIONAL];
  }

  // Reference.
  message Reference {
    // Unstructured document information.
    message UnstructuredDocumentInfo {
      // Chunk content.
      message ChunkContent {
        // Chunk textual content.
        string content = 1;

        // Page identifier.
        string page_identifier = 2;

        // The relevance of the chunk for a given query. Values range from 0.0
        // (completely irrelevant) to 1.0 (completely relevant).
        // This value is for informational purpose only. It may change for
        // the same query and chunk at any time due to a model retraining or
        // change in implementation.
        optional float relevance_score = 3;
      }

      // 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 cited chunk contents derived from document content.
      repeated ChunkContent chunk_contents = 4;

      // The structured JSON metadata for the document.
      // It is populated from the struct data from the Chunk in search result.
      google.protobuf.Struct struct_data = 5;
    }

    // Chunk information.
    message ChunkInfo {
      // Document metadata.
      message DocumentMetadata {
        // 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;

        // Page identifier.
        string page_identifier = 4;

        // The structured JSON metadata for the document.
        // It is populated from the struct data from the Chunk in search result.
        google.protobuf.Struct struct_data = 5;
      }

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

      // Chunk textual content.
      string content = 2;

      // The relevance of the chunk for a given query. Values range from 0.0
      // (completely irrelevant) to 1.0 (completely relevant).
      // This value is for informational purpose only. It may change for
      // the same query and chunk at any time due to a model retraining or
      // change in implementation.
      optional float relevance_score = 3;

      // Document metadata.
      DocumentMetadata document_metadata = 4;
    }

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

      // Structured search data.
      google.protobuf.Struct struct_data = 2;

      // Output only. The title of the document.
      string title = 3 [(google.api.field_behavior) = OUTPUT_ONLY];

      // Output only. The URI of the document.
      string uri = 4 [(google.api.field_behavior) = OUTPUT_ONLY];
    }

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

      // Chunk information.
      ChunkInfo chunk_info = 2;

      // Structured document information.
      StructuredDocumentInfo structured_document_info = 3;
    }
  }

  // Step information.
  message Step {
    // Action.
    message Action {
      // Search action.
      message SearchAction {
        // The query to search.
        string query = 1;
      }

      // Observation.
      message Observation {
        message SearchResult {
          // Snippet information.
          message SnippetInfo {
            // Snippet content.
            string snippet = 1;

            // Status of the snippet defined by the search team.
            string snippet_status = 2;
          }

          // Chunk information.
          message ChunkInfo {
            // Chunk resource name.
            string chunk = 1;

            // Chunk textual content.
            string content = 2;

            // The relevance of the chunk for a given query. Values range from
            // 0.0 (completely irrelevant) to 1.0 (completely relevant).
            // This value is for informational purpose only. It may change for
            // the same query and chunk at any time due to a model retraining or
            // change in implementation.
            optional float relevance_score = 3;
          }

          // Document resource name.
          string document = 1;

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

          // Title.
          string title = 3;

          // If citation_type is DOCUMENT_LEVEL_CITATION, populate document
          // level snippets.
          repeated SnippetInfo snippet_info = 4;

          // If citation_type is CHUNK_LEVEL_CITATION and chunk mode is on,
          // populate chunk info.
          repeated ChunkInfo chunk_info = 5;

          // Data representation.
          // The structured JSON data for the document.
          // It's populated from the struct data from the Document, or the
          // Chunk in search result.
          google.protobuf.Struct struct_data = 6;
        }

        // Search results observed by the search action, it can be snippets info
        // or chunk info, depending on the citation type set by the user.
        repeated SearchResult search_results = 2;
      }

      // The action.
      oneof action {
        // Search action.
        SearchAction search_action = 2;
      }

      // Observation.
      Observation observation = 3;
    }

    // Enumeration of the state of the step.
    enum State {
      // Unknown.
      STATE_UNSPECIFIED = 0;

      // Step is currently in progress.
      IN_PROGRESS = 1;

      // Step currently failed.
      FAILED = 2;

      // Step has succeeded.
      SUCCEEDED = 3;
    }

    // The state of the step.
    State state = 1;

    // The description of the step.
    string description = 2;

    // The thought of the step.
    string thought = 3;

    // Actions.
    repeated Action actions = 4;
  }

  // Query understanding information.
  message QueryUnderstandingInfo {
    // Query classification information.
    message QueryClassificationInfo {
      // 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;

        // User defined query classification type.
        USER_DEFINED_CLASSIFICATION_QUERY = 5;
      }

      // Query classification type.
      Type type = 1;

      // Classification output.
      bool positive = 2;
    }

    // Query classification information.
    repeated QueryClassificationInfo query_classification_info = 1;
  }

  // Enumeration of the state of the answer generation.
  enum State {
    // Unknown.
    STATE_UNSPECIFIED = 0;

    // Answer generation is currently in progress.
    IN_PROGRESS = 1;

    // Answer generation currently failed.
    FAILED = 2;

    // Answer generation has succeeded.
    SUCCEEDED = 3;

    // Answer generation is currently in progress.
    STREAMING = 4;
  }

  // An enum for answer skipped reasons.
  enum AnswerSkippedReason {
    // Default value. The answer skipped reason is not specified.
    ANSWER_SKIPPED_REASON_UNSPECIFIED = 0;

    // The adversarial query ignored case.
    ADVERSARIAL_QUERY_IGNORED = 1;

    // The non-answer seeking query ignored case
    //
    // Google skips the answer if the query is chit chat.
    NON_ANSWER_SEEKING_QUERY_IGNORED = 2;

    // The out-of-domain query ignored case.
    //
    // Google skips the answer if there are no high-relevance search results.
    OUT_OF_DOMAIN_QUERY_IGNORED = 3;

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

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

    // The jail-breaking query ignored case.
    //
    // For example, "Reply in the tone of a competing company's CEO".
    // Google skips the answer if the query is classified as a jail-breaking
    // query.
    JAIL_BREAKING_QUERY_IGNORED = 6;

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

    // The non-answer seeking query ignored case.
    //
    // Google skips the answer if the query doesn't have clear intent.
    NON_ANSWER_SEEKING_QUERY_IGNORED_V2 = 8;

    // The low-grounded answer case.
    //
    // Google skips the answer if a well grounded answer was unable to be
    // generated.
    LOW_GROUNDED_ANSWER = 9;

    // The user defined query classification ignored case.
    //
    // Google skips the answer if the query is classified as a user defined
    // query classification.
    USER_DEFINED_CLASSIFICATION_QUERY_IGNORED = 10;

    // The unhelpful answer case.
    //
    // Google skips the answer if the answer is not helpful. This can be due to
    // a variety of factors, including but not limited to: the query is not
    // answerable, the answer is not relevant to the query, or the answer is
    // not well-formatted.
    UNHELPFUL_ANSWER = 11;
  }

  // Immutable. Fully qualified name
  // `projects/{project}/locations/global/collections/{collection}/engines/{engine}/sessions/*/answers/*`
  string name = 1 [(google.api.field_behavior) = IMMUTABLE];

  // The state of the answer generation.
  State state = 2;

  // The textual answer.
  string answer_text = 3;

  // A score in the range of [0, 1] describing how grounded the answer is by the
  // reference chunks.
  optional double grounding_score = 12;

  // Citations.
  repeated Citation citations = 4;

  // Optional. Grounding supports.
  repeated GroundingSupport grounding_supports = 13
      [(google.api.field_behavior) = OPTIONAL];

  // References.
  repeated Reference references = 5;

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

  // Answer generation steps.
  repeated Step steps = 7;

  // Query understanding information.
  QueryUnderstandingInfo query_understanding_info = 10;

  // Additional answer-skipped reasons. This provides the reason for ignored
  // cases. If nothing is skipped, this field is not set.
  repeated AnswerSkippedReason answer_skipped_reasons = 11;

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

  // Output only. Answer completed timestamp.
  google.protobuf.Timestamp complete_time = 9
      [(google.api.field_behavior) = OUTPUT_ONLY];

  // Optional. Safety ratings.
  repeated SafetyRating safety_ratings = 14
      [(google.api.field_behavior) = OPTIONAL];
}
