Skip to content

Commit 10865d8

Browse files
committed
feat: add deployment model classes (#584)
## Summary Add deployment model classes for different index deployment configurations. Closes SDK-103 ## Classes | Class | Deployment Type | Key Parameters | |-------|-----------------|----------------| | `ServerlessDeployment` | `serverless` | `cloud`, `region` | | `ByocDeployment` | `byoc` | `environment` | | `PodDeployment` | `pod` | `environment`, `pod_type`, `replicas`, `shards` | ## Usage Example ```python from pinecone import ServerlessDeployment, ByocDeployment, PodDeployment # Serverless deployment pc.create_index( name="my-index", schema=schema, deployment=ServerlessDeployment(cloud="aws", region="us-east-1"), ) # BYOC deployment pc.create_index( name="my-index", schema=schema, deployment=ByocDeployment(environment="aws-us-east-1-b92"), ) # Pod deployment pc.create_index( name="my-index", schema=schema, deployment=PodDeployment( environment="us-east-1-aws", pod_type="p1.x1", replicas=2, ), ) ``` ## Test Plan - [x] Unit tests for ServerlessDeployment serialization - [x] Unit tests for ByocDeployment serialization - [x] Unit tests for PodDeployment with various options - [x] mypy type checking passes <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Low risk: this PR only adds new model/dataclass types and exports them; it doesn’t change existing request flows, but downstream code may start relying on the new `to_dict` serialization format. > > **Overview** > Adds new deployment configuration dataclasses (`ServerlessDeployment`, `ByocDeployment`, `PodDeployment`) with `to_dict()` serialization and a `Deployment` union type in `db_control/models/deployment.py`. > > Exports these types through `pinecone.db_control.models` and top-level `pinecone` lazy imports, and adds unit tests validating constructor defaults and `to_dict()` output across deployment variants. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit c2e965d. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
1 parent 9dcb0ff commit 10865d8

3 files changed

Lines changed: 388 additions & 1 deletion

File tree

codegen/apis

Submodule apis updated from d5ac931 to 4eac4da

pinecone/db_control/request_factory.py

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,12 @@
4444
CreateIndexFromBackupRequest,
4545
)
4646
from pinecone.db_control.models import ServerlessSpec, PodSpec, ByocSpec, IndexModel, IndexEmbed
47+
from pinecone.db_control.models.deployment import (
48+
ServerlessDeployment,
49+
PodDeployment,
50+
ByocDeployment,
51+
)
52+
from pinecone.db_control.models.schema_fields import DenseVectorField, SparseVectorField
4753

