pinecone.core.grpc.index_grpc

  1import logging
  2import numbers
  3from abc import ABC, abstractmethod
  4from functools import wraps
  5from importlib.util import find_spec
  6from typing import NamedTuple, Optional, Dict, Iterable, Union, List, Tuple, Any
  7from collections.abc import Mapping
  8
  9import certifi
 10import grpc
 11from google.protobuf import json_format
 12from grpc._channel import _InactiveRpcError, _MultiThreadedRendezvous
 13from tqdm.autonotebook import tqdm
 14import json
 15
 16from pinecone import FetchResponse, QueryResponse, ScoredVector, SingleQueryResults, DescribeIndexStatsResponse
 17from pinecone.config import Config
 18from pinecone.core.client.model.namespace_summary import NamespaceSummary
 19from pinecone.core.client.model.vector import Vector as _Vector
 20from pinecone.core.grpc.protos.vector_service_pb2 import (
 21    Vector as GRPCVector,
 22    QueryVector as GRPCQueryVector,
 23    UpsertRequest,
 24    UpsertResponse,
 25    DeleteRequest,
 26    QueryRequest,
 27    FetchRequest,
 28    UpdateRequest,
 29    DescribeIndexStatsRequest,
 30    DeleteResponse,
 31    UpdateResponse,
 32    SparseValues as GRPCSparseValues,
 33)
 34from pinecone.core.client.model.sparse_values import SparseValues
 35from pinecone.core.grpc.protos.vector_service_pb2_grpc import VectorServiceStub
 36from pinecone.core.grpc.retry import RetryOnRpcErrorClientInterceptor, RetryConfig
 37from pinecone.core.utils import _generate_request_id, dict_to_proto_struct, fix_tuple_length
 38from pinecone.core.utils.constants import (
 39    MAX_MSG_SIZE,
 40    REQUEST_ID,
 41    CLIENT_VERSION,
 42    REQUIRED_VECTOR_FIELDS,
 43    OPTIONAL_VECTOR_FIELDS,
 44)
 45from pinecone.exceptions import PineconeException
 46
 47__all__ = ["GRPCIndex", "GRPCVector", "GRPCQueryVector", "GRPCSparseValues"]
 48
 49_logger = logging.getLogger(__name__)
 50
 51
 52class GRPCClientConfig(NamedTuple):
 53    """
 54    GRPC client configuration options.
 55
 56    :param secure: Whether to use encrypted protocol (SSL). defaults to True.
 57    :type traceroute: bool, optional
 58    :param timeout: defaults to 2 seconds. Fail if gateway doesn't receive response within timeout.
 59    :type timeout: int, optional
 60    :param conn_timeout: defaults to 1. Timeout to retry connection if gRPC is unavailable. 0 is no retry.
 61    :type conn_timeout: int, optional
 62    :param reuse_channel: Whether to reuse the same grpc channel for multiple requests
 63    :type reuse_channel: bool, optional
 64    :param retry_config: RetryConfig indicating how requests should be retried
 65    :type retry_config: RetryConfig, optional
 66    :param grpc_channel_options: A dict of gRPC channel arguments
 67    :type grpc_channel_options: Dict[str, str]
 68    """
 69
 70    secure: bool = True
 71    timeout: int = 20
 72    conn_timeout: int = 1
 73    reuse_channel: bool = True
 74    retry_config: Optional[RetryConfig] = None
 75    grpc_channel_options: Dict[str, str] = None
 76
 77    @classmethod
 78    def _from_dict(cls, kwargs: dict):
 79        cls_kwargs = {kk: vv for kk, vv in kwargs.items() if kk in cls._fields}
 80        return cls(**cls_kwargs)
 81
 82
 83class GRPCIndexBase(ABC):
 84    """
 85    Base class for grpc-based interaction with Pinecone indexes
 86    """
 87
 88    _pool = None
 89
 90    def __init__(
 91        self, index_name: str, channel=None, grpc_config: GRPCClientConfig = None, _endpoint_override: str = None
 92    ):
 93        self.name = index_name
 94
 95        self.grpc_client_config = grpc_config or GRPCClientConfig()
 96        self.retry_config = self.grpc_client_config.retry_config or RetryConfig()
 97        self.fixed_metadata = {"api-key": Config.API_KEY, "service-name": index_name, "client-version": CLIENT_VERSION}
 98        self._endpoint_override = _endpoint_override
 99
