Anuj2209's picture
initialized project
cabe7a5
Raw
History Blame Contribute Delete
2.89 kB
"""Ticket data model with ground-truth labels for deterministic grading."""
from __future__ import annotations
from typing import Literal
from pydantic import BaseModel, Field
Category = Literal[
"billing",
"bug_report",
"feature_request",
"account_access",
"general_inquiry",
"cancellation",
]
Priority = Literal["low", "medium", "high", "critical"]
Department = Literal["billing", "technical", "account", "general"]
Sentiment = Literal["angry", "frustrated", "neutral", "satisfied"]
CustomerTier = Literal["free", "pro", "enterprise"]
Difficulty = Literal["easy", "medium", "hard"]
EscalationTarget = Literal["l2_support", "engineering", "management"]
CustomerValue = Literal["low", "medium", "high"]
SLA_DEFAULTS: dict[str, int] = {
"low": 8,
"medium": 6,
"high": 4,
"critical": 3,
}
CUSTOMER_VALUE_PENALTY_MULTIPLIER: dict[str, float] = {
"low": 1.0,
"medium": 1.3,
"high": 1.8,
}
class KeywordSpec(BaseModel):
"""Weighted keyword specification for grading text quality.
*required* β€” must appear; 60 % of quality score.
*optional* β€” bonus if present; 40 % of quality score.
*forbidden* β€” penalty per match (``-0.03`` each).
*min_required_hits* β€” hard floor; score halved when not met.
"""
model_config = {"frozen": True}
required: list[str] = Field(default_factory=list)
optional: list[str] = Field(default_factory=list)
forbidden: list[str] = Field(default_factory=list)
min_required_hits: int = 0
class TicketData(BaseModel):
"""Ground-truth ticket used internally by the environment."""
model_config = {"frozen": True}
ticket_id: str
ticket_text: str
customer_sentiment: Sentiment
customer_tier: CustomerTier
gold_category: Category
gold_priority: Priority
gold_department: Department
response_spec: KeywordSpec = Field(default_factory=KeywordSpec)
resolution_spec: KeywordSpec = Field(default_factory=KeywordSpec)
requires_escalation: bool = False
escalation_reason: str | None = None
escalation_target: EscalationTarget | None = None
compensation_range: tuple[float, float] | None = None
constraints: list[str] = Field(default_factory=list)
difficulty: Difficulty
category_hint: str | None = None
# --- v2 fields ---
customer_value: CustomerValue = "medium"
sla_steps: int | None = None
secondary_category: Category | None = None
distractors: list[str] = Field(default_factory=list)
partial_info: bool = False
info_reveals: str | None = None
@property
def effective_sla_steps(self) -> int:
if self.sla_steps is not None:
return self.sla_steps
return SLA_DEFAULTS[self.gold_priority]
@property
def penalty_multiplier(self) -> float:
return CUSTOMER_VALUE_PENALTY_MULTIPLIER[self.customer_value]