From bf4c0afc62ace33d889113f0cd035f949e0bf120 Mon Sep 17 00:00:00 2001 From: Jen Hamon Date: Mon, 17 Nov 2025 10:44:22 -0500 Subject: [PATCH] Review and update docstrings for Admin class --- pinecone/admin/admin.py | 43 ++++++++- pinecone/admin/resources/api_key.py | 48 +++++++++- pinecone/admin/resources/organization.py | 3 + pinecone/admin/resources/project.py | 6 ++ pinecone/inference/inference.py | 66 +++++++++++-- pinecone/inference/inference_asyncio.py | 115 +++++++++++++++++++++-- 6 files changed, 265 insertions(+), 16 deletions(-) diff --git a/pinecone/admin/admin.py b/pinecone/admin/admin.py index 4a48e9012..74c8840b4 100644 --- a/pinecone/admin/admin.py +++ b/pinecone/admin/admin.py @@ -58,6 +58,46 @@ def __init__( dictionary of key-value pairs. This is primarily used for internal testing purposes. :type additional_headers: Optional[dict[str, str]] + + Examples + -------- + + .. code-block:: python + :caption: Initialize Admin using environment variables + + import os + from pinecone import Admin + + # Set environment variables + os.environ["PINECONE_CLIENT_ID"] = "your-client-id" + os.environ["PINECONE_CLIENT_SECRET"] = "your-client-secret" + + # Initialize Admin (reads from environment variables) + admin = Admin() + + .. code-block:: python + :caption: Initialize Admin with explicit credentials + + from pinecone import Admin + + # Initialize Admin with explicit credentials + admin = Admin( + client_id="your-client-id", + client_secret="your-client-secret" + ) + + .. code-block:: python + :caption: Initialize Admin with additional headers + + from pinecone import Admin + + # Initialize Admin with additional headers for testing + admin = Admin( + client_id="your-client-id", + client_secret="your-client-secret", + additional_headers={"X-Custom-Header": "value"} + ) + """ if client_id is not None: @@ -149,7 +189,7 @@ def project(self): # Create a project with no quota for pod indexes admin.project.create( - name="my-project" + name="my-project", max_pods=0 ) @@ -169,6 +209,7 @@ def project(self): admin = Admin() project = admin.project.get(name="my-project") admin.project.delete(project_id=project.id) + """ if self._project is None: from pinecone.admin.resources import ProjectResource diff --git a/pinecone/admin/resources/api_key.py b/pinecone/admin/resources/api_key.py index 38f7a522c..0aec8ea4c 100644 --- a/pinecone/admin/resources/api_key.py +++ b/pinecone/admin/resources/api_key.py @@ -67,6 +67,7 @@ def list(self, project_id: str): print(api_key.name) print(api_key.description) print(api_key.roles) + """ return self._api_keys_api.list_project_api_keys(project_id=project_id) @@ -108,12 +109,54 @@ def fetch(self, api_key_id: str): @require_kwargs def get(self, api_key_id: str): - """Alias for :func:`fetch`""" + """Alias for :func:`fetch` + + Examples + -------- + + .. code-block:: python + :caption: Get an API key by api_key_id + + from pinecone import Admin + + # Credentials read from PINECONE_CLIENT_ID and + # PINECONE_CLIENT_SECRET environment variables + admin = Admin() + + api_key = admin.api_key.get(api_key_id='my-api-key-id') + print(api_key.id) + print(api_key.name) + print(api_key.description) + print(api_key.roles) + print(api_key.created_at) + + """ return self.fetch(api_key_id=api_key_id) @require_kwargs def describe(self, api_key_id: str): - """Alias for :func:`fetch`""" + """Alias for :func:`fetch` + + Examples + -------- + + .. code-block:: python + :caption: Describe an API key by api_key_id + + from pinecone import Admin + + # Credentials read from PINECONE_CLIENT_ID and + # PINECONE_CLIENT_SECRET environment variables + admin = Admin() + + api_key = admin.api_key.describe(api_key_id='my-api-key-id') + print(api_key.id) + print(api_key.name) + print(api_key.description) + print(api_key.roles) + print(api_key.created_at) + + """ return self.fetch(api_key_id=api_key_id) @require_kwargs @@ -204,6 +247,7 @@ def create( api_key_value = api_key_response.value print(api_key_value) + """ args = [("name", name), ("description", description), ("roles", roles)] create_api_key_request = CreateAPIKeyRequest(**parse_non_empty_args(args)) diff --git a/pinecone/admin/resources/organization.py b/pinecone/admin/resources/organization.py index a1c893766..bc5354ea3 100644 --- a/pinecone/admin/resources/organization.py +++ b/pinecone/admin/resources/organization.py @@ -64,6 +64,7 @@ def list(self): print(organization.name) print(organization.plan) print(organization.payment_status) + """ return self._organizations_api.list_organizations() @@ -125,6 +126,7 @@ def get(self, organization_id: str): ) print(organization.id) print(organization.name) + """ return self.fetch(organization_id=organization_id) @@ -150,6 +152,7 @@ def describe(self, organization_id: str): ) print(organization.id) print(organization.name) + """ return self.fetch(organization_id=organization_id) diff --git a/pinecone/admin/resources/project.py b/pinecone/admin/resources/project.py index 02e56aee1..d1f1d0ef0 100644 --- a/pinecone/admin/resources/project.py +++ b/pinecone/admin/resources/project.py @@ -74,6 +74,7 @@ def list(self): print(project.name) print(project.max_pods) print(project.force_encryption_with_cmek) + """ return self._projects_api.list_projects() @@ -129,6 +130,7 @@ def fetch(self, project_id: str | None = None, name: str | None = None): print(project.force_encryption_with_cmek) print(project.organization_id) print(project.created_at) + """ if project_id is not None and name is not None: raise ValueError("Either project_id or name must be provided but not both") @@ -174,6 +176,7 @@ def get(self, project_id: str | None = None, name: str | None = None): print(project.name) print(project.max_pods) print(project.force_encryption_with_cmek) + """ return self.fetch(project_id=project_id, name=name) @@ -201,6 +204,7 @@ def describe(self, project_id: str | None = None, name: str | None = None): print(project.name) print(project.max_pods) print(project.force_encryption_with_cmek) + """ return self.fetch(project_id=project_id, name=name) @@ -256,6 +260,7 @@ def exists(self, project_id: str | None = None, name: str | None = None): print(f"Project {project_id} exists") else: print(f"Project {project_id} does not exist") + """ if project_id is not None and name is not None: raise ValueError("Either project_id or name must be provided but not both") @@ -453,6 +458,7 @@ def delete( print("Project deleted successfully") else: print("Project deletion failed") + """ project = self.get(project_id=project_id) diff --git a/pinecone/inference/inference.py b/pinecone/inference/inference.py index 061a2f85b..cc264c63a 100644 --- a/pinecone/inference/inference.py +++ b/pinecone/inference/inference.py @@ -194,6 +194,31 @@ def embed( # usage={'total_tokens': 6} # ) + You can also use a single string input: + + .. code-block:: python + + from pinecone import Pinecone + + pc = Pinecone() + output = pc.inference.embed( + model="text-embedding-3-small", + inputs="Hello, world!" + ) + + Or use the EmbedModel enum: + + .. code-block:: python + + from pinecone import Pinecone + from pinecone.inference import EmbedModel + + pc = Pinecone() + outputs = pc.inference.embed( + model=EmbedModel.TEXT_EMBEDDING_3_SMALL, + inputs=["Document 1", "Document 2"] + ) + """ request_body = InferenceRequestBuilder.embed_request( model=model, inputs=inputs, parameters=parameters @@ -235,8 +260,7 @@ def rerank( relevance, with the first being the most relevant. The ``index`` field can be used to locate the document relative to the list of documents specified in the request. Each document contains a ``score`` key representing how close the document relates to the query. - - Example: + :rtype: RerankResult .. code-block:: python @@ -275,6 +299,38 @@ def rerank( # usage={'rerank_units': 1} # ) + You can also use document dictionaries with custom fields: + + .. code-block:: python + + from pinecone import Pinecone + + pc = Pinecone() + result = pc.inference.rerank( + model="pinecone-rerank-v0", + query="What is machine learning?", + documents=[ + {"text": "Machine learning is a subset of AI.", "category": "tech"}, + {"text": "Cooking recipes for pasta.", "category": "food"}, + ], + rank_fields=["text"], + top_n=1 + ) + + Or use the RerankModel enum: + + .. code-block:: python + + from pinecone import Pinecone + from pinecone.inference import RerankModel + + pc = Pinecone() + result = pc.inference.rerank( + model=RerankModel.PINECONE_RERANK_V0, + query="Your query here", + documents=["doc1", "doc2", "doc3"] + ) + """ rerank_request = InferenceRequestBuilder.rerank( model=model, @@ -302,8 +358,7 @@ def list_models( :type vector_type: str, optional :return: A list of models. - - Example: + :rtype: ModelInfoList .. code-block:: python @@ -339,8 +394,6 @@ def get_model(self, model_name: str) -> "ModelInfo": :return: A ModelInfo object. :rtype: ModelInfo - Example: - .. code-block:: python from pinecone import Pinecone @@ -371,5 +424,6 @@ def get_model(self, model_name: str) -> "ModelInfo": # "provider_name": "Pinecone", # "supported_metrics": [] # } + """ return self.model.get(model_name=model_name) diff --git a/pinecone/inference/inference_asyncio.py b/pinecone/inference/inference_asyncio.py index 4a3f41658..4696d3726 100644 --- a/pinecone/inference/inference_asyncio.py +++ b/pinecone/inference/inference_asyncio.py @@ -76,8 +76,6 @@ async def embed( ``usage`` key contains the total number of tokens used at request-time. :rtype: EmbeddingsList - Example: - .. code-block:: python import asyncio @@ -101,6 +99,40 @@ async def main(): # ) asyncio.run(main()) + + You can also use a single string input: + + .. code-block:: python + + import asyncio + from pinecone import PineconeAsyncio + + async def main(): + async with PineconeAsyncio() as pc: + output = await pc.inference.embed( + model="text-embedding-3-small", + inputs="Hello, world!" + ) + + asyncio.run(main()) + + Or use the EmbedModel enum: + + .. code-block:: python + + import asyncio + from pinecone import PineconeAsyncio + from pinecone.inference import EmbedModel + + async def main(): + async with PineconeAsyncio() as pc: + outputs = await pc.inference.embed( + model=EmbedModel.TEXT_EMBEDDING_3_SMALL, + inputs=["Document 1", "Document 2"] + ) + + asyncio.run(main()) + """ request_body = InferenceRequestBuilder.embed_request( model=model, inputs=inputs, parameters=parameters @@ -189,8 +221,6 @@ async def rerank( representing how close the document relates to the query. :rtype: RerankResult - Example: - .. code-block:: python import asyncio @@ -224,6 +254,47 @@ async def main(): # ) asyncio.run(main()) + + You can also use document dictionaries with custom fields: + + .. code-block:: python + + import asyncio + from pinecone import PineconeAsyncio + + async def main(): + async with PineconeAsyncio() as pc: + result = await pc.inference.rerank( + model="pinecone-rerank-v0", + query="What is machine learning?", + documents=[ + {"text": "Machine learning is a subset of AI.", "category": "tech"}, + {"text": "Cooking recipes for pasta.", "category": "food"}, + ], + rank_fields=["text"], + top_n=1 + ) + + asyncio.run(main()) + + Or use the RerankModel enum: + + .. code-block:: python + + import asyncio + from pinecone import PineconeAsyncio + from pinecone.inference import RerankModel + + async def main(): + async with PineconeAsyncio() as pc: + result = await pc.inference.rerank( + model=RerankModel.PINECONE_RERANK_V0, + query="Your query here", + documents=["doc1", "doc2", "doc3"] + ) + + asyncio.run(main()) + """ rerank_request = InferenceRequestBuilder.rerank( model=model, @@ -252,6 +323,30 @@ async def list_models( :return: A list of models. :rtype: ModelInfoList + + .. code-block:: python + + import asyncio + from pinecone import PineconeAsyncio + + async def main(): + async with PineconeAsyncio() as pc: + # List all models + models = await pc.inference.list_models() + + # List models, with model type filtering + models = await pc.inference.list_models(type="embed") + models = await pc.inference.list_models(type="rerank") + + # List models, with vector type filtering + models = await pc.inference.list_models(vector_type="dense") + models = await pc.inference.list_models(vector_type="sparse") + + # List models, with both type and vector type filtering + models = await pc.inference.list_models(type="rerank", vector_type="dense") + + asyncio.run(main()) + """ args = parse_non_empty_args([("type", type), ("vector_type", vector_type)]) resp = await self.__inference_api.list_models(**args) @@ -267,8 +362,6 @@ async def get_model(self, model_name: str) -> ModelInfo: :return: A ModelInfo object. :rtype: ModelInfo - Example: - .. code-block:: python import asyncio @@ -276,9 +369,17 @@ async def get_model(self, model_name: str) -> ModelInfo: async def main(): async with PineconeAsyncio() as pc: - model = await pc.inference.get_model(model_name="text-embedding-3-small") + model_info = await pc.inference.get_model(model_name="text-embedding-3-small") + print(model_info) + # { + # "model": "text-embedding-3-small", + # "short_description": "...", + # "type": "embed", + # ... + # } asyncio.run(main()) + """ resp = await self.__inference_api.get_model(model_name=model_name) return ModelInfo(resp)