44 lines
1.8 KiB
Python
44 lines
1.8 KiB
Python
"""The triage verdict exchanged with the intake-gate model.
|
|
|
|
Pure module: no FastAPI imports and no HTTPException.
|
|
|
|
``extra="forbid"`` is load-bearing — it emits ``additionalProperties: false``, which
|
|
the structured-outputs schema dialect requires (same reason as
|
|
app/models/scoring.py:22-23). Every field is required: structured outputs puts all
|
|
declared properties in ``required``, so a defaulted field buys nothing here.
|
|
|
|
Mirrors agent/models.py — this package's models.py holds the shape the LLM pass
|
|
exchanges, not a SQLModel table. The triage TABLE lives in inbox/models.py beside
|
|
Inbox_Messages, because it is an inbox-domain fact and this package never opens a
|
|
session.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from pydantic import BaseModel, ConfigDict, Field
|
|
|
|
from inbox_classifier.enums import Triage_Reason_Code
|
|
|
|
|
|
class EmailTriageVerdict(BaseModel):
|
|
"""One intake decision about one email.
|
|
|
|
``confidence`` carries the model's doubt so the boolean does not have to. The
|
|
prompt tells it to answer the boolean the way a recruiter would want and to report
|
|
uncertainty here instead, which is what makes INBOX_TRIAGE_MIN_CONFIDENCE a usable
|
|
knob rather than a second, contradictory gate.
|
|
|
|
reason_code is the Triage_Reason_Code enum rather than a Literal, so the labels
|
|
live in one place; Pydantic renders it as the same JSON-schema enum either way.
|
|
"""
|
|
|
|
model_config = ConfigDict(extra="forbid")
|
|
|
|
is_application: bool
|
|
reason_code: Triage_Reason_Code
|
|
confidence: float = Field(ge=0.0, le=1.0)
|
|
# One clause naming the signal used. Stored for the review screen, never logged:
|
|
# the model is told not to quote personal data, but it is still model-authored
|
|
# text derived from an email body.
|
|
evidence: str = Field(min_length=1, max_length=200)
|