Source code for arize.annotation_configs.client

"""Client implementation for managing annotation configs in the Arize platform."""

from __future__ import annotations

import logging
from typing import TYPE_CHECKING

from arize.annotation_configs.types import AnnotationConfigType
from arize.pre_releases import ReleaseStage, prerelease_endpoint
from arize.utils.resolve import (
    _find_annotation_config_id,
    _find_space_id,
    _resolve_resource,
)

if TYPE_CHECKING:
    import builtins

    from arize._generated.api_client.api_client import ApiClient
    from arize.annotation_configs.types import (
        AnnotationConfig,
        AnnotationConfigsList200Response,
        CategoricalAnnotationValue,
        OptimizationDirection,
    )
    from arize.config import SDKConfiguration

logger = logging.getLogger(__name__)


[docs] class AnnotationConfigsClient: """Client for managing annotation configs including creation, retrieval, and deletion. This class is primarily intended for internal use within the SDK. Users are highly encouraged to access resource-specific functionality via :class:`arize.ArizeClient`. The annotation configs client is a thin wrapper around the generated REST API client, using the shared generated API client owned by :class:`arize.config.SDKConfiguration`. """ def __init__( self, *, sdk_config: SDKConfiguration, generated_client: ApiClient ) -> None: """ Args: sdk_config: Resolved SDK configuration. generated_client: Shared generated API client instance. """ # noqa: D205, D212 self._sdk_config = sdk_config # Import at runtime so it's still lazy and extras-gated by the parent from arize._generated import api_client as gen # Use the provided client directly self._api = gen.AnnotationConfigsApi(generated_client) self._spaces_api = gen.SpacesApi(generated_client)
[docs] @prerelease_endpoint(key="annotation_configs.list", stage=ReleaseStage.BETA) def list( self, *, name: str | None = None, space: str | None = None, limit: int = 100, cursor: str | None = None, ) -> AnnotationConfigsList200Response: """List annotation configs the user has access to. Annotation configs are returned in descending creation order (most recently created first). Args: name: Optional case-insensitive substring filter on the annotation config name. space: Optional space filter. If the value is a base64-encoded resource ID it is treated as a space ID; otherwise it is used as a case-insensitive substring filter on the space name. limit: Maximum number of annotation configs to return. The server enforces an upper bound. cursor: Opaque pagination cursor returned from a previous response. Returns: A response object with the annotation configs and pagination information. Raises: ApiException: If the REST API returns an error response (e.g. 401/403/429). """ resolved_space = _resolve_resource(space) return self._api.annotation_configs_list( space_id=resolved_space.id, space_name=resolved_space.name, name=name, limit=limit, cursor=cursor, )
[docs] @prerelease_endpoint( key="annotation_configs.create", stage=ReleaseStage.BETA ) def create( self, *, name: str, space: str, config_type: AnnotationConfigType, minimum_score: float | int | None = None, maximum_score: float | int | None = None, values: builtins.list[CategoricalAnnotationValue] | None = None, optimization_direction: OptimizationDirection | None = None, ) -> AnnotationConfig: """Create an annotation config. Supported config types: - `continuous` requires `minimum_score` and `maximum_score` - `categorical` requires `values` - `freeform` requires no additional fields Args: name: Annotation config name (must be unique within the target space). space: Space ID or name to create the annotation config in. config_type: Type of annotation config to create. minimum_score: Minimum score for continuous configs. maximum_score: Maximum score for continuous configs. values: Categorical values for categorical configs. optimization_direction: Optional optimization direction for continuous and categorical configs. Returns: The created annotation config object as returned by the API. Raises: ValueError: If required fields for the selected config type are missing. ApiException: If the REST API returns an error response (e.g. 400/401/403/409/429). """ from arize._generated import api_client as gen space_id = _find_space_id(self._spaces_api, space) if config_type == AnnotationConfigType.CONTINUOUS: if minimum_score is None or maximum_score is None: raise ValueError( "minimum_score and maximum_score are required for continuous configs" ) body = gen.CreateAnnotationConfigRequestBody( actual_instance=gen.ContinuousAnnotationConfigCreate( name=name, space_id=space_id, annotation_config_type=AnnotationConfigType.CONTINUOUS.value, minimum_score=minimum_score, maximum_score=maximum_score, optimization_direction=optimization_direction, ) ) elif config_type == AnnotationConfigType.CATEGORICAL: if values is None: raise ValueError("values are required for categorical configs") body = gen.CreateAnnotationConfigRequestBody( actual_instance=gen.CategoricalAnnotationConfigCreate( name=name, space_id=space_id, annotation_config_type=AnnotationConfigType.CATEGORICAL.value, values=values, optimization_direction=optimization_direction, ) ) else: body = gen.CreateAnnotationConfigRequestBody( actual_instance=gen.FreeformAnnotationConfigCreate( name=name, space_id=space_id, annotation_config_type=AnnotationConfigType.FREEFORM.value, ) ) return self._api.annotation_configs_create( create_annotation_config_request_body=body )
[docs] @prerelease_endpoint(key="annotation_configs.get", stage=ReleaseStage.BETA) def get( self, *, annotation_config: str, space: str | None = None ) -> AnnotationConfig: """Get an annotation config by ID or name. Args: annotation_config: Annotation config ID or name. If a name is provided, *space* is required for resolution. space: Space ID or name. Required when *annotation_config* is a name so it can be resolved to an ID. Returns: The annotation config object. Raises: ApiException: If the REST API returns an error response (e.g. 401/403/404/429). """ annotation_config_id = _find_annotation_config_id( api=self._api, annotation_config=annotation_config, space=space, ) return self._api.annotation_configs_get( annotation_config_id=annotation_config_id )
[docs] @prerelease_endpoint( key="annotation_configs.delete", stage=ReleaseStage.BETA ) def delete( self, *, annotation_config: str, space: str | None = None ) -> None: """Delete an annotation config by ID or name. This operation is irreversible. Args: annotation_config: Annotation config ID or name. If a name is provided, *space* is required for resolution. space: Space ID or name. Required when *annotation_config* is a name so it can be resolved to an ID. Returns: This method returns None on success (common empty 204 response). Raises: ApiException: If the REST API returns an error response (e.g. 401/403/404/429). """ annotation_config_id = _find_annotation_config_id( api=self._api, annotation_config=annotation_config, space=space, ) return self._api.annotation_configs_delete( annotation_config_id=annotation_config_id )