100        self.method_config = json.dumps(
101            {
102                "methodConfig": [
103                    {
104                        "name": [{"service": "VectorService.Upsert"}],
105                        "retryPolicy": {
106                            "maxAttempts": 5,
107                            "initialBackoff": "0.1s",
108                            "maxBackoff": "1s",
109                            "backoffMultiplier": 2,
110                            "retryableStatusCodes": ["UNAVAILABLE"],
111                        },
112                    },
113                    {
114                        "name": [{"service": "VectorService"}],
115                        "retryPolicy": {
116                            "maxAttempts": 5,
117                            "initialBackoff": "0.1s",
118                            "maxBackoff": "1s",
119                            "backoffMultiplier": 2,
120                            "retryableStatusCodes": ["UNAVAILABLE"],
121                        },
122                    },
123                ]
124            }
125        )
126
127        self._channel = channel or self._gen_channel()
128        self.stub = self.stub_class(self._channel)
129
130    @property
131    @abstractmethod
132    def stub_class(self):
133        pass
134
135    def _endpoint(self):
136        return (
137            self._endpoint_override
138            if self._endpoint_override
139            else f"{self.name}-{Config.PROJECT_NAME}.svc.{Config.ENVIRONMENT}.pinecone.io:443"
140        )
141
142    def _gen_channel(self, options=None):
143        target = self._endpoint()
144        default_options = {
145            "grpc.max_send_message_length": MAX_MSG_SIZE,
146            "grpc.max_receive_message_length": MAX_MSG_SIZE,
147            "grpc.service_config": self.method_config,
148            "grpc.enable_retries": True,
149        }
150        if self.grpc_client_config.secure:
151            default_options["grpc.ssl_target_name_override"] = target.split(":")[0]
152        user_provided_options = options or {}
153        _options = tuple((k, v) for k, v in {**default_options, **user_provided_options}.items())
154        _logger.debug(
155            "creating new channel with endpoint %s options %s and config %s", target, _options, self.grpc_client_config
156        )
157        if not self.grpc_client_config.secure:
158            channel = grpc.insecure_channel(target, options=_options)
159        else:
160            root_cas = open(certifi.where(), "rb").read()
161            tls = grpc.ssl_channel_credentials(root_certificates=root_cas)
162            channel = grpc.secure_channel(target, tls, options=_options)
163
164        return channel
165
166    @property
167    def channel(self):
168        """Creates GRPC channel."""
169        if self.grpc_client_config.reuse_channel and self._channel and self.grpc_server_on():
170            return self._channel
171        self._channel = self._gen_channel()
172        return self._channel
173
174    def grpc_server_on(self) -> bool:
175        try:
176            grpc.channel_ready_future(self._channel).result(timeout=self.grpc_client_config.conn_timeout)
177            return True
178        except grpc.FutureTimeoutError:
179            return False
180
181    def close(self):
182        """Closes the connection to the index."""
183        try:
184            self._channel.close()
185        except TypeError:
186            pass
187
188    def _wrap_grpc_call(
189        self, func, request, timeout=None, metadata=None, credentials=None, wait_for_ready=None, compression=None
190    ):
191        @wraps(func)
192        def wrapped():
193            user_provided_metadata = metadata or {}
194            _metadata = tuple(
195                (k, v) for k, v in {**self.fixed_metadata, **self._request_metadata(), **user_provided_metadata}.items()
196            )
197            try:
198                return func(
199                    request,
200                    timeout=timeout,
201                    metadata=_metadata,
202                    credentials=credentials,
203                    wait_for_ready=wait_for_ready,
204                    compression=compression,
205                )
206            except _InactiveRpcError as e:
207                raise PineconeException(e._state.debug_error_string) from e
208
209        return wrapped()
210
211    def _request_metadata(self) -> Dict[str, str]:
212        return {REQUEST_ID: _generate_request_id()}
213
214    def __enter__(self):
215        return self
216
217    def __exit__(self, exc_type, exc_value, traceback):
218        self.close()
219
220
221def parse_sparse_values(sparse_values: dict):
222    return (
223        SparseValues(indices=sparse_values["indices"], values=sparse_values["values"])
224        if sparse_values
225        else SparseValues(indices=[], values=[])
226    )
227
228
229def parse_fetch_response(response: dict):
230    vd = {}
231    vectors = response.get("vectors")
232    if not vectors:
233        return None
234    for id, vec in vectors.items():
235        v_obj = _Vector(
236            id=vec["id"],
237            values=vec["values"],
238            sparse_values=parse_sparse_values(vec.get("sparseValues")),
239            metadata=vec.get("metadata", None),
240            _check_type=False,
241        )
242        vd[id] = v_obj
243    namespace = response.get("namespace", "")
244    return FetchResponse(vectors=vd, namespace=namespace, _check_type=False)
245
246
247def parse_query_response(response: dict, unary_query: bool, _check_type: bool = False):
248    res = []
249
250    # TODO: consider deleting this deprecated case
251    for match in response.get("results", []):
252        namespace = match.get("namespace", "")
253        m = []
254        if "matches" in match:
255            for item in match["matches"]:
256                sc = ScoredVector(
257                    id=item["id"],
258                    score=item.get("score", 0.0),
259                    values=item.get("values", []),
260                    sparse_values=parse_sparse_values(item.get("sparseValues")),
261                    metadata=item.get("metadata", {}),
262                )
263                m.append(sc)
264        res.append(SingleQueryResults(matches=m, namespace=namespace))
265
266    m = []
267    for item in response.get("matches", []):
268        sc = ScoredVector(
269            id=item["id"],
270            score=item.get("score", 0.0),
271            values=item.get("values", []),
272            sparse_values=parse_sparse_values(item.get("sparseValues")),
273            metadata=item.get("metadata", {}),
274            _check_type=_check_type,
275        )
276        m.append(sc)
277
278    kwargs = {"_check_type": _check_type}
279    if unary_query:
280        kwargs["namespace"] = response.get("namespace", "")
281        kwargs["matches"] = m
282    else:
283        kwargs["results"] = res
284    return QueryResponse(**kwargs)
285
286
287def parse_stats_response(response: dict):
288    fullness = response.get("indexFullness", 0.0)
289    total_vector_count = response.get("totalVectorCount", 0)
290    dimension = response.get("dimension", 0)
291    summaries = response.get("namespaces", {})
292    namespace_summaries = {}
293    for key in summaries:
294        vc = summaries[key].get("vectorCount", 0)
295        namespace_summaries[key] = NamespaceSummary(vector_count=vc)
296    return DescribeIndexStatsResponse(
297        namespaces=namespace_summaries,
298        dimension=dimension,
299        index_fullness=fullness,
300        total_vector_count=total_vector_count,
301        _check_type=False,
302    )
303
304
305class PineconeGrpcFuture:
306    def __init__(self, delegate):
307        self._delegate = delegate
308
309    def cancel(self):
310        return self._delegate.cancel()
311
312    def cancelled(self):
313        return self._delegate.cancelled()
314
315    def running(self):
316        return self._delegate.running()
317
318    def done(self):
319        return self._delegate.done()
320
321    def add_done_callback(self, fun):
322        return self._delegate.add_done_callback(fun)
323
324    def result(self, timeout=None):
325        try:
326            return self._delegate.result(timeout=timeout)
327        except _MultiThreadedRendezvous as e:
328            raise PineconeException(e._state.debug_error_string) from e
329
330    def exception(self, timeout=None):
331        return self._delegate.exception(timeout=timeout)
332
333    def traceback(self, timeout=None):
334        return self._delegate.traceback(timeout=timeout)
335
336
337class GRPCIndex(GRPCIndexBase):
338
339    """A client for interacting with a Pinecone index via GRPC API."""
340
341    @property
342    def stub_class(self):
343        return VectorServiceStub
344
345    def upsert(
346        self,
347        vectors: Union[List[GRPCVector], List[tuple], List[dict]],
348        async_req: bool = False,
349        namespace: Optional[str] = None,
350        batch_size: Optional[int] = None,
351        show_progress: bool = True,
352        **kwargs
353    ) -> Union[UpsertResponse, PineconeGrpcFuture]:
354        """
355        The upsert operation writes vectors into a namespace.
356        If a new value is upserted for an existing vector id, it will overwrite the previous value.
357
358        Examples:
359            >>> index.upsert([('id1', [1.0, 2.0, 3.0], {'key': 'value'}),
360                              ('id2', [1.0, 2.0, 3.0])
361                              ],
362                              namespace='ns1', async_req=True)
363            >>> index.upsert([{'id': 'id1', 'values': [1.0, 2.0, 3.0], 'metadata': {'key': 'value'}},
364                              {'id': 'id2',
365                                        'values': [1.0, 2.0, 3.0],
366                                        'sprase_values': {'indices': [1, 8], 'values': [0.2, 0.4]},
367                              ])
368            >>> index.upsert([GRPCVector(id='id1', values=[1.0, 2.0, 3.0], metadata={'key': 'value'}),
369                              GRPCVector(id='id2', values=[1.0, 2.0, 3.0]),
370                              GRPCVector(id='id3',
371                                         values=[1.0, 2.0, 3.0],
372                                         sparse_values=GRPCSparseValues(indices=[1, 2], values=[0.2, 0.4]))])
373
374        Args:
375            vectors (Union[List[Vector], List[Tuple]]): A list of vectors to upsert.
376
377                     A vector can be represented by a 1) GRPCVector object, a 2) tuple or 3) a dictionary
378                     1) if a tuple is used, it must be of the form (id, values, metadata) or (id, values).
379                        where id is a string, vector is a list of floats, and metadata is a dict.
380                        Examples: ('id1', [1.0, 2.0, 3.0], {'key': 'value'}), ('id2', [1.0, 2.0, 3.0])
381
382                    2) if a GRPCVector object is used, a GRPCVector object must be of the form
383                        GRPCVector(id, values, metadata), where metadata is an optional argument of type
384                        Dict[str, Union[str, float, int, bool, List[int], List[float], List[str]]]
385                       Examples: GRPCVector(id='id1', values=[1.0, 2.0, 3.0], metadata={'key': 'value'}),
386                                 GRPCVector(id='id2', values=[1.0, 2.0, 3.0]),
387                                 GRPCVector(id='id3',
388                                            values=[1.0, 2.0, 3.0],
389                                            sparse_values=GRPCSparseValues(indices=[1, 2], values=[0.2, 0.4]))
390
391                    3) if a dictionary is used, it must be in the form
392                       {'id': str, 'values': List[float], 'sparse_values': {'indices': List[int], 'values': List[float]},
393                        'metadata': dict}
394
395                    Note: the dimension of each vector must match the dimension of the index.
396            async_req (bool): If True, the upsert operation will be performed asynchronously.
397                              Cannot be used with batch_size.
398                              Defaults to False. See: https://docs.pinecone.io/docs/performance-tuning [optional]
399            namespace (str): The namespace to write to. If not specified, the default namespace is used. [optional]
400            batch_size (int): The number of vectors to upsert in each batch.
401                                Cannot be used with async_req=Ture.
402                               If not specified, all vectors will be upserted in a single batch. [optional]
403            show_progress (bool): Whether to show a progress bar using tqdm.
404                                  Applied only if batch_size is provided. Default is True.
405
406        Returns: UpsertResponse, contains the number of vectors upserted
407        """
408        if async_req and batch_size is not None:
409            raise ValueError(
410                "async_req is not supported when batch_size is provided."
411                "To upsert in parallel, please follow: "
412                "https://docs.pinecone.io/docs/performance-tuning"
413            )
414
415        def _dict_to_grpc_vector(item):
416            item_keys = set(item.keys())
417            if not item_keys.issuperset(REQUIRED_VECTOR_FIELDS):
418                raise ValueError(
419                    f"Vector dictionary is missing required fields: {list(REQUIRED_VECTOR_FIELDS - item_keys)}"
420                )
421
422            excessive_keys = item_keys - (REQUIRED_VECTOR_FIELDS | OPTIONAL_VECTOR_FIELDS)
423            if len(excessive_keys) > 0:
424                raise ValueError(
425                    f"Found excess keys in the vector dictionary: {list(excessive_keys)}. "
426                    f"The allowed keys are: {list(REQUIRED_VECTOR_FIELDS | OPTIONAL_VECTOR_FIELDS)}"
427                )
428
429            sparse_values = None
430            if "sparse_values" in item:
431                if not isinstance(item["sparse_values"], Mapping):
432                    raise TypeError(
433                        f"Column `sparse_values` is expected to be a dictionary, found {type(item['sparse_values'])}"
434                    )
435                indices = item["sparse_values"].get("indices", None)
436                values = item["sparse_values"].get("values", None)
437                try:
438                    sparse_values = GRPCSparseValues(indices=indices, values=values)
439                except TypeError as e:
440                    raise TypeError(
441                        "Found unexpected data in column `sparse_values`. "
442                        "Expected format is `'sparse_values': {'indices': List[int], 'values': List[float]}`."
443                    ) from e
444
445            metadata = item.get("metadata", None)
446            if metadata is not None and not isinstance(metadata, Mapping):
447                raise TypeError(f"Column `metadata` is expected to be a dictionary, found {type(metadata)}")
448
449            try:
450                return GRPCVector(
451                    id=item["id"],
452                    values=item["values"],
453                    sparse_values=sparse_values,
454                    metadata=dict_to_proto_struct(metadata),
455                )
456
457            except TypeError as e:
458                # No need to raise a dedicated error for `id` - protobuf's error message is clear enough
459                if not isinstance(item["values"], Iterable) or not isinstance(item["values"][0], numbers.Real):
460                    raise TypeError(f"Column `values` is expected to be a list of floats")
461                raise
462
463        def _vector_transform(item):
464            if isinstance(item, GRPCVector):
465                return item
466            elif isinstance(item, tuple):
467                if len(item) > 3:
468                    raise ValueError(
469                        f"Found a tuple of length {len(item)} which is not supported. "
470                        f"Vectors can be represented as tuples either the form (id, values, metadata) or (id, values). "
471                        f"To pass sparse values please use either dicts or GRPCVector objects as inputs."
472                    )
473                id, values, metadata = fix_tuple_length(item, 3)
474                return GRPCVector(id=id, values=values, metadata=dict_to_proto_struct(metadata) or {})
475            elif isinstance(item, Mapping):
476                return _dict_to_grpc_vector(item)
477            raise ValueError(f"Invalid vector value passed: cannot interpret type {type(item)}")
478
479        timeout = kwargs.pop("timeout", None)
480
481        vectors = list(map(_vector_transform, vectors))
482        if async_req:
483            args_dict = self._parse_non_empty_args([("namespace", namespace)])
484            request = UpsertRequest(vectors=vectors, **args_dict, **kwargs)
485            future = self._wrap_grpc_call(self.stub.Upsert.future, request, timeout=timeout)
486            return PineconeGrpcFuture(future)
487
488        if batch_size is None:
489            return self._upsert_batch(vectors, namespace, timeout=timeout, **kwargs)
490
491        if not isinstance(batch_size, int) or batch_size <= 0:
492            raise ValueError("batch_size must be a positive integer")
493
494        pbar = tqdm(total=len(vectors), disable=not show_progress, desc="Upserted vectors")
495        total_upserted = 0
496        for i in range(0, len(vectors), batch_size):
497            batch_result = self._upsert_batch(vectors[i : i + batch_size], namespace, timeout=timeout, **kwargs)
498            pbar.update(batch_result.upserted_count)
499            # we can't use here pbar.n for the case show_progress=False
500            total_upserted += batch_result.upserted_count
501
502        return UpsertResponse(upserted_count=total_upserted)
503
504    def _upsert_batch(
505        self, vectors: List[GRPCVector], namespace: Optional[str], timeout: Optional[float], **kwargs
506    ) -> UpsertResponse:
507        args_dict = self._parse_non_empty_args([("namespace", namespace)])
508        request = UpsertRequest(vectors=vectors, **args_dict)
509        return self._wrap_grpc_call(self.stub.Upsert, request, timeout=timeout, **kwargs)
510
511    def upsert_from_dataframe(
512        self,
513        df,
514        namespace: str = None,
515        batch_size: int = 500,
516        use_async_requests: bool = True,
517        show_progress: bool = True,
518    ) -> None:
519        """Upserts a dataframe into the index.
520
521        Args:
522            df: A pandas dataframe with the following columns: id, vector, and metadata.
523            namespace: The namespace to upsert into.
524            batch_size: The number of rows to upsert in a single batch.
525            use_async_requests: Whether to upsert multiple requests at the same time using asynchronous request mechanism.
526                                Set to `False`
527            show_progress: Whether to show a progress bar.
528        """
529        try:
530            import pandas as pd
531        except ImportError:
532            raise RuntimeError(
533                "The `pandas` package is not installed. Please install pandas to use `upsert_from_dataframe()`"
534            )
535
536        if not isinstance(df, pd.DataFrame):
537            raise ValueError(f"Only pandas dataframes are supported. Found: {type(df)}")
538
539        pbar = tqdm(total=len(df), disable=not show_progress, desc="sending upsert requests")
540        results = []
541        for chunk in self._iter_dataframe(df, batch_size=batch_size):
542            res = self.upsert(vectors=chunk, namespace=namespace, async_req=use_async_requests)
543            pbar.update(len(chunk))
544            results.append(res)
545
546        if use_async_requests:
547            results = [async_result.result() for async_result in tqdm(results, desc="collecting async responses")]
548
549        upserted_count = 0
550        for res in results:
551            upserted_count += res.upserted_count
552
553        return UpsertResponse(upserted_count=upserted_count)
554
555    @staticmethod
556    def _iter_dataframe(df, batch_size):
557        for i in range(0, len(df), batch_size):
558            batch = df.iloc[i : i + batch_size].to_dict(orient="records")
559            yield batch
560
561    def delete(
562        self,
563        ids: Optional[List[str]] = None,
564        delete_all: Optional[bool] = None,
565        namespace: Optional[str] = None,
566        filter: Optional[Dict[str, Union[str, float, int, bool, List, dict]]] = None,
567        async_req: bool = False,
568        **kwargs
569    ) -> Union[DeleteResponse, PineconeGrpcFuture]:
570        """
571        The Delete operation deletes vectors from the index, from a single namespace.
572        No error raised if the vector id does not exist.
573        Note: for any delete call, if namespace is not specified, the default namespace is used.
574
575        Delete can occur in the following mutual exclusive ways:
576        1. Delete by ids from a single namespace
577        2. Delete all vectors from a single namespace by setting delete_all to True
578        3. Delete all vectors from a single namespace by specifying a metadata filter
579           (note that for this option delete all must be set to False)
580
581        Examples:
582            >>> index.delete(ids=['id1', 'id2'], namespace='my_namespace')
583            >>> index.delete(delete_all=True, namespace='my_namespace')
584            >>> index.delete(filter={'key': 'value'}, namespace='my_namespace', async_req=True)
585
586        Args:
587            ids (List[str]): Vector ids to delete [optional]
588            delete_all (bool): This indicates that all vectors in the index namespace should be deleted.. [optional]
589                               Default is False.
590            namespace (str): The namespace to delete vectors from [optional]
591                             If not specified, the default namespace is used.
592            filter (Dict[str, Union[str, float, int, bool, List, dict]]):
593                    If specified, the metadata filter here will be used to select the vectors to delete.
594                    This is mutually exclusive with specifying ids to delete in the ids param or using delete_all=True.
595                     See https://www.pinecone.io/docs/metadata-filtering/.. [optional]
596            async_req (bool): If True, the delete operation will be performed asynchronously.
597                              Defaults to False. [optional]
598
599        Returns: DeleteResponse (contains no data) or a PineconeGrpcFuture object if async_req is True.
600        """
601
602        if filter is not None:
603            filter = dict_to_proto_struct(filter)
604
605        args_dict = self._parse_non_empty_args(
606            [("ids", ids), ("delete_all", delete_all), ("namespace", namespace), ("filter", filter)]
607        )
608        timeout = kwargs.pop("timeout", None)
609
610        request = DeleteRequest(**args_dict, **kwargs)
611        if async_req:
612            future = self._wrap_grpc_call(self.stub.Delete.future, request, timeout=timeout)
613            return PineconeGrpcFuture(future)
614        else:
615            return self._wrap_grpc_call(self.stub.Delete, request, timeout=timeout)
616
617    def fetch(self, ids: Optional[List[str]], namespace: Optional[str] = None, **kwargs) -> FetchResponse:
618        """
619        The fetch operation looks up and returns vectors, by ID, from a single namespace.
620        The returned vectors include the vector data and/or metadata.
621
622        Examples:
623            >>> index.fetch(ids=['id1', 'id2'], namespace='my_namespace')
624            >>> index.fetch(ids=['id1', 'id2'])
625
626        Args:
627            ids (List[str]): The vector IDs to fetch.
628            namespace (str): The namespace to fetch vectors from.
629                             If not specified, the default namespace is used. [optional]
630
631        Returns: FetchResponse object which contains the list of Vector objects, and namespace name.
632        """
633        timeout = kwargs.pop("timeout", None)
634
635        args_dict = self._parse_non_empty_args([("namespace", namespace)])
636
637        request = FetchRequest(ids=ids, **args_dict, **kwargs)
638        response = self._wrap_grpc_call(self.stub.Fetch, request, timeout=timeout)
639        json_response = json_format.MessageToDict(response)
640        return parse_fetch_response(json_response)
641
642    def query(
643        self,
644        vector: Optional[List[float]] = None,
645        id: Optional[str] = None,
646        queries: Optional[Union[List[GRPCQueryVector], List[Tuple]]] = None,
647        namespace: Optional[str] = None,
648        top_k: Optional[int] = None,
649        filter: Optional[Dict[str, Union[str, float, int, bool, List, dict]]] = None,
650        include_values: Optional[bool] = None,
651        include_metadata: Optional[bool] = None,
652        sparse_vector: Optional[Union[GRPCSparseValues, Dict[str, Union[List[float], List[int]]]]] = None,
653        **kwargs
654    ) -> QueryResponse:
655        """
656        The Query operation searches a namespace, using a query vector.
657        It retrieves the ids of the most similar items in a namespace, along with their similarity scores.
658
659        Examples:
660            >>> index.query(vector=[1, 2, 3], top_k=10, namespace='my_namespace')
661            >>> index.query(id='id1', top_k=10, namespace='my_namespace')
662            >>> index.query(vector=[1, 2, 3], top_k=10, namespace='my_namespace', filter={'key': 'value'})
663            >>> index.query(id='id1', top_k=10, namespace='my_namespace', include_metadata=True, include_values=True)
664            >>> index.query(vector=[1, 2, 3], sparse_vector={'indices': [1, 2], 'values': [0.2, 0.4]},
665            >>>             top_k=10, namespace='my_namespace')
666            >>> index.query(vector=[1, 2, 3], sparse_vector=GRPCSparseValues([1, 2], [0.2, 0.4]),
667            >>>             top_k=10, namespace='my_namespace')
668
669        Args:
670            vector (List[float]): The query vector. This should be the same length as the dimension of the index
671                                  being queried. Each `query()` request can contain only one of the parameters
672                                  `queries`, `id` or `vector`.. [optional]
673            id (str): The unique ID of the vector to be used as a query vector.
674                      Each `query()` request can contain only one of the parameters
675                      `queries`, `vector`, or  `id`.. [optional]
676            queries ([GRPCQueryVector]): DEPRECATED. The query vectors.
677                                     Each `query()` request can contain only one of the parameters
678                                     `queries`, `vector`, or  `id`.. [optional]
679            top_k (int): The number of results to return for each query. Must be an integer greater than 1.
680            namespace (str): The namespace to fetch vectors from.
681                             If not specified, the default namespace is used. [optional]
682            filter (Dict[str, Union[str, float, int, bool, List, dict]]):
683                    The filter to apply. You can use vector metadata to limit your search.
684                    See https://www.pinecone.io/docs/metadata-filtering/.. [optional]
685            include_values (bool): Indicates whether vector values are included in the response.
686                                   If omitted the server will use the default value of False [optional]
687            include_metadata (bool): Indicates whether metadata is included in the response as well as the ids.
688                                     If omitted the server will use the default value of False  [optional]
689            sparse_vector: (Union[SparseValues, Dict[str, Union[List[float], List[int]]]]): sparse values of the query vector.
690                            Expected to be either a GRPCSparseValues object or a dict of the form:
691                             {'indices': List[int], 'values': List[float]}, where the lists each have the same length.
692
693        Returns: QueryResponse object which contains the list of the closest vectors as ScoredVector objects,
694                 and namespace name.
695        """
696
697        def _query_transform(item):
698            if isinstance(item, GRPCQueryVector):
699                return item
700            if isinstance(item, tuple):
701                values, filter = fix_tuple_length(item, 2)
702                filter = dict_to_proto_struct(filter)
703                return GRPCQueryVector(values=values, filter=filter)
704            if isinstance(item, Iterable):
705                return GRPCQueryVector(values=item)
706            raise ValueError(f"Invalid query vector value passed: cannot interpret type {type(item)}")
707
708        queries = list(map(_query_transform, queries)) if queries is not None else None
709
710        if filter is not None:
711            filter = dict_to_proto_struct(filter)
712
713        sparse_vector = self._parse_sparse_values_arg(sparse_vector)
714        args_dict = self._parse_non_empty_args(
715            [
716                ("vector", vector),
717                ("id", id),
718                ("queries", queries),
719                ("namespace", namespace),
720                ("top_k", top_k),
721                ("filter", filter),
722                ("include_values", include_values),
723                ("include_metadata", include_metadata),
724                ("sparse_vector", sparse_vector),
725            ]
726        )
727
728        request = QueryRequest(**args_dict)
729
730        timeout = kwargs.pop("timeout", None)
731        response = self._wrap_grpc_call(self.stub.Query, request, timeout=timeout)
732        json_response = json_format.MessageToDict(response)
733        return parse_query_response(json_response, vector is not None or id, _check_type=False)
734
735    def update(
736        self,
737        id: str,
738        async_req: bool = False,
739        values: Optional[List[float]] = None,
740        set_metadata: Optional[Dict[str, Union[str, float, int, bool, List[int], List[float], List[str]]]] = None,
741        namespace: Optional[str] = None,
742        sparse_values: Optional[Union[GRPCSparseValues, Dict[str, Union[List[float], List[int]]]]] = None,
743        **kwargs
744    ) -> Union[UpdateResponse, PineconeGrpcFuture]:
745        """
746        The Update operation updates vector in a namespace.
747        If a value is included, it will overwrite the previous value.
748        If a set_metadata is included,
749        the values of the fields specified in it will be added or overwrite the previous value.
750
751        Examples:
752            >>> index.update(id='id1', values=[1, 2, 3], namespace='my_namespace')
753            >>> index.update(id='id1', set_metadata={'key': 'value'}, namespace='my_namespace', async_req=True)
754            >>> index.update(id='id1', values=[1, 2, 3], sparse_values={'indices': [1, 2], 'values': [0.2, 0.4]},
755            >>>              namespace='my_namespace')
756            >>> index.update(id='id1', values=[1, 2, 3], sparse_values=GRPCSparseValues(indices=[1, 2], values=[0.2, 0.4]),
757            >>>              namespace='my_namespace')
758
759        Args:
760            id (str): Vector's unique id.
761            async_req (bool): If True, the update operation will be performed asynchronously.
762                              Defaults to False. [optional]
763            values (List[float]): vector values to set. [optional]
764            set_metadata (Dict[str, Union[str, float, int, bool, List[int], List[float], List[str]]]]):
765                metadata to set for vector. [optional]
766            namespace (str): Namespace name where to update the vector.. [optional]
767            sparse_values: (Dict[str, Union[List[float], List[int]]]): sparse values to update for the vector.
768                           Expected to be either a GRPCSparseValues object or a dict of the form:
769                           {'indices': List[int], 'values': List[float]} where the lists each have the same length.
770
771
772        Returns: UpdateResponse (contains no data) or a PineconeGrpcFuture object if async_req is True.
773        """
774        if set_metadata is not None:
775            set_metadata = dict_to_proto_struct(set_metadata)
776        timeout = kwargs.pop("timeout", None)
777
778        sparse_values = self._parse_sparse_values_arg(sparse_values)
779        args_dict = self._parse_non_empty_args(
780            [
781                ("values", values),
782                ("set_metadata", set_metadata),
783                ("namespace", namespace),
784                ("sparse_values", sparse_values),
785            ]
786        )
787
788        request = UpdateRequest(id=id, **args_dict)
789        if async_req:
790            future = self._wrap_grpc_call(self.stub.Update.future, request, timeout=timeout)
791            return PineconeGrpcFuture(future)
792        else:
793            return self._wrap_grpc_call(self.stub.Update, request, timeout=timeout)
794
795    def describe_index_stats(
796        self, filter: Optional[Dict[str, Union[str, float, int, bool, List, dict]]] = None, **kwargs
797    ) -> DescribeIndexStatsResponse:
798        """
799        The DescribeIndexStats operation returns statistics about the index's contents.
800        For example: The vector count per namespace and the number of dimensions.
801
802        Examples:
803            >>> index.describe_index_stats()
804            >>> index.describe_index_stats(filter={'key': 'value'})
805
806        Args:
807            filter (Dict[str, Union[str, float, int, bool, List, dict]]):
808            If this parameter is present, the operation only returns statistics for vectors that satisfy the filter.
809            See https://www.pinecone.io/docs/metadata-filtering/.. [optional]
810
811        Returns: DescribeIndexStatsResponse object which contains stats about the index.
812        """
813        if filter is not None:
814            filter = dict_to_proto_struct(filter)
815        args_dict = self._parse_non_empty_args([("filter", filter)])
816        timeout = kwargs.pop("timeout", None)
817
818        request = DescribeIndexStatsRequest(**args_dict)
819        response = self._wrap_grpc_call(self.stub.DescribeIndexStats, request, timeout=timeout)
820        json_response = json_format.MessageToDict(response)
821        return parse_stats_response(json_response)
822
823    @staticmethod
824    def _parse_non_empty_args(args: List[Tuple[str, Any]]) -> Dict[str, Any]:
825        return {arg_name: val for arg_name, val in args if val is not None}
826
827    @staticmethod
828    def _parse_sparse_values_arg(
829        sparse_values: Optional[Union[GRPCSparseValues, Dict[str, Union[List[float], List[int]]]]]
830    ) -> Optional[GRPCSparseValues]:
831        if sparse_values is None:
832            return None
833
834        if isinstance(sparse_values, GRPCSparseValues):
835            return sparse_values
836
837        if not isinstance(sparse_values, dict) or "indices" not in sparse_values or "values" not in sparse_values:
838            raise ValueError(
839                "Invalid sparse values argument. Expected a dict of: {'indices': List[int], 'values': List[float]}."
840                f"Received: {sparse_values}"
841            )
842
843        return GRPCSparseValues(indices=sparse_values["indices"], values=sparse_values["values"])
class GRPCIndex(GRPCIndexBase):
338class GRPCIndex(GRPCIndexBase):
339
340    """A client for interacting with a Pinecone index via GRPC API."""
341
342    @property
343    def stub_class(self):
344        return VectorServiceStub
345
346    def upsert(
347        self,
348        vectors: Union[List[GRPCVector], List[tuple], List[dict]],
349        async_req: bool = False,
350        namespace: Optional[str] = None,
351        batch_size: Optional[int] = None,
352        show_progress: bool = True,
353        **kwargs
354    ) -> Union[UpsertResponse, PineconeGrpcFuture]:
355        """
356        The upsert operation writes vectors into a namespace.
357        If a new value is upserted for an existing vector id, it will overwrite the previous value.
358
359        Examples:
360            >>> index.upsert([('id1', [1.0, 2.0, 3.0], {'key': 'value'}),
361                              ('id2', [1.0, 2.0, 3.0])
362                              ],
363                              namespace='ns1', async_req=True)
364            >>> index.upsert([{'id': 'id1', 'values': [1.0, 2.0, 3.0], 'metadata': {'key': 'value'}},
365                              {'id': 'id2',
366                                        'values': [1.0, 2.0, 3.0],
367                                        'sprase_values': {'indices': [1, 8], 'values': [0.2, 0.4]},
368                              ])
369            >>> index.upsert([GRPCVector(id='id1', values=[1.0, 2.0, 3.0], metadata={'key': 'value'}),
370                              GRPCVector(id='id2', values=[1.0, 2.0, 3.0]),
371                              GRPCVector(id='id3',
372                                         values=[1.0, 2.0, 3.0],
373                                         sparse_values=GRPCSparseValues(indices=[1, 2], values=[0.2, 0.4]))])
374
375        Args:
376            vectors (Union[List[Vector], List[Tuple]]): A list of vectors to upsert.
377
378                     A vector can be represented by a 1) GRPCVector object, a 2) tuple or 3) a dictionary
379                     1) if a tuple is used, it must be of the form (id, values, metadata) or (id, values).
380                        where id is a string, vector is a list of floats, and metadata is a dict.
381                        Examples: ('id1', [1.0, 2.0, 3.0], {'key': 'value'}), ('id2', [1.0, 2.0, 3.0])
382
383                    2) if a GRPCVector object is used, a GRPCVector object must be of the form
384                        GRPCVector(id, values, metadata), where metadata is an optional argument of type
385                        Dict[str, Union[str, float, int, bool, List[int], List[float], List[str]]]
386                       Examples: GRPCVector(id='id1', values=[1.0, 2.0, 3.0], metadata={'key': 'value'}),
387                                 GRPCVector(id='id2', values=[1.0, 2.0, 3.0]),
388                                 GRPCVector(id='id3',
389                                            values=[1.0, 2.0, 3.0],
390                                            sparse_values=GRPCSparseValues(indices=[1, 2], values=[0.2, 0.4]))
391
392                    3) if a dictionary is used, it must be in the form
393                       {'id': str, 'values': List[float], 'sparse_values': {'indices': List[int], 'values': List[float]},
394                        'metadata': dict}
395
396                    Note: the dimension of each vector must match the dimension of the index.
397            async_req (bool): If True, the upsert operation will be performed asynchronously.
398                              Cannot be used with batch_size.
399                              Defaults to False. See: https://docs.pinecone.io/docs/performance-tuning [optional]
400            namespace (str): The namespace to write to. If not specified, the default namespace is used. [optional]
401            batch_size (int): The number of vectors to upsert in each batch.
402                                Cannot be used with async_req=Ture.
403                               If not specified, all vectors will be upserted in a single batch. [optional]
404            show_progress (bool): Whether to show a progress bar using tqdm.
405                                  Applied only if batch_size is provided. Default is True.
406
407        Returns: UpsertResponse, contains the number of vectors upserted
408        """
409        if async_req and batch_size is not None:
410            raise ValueError(
411                "async_req is not supported when batch_size is provided."
412                "To upsert in parallel, please follow: "
413                "https://docs.pinecone.io/docs/performance-tuning"
414            )
415
416        def _dict_to_grpc_vector(item):
417            item_keys = set(item.keys())
418            if not item_keys.issuperset(REQUIRED_VECTOR_FIELDS):
419                raise ValueError(
420                    f"Vector dictionary is missing required fields: {list(REQUIRED_VECTOR_FIELDS - item_keys)}"
421                )
422
423            excessive_keys = item_keys - (REQUIRED_VECTOR_FIELDS | OPTIONAL_VECTOR_FIELDS)
424            if len(excessive_keys) > 0:
425                raise ValueError(
426                    f"Found excess keys in the vector dictionary: {list(excessive_keys)}. "
427                    f"The allowed keys are: {list(REQUIRED_VECTOR_FIELDS | OPTIONAL_VECTOR_FIELDS)}"
428                )
429
430            sparse_values = None
431            if "sparse_values" in item:
432                if not isinstance(item["sparse_values"], Mapping):
433                    raise TypeError(
434                        f"Column `sparse_values` is expected to be a dictionary, found {type(item['sparse_values'])}"
435                    )
436                indices = item["sparse_values"].get("indices", None)
437                values = item["sparse_values"].get("values", None)
438                try:
439                    sparse_values = GRPCSparseValues(indices=indices, values=values)
440                except TypeError as e:
441                    raise TypeError(
442                        "Found unexpected data in column `sparse_values`. "
443                        "Expected format is `'sparse_values': {'indices': List[int], 'values': List[float]}`."
444                    ) from e
445
446            metadata = item.get("metadata", None)
447            if metadata is not None and not isinstance(metadata, Mapping):
448                raise TypeError(f"Column `metadata` is expected to be a dictionary, found {type(metadata)}")
449
450            try:
451                return GRPCVector(
452                    id=item["id"],
453                    values=item["values"],
454                    sparse_values=sparse_values,
455                    metadata=dict_to_proto_struct(metadata),
456                )
457
458            except TypeError as e:
459                # No need to raise a dedicated error for `id` - protobuf's error message is clear enough
460                if not isinstance(item["values"], Iterable) or not isinstance(item["values"][0], numbers.Real):
461                    raise TypeError(f"Column `values` is expected to be a list of floats")
462                raise
463
464        def _vector_transform(item):
465            if isinstance(item, GRPCVector):
466                return item
467            elif isinstance(item, tuple):
468                if len(item) > 3:
469                    raise ValueError(
470                        f"Found a tuple of length {len(item)} which is not supported. "
471                        f"Vectors can be represented as tuples either the form (id, values, metadata) or (id, values). "
472                        f"To pass sparse values please use either dicts or GRPCVector objects as inputs."
473                    )
474                id, values, metadata = fix_tuple_length(item, 3)
475                return GRPCVector(id=id, values=values, metadata=dict_to_proto_struct(metadata) or {})
476            elif isinstance(item, Mapping):
477                return _dict_to_grpc_vector(item)
478            raise ValueError(f"Invalid vector value passed: cannot interpret type {type(item)}")
479
480        timeout = kwargs.pop("timeout", None)
481
482        vectors = list(map(_vector_transform, vectors))
483        if async_req:
484            args_dict = self._parse_non_empty_args([("namespace", namespace)])
485            request = UpsertRequest(vectors=vectors, **args_dict, **kwargs)
486            future = self._wrap_grpc_call(self.stub.Upsert.future, request, timeout=timeout)
487            return PineconeGrpcFuture(future)
488
489        if batch_size is None:
490            return self._upsert_batch(vectors, namespace, timeout=timeout, **kwargs)
491
492        if not isinstance(batch_size, int) or batch_size <= 0:
493            raise ValueError("batch_size must be a positive integer")
494
495        pbar = tqdm(total=len(vectors), disable=not show_progress, desc="Upserted vectors")
496        total_upserted = 0
497        for i in range(0, len(vectors), batch_size):
498            batch_result = self._upsert_batch(vectors[i : i + batch_size], namespace, timeout=timeout, **kwargs)
499            pbar.update(batch_result.upserted_count)
500            # we can't use here pbar.n for the case show_progress=False
501            total_upserted += batch_result.upserted_count
502
503        return UpsertResponse(upserted_count=total_upserted)
504
505    def _upsert_batch(
506        self, vectors: List[GRPCVector], namespace: Optional[str], timeout: Optional[float], **kwargs
507    ) -> UpsertResponse:
508        args_dict = self._parse_non_empty_args([("namespace", namespace)])
509        request = UpsertRequest(vectors=vectors, **args_dict)
510        return self._wrap_grpc_call(self.stub.Upsert, request, timeout=timeout, **kwargs)
511
512    def upsert_from_dataframe(
513        self,
514        df,
515        namespace: str = None,
516        batch_size: int = 500,
517        use_async_requests: bool = True,
518        show_progress: bool = True,
519    ) -> None:
520        """Upserts a dataframe into the index.
521
522        Args:
523            df: A pandas dataframe with the following columns: id, vector, and metadata.
524            namespace: The namespace to upsert into.
525            batch_size: The number of rows to upsert in a single batch.
526            use_async_requests: Whether to upsert multiple requests at the same time using asynchronous request mechanism.
527                                Set to `False`
528            show_progress: Whether to show a progress bar.
529        """
530        try:
531            import pandas as pd
532        except ImportError:
533            raise RuntimeError(
534                "The `pandas` package is not installed. Please install pandas to use `upsert_from_dataframe()`"
535            )
536
537        if not isinstance(df, pd.DataFrame):
538            raise ValueError(f"Only pandas dataframes are supported. Found: {type(df)}")
539
540        pbar = tqdm(total=len(df), disable=not show_progress, desc="sending upsert requests")
541        results = []
542        for chunk in self._iter_dataframe(df, batch_size=batch_size):
543            res = self.upsert(vectors=chunk, namespace=namespace, async_req=use_async_requests)
544            pbar.update(len(chunk))
545            results.append(res)
546
547        if use_async_requests:
548            results = [async_result.result() for async_result in tqdm(results, desc="collecting async responses")]
549
550        upserted_count = 0
551        for res in results:
552            upserted_count += res.upserted_count
553
554        return UpsertResponse(upserted_count=upserted_count)
555
556    @staticmethod
557    def _iter_dataframe(df, batch_size):
558        for i in range(0, len(df), batch_size):
559            batch = df.iloc[i : i + batch_size].to_dict(orient="records")
560            yield batch
561
562    def delete(
563        self,
564        ids: Optional[List[str]] = None,
565        delete_all: Optional[bool] = None,
566        namespace: Optional[str] = None,
567        filter: Optional[Dict[str, Union[str, float, int, bool, List, dict]]] = None,
568        async_req: bool = False,
569        **kwargs
570    ) -> Union[DeleteResponse, PineconeGrpcFuture]:
571        """
572        The Delete operation deletes vectors from the index, from a single namespace.
573        No error raised if the vector id does not exist.
574        Note: for any delete call, if namespace is not specified, the default namespace is used.
575
576        Delete can occur in the following mutual exclusive ways:
577        1. Delete by ids from a single namespace
578        2. Delete all vectors from a single namespace by setting delete_all to True
579        3. Delete all vectors from a single namespace by specifying a metadata filter
580           (note that for this option delete all must be set to False)
581
582        Examples:
583            >>> index.delete(ids=['id1', 'id2'], namespace='my_namespace')
584            >>> index.delete(delete_all=True, namespace='my_namespace')
585            >>> index.delete(filter={'key': 'value'}, namespace='my_namespace', async_req=True)
586
587        Args:
588            ids (List[str]): Vector ids to delete [optional]
589            delete_all (bool): This indicates that all vectors in the index namespace should be deleted.. [optional]
590                               Default is False.
591            namespace (str): The namespace to delete vectors from [optional]
592                             If not specified, the default namespace is used.
593            filter (Dict[str, Union[str, float, int, bool, List, dict]]):
594                    If specified, the metadata filter here will be used to select the vectors to delete.
595                    This is mutually exclusive with specifying ids to delete in the ids param or using delete_all=True.
596                     See https://www.pinecone.io/docs/metadata-filtering/.. [optional]
597            async_req (bool): If True, the delete operation will be performed asynchronously.
598                              Defaults to False. [optional]
599
600        Returns: DeleteResponse (contains no data) or a PineconeGrpcFuture object if async_req is True.
601        """
602
603        if filter is not None:
604            filter = dict_to_proto_struct(filter)
605
606        args_dict = self._parse_non_empty_args(
607            [("ids", ids), ("delete_all", delete_all), ("namespace", namespace), ("filter", filter)]
608        )
609        timeout = kwargs.pop("timeout", None)
610
611        request = DeleteRequest(**args_dict, **kwargs)
612        if async_req:
613            future = self._wrap_grpc_call(self.stub.Delete.future, request, timeout=timeout)
614            return PineconeGrpcFuture(future)
615        else:
616            return self._wrap_grpc_call(self.stub.Delete, request, timeout=timeout)
617
618    def fetch(self, ids: Optional[List[str]], namespace: Optional[str] = None, **kwargs) -> FetchResponse:
619        """
620        The fetch operation looks up and returns vectors, by ID, from a single namespace.
621        The returned vectors include the vector data and/or metadata.
622
623        Examples:
624            >>> index.fetch(ids=['id1', 'id2'], namespace='my_namespace')
625            >>> index.fetch(ids=['id1', 'id2'])
626
627        Args:
628            ids (List[str]): The vector IDs to fetch.
629            namespace (str): The namespace to fetch vectors from.
630                             If not specified, the default namespace is used. [optional]
631
632        Returns: FetchResponse object which contains the list of Vector objects, and namespace name.
633        """
634        timeout = kwargs.pop("timeout", None)
635
636        args_dict = self._parse_non_empty_args([("namespace", namespace)])
637
638        request = FetchRequest(ids=ids, **args_dict, **kwargs)
639        response = self._wrap_grpc_call(self.stub.Fetch, request, timeout=timeout)
640        json_response = json_format.MessageToDict(response)
641        return parse_fetch_response(json_response)
642
643    def query(
644        self,
645        vector: Optional[List[float]] = None,
646        id: Optional[str] = None,
647        queries: Optional[Union[List[GRPCQueryVector], List[Tuple]]] = None,
648        namespace: Optional[str] = None,
649        top_k: Optional[int] = None,
650        filter: Optional[Dict[str, Union[str, float, int, bool, List, dict]]] = None,
651        include_values: Optional[bool] = None,
652        include_metadata: Optional[bool] = None,
653        sparse_vector: Optional[Union[GRPCSparseValues, Dict[str, Union[List[float], List[int]]]]] = None,
654        **kwargs
655    ) -> QueryResponse:
656        """
657        The Query operation searches a namespace, using a query vector.
658        It retrieves the ids of the most similar items in a namespace, along with their similarity scores.
659
660        Examples:
661            >>> index.query(vector=[1, 2, 3], top_k=10, namespace='my_namespace')
662            >>> index.query(id='id1', top_k=10, namespace='my_namespace')
663            >>> index.query(vector=[1, 2, 3], top_k=10, namespace='my_namespace', filter={'key': 'value'})
664            >>> index.query(id='id1', top_k=10, namespace='my_namespace', include_metadata=True, include_values=True)
665            >>> index.query(vector=[1, 2, 3], sparse_vector={'indices': [1, 2], 'values': [0.2, 0.4]},
666            >>>             top_k=10, namespace='my_namespace')
667            >>> index.query(vector=[1, 2, 3], sparse_vector=GRPCSparseValues([1, 2], [0.2, 0.4]),
668            >>>             top_k=10, namespace='my_namespace')
669
670        Args:
671            vector (List[float]): The query vector. This should be the same length as the dimension of the index
672                                  being queried. Each `query()` request can contain only one of the parameters
673                                  `queries`, `id` or `vector`.. [optional]
674            id (str): The unique ID of the vector to be used as a query vector.
675                      Each `query()` request can contain only one of the parameters
676                      `queries`, `vector`, or  `id`.. [optional]
677            queries ([GRPCQueryVector]): DEPRECATED. The query vectors.
678                                     Each `query()` request can contain only one of the parameters
679                                     `queries`, `vector`, or  `id`.. [optional]
680            top_k (int): The number of results to return for each query. Must be an integer greater than 1.
681            namespace (str): The namespace to fetch vectors from.
682                             If not specified, the default namespace is used. [optional]
683            filter (Dict[str, Union[str, float, int, bool, List, dict]]):
684                    The filter to apply. You can use vector metadata to limit your search.
685                    See https://www.pinecone.io/docs/metadata-filtering/.. [optional]
686            include_values (bool): Indicates whether vector values are included in the response.
687                                   If omitted the server will use the default value of False [optional]
688            include_metadata (bool): Indicates whether metadata is included in the response as well as the ids.
689                                     If omitted the server will use the default value of False  [optional]
690            sparse_vector: (Union[SparseValues, Dict[str, Union[List[float], List[int]]]]): sparse values of the query vector.
691                            Expected to be either a GRPCSparseValues object or a dict of the form:
692                             {'indices': List[int], 'values': List[float]}, where the lists each have the same length.
693
694        Returns: QueryResponse object which contains the list of the closest vectors as ScoredVector objects,
695                 and namespace name.
696        """
697
698        def _query_transform(item):
699            if isinstance(item, GRPCQueryVector):
700                return item
701            if isinstance(item, tuple):
702                values, filter = fix_tuple_length(item, 2)
703                filter = dict_to_proto_struct(filter)
704                return GRPCQueryVector(values=values, filter=filter)
705            if isinstance(item, Iterable):
706                return GRPCQueryVector(values=item)
707            raise ValueError(f"Invalid query vector value passed: cannot interpret type {type(item)}")
708
709        queries = list(map(_query_transform, queries)) if queries is not None else None
710
711        if filter is not None:
712            filter = dict_to_proto_struct(filter)
713
714        sparse_vector = self._parse_sparse_values_arg(sparse_vector)
715        args_dict = self._parse_non_empty_args(
716            [
717                ("vector", vector),
718                ("id", id),
719                ("queries", queries),
720                ("namespace", namespace),
721                ("top_k", top_k),
722                ("filter", filter),
723                ("include_values", include_values),
724                ("include_metadata", include_metadata),
725                ("sparse_vector", sparse_vector),
726            ]
727        )
728
729        request = QueryRequest(**args_dict)
730
731        timeout = kwargs.pop("timeout", None)
732        response = self._wrap_grpc_call(self.stub.Query, request, timeout=timeout)
733        json_response = json_format.MessageToDict(response)
734        return parse_query_response(json_response, vector is not None or id, _check_type=False)
735
736    def update(
737        self,
738        id: str,
739        async_req: bool = False,
740        values: Optional[List[float]] = None,
741        set_metadata: Optional[Dict[str, Union[str, float, int, bool, List[int], List[float], List[str]]]] = None,
742        namespace: Optional[str] = None,
743        sparse_values: Optional[Union[GRPCSparseValues, Dict[str, Union[List[float], List[int]]]]] = None,
744        **kwargs
745    ) -> Union[UpdateResponse, PineconeGrpcFuture]:
746        """
747        The Update operation updates vector in a namespace.
748        If a value is included, it will overwrite the previous value.
749        If a set_metadata is included,
750        the values of the fields specified in it will be added or overwrite the previous value.
751
752        Examples:
753            >>> index.update(id='id1', values=[1, 2, 3], namespace='my_namespace')
754            >>> index.update(id='id1', set_metadata={'key': 'value'}, namespace='my_namespace', async_req=True)
755            >>> index.update(id='id1', values=[1, 2, 3], sparse_values={'indices': [1, 2], 'values': [0.2, 0.4]},
756            >>>              namespace='my_namespace')
757            >>> index.update(id='id1', values=[1, 2, 3], sparse_values=GRPCSparseValues(indices=[1, 2], values=[0.2, 0.4]),
758            >>>              namespace='my_namespace')
759
760        Args:
761            id (str): Vector's unique id.
762            async_req (bool): If True, the update operation will be performed asynchronously.
763                              Defaults to False. [optional]
764            values (List[float]): vector values to set. [optional]
765            set_metadata (Dict[str, Union[str, float, int, bool, List[int], List[float], List[str]]]]):
766                metadata to set for vector. [optional]
767            namespace (str): Namespace name where to update the vector.. [optional]
768            sparse_values: (Dict[str, Union[List[float], List[int]]]): sparse values to update for the vector.
769                           Expected to be either a GRPCSparseValues object or a dict of the form:
770                           {'indices': List[int], 'values': List[float]} where the lists each have the same length.
771
772
773        Returns: UpdateResponse (contains no data) or a PineconeGrpcFuture object if async_req is True.
774        """
775        if set_metadata is not None:
776            set_metadata = dict_to_proto_struct(set_metadata)
777        timeout = kwargs.pop("timeout", None)
778
779        sparse_values = self._parse_sparse_values_arg(sparse_values)
780        args_dict = self._parse_non_empty_args(
781            [
782                ("values", values),
783                ("set_metadata", set_metadata),
784                ("namespace", namespace),
785                ("sparse_values", sparse_values),
786            ]
787        )
788
789        request = UpdateRequest(id=id, **args_dict)
790        if async_req:
791            future = self._wrap_grpc_call(self.stub.Update.future, request, timeout=timeout)
792            return PineconeGrpcFuture(future)
793        else:
794            return self._wrap_grpc_call(self.stub.Update, request, timeout=timeout)
795
796    def describe_index_stats(
797        self, filter: Optional[Dict[str, Union[str, float, int, bool, List, dict]]] = None, **kwargs
798    ) -> DescribeIndexStatsResponse:
799        """
800        The DescribeIndexStats operation returns statistics about the index's contents.
801        For example: The vector count per namespace and the number of dimensions.
802
803        Examples:
804            >>> index.describe_index_stats()
805            >>> index.describe_index_stats(filter={'key': 'value'})
806
807        Args:
808            filter (Dict[str, Union[str, float, int, bool, List, dict]]):
809            If this parameter is present, the operation only returns statistics for vectors that satisfy the filter.
810            See https://www.pinecone.io/docs/metadata-filtering/.. [optional]
811
812        Returns: DescribeIndexStatsResponse object which contains stats about the index.
813        """
814        if filter is not None:
815            filter = dict_to_proto_struct(filter)
816        args_dict = self._parse_non_empty_args([("filter", filter)])
817        timeout = kwargs.pop("timeout", None)
818
819        request = DescribeIndexStatsRequest(**args_dict)
820        response = self._wrap_grpc_call(self.stub.DescribeIndexStats, request, timeout=timeout)
821        json_response = json_format.MessageToDict(response)
822        return parse_stats_response(json_response)
823
824    @staticmethod
825    def _parse_non_empty_args(args: List[Tuple[str, Any]]) -> Dict[str, Any]:
826        return {arg_name: val for arg_name, val in args if val is not None}
827
828    @staticmethod
829    def _parse_sparse_values_arg(
830        sparse_values: Optional[Union[GRPCSparseValues, Dict[str, Union[List[float], List[int]]]]]
831    ) -> Optional[GRPCSparseValues]:
832        if sparse_values is None:
833            return None
834
835        if isinstance(sparse_values, GRPCSparseValues):
836            return sparse_values
837
838        if not isinstance(sparse_values, dict) or "indices" not in sparse_values or "values" not in sparse_values:
839            raise ValueError(
840                "Invalid sparse values argument. Expected a dict of: {'indices': List[int], 'values': List[float]}."
841                f"Received: {sparse_values}"
842            )
843
844        return GRPCSparseValues(indices=sparse_values["indices"], values=sparse_values["values"])

