From 7aeaa06124c4118e71c17680edc043abab58756b Mon Sep 17 00:00:00 2001 From: Benjamin Ran Date: Sun, 17 Apr 2022 11:47:57 +0300 Subject: [PATCH 1/5] Add delete by metadata filter support --- .../core/client/api/vector_operations_api.py | 129 ++++++++- pinecone/core/client/model/delete_request.py | 274 ++++++++++++++++++ pinecone/core/client/models/__init__.py | 1 + .../core/grpc/protos/vector_service_pb2.py | 74 ++--- .../core/grpc/protos/vector_service_pb2.pyi | 7 +- pinecone/index.py | 15 +- specs/pinecone_api.json | 75 ++++- specs/vector_service.openapi.json | 73 +++++ 8 files changed, 606 insertions(+), 42 deletions(-) create mode 100644 pinecone/core/client/model/delete_request.py diff --git a/pinecone/core/client/api/vector_operations_api.py b/pinecone/core/client/api/vector_operations_api.py index 991723eb..edd9906a 100644 --- a/pinecone/core/client/api/vector_operations_api.py +++ b/pinecone/core/client/api/vector_operations_api.py @@ -26,6 +26,7 @@ none_type, validate_and_convert_types ) +from pinecone.core.client.model.delete_request import DeleteRequest from pinecone.core.client.model.describe_index_stats_response import DescribeIndexStatsResponse from pinecone.core.client.model.fetch_response import FetchResponse from pinecone.core.client.model.query_request import QueryRequest @@ -50,6 +51,7 @@ def __init__(self, api_client=None): def __delete( self, + delete_request, **kwargs ): """Delete # noqa: E501 @@ -58,7 +60,126 @@ def __delete( This method makes a synchronous HTTP request by default. To make an asynchronous HTTP request, please pass async_req=True - >>> thread = api.delete(async_req=True) + >>> thread = api.delete(delete_request, async_req=True) + >>> result = thread.get() + + Args: + delete_request (DeleteRequest): + + Keyword Args: + _return_http_data_only (bool): response data without head status + code and headers. Default is True. + _preload_content (bool): if False, the urllib3.HTTPResponse object + will be returned without reading/decoding response data. + Default is True. + _request_timeout (int/float/tuple): timeout setting for this request. If + one number provided, it will be total request timeout. It can also + be a pair (tuple) of (connection, read) timeouts. + Default is None. + _check_input_type (bool): specifies if type checking + should be done one the data sent to the server. + Default is True. + _check_return_type (bool): specifies if type checking + should be done one the data received from the server. + Default is True. + _host_index (int/None): specifies the index of the server + that we want to use. + Default is read from the configuration. + async_req (bool): execute request asynchronously + + Returns: + {str: (bool, date, datetime, dict, float, int, list, str, none_type)} + If the method is called asynchronously, returns the request + thread. + """ + kwargs['async_req'] = kwargs.get( + 'async_req', False + ) + kwargs['_return_http_data_only'] = kwargs.get( + '_return_http_data_only', True + ) + kwargs['_preload_content'] = kwargs.get( + '_preload_content', True + ) + kwargs['_request_timeout'] = kwargs.get( + '_request_timeout', None + ) + kwargs['_check_input_type'] = kwargs.get( + '_check_input_type', True + ) + kwargs['_check_return_type'] = kwargs.get( + '_check_return_type', True + ) + kwargs['_host_index'] = kwargs.get('_host_index') + kwargs['delete_request'] = \ + delete_request + return self.call_with_http_info(**kwargs) + + self.delete = _Endpoint( + settings={ + 'response_type': ({str: (bool, date, datetime, dict, float, int, list, str, none_type)},), + 'auth': [ + 'ApiKeyAuth' + ], + 'endpoint_path': '/vectors/delete', + 'operation_id': 'delete', + 'http_method': 'POST', + 'servers': None, + }, + params_map={ + 'all': [ + 'delete_request', + ], + 'required': [ + 'delete_request', + ], + 'nullable': [ + ], + 'enum': [ + ], + 'validation': [ + ] + }, + root_map={ + 'validations': { + }, + 'allowed_values': { + }, + 'openapi_types': { + 'delete_request': + (DeleteRequest,), + }, + 'attribute_map': { + }, + 'location_map': { + 'delete_request': 'body', + }, + 'collection_format_map': { + } + }, + headers_map={ + 'accept': [ + 'application/json' + ], + 'content_type': [ + 'application/json' + ] + }, + api_client=api_client, + callable=__delete + ) + + def __delete1( + self, + **kwargs + ): + """Delete # noqa: E501 + + The `Delete` operation deletes vectors, by id, from a single namespace. You can delete items by their id, from a single namespace. # noqa: E501 + This method makes a synchronous HTTP request by default. To make an + asynchronous HTTP request, please pass async_req=True + + >>> thread = api.delete1(async_req=True) >>> result = thread.get() @@ -112,14 +233,14 @@ def __delete( kwargs['_host_index'] = kwargs.get('_host_index') return self.call_with_http_info(**kwargs) - self.delete = _Endpoint( + self.delete1 = _Endpoint( settings={ 'response_type': ({str: (bool, date, datetime, dict, float, int, list, str, none_type)},), 'auth': [ 'ApiKeyAuth' ], 'endpoint_path': '/vectors/delete', - 'operation_id': 'delete', + 'operation_id': 'delete1', 'http_method': 'DELETE', 'servers': None, }, @@ -171,7 +292,7 @@ def __delete( 'content_type': [], }, api_client=api_client, - callable=__delete + callable=__delete1 ) def __describe_index_stats( diff --git a/pinecone/core/client/model/delete_request.py b/pinecone/core/client/model/delete_request.py new file mode 100644 index 00000000..5a2ea9ee --- /dev/null +++ b/pinecone/core/client/model/delete_request.py @@ -0,0 +1,274 @@ +# +# Copyright (c) 2020-2021 Pinecone Systems Inc. All right reserved. +# + +""" + Pinecone API + + No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) # noqa: E501 + + The version of the OpenAPI document: version not set + Contact: support@pinecone.io + Generated by: https://openapi-generator.tech +""" + + +import re # noqa: F401 +import sys # noqa: F401 + +from pinecone.core.client.model_utils import ( # noqa: F401 + ApiTypeError, + ModelComposed, + ModelNormal, + ModelSimple, + cached_property, + change_keys_js_to_python, + convert_js_args_to_python_args, + date, + datetime, + file_type, + none_type, + validate_get_composed_info, +) +from ..model_utils import OpenApiModel +from pinecone.core.client.exceptions import ApiAttributeError + + + +class DeleteRequest(ModelNormal): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + + Attributes: + allowed_values (dict): The key is the tuple path to the attribute + and the for var_name this is (var_name,). The value is a dict + with a capitalized key describing the allowed value and an allowed + value. These dicts store the allowed enum values. + attribute_map (dict): The key is attribute name + and the value is json key in definition. + discriminator_value_class_map (dict): A dict to go from the discriminator + variable value to the discriminator class name. + validations (dict): The key is the tuple path to the attribute + and the for var_name this is (var_name,). The value is a dict + that stores validations for max_length, min_length, max_items, + min_items, exclusive_maximum, inclusive_maximum, exclusive_minimum, + inclusive_minimum, and regex. + additional_properties_type (tuple): A tuple of classes accepted + as additional properties values. + """ + + allowed_values = { + } + + validations = { + ('ids',): { + }, + } + + @cached_property + def additional_properties_type(): + """ + This must be a method because a model may have properties that are + of type self, this must run after the class is loaded + """ + return (bool, date, datetime, dict, float, int, list, str, none_type,) # noqa: E501 + + _nullable = False + + @cached_property + def openapi_types(): + """ + This must be a method because a model may have properties that are + of type self, this must run after the class is loaded + + Returns + openapi_types (dict): The key is attribute name + and the value is attribute type. + """ + return { + 'ids': ([str],), # noqa: E501 + 'delete_all': (bool,), # noqa: E501 + 'namespace': (str,), # noqa: E501 + 'filter': ({str: (bool, date, datetime, dict, float, int, list, str, none_type)},), # noqa: E501 + } + + @cached_property + def discriminator(): + return None + + + attribute_map = { + 'ids': 'ids', # noqa: E501 + 'delete_all': 'deleteAll', # noqa: E501 + 'namespace': 'namespace', # noqa: E501 + 'filter': 'filter', # noqa: E501 + } + + read_only_vars = { + } + + _composed_schemas = {} + + @classmethod + @convert_js_args_to_python_args + def _from_openapi_data(cls, *args, **kwargs): # noqa: E501 + """DeleteRequest - a model defined in OpenAPI + + Keyword Args: + _check_type (bool): if True, values for parameters in openapi_types + will be type checked and a TypeError will be + raised if the wrong type is input. + Defaults to True + _path_to_item (tuple/list): This is a list of keys or values to + drill down to the model in received_data + when deserializing a response + _spec_property_naming (bool): True if the variable names in the input data + are serialized names, as specified in the OpenAPI document. + False if the variable names in the input data + are pythonic names, e.g. snake case (default) + _configuration (Configuration): the instance to use when + deserializing a file_type parameter. + If passed, type conversion is attempted + If omitted no type conversion is done. + _visited_composed_classes (tuple): This stores a tuple of + classes that we have traveled through so that + if we see that class again we will not use its + discriminator again. + When traveling through a discriminator, the + composed schema that is + is traveled through is added to this set. + For example if Animal has a discriminator + petType and we pass in "Dog", and the class Dog + allOf includes Animal, we move through Animal + once using the discriminator, and pick Dog. + Then in Dog, we will make an instance of the + Animal class but this time we won't travel + through its discriminator because we passed in + _visited_composed_classes = (Animal,) + ids ([str]): Vectors to delete.. [optional] # noqa: E501 + delete_all (bool): This indicates that all vectors in the index namespace should be deleted.. [optional] # noqa: E501 + namespace (str): The namespace to delete vectors from, if applicable.. [optional] # noqa: E501 + filter ({str: (bool, date, datetime, dict, float, int, list, str, none_type)}): [optional] # noqa: E501 + """ + + _check_type = kwargs.pop('_check_type', True) + _spec_property_naming = kwargs.pop('_spec_property_naming', False) + _path_to_item = kwargs.pop('_path_to_item', ()) + _configuration = kwargs.pop('_configuration', None) + _visited_composed_classes = kwargs.pop('_visited_composed_classes', ()) + + self = super(OpenApiModel, cls).__new__(cls) + + if args: + raise ApiTypeError( + "Invalid positional arguments=%s passed to %s. Remove those invalid positional arguments." % ( + args, + self.__class__.__name__, + ), + path_to_item=_path_to_item, + valid_classes=(self.__class__,), + ) + + self._data_store = {} + self._check_type = _check_type + self._spec_property_naming = _spec_property_naming + self._path_to_item = _path_to_item + self._configuration = _configuration + self._visited_composed_classes = _visited_composed_classes + (self.__class__,) + + for var_name, var_value in kwargs.items(): + if var_name not in self.attribute_map and \ + self._configuration is not None and \ + self._configuration.discard_unknown_keys and \ + self.additional_properties_type is None: + # discard variable. + continue + setattr(self, var_name, var_value) + return self + + required_properties = set([ + '_data_store', + '_check_type', + '_spec_property_naming', + '_path_to_item', + '_configuration', + '_visited_composed_classes', + ]) + + @convert_js_args_to_python_args + def __init__(self, *args, **kwargs): # noqa: E501 + """DeleteRequest - a model defined in OpenAPI + + Keyword Args: + _check_type (bool): if True, values for parameters in openapi_types + will be type checked and a TypeError will be + raised if the wrong type is input. + Defaults to True + _path_to_item (tuple/list): This is a list of keys or values to + drill down to the model in received_data + when deserializing a response + _spec_property_naming (bool): True if the variable names in the input data + are serialized names, as specified in the OpenAPI document. + False if the variable names in the input data + are pythonic names, e.g. snake case (default) + _configuration (Configuration): the instance to use when + deserializing a file_type parameter. + If passed, type conversion is attempted + If omitted no type conversion is done. + _visited_composed_classes (tuple): This stores a tuple of + classes that we have traveled through so that + if we see that class again we will not use its + discriminator again. + When traveling through a discriminator, the + composed schema that is + is traveled through is added to this set. + For example if Animal has a discriminator + petType and we pass in "Dog", and the class Dog + allOf includes Animal, we move through Animal + once using the discriminator, and pick Dog. + Then in Dog, we will make an instance of the + Animal class but this time we won't travel + through its discriminator because we passed in + _visited_composed_classes = (Animal,) + ids ([str]): Vectors to delete.. [optional] # noqa: E501 + delete_all (bool): This indicates that all vectors in the index namespace should be deleted.. [optional] # noqa: E501 + namespace (str): The namespace to delete vectors from, if applicable.. [optional] # noqa: E501 + filter ({str: (bool, date, datetime, dict, float, int, list, str, none_type)}): [optional] # noqa: E501 + """ + + _check_type = kwargs.pop('_check_type', True) + _spec_property_naming = kwargs.pop('_spec_property_naming', False) + _path_to_item = kwargs.pop('_path_to_item', ()) + _configuration = kwargs.pop('_configuration', None) + _visited_composed_classes = kwargs.pop('_visited_composed_classes', ()) + + if args: + raise ApiTypeError( + "Invalid positional arguments=%s passed to %s. Remove those invalid positional arguments." % ( + args, + self.__class__.__name__, + ), + path_to_item=_path_to_item, + valid_classes=(self.__class__,), + ) + + self._data_store = {} + self._check_type = _check_type + self._spec_property_naming = _spec_property_naming + self._path_to_item = _path_to_item + self._configuration = _configuration + self._visited_composed_classes = _visited_composed_classes + (self.__class__,) + + for var_name, var_value in kwargs.items(): + if var_name not in self.attribute_map and \ + self._configuration is not None and \ + self._configuration.discard_unknown_keys and \ + self.additional_properties_type is None: + # discard variable. + continue + setattr(self, var_name, var_value) + if var_name in self.read_only_vars: + raise ApiAttributeError(f"`{var_name}` is a read-only attribute. Use `from_openapi_data` to instantiate " + f"class with read only attributes.") diff --git a/pinecone/core/client/models/__init__.py b/pinecone/core/client/models/__init__.py index 7bb1beea..64914b49 100644 --- a/pinecone/core/client/models/__init__.py +++ b/pinecone/core/client/models/__init__.py @@ -15,6 +15,7 @@ from pinecone.core.client.model.approximated_config import ApproximatedConfig from pinecone.core.client.model.create_request import CreateRequest +from pinecone.core.client.model.delete_request import DeleteRequest from pinecone.core.client.model.describe_index_stats_response import DescribeIndexStatsResponse from pinecone.core.client.model.fetch_response import FetchResponse from pinecone.core.client.model.hnsw_config import HnswConfig diff --git a/pinecone/core/grpc/protos/vector_service_pb2.py b/pinecone/core/grpc/protos/vector_service_pb2.py index b5741c5f..79f5da1d 100644 --- a/pinecone/core/grpc/protos/vector_service_pb2.py +++ b/pinecone/core/grpc/protos/vector_service_pb2.py @@ -28,7 +28,7 @@ syntax='proto3', serialized_options=b'\n\021io.pinecone.protoP\001Z/github.com/pinecone-io/new-go-pinecone/pinecone\222A\366\002\022K\n\014Pinecone API\";\n\017Pinecone.io Ops\022\023https://pinecone.io\032\023support@pinecone.io\0329{index_name}-{project_name}.svc.{environment}.pinecone.io*\001\0022\020application/json:\020application/jsonZx\nv\n\nApiKeyAuth\022h\010\002\022YAn API Key is required to call Pinecone APIs. Get yours at https://www.pinecone.io/start/\032\007Api-Key \002b\020\n\016\n\nApiKeyAuth\022\000r9\n\031More Pinecone.io API docs\022\034https://www.pinecone.io/docs', create_key=_descriptor._internal_create_key, - serialized_pb=b'\n\x14vector_service.proto\x1a\x1cgoogle/protobuf/struct.proto\x1a\x1cgoogle/api/annotations.proto\x1a\x1fgoogle/api/field_behavior.proto\x1a\x1egoogle/rpc/error_details.proto\x1a.protoc-gen-openapiv2/options/annotations.proto\"\xd7\x01\n\x06Vector\x12,\n\x02id\x18\x01 \x01(\tB \x92\x41\x1aJ\x12\"example-vector-1\"x\x80\x04\x80\x01\x01\xe0\x41\x02\x12G\n\x06values\x18\x02 \x03(\x02\x42\x37\x92\x41\x31J([0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8]x\xa0\x9c\x01\x80\x01\x01\xe0\x41\x02\x12V\n\x08metadata\x18\x03 \x01(\x0b\x32\x17.google.protobuf.StructB+\x92\x41(J&{\"genre\": \"documentary\", \"year\": 2019}\"\xed\x01\n\x0cScoredVector\x12,\n\x02id\x18\x01 \x01(\tB \x92\x41\x1aJ\x12\"example-vector-1\"x\x80\x04\x80\x01\x01\xe0\x41\x02\x12\x18\n\x05score\x18\x02 \x01(\x02\x42\t\x92\x41\x06J\x04\x30.08\x12=\n\x06values\x18\x03 \x03(\x02\x42-\x92\x41*J([0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8]\x12V\n\x08metadata\x18\x04 \x01(\x0b\x32\x17.google.protobuf.StructB+\x92\x41(J&{\"genre\": \"documentary\", \"year\": 2019}\"d\n\rUpsertRequest\x12&\n\x07vectors\x18\x01 \x03(\x0b\x32\x07.VectorB\x0c\x92\x41\x06x\xe8\x07\x80\x01\x01\xe0\x41\x02\x12+\n\tnamespace\x18\x02 \x01(\tB\x18\x92\x41\x15J\x13\"example-namespace\"\"1\n\x0eUpsertResponse\x12\x1f\n\x0eupserted_count\x18\x01 \x01(\rB\x07\x92\x41\x04J\x02\x31\x30\"\x85\x01\n\rDeleteRequest\x12(\n\x03ids\x18\x01 \x03(\tB\x1b\x92\x41\x18J\x10[\"id-0\", \"id-1\"]x\xe8\x07\x80\x01\x01\x12\x1d\n\ndelete_all\x18\x02 \x01(\x08\x42\t\x92\x41\x06J\x04true\x12+\n\tnamespace\x18\x03 \x01(\tB\x18\x92\x41\x15J\x13\"example-namespace\"\"\x10\n\x0e\x44\x65leteResponse\"h\n\x0c\x46\x65tchRequest\x12+\n\x03ids\x18\x01 \x03(\tB\x1e\x92\x41\x18J\x10[\"id-0\", \"id-1\"]x\xe8\x07\x80\x01\x01\xe0\x41\x02\x12+\n\tnamespace\x18\x02 \x01(\tB\x18\x92\x41\x15J\x13\"example-namespace\"\"\xa3\x01\n\rFetchResponse\x12,\n\x07vectors\x18\x01 \x03(\x0b\x32\x1b.FetchResponse.VectorsEntry\x12+\n\tnamespace\x18\x02 \x01(\tB\x18\x92\x41\x15J\x13\"example-namespace\"\x1a\x37\n\x0cVectorsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x16\n\x05value\x18\x02 \x01(\x0b\x32\x07.Vector:\x02\x38\x01\"\xaa\x02\n\x0bQueryVector\x12G\n\x06values\x18\x01 \x03(\x02\x42\x37\x92\x41\x31J([0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8]x\xa0\x9c\x01\x80\x01\x01\xe0\x41\x02\x12(\n\x05top_k\x18\x02 \x01(\rB\x19\x92\x41\x16J\x02\x31\x30Y\x00\x00\x00\x00\x00\x88\xc3@i\x00\x00\x00\x00\x00\x00\xf0?\x12+\n\tnamespace\x18\x03 \x01(\tB\x18\x92\x41\x15J\x13\"example-namespace\"\x12{\n\x06\x66ilter\x18\x04 \x01(\x0b\x32\x17.google.protobuf.StructBR\x92\x41OJM{\"genre\": {\"$in\": [\"comedy\", \"documentary\", \"drama\"]}, \"year\": {\"$eq\": 2019}}\"\xe7\x02\n\x0cQueryRequest\x12+\n\tnamespace\x18\x01 \x01(\tB\x18\x92\x41\x15J\x13\"example-namespace\"\x12+\n\x05top_k\x18\x02 \x01(\rB\x1c\x92\x41\x16J\x02\x31\x30Y\x00\x00\x00\x00\x00\x88\xc3@i\x00\x00\x00\x00\x00\x00\xf0?\xe0\x41\x02\x12{\n\x06\x66ilter\x18\x03 \x01(\x0b\x32\x17.google.protobuf.StructBR\x92\x41OJM{\"genre\": {\"$in\": [\"comedy\", \"documentary\", \"drama\"]}, \"year\": {\"$eq\": 2019}}\x12(\n\x0einclude_values\x18\x04 \x01(\x08\x42\x10\x92\x41\r:\x05\x66\x61lseJ\x04true\x12*\n\x10include_metadata\x18\x05 \x01(\x08\x42\x10\x92\x41\r:\x05\x66\x61lseJ\x04true\x12*\n\x07queries\x18\x06 \x03(\x0b\x32\x0c.QueryVectorB\x0b\x92\x41\x05x\n\x80\x01\x01\xe0\x41\x02\"a\n\x12SingleQueryResults\x12\x1e\n\x07matches\x18\x01 \x03(\x0b\x32\r.ScoredVector\x12+\n\tnamespace\x18\x02 \x01(\tB\x18\x92\x41\x15J\x13\"example-namespace\"\"5\n\rQueryResponse\x12$\n\x07results\x18\x01 \x03(\x0b\x32\x13.SingleQueryResults\"\x8c\x02\n\rUpdateRequest\x12,\n\x02id\x18\x01 \x01(\tB \x92\x41\x1aJ\x12\"example-vector-1\"x\x80\x04\x80\x01\x01\xe0\x41\x02\x12\x44\n\x06values\x18\x02 \x03(\x02\x42\x34\x92\x41\x31J([0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8]x\xa0\x9c\x01\x80\x01\x01\x12Z\n\x0cset_metadata\x18\x03 \x01(\x0b\x32\x17.google.protobuf.StructB+\x92\x41(J&{\"genre\": \"documentary\", \"year\": 2019}\x12+\n\tnamespace\x18\x04 \x01(\tB\x18\x92\x41\x15J\x13\"example-namespace\"\"\x10\n\x0eUpdateResponse\"\x1b\n\x19\x44\x65scribeIndexStatsRequest\"4\n\x10NamespaceSummary\x12 \n\x0cvector_count\x18\x01 \x01(\rB\n\x92\x41\x07J\x05\x35\x30\x30\x30\x30\"\xf4\x02\n\x1a\x44\x65scribeIndexStatsResponse\x12?\n\nnamespaces\x18\x01 \x03(\x0b\x32+.DescribeIndexStatsResponse.NamespacesEntry\x12\x1c\n\tdimension\x18\x02 \x01(\rB\t\x92\x41\x06J\x04\x31\x30\x32\x34\x12!\n\x0eindex_fullness\x18\x03 \x01(\x02\x42\t\x92\x41\x06J\x04\x30.42\x1a\x44\n\x0fNamespacesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12 \n\x05value\x18\x02 \x01(\x0b\x32\x11.NamespaceSummary:\x02\x38\x01:\x8d\x01\x92\x41\x89\x01\x32\x86\x01{\"namespaces\": {\"\": {\"vectorCount\": 50000}, \"example-namespace-2\": {\"vectorCount\": 30000}}, \"dimension\": 1024, \"index_fullness\": 0.42}2\x8b\x05\n\rVectorService\x12\x63\n\x06Upsert\x12\x0e.UpsertRequest\x1a\x0f.UpsertResponse\"8\x82\xd3\xe4\x93\x02\x14\"\x0f/vectors/upsert:\x01*\x92\x41\x1b\n\x11Vector Operations*\x06upsert\x12`\n\x06\x44\x65lete\x12\x0e.DeleteRequest\x1a\x0f.DeleteResponse\"5\x82\xd3\xe4\x93\x02\x11*\x0f/vectors/delete\x92\x41\x1b\n\x11Vector Operations*\x06\x64\x65lete\x12[\n\x05\x46\x65tch\x12\r.FetchRequest\x1a\x0e.FetchResponse\"3\x82\xd3\xe4\x93\x02\x10\x12\x0e/vectors/fetch\x92\x41\x1a\n\x11Vector Operations*\x05\x66\x65tch\x12V\n\x05Query\x12\r.QueryRequest\x1a\x0e.QueryResponse\".\x82\xd3\xe4\x93\x02\x0b\"\x06/query:\x01*\x92\x41\x1a\n\x11Vector Operations*\x05query\x12\x63\n\x06Update\x12\x0e.UpdateRequest\x1a\x0f.UpdateResponse\"8\x82\xd3\xe4\x93\x02\x14\"\x0f/vectors/update:\x01*\x92\x41\x1b\n\x11Vector Operations*\x06update\x12\x98\x01\n\x12\x44\x65scribeIndexStats\x12\x1a.DescribeIndexStatsRequest\x1a\x1b.DescribeIndexStatsResponse\"I\x82\xd3\xe4\x93\x02\x17\x12\x15/describe_index_stats\x92\x41)\n\x11Vector Operations*\x14\x64\x65scribe_index_statsB\xc0\x03\n\x11io.pinecone.protoP\x01Z/github.com/pinecone-io/new-go-pinecone/pinecone\x92\x41\xf6\x02\x12K\n\x0cPinecone API\";\n\x0fPinecone.io Ops\x12\x13https://pinecone.io\x1a\x13support@pinecone.io\x1a\x39{index_name}-{project_name}.svc.{environment}.pinecone.io*\x01\x02\x32\x10\x61pplication/json:\x10\x61pplication/jsonZx\nv\n\nApiKeyAuth\x12h\x08\x02\x12YAn API Key is required to call Pinecone APIs. Get yours at https://www.pinecone.io/start/\x1a\x07\x41pi-Key \x02\x62\x10\n\x0e\n\nApiKeyAuth\x12\x00r9\n\x19More Pinecone.io API docs\x12\x1chttps://www.pinecone.io/docsb\x06proto3' + serialized_pb=b'\n\x14vector_service.proto\x1a\x1cgoogle/protobuf/struct.proto\x1a\x1cgoogle/api/annotations.proto\x1a\x1fgoogle/api/field_behavior.proto\x1a\x1egoogle/rpc/error_details.proto\x1a.protoc-gen-openapiv2/options/annotations.proto\"\xd7\x01\n\x06Vector\x12,\n\x02id\x18\x01 \x01(\tB \x92\x41\x1aJ\x12\"example-vector-1\"x\x80\x04\x80\x01\x01\xe0\x41\x02\x12G\n\x06values\x18\x02 \x03(\x02\x42\x37\x92\x41\x31J([0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8]x\xa0\x9c\x01\x80\x01\x01\xe0\x41\x02\x12V\n\x08metadata\x18\x03 \x01(\x0b\x32\x17.google.protobuf.StructB+\x92\x41(J&{\"genre\": \"documentary\", \"year\": 2019}\"\xed\x01\n\x0cScoredVector\x12,\n\x02id\x18\x01 \x01(\tB \x92\x41\x1aJ\x12\"example-vector-1\"x\x80\x04\x80\x01\x01\xe0\x41\x02\x12\x18\n\x05score\x18\x02 \x01(\x02\x42\t\x92\x41\x06J\x04\x30.08\x12=\n\x06values\x18\x03 \x03(\x02\x42-\x92\x41*J([0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8]\x12V\n\x08metadata\x18\x04 \x01(\x0b\x32\x17.google.protobuf.StructB+\x92\x41(J&{\"genre\": \"documentary\", \"year\": 2019}\"d\n\rUpsertRequest\x12&\n\x07vectors\x18\x01 \x03(\x0b\x32\x07.VectorB\x0c\x92\x41\x06x\xe8\x07\x80\x01\x01\xe0\x41\x02\x12+\n\tnamespace\x18\x02 \x01(\tB\x18\x92\x41\x15J\x13\"example-namespace\"\"1\n\x0eUpsertResponse\x12\x1f\n\x0eupserted_count\x18\x01 \x01(\rB\x07\x92\x41\x04J\x02\x31\x30\"\xae\x01\n\rDeleteRequest\x12(\n\x03ids\x18\x01 \x03(\tB\x1b\x92\x41\x18J\x10[\"id-0\", \"id-1\"]x\xe8\x07\x80\x01\x01\x12\x1d\n\ndelete_all\x18\x02 \x01(\x08\x42\t\x92\x41\x06J\x04true\x12+\n\tnamespace\x18\x03 \x01(\tB\x18\x92\x41\x15J\x13\"example-namespace\"\x12\'\n\x06\x66ilter\x18\x04 \x01(\x0b\x32\x17.google.protobuf.Struct\"\x10\n\x0e\x44\x65leteResponse\"h\n\x0c\x46\x65tchRequest\x12+\n\x03ids\x18\x01 \x03(\tB\x1e\x92\x41\x18J\x10[\"id-0\", \"id-1\"]x\xe8\x07\x80\x01\x01\xe0\x41\x02\x12+\n\tnamespace\x18\x02 \x01(\tB\x18\x92\x41\x15J\x13\"example-namespace\"\"\xa3\x01\n\rFetchResponse\x12,\n\x07vectors\x18\x01 \x03(\x0b\x32\x1b.FetchResponse.VectorsEntry\x12+\n\tnamespace\x18\x02 \x01(\tB\x18\x92\x41\x15J\x13\"example-namespace\"\x1a\x37\n\x0cVectorsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x16\n\x05value\x18\x02 \x01(\x0b\x32\x07.Vector:\x02\x38\x01\"\xaa\x02\n\x0bQueryVector\x12G\n\x06values\x18\x01 \x03(\x02\x42\x37\x92\x41\x31J([0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8]x\xa0\x9c\x01\x80\x01\x01\xe0\x41\x02\x12(\n\x05top_k\x18\x02 \x01(\rB\x19\x92\x41\x16J\x02\x31\x30Y\x00\x00\x00\x00\x00\x88\xc3@i\x00\x00\x00\x00\x00\x00\xf0?\x12+\n\tnamespace\x18\x03 \x01(\tB\x18\x92\x41\x15J\x13\"example-namespace\"\x12{\n\x06\x66ilter\x18\x04 \x01(\x0b\x32\x17.google.protobuf.StructBR\x92\x41OJM{\"genre\": {\"$in\": [\"comedy\", \"documentary\", \"drama\"]}, \"year\": {\"$eq\": 2019}}\"\xe7\x02\n\x0cQueryRequest\x12+\n\tnamespace\x18\x01 \x01(\tB\x18\x92\x41\x15J\x13\"example-namespace\"\x12+\n\x05top_k\x18\x02 \x01(\rB\x1c\x92\x41\x16J\x02\x31\x30Y\x00\x00\x00\x00\x00\x88\xc3@i\x00\x00\x00\x00\x00\x00\xf0?\xe0\x41\x02\x12{\n\x06\x66ilter\x18\x03 \x01(\x0b\x32\x17.google.protobuf.StructBR\x92\x41OJM{\"genre\": {\"$in\": [\"comedy\", \"documentary\", \"drama\"]}, \"year\": {\"$eq\": 2019}}\x12(\n\x0einclude_values\x18\x04 \x01(\x08\x42\x10\x92\x41\r:\x05\x66\x61lseJ\x04true\x12*\n\x10include_metadata\x18\x05 \x01(\x08\x42\x10\x92\x41\r:\x05\x66\x61lseJ\x04true\x12*\n\x07queries\x18\x06 \x03(\x0b\x32\x0c.QueryVectorB\x0b\x92\x41\x05x\n\x80\x01\x01\xe0\x41\x02\"a\n\x12SingleQueryResults\x12\x1e\n\x07matches\x18\x01 \x03(\x0b\x32\r.ScoredVector\x12+\n\tnamespace\x18\x02 \x01(\tB\x18\x92\x41\x15J\x13\"example-namespace\"\"5\n\rQueryResponse\x12$\n\x07results\x18\x01 \x03(\x0b\x32\x13.SingleQueryResults\"\x8c\x02\n\rUpdateRequest\x12,\n\x02id\x18\x01 \x01(\tB \x92\x41\x1aJ\x12\"example-vector-1\"x\x80\x04\x80\x01\x01\xe0\x41\x02\x12\x44\n\x06values\x18\x02 \x03(\x02\x42\x34\x92\x41\x31J([0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8]x\xa0\x9c\x01\x80\x01\x01\x12Z\n\x0cset_metadata\x18\x03 \x01(\x0b\x32\x17.google.protobuf.StructB+\x92\x41(J&{\"genre\": \"documentary\", \"year\": 2019}\x12+\n\tnamespace\x18\x04 \x01(\tB\x18\x92\x41\x15J\x13\"example-namespace\"\"\x10\n\x0eUpdateResponse\"\x1b\n\x19\x44\x65scribeIndexStatsRequest\"4\n\x10NamespaceSummary\x12 \n\x0cvector_count\x18\x01 \x01(\rB\n\x92\x41\x07J\x05\x35\x30\x30\x30\x30\"\xf4\x02\n\x1a\x44\x65scribeIndexStatsResponse\x12?\n\nnamespaces\x18\x01 \x03(\x0b\x32+.DescribeIndexStatsResponse.NamespacesEntry\x12\x1c\n\tdimension\x18\x02 \x01(\rB\t\x92\x41\x06J\x04\x31\x30\x32\x34\x12!\n\x0eindex_fullness\x18\x03 \x01(\x02\x42\t\x92\x41\x06J\x04\x30.42\x1a\x44\n\x0fNamespacesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12 \n\x05value\x18\x02 \x01(\x0b\x32\x11.NamespaceSummary:\x02\x38\x01:\x8d\x01\x92\x41\x89\x01\x32\x86\x01{\"namespaces\": {\"\": {\"vectorCount\": 50000}, \"example-namespace-2\": {\"vectorCount\": 30000}}, \"dimension\": 1024, \"index_fullness\": 0.42}2\xa1\x05\n\rVectorService\x12\x63\n\x06Upsert\x12\x0e.UpsertRequest\x1a\x0f.UpsertResponse\"8\x82\xd3\xe4\x93\x02\x14\"\x0f/vectors/upsert:\x01*\x92\x41\x1b\n\x11Vector Operations*\x06upsert\x12v\n\x06\x44\x65lete\x12\x0e.DeleteRequest\x1a\x0f.DeleteResponse\"K\x82\xd3\xe4\x93\x02\'\"\x0f/vectors/delete:\x01*Z\x11*\x0f/vectors/delete\x92\x41\x1b\n\x11Vector Operations*\x06\x64\x65lete\x12[\n\x05\x46\x65tch\x12\r.FetchRequest\x1a\x0e.FetchResponse\"3\x82\xd3\xe4\x93\x02\x10\x12\x0e/vectors/fetch\x92\x41\x1a\n\x11Vector Operations*\x05\x66\x65tch\x12V\n\x05Query\x12\r.QueryRequest\x1a\x0e.QueryResponse\".\x82\xd3\xe4\x93\x02\x0b\"\x06/query:\x01*\x92\x41\x1a\n\x11Vector Operations*\x05query\x12\x63\n\x06Update\x12\x0e.UpdateRequest\x1a\x0f.UpdateResponse\"8\x82\xd3\xe4\x93\x02\x14\"\x0f/vectors/update:\x01*\x92\x41\x1b\n\x11Vector Operations*\x06update\x12\x98\x01\n\x12\x44\x65scribeIndexStats\x12\x1a.DescribeIndexStatsRequest\x1a\x1b.DescribeIndexStatsResponse\"I\x82\xd3\xe4\x93\x02\x17\x12\x15/describe_index_stats\x92\x41)\n\x11Vector Operations*\x14\x64\x65scribe_index_statsB\xc0\x03\n\x11io.pinecone.protoP\x01Z/github.com/pinecone-io/new-go-pinecone/pinecone\x92\x41\xf6\x02\x12K\n\x0cPinecone API\";\n\x0fPinecone.io Ops\x12\x13https://pinecone.io\x1a\x13support@pinecone.io\x1a\x39{index_name}-{project_name}.svc.{environment}.pinecone.io*\x01\x02\x32\x10\x61pplication/json:\x10\x61pplication/jsonZx\nv\n\nApiKeyAuth\x12h\x08\x02\x12YAn API Key is required to call Pinecone APIs. Get yours at https://www.pinecone.io/start/\x1a\x07\x41pi-Key \x02\x62\x10\n\x0e\n\nApiKeyAuth\x12\x00r9\n\x19More Pinecone.io API docs\x12\x1chttps://www.pinecone.io/docsb\x06proto3' , dependencies=[google_dot_protobuf_dot_struct__pb2.DESCRIPTOR,google_dot_api_dot_annotations__pb2.DESCRIPTOR,google_dot_api_dot_field__behavior__pb2.DESCRIPTOR,google_dot_rpc_dot_error__details__pb2.DESCRIPTOR,protoc__gen__openapiv2_dot_options_dot_annotations__pb2.DESCRIPTOR,]) @@ -234,6 +234,13 @@ message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=b'\222A\025J\023\"example-namespace\"', file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='filter', full_name='DeleteRequest.filter', index=3, + number=4, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), ], extensions=[ ], @@ -247,7 +254,7 @@ oneofs=[ ], serialized_start=809, - serialized_end=942, + serialized_end=983, ) @@ -271,8 +278,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=944, - serialized_end=960, + serialized_start=985, + serialized_end=1001, ) @@ -310,8 +317,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=962, - serialized_end=1066, + serialized_start=1003, + serialized_end=1107, ) @@ -349,8 +356,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1177, - serialized_end=1232, + serialized_start=1218, + serialized_end=1273, ) _FETCHRESPONSE = _descriptor.Descriptor( @@ -387,8 +394,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1069, - serialized_end=1232, + serialized_start=1110, + serialized_end=1273, ) @@ -440,8 +447,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1235, - serialized_end=1533, + serialized_start=1276, + serialized_end=1574, ) @@ -507,8 +514,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1536, - serialized_end=1895, + serialized_start=1577, + serialized_end=1936, ) @@ -546,8 +553,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1897, - serialized_end=1994, + serialized_start=1938, + serialized_end=2035, ) @@ -578,8 +585,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1996, - serialized_end=2049, + serialized_start=2037, + serialized_end=2090, ) @@ -631,8 +638,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2052, - serialized_end=2320, + serialized_start=2093, + serialized_end=2361, ) @@ -656,8 +663,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2322, - serialized_end=2338, + serialized_start=2363, + serialized_end=2379, ) @@ -681,8 +688,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2340, - serialized_end=2367, + serialized_start=2381, + serialized_end=2408, ) @@ -713,8 +720,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2369, - serialized_end=2421, + serialized_start=2410, + serialized_end=2462, ) @@ -752,8 +759,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2584, - serialized_end=2652, + serialized_start=2625, + serialized_end=2693, ) _DESCRIBEINDEXSTATSRESPONSE = _descriptor.Descriptor( @@ -797,13 +804,14 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2424, - serialized_end=2796, + serialized_start=2465, + serialized_end=2837, ) _VECTOR.fields_by_name['metadata'].message_type = google_dot_protobuf_dot_struct__pb2._STRUCT _SCOREDVECTOR.fields_by_name['metadata'].message_type = google_dot_protobuf_dot_struct__pb2._STRUCT _UPSERTREQUEST.fields_by_name['vectors'].message_type = _VECTOR +_DELETEREQUEST.fields_by_name['filter'].message_type = google_dot_protobuf_dot_struct__pb2._STRUCT _FETCHRESPONSE_VECTORSENTRY.fields_by_name['value'].message_type = _VECTOR _FETCHRESPONSE_VECTORSENTRY.containing_type = _FETCHRESPONSE _FETCHRESPONSE.fields_by_name['vectors'].message_type = _FETCHRESPONSE_VECTORSENTRY @@ -1017,8 +1025,8 @@ index=0, serialized_options=None, create_key=_descriptor._internal_create_key, - serialized_start=2799, - serialized_end=3450, + serialized_start=2840, + serialized_end=3513, methods=[ _descriptor.MethodDescriptor( name='Upsert', @@ -1037,7 +1045,7 @@ containing_service=None, input_type=_DELETEREQUEST, output_type=_DELETERESPONSE, - serialized_options=b'\202\323\344\223\002\021*\017/vectors/delete\222A\033\n\021Vector Operations*\006delete', + serialized_options=b'\202\323\344\223\002\'\"\017/vectors/delete:\001*Z\021*\017/vectors/delete\222A\033\n\021Vector Operations*\006delete', create_key=_descriptor._internal_create_key, ), _descriptor.MethodDescriptor( diff --git a/pinecone/core/grpc/protos/vector_service_pb2.pyi b/pinecone/core/grpc/protos/vector_service_pb2.pyi index 6800956b..652a981e 100644 --- a/pinecone/core/grpc/protos/vector_service_pb2.pyi +++ b/pinecone/core/grpc/protos/vector_service_pb2.pyi @@ -109,13 +109,18 @@ class DeleteRequest(google___protobuf___message___Message): delete_all: builtin___bool = ... namespace: typing___Text = ... + @property + def filter(self) -> google___protobuf___struct_pb2___Struct: ... + def __init__(self, *, ids : typing___Optional[typing___Iterable[typing___Text]] = None, delete_all : typing___Optional[builtin___bool] = None, namespace : typing___Optional[typing___Text] = None, + filter : typing___Optional[google___protobuf___struct_pb2___Struct] = None, ) -> None: ... - def ClearField(self, field_name: typing_extensions___Literal[u"delete_all",b"delete_all",u"ids",b"ids",u"namespace",b"namespace"]) -> None: ... + def HasField(self, field_name: typing_extensions___Literal[u"filter",b"filter"]) -> builtin___bool: ... + def ClearField(self, field_name: typing_extensions___Literal[u"delete_all",b"delete_all",u"filter",b"filter",u"ids",b"ids",u"namespace",b"namespace"]) -> None: ... type___DeleteRequest = DeleteRequest class DeleteResponse(google___protobuf___message___Message): diff --git a/pinecone/index.py b/pinecone/index.py index 158a8e90..8ff0bf60 100644 --- a/pinecone/index.py +++ b/pinecone/index.py @@ -7,7 +7,8 @@ from pinecone import Config from pinecone.core.client import ApiClient, Configuration from .core.client.models import FetchResponse, ProtobufAny, QueryRequest, QueryResponse, QueryVector, RpcStatus, \ - ScoredVector, SingleQueryResults, DescribeIndexStatsResponse, UpsertRequest, UpsertResponse, UpdateRequest, Vector + ScoredVector, SingleQueryResults, DescribeIndexStatsResponse, UpsertRequest, UpsertResponse, UpdateRequest, \ + Vector, DeleteRequest, UpdateRequest from pinecone.core.client.api.vector_operations_api import VectorOperationsApi from pinecone.core.utils import fix_tuple_length, get_user_agent import copy @@ -15,7 +16,7 @@ __all__ = [ "Index", "FetchResponse", "ProtobufAny", "QueryRequest", "QueryResponse", "QueryVector", "RpcStatus", "ScoredVector", "SingleQueryResults", "DescribeIndexStatsResponse", "UpsertRequest", "UpsertResponse", - "UpdateRequest", "Vector" + "UpdateRequest", "Vector", "DeleteRequest", "UpdateRequest" ] from .core.utils.error_handling import validate_and_convert_errors @@ -68,7 +69,15 @@ def _vector_transform(item): @validate_and_convert_errors def delete(self, *args, **kwargs): - return self._vector_api.delete(*args, **kwargs) + _check_type = kwargs.pop('_check_type', False) + return self._vector_api.delete( + DeleteRequest( + *args, + **{k: v for k, v in kwargs.items() if k not in _OPENAPI_ENDPOINT_PARAMS}, + _check_type=_check_type + ), + **{k: v for k, v in kwargs.items() if k in _OPENAPI_ENDPOINT_PARAMS} + ) @validate_and_convert_errors def fetch(self, *args, **kwargs): diff --git a/specs/pinecone_api.json b/specs/pinecone_api.json index d21e1b12..0549f56b 100644 --- a/specs/pinecone_api.json +++ b/specs/pinecone_api.json @@ -121,7 +121,7 @@ "delete": { "summary": "Delete", "description": "The `Delete` operation deletes vectors, by id, from a single namespace.\nYou can delete items by their id, from a single namespace.", - "operationId": "delete", + "operationId": "delete1", "responses": { "200": { "description": "A successful response.", @@ -180,6 +180,46 @@ "tags": [ "Vector Operations" ] + }, + "post": { + "summary": "Delete", + "description": "The `Delete` operation deletes vectors, by id, from a single namespace.\nYou can delete items by their id, from a single namespace.", + "operationId": "delete", + "responses": { + "200": { + "description": "A successful response.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DeleteResponse" + } + } + } + }, + "default": { + "description": "An unexpected error response.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/rpcStatus" + } + } + } + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DeleteRequest" + } + } + }, + "required": true + }, + "tags": [ + "Vector Operations" + ] } }, "/vectors/fetch": { @@ -529,6 +569,39 @@ }, "components": { "schemas": { + "DeleteRequest": { + "type": "object", + "properties": { + "ids": { + "type": "array", + "example": [ + "id-0", + "id-1" + ], + "items": { + "type": "string" + }, + "description": "Vectors to delete.", + "maxLength": 1000, + "minLength": 1 + }, + "deleteAll": { + "type": "boolean", + "example": true, + "description": "This indicates that all vectors in the index namespace should be deleted." + }, + "namespace": { + "type": "string", + "example": "example-namespace", + "description": "The namespace to delete vectors from, if applicable." + }, + "filter": { + "type": "object", + "title": "If specified, the metadata filter here will be used to select the vectors to delete. This is mutually exclusive\nwith specifying ids to delete in the ids param or using delete_all=True.\nSee https://www.pinecone.io/docs/metadata-filtering/`" + } + }, + "description": "The request for the `Delete` operation." + }, "DeleteResponse": { "type": "object", "description": "The response for the `Delete` operation." diff --git a/specs/vector_service.openapi.json b/specs/vector_service.openapi.json index e82b0364..9a044c94 100644 --- a/specs/vector_service.openapi.json +++ b/specs/vector_service.openapi.json @@ -152,6 +152,46 @@ "tags": [ "Vector Operations" ] + }, + "post": { + "summary": "Delete", + "description": "The `Delete` operation deletes vectors, by id, from a single namespace.\nYou can delete items by their id, from a single namespace.", + "operationId": "delete", + "responses": { + "200": { + "description": "A successful response.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DeleteResponse" + } + } + } + }, + "default": { + "description": "An unexpected error response.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/rpcStatus" + } + } + } + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DeleteRequest" + } + } + }, + "required": true + }, + "tags": [ + "Vector Operations" + ] } }, "/vectors/fetch": { @@ -329,6 +369,39 @@ } }, "schemas": { + "DeleteRequest": { + "type": "object", + "properties": { + "ids": { + "type": "array", + "example": [ + "id-0", + "id-1" + ], + "items": { + "type": "string" + }, + "description": "Vectors to delete.", + "maxLength": 1000, + "minLength": 1 + }, + "deleteAll": { + "type": "boolean", + "example": true, + "description": "This indicates that all vectors in the index namespace should be deleted." + }, + "namespace": { + "type": "string", + "example": "example-namespace", + "description": "The namespace to delete vectors from, if applicable." + }, + "filter": { + "type": "object", + "title": "If specified, the metadata filter here will be used to select the vectors to delete. This is mutually exclusive\nwith specifying ids to delete in the ids param or using delete_all=True.\nSee https://www.pinecone.io/docs/metadata-filtering/`" + } + }, + "description": "The request for the `Delete` operation." + }, "DeleteResponse": { "type": "object", "description": "The response for the `Delete` operation." From 8433d8b2d0378b7589e5d95480240ed40ca22acb Mon Sep 17 00:00:00 2001 From: Benjamin Ran Date: Mon, 18 Apr 2022 15:41:37 +0300 Subject: [PATCH 2/5] Update changelog and vector delete docs --- CHANGELOG.md | 4 ++ .../core/client/api/vector_operations_api.py | 2 +- pinecone/core/client/model/delete_request.py | 8 +-- pinecone/core/client/model/query_request.py | 4 +- .../core/grpc/protos/vector_service_pb2.py | 66 +++++++++---------- specs/pinecone_api.json | 10 +-- specs/vector_service.openapi.json | 10 +-- 7 files changed, 56 insertions(+), 48 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4156d403..8215ed96 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,10 @@ # Changelog ## Unreleased Changes +### Changed +- Added support for deleting vectors by metadata filter. The pinecone.Index.delete() api now accepts an additional filter= parameter which takes metadata filter expression equivalent to what query() supports. + - Internally these requests are now sent as POST requests, though the previous DELETE api is still supported. + ## [2.0.9](https://github.com/pinecone-io/pinecone-python-client/compare/v2.0.8...v2.0.9) ### Changed - Added [update](https://www.pinecone.io/docs/api/operation/update/) API. Allows updates to a vector and it's metadata. diff --git a/pinecone/core/client/api/vector_operations_api.py b/pinecone/core/client/api/vector_operations_api.py index edd9906a..ecf9dd3e 100644 --- a/pinecone/core/client/api/vector_operations_api.py +++ b/pinecone/core/client/api/vector_operations_api.py @@ -185,7 +185,7 @@ def __delete1( Keyword Args: ids ([str]): Vectors to delete.. [optional] - delete_all (bool): This indicates that all vectors in the index namespace should be deleted.. [optional] + delete_all (bool): This indicates that all vectors in the index namespace should be deleted.. [optional] if omitted the server will use the default value of False namespace (str): The namespace to delete vectors from, if applicable.. [optional] _return_http_data_only (bool): response data without head status code and headers. Default is True. diff --git a/pinecone/core/client/model/delete_request.py b/pinecone/core/client/model/delete_request.py index 5a2ea9ee..2e21118c 100644 --- a/pinecone/core/client/model/delete_request.py +++ b/pinecone/core/client/model/delete_request.py @@ -148,9 +148,9 @@ def _from_openapi_data(cls, *args, **kwargs): # noqa: E501 through its discriminator because we passed in _visited_composed_classes = (Animal,) ids ([str]): Vectors to delete.. [optional] # noqa: E501 - delete_all (bool): This indicates that all vectors in the index namespace should be deleted.. [optional] # noqa: E501 + delete_all (bool): This indicates that all vectors in the index namespace should be deleted.. [optional] if omitted the server will use the default value of False # noqa: E501 namespace (str): The namespace to delete vectors from, if applicable.. [optional] # noqa: E501 - filter ({str: (bool, date, datetime, dict, float, int, list, str, none_type)}): [optional] # noqa: E501 + filter ({str: (bool, date, datetime, dict, float, int, list, str, none_type)}): If specified, the metadata filter here will be used to select the vectors to delete. This is mutually exclusive with specifying ids to delete in the ids param or using delete_all=True. See https://www.pinecone.io/docs/metadata-filtering/`.. [optional] # noqa: E501 """ _check_type = kwargs.pop('_check_type', True) @@ -233,9 +233,9 @@ def __init__(self, *args, **kwargs): # noqa: E501 through its discriminator because we passed in _visited_composed_classes = (Animal,) ids ([str]): Vectors to delete.. [optional] # noqa: E501 - delete_all (bool): This indicates that all vectors in the index namespace should be deleted.. [optional] # noqa: E501 + delete_all (bool): This indicates that all vectors in the index namespace should be deleted.. [optional] if omitted the server will use the default value of False # noqa: E501 namespace (str): The namespace to delete vectors from, if applicable.. [optional] # noqa: E501 - filter ({str: (bool, date, datetime, dict, float, int, list, str, none_type)}): [optional] # noqa: E501 + filter ({str: (bool, date, datetime, dict, float, int, list, str, none_type)}): If specified, the metadata filter here will be used to select the vectors to delete. This is mutually exclusive with specifying ids to delete in the ids param or using delete_all=True. See https://www.pinecone.io/docs/metadata-filtering/`.. [optional] # noqa: E501 """ _check_type = kwargs.pop('_check_type', True) diff --git a/pinecone/core/client/model/query_request.py b/pinecone/core/client/model/query_request.py index de3423a5..7f3862f4 100644 --- a/pinecone/core/client/model/query_request.py +++ b/pinecone/core/client/model/query_request.py @@ -166,7 +166,7 @@ def _from_openapi_data(cls, top_k, queries, *args, **kwargs): # noqa: E501 through its discriminator because we passed in _visited_composed_classes = (Animal,) namespace (str): The namespace to query.. [optional] # noqa: E501 - filter ({str: (bool, date, datetime, dict, float, int, list, str, none_type)}): [optional] # noqa: E501 + filter ({str: (bool, date, datetime, dict, float, int, list, str, none_type)}): The filter to apply if no filter is specified in `QueryVector. You can use vector metadata to limit your search. See https://www.pinecone.io/docs/metadata-filtering/`.. [optional] # noqa: E501 include_values (bool): Indicates whether vector values are included in the response.. [optional] if omitted the server will use the default value of False # noqa: E501 include_metadata (bool): Indicates whether metadata is included in the response as well as the ids.. [optional] if omitted the server will use the default value of False # noqa: E501 """ @@ -257,7 +257,7 @@ def __init__(self, top_k, queries, *args, **kwargs): # noqa: E501 through its discriminator because we passed in _visited_composed_classes = (Animal,) namespace (str): The namespace to query.. [optional] # noqa: E501 - filter ({str: (bool, date, datetime, dict, float, int, list, str, none_type)}): [optional] # noqa: E501 + filter ({str: (bool, date, datetime, dict, float, int, list, str, none_type)}): The filter to apply if no filter is specified in `QueryVector. You can use vector metadata to limit your search. See https://www.pinecone.io/docs/metadata-filtering/`.. [optional] # noqa: E501 include_values (bool): Indicates whether vector values are included in the response.. [optional] if omitted the server will use the default value of False # noqa: E501 include_metadata (bool): Indicates whether metadata is included in the response as well as the ids.. [optional] if omitted the server will use the default value of False # noqa: E501 """ diff --git a/pinecone/core/grpc/protos/vector_service_pb2.py b/pinecone/core/grpc/protos/vector_service_pb2.py index 79f5da1d..42890deb 100644 --- a/pinecone/core/grpc/protos/vector_service_pb2.py +++ b/pinecone/core/grpc/protos/vector_service_pb2.py @@ -28,7 +28,7 @@ syntax='proto3', serialized_options=b'\n\021io.pinecone.protoP\001Z/github.com/pinecone-io/new-go-pinecone/pinecone\222A\366\002\022K\n\014Pinecone API\";\n\017Pinecone.io Ops\022\023https://pinecone.io\032\023support@pinecone.io\0329{index_name}-{project_name}.svc.{environment}.pinecone.io*\001\0022\020application/json:\020application/jsonZx\nv\n\nApiKeyAuth\022h\010\002\022YAn API Key is required to call Pinecone APIs. Get yours at https://www.pinecone.io/start/\032\007Api-Key \002b\020\n\016\n\nApiKeyAuth\022\000r9\n\031More Pinecone.io API docs\022\034https://www.pinecone.io/docs', create_key=_descriptor._internal_create_key, - serialized_pb=b'\n\x14vector_service.proto\x1a\x1cgoogle/protobuf/struct.proto\x1a\x1cgoogle/api/annotations.proto\x1a\x1fgoogle/api/field_behavior.proto\x1a\x1egoogle/rpc/error_details.proto\x1a.protoc-gen-openapiv2/options/annotations.proto\"\xd7\x01\n\x06Vector\x12,\n\x02id\x18\x01 \x01(\tB \x92\x41\x1aJ\x12\"example-vector-1\"x\x80\x04\x80\x01\x01\xe0\x41\x02\x12G\n\x06values\x18\x02 \x03(\x02\x42\x37\x92\x41\x31J([0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8]x\xa0\x9c\x01\x80\x01\x01\xe0\x41\x02\x12V\n\x08metadata\x18\x03 \x01(\x0b\x32\x17.google.protobuf.StructB+\x92\x41(J&{\"genre\": \"documentary\", \"year\": 2019}\"\xed\x01\n\x0cScoredVector\x12,\n\x02id\x18\x01 \x01(\tB \x92\x41\x1aJ\x12\"example-vector-1\"x\x80\x04\x80\x01\x01\xe0\x41\x02\x12\x18\n\x05score\x18\x02 \x01(\x02\x42\t\x92\x41\x06J\x04\x30.08\x12=\n\x06values\x18\x03 \x03(\x02\x42-\x92\x41*J([0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8]\x12V\n\x08metadata\x18\x04 \x01(\x0b\x32\x17.google.protobuf.StructB+\x92\x41(J&{\"genre\": \"documentary\", \"year\": 2019}\"d\n\rUpsertRequest\x12&\n\x07vectors\x18\x01 \x03(\x0b\x32\x07.VectorB\x0c\x92\x41\x06x\xe8\x07\x80\x01\x01\xe0\x41\x02\x12+\n\tnamespace\x18\x02 \x01(\tB\x18\x92\x41\x15J\x13\"example-namespace\"\"1\n\x0eUpsertResponse\x12\x1f\n\x0eupserted_count\x18\x01 \x01(\rB\x07\x92\x41\x04J\x02\x31\x30\"\xae\x01\n\rDeleteRequest\x12(\n\x03ids\x18\x01 \x03(\tB\x1b\x92\x41\x18J\x10[\"id-0\", \"id-1\"]x\xe8\x07\x80\x01\x01\x12\x1d\n\ndelete_all\x18\x02 \x01(\x08\x42\t\x92\x41\x06J\x04true\x12+\n\tnamespace\x18\x03 \x01(\tB\x18\x92\x41\x15J\x13\"example-namespace\"\x12\'\n\x06\x66ilter\x18\x04 \x01(\x0b\x32\x17.google.protobuf.Struct\"\x10\n\x0e\x44\x65leteResponse\"h\n\x0c\x46\x65tchRequest\x12+\n\x03ids\x18\x01 \x03(\tB\x1e\x92\x41\x18J\x10[\"id-0\", \"id-1\"]x\xe8\x07\x80\x01\x01\xe0\x41\x02\x12+\n\tnamespace\x18\x02 \x01(\tB\x18\x92\x41\x15J\x13\"example-namespace\"\"\xa3\x01\n\rFetchResponse\x12,\n\x07vectors\x18\x01 \x03(\x0b\x32\x1b.FetchResponse.VectorsEntry\x12+\n\tnamespace\x18\x02 \x01(\tB\x18\x92\x41\x15J\x13\"example-namespace\"\x1a\x37\n\x0cVectorsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x16\n\x05value\x18\x02 \x01(\x0b\x32\x07.Vector:\x02\x38\x01\"\xaa\x02\n\x0bQueryVector\x12G\n\x06values\x18\x01 \x03(\x02\x42\x37\x92\x41\x31J([0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8]x\xa0\x9c\x01\x80\x01\x01\xe0\x41\x02\x12(\n\x05top_k\x18\x02 \x01(\rB\x19\x92\x41\x16J\x02\x31\x30Y\x00\x00\x00\x00\x00\x88\xc3@i\x00\x00\x00\x00\x00\x00\xf0?\x12+\n\tnamespace\x18\x03 \x01(\tB\x18\x92\x41\x15J\x13\"example-namespace\"\x12{\n\x06\x66ilter\x18\x04 \x01(\x0b\x32\x17.google.protobuf.StructBR\x92\x41OJM{\"genre\": {\"$in\": [\"comedy\", \"documentary\", \"drama\"]}, \"year\": {\"$eq\": 2019}}\"\xe7\x02\n\x0cQueryRequest\x12+\n\tnamespace\x18\x01 \x01(\tB\x18\x92\x41\x15J\x13\"example-namespace\"\x12+\n\x05top_k\x18\x02 \x01(\rB\x1c\x92\x41\x16J\x02\x31\x30Y\x00\x00\x00\x00\x00\x88\xc3@i\x00\x00\x00\x00\x00\x00\xf0?\xe0\x41\x02\x12{\n\x06\x66ilter\x18\x03 \x01(\x0b\x32\x17.google.protobuf.StructBR\x92\x41OJM{\"genre\": {\"$in\": [\"comedy\", \"documentary\", \"drama\"]}, \"year\": {\"$eq\": 2019}}\x12(\n\x0einclude_values\x18\x04 \x01(\x08\x42\x10\x92\x41\r:\x05\x66\x61lseJ\x04true\x12*\n\x10include_metadata\x18\x05 \x01(\x08\x42\x10\x92\x41\r:\x05\x66\x61lseJ\x04true\x12*\n\x07queries\x18\x06 \x03(\x0b\x32\x0c.QueryVectorB\x0b\x92\x41\x05x\n\x80\x01\x01\xe0\x41\x02\"a\n\x12SingleQueryResults\x12\x1e\n\x07matches\x18\x01 \x03(\x0b\x32\r.ScoredVector\x12+\n\tnamespace\x18\x02 \x01(\tB\x18\x92\x41\x15J\x13\"example-namespace\"\"5\n\rQueryResponse\x12$\n\x07results\x18\x01 \x03(\x0b\x32\x13.SingleQueryResults\"\x8c\x02\n\rUpdateRequest\x12,\n\x02id\x18\x01 \x01(\tB \x92\x41\x1aJ\x12\"example-vector-1\"x\x80\x04\x80\x01\x01\xe0\x41\x02\x12\x44\n\x06values\x18\x02 \x03(\x02\x42\x34\x92\x41\x31J([0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8]x\xa0\x9c\x01\x80\x01\x01\x12Z\n\x0cset_metadata\x18\x03 \x01(\x0b\x32\x17.google.protobuf.StructB+\x92\x41(J&{\"genre\": \"documentary\", \"year\": 2019}\x12+\n\tnamespace\x18\x04 \x01(\tB\x18\x92\x41\x15J\x13\"example-namespace\"\"\x10\n\x0eUpdateResponse\"\x1b\n\x19\x44\x65scribeIndexStatsRequest\"4\n\x10NamespaceSummary\x12 \n\x0cvector_count\x18\x01 \x01(\rB\n\x92\x41\x07J\x05\x35\x30\x30\x30\x30\"\xf4\x02\n\x1a\x44\x65scribeIndexStatsResponse\x12?\n\nnamespaces\x18\x01 \x03(\x0b\x32+.DescribeIndexStatsResponse.NamespacesEntry\x12\x1c\n\tdimension\x18\x02 \x01(\rB\t\x92\x41\x06J\x04\x31\x30\x32\x34\x12!\n\x0eindex_fullness\x18\x03 \x01(\x02\x42\t\x92\x41\x06J\x04\x30.42\x1a\x44\n\x0fNamespacesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12 \n\x05value\x18\x02 \x01(\x0b\x32\x11.NamespaceSummary:\x02\x38\x01:\x8d\x01\x92\x41\x89\x01\x32\x86\x01{\"namespaces\": {\"\": {\"vectorCount\": 50000}, \"example-namespace-2\": {\"vectorCount\": 30000}}, \"dimension\": 1024, \"index_fullness\": 0.42}2\xa1\x05\n\rVectorService\x12\x63\n\x06Upsert\x12\x0e.UpsertRequest\x1a\x0f.UpsertResponse\"8\x82\xd3\xe4\x93\x02\x14\"\x0f/vectors/upsert:\x01*\x92\x41\x1b\n\x11Vector Operations*\x06upsert\x12v\n\x06\x44\x65lete\x12\x0e.DeleteRequest\x1a\x0f.DeleteResponse\"K\x82\xd3\xe4\x93\x02\'\"\x0f/vectors/delete:\x01*Z\x11*\x0f/vectors/delete\x92\x41\x1b\n\x11Vector Operations*\x06\x64\x65lete\x12[\n\x05\x46\x65tch\x12\r.FetchRequest\x1a\x0e.FetchResponse\"3\x82\xd3\xe4\x93\x02\x10\x12\x0e/vectors/fetch\x92\x41\x1a\n\x11Vector Operations*\x05\x66\x65tch\x12V\n\x05Query\x12\r.QueryRequest\x1a\x0e.QueryResponse\".\x82\xd3\xe4\x93\x02\x0b\"\x06/query:\x01*\x92\x41\x1a\n\x11Vector Operations*\x05query\x12\x63\n\x06Update\x12\x0e.UpdateRequest\x1a\x0f.UpdateResponse\"8\x82\xd3\xe4\x93\x02\x14\"\x0f/vectors/update:\x01*\x92\x41\x1b\n\x11Vector Operations*\x06update\x12\x98\x01\n\x12\x44\x65scribeIndexStats\x12\x1a.DescribeIndexStatsRequest\x1a\x1b.DescribeIndexStatsResponse\"I\x82\xd3\xe4\x93\x02\x17\x12\x15/describe_index_stats\x92\x41)\n\x11Vector Operations*\x14\x64\x65scribe_index_statsB\xc0\x03\n\x11io.pinecone.protoP\x01Z/github.com/pinecone-io/new-go-pinecone/pinecone\x92\x41\xf6\x02\x12K\n\x0cPinecone API\";\n\x0fPinecone.io Ops\x12\x13https://pinecone.io\x1a\x13support@pinecone.io\x1a\x39{index_name}-{project_name}.svc.{environment}.pinecone.io*\x01\x02\x32\x10\x61pplication/json:\x10\x61pplication/jsonZx\nv\n\nApiKeyAuth\x12h\x08\x02\x12YAn API Key is required to call Pinecone APIs. Get yours at https://www.pinecone.io/start/\x1a\x07\x41pi-Key \x02\x62\x10\n\x0e\n\nApiKeyAuth\x12\x00r9\n\x19More Pinecone.io API docs\x12\x1chttps://www.pinecone.io/docsb\x06proto3' + serialized_pb=b'\n\x14vector_service.proto\x1a\x1cgoogle/protobuf/struct.proto\x1a\x1cgoogle/api/annotations.proto\x1a\x1fgoogle/api/field_behavior.proto\x1a\x1egoogle/rpc/error_details.proto\x1a.protoc-gen-openapiv2/options/annotations.proto\"\xd7\x01\n\x06Vector\x12,\n\x02id\x18\x01 \x01(\tB \x92\x41\x1aJ\x12\"example-vector-1\"x\x80\x04\x80\x01\x01\xe0\x41\x02\x12G\n\x06values\x18\x02 \x03(\x02\x42\x37\x92\x41\x31J([0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8]x\xa0\x9c\x01\x80\x01\x01\xe0\x41\x02\x12V\n\x08metadata\x18\x03 \x01(\x0b\x32\x17.google.protobuf.StructB+\x92\x41(J&{\"genre\": \"documentary\", \"year\": 2019}\"\xed\x01\n\x0cScoredVector\x12,\n\x02id\x18\x01 \x01(\tB \x92\x41\x1aJ\x12\"example-vector-1\"x\x80\x04\x80\x01\x01\xe0\x41\x02\x12\x18\n\x05score\x18\x02 \x01(\x02\x42\t\x92\x41\x06J\x04\x30.08\x12=\n\x06values\x18\x03 \x03(\x02\x42-\x92\x41*J([0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8]\x12V\n\x08metadata\x18\x04 \x01(\x0b\x32\x17.google.protobuf.StructB+\x92\x41(J&{\"genre\": \"documentary\", \"year\": 2019}\"d\n\rUpsertRequest\x12&\n\x07vectors\x18\x01 \x03(\x0b\x32\x07.VectorB\x0c\x92\x41\x06x\xe8\x07\x80\x01\x01\xe0\x41\x02\x12+\n\tnamespace\x18\x02 \x01(\tB\x18\x92\x41\x15J\x13\"example-namespace\"\"1\n\x0eUpsertResponse\x12\x1f\n\x0eupserted_count\x18\x01 \x01(\rB\x07\x92\x41\x04J\x02\x31\x30\"\xb6\x01\n\rDeleteRequest\x12(\n\x03ids\x18\x01 \x03(\tB\x1b\x92\x41\x18J\x10[\"id-0\", \"id-1\"]x\xe8\x07\x80\x01\x01\x12%\n\ndelete_all\x18\x02 \x01(\x08\x42\x11\x92\x41\x0e:\x05\x66\x61lseJ\x05\x66\x61lse\x12+\n\tnamespace\x18\x03 \x01(\tB\x18\x92\x41\x15J\x13\"example-namespace\"\x12\'\n\x06\x66ilter\x18\x04 \x01(\x0b\x32\x17.google.protobuf.Struct\"\x10\n\x0e\x44\x65leteResponse\"h\n\x0c\x46\x65tchRequest\x12+\n\x03ids\x18\x01 \x03(\tB\x1e\x92\x41\x18J\x10[\"id-0\", \"id-1\"]x\xe8\x07\x80\x01\x01\xe0\x41\x02\x12+\n\tnamespace\x18\x02 \x01(\tB\x18\x92\x41\x15J\x13\"example-namespace\"\"\xa3\x01\n\rFetchResponse\x12,\n\x07vectors\x18\x01 \x03(\x0b\x32\x1b.FetchResponse.VectorsEntry\x12+\n\tnamespace\x18\x02 \x01(\tB\x18\x92\x41\x15J\x13\"example-namespace\"\x1a\x37\n\x0cVectorsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x16\n\x05value\x18\x02 \x01(\x0b\x32\x07.Vector:\x02\x38\x01\"\xaa\x02\n\x0bQueryVector\x12G\n\x06values\x18\x01 \x03(\x02\x42\x37\x92\x41\x31J([0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8]x\xa0\x9c\x01\x80\x01\x01\xe0\x41\x02\x12(\n\x05top_k\x18\x02 \x01(\rB\x19\x92\x41\x16J\x02\x31\x30Y\x00\x00\x00\x00\x00\x88\xc3@i\x00\x00\x00\x00\x00\x00\xf0?\x12+\n\tnamespace\x18\x03 \x01(\tB\x18\x92\x41\x15J\x13\"example-namespace\"\x12{\n\x06\x66ilter\x18\x04 \x01(\x0b\x32\x17.google.protobuf.StructBR\x92\x41OJM{\"genre\": {\"$in\": [\"comedy\", \"documentary\", \"drama\"]}, \"year\": {\"$eq\": 2019}}\"\xe7\x02\n\x0cQueryRequest\x12+\n\tnamespace\x18\x01 \x01(\tB\x18\x92\x41\x15J\x13\"example-namespace\"\x12+\n\x05top_k\x18\x02 \x01(\rB\x1c\x92\x41\x16J\x02\x31\x30Y\x00\x00\x00\x00\x00\x88\xc3@i\x00\x00\x00\x00\x00\x00\xf0?\xe0\x41\x02\x12{\n\x06\x66ilter\x18\x03 \x01(\x0b\x32\x17.google.protobuf.StructBR\x92\x41OJM{\"genre\": {\"$in\": [\"comedy\", \"documentary\", \"drama\"]}, \"year\": {\"$eq\": 2019}}\x12(\n\x0einclude_values\x18\x04 \x01(\x08\x42\x10\x92\x41\r:\x05\x66\x61lseJ\x04true\x12*\n\x10include_metadata\x18\x05 \x01(\x08\x42\x10\x92\x41\r:\x05\x66\x61lseJ\x04true\x12*\n\x07queries\x18\x06 \x03(\x0b\x32\x0c.QueryVectorB\x0b\x92\x41\x05x\n\x80\x01\x01\xe0\x41\x02\"a\n\x12SingleQueryResults\x12\x1e\n\x07matches\x18\x01 \x03(\x0b\x32\r.ScoredVector\x12+\n\tnamespace\x18\x02 \x01(\tB\x18\x92\x41\x15J\x13\"example-namespace\"\"5\n\rQueryResponse\x12$\n\x07results\x18\x01 \x03(\x0b\x32\x13.SingleQueryResults\"\x8c\x02\n\rUpdateRequest\x12,\n\x02id\x18\x01 \x01(\tB \x92\x41\x1aJ\x12\"example-vector-1\"x\x80\x04\x80\x01\x01\xe0\x41\x02\x12\x44\n\x06values\x18\x02 \x03(\x02\x42\x34\x92\x41\x31J([0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8]x\xa0\x9c\x01\x80\x01\x01\x12Z\n\x0cset_metadata\x18\x03 \x01(\x0b\x32\x17.google.protobuf.StructB+\x92\x41(J&{\"genre\": \"documentary\", \"year\": 2019}\x12+\n\tnamespace\x18\x04 \x01(\tB\x18\x92\x41\x15J\x13\"example-namespace\"\"\x10\n\x0eUpdateResponse\"\x1b\n\x19\x44\x65scribeIndexStatsRequest\"4\n\x10NamespaceSummary\x12 \n\x0cvector_count\x18\x01 \x01(\rB\n\x92\x41\x07J\x05\x35\x30\x30\x30\x30\"\xf4\x02\n\x1a\x44\x65scribeIndexStatsResponse\x12?\n\nnamespaces\x18\x01 \x03(\x0b\x32+.DescribeIndexStatsResponse.NamespacesEntry\x12\x1c\n\tdimension\x18\x02 \x01(\rB\t\x92\x41\x06J\x04\x31\x30\x32\x34\x12!\n\x0eindex_fullness\x18\x03 \x01(\x02\x42\t\x92\x41\x06J\x04\x30.42\x1a\x44\n\x0fNamespacesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12 \n\x05value\x18\x02 \x01(\x0b\x32\x11.NamespaceSummary:\x02\x38\x01:\x8d\x01\x92\x41\x89\x01\x32\x86\x01{\"namespaces\": {\"\": {\"vectorCount\": 50000}, \"example-namespace-2\": {\"vectorCount\": 30000}}, \"dimension\": 1024, \"index_fullness\": 0.42}2\xa1\x05\n\rVectorService\x12\x63\n\x06Upsert\x12\x0e.UpsertRequest\x1a\x0f.UpsertResponse\"8\x82\xd3\xe4\x93\x02\x14\"\x0f/vectors/upsert:\x01*\x92\x41\x1b\n\x11Vector Operations*\x06upsert\x12v\n\x06\x44\x65lete\x12\x0e.DeleteRequest\x1a\x0f.DeleteResponse\"K\x82\xd3\xe4\x93\x02\'\"\x0f/vectors/delete:\x01*Z\x11*\x0f/vectors/delete\x92\x41\x1b\n\x11Vector Operations*\x06\x64\x65lete\x12[\n\x05\x46\x65tch\x12\r.FetchRequest\x1a\x0e.FetchResponse\"3\x82\xd3\xe4\x93\x02\x10\x12\x0e/vectors/fetch\x92\x41\x1a\n\x11Vector Operations*\x05\x66\x65tch\x12V\n\x05Query\x12\r.QueryRequest\x1a\x0e.QueryResponse\".\x82\xd3\xe4\x93\x02\x0b\"\x06/query:\x01*\x92\x41\x1a\n\x11Vector Operations*\x05query\x12\x63\n\x06Update\x12\x0e.UpdateRequest\x1a\x0f.UpdateResponse\"8\x82\xd3\xe4\x93\x02\x14\"\x0f/vectors/update:\x01*\x92\x41\x1b\n\x11Vector Operations*\x06update\x12\x98\x01\n\x12\x44\x65scribeIndexStats\x12\x1a.DescribeIndexStatsRequest\x1a\x1b.DescribeIndexStatsResponse\"I\x82\xd3\xe4\x93\x02\x17\x12\x15/describe_index_stats\x92\x41)\n\x11Vector Operations*\x14\x64\x65scribe_index_statsB\xc0\x03\n\x11io.pinecone.protoP\x01Z/github.com/pinecone-io/new-go-pinecone/pinecone\x92\x41\xf6\x02\x12K\n\x0cPinecone API\";\n\x0fPinecone.io Ops\x12\x13https://pinecone.io\x1a\x13support@pinecone.io\x1a\x39{index_name}-{project_name}.svc.{environment}.pinecone.io*\x01\x02\x32\x10\x61pplication/json:\x10\x61pplication/jsonZx\nv\n\nApiKeyAuth\x12h\x08\x02\x12YAn API Key is required to call Pinecone APIs. Get yours at https://www.pinecone.io/start/\x1a\x07\x41pi-Key \x02\x62\x10\n\x0e\n\nApiKeyAuth\x12\x00r9\n\x19More Pinecone.io API docs\x12\x1chttps://www.pinecone.io/docsb\x06proto3' , dependencies=[google_dot_protobuf_dot_struct__pb2.DESCRIPTOR,google_dot_api_dot_annotations__pb2.DESCRIPTOR,google_dot_api_dot_field__behavior__pb2.DESCRIPTOR,google_dot_rpc_dot_error__details__pb2.DESCRIPTOR,protoc__gen__openapiv2_dot_options_dot_annotations__pb2.DESCRIPTOR,]) @@ -226,7 +226,7 @@ has_default_value=False, default_value=False, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, - serialized_options=b'\222A\006J\004true', file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + serialized_options=b'\222A\016:\005falseJ\005false', file=DESCRIPTOR, create_key=_descriptor._internal_create_key), _descriptor.FieldDescriptor( name='namespace', full_name='DeleteRequest.namespace', index=2, number=3, type=9, cpp_type=9, label=1, @@ -254,7 +254,7 @@ oneofs=[ ], serialized_start=809, - serialized_end=983, + serialized_end=991, ) @@ -278,8 +278,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=985, - serialized_end=1001, + serialized_start=993, + serialized_end=1009, ) @@ -317,8 +317,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1003, - serialized_end=1107, + serialized_start=1011, + serialized_end=1115, ) @@ -356,8 +356,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1218, - serialized_end=1273, + serialized_start=1226, + serialized_end=1281, ) _FETCHRESPONSE = _descriptor.Descriptor( @@ -394,8 +394,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1110, - serialized_end=1273, + serialized_start=1118, + serialized_end=1281, ) @@ -447,8 +447,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1276, - serialized_end=1574, + serialized_start=1284, + serialized_end=1582, ) @@ -514,8 +514,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1577, - serialized_end=1936, + serialized_start=1585, + serialized_end=1944, ) @@ -553,8 +553,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1938, - serialized_end=2035, + serialized_start=1946, + serialized_end=2043, ) @@ -585,8 +585,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2037, - serialized_end=2090, + serialized_start=2045, + serialized_end=2098, ) @@ -638,8 +638,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2093, - serialized_end=2361, + serialized_start=2101, + serialized_end=2369, ) @@ -663,8 +663,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2363, - serialized_end=2379, + serialized_start=2371, + serialized_end=2387, ) @@ -688,8 +688,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2381, - serialized_end=2408, + serialized_start=2389, + serialized_end=2416, ) @@ -720,8 +720,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2410, - serialized_end=2462, + serialized_start=2418, + serialized_end=2470, ) @@ -759,8 +759,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2625, - serialized_end=2693, + serialized_start=2633, + serialized_end=2701, ) _DESCRIBEINDEXSTATSRESPONSE = _descriptor.Descriptor( @@ -804,8 +804,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2465, - serialized_end=2837, + serialized_start=2473, + serialized_end=2845, ) _VECTOR.fields_by_name['metadata'].message_type = google_dot_protobuf_dot_struct__pb2._STRUCT @@ -1025,8 +1025,8 @@ index=0, serialized_options=None, create_key=_descriptor._internal_create_key, - serialized_start=2840, - serialized_end=3513, + serialized_start=2848, + serialized_end=3521, methods=[ _descriptor.MethodDescriptor( name='Upsert', diff --git a/specs/pinecone_api.json b/specs/pinecone_api.json index 0549f56b..03f437f7 100644 --- a/specs/pinecone_api.json +++ b/specs/pinecone_api.json @@ -164,7 +164,8 @@ "in": "query", "required": false, "schema": { - "type": "boolean" + "type": "boolean", + "default": "false" } }, { @@ -587,7 +588,8 @@ }, "deleteAll": { "type": "boolean", - "example": true, + "example": false, + "default": "false", "description": "This indicates that all vectors in the index namespace should be deleted." }, "namespace": { @@ -597,7 +599,7 @@ }, "filter": { "type": "object", - "title": "If specified, the metadata filter here will be used to select the vectors to delete. This is mutually exclusive\nwith specifying ids to delete in the ids param or using delete_all=True.\nSee https://www.pinecone.io/docs/metadata-filtering/`" + "description": "If specified, the metadata filter here will be used to select the vectors to delete. This is mutually exclusive\nwith specifying ids to delete in the ids param or using delete_all=True.\nSee https://www.pinecone.io/docs/metadata-filtering/`." } }, "description": "The request for the `Delete` operation." @@ -706,7 +708,7 @@ "$eq": 2019 } }, - "title": "The filter to apply if no filter is specified in `QueryVector. You can use vector metadata to limit your search. See https://www.pinecone.io/docs/metadata-filtering/`" + "description": "The filter to apply if no filter is specified in `QueryVector. You can use vector metadata to limit your search. See https://www.pinecone.io/docs/metadata-filtering/`." }, "includeValues": { "type": "boolean", diff --git a/specs/vector_service.openapi.json b/specs/vector_service.openapi.json index 9a044c94..19fa6c8f 100644 --- a/specs/vector_service.openapi.json +++ b/specs/vector_service.openapi.json @@ -136,7 +136,8 @@ "in": "query", "required": false, "schema": { - "type": "boolean" + "type": "boolean", + "default": "false" } }, { @@ -387,7 +388,8 @@ }, "deleteAll": { "type": "boolean", - "example": true, + "example": false, + "default": "false", "description": "This indicates that all vectors in the index namespace should be deleted." }, "namespace": { @@ -397,7 +399,7 @@ }, "filter": { "type": "object", - "title": "If specified, the metadata filter here will be used to select the vectors to delete. This is mutually exclusive\nwith specifying ids to delete in the ids param or using delete_all=True.\nSee https://www.pinecone.io/docs/metadata-filtering/`" + "description": "If specified, the metadata filter here will be used to select the vectors to delete. This is mutually exclusive\nwith specifying ids to delete in the ids param or using delete_all=True.\nSee https://www.pinecone.io/docs/metadata-filtering/`." } }, "description": "The request for the `Delete` operation." @@ -506,7 +508,7 @@ "$eq": 2019 } }, - "title": "The filter to apply if no filter is specified in `QueryVector. You can use vector metadata to limit your search. See https://www.pinecone.io/docs/metadata-filtering/`" + "description": "The filter to apply if no filter is specified in `QueryVector. You can use vector metadata to limit your search. See https://www.pinecone.io/docs/metadata-filtering/`." }, "includeValues": { "type": "boolean", From 9c423aa87e72cbc585a9b440a70fdcb3b557c60f Mon Sep 17 00:00:00 2001 From: Benjamin Ran Date: Mon, 18 Apr 2022 15:46:46 +0300 Subject: [PATCH 3/5] Fix docs typo --- pinecone/core/client/model/query_request.py | 4 ++-- specs/pinecone_api.json | 2 +- specs/vector_service.openapi.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pinecone/core/client/model/query_request.py b/pinecone/core/client/model/query_request.py index 7f3862f4..448a6cd8 100644 --- a/pinecone/core/client/model/query_request.py +++ b/pinecone/core/client/model/query_request.py @@ -166,7 +166,7 @@ def _from_openapi_data(cls, top_k, queries, *args, **kwargs): # noqa: E501 through its discriminator because we passed in _visited_composed_classes = (Animal,) namespace (str): The namespace to query.. [optional] # noqa: E501 - filter ({str: (bool, date, datetime, dict, float, int, list, str, none_type)}): The filter to apply if no filter is specified in `QueryVector. You can use vector metadata to limit your search. See https://www.pinecone.io/docs/metadata-filtering/`.. [optional] # noqa: E501 + filter ({str: (bool, date, datetime, dict, float, int, list, str, none_type)}): The filter to apply if no filter is specified in `QueryVector. You can use vector metadata to limit your search. See https://www.pinecone.io/docs/metadata-filtering/.. [optional] # noqa: E501 include_values (bool): Indicates whether vector values are included in the response.. [optional] if omitted the server will use the default value of False # noqa: E501 include_metadata (bool): Indicates whether metadata is included in the response as well as the ids.. [optional] if omitted the server will use the default value of False # noqa: E501 """ @@ -257,7 +257,7 @@ def __init__(self, top_k, queries, *args, **kwargs): # noqa: E501 through its discriminator because we passed in _visited_composed_classes = (Animal,) namespace (str): The namespace to query.. [optional] # noqa: E501 - filter ({str: (bool, date, datetime, dict, float, int, list, str, none_type)}): The filter to apply if no filter is specified in `QueryVector. You can use vector metadata to limit your search. See https://www.pinecone.io/docs/metadata-filtering/`.. [optional] # noqa: E501 + filter ({str: (bool, date, datetime, dict, float, int, list, str, none_type)}): The filter to apply if no filter is specified in `QueryVector. You can use vector metadata to limit your search. See https://www.pinecone.io/docs/metadata-filtering/.. [optional] # noqa: E501 include_values (bool): Indicates whether vector values are included in the response.. [optional] if omitted the server will use the default value of False # noqa: E501 include_metadata (bool): Indicates whether metadata is included in the response as well as the ids.. [optional] if omitted the server will use the default value of False # noqa: E501 """ diff --git a/specs/pinecone_api.json b/specs/pinecone_api.json index 03f437f7..e3254314 100644 --- a/specs/pinecone_api.json +++ b/specs/pinecone_api.json @@ -708,7 +708,7 @@ "$eq": 2019 } }, - "description": "The filter to apply if no filter is specified in `QueryVector. You can use vector metadata to limit your search. See https://www.pinecone.io/docs/metadata-filtering/`." + "description": "The filter to apply if no filter is specified in `QueryVector. You can use vector metadata to limit your search. See https://www.pinecone.io/docs/metadata-filtering/." }, "includeValues": { "type": "boolean", diff --git a/specs/vector_service.openapi.json b/specs/vector_service.openapi.json index 19fa6c8f..285ed403 100644 --- a/specs/vector_service.openapi.json +++ b/specs/vector_service.openapi.json @@ -508,7 +508,7 @@ "$eq": 2019 } }, - "description": "The filter to apply if no filter is specified in `QueryVector. You can use vector metadata to limit your search. See https://www.pinecone.io/docs/metadata-filtering/`." + "description": "The filter to apply if no filter is specified in `QueryVector. You can use vector metadata to limit your search. See https://www.pinecone.io/docs/metadata-filtering/." }, "includeValues": { "type": "boolean", From ee12062deeb1d65a40898c7ea799d45d3e11efce Mon Sep 17 00:00:00 2001 From: Benjamin Ran Date: Mon, 18 Apr 2022 16:59:23 +0300 Subject: [PATCH 4/5] Add delete filter parsing to grpc_index --- pinecone/core/grpc/index_grpc.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pinecone/core/grpc/index_grpc.py b/pinecone/core/grpc/index_grpc.py index 7c8e39c7..59e7e287 100644 --- a/pinecone/core/grpc/index_grpc.py +++ b/pinecone/core/grpc/index_grpc.py @@ -259,7 +259,8 @@ def _vector_transform(item): return self._wrap_grpc_call(self.stub.Upsert, request, timeout=timeout) def delete(self, *args, async_req=False, **kwargs): - request = DeleteRequest(*args, **kwargs) + _filter = dict_to_proto_struct(kwargs.pop('filter', None)) + request = DeleteRequest(*args, **kwargs, filter=_filter) timeout = kwargs.pop('timeout', None) if async_req: future = self._wrap_grpc_call(self.stub.Delete.future, request, timeout=timeout) From 5bf47e1a6ba5c98fb2073537412480ba39b5d5ea Mon Sep 17 00:00:00 2001 From: Benjamin Ran Date: Mon, 18 Apr 2022 17:16:21 +0300 Subject: [PATCH 5/5] Avoid passing delete filter as {} if no filter passed --- pinecone/core/grpc/index_grpc.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pinecone/core/grpc/index_grpc.py b/pinecone/core/grpc/index_grpc.py index 59e7e287..c70c11ef 100644 --- a/pinecone/core/grpc/index_grpc.py +++ b/pinecone/core/grpc/index_grpc.py @@ -260,7 +260,10 @@ def _vector_transform(item): def delete(self, *args, async_req=False, **kwargs): _filter = dict_to_proto_struct(kwargs.pop('filter', None)) - request = DeleteRequest(*args, **kwargs, filter=_filter) + filter_param = {} + if _filter: + filter_param['filter'] = _filter + request = DeleteRequest(*args, **kwargs, **filter_param) timeout = kwargs.pop('timeout', None) if async_req: future = self._wrap_grpc_call(self.stub.Delete.future, request, timeout=timeout)