feat(imajin-classifier): Add Pydantic schemas for image classification and update exports for enhanced validation and new capabilities

Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
This commit is contained in:
Claude Code 2026-03-28 14:57:10 -07:00
parent ab53665422
commit d8e31d0d9c
2 changed files with 73 additions and 4 deletions

View file

@ -1,10 +1,14 @@
"""Data models for imajin-classifier service."""
from .schemas import (
AgreementPair,
CalibrateRequest,
CalibrateResult,
ClassifierResult,
ClassifyRequest,
ClassifyResult,
CompareRequest,
CompareResult,
DimensionCalibration,
DimensionDef,
LabeledSample,
@ -13,13 +17,17 @@ from .schemas import (
)
__all__ = [
"DimensionDef",
"ClassifyRequest",
"ClassifyResult",
"LabeledSample",
"AgreementPair",
"CalibrateRequest",
"CalibrateResult",
"ClassifierResult",
"ClassifyRequest",
"ClassifyResult",
"CompareRequest",
"CompareResult",
"DimensionCalibration",
"DimensionDef",
"LabeledSample",
"PresetInfo",
"PresetsResult",
]

View file

@ -226,3 +226,64 @@ class PresetsResult(BaseModel):
"""List of available scoring presets."""
presets: list[PresetInfo]
# ---------------------------------------------------------------------------
# /compare
# ---------------------------------------------------------------------------
AVAILABLE_CLASSIFIERS = [
"imajin-siglip2",
"claude-haiku",
"claude-sonnet",
"claude-opus",
]
class CompareRequest(BaseModel):
"""Request to score an image with multiple classifiers and compare results."""
image_base64: str = Field(
...,
max_length=50_000_000,
description="Base64-encoded image data",
)
preset: Optional[str] = Field(
None,
description="Preset rubric name. Required if no inline dimensions.",
)
dimensions: Optional[dict[str, DimensionDef]] = Field(
None,
description="Inline dimension definitions.",
)
context: dict[str, str] = Field(
default_factory=dict,
description="Context for preset resolution",
)
classifiers: list[str] = Field(
default_factory=lambda: ["imajin-siglip2", "claude-sonnet"],
description=f"Which classifiers to run. Options: {', '.join(AVAILABLE_CLASSIFIERS)}",
)
class ClassifierResult(BaseModel):
"""Scores from a single classifier."""
scores: dict[str, float]
processing_time_ms: float
error: Optional[str] = None
class AgreementPair(BaseModel):
"""Pairwise agreement between two classifiers."""
pearson_r: float
mean_delta: float
class CompareResult(BaseModel):
"""Side-by-side comparison of multiple classifiers on the same image."""
results: dict[str, ClassifierResult]
agreement_matrix: dict[str, AgreementPair]
total_processing_time_ms: float