A client for interacting with a Pinecone index via GRPC API.

stub_class
def upsert( self, vectors: Union[List[vector_service_pb2.Vector], List[tuple], List[dict]], async_req: bool = False, namespace: Optional[str] = None, batch_size: Optional[int] = None, show_progress: bool = True, **kwargs) -> Union[vector_service_pb2.UpsertResponse, pinecone.core.grpc.index_grpc.PineconeGrpcFuture]:
346    def upsert(
347        self,
348        vectors: Union[List[GRPCVector], List[tuple], List[dict]],
349        async_req: bool = False,
350        namespace: Optional[str] = None,
351        batch_size: Optional[int] = None,
352        show_progress: bool = True,
353        **kwargs
354    ) -> Union[UpsertResponse, PineconeGrpcFuture]:
355        """
356        The upsert operation writes vectors into a namespace.
357        If a new value is upserted for an existing vector id, it will overwrite the previous value.
358
359        Examples:
360            >>> index.upsert([('id1', [1.0, 2.0, 3.0], {'key': 'value'}),
361                              ('id2', [1.0, 2.0, 3.0])
362                              ],
363                              namespace='ns1', async_req=True)
364            >>> index.upsert([{'id': 'id1', 'values': [1.0, 2.0, 3.0], 'metadata': {'key': 'value'}},
365                              {'id': 'id2',
366                                        'values': [1.0, 2.0, 3.0],
367                                        'sprase_values': {'indices': [1, 8], 'values': [0.2, 0.4]},
368                              ])
369            >>> index.upsert([GRPCVector(id='id1', values=[1.0, 2.0, 3.0], metadata={'key': 'value'}),
370                              GRPCVector(id='id2', values=[1.0, 2.0, 3.0]),
371                              GRPCVector(id='id3',
372                                         values=[1.0, 2.0, 3.0],
373                                         sparse_values=GRPCSparseValues(indices=[1, 2], values=[0.2, 0.4]))])
374
375        Args:
376            vectors (Union[List[Vector], List[Tuple]]): A list of vectors to upsert.
377
378                     A vector can be represented by a 1) GRPCVector object, a 2) tuple or 3) a dictionary
379                     1) if a tuple is used, it must be of the form (id, values, metadata) or (id, values).
380                        where id is a string, vector is a list of floats, and metadata is a dict.
381                        Examples: ('id1', [1.0, 2.0, 3.0], {'key': 'value'}), ('id2', [1.0, 2.0, 3.0])
382
383                    2) if a GRPCVector object is used, a GRPCVector object must be of the form
384                        GRPCVector(id, values, metadata), where metadata is an optional argument of type
385                        Dict[str, Union[str, float, int, bool, List[int], List[float], List[str]]]
386                       Examples: GRPCVector(id='id1', values=[1.0, 2.0, 3.0], metadata={'key': 'value'}),
387                                 GRPCVector(id='id2', values=[1.0, 2.0, 3.0]),
388                                 GRPCVector(id='id3',
389                                            values=[1.0, 2.0, 3.0],
390                                            sparse_values=GRPCSparseValues(indices=[1, 2], values=[0.2, 0.4]))
391
392                    3) if a dictionary is used, it must be in the form
393                       {'id': str, 'values': List[float], 'sparse_values': {'indices': List[int], 'values': List[float]},
394                        'metadata': dict}
395
396                    Note: the dimension of each vector must match the dimension of the index.
397            async_req (bool): If True, the upsert operation will be performed asynchronously.
398                              Cannot be used with batch_size.
399                              Defaults to False. See: https://docs.pinecone.io/docs/performance-tuning [optional]
400            namespace (str): The namespace to write to. If not specified, the default namespace is used. [optional]
401            batch_size (int): The number of vectors to upsert in each batch.
402                                Cannot be used with async_req=Ture.
403                               If not specified, all vectors will be upserted in a single batch. [optional]
404            show_progress (bool): Whether to show a progress bar using tqdm.
405                                  Applied only if batch_size is provided. Default is True.
406
407        Returns: UpsertResponse, contains the number of vectors upserted
408        """
409        if async_req and batch_size is not None:
410            raise ValueError(
411                "async_req is not supported when batch_size is provided."
412                "To upsert in parallel, please follow: "
413                "https://docs.pinecone.io/docs/performance-tuning"
414            )
415
416        def _dict_to_grpc_vector(item):
417            item_keys = set(item.keys())
418            if not item_keys.issuperset(REQUIRED_VECTOR_FIELDS):
419                raise ValueError(
420                    f"Vector dictionary is missing required fields: {list(REQUIRED_VECTOR_FIELDS - item_keys)}"
421                )
422
423            excessive_keys = item_keys - (REQUIRED_VECTOR_FIELDS | OPTIONAL_VECTOR_FIELDS)
424            if len(excessive_keys) > 0:
425                raise ValueError(
426                    f"Found excess keys in the vector dictionary: {list(excessive_keys)}. "
427                    f"The allowed keys are: {list(REQUIRED_VECTOR_FIELDS | OPTIONAL_VECTOR_FIELDS)}"
428                )
429
430            sparse_values = None
431            if "sparse_values" in item:
432                if not isinstance(item["sparse_values"], Mapping):
433                    raise TypeError(
434                        f"Column `sparse_values` is expected to be a dictionary, found {type(item['sparse_values'])}"
435                    )
436                indices = item["sparse_values"].get("indices", None)
437                values = item["sparse_values"].get("values", None)
438                try:
439                    sparse_values = GRPCSparseValues(indices=indices, values=values)
440                except TypeError as e:
441                    raise TypeError(
442                        "Found unexpected data in column `sparse_values`. "
443                        "Expected format is `'sparse_values': {'indices': List[int], 'values': List[float]}`."
444                    ) from e
445
446            metadata = item.get("metadata", None)
447            if metadata is not None and not isinstance(metadata, Mapping):
448                raise TypeError(f"Column `metadata` is expected to be a dictionary, found {type(metadata)}")
449
450            try:
451                return GRPCVector(
452                    id=item["id"],
453                    values=item["values"],
454                    sparse_values=sparse_values,
455                    metadata=dict_to_proto_struct(metadata),
456                )
457
458            except TypeError as e:
459                # No need to raise a dedicated error for `id` - protobuf's error message is clear enough
460                if not isinstance(item["values"], Iterable) or not isinstance(item["values"][0], numbers.Real):
461                    raise TypeError(f"Column `values` is expected to be a list of floats")
462                raise
463
464        def _vector_transform(item):
465            if isinstance(item, GRPCVector):
466                return item
467            elif isinstance(item, tuple):
468                if len(item) > 3:
469                    raise ValueError(
470                        f"Found a tuple of length {len(item)} which is not supported. "
471                        f"Vectors can be represented as tuples either the form (id, values, metadata) or (id, values). "
472                        f"To pass sparse values please use either dicts or GRPCVector objects as inputs."
473                    )
474                id, values, metadata = fix_tuple_length(item, 3)
475                return GRPCVector(id=id, values=values, metadata=dict_to_proto_struct(metadata) or {})
476            elif isinstance(item, Mapping):
477                return _dict_to_grpc_vector(item)
478            raise ValueError(f"Invalid vector value passed: cannot interpret type {type(item)}")
479
480        timeout = kwargs.pop("timeout", None)
481
482        vectors = list(map(_vector_transform, vectors))
483        if async_req:
484            args_dict = self._parse_non_empty_args([("namespace", namespace)])
485            request = UpsertRequest(vectors=vectors, **args_dict, **kwargs)
486            future = self._wrap_grpc_call(self.stub.Upsert.future, request, timeout=timeout)
487            return PineconeGrpcFuture(future)
488
489        if batch_size is None:
490            return self._upsert_batch(vectors, namespace, timeout=timeout, **kwargs)
491
492        if not isinstance(batch_size, int) or batch_size <= 0:
493            raise ValueError("batch_size must be a positive integer")
494
495        pbar = tqdm(total=len(vectors), disable=not show_progress, desc="Upserted vectors")
496        total_upserted = 0
497        for i in range(0, len(vectors), batch_size):
498            batch_result = self._upsert_batch(vectors[i : i + batch_size], namespace, timeout=timeout, **kwargs)
499            pbar.update(batch_result.upserted_count)
500            # we can't use here pbar.n for the case show_progress=False
501            total_upserted += batch_result.upserted_count
502
503        return UpsertResponse(upserted_count=total_upserted)