4854
from pinecone.db_control.enums import (
4955
Metric,
@@ -361,6 +367,131 @@ def __parse_index_spec(spec: Dict | ServerlessSpec | PodSpec | ByocSpec) -> Inde
361367

362368
return cast(IndexSpec, index_spec)
363369

370+
@staticmethod
371+
def _translate_legacy_request(
372+
spec: Dict | ServerlessSpec | PodSpec | ByocSpec,
373+
dimension: int | None = None,
374+
metric: (Metric | str) | None = None,
375+
vector_type: (VectorType | str) | None = VectorType.DENSE,
376+
) -> tuple[dict[str, Any], dict[str, Any]]:
377+
"""Translate legacy spec-based request to deployment + schema format.
378+
379+
This method converts legacy index creation parameters (spec, dimension, metric,
380+
vector_type) to the new API format using deployment and schema structures.
381+
382+
:param spec: The legacy spec (ServerlessSpec, PodSpec, ByocSpec, or dict).
383+
:param dimension: The vector dimension (for dense vectors).
384+
:param metric: The distance metric (cosine, euclidean, dotproduct).
385+
:param vector_type: The vector type (dense or sparse).
386+
:returns: A tuple of (deployment_dict, schema_dict) for the new API format.
387+
388+
**Translation Mappings:**
389+
390+
* `ServerlessSpec(cloud, region)` → `deployment` with `deployment_type="serverless"`
391+
* `PodSpec(environment, ...)` → `deployment` with `deployment_type="pod"`
392+
* `ByocSpec(environment)` → `deployment` with `deployment_type="byoc"`
393+
* `dimension` + `metric` + `vector_type="dense"` → `schema.fields._values` (dense_vector)
394+
* `vector_type="sparse"` → `schema.fields._sparse_values` (sparse_vector)
395+
396+
Example::
397+
398+
deployment, schema = PineconeDBControlRequestFactory._translate_legacy_request(
399+
spec=ServerlessSpec(cloud="aws", region="us-east-1"),
400+
dimension=1536,
401+
metric="cosine",
402+
vector_type="dense"
403+
)
404+
# Returns:
405+
# (
406+
# {"deployment_type": "serverless", "cloud": "aws", "region": "us-east-1"},
407+
# {"fields": {"_values": {"type": "dense_vector", "dimension": 1536, "metric": "cosine"}}}
408+
# )
409+
"""
410+
# Convert metric to string if it's an enum
411+
if metric is not None:
412+
metric = convert_enum_to_string(metric)
413+
if vector_type is not None:
414+
vector_type = convert_enum_to_string(vector_type)
415+
416+
# Translate spec to deployment
417+
deployment_dict: dict[str, Any]
418+
if isinstance(spec, dict):
419+
if "serverless" in spec:
420+
serverless_spec = spec["serverless"]
421+
# Convert enum values to strings for consistency with __parse_index_spec
422+
cloud = convert_enum_to_string(serverless_spec.get("cloud", ""))
423+
region = convert_enum_to_string(serverless_spec.get("region", ""))
424+
deployment = ServerlessDeployment(cloud=cloud, region=region)
425+
deployment_dict = deployment.to_dict()
426+
elif "pod" in spec:
427+
pod_spec = spec["pod"]
428+
# Convert enum values to strings for consistency with __parse_index_spec
429+
environment = convert_enum_to_string(pod_spec.get("environment", ""))
430+
pod_type = convert_enum_to_string(pod_spec.get("pod_type", "p1.x1"))
431+
deployment = PodDeployment(
432+
environment=environment,
433+
pod_type=pod_type,
434+
replicas=pod_spec.get("replicas", 1),
435+
shards=pod_spec.get("shards", 1),
436+
pods=pod_spec.get("pods"),
437+
)
438+
deployment_dict = deployment.to_dict()
439+
elif "byoc" in spec:
440+
byoc_spec = spec["byoc"]
441+
# Convert enum values to strings for consistency with __parse_index_spec
442+
environment = convert_enum_to_string(byoc_spec.get("environment", ""))
443+
deployment = ByocDeployment(environment=environment)
444+
deployment_dict = deployment.to_dict()
445+
else:
446+
raise ValueError("spec must contain either 'serverless', 'pod', or 'byoc' key")
447+
elif isinstance(spec, ServerlessSpec):
448+
deployment = ServerlessDeployment(cloud=spec.cloud, region=spec.region)
449+
deployment_dict = deployment.to_dict()
450+
elif isinstance(spec, PodSpec):
451+
# PodDeployment requires pod_type, but PodSpec defaults to "p1.x1"
452+
pod_type = spec.pod_type if spec.pod_type is not None else "p1.x1"
453+
# Use explicit None check to preserve 0 values (consistent with dict handling)
454+
replicas = spec.replicas if spec.replicas is not None else 1
455+
shards = spec.shards if spec.shards is not None else 1
456+
deployment = PodDeployment(
457+
environment=spec.environment,
458+
pod_type=pod_type,
459+
replicas=replicas,
460+
shards=shards,
461+
pods=spec.pods,
462+
)
463+
deployment_dict = deployment.to_dict()
464+
elif isinstance(spec, ByocSpec):
465+
deployment = ByocDeployment(environment=spec.environment)
466+
deployment_dict = deployment.to_dict()
467+
else:
468+
raise TypeError("spec must be of type dict, ServerlessSpec, PodSpec, or ByocSpec")
469+
470+
# Translate dimension/metric/vector_type to schema
471+
schema_dict: dict[str, Any] = {"fields": {}}
472+
if vector_type == VectorType.SPARSE.value:
473+
# Sparse vector: use _sparse_values field
474+
if metric is None:
475+
metric = "dotproduct" # Default for sparse vectors
476+
sparse_field = SparseVectorField(metric=metric)
477+
schema_dict["fields"]["_sparse_values"] = sparse_field.to_dict()
478+
elif vector_type == VectorType.DENSE.value:
479+
# Dense vector: use _values field
480+
if dimension is None:
481+
raise ValueError("dimension is required for dense vector indexes")
482+
if metric is None:
483+
metric = Metric.COSINE.value # Default for dense vectors
484+
dense_field = DenseVectorField(dimension=dimension, metric=metric)
485+
schema_dict["fields"]["_values"] = dense_field.to_dict()
486+
elif vector_type is not None:
487+
# Invalid vector_type value - raise error instead of silently returning empty schema
488+
raise ValueError(
489+
f"Invalid vector_type: '{vector_type}'. Must be '{VectorType.DENSE.value}' or '{VectorType.SPARSE.value}'"
490+
)
491+
# If vector_type is None, return empty schema fields (no vector index)
492+
493+
return deployment_dict, schema_dict
494+
364495
@staticmethod
365496
def create_index_request(
366497
name: str,

0 commit comments

Comments
 (0)