Spaces:
Sleeping
Sleeping
Update features/insight_and_tasks/agents/task_extraction_agent.py
Browse files
features/insight_and_tasks/agents/task_extraction_agent.py
CHANGED
@@ -43,7 +43,7 @@ class TaskExtractionAgent:
|
|
43 |
current_date: The current date to use for quarter calculations. Defaults to today.
|
44 |
"""
|
45 |
self.api_key = api_key # Store if needed by LlmAgent or other components
|
46 |
-
self.model_name = model_name or DEFAULT_AGENT_MODEL
|
47 |
self.current_date = current_date or datetime.utcnow().date() # Use date object for consistency
|
48 |
|
49 |
# LlmAgent is initialized with dynamic instruction and output schema
|
@@ -80,63 +80,149 @@ class TaskExtractionAgent:
|
|
80 |
return max(0, days_remaining) # Ensure non-negative
|
81 |
|
82 |
def _get_instruction_prompt(self) -> str:
|
83 |
-
"""Generates the dynamic instruction string for the
|
84 |
quarter = self._get_quarter(self.current_date)
|
85 |
days_remaining = self._days_until_quarter_end(self.current_date)
|
86 |
-
|
87 |
-
# Dynamically
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
96 |
|
97 |
return f"""
|
98 |
-
You are a Time-Aware Task Extraction Specialist
|
99 |
-
|
100 |
-
|
101 |
-
CURRENT CONTEXTUAL INFORMATION (DO NOT CHANGE THIS IN YOUR OUTPUT):
|
102 |
- Current Quarter: Q{quarter}
|
103 |
- Days remaining in current quarter: {days_remaining}
|
104 |
-
- Today's Date (for context): {self.current_date.isoformat()}
|
|
|
105 |
YOUR MANDATE:
|
106 |
-
1.
|
107 |
-
2.
|
108 |
-
3.
|
109 |
-
4.
|
110 |
-
5.
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
116 |
OUTPUT FORMAT:
|
117 |
-
You MUST return a
|
118 |
-
|
119 |
-
- 'current_quarter_info': A string exactly like "Q{quarter}, {days_remaining} days remaining". (This is fixed based on the context above).
|
120 |
-
- 'okrs': A list, where each item is an 'OKR' object.
|
121 |
-
- 'overall_strategic_focus': (Optional) A brief summary of the main strategic themes emerging from the OKRs.
|
122 |
-
- 'generation_timestamp': (This will be auto-filled if you conform to the schema, or you can provide an ISO timestamp).
|
123 |
-
Example of a Task (ensure all fields from the Pydantic model are covered):
|
124 |
{{
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
138 |
}}
|
139 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
140 |
"""
|
141 |
|
142 |
async def extract_tasks(self, comprehensive_analysis: str) -> TaskExtractionOutput:
|
|
|
43 |
current_date: The current date to use for quarter calculations. Defaults to today.
|
44 |
"""
|
45 |
self.api_key = api_key # Store if needed by LlmAgent or other components
|
46 |
+
self.model_name = "gemini-2.5-pro-preview-03-25" #model_name or DEFAULT_AGENT_MODEL
|
47 |
self.current_date = current_date or datetime.utcnow().date() # Use date object for consistency
|
48 |
|
49 |
# LlmAgent is initialized with dynamic instruction and output schema
|
|
|
80 |
return max(0, days_remaining) # Ensure non-negative
|
81 |
|
82 |
def _get_instruction_prompt(self) -> str:
|
83 |
+
"""Generates the dynamic instruction string for the LLM agent."""
|
84 |
quarter = self._get_quarter(self.current_date)
|
85 |
days_remaining = self._days_until_quarter_end(self.current_date)
|
86 |
+
|
87 |
+
# Dynamically get enum values to include in the prompt
|
88 |
+
effort_levels_str = _get_enum_values_str(EffortLevel)
|
89 |
+
task_types_str = _get_enum_values_str(TaskType)
|
90 |
+
data_subjects_str = _get_enum_values_str(DataSubject)
|
91 |
+
timeline_categories_str = _get_enum_values_str(TimelineCategory)
|
92 |
+
priority_levels_str = _get_enum_values_str(PriorityLevel)
|
93 |
+
|
94 |
+
# Detailed schema descriptions based on your Pydantic models.
|
95 |
+
# These are manually transcribed from your model descriptions for this example.
|
96 |
+
# For maximum robustness, consider a helper function to generate these
|
97 |
+
# strings directly by introspecting your Pydantic models if they change frequently.
|
98 |
+
task_schema_details = f"""
|
99 |
+
'Task' Model Schema: Represents a single, actionable item.
|
100 |
+
(Refer to your Pydantic 'Task' model for exact field definitions and descriptions)
|
101 |
+
- task_category (string, required): The broader strategic category or theme (e.g., Content Strategy, Audience Engagement, Reputation Management, Performance Monitoring). Helps in organizing and reporting tasks.
|
102 |
+
- task_description (string, required): A concise, clear, and actionable description of what needs to be done for this specific task.
|
103 |
+
- objective_deliverable (string, required): The specific, measurable outcome or output expected from completing this task. Clearly defines what 'done' looks like.
|
104 |
+
- effort (string, required): An estimation of the resources (time, complexity) required. Allowed values: {effort_levels_str}.
|
105 |
+
- timeline (string, required): The projected timeframe for completing this task. Allowed values: {timeline_categories_str}.
|
106 |
+
- responsible_party (string, required): The designated team, role, or individual accountable for execution.
|
107 |
+
- success_criteria_metrics (string, required): Specific, measurable criteria and KPIs to determine task success.
|
108 |
+
- dependencies_prerequisites (string, optional): Any tasks, resources, or conditions that must be met before this task can begin or be completed. If not applicable, omit or use null.
|
109 |
+
- priority (string, required): The assigned priority level. Allowed values: {priority_levels_str}.
|
110 |
+
- priority_justification (string, required): A brief rationale for the assigned priority level, linking to impact or urgency.
|
111 |
+
- why_proposed (string, required): The core reason for proposing this task, clearly linking back to specific findings or insights from the data analysis.
|
112 |
+
- task_type (string, required): Classifies the task. Allowed values: {task_types_str}.
|
113 |
+
- data_subject (string, conditional): For 'tracking' tasks, specifies the primary data domain (e.g., follower_stats, posts). Allowed values: {data_subjects_str}. This field MUST be specified if 'task_type' is '{TaskType.TRACKING.value}'. For '{TaskType.INITIATIVE.value}' tasks, it can be '{DataSubject.GENERAL.value}', null, or omitted if not specific.
|
114 |
+
"""
|
115 |
+
|
116 |
+
key_result_schema_details = f"""
|
117 |
+
'KeyResult' Model Schema: A specific, measurable outcome contributing to an Objective.
|
118 |
+
(Refer to your Pydantic 'KeyResult' model for exact field definitions and descriptions)
|
119 |
+
- key_result_description (string, required): A clear, specific, measurable, achievable, relevant, and time-bound (SMART) description of the desired outcome.
|
120 |
+
- tasks (array of 'Task' objects, required, can be empty if no tasks defined yet): A list of specific, actionable tasks to achieve this key result.
|
121 |
+
- target_metric (string, optional): The primary metric to quantify achievement (e.g., 'Follower Growth Rate').
|
122 |
+
- target_value (string, optional): The specific target for the 'target_metric' (e.g., '5%', '1000 new followers').
|
123 |
+
"""
|
124 |
+
|
125 |
+
okr_schema_details = f"""
|
126 |
+
'OKR' Model Schema: Defines an Objective and its associated Key Results.
|
127 |
+
(Refer to your Pydantic 'OKR' model for exact field definitions and descriptions)
|
128 |
+
- objective_description (string, required): A high-level, qualitative, and aspirational goal.
|
129 |
+
- key_results (array of 'KeyResult' objects, required): A list of 2-5 specific and measurable Key Results that define success for the objective.
|
130 |
+
- objective_timeline (string, required): The overall projected timeline category for achieving this objective. Allowed values: {timeline_categories_str}.
|
131 |
+
- objective_owner (string, optional): The team or individual primarily responsible for this objective.
|
132 |
+
"""
|
133 |
+
|
134 |
+
task_extraction_output_schema_details = f"""
|
135 |
+
'TaskExtractionOutput' Model Schema: This is the root JSON object you MUST return.
|
136 |
+
(Refer to your Pydantic 'TaskExtractionOutput' model for exact field definitions and descriptions)
|
137 |
+
- current_quarter_info (string, required): Information about the current quarter. YOU MUST USE THIS EXACT VALUE: "Q{quarter}, {days_remaining} days remaining".
|
138 |
+
- okrs (array of 'OKR' objects, required): A list of Objectives and Key Results derived from the analysis.
|
139 |
+
- overall_strategic_focus (string, optional): A brief summary of the main strategic focus areas identified.
|
140 |
+
- generation_timestamp (string, required, ISO 8601 format e.g., "YYYY-MM-DDTHH:MM:SS.ffffffZ"): Timestamp of when this output was generated. You should generate this.
|
141 |
+
"""
|
142 |
|
143 |
return f"""
|
144 |
+
You are a Time-Aware Task Extraction Specialist, an AI expert in meticulously analyzing strategic insights (e.g., from LinkedIn analytics) and transforming them into a structured set of actionable tasks, organized within an Objectives and KeyResults (OKRs) framework.
|
145 |
+
|
146 |
+
CURRENT CONTEXTUAL INFORMATION (CRITICAL - Use these exact values in your output where specified):
|
|
|
147 |
- Current Quarter: Q{quarter}
|
148 |
- Days remaining in current quarter: {days_remaining}
|
149 |
+
- Today's Date (for your context only, not for direct output unless specified by a schema field): {self.current_date.isoformat()}
|
150 |
+
|
151 |
YOUR MANDATE:
|
152 |
+
1. Thoroughly analyze the provided 'comprehensive_analysis' text.
|
153 |
+
2. Define clear, aspirational Objectives. These become the 'objective_description' in 'OKR' objects.
|
154 |
+
3. For each Objective, formulate 2-3 specific, measurable Key Results. These populate the 'key_results' list within each 'OKR' object.
|
155 |
+
4. Under each KeyResult, detail the actionable Tasks required to achieve it. These populate the 'tasks' list within each 'KeyResult' object.
|
156 |
+
5. Strict Schema Adherence: Your entire output MUST be a single, valid JSON object that strictly conforms to the 'TaskExtractionOutput' Pydantic schema. All nested objects ('OKR', 'KeyResult', 'Task') MUST also strictly conform to their respective schemas. Pay extremely close attention to required fields, data types (string, array, etc.), and valid enum values.
|
157 |
+
|
158 |
+
DETAILED SCHEMA DEFINITIONS (Your output MUST precisely follow these structures):
|
159 |
+
{task_extraction_output_schema_details}
|
160 |
+
|
161 |
+
{okr_schema_details}
|
162 |
+
|
163 |
+
{key_result_schema_details}
|
164 |
+
|
165 |
+
{task_schema_details}
|
166 |
+
|
167 |
+
KEY GUIDELINES FOR QUALITY AND ACCURACY:
|
168 |
+
- Task Timelines: Must be realistic considering the {days_remaining} days left in Q{quarter}. Prioritize actions that can achieve significant progress or be completed within this timeframe. Use 'timeline' values exclusively from: {timeline_categories_str}.
|
169 |
+
- Task Types: Clearly distinguish between '{TaskType.INITIATIVE.value}' (new actions/projects) and '{TaskType.TRACKING.value}' (ongoing monitoring/measurement). Use 'task_type' values exclusively from: {task_types_str}.
|
170 |
+
- Data Subjects for Tracking: If 'task_type' is '{TaskType.TRACKING.value}', the 'data_subject' field is MANDATORY and must be one of: {data_subjects_str}. For '{TaskType.INITIATIVE.value}' tasks, 'data_subject' can be '{DataSubject.GENERAL.value}', null, or omitted if not specific to one data type.
|
171 |
+
- Rationale ('why_proposed'): This is CRUCIAL. Each task's 'why_proposed' field must provide a clear justification, explicitly linking the task back to specific findings, trends, or recommendations mentioned in the input 'comprehensive_analysis'. Avoid generic statements.
|
172 |
+
- Priority & Justification: Assign a 'priority' (from {priority_levels_str}) to each task and provide a concise 'priority_justification' explaining its importance.
|
173 |
+
- Actionability: All descriptions (Objective, Key Result, Task) must be clear, concise, and define concrete actions or measurable outcomes.
|
174 |
+
- Measurability: Key Results and Task 'success_criteria_metrics' must be specific and quantifiable.
|
175 |
+
- Completeness: Ensure all REQUIRED fields in every Pydantic model are present in your JSON output. Optional fields can be omitted or set to null if not applicable.
|
176 |
+
|
177 |
+
INPUT:
|
178 |
+
You will receive a 'comprehensive_analysis' text.
|
179 |
+
|
180 |
OUTPUT FORMAT:
|
181 |
+
You MUST return a SINGLE JSON object. This object must be a valid instance of the 'TaskExtractionOutput' Pydantic schema.
|
182 |
+
Example of the overall JSON structure (content is illustrative; refer to schemas for full details):
|
|
|
|
|
|
|
|
|
|
|
183 |
{{
|
184 |
+
"current_quarter_info": "Q{quarter}, {days_remaining} days remaining",
|
185 |
+
"okrs": [
|
186 |
+
{{
|
187 |
+
"objective_description": "Example: Elevate brand visibility and engagement across key digital channels.",
|
188 |
+
"objective_timeline": "{TimelineCategory.SHORT_TERM.value}",
|
189 |
+
"objective_owner": "Marketing Department",
|
190 |
+
"key_results": [
|
191 |
+
{{
|
192 |
+
"key_result_description": "Example: Increase organic reach on LinkedIn by 15%.",
|
193 |
+
"target_metric": "LinkedIn Organic Reach Percentage Increase",
|
194 |
+
"target_value": "15%",
|
195 |
+
"tasks": [
|
196 |
+
// ... Array of Task objects, each following the 'Task' schema ...
|
197 |
+
// See detailed Task example below.
|
198 |
+
]
|
199 |
+
}}
|
200 |
+
]
|
201 |
+
}}
|
202 |
+
],
|
203 |
+
"overall_strategic_focus": "Example: Focus on data-driven content strategy and proactive community engagement to boost Q{quarter} performance.", // Optional
|
204 |
+
"generation_timestamp": "{datetime.utcnow().isoformat()}Z" // Generate an ISO 8601 UTC timestamp
|
205 |
}}
|
206 |
+
|
207 |
+
Detailed Example of a single 'Task' object (ensure all fields are covered as per schema):
|
208 |
+
{{
|
209 |
+
"task_category": "Content Strategy",
|
210 |
+
"task_description": "Develop and schedule a 4-week content calendar for LinkedIn focusing on industry insights.",
|
211 |
+
"objective_deliverable": "Deliverable: A finalized 4-week content calendar with 3 posts per week, approved and scheduled.",
|
212 |
+
"effort": "{EffortLevel.MEDIUM.value}",
|
213 |
+
"timeline": "{TimelineCategory.IMMEDIATE.value}",
|
214 |
+
"responsible_party": "Content Marketing Manager",
|
215 |
+
"success_criteria_metrics": "Content calendar completed and approved by [Date]. All posts scheduled by [Date].",
|
216 |
+
"dependencies_prerequisites": "Completion of Q{quarter} keyword research and audience persona refinement.",
|
217 |
+
"priority": "{PriorityLevel.HIGH.value}",
|
218 |
+
"priority_justification": "Critical for maintaining consistent brand voice and achieving engagement targets for the quarter.",
|
219 |
+
"why_proposed": "Analysis of LinkedIn insights report (Page 3) showed a 20% drop in engagement last month, attributed to inconsistent posting schedule and lack of targeted content themes.",
|
220 |
+
"task_type": "{TaskType.INITIATIVE.value}",
|
221 |
+
"data_subject": "{DataSubject.POSTS.value}" // Could be 'general' for broader initiatives too
|
222 |
+
}}
|
223 |
+
|
224 |
+
Focus on precision, quality, actionability, and strict adherence to the specified JSON output schema and all constraints.
|
225 |
+
Ensure all string values in the JSON are properly escaped if they contain special characters (e.g., newlines, quotes).
|
226 |
"""
|
227 |
|
228 |
async def extract_tasks(self, comprehensive_analysis: str) -> TaskExtractionOutput:
|