The upsert operation writes vectors into a namespace. If a new value is upserted for an existing vector id, it will overwrite the previous value.

Examples:
>>> index.upsert([('id1', [1.0, 2.0, 3.0], {'key': 'value'}),
                  ('id2', [1.0, 2.0, 3.0])
                  ],
                  namespace='ns1', async_req=True)
>>> index.upsert([{'id': 'id1', 'values': [1.0, 2.0, 3.0], 'metadata': {'key': 'value'}},
                  {'id': 'id2',
                            'values': [1.0, 2.0, 3.0],
                            'sprase_values': {'indices': [1, 8], 'values': [0.2, 0.4]},
                  ])
>>> index.upsert([GRPCVector(id='id1', values=[1.0, 2.0, 3.0], metadata={'key': 'value'}),
                  GRPCVector(id='id2', values=[1.0, 2.0, 3.0]),
                  GRPCVector(id='id3',
                             values=[1.0, 2.0, 3.0],
                             sparse_values=GRPCSparseValues(indices=[1, 2], values=[0.2, 0.4]))])
Arguments:
  • vectors (Union[List[Vector], List[Tuple]]): A list of vectors to upsert.

    A vector can be represented by a 1) GRPCVector object, a 2) tuple or 3) a dictionary 1) if a tuple is used, it must be of the form (id, values, metadata) or (id, values). where id is a string, vector is a list of floats, and metadata is a dict. Examples: ('id1', [1.0, 2.0, 3.0], {'key': 'value'}), ('id2', [1.0, 2.0, 3.0])

    2) if a GRPCVector object is used, a GRPCVector object must be of the form GRPCVector(id, values, metadata), where metadata is an optional argument of type Dict[str, Union[str, float, int, bool, List[int], List[float], List[str]]] Examples: GRPCVector(id='id1', values=[1.0, 2.0, 3.0], metadata={'key': 'value'}), GRPCVector(id='id2', values=[1.0, 2.0, 3.0]), GRPCVector(id='id3', values=[1.0, 2.0, 3.0], sparse_values=GRPCSparseValues(indices=[1, 2], values=[0.2, 0.4]))

    3) if a dictionary is used, it must be in the form {'id': str, 'values': List[float], 'sparse_values': {'indices': List[int], 'values': List[float]}, 'metadata': dict}

    Note: the dimension of each vector must match the dimension of the index.

  • async_req (bool): If True, the upsert operation will be performed asynchronously. Cannot be used with batch_size. Defaults to False. See: https://docs.pinecone.io/docs/performance-tuning [optional]
  • namespace (str): The namespace to write to. If not specified, the default namespace is used. [optional]
  • batch_size (int): The number of vectors to upsert in each batch. Cannot be used with async_req=Ture. If not specified, all vectors will be upserted in a single batch. [optional]
  • show_progress (bool): Whether to show a progress bar using tqdm. Applied only if batch_size is provided. Default is True.

