// 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/annotations.proto";
import "google/api/client.proto";
import "google/api/field_behavior.proto";
import "google/api/resource.proto";
import "google/cloud/discoveryengine/v1/grounding.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 = "GroundedGenerationServiceProto";
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 grounded generation.
service GroundedGenerationService {
  option (google.api.default_host) = "discoveryengine.googleapis.com";
  option (google.api.oauth_scopes) =
      "https://www.googleapis.com/auth/cloud-platform";

  // Generates grounded content in a streaming fashion.
  rpc StreamGenerateGroundedContent(stream GenerateGroundedContentRequest)
      returns (stream GenerateGroundedContentResponse) {
    option (google.api.http) = {
      post: "/v1/{location=projects/*/locations/*}:streamGenerateGroundedContent"
      body: "*"
    };
  }

  // Generates grounded content.
  rpc GenerateGroundedContent(GenerateGroundedContentRequest)
      returns (GenerateGroundedContentResponse) {
    option (google.api.http) = {
      post: "/v1/{location=projects/*/locations/*}:generateGroundedContent"
      body: "*"
    };
  }

  // Performs a grounding check.
  rpc CheckGrounding(CheckGroundingRequest) returns (CheckGroundingResponse) {
    option (google.api.http) = {
      post: "/v1/{grounding_config=projects/*/locations/*/groundingConfigs/*}:check"
      body: "*"
    };
  }
}

// Base structured datatype containing multi-part content of a message.
message GroundedGenerationContent {
  // Single part of content.
  message Part {
    // Holder of data. It only supports text for now.
    oneof data {
      // Inline text.
      string text = 1;
    }
  }

  // Producer of the content. Must be either `user` or `model`.
  //
  // Intended to be used for multi-turn conversations. Otherwise, it can be left
  // unset.
  string role = 1;

  // Ordered `Parts` that constitute a single message.
  repeated Part parts = 2;
}

// Top-level message sent by the client for the `GenerateGroundedContent`
// method.
message GenerateGroundedContentRequest {
  // Content generation specification.
  message GenerationSpec {
    // Specifies which Vertex model id to use for generation.
    string model_id = 3;

    // Language code for content. Use language tags defined by
    // [BCP47](https://www.rfc-editor.org/rfc/bcp/bcp47.txt).
    string language_code = 2;

    // If specified, custom value for the temperature will be used.
    optional float temperature = 4;

    // If specified, custom value for nucleus sampling will be used.
    optional float top_p = 5;

    // If specified, custom value for top-k sampling will be used.
    optional int32 top_k = 7;

    // If specified, custom value for frequency penalty will be used.
    optional float frequency_penalty = 8;

    // If specified, custom value for the seed will be used.
    optional int32 seed = 12;

    // If specified, custom value for presence penalty will be used.
    optional float presence_penalty = 9;

    // If specified, custom value for max output tokens will be used.
    optional int32 max_output_tokens = 10;
  }

  // Describes the options to customize dynamic retrieval.
  message DynamicRetrievalConfiguration {
    // Describes the predictor settings for dynamic retrieval.
    message DynamicRetrievalPredictor {
      // The version of the predictor to be used in dynamic retrieval.
      enum Version {
        // Automatically choose the best version of the retrieval predictor.
        VERSION_UNSPECIFIED = 0;

        // The V1 model which is evaluating each source independently.
        V1_INDEPENDENT = 1;
      }

      // The version of the predictor to be used in dynamic retrieval.
      Version version = 1;

      // The value of the threshold. If the predictor will predict a
      // value smaller than this, it would suppress grounding in the source.
      optional float threshold = 2;
    }

    // Specification for the predictor for dynamic retrieval.
    DynamicRetrievalPredictor predictor = 1;
  }

  // Grounding source.
  message GroundingSource {
    // Message to be used for grounding based on inline content.
    message InlineSource {
      // List of facts to be used for grounding.
      repeated GroundingFact grounding_facts = 1;

      // Attributes associated with the content.
      //
      // Common attributes include `source` (indicating where the content was
      // sourced from) and `author` (indicating the author of the content).
      map<string, string> attributes = 2;
    }

    // Message to be used for grounding with Vertex AI Search.
    message SearchSource {
      // The resource name of the Engine to use.
      //
      // Format:
      // `projects/{project}/locations/{location}/collections/{collection_id}/engines/{engine_id}/servingConfigs/{serving_config_id}`
      string serving_config = 1 [(google.api.resource_reference) = {
        type: "discoveryengine.googleapis.com/ServingConfig"
      }];

      // Number of search results to return.
      //
      // The default value is 10. The maximumm allowed value is 10.
      int32 max_result_count = 2;

      // Filter expression to be applied to the search.
      //
      // The syntax is the same as
      // [SearchRequest.filter][google.cloud.discoveryengine.v1.SearchRequest.filter].
      string filter = 3;

      // If set, safe search is enabled in Vertex AI Search requests.
      bool safe_search = 5;
    }

    // Google Search config parameters.
    message GoogleSearchSource {
      // Optional. Specifies the dynamic retrieval configuration for the given
      // source.
      DynamicRetrievalConfiguration dynamic_retrieval_config = 2
          [(google.api.field_behavior) = OPTIONAL];
    }

    // Params for using enterprise web retrieval as grounding source.
    message EnterpriseWebRetrievalSource {}

    // Sources.
    oneof source {
      // If set, grounding is performed with inline content.
      InlineSource inline_source = 1;

      // If set, grounding is performed with Vertex AI Search.
      SearchSource search_source = 2;

      // If set, grounding is performed with Google Search.
      GoogleSearchSource google_search_source = 3;

      // If set, grounding is performed with enterprise web retrieval.
      EnterpriseWebRetrievalSource enterprise_web_retrieval_source = 8;
    }
  }

  // Grounding specification.
  message GroundingSpec {
    // Grounding sources.
    repeated GroundingSource grounding_sources = 1;
  }

  // Required. Location resource.
  //
  // Format: `projects/{project}/locations/{location}`.
  string location = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "discoveryengine.googleapis.com/Location"
    }
  ];

  // Content of the system instruction for the current API.
  //
  // These instructions will take priority over any other prompt instructions
  // if the selected model is supporting them.
  GroundedGenerationContent system_instruction = 5;

  // Content of the current conversation with the model.
  //
  // For single-turn queries, this is a single instance. For multi-turn queries,
  // this is a repeated field that contains conversation history + latest
  // request.
  repeated GroundedGenerationContent contents = 2;

  // Content generation specification.
  GenerationSpec generation_spec = 3;

  // Grounding specification.
  GroundingSpec grounding_spec = 4;

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

