// Copyright 2025 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

syntax = "proto3";

package google.cloud.discoveryengine.v1alpha;

import "google/api/field_behavior.proto";
import "google/api/resource.proto";
import "google/protobuf/struct.proto";
import "google/protobuf/timestamp.proto";

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

// 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).
    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 {
    // ID of the citation source.
    string reference_id = 1;
  }

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

    // 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.
        NON_ANSWER_SEEKING_QUERY = 2;

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

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

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

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

  // Citations.
  repeated Citation citations = 4;

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