Returns: UpsertResponse, contains the number of vectors upserted

def upsert_from_dataframe( self, df, namespace: str = None, batch_size: int = 500, use_async_requests: bool = True, show_progress: bool = True) -> None:
512    def upsert_from_dataframe(
513        self,
514        df,
515        namespace: str = None,
516        batch_size: int = 500,
517        use_async_requests: bool = True,
518        show_progress: bool = True,
519    ) -> None:
520        """Upserts a dataframe into the index.
521
522        Args:
523            df: A pandas dataframe with the following columns: id, vector, and metadata.
524            namespace: The namespace to upsert into.
525            batch_size: The number of rows to upsert in a single batch.
526            use_async_requests: Whether to upsert multiple requests at the same time using asynchronous request mechanism.
527                                Set to `False`
528            show_progress: Whether to show a progress bar.
529        """
530        try:
531            import pandas as pd
532        except ImportError:
533            raise RuntimeError(
534                "The `pandas` package is not installed. Please install pandas to use `upsert_from_dataframe()`"
535            )
536
537        if not isinstance(df, pd.DataFrame):
538            raise ValueError(f"Only pandas dataframes are supported. Found: {type(df)}")
539
540        pbar = tqdm(total=len(df), disable=not show_progress, desc="sending upsert requests")
541        results = []
542        for chunk in self._iter_dataframe(df, batch_size=batch_size):
543            res = self.upsert(vectors=chunk, namespace=namespace, async_req=use_async_requests)
544            pbar.update(len(chunk))
545            results.append(res)
546
547        if use_async_requests:
548            results = [async_result.result() for async_result in tqdm(results, desc="collecting async responses")]
549
550        upserted_count = 0
551        for res in results:
552            upserted_count += res.upserted_count
553
554        return UpsertResponse(upserted_count=upserted_count)

