syntax = "proto3";

import "points.proto";
import "qdrant_common.proto";

package qdrant;
option csharp_namespace = "Qdrant.Client.Grpc";

service PointsInternal {
  rpc Upsert(UpsertPointsInternal) returns (PointsOperationResponseInternal) {}
  rpc Sync(SyncPointsInternal) returns (PointsOperationResponseInternal) {}
  rpc Delete(DeletePointsInternal) returns (PointsOperationResponseInternal) {}
  rpc UpdateVectors(UpdateVectorsInternal)
      returns (PointsOperationResponseInternal) {}
  rpc DeleteVectors(DeleteVectorsInternal)
      returns (PointsOperationResponseInternal) {}
  rpc SetPayload(SetPayloadPointsInternal)
      returns (PointsOperationResponseInternal) {}
  rpc OverwritePayload(SetPayloadPointsInternal)
      returns (PointsOperationResponseInternal) {}
  rpc DeletePayload(DeletePayloadPointsInternal)
      returns (PointsOperationResponseInternal) {}
  rpc ClearPayload(ClearPayloadPointsInternal)
      returns (PointsOperationResponseInternal) {}
  rpc CreateFieldIndex(CreateFieldIndexCollectionInternal)
      returns (PointsOperationResponseInternal) {}
  rpc DeleteFieldIndex(DeleteFieldIndexCollectionInternal)
      returns (PointsOperationResponseInternal) {}
  rpc UpdateBatch(UpdateBatchInternal)
      returns (PointsOperationResponseInternal) {}
  rpc CoreSearchBatch(CoreSearchBatchPointsInternal)
      returns (SearchBatchResponse) {}
  rpc Scroll(ScrollPointsInternal) returns (ScrollResponse) {}
  rpc Count(CountPointsInternal) returns (CountResponse) {}
  rpc Recommend(RecommendPointsInternal) returns (RecommendResponse) {}
  rpc Get(GetPointsInternal) returns (GetResponse) {}
  rpc QueryBatch(QueryBatchPointsInternal)
      returns (QueryBatchResponseInternal) {}
  rpc Facet(FacetCountsInternal) returns (FacetResponseInternal) {}
}

message SyncPoints {
  // name of the collection
  string collection_name = 1;
  // Wait until the changes have been applied?
  optional bool wait = 2;
  repeated PointStruct points = 3;
  // Start of the sync range
  optional PointId from_id = 4;
  // End of the sync range
  optional PointId to_id = 5;
  optional WriteOrdering ordering = 6;
  // Timeout for the request in seconds
  optional uint64 timeout = 7;
}

message SyncPointsInternal {
  SyncPoints sync_points = 1;
  optional uint32 shard_id = 2;
  optional ClockTag clock_tag = 3;
}

message UpsertPointsInternal {
  UpsertPoints upsert_points = 1;
  optional uint32 shard_id = 2;
  optional ClockTag clock_tag = 3;
}

message DeletePointsInternal {
  DeletePoints delete_points = 1;
  optional uint32 shard_id = 2;
  optional ClockTag clock_tag = 3;
}

message UpdateVectorsInternal {
  UpdatePointVectors update_vectors = 1;
  optional uint32 shard_id = 2;
  optional ClockTag clock_tag = 3;
}

message DeleteVectorsInternal {
  DeletePointVectors delete_vectors = 1;
  optional uint32 shard_id = 2;
  optional ClockTag clock_tag = 3;
}

message SetPayloadPointsInternal {
  SetPayloadPoints set_payload_points = 1;
  optional uint32 shard_id = 2;
  optional ClockTag clock_tag = 3;
}

message DeletePayloadPointsInternal {
  DeletePayloadPoints delete_payload_points = 1;
  optional uint32 shard_id = 2;
  optional ClockTag clock_tag = 3;
}

message ClearPayloadPointsInternal {
  ClearPayloadPoints clear_payload_points = 1;
  optional uint32 shard_id = 2;
  optional ClockTag clock_tag = 3;
}

message CreateFieldIndexCollectionInternal {
  CreateFieldIndexCollection create_field_index_collection = 1;
  optional uint32 shard_id = 2;
  optional ClockTag clock_tag = 3;
}

