# coding: utf-8

"""
    Mixpeek API

    This is the Mixpeek API, providing access to various endpoints for data processing and retrieval.

    The version of the OpenAPI document: 1.3.0
    Contact: info@mixpeek.com
    Generated by OpenAPI Generator (https://openapi-generator.tech)

    Do not edit the class manually.
"""  # noqa: E501


from __future__ import annotations
import pprint
import re  # noqa: F401
import json

from pydantic import BaseModel, ConfigDict, Field, StrictBool, StrictStr
from typing import Any, ClassVar, Dict, List, Optional
from typing_extensions import Annotated
from mixpeek.models.bucket_schema_field_type import BucketSchemaFieldType
from mixpeek.models.vector_data_type import VectorDataType
from mixpeek.models.vector_purpose import VectorPurpose
from mixpeek.models.vector_type import VectorType
from typing import Optional, Set
from typing_extensions import Self

class VectorIndex(BaseModel):
    """
    Configuration for a single vector index in Qdrant.  Defines the fully-qualified vector index including storage name, dimensions, distance metric, and inference service. This is the actual index that gets created in Qdrant and used for vector similarity search.  Key Concepts:     - The `name` field is the FULL qualified name used as the Qdrant collection name     - Format: {extractor}_{version}_{output} (e.g., \"text_extractor_v1_embedding\")     - This ensures namespace isolation between extractors and versions     - Different from VectorIndexDefinition.name which is the short user-facing name  Use Cases:     - Define vector storage configuration for feature extractors     - Specify inference service and model parameters     - Configure distance metrics for similarity search     - Set storage optimization (on-disk for large vectors)  Requirements:     - name: REQUIRED - Must be unique across all extractors in namespace     - description: REQUIRED - Explain what this vector represents     - dimensions: REQUIRED for DENSE vectors, OPTIONAL for SPARSE     - type: REQUIRED - Must match VectorType enum     - inference_name: REQUIRED - Must reference a valid inference service
    """ # noqa: E501
    name: Optional[StrictStr] = Field(default=None, description="OPTIONAL. Qdrant named vector identifier. If not provided, auto-derived from inference_service_id using the same conversion as inference_name (org/model -> org__model with hyphens as underscores). This enables cross-extractor compatibility: extractors using the same model will share the same named vector in Qdrant, allowing direct vector search across collections without fusion logic.")
    description: Annotated[str, Field(min_length=10, strict=True)] = Field(description="REQUIRED. Human-readable description of what this vector index represents. Explain the content type, use cases, and search characteristics. Shown in API documentation and collection metadata. Be specific about what embeddings are stored here.")
    dimensions: Optional[Annotated[int, Field(strict=True, ge=1)]] = Field(default=None, description="Number of vector dimensions. REQUIRED for DENSE vectors (e.g., 1024 for E5-Large, 1408 for multimodal). NOT REQUIRED for SPARSE vectors (dimensions determined dynamically). Must match the output dimensions of the inference service. Cannot be changed after index creation without recreating the collection.")
    type: VectorType = Field(description="REQUIRED. Vector storage format type. Determines how vectors are stored and searched in Qdrant. Use DENSE for traditional embeddings (most common), SPARSE for keyword-based models like SPLADE, MULTI_DENSE for late-interaction models like ColBERT. Must match the output format of your inference service.")
    distance: Optional[StrictStr] = Field(default='cosine', description="Distance metric for similarity search. OPTIONAL - defaults to 'cosine' (normalized dot product). Options: 'cosine' (most common, normalized), 'dot' (raw dot product), 'euclidean' (L2 distance), 'manhattan' (L1 distance). Cosine recommended for most embeddings as it's scale-invariant. Must match the metric your model was trained with.")
    datatype: Optional[VectorDataType] = Field(default=None, description="Data type for storing vector values. OPTIONAL - defaults to FLOAT32 (standard precision). Use FLOAT32 for general use (4 bytes per dimension). Use FLOAT16 to save 50% storage with minimal quality loss. Use UINT8 for maximum compression (quantization, ~2% quality loss). Lower precision = smaller storage + faster search, slightly lower accuracy.")
    on_disk: Optional[StrictBool] = Field(default=None, description="OPTIONAL. If true, vectors stored on disk instead of RAM. Defaults to true for memory efficiency. Set to false for faster search with higher memory usage. Trade-off: on_disk=true saves ~95% RAM but ~10x slower search. Recommended to keep default (true) unless RAM is abundant and low latency critical.")
    supported_inputs: Optional[List[BucketSchemaFieldType]] = Field(default=None, description="OPTIONAL. List of bucket schema field types this vector can process. Validates that input fields are compatible with this index. Examples: TEXT and STRING for text embeddings, VIDEO and IMAGE for multimodal embeddings, DOCUMENT for PDF extractors. Used for validation during collection creation.")
    inference_name: Optional[StrictStr] = Field(default=None, description="DEPRECATED: Use inference_service_id instead. Identifier of the inference service to generate embeddings. Must reference a valid inference service registered in the system. Examples: 'multilingual_e5_large_instruct_v1' for text, 'vertex_multimodal_embedding' for video, 'laion_clip_vit_l_14_v1' for images. This determines which model creates the vectors during ingestion. Cannot be changed after collection creation.")
    inference_service_id: Optional[StrictStr] = Field(default=None, description="RECOMMENDED. Service ID in org/name format (e.g., 'intfloat/e5-large'). When set, dimensions and distance are automatically derived from the registry. This is the canonical identifier for cross-plugin compatibility. Plugins using the same service_id can search across each other's vectors. Takes precedence over inference_name when both are set.")
    purpose: Optional[VectorPurpose] = Field(default=None, description="RECOMMENDED. Semantic purpose of this vector index. Enables pipelines to look up vector configs by purpose (text, code, image) without needing to know the specific inference_service_id. This provides automatic configuration - the pipeline just says 'give me the text vector' and gets the correct column name. If not specified, pipeline must use inference_service_id lookup.")
    vector_name_override: Optional[StrictStr] = Field(default=None, description="OPTIONAL. Override for Qdrant named vector identifier. When set, this value is used as the Qdrant vector name instead of auto-deriving from inference_service_id. This enables multiple vectors from the same embedding model with different storage names. The inference_service_id is still used for cross-extractor compatibility checking, but storage uses this custom name. Use case: A single extractor producing N vectors (e.g., title_embedding, body_embedding) using the same model but needing separate storage.")
    __properties: ClassVar[List[str]] = ["name", "description", "dimensions", "type", "distance", "datatype", "on_disk", "supported_inputs", "inference_name", "inference_service_id", "purpose", "vector_name_override"]

    model_config = ConfigDict(
        populate_by_name=True,
        validate_assignment=True,
        protected_namespaces=(),
    )


    def to_str(self) -> str:
        """Returns the string representation of the model using alias"""
        return pprint.pformat(self.model_dump(by_alias=True))

    def to_json(self) -> str:
        """Returns the JSON representation of the model using alias"""
        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
        return json.dumps(self.to_dict())

    @classmethod
    def from_json(cls, json_str: str) -> Optional[Self]:
        """Create an instance of VectorIndex from a JSON string"""
        return cls.from_dict(json.loads(json_str))

    def to_dict(self) -> Dict[str, Any]:
        """Return the dictionary representation of the model using alias.

        This has the following differences from calling pydantic's
        `self.model_dump(by_alias=True)`:

        * `None` is only added to the output dict for nullable fields that
          were set at model initialization. Other fields with value `None`
          are ignored.
        """
        excluded_fields: Set[str] = set([
        ])

        _dict = self.model_dump(
            by_alias=True,
            exclude=excluded_fields,
            exclude_none=True,
        )
        return _dict

    @classmethod
    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
        """Create an instance of VectorIndex from a dict"""
        if obj is None:
            return None

        if not isinstance(obj, dict):
            return cls.model_validate(obj)

        _obj = cls.model_validate({
            "name": obj.get("name"),
            "description": obj.get("description"),
            "dimensions": obj.get("dimensions"),
            "type": obj.get("type"),
            "distance": obj.get("distance") if obj.get("distance") is not None else 'cosine',
            "datatype": obj.get("datatype"),
            "on_disk": obj.get("on_disk"),
            "supported_inputs": obj.get("supported_inputs"),
            "inference_name": obj.get("inference_name"),
            "inference_service_id": obj.get("inference_service_id"),
            "purpose": obj.get("purpose"),
            "vector_name_override": obj.get("vector_name_override")
        })
        return _obj