Upserts a dataframe into the index.

Arguments:
  • df: A pandas dataframe with the following columns: id, vector, and metadata.
  • namespace: The namespace to upsert into.
  • batch_size: The number of rows to upsert in a single batch.
  • use_async_requests: Whether to upsert multiple requests at the same time using asynchronous request mechanism. Set to False
  • show_progress: Whether to show a progress bar.
def delete( self, ids: Optional[List[str]] = None, delete_all: Optional[bool] = None, namespace: Optional[str] = None, filter: Optional[Dict[str, Union[str, float, int, bool, List, dict]]] = None, async_req: bool = False, **kwargs) -> Union[vector_service_pb2.DeleteResponse, pinecone.core.grpc.index_grpc.PineconeGrpcFuture]:
562    def delete(
563        self,
564        ids: Optional[List[str]] = None,
565        delete_all: Optional[bool] = None,
566        namespace: Optional[str] = None,
567        filter: Optional[Dict[str, Union[str, float, int, bool, List, dict]]] = None,
568        async_req: bool = False,
569        **kwargs
570    ) -> Union[DeleteResponse, PineconeGrpcFuture]:
571        """
572        The Delete operation deletes vectors from the index, from a single namespace.
573        No error raised if the vector id does not exist.
574        Note: for any delete call, if namespace is not specified, the default namespace is used.
575
576        Delete can occur in the following mutual exclusive ways:
577        1. Delete by ids from a single namespace
578        2. Delete all vectors from a single namespace by setting delete_all to True
579        3. Delete all vectors from a single namespace by specifying a metadata filter
580           (note that for this option delete all must be set to False)
581
582        Examples:
583            >>> index.delete(ids=['id1', 'id2'], namespace='my_namespace')
584            >>> index.delete(delete_all=True, namespace='my_namespace')
585            >>> index.delete(filter={'key': 'value'}, namespace='my_namespace', async_req=True)
586
587        Args:
588            ids (List[str]): Vector ids to delete [optional]
589            delete_all (bool): This indicates that all vectors in the index namespace should be deleted.. [optional]
590                               Default is False.
591            namespace (str): The namespace to delete vectors from [optional]
592                             If not specified, the default namespace is used.
593            filter (Dict[str, Union[str, float, int, bool, List, dict]]):
594                    If specified, the metadata filter here will be used to select the vectors to delete.
595                    This is mutually exclusive with specifying ids to delete in the ids param or using delete_all=True.
596                     See https://www.pinecone.io/docs/metadata-filtering/.. [optional]
597            async_req (bool): If True, the delete operation will be performed asynchronously.
598                              Defaults to False. [optional]
599
600        Returns: DeleteResponse (contains no data) or a PineconeGrpcFuture object if async_req is True.
601        """
602
603        if filter is not None:
604            filter = dict_to_proto_struct(filter)
605
606        args_dict = self._parse_non_empty_args(
607            [("ids", ids), ("delete_all", delete_all), ("namespace", namespace), ("filter", filter)]
608        )
609        timeout = kwargs.pop("timeout", None)
610
611        request = DeleteRequest(**args_dict, **kwargs)
612        if async_req:
613            future = self._wrap_grpc_call(self.stub.Delete.future, request, timeout=timeout)
614            return PineconeGrpcFuture(future)
615        else:
616            return self._wrap_grpc_call(self.stub.Delete, request, timeout=timeout)