message DeleteFieldIndexCollectionInternal {
  DeleteFieldIndexCollection delete_field_index_collection = 1;
  optional uint32 shard_id = 2;
  optional ClockTag clock_tag = 3;
}

message UpdateOperation {
  oneof update {
    SyncPointsInternal sync = 1;
    UpsertPointsInternal upsert = 2;
    DeletePointsInternal delete = 3;
    UpdateVectorsInternal update_vectors = 4;
    DeleteVectorsInternal delete_vectors = 5;
    SetPayloadPointsInternal set_payload = 6;
    SetPayloadPointsInternal overwrite_payload = 7;
    DeletePayloadPointsInternal delete_payload = 8;
    ClearPayloadPointsInternal clear_payload = 9;
    CreateFieldIndexCollectionInternal create_field_index = 10;
    DeleteFieldIndexCollectionInternal delete_field_index = 11;
  }
}

message UpdateBatchInternal {
  repeated UpdateOperation operations = 1;
}

// Has to be backward compatible with `PointsOperationResponse`!
message PointsOperationResponseInternal {
  UpdateResultInternal result = 1;
  // Time spent to process
  double time = 2;
  optional HardwareUsage hardware_usage = 3;
  optional InferenceUsage inference_usage = 4;
}

// Has to be backward compatible with `UpdateResult`!
message UpdateResultInternal {
  // Number of operation
  optional uint64 operation_id = 1;
  // Operation status
  UpdateStatus status = 2;
  optional ClockTag clock_tag = 3;
}

message ClockTag {
  uint64 peer_id = 1;
  uint32 clock_id = 2;
  uint64 clock_tick = 3;
  uint64 token = 4;
  bool force = 5;
}

message SearchPointsInternal {
  SearchPoints search_points = 1;
  optional uint32 shard_id = 2;
}

message SearchBatchPointsInternal {
  string collection_name = 1;
  repeated SearchPoints search_points = 2;
  optional uint32 shard_id = 3;
  optional uint64 timeout = 4;
}

message RecoQuery {
  repeated Vector positives = 1;
  repeated Vector negatives = 2;
}

message ContextPair {
  Vector positive = 1;
  Vector negative = 2;
}

message DiscoveryQuery {
  Vector target = 1;
  repeated ContextPair context = 2;
}

message ContextQuery {
  repeated ContextPair context = 1;
}

message QueryEnum {
  oneof query {
    // ANN
    Vector nearest_neighbors = 1;
    // Recommend points with higher similarity to positive examples
    RecoQuery recommend_best_score = 2;
    // Search for points that get closer to a target,
    // constrained by a context of positive and negative pairs
    DiscoveryQuery discover = 3;
    // Use only the context to find points that minimize loss against negative examples
    ContextQuery context = 4;
    // Recommend points which have the greatest sum of scores against all vectors.
    // Positive vectors are added, negatives are subtracted.
    RecoQuery recommend_sum_scores = 5;
  }
}

// This is only used internally, so it makes more sense to add it here rather than in points.proto
message CoreSearchPoints {
  string collection_name = 1;
  QueryEnum query = 2;
  Filter filter = 3;
  uint64 limit = 4;
  WithPayloadSelector with_payload = 5;
  SearchParams params = 6;
  optional float score_threshold = 7;
  optional uint64 offset = 8;
  optional string vector_name = 9;
  optional WithVectorsSelector with_vectors = 10;
  optional ReadConsistency read_consistency = 11;
}

message CoreSearchBatchPointsInternal {
  string collection_name = 1;
  repeated CoreSearchPoints search_points = 2;
  optional uint32 shard_id = 3;
  optional uint64 timeout = 4;
}

message ScrollPointsInternal {
  ScrollPoints scroll_points = 1;
  optional uint32 shard_id = 2;
}

message RecommendPointsInternal {
  RecommendPoints recommend_points = 1;
  optional uint32 shard_id = 2;
}

message GetPointsInternal {
  GetPoints get_points = 1;
  optional uint32 shard_id = 2;
}

message CountPointsInternal {
  CountPoints count_points = 1;
  optional uint32 shard_id = 2;
}