// Response for the `GenerateGroundedContent` method.
message GenerateGroundedContentResponse {
  // A response candidate generated from the model.
  message Candidate {
    // Citation for the generated content.
    message GroundingMetadata {
      // Describes the metadata associated with a retrieval step.
      message RetrievalMetadata {
        // Describes the source to which the metadata is associated to.
        enum Source {
          // Unspecified source.
          SOURCE_UNSPECIFIED = 0;

          // Vertex AI search.
          VERTEX_AI_SEARCH = 1;

          // Google Search.
          GOOGLE_SEARCH = 3;

          // User inline provided content.
          INLINE_CONTENT = 2;

          // Google Maps.
          GOOGLE_MAPS = 4;
        }

        // Describes the source to which the metadata is referring to.
        Source source = 1;

        // Metadata for dynamic retrieval.
        DynamicRetrievalMetadata dynamic_retrieval_metadata = 2;
      }

      // Describes the metadata about dynamic retrieval.
      message DynamicRetrievalMetadata {
        // Metadata for the dynamic retrieval predictor.
        DynamicRetrievalPredictorMetadata predictor_metadata = 1;
      }

      // Describes the metadata about the dynamic retrieval predictor.
      message DynamicRetrievalPredictorMetadata {
        // The version of the predictor which was used in dynamic retrieval.
        enum Version {
          // Unspecified version, should never be used.
          VERSION_UNSPECIFIED = 0;

          // The V1 model which is evaluating each source independently.
          V1_INDEPENDENT = 1;
        }

        // The version of the predictor which was used in dynamic retrieval.
        Version version = 1;

        // The value of the predictor. This should be between [0, 1] where
        // a value of 0 means that the query would not benefit from grounding,
        // while a value of 1.0 means that the query would benefit the most.
        // In between values allow to differentiate between different usefulness
        // scores for grounding.
        optional float prediction = 2;
      }

      // Google search entry point.
      message SearchEntryPoint {
        // Web content snippet that can be embedded in a web page or an app
        // webview.
        string rendered_content = 1;

        // Base64 encoded JSON representing array of <search term, search url>
        // tuple.
        bytes sdk_blob = 2;
      }

      // Grounding info for a claim in the candidate and its support.
      message GroundingSupport {
        // Text for the claim in the candidate. Always provided when a
        // support is found.
        string claim_text = 1;

        // A list of indices (into 'support_chunks') specifying the
        // citations associated with the claim. For instance [1,3,4] means
        // that support_chunks[1], support_chunks[3],
        // support_chunks[4] are the chunks attributed to the claim.
        repeated int32 support_chunk_indices = 3;

        // A score in the range of [0, 1] describing how grounded is a specific
        // claim in the support chunks indicated.
        // Higher value means that the claim is better supported by the chunks.
        optional float support_score = 2;
      }

      // Metadata about an image from the web search.
      message ImageMetadata {
        // Metadata about the website that the image is from.
        message WebsiteInfo {
          // The url of the website.
          string uri = 1;

          // The title of the website.
          string title = 2;
        }

        // Metadata about the image.
        message Image {
          // The url of the image.
          string uri = 1;

          // The width of the image in pixels.
          int32 width = 2;

          // The height of the image in pixels.
          int32 height = 3;
        }

        // Metadata about the full size image.
        Image image = 1;

        // Metadata about the thumbnail.
        Image thumbnail = 2;

        // The details about the website that the image is from.
        WebsiteInfo source = 3;
      }

      // Retrieval metadata to provide an understanding in the
      // retrieval steps performed by the model. There can be multiple such
      // messages which can correspond to different parts of the retrieval. This
      // is a mechanism used to ensure transparency to our users.
      repeated RetrievalMetadata retrieval_metadata = 5;

      // List of chunks to be attributed across all claims in the candidate.
      // These are derived from the grounding sources supplied in the request.
      repeated FactChunk support_chunks = 1;

      // Web search queries for the following-up web search.
      repeated string web_search_queries = 3;

      // Google search entry for the following-up web searches.
      SearchEntryPoint search_entry_point = 4;

      // GroundingSupport across all claims in the answer candidate.
      // An support to a fact indicates that the claim is supported by
      // the fact.
      repeated GroundingSupport grounding_support = 2;

      // Images from the web search.
      repeated ImageMetadata images = 9;
    }

    // Index of the candidate.
    int32 index = 1;

    // Content of the candidate.
    GroundedGenerationContent content = 2;

    // The overall grounding score for the candidate, in the range of [0, 1].
    optional float grounding_score = 3;

    // Grounding metadata for the generated content.
    GroundingMetadata grounding_metadata = 4;
  }

  // Generated candidates.
  repeated Candidate candidates = 1;
}

