|
|
import anthropic |
|
|
import os |
|
|
import json |
|
|
from typing import List, Dict, Union, Any |
|
|
from dotenv import load_dotenv |
|
|
|
|
|
load_dotenv() |
|
|
|
|
|
|
|
|
if not os.getenv("ANTHROPIC_API_KEY"): |
|
|
raise ValueError("ANTHROPIC_API_KEY environment variable is not set") |
|
|
|
|
|
client = anthropic.Anthropic(api_key=os.getenv("ANTHROPIC_API_KEY")) |
|
|
|
|
|
def llm_parse_tasks(user_input: str) -> Union[List[Dict[str, Any]], str]: |
|
|
""" |
|
|
Parse user input into structured tasks using Claude 3. |
|
|
|
|
|
Args: |
|
|
user_input (str): The user's natural language input describing their goals |
|
|
|
|
|
Returns: |
|
|
Union[List[Dict[str, Any]], str]: Either a list of task dictionaries or an error message |
|
|
""" |
|
|
prompt = f""" |
|
|
You are a helpful assistant that turns vague personal goals into clear, actionable tasks. |
|
|
|
|
|
Break this input into tasks with: |
|
|
- task name (key: "task") |
|
|
- category (key: "category") - Choose from: Career, Learning, Personal, Outreach, Health, Finance |
|
|
- priority (key: "priority") - Choose from: High, Medium, Low |
|
|
- optional due date (key: "dueDate") - Use ISO format YYYY-MM-DD if date is mentioned or inferred |
|
|
- notes (key: "notes") - Add relevant context or subtasks |
|
|
|
|
|
Return ONLY a valid JSON array of task objects with the exact keys mentioned above. |
|
|
Each task MUST have at least task, category, and priority fields. |
|
|
|
|
|
Input: \"\"\"{user_input}\"\"\" |
|
|
""" |
|
|
|
|
|
try: |
|
|
response = client.messages.create( |
|
|
model="claude-3-haiku-20240307", |
|
|
max_tokens=1024, |
|
|
temperature=0.4, |
|
|
messages=[ |
|
|
{"role": "user", "content": prompt} |
|
|
] |
|
|
) |
|
|
|
|
|
content = response.content[0].text.strip() |
|
|
tasks = json.loads(content) |
|
|
|
|
|
|
|
|
for task in tasks: |
|
|
if not all(k in task for k in ["task", "category", "priority"]): |
|
|
return "Error: Each task must have task, category, and priority fields" |
|
|
|
|
|
|
|
|
if task["category"] not in ["Career", "Learning", "Personal", "Outreach", "Health", "Finance"]: |
|
|
return f"Error: Invalid category '{task['category']}' in task '{task['task']}'" |
|
|
|
|
|
if task["priority"] not in ["High", "Medium", "Low"]: |
|
|
return f"Error: Invalid priority '{task['priority']}' in task '{task['task']}'" |
|
|
|
|
|
return tasks |
|
|
except anthropic.APIError as e: |
|
|
return f"Claude API Error: {str(e)}" |
|
|
except json.JSONDecodeError: |
|
|
return "Error: Failed to parse Claude's response as JSON" |
|
|
except Exception as e: |
|
|
return f"Unexpected error: {str(e)}" |
|
|
|