thangvip's picture
feat: deploy complete Compliment Forest app
9dad6a7 verified
Raw
History Blame
2.86 kB
from __future__ import annotations
from typing import Literal
from pydantic import BaseModel, ConfigDict, Field, field_validator
class StrictModel(BaseModel):
model_config = ConfigDict(extra="forbid", str_strip_whitespace=True)
class Clearing(StrictModel):
creature: str = Field(min_length=3, max_length=80)
strength: str = Field(min_length=3, max_length=100)
line: str = Field(min_length=12, max_length=360)
reflection: str = Field(min_length=12, max_length=260)
spell: str = Field(min_length=3, max_length=80)
image_prompt: str = Field(min_length=8, max_length=300)
@field_validator("spell")
@classmethod
def validate_spell(cls, value: str) -> str:
if not value.lower().startswith(("i ", "i'm ", "i am ")):
raise ValueError("spell must be a first-person present-tense mantra")
if len(value.split()) > 12:
raise ValueError("spell must contain at most 12 words")
return value
class ForestDraft(StrictModel):
forest_title: str = Field(min_length=3, max_length=120)
proposed_strengths: list[str] = Field(min_length=3, max_length=6)
clearings: list[Clearing] = Field(min_length=1, max_length=6)
@field_validator("proposed_strengths")
@classmethod
def validate_unique_strengths(cls, values: list[str]) -> list[str]:
normalized = {value.casefold() for value in values}
if len(normalized) != len(values):
raise ValueError("proposed strengths must be unique")
return values
class CriticScore(StrictModel):
index: int = Field(ge=0, le=5)
specificity: int = Field(ge=1, le=5)
warmth: int = Field(ge=1, le=5)
non_genericness: int = Field(ge=1, le=5)
non_toxic_positivity: int = Field(ge=1, le=5)
reason: str = Field(min_length=3, max_length=240)
class CriticDecision(StrictModel):
keep_indices: list[int] = Field(min_length=1, max_length=6)
revise_indices: list[int] = Field(default_factory=list, max_length=6)
reasons: dict[str, str] = Field(default_factory=dict)
scores: list[CriticScore] = Field(default_factory=list, max_length=6)
@field_validator("keep_indices", "revise_indices")
@classmethod
def validate_unique_indices(cls, values: list[int]) -> list[int]:
if len(set(values)) != len(values):
raise ValueError("indices must be unique")
if any(index < 0 or index > 5 for index in values):
raise ValueError("indices must be between zero and five")
return values
class GuardResult(StrictModel):
allowed: bool
category: Literal["ok", "invalid", "crisis", "abuse", "medical"]
message: str = ""
class StreamEvent(StrictModel):
type: Literal["status", "support", "forest", "clearing", "complete", "error"]
message: str = ""
data: dict[str, object] = Field(default_factory=dict)