// A bare vector. No id reference here.
message RawVector {
  oneof variant {
    DenseVector dense = 1;
    SparseVector sparse = 2;
    MultiDenseVector multi_dense = 3;
  }
}

// Query variants for raw vectors (ids have been substituted with vectors)
message RawQuery {
  message Recommend {
    repeated RawVector positives = 1;
    repeated RawVector negatives = 2;
  }

  message RawContextPair {
    RawVector positive = 1;
    RawVector negative = 2;
  }

  message Discovery {
    RawVector target = 1;
    repeated RawContextPair context = 2;
  }

  message Context {
    repeated RawContextPair context = 1;
  }

  message Feedback {
    RawVector target = 1;
    repeated RawFeedbackItem feedback = 2;
    FeedbackStrategy strategy = 3;
  }

  message RawFeedbackItem {
    RawVector vector = 1;
    float score = 2;
  }

  oneof variant {
    // ANN
    RawVector nearest = 1;
    // Recommend points with highest similarity to positive examples,
    // or lowest to negative examples
    Recommend recommend_best_score = 2;
    // Search for points that get closer to a target,
    // constrained by a context of positive and negative pairs
    Discovery discover = 3;
    // Use only the context to find points that minimize loss against negative examples
    Context context = 4;
    // Recommend points which have the greatest sum of scores against all vectors.
    // Positive vectors are added, negatives are subtracted.
    Recommend recommend_sum_scores = 5;
    Feedback feedback = 6;
  }
}

message MmrInternal {
  // Query vector to use for relevance
  RawVector vector = 1;
  // Lambda parameter controlling diversity vs relevance trade-off
  float lambda = 2;
  uint32 candidates_limit = 3;
}

message QueryShardPoints {
  message Query {
    oneof score {
      // (re)score against a vector query
      RawQuery vector = 1;
      // One of the fusion methods
      Fusion fusion = 2;
      // Order by a field
      OrderBy order_by = 3;
      // Sample points
      Sample sample = 4;
      // Use an arbitrary formula to rescore points
      Formula formula = 5;
      // Maximal Marginal Relevance
      MmrInternal mmr = 6;
      // Parameterized RRF fusion
      Rrf rrf = 7;
    }
  }

  message Prefetch {
    repeated Prefetch prefetch = 1;
    Query query = 2;
    optional string using = 3;
    Filter filter = 4;
    uint64 limit = 5;
    SearchParams params = 6;
    optional float score_threshold = 7;
  }

  repeated Prefetch prefetch = 1;
  Query query = 2;
  optional string using = 3;
  Filter filter = 4;
  uint64 limit = 5;
  SearchParams params = 6;
  optional float score_threshold = 7;
  uint64 offset = 8;
  WithPayloadSelector with_payload = 9;
  WithVectorsSelector with_vectors = 10;
}

message QueryBatchPointsInternal {
  string collection_name = 1;
  repeated QueryShardPoints query_points = 2;
  optional uint32 shard_id = 3;
  optional uint64 timeout = 4;
}

message IntermediateResult {
  repeated ScoredPoint result = 1;
}

message QueryResultInternal {
  repeated IntermediateResult intermediate_results = 1;
}

message QueryBatchResponseInternal {
  repeated QueryResultInternal results = 1;
  // Time spent to process
  double time = 2;
  optional HardwareUsage hardware_usage = 5;
  optional InferenceUsage inference_usage = 6;
}

message FacetCountsInternal {
  string collection_name = 1;
  string key = 2;
  optional Filter filter = 3;
  uint64 limit = 4;
  bool exact = 5;
  uint32 shard_id = 6;
  optional uint64 timeout = 7;
}

message FacetValueInternal {
  oneof variant {
    string keyword_value = 1;
    int64 integer_value = 2;
    bytes uuid_value = 3;
    bool bool_value = 4;
  }
}

message FacetHitInternal {
  FacetValueInternal value = 1;
  uint64 count = 2;
}

message FacetResponseInternal {
  repeated FacetHitInternal hits = 1;
  // Time spent to process
  double time = 2;
  optional HardwareUsage usage = 3;
}
