# 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, field_validator
from typing import Any, ClassVar, Dict, List, Optional, Union
from typing_extensions import Annotated
from typing import Optional, Set
from typing_extensions import Self

class DocumentGraphExtractorParams(BaseModel):
    """
    Parameters for the document graph extractor.  This extractor decomposes PDFs into spatial blocks with layout classification, confidence scoring, and optional VLM correction for degraded documents.  **When to Use**:     - Historical/archival document processing (FBI files, old records)     - Scanned documents with mixed quality     - Documents requiring spatial understanding (forms, tables, multi-column)     - When you need block-level granularity with bounding boxes     - When confidence scoring is needed for downstream filtering  **When NOT to Use**:     - Simple text-only documents -> Use text_extractor instead     - When page-level granularity is sufficient -> Use pdf_extractor instead     - Real-time processing requirements -> VLM correction adds latency
    """ # noqa: E501
    extractor_type: Optional[StrictStr] = Field(default='document_graph_extractor', description="Discriminator field for parameter type identification. Must be 'document_graph_extractor'.")
    use_layout_detection: Optional[StrictBool] = Field(default=True, description="Enable ML-based layout detection to find ALL document elements (text, images, tables, figures). When enabled, uses the configured layout_detector to detect and extract both text regions AND non-text elements (scanned images, figures, charts) as separate documents. **Recommended for**: Scanned documents, image-heavy PDFs, mixed content documents. **When disabled**: Falls back to text-only extraction (faster but misses images). Default: True (detects all elements including images).")
    layout_detector: Optional[StrictStr] = Field(default='pymupdf', description="Layout detection engine to use when use_layout_detection=True. 'pymupdf': Fast, rule-based detection using PyMuPDF heuristics (~15 pages/sec). 'docling': SOTA ML-based detection using IBM Docling with DiT model (~3-8 sec/doc). **Docling advantages**: Better semantic type detection (section_header vs paragraph), true table structure extraction (rows/cols), more accurate figure detection. **PyMuPDF advantages**: Much faster, lower memory usage, simpler dependencies. Default: 'pymupdf' for speed. Use 'docling' for accuracy-critical applications.")
    vertical_threshold: Optional[Union[Annotated[float, Field(le=100.0, strict=True, ge=1.0)], Annotated[int, Field(le=100, strict=True, ge=1)]]] = Field(default=15.0, description="Maximum vertical gap (in points) between lines to be grouped in same block. Increase for looser grouping, decrease for tighter blocks. Default 15pt works well for standard documents.")
    horizontal_threshold: Optional[Union[Annotated[float, Field(le=200.0, strict=True, ge=1.0)], Annotated[int, Field(le=200, strict=True, ge=1)]]] = Field(default=50.0, description="Maximum horizontal distance (in points) for overlap detection. Affects column detection and block merging. Increase for wider columns, decrease for narrow layouts.")
    min_text_length: Optional[Annotated[int, Field(le=500, strict=True, ge=1)]] = Field(default=20, description="Minimum text length (characters) to keep a block. Blocks with less text are filtered out. Helps remove noise and tiny fragments.")
    base_confidence: Optional[Union[Annotated[float, Field(le=1.0, strict=True, ge=0.0)], Annotated[int, Field(le=1, strict=True, ge=0)]]] = Field(default=0.85, description="Base confidence score for embedded (native) text. Penalties are subtracted for OCR artifacts, encoding issues, etc.")
    min_confidence_for_vlm: Optional[Union[Annotated[float, Field(le=1.0, strict=True, ge=0.0)], Annotated[int, Field(le=1, strict=True, ge=0)]]] = Field(default=0.6, description="Confidence threshold below which VLM correction is triggered. Blocks with confidence < this value get sent to VLM for correction. Only applies when use_vlm_correction=True.")
    use_vlm_correction: Optional[StrictBool] = Field(default=True, description="Enable VLM (Vision Language Model) correction for low-confidence blocks. Uses Gemini/GPT-4V to correct OCR errors by analyzing the page image. Significantly slower (~1 page/sec) but improves accuracy for degraded docs.")
    fast_mode: Optional[StrictBool] = Field(default=False, description="Skip VLM correction entirely for maximum throughput (~15 pages/sec). Overrides use_vlm_correction. Use when speed is more important than accuracy.")
    vlm_provider: Optional[StrictStr] = Field(default='google', description="LLM provider for VLM correction. Options: 'google' (Gemini), 'openai' (GPT-4V), 'anthropic' (Claude). Google recommended for best vision quality.")
    vlm_model: Optional[StrictStr] = Field(default='gemini-2.0-flash', description="Specific model for VLM correction. Examples: 'gemini-2.0-flash', 'gpt-4o', 'claude-3-5-sonnet'.")
    llm_api_key: Optional[StrictStr] = Field(default=None, description="API key for VLM correction (BYOK - Bring Your Own Key). Supports: - Direct key: 'sk-proj-abc123...' - Secret reference: '{{SECRET.openai_api_key}}'  When using secret reference, the key is loaded from your organization's secrets vault at runtime. Store secrets via POST /v1/organizations/secrets.  If not provided, uses Mixpeek's default API keys.")
    run_text_embedding: Optional[StrictBool] = Field(default=True, description="Generate text embeddings for semantic search over block content. Uses E5-Large (1024-dim) for multilingual support.")
    render_dpi: Optional[Annotated[int, Field(le=300, strict=True, ge=72)]] = Field(default=150, description="DPI for page rendering (used for VLM correction). 72: Fast, lower quality. 150: Balanced (recommended). 300: High quality, slower.")
    generate_thumbnails: Optional[StrictBool] = Field(default=True, description="Generate thumbnail images for blocks. Useful for visual previews and UI display.")
    thumbnail_mode: Optional[StrictStr] = Field(default='both', description="Thumbnail generation mode. 'full_page': Low-res thumbnail of entire page. 'segment': Cropped thumbnail of just the block's bounding box. 'both': Generate both types (recommended for flexibility).")
    thumbnail_dpi: Optional[Annotated[int, Field(le=150, strict=True, ge=36)]] = Field(default=72, description="DPI for thumbnail generation. Lower DPI = smaller files. 72: Standard web quality. 36: Very small thumbnails.")
    __properties: ClassVar[List[str]] = ["extractor_type", "use_layout_detection", "layout_detector", "vertical_threshold", "horizontal_threshold", "min_text_length", "base_confidence", "min_confidence_for_vlm", "use_vlm_correction", "fast_mode", "vlm_provider", "vlm_model", "llm_api_key", "run_text_embedding", "render_dpi", "generate_thumbnails", "thumbnail_mode", "thumbnail_dpi"]

    @field_validator('extractor_type')
    def extractor_type_validate_enum(cls, value):
        """Validates the enum"""
        if value is None:
            return value

        if value not in set(['document_graph_extractor']):
            raise ValueError("must be one of enum values ('document_graph_extractor')")
        return value

    @field_validator('layout_detector')
    def layout_detector_validate_enum(cls, value):
        """Validates the enum"""
        if value is None:
            return value

        if value not in set(['pymupdf', 'docling']):
            raise ValueError("must be one of enum values ('pymupdf', 'docling')")
        return value

    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 DocumentGraphExtractorParams 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 DocumentGraphExtractorParams from a dict"""
        if obj is None:
            return None

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

        _obj = cls.model_validate({
            "extractor_type": obj.get("extractor_type") if obj.get("extractor_type") is not None else 'document_graph_extractor',
            "use_layout_detection": obj.get("use_layout_detection") if obj.get("use_layout_detection") is not None else True,
            "layout_detector": obj.get("layout_detector") if obj.get("layout_detector") is not None else 'pymupdf',
            "vertical_threshold": obj.get("vertical_threshold") if obj.get("vertical_threshold") is not None else 15.0,
            "horizontal_threshold": obj.get("horizontal_threshold") if obj.get("horizontal_threshold") is not None else 50.0,
            "min_text_length": obj.get("min_text_length") if obj.get("min_text_length") is not None else 20,
            "base_confidence": obj.get("base_confidence") if obj.get("base_confidence") is not None else 0.85,
            "min_confidence_for_vlm": obj.get("min_confidence_for_vlm") if obj.get("min_confidence_for_vlm") is not None else 0.6,
            "use_vlm_correction": obj.get("use_vlm_correction") if obj.get("use_vlm_correction") is not None else True,
            "fast_mode": obj.get("fast_mode") if obj.get("fast_mode") is not None else False,
            "vlm_provider": obj.get("vlm_provider") if obj.get("vlm_provider") is not None else 'google',
            "vlm_model": obj.get("vlm_model") if obj.get("vlm_model") is not None else 'gemini-2.0-flash',
            "llm_api_key": obj.get("llm_api_key"),
            "run_text_embedding": obj.get("run_text_embedding") if obj.get("run_text_embedding") is not None else True,
            "render_dpi": obj.get("render_dpi") if obj.get("render_dpi") is not None else 150,
            "generate_thumbnails": obj.get("generate_thumbnails") if obj.get("generate_thumbnails") is not None else True,
            "thumbnail_mode": obj.get("thumbnail_mode") if obj.get("thumbnail_mode") is not None else 'both',
            "thumbnail_dpi": obj.get("thumbnail_dpi") if obj.get("thumbnail_dpi") is not None else 72
        })
        return _obj