The Delete operation deletes vectors from the index, from a single namespace. No error raised if the vector id does not exist. Note: for any delete call, if namespace is not specified, the default namespace is used.

Delete can occur in the following mutual exclusive ways:

  1. Delete by ids from a single namespace
  2. Delete all vectors from a single namespace by setting delete_all to True
  3. Delete all vectors from a single namespace by specifying a metadata filter (note that for this option delete all must be set to False)
Examples:
>>> index.delete(ids=['id1', 'id2'], namespace='my_namespace')
>>> index.delete(delete_all=True, namespace='my_namespace')
>>> index.delete(filter={'key': 'value'}, namespace='my_namespace', async_req=True)
Arguments:
  • ids (List[str]): Vector ids to delete [optional]
  • delete_all (bool): This indicates that all vectors in the index namespace should be deleted.. [optional] Default is False.
  • namespace (str): The namespace to delete vectors from [optional] If not specified, the default namespace is used.
  • filter (Dict[str, Union[str, float, int, bool, List, dict]]): 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]
  • async_req (bool): If True, the delete operation will be performed asynchronously. Defaults to False. [optional]

Returns: DeleteResponse (contains no data) or a PineconeGrpcFuture object if async_req is True.

def fetch( self, ids: Optional[List[str]], namespace: Optional[str] = None, **kwargs) -> pinecone.core.client.model.fetch_response.FetchResponse:
618    def fetch(self, ids: Optional[List[str]], namespace: Optional[str] = None, **kwargs) -> FetchResponse:
619        """
620        The fetch operation looks up and returns vectors, by ID, from a single namespace.
621        The returned vectors include the vector data and/or metadata.
622
623        Examples:
624            >>> index.fetch(ids=['id1', 'id2'], namespace='my_namespace')
625            >>> index.fetch(ids=['id1', 'id2'])
626
627        Args:
628            ids (List[str]): The vector IDs to fetch.
629            namespace (str): The namespace to fetch vectors from.
630                             If not specified, the default namespace is used. [optional]
631
632        Returns: FetchResponse object which contains the list of Vector objects, and namespace name.
633        """
634        timeout = kwargs.pop("timeout", None)
635
636        args_dict = self._parse_non_empty_args([("namespace", namespace)])
637
638        request = FetchRequest(ids=ids, **args_dict, **kwargs)
639        response = self._wrap_grpc_call(self.stub.Fetch, request, timeout=timeout)
640        json_response = json_format.MessageToDict(response)
641        return parse_fetch_response(json_response)

The fetch operation looks up and returns vectors, by ID, from a single namespace. The returned vectors include the vector data and/or metadata.

Examples:
>>> index.fetch(ids=['id1', 'id2'], namespace='my_namespace')
>>> index.fetch(ids=['id1', 'id2'])
Arguments:
  • ids (List[str]): The vector IDs to fetch.
  • namespace (str): The namespace to fetch vectors from. If not specified, the default namespace is used. [optional]

Returns: FetchResponse object which contains the list of Vector objects, and namespace name.

def query( self, vector: Optional[List[float]] = None, id: Optional[str] = None, queries: Union[List[vector_service_pb2.QueryVector], List[Tuple], NoneType] = None, namespace: Optional[str] = None, top_k: Optional[int] = None, filter: Optional[Dict[str, Union[str, float, int, bool, List, dict]]] = None, include_values: Optional[bool] = None, include_metadata: Optional[bool] = None, sparse_vector: Union[vector_service_pb2.SparseValues, Dict[str, Union[List[float], List[int]]], NoneType] = None, **kwargs) -> pinecone.core.client.model.query_response.QueryResponse:
643    def query(
644        self,
645        vector: Optional[List[float]] = None,
646        id: Optional[str] = None,
647        queries: Optional[Union[List[GRPCQueryVector], List[Tuple]]] = None,
648        namespace: Optional[str] = None,
649        top_k: Optional[int] = None,
650        filter: Optional[Dict[str, Union[str, float, int, bool, List, dict]]] = None,
651        include_values: Optional[bool] = None,
652        include_metadata: Optional[bool] = None,
653        sparse_vector: Optional[Union[GRPCSparseValues, Dict[str, Union[List[float], List[int]]]]] = None,
654        **kwargs
655    ) -> QueryResponse:
656        """
657        The Query operation searches a namespace, using a query vector.
658        It retrieves the ids of the most similar items in a namespace, along with their similarity scores.
659
660        Examples:
661            >>> index.query(vector=[1, 2, 3], top_k=10, namespace='my_namespace')
662            >>> index.query(id='id1', top_k=10, namespace='my_namespace')
663            >>> index.query(vector=[1, 2, 3], top_k=10, namespace='my_namespace', filter={'key': 'value'})
664            >>> index.query(id='id1', top_k=10, namespace='my_namespace', include_metadata=True, include_values=True)
665            >>> index.query(vector=[1, 2, 3], sparse_vector={'indices': [1, 2], 'values': [0.2, 0.4]},
666            >>>             top_k=10, namespace='my_namespace')
667            >>> index.query(vector=[1, 2, 3], sparse_vector=GRPCSparseValues([1, 2], [0.2, 0.4]),
668            >>>             top_k=10, namespace='my_namespace')
669
670        Args:
671            vector (List[float]): The query vector. This should be the same length as the dimension of the index
672                                  being queried. Each `query()` request can contain only one of the parameters
673                                  `queries`, `id` or `vector`.. [optional]
674            id (str): The unique ID of the vector to be used as a query vector.
675                      Each `query()` request can contain only one of the parameters
676                      `queries`, `vector`, or  `id`.. [optional]
677            queries ([GRPCQueryVector]): DEPRECATED. The query vectors.
678                                     Each `query()` request can contain only one of the parameters
679                                     `queries`, `vector`, or  `id`.. [optional]
680            top_k (int): The number of results to return for each query. Must be an integer greater than 1.
681            namespace (str): The namespace to fetch vectors from.
682                             If not specified, the default namespace is used. [optional]
683            filter (Dict[str, Union[str, float, int, bool, List, dict]]):
684                    The filter to apply. You can use vector metadata to limit your search.
685                    See https://www.pinecone.io/docs/metadata-filtering/.. [optional]
686            include_values (bool): Indicates whether vector values are included in the response.
687                                   If omitted the server will use the default value of False [optional]
688            include_metadata (bool): Indicates whether metadata is included in the response as well as the ids.
689                                     If omitted the server will use the default value of False  [optional]
690            sparse_vector: (Union[SparseValues, Dict[str, Union[List[float], List[int]]]]): sparse values of the query vector.
691                            Expected to be either a GRPCSparseValues object or a dict of the form:
692                             {'indices': List[int], 'values': List[float]}, where the lists each have the same length.
693
694        Returns: QueryResponse object which contains the list of the closest vectors as ScoredVector objects,
695                 and namespace name.
696        """
697
698        def _query_transform(item):
699            if isinstance(item, GRPCQueryVector):
700                return item
701            if isinstance(item, tuple):
702                values, filter = fix_tuple_length(item, 2)
703                filter = dict_to_proto_struct(filter)
704                return GRPCQueryVector(values=values, filter=filter)
705            if isinstance(item, Iterable):
706                return GRPCQueryVector(values=item)
707            raise ValueError(f"Invalid query vector value passed: cannot interpret type {type(item)}")
708
709        queries = list(map(_query_transform, queries)) if queries is not None else None
710
711        if filter is not None:
712            filter = dict_to_proto_struct(filter)
713
714        sparse_vector = self._parse_sparse_values_arg(sparse_vector)
715        args_dict = self._parse_non_empty_args(
716            [
717                ("vector", vector),
718                ("id", id),
719                ("queries", queries),
720                ("namespace", namespace),
721                ("top_k", top_k),
722                ("filter", filter),
723                ("include_values", include_values),
724                ("include_metadata", include_metadata),
725                ("sparse_vector", sparse_vector),
726            ]
727        )
728
729        request = QueryRequest(**args_dict)
730
731        timeout = kwargs.pop("timeout", None)
732        response = self._wrap_grpc_call(self.stub.Query, request, timeout=timeout)
733        json_response = json_format.MessageToDict(response)
734        return parse_query_response(json_response, vector is not None or id, _check_type=False)

