Spaces:
Running
Running
# 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." | |
) | |
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." | |
) | |