GuglielmoTor's picture
Create tasks.py
eab332f verified
raw
history blame
8.08 kB
# data_models/tasks.py
from enum import Enum
from typing import List, Optional, Literal
from pydantic import BaseModel, Field, field_validator
from datetime import datetime
# Using Literal for more precise string enums if preferred over Enum class for Pydantic
# However, Enum provides better structure and can be used with Field choices.
class EffortLevel(str, Enum):
"""Estimated effort level for a task."""
SMALL = "Small"
MEDIUM = "Medium"
LARGE = "Large"
class TaskType(str, Enum):
"""Type of task, indicating its nature."""
INITIATIVE = "initiative" # Action-oriented, new projects/changes
TRACKING = "tracking" # Measurement-focused, monitoring existing metrics/processes
class DataSubject(str, Enum):
"""Specifies the primary data domain a tracking task relates to."""
FOLLOWER_STATS = "follower_stats"
POSTS = "posts"
MENTIONS = "mentions"
GENERAL = "general" # For initiatives or tasks not tied to a single data type
class TimelineCategory(str, Enum):
"""Categorization of task timelines."""
IMMEDIATE = "Immediate" # (e.g., 1-2 weeks)
SHORT_TERM = "Short-term" # (e.g., rest of current quarter, up to 3 months)
MEDIUM_TERM = "Medium-term" # (e.g., next quarter, 3-6 months)
LONG_TERM = "Long-term" # (e.g., 6+ months)
class PriorityLevel(str, Enum):
"""Priority level for tasks."""
HIGH = "High"
MEDIUM = "Medium"
LOW = "Low"
class Task(BaseModel):
"""
Represents a single actionable task derived from analysis.
"""
task_category: str = Field(
description="The broader category or theme of the task (e.g., Content Strategy, Audience Engagement, Reputation Management, Performance Monitoring)."
)
task_description: str = Field( # Renamed from 'task' for clarity
description="A concise yet clear description of the specific action to be taken."
)
objective_deliverable: str = Field(
description="The clear, measurable objective this task aims to achieve and the specific deliverable(s) expected upon completion."
)
effort: EffortLevel = Field(
description="Estimated effort required to complete the task (Small, Medium, Large)."
)
timeline: TimelineCategory = Field(
description="Projected timeline for task completion, considering urgency and dependencies."
)
responsible_party: str = Field(
description="The team, role, or individual suggested to be responsible for executing this task (e.g., Marketing Team, Content Creation Lead, Social Media Manager)."
)
success_criteria_metrics: str = Field(
description="Specific, measurable criteria and metrics that will be used to determine if the task was successfully completed and achieved its objective."
)
dependencies_prerequisites: Optional[str] = Field(
default=None,
description="Any other tasks, resources, or conditions that must be met before this task can begin or be completed."
)
priority: PriorityLevel = Field(
description="The priority level of the task (High, Medium, Low)."
)
priority_justification: str = Field(
description="A brief explanation for the assigned priority level, linking it to impact or urgency."
)
why_proposed: str = Field(
description="The rationale behind proposing this task, clearly linking it back to specific findings or insights from the data analysis."
)
task_type: TaskType = Field(
description="Indicates whether this task is a new 'initiative' or ongoing 'tracking' of performance/metrics."
)
data_subject: Optional[DataSubject] = Field(
default=None,
description="For 'tracking' tasks, specifies the primary data subject (e.g., follower_stats, posts, mentions). Can be 'general' or null for 'initiative' tasks."
)
@field_validator('data_subject')
@classmethod
def check_data_subject_for_tracking(cls, value: Optional[DataSubject], values) -> Optional[DataSubject]:
# Pydantic v2 uses `values.data` to get other field values if needed before validation
# For Pydantic v1, it would be `values.get('task_type')`
# This example assumes Pydantic v2 structure for `values` if needed, but here we only need `task_type`
# which should already be validated or available.
# For simplicity, accessing it via `values.data.get('task_type')` in Pydantic v2 context.
# If using Pydantic v1, it's `values.get('task_type')`.
# Let's assume `values` is a dict-like object containing other fields.
# The validator structure depends on Pydantic version.
# For Pydantic v2, it's `info: ValidationInfo` and `info.data.get('task_type')`
# For Pydantic v1, `values` is a dict.
# For this example, let's assume `values` is a dict of the fields.
task_type_value = None
if hasattr(values, 'data'): # Pydantic v2 way
task_type_value = values.data.get('task_type')
elif isinstance(values, dict): # Pydantic v1 way (or if it's passed as a dict)
task_type_value = values.get('task_type')
if task_type_value == TaskType.TRACKING and value is None:
raise ValueError("For 'tracking' tasks, 'data_subject' must be specified.")
if task_type_value == TaskType.INITIATIVE and value is DataSubject.GENERAL:
# This is acceptable, or you might want to enforce it to be None
pass
return value
class KeyResult(BaseModel):
"""
A measurable outcome that contributes to an Objective.
"""
key_result_description: str = Field( # Renamed from 'key_result'
description="A clear, specific, and measurable description of the key result."
)
tasks: List[Task] = Field(
default_factory=list,
description="A list of specific tasks that will be undertaken to achieve this key result."
)
target_metric: Optional[str] = Field(
default=None,
description="The primary metric used to measure the achievement of this key result (e.g., 'Follower Growth Rate', 'Average Engagement Rate')."
)
target_value: Optional[str] = Field( # Can be numeric or descriptive (e.g., "Increase by 10%", "Achieve 5%")
default=None,
description="The specific target value for the metric (e.g., '5%', '1000 new followers')."
)
class OKR(BaseModel):
"""
Defines an Objective and its associated Key Results (OKRs).
"""
objective_description: str = Field( # Renamed from 'objective'
description="A high-level, qualitative goal that the team aims to achieve. Should be aspirational and motivating."
)
key_results: List[KeyResult] = Field(
default_factory=list,
description="A list of 2-5 specific, measurable, achievable, relevant, and time-bound (SMART) key results that define success for the objective."
)
objective_timeline: TimelineCategory = Field(
description="The overall timeline category for achieving this objective."
)
objective_owner: Optional[str] = Field(
default=None,
description="The team or individual primarily responsible for this objective."
)
class TaskExtractionOutput(BaseModel):
"""
Structured output from the TaskExtractionAgent, including context and OKRs.
"""
current_quarter_info: str = Field(
description="Information about the current quarter and days remaining (e.g., 'Q2 2025, 45 days remaining')."
)
okrs: List[OKR] = Field(
default_factory=list,
description="A list of Objectives and Key Results (OKRs) derived from the analysis."
)
overall_strategic_focus: Optional[str] = Field(
default=None,
description="A brief summary of the main strategic focus areas identified from the tasks."
)
generation_timestamp: str = Field(
default_factory=lambda: datetime.utcnow().isoformat(),
description="Timestamp of when this task extraction output was generated."
)