Skip to content

Commit eade7dd

Browse files
authored
Expose connection_pool_maxsize on Index and add docstrings (#415)
## Problem To explore the impact on performance, I want to expose a configuration kwarg for `connection_pool_maxsize` on `Index`. ## Solution This `connection_pool_maxsize` value is passed in to `urllib3.PoolManager` as `maxsize`. This param controls how many connections are cached for a given host. If we are using a large number of threads to increase parallelism but this maxsize value is relatively small, we can end up taking unnecessary overhead to establish and discard connections beyond the maxsize that are being cached. By default `connection_pool_maxsize` is set to `multiprocessing.cpu_count() * 5`. In Google colab, cpu count is only 2 so this is fairly limiting. ### Usage ```python from pinecone import Pinecone pc = Pinecone(api_key='key') index = pc.Index( host="jen1024-dojoi3u.svc.apw5-4e34-81fa.pinecone.io", pool_threads=25, connection_pool_maxsize=25 ) ``` ## Type of Change - [x] New feature (non-breaking change which adds functionality) ## Test Plan I ran some local performance tests and saw this does have an impact to performance.
1 parent e668c89 commit eade7dd

File tree

2 files changed

+53
-0
lines changed

2 files changed

+53
-0
lines changed

pinecone/control/pinecone.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -765,6 +765,14 @@ def Index(self, name: str = "", host: str = "", **kwargs):
765765
# Now you're ready to perform data operations
766766
index.query(vector=[...], top_k=10)
767767
```
768+
769+
Arguments:
770+
name: The name of the index to target. If you specify the name of the index, the client will
771+
fetch the host url from the Pinecone control plane.
772+
host: The host url of the index to target. If you specify the host url, the client will use
773+
the host url directly without making any additional calls to the control plane.
774+
pool_threads: The number of threads to use when making parallel requests by calling index methods with optional kwarg async_req=True, or using methods that make use of parallelism automatically such as query_namespaces(). Default: 1
775+
connection_pool_maxsize: The maximum number of connections to keep in the connection pool. Default: 5 * multiprocessing.cpu_count()
768776
"""
769777
if name == "" and host == "":
770778
raise ValueError("Either name or host must be specified")

pinecone/data/index.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,9 @@ def __init__(
105105
self._openapi_config = ConfigBuilder.build_openapi_config(self.config, openapi_config)
106106
self._pool_threads = pool_threads
107107

108+
if kwargs.get("connection_pool_maxsize", None):
109+
self._openapi_config.connection_pool_maxsize = kwargs.get("connection_pool_maxsize")
110+
108111
self._vector_api = setup_openapi_client(
109112
api_client_klass=ApiClient,
110113
api_klass=DataPlaneApi,
@@ -512,6 +515,48 @@ def query_namespaces(
512515
] = None,
513516
**kwargs,
514517
) -> QueryNamespacesResults:
518+
"""The query_namespaces() method is used to make a query to multiple namespaces in parallel and combine the results into one result set.
519+
520+
Since several asynchronous calls are made on your behalf when calling this method, you will need to tune the pool_threads and connection_pool_maxsize parameter of the Index constructor to suite your workload.
521+
522+
Examples:
523+
524+
```python
525+
from pinecone import Pinecone
526+
527+
pc = Pinecone(api_key="your-api-key")
528+
index = pc.Index(
529+
host="index-name",
530+
pool_threads=32,
531+
connection_pool_maxsize=32
532+
)
533+
534+
query_vec = [0.1, 0.2, 0.3] # An embedding that matches the index dimension
535+
combined_results = index.query_namespaces(
536+
vector=query_vec,
537+
namespaces=['ns1', 'ns2', 'ns3', 'ns4'],
538+
top_k=10,
539+
filter={'genre': {"$eq": "drama"}},
540+
include_values=True,
541+
include_metadata=True
542+
)
543+
for vec in combined_results.matches:
544+
print(vec.id, vec.score)
545+
print(combined_results.usage)
546+
```
547+
548+
Args:
549+
vector (List[float]): The query vector, must be the same length as the dimension of the index being queried.
550+
namespaces (List[str]): The list of namespaces to query.
551+
top_k (Optional[int], optional): The number of results you would like to request from each namespace. Defaults to 10.
552+
filter (Optional[Dict[str, Union[str, float, int, bool, List, dict]]], optional): Pass an optional filter to filter results based on metadata. Defaults to None.
553+
include_values (Optional[bool], optional): Boolean field indicating whether vector values should be included with results. Defaults to None.
554+
include_metadata (Optional[bool], optional): Boolean field indicating whether vector metadata should be included with results. Defaults to None.
555+
sparse_vector (Optional[ Union[SparseValues, Dict[str, Union[List[float], List[int]]]] ], optional): If you are working with a dotproduct index, you can pass a sparse vector as part of your hybrid search. Defaults to None.
556+
557+
Returns:
558+
QueryNamespacesResults: A QueryNamespacesResults object containing the combined results from all namespaces, as well as the combined usage cost in read units.
559+
"""
515560
if namespaces is None or len(namespaces) == 0:
516561
raise ValueError("At least one namespace must be specified")
517562
if len(vector) == 0:

0 commit comments

Comments
 (0)