The Query operation searches a namespace, using a query vector. It retrieves the ids of the most similar items in a namespace, along with their similarity scores.

Examples:
>>> index.query(vector=[1, 2, 3], top_k=10, namespace='my_namespace')
>>> index.query(id='id1', top_k=10, namespace='my_namespace')
>>> index.query(vector=[1, 2, 3], top_k=10, namespace='my_namespace', filter={'key': 'value'})
>>> index.query(id='id1', top_k=10, namespace='my_namespace', include_metadata=True, include_values=True)
>>> index.query(vector=[1, 2, 3], sparse_vector={'indices': [1, 2], 'values': [0.2, 0.4]},
>>>             top_k=10, namespace='my_namespace')
>>> index.query(vector=[1, 2, 3], sparse_vector=GRPCSparseValues([1, 2], [0.2, 0.4]),
>>>             top_k=10, namespace='my_namespace')
Arguments:
  • vector (List[float]): The query vector. This should be the same length as the dimension of the index being queried. Each query() request can contain only one of the parameters queries, id or vector.. [optional]
  • id (str): The unique ID of the vector to be used as a query vector. Each query() request can contain only one of the parameters queries, vector, or id.. [optional]
  • queries ([GRPCQueryVector]): DEPRECATED. The query vectors. Each query() request can contain only one of the parameters queries, vector, or id.. [optional]
  • top_k (int): The number of results to return for each query. Must be an integer greater than 1.
  • namespace (str): The namespace to fetch vectors from. If not specified, the default namespace is used. [optional]
  • filter (Dict[str, Union[str, float, int, bool, List, dict]]): The filter to apply. You can use vector metadata to limit your search. See https://www.pinecone.io/docs/metadata-filtering/.. [optional]
  • include_values (bool): Indicates whether vector values are included in the response. If omitted the server will use the default value of False [optional]
  • include_metadata (bool): Indicates whether metadata is included in the response as well as the ids. If omitted the server will use the default value of False [optional]
  • sparse_vector: (Union[SparseValues, Dict[str, Union[List[float], List[int]]]]): sparse values of the query vector. Expected to be either a GRPCSparseValues object or a dict of the form: {'indices': List[int], 'values': List[float]}, where the lists each have the same length.

Returns: QueryResponse object which contains the list of the closest vectors as ScoredVector objects, and namespace name.

def update( self, id: str, async_req: bool = False, values: Optional[List[float]] = None, set_metadata: Optional[Dict[str, Union[str, float, int, bool, List[int], List[float], List[str]]]] = None, namespace: Optional[str] = None, sparse_values: Union[vector_service_pb2.SparseValues, Dict[str, Union[List[float], List[int]]], NoneType] = None, **kwargs) -> Union[vector_service_pb2.UpdateResponse, pinecone.core.grpc.index_grpc.PineconeGrpcFuture]:
736    def update(
737        self,
738        id: str,
739        async_req: bool = False,
740        values: Optional[List[float]] = None,
741        set_metadata: Optional[Dict[str, Union[str, float, int, bool, List[int], List[float], List[str]]]] = None,
742        namespace: Optional[str] = None,
743        sparse_values: Optional[Union[GRPCSparseValues, Dict[str, Union[List[float], List[int]]]]] = None,
744        **kwargs
745    ) -> Union[UpdateResponse, PineconeGrpcFuture]:
746        """
747        The Update operation updates vector in a namespace.
748        If a value is included, it will overwrite the previous value.
749        If a set_metadata is included,
750        the values of the fields specified in it will be added or overwrite the previous value.
751
752        Examples:
753            >>> index.update(id='id1', values=[1, 2, 3], namespace='my_namespace')
754            >>> index.update(id='id1', set_metadata={'key': 'value'}, namespace='my_namespace', async_req=True)
755            >>> index.update(id='id1', values=[1, 2, 3], sparse_values={'indices': [1, 2], 'values': [0.2, 0.4]},
756            >>>              namespace='my_namespace')
757            >>> index.update(id='id1', values=[1, 2, 3], sparse_values=GRPCSparseValues(indices=[1, 2], values=[0.2, 0.4]),
758            >>>              namespace='my_namespace')
759
760        Args:
761            id (str): Vector's unique id.
762            async_req (bool): If True, the update operation will be performed asynchronously.
763                              Defaults to False. [optional]
764            values (List[float]): vector values to set. [optional]
765            set_metadata (Dict[str, Union[str, float, int, bool, List[int], List[float], List[str]]]]):
766                metadata to set for vector. [optional]
767            namespace (str): Namespace name where to update the vector.. [optional]
768            sparse_values: (Dict[str, Union[List[float], List[int]]]): sparse values to update for the vector.
769                           Expected to be either a GRPCSparseValues object or a dict of the form:
770                           {'indices': List[int], 'values': List[float]} where the lists each have the same length.
771
772
773        Returns: UpdateResponse (contains no data) or a PineconeGrpcFuture object if async_req is True.
774        """
775        if set_metadata is not None:
776            set_metadata = dict_to_proto_struct(set_metadata)
777        timeout = kwargs.pop("timeout", None)
778
779        sparse_values = self._parse_sparse_values_arg(sparse_values)
780        args_dict = self._parse_non_empty_args(
781            [
782                ("values", values),
783                ("set_metadata", set_metadata),
784                ("namespace", namespace),
785                ("sparse_values", sparse_values),
786            ]
787        )
788
789        request = UpdateRequest(id=id, **args_dict)
790        if async_req:
791            future = self._wrap_grpc_call(self.stub.Update.future, request, timeout=timeout)
792            return PineconeGrpcFuture(future)
793        else:
794            return self._wrap_grpc_call(self.stub.Update, request, timeout=timeout)

The Update operation updates vector in a namespace. If a value is included, it will overwrite the previous value. If a set_metadata is included, the values of the fields specified in it will be added or overwrite the previous value.

Examples:
>>> index.update(id='id1', values=[1, 2, 3], namespace='my_namespace')
>>> index.update(id='id1', set_metadata={'key': 'value'}, namespace='my_namespace', async_req=True)
>>> index.update(id='id1', values=[1, 2, 3], sparse_values={'indices': [1, 2], 'values': [0.2, 0.4]},
>>>              namespace='my_namespace')
>>> index.update(id='id1', values=[1, 2, 3], sparse_values=GRPCSparseValues(indices=[1, 2], values=[0.2, 0.4]),
>>>              namespace='my_namespace')
Arguments:
  • id (str): Vector's unique id.
  • async_req (bool): If True, the update operation will be performed asynchronously. Defaults to False. [optional]
  • values (List[float]): vector values to set. [optional]
  • set_metadata (Dict[str, Union[str, float, int, bool, List[int], List[float], List[str]]]]): metadata to set for vector. [optional]
  • namespace (str): Namespace name where to update the vector.. [optional]
  • sparse_values: (Dict[str, Union[List[float], List[int]]]): sparse values to update for the vector. Expected to be either a GRPCSparseValues object or a dict of the form: {'indices': List[int], 'values': List[float]} where the lists each have the same length.

Returns: UpdateResponse (contains no data) or a PineconeGrpcFuture object if async_req is True.

def describe_index_stats( self, filter: Optional[Dict[str, Union[str, float, int, bool, List, dict]]] = None, **kwargs) -> pinecone.core.client.model.describe_index_stats_response.DescribeIndexStatsResponse:
796    def describe_index_stats(
797        self, filter: Optional[Dict[str, Union[str, float, int, bool, List, dict]]] = None, **kwargs
798    ) -> DescribeIndexStatsResponse:
799        """
800        The DescribeIndexStats operation returns statistics about the index's contents.
801        For example: The vector count per namespace and the number of dimensions.
802
803        Examples:
804            >>> index.describe_index_stats()
805            >>> index.describe_index_stats(filter={'key': 'value'})
806
807        Args:
808            filter (Dict[str, Union[str, float, int, bool, List, dict]]):
809            If this parameter is present, the operation only returns statistics for vectors that satisfy the filter.
810            See https://www.pinecone.io/docs/metadata-filtering/.. [optional]
811
812        Returns: DescribeIndexStatsResponse object which contains stats about the index.
813        """
814        if filter is not None:
815            filter = dict_to_proto_struct(filter)
816        args_dict = self._parse_non_empty_args([("filter", filter)])
817        timeout = kwargs.pop("timeout", None)
818
819        request = DescribeIndexStatsRequest(**args_dict)
820        response = self._wrap_grpc_call(self.stub.DescribeIndexStats, request, timeout=timeout)
821        json_response = json_format.MessageToDict(response)
822        return parse_stats_response(json_response)

The DescribeIndexStats operation returns statistics about the index's contents. For example: The vector count per namespace and the number of dimensions.

Examples:
>>> index.describe_index_stats()
>>> index.describe_index_stats(filter={'key': 'value'})
Arguments:
  • filter (Dict[str, Union[str, float, int, bool, List, dict]]):
  • If this parameter is present, the operation only returns statistics for vectors that satisfy the filter.
  • See https: //www.pinecone.io/docs/metadata-filtering/.. [optional]

Returns: DescribeIndexStatsResponse object which contains stats about the index.

GRPCVector = <class 'vector_service_pb2.Vector'>
GRPCQueryVector = <class 'vector_service_pb2.QueryVector'>
GRPCSparseValues = <class 'vector_service_pb2.SparseValues'>