// Specification for the grounding check.
message CheckGroundingSpec {
  // The threshold (in [0,1]) used for determining whether a fact must be
  // cited for a claim in the answer candidate. Choosing a higher threshold
  // will lead to fewer but very strong citations, while choosing a lower
  // threshold may lead to more but somewhat weaker citations. If unset, the
  // threshold will default to 0.6.
  optional double citation_threshold = 1;
}

// Request message for
// [GroundedGenerationService.CheckGrounding][google.cloud.discoveryengine.v1.GroundedGenerationService.CheckGrounding]
// method.
message CheckGroundingRequest {
  // Required. The resource name of the grounding config, such as
  // `projects/*/locations/global/groundingConfigs/default_grounding_config`.
  string grounding_config = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "discoveryengine.googleapis.com/GroundingConfig"
    }
  ];

  // Answer candidate to check. It can have a maximum length of 4096 tokens.
  string answer_candidate = 2;

  // List of facts for the grounding check.
  // We support up to 200 facts.
  repeated GroundingFact facts = 3;

  // Configuration of the grounding check.
  CheckGroundingSpec grounding_spec = 4;

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

// Response message for the
// [GroundedGenerationService.CheckGrounding][google.cloud.discoveryengine.v1.GroundedGenerationService.CheckGrounding]
// method.
message CheckGroundingResponse {
  // Fact chunk for grounding check.
  message CheckGroundingFactChunk {
    // Text content of the fact chunk. Can be at most 10K characters long.
    string chunk_text = 1;
  }

  // Text and citation info for a claim in the answer candidate.
  message Claim {
    // Position indicating the start of the claim in the answer candidate,
    // measured in bytes. Note that this is not measured in characters and,
    // therefore, must be rendered in the user interface keeping in mind that
    // some characters may take more than one byte. For example,
    // if the claim text contains non-ASCII characters, the start and end
    // positions vary when measured in characters
    // (programming-language-dependent) and when measured in bytes
    // (programming-language-independent).
    optional int32 start_pos = 1;

    // Position indicating the end of the claim in the answer candidate,
    // exclusive, in bytes. Note that this is not measured in characters and,
    // therefore, must be rendered as such. For example, if the claim text
    // contains non-ASCII characters, the start and end positions vary when
    // measured in characters (programming-language-dependent) and when measured
    // in bytes (programming-language-independent).
    optional int32 end_pos = 2;

    // Text for the claim in the answer candidate. Always provided regardless of
    // whether citations or anti-citations are found.
    string claim_text = 3;

    // A list of indices (into 'cited_chunks') specifying the citations
    // associated with the claim. For instance [1,3,4] means that
    // cited_chunks[1], cited_chunks[3], cited_chunks[4] are the facts cited
    // supporting for the claim. A citation to a fact indicates that the claim
    // is supported by the fact.
    repeated int32 citation_indices = 4;

    // Indicates that this claim required grounding check. When the system
    // decided this claim doesn't require attribution/grounding check, this
    // field will be set to false. In that case, no grounding check was done for
    // the claim and therefore
    // [citation_indices][google.cloud.discoveryengine.v1.CheckGroundingResponse.Claim.citation_indices]
    // should not be returned.
    optional bool grounding_check_required = 6;
  }

  // The support score for the input answer candidate.
  // Higher the score, higher is the fraction of claims that are supported by
  // the provided facts. This is always set when a response is returned.
  optional float support_score = 1;

  // List of facts cited across all claims in the answer candidate.
  // These are derived from the facts supplied in the request.
  repeated FactChunk cited_chunks = 3;

  // List of facts cited across all claims in the answer candidate.
  // These are derived from the facts supplied in the request.
  repeated CheckGroundingFactChunk cited_facts = 6;

  // Claim texts and citation info across all claims in the answer candidate.
  repeated Claim claims = 4;
}
