Initial commit
This commit is contained in:
242
backend/app/schemas/settings.py
Normal file
242
backend/app/schemas/settings.py
Normal file
@@ -0,0 +1,242 @@
|
||||
"""Pydantic schemas for application-level runtime settings."""
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
|
||||
class ProviderSettingsResponse(BaseModel):
|
||||
"""Represents a persisted model provider with non-secret connection metadata."""
|
||||
|
||||
id: str
|
||||
label: str
|
||||
provider_type: str = "openai_compatible"
|
||||
base_url: str
|
||||
timeout_seconds: int
|
||||
api_key_set: bool
|
||||
api_key_masked: str = ""
|
||||
|
||||
|
||||
class ProviderSettingsUpdateRequest(BaseModel):
|
||||
"""Represents a model provider create-or-update request."""
|
||||
|
||||
id: str
|
||||
label: str
|
||||
provider_type: str = "openai_compatible"
|
||||
base_url: str
|
||||
timeout_seconds: int = Field(default=45, ge=5, le=180)
|
||||
api_key: str | None = None
|
||||
clear_api_key: bool = False
|
||||
|
||||
|
||||
class OcrTaskSettingsResponse(BaseModel):
|
||||
"""Represents OCR task runtime settings and prompt configuration."""
|
||||
|
||||
enabled: bool
|
||||
provider_id: str
|
||||
model: str
|
||||
prompt: str
|
||||
|
||||
|
||||
class OcrTaskSettingsUpdateRequest(BaseModel):
|
||||
"""Represents OCR task settings updates."""
|
||||
|
||||
enabled: bool | None = None
|
||||
provider_id: str | None = None
|
||||
model: str | None = None
|
||||
prompt: str | None = None
|
||||
|
||||
|
||||
class SummaryTaskSettingsResponse(BaseModel):
|
||||
"""Represents summarization task runtime settings."""
|
||||
|
||||
enabled: bool
|
||||
provider_id: str
|
||||
model: str
|
||||
prompt: str
|
||||
max_input_tokens: int
|
||||
|
||||
|
||||
class SummaryTaskSettingsUpdateRequest(BaseModel):
|
||||
"""Represents summarization task settings updates."""
|
||||
|
||||
enabled: bool | None = None
|
||||
provider_id: str | None = None
|
||||
model: str | None = None
|
||||
prompt: str | None = None
|
||||
max_input_tokens: int | None = Field(default=None, ge=512, le=64000)
|
||||
|
||||
|
||||
class RoutingTaskSettingsResponse(BaseModel):
|
||||
"""Represents routing task runtime settings for path and tag classification."""
|
||||
|
||||
enabled: bool
|
||||
provider_id: str
|
||||
model: str
|
||||
prompt: str
|
||||
neighbor_count: int
|
||||
neighbor_min_similarity: float
|
||||
auto_apply_confidence_threshold: float
|
||||
auto_apply_neighbor_similarity_threshold: float
|
||||
neighbor_path_override_enabled: bool
|
||||
neighbor_path_override_min_similarity: float
|
||||
neighbor_path_override_min_gap: float
|
||||
neighbor_path_override_max_confidence: float
|
||||
|
||||
|
||||
class RoutingTaskSettingsUpdateRequest(BaseModel):
|
||||
"""Represents routing task settings updates."""
|
||||
|
||||
enabled: bool | None = None
|
||||
provider_id: str | None = None
|
||||
model: str | None = None
|
||||
prompt: str | None = None
|
||||
neighbor_count: int | None = Field(default=None, ge=1, le=40)
|
||||
neighbor_min_similarity: float | None = Field(default=None, ge=0.0, le=1.0)
|
||||
auto_apply_confidence_threshold: float | None = Field(default=None, ge=0.0, le=1.0)
|
||||
auto_apply_neighbor_similarity_threshold: float | None = Field(default=None, ge=0.0, le=1.0)
|
||||
neighbor_path_override_enabled: bool | None = None
|
||||
neighbor_path_override_min_similarity: float | None = Field(default=None, ge=0.0, le=1.0)
|
||||
neighbor_path_override_min_gap: float | None = Field(default=None, ge=0.0, le=1.0)
|
||||
neighbor_path_override_max_confidence: float | None = Field(default=None, ge=0.0, le=1.0)
|
||||
|
||||
|
||||
class UploadDefaultsResponse(BaseModel):
|
||||
"""Represents default upload destination and default tags."""
|
||||
|
||||
logical_path: str
|
||||
tags: list[str] = Field(default_factory=list)
|
||||
|
||||
|
||||
class UploadDefaultsUpdateRequest(BaseModel):
|
||||
"""Represents updates for default upload destination and default tags."""
|
||||
|
||||
logical_path: str | None = None
|
||||
tags: list[str] | None = None
|
||||
|
||||
|
||||
class DisplaySettingsResponse(BaseModel):
|
||||
"""Represents document-list display preferences."""
|
||||
|
||||
cards_per_page: int = Field(default=12, ge=1, le=200)
|
||||
log_typing_animation_enabled: bool = True
|
||||
|
||||
|
||||
class DisplaySettingsUpdateRequest(BaseModel):
|
||||
"""Represents updates for document-list display preferences."""
|
||||
|
||||
cards_per_page: int | None = Field(default=None, ge=1, le=200)
|
||||
log_typing_animation_enabled: bool | None = None
|
||||
|
||||
|
||||
class PredefinedPathEntryResponse(BaseModel):
|
||||
"""Represents one predefined logical path with global discoverability scope."""
|
||||
|
||||
value: str
|
||||
global_shared: bool
|
||||
|
||||
|
||||
class PredefinedPathEntryUpdateRequest(BaseModel):
|
||||
"""Represents one predefined logical path create-or-update request."""
|
||||
|
||||
value: str
|
||||
global_shared: bool = False
|
||||
|
||||
|
||||
class PredefinedTagEntryResponse(BaseModel):
|
||||
"""Represents one predefined tag with global discoverability scope."""
|
||||
|
||||
value: str
|
||||
global_shared: bool
|
||||
|
||||
|
||||
class PredefinedTagEntryUpdateRequest(BaseModel):
|
||||
"""Represents one predefined tag create-or-update request."""
|
||||
|
||||
value: str
|
||||
global_shared: bool = False
|
||||
|
||||
|
||||
class HandwritingStyleSettingsResponse(BaseModel):
|
||||
"""Represents handwriting-style clustering settings used by Typesense image embeddings."""
|
||||
|
||||
enabled: bool
|
||||
embed_model: str
|
||||
neighbor_limit: int
|
||||
match_min_similarity: float
|
||||
bootstrap_match_min_similarity: float
|
||||
bootstrap_sample_size: int
|
||||
image_max_side: int
|
||||
|
||||
|
||||
class HandwritingStyleSettingsUpdateRequest(BaseModel):
|
||||
"""Represents updates for handwriting-style clustering and match thresholds."""
|
||||
|
||||
enabled: bool | None = None
|
||||
embed_model: str | None = None
|
||||
neighbor_limit: int | None = Field(default=None, ge=1, le=32)
|
||||
match_min_similarity: float | None = Field(default=None, ge=0.0, le=1.0)
|
||||
bootstrap_match_min_similarity: float | None = Field(default=None, ge=0.0, le=1.0)
|
||||
bootstrap_sample_size: int | None = Field(default=None, ge=1, le=30)
|
||||
image_max_side: int | None = Field(default=None, ge=256, le=4096)
|
||||
|
||||
|
||||
class TaskSettingsResponse(BaseModel):
|
||||
"""Represents all task-level model bindings and prompt settings."""
|
||||
|
||||
ocr_handwriting: OcrTaskSettingsResponse
|
||||
summary_generation: SummaryTaskSettingsResponse
|
||||
routing_classification: RoutingTaskSettingsResponse
|
||||
|
||||
|
||||
class TaskSettingsUpdateRequest(BaseModel):
|
||||
"""Represents partial updates for task-level settings."""
|
||||
|
||||
ocr_handwriting: OcrTaskSettingsUpdateRequest | None = None
|
||||
summary_generation: SummaryTaskSettingsUpdateRequest | None = None
|
||||
routing_classification: RoutingTaskSettingsUpdateRequest | None = None
|
||||
|
||||
|
||||
class AppSettingsResponse(BaseModel):
|
||||
"""Represents all application settings exposed by the API."""
|
||||
|
||||
upload_defaults: UploadDefaultsResponse
|
||||
display: DisplaySettingsResponse
|
||||
handwriting_style_clustering: HandwritingStyleSettingsResponse
|
||||
predefined_paths: list[PredefinedPathEntryResponse] = Field(default_factory=list)
|
||||
predefined_tags: list[PredefinedTagEntryResponse] = Field(default_factory=list)
|
||||
providers: list[ProviderSettingsResponse]
|
||||
tasks: TaskSettingsResponse
|
||||
|
||||
|
||||
class AppSettingsUpdateRequest(BaseModel):
|
||||
"""Represents full settings update input for providers and task bindings."""
|
||||
|
||||
upload_defaults: UploadDefaultsUpdateRequest | None = None
|
||||
display: DisplaySettingsUpdateRequest | None = None
|
||||
handwriting_style_clustering: HandwritingStyleSettingsUpdateRequest | None = None
|
||||
predefined_paths: list[PredefinedPathEntryUpdateRequest] | None = None
|
||||
predefined_tags: list[PredefinedTagEntryUpdateRequest] | None = None
|
||||
providers: list[ProviderSettingsUpdateRequest] | None = None
|
||||
tasks: TaskSettingsUpdateRequest | None = None
|
||||
|
||||
|
||||
class HandwritingSettingsResponse(BaseModel):
|
||||
"""Represents legacy handwriting response shape kept for backward compatibility."""
|
||||
|
||||
provider: str = "openai_compatible"
|
||||
enabled: bool
|
||||
openai_base_url: str
|
||||
openai_model: str
|
||||
openai_timeout_seconds: int
|
||||
openai_api_key_set: bool
|
||||
openai_api_key_masked: str = ""
|
||||
|
||||
|
||||
class HandwritingSettingsUpdateRequest(BaseModel):
|
||||
"""Represents legacy handwriting update shape kept for backward compatibility."""
|
||||
|
||||
enabled: bool | None = None
|
||||
openai_base_url: str | None = None
|
||||
openai_model: str | None = None
|
||||
openai_timeout_seconds: int | None = Field(default=None, ge=5, le=180)
|
||||
openai_api_key: str | None = None
|
||||
clear_openai_api_key: bool = False
|
||||
Reference in New Issue
Block a user