Rakshitjan's picture
Update app.py
5f83ea5 verified
# app.py
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
import os, re, json
from datetime import datetime, timedelta
from typing import Optional, Dict, Any
from groq import Groq
# Initialize Groq client using environment variable
GROQ_KEY = "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"
if not GROQ_KEY:
raise RuntimeError("Missing GROQ_API_KEY. Set it as an environment variable or in Hugging Face Secrets.")
client = Groq(api_key=GROQ_KEY)
app = FastAPI(title="Task Parsing API (Groq-powered)")
# -------------------- PROMPTS --------------------
llm_task_create_agent_system_prompt = f"""
You are a task creation agent. Extract the following from user input:
- Task Name (Text)
- Task Priority (High, Medium, Low)
- Task Deadline (STRICTLY 'YYYY-MM-DD HH:MM:SS')
- Task Status (Pending, Completed)
- Task Type (Work, Health, Personal)
- Date Created (If not given, use current time)
⚠️ ALL datetime values must follow 'YYYY-MM-DD HH:MM:SS'. NO natural language like 'tomorrow' or 'evening'.
Output JUST a JSON object. Example:
{{"Task Name": "Submit report", "Task Priority": "High", "Task Deadline": "2025-07-17 18:00:00", "Task Status": "Pending", "Task Type": "Work", "Date Created": "2025-07-01 12:00:00"}}
"""
# -------------------- HELPERS --------------------
def extract_json_from_response(text: str):
match = re.search(r"\{[\s\S]*\}", text)
if not match:
return None
try:
return json.loads(match.group())
except json.JSONDecodeError:
return None
DATETIME_REGEX = r"\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}"
def validate_datetime_format(dt_str: str) -> bool:
if re.fullmatch(DATETIME_REGEX, dt_str):
try:
datetime.strptime(dt_str, "%Y-%m-%d %H:%M:%S")
return True
except:
return False
return False
# -------------------- GROQ CALLER --------------------
def call_groq_system(system_prompt: str, user_message: str, model: str = "llama-3.3-70b-versatile"):
"""Generic wrapper to call Groq chat API."""
chat_completion = client.chat.completions.create(
model=model,
messages=[
{"role": "system", "content": system_prompt},
{"role": "user", "content": user_message},
],
)
return chat_completion.choices[0].message.content.strip()
# -------------------- AGENTS --------------------
def run_task_creation_agent(nl_task: str):
reply = call_groq_system(llm_task_create_agent_system_prompt, nl_task)
parsed = extract_json_from_response(reply)
if not parsed:
raise ValueError(f"LLM did not return valid JSON. Raw:\n{reply}")
if not validate_datetime_format(parsed.get("Task Deadline", "")):
raise ValueError(f"Invalid 'Task Deadline': {parsed.get('Task Deadline')}")
if not validate_datetime_format(parsed.get("Date Created", "")):
parsed["Date Created"] = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
parsed.setdefault("Task Status", "Pending")
parsed.setdefault("Task Priority", "Medium")
parsed.setdefault("Task Type", "Work")
return parsed
def scheduler_agent(task_json: Dict[str, Any]) -> str:
"""Simplified scheduler — returns the deadline as the scheduled time."""
deadline = task_json.get("Task Deadline")
if not validate_datetime_format(deadline):
raise ValueError("Scheduler requires a valid Task Deadline.")
return deadline
def reminder_agent(task_json: Dict[str, Any], scheduled_time_str: str):
scheduled = datetime.strptime(scheduled_time_str, "%Y-%m-%d %H:%M:%S")
priority = (task_json.get("Task Priority") or "Medium").lower()
if priority == "high":
offsets = [timedelta(hours=24), timedelta(hours=1)]
elif priority == "low":
offsets = [timedelta(days=1), timedelta(days=3)]
else:
offsets = [timedelta(hours=12), timedelta(hours=1)]
reminders = []
for off in offsets:
r = scheduled - off
if r > datetime.now():
reminders.append(r.strftime("%Y-%m-%d %H:%M:%S"))
return reminders
# -------------------- MODELS --------------------
class ParseRequest(BaseModel):
text: str
class ParseResponse(BaseModel):
task_json: Dict[str, Any]
scheduled_time: str
reminders: list
# -------------------- ENDPOINTS --------------------
@app.post("/parse-task", response_model=ParseResponse)
def parse_task(req: ParseRequest):
try:
task_json = run_task_creation_agent(req.text)
scheduled_time = scheduler_agent(task_json)
reminders = reminder_agent(task_json, scheduled_time)
return ParseResponse(task_json=task_json, scheduled_time=scheduled_time, reminders=reminders)
except Exception as e:
raise HTTPException(status_code=400, detail=str(e))
@app.get("/health")
def health():
return {"status": "ok"}