Rakshitjan commited on
Commit
257b532
·
verified ·
1 Parent(s): 2178d32

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +40 -65
app.py CHANGED
@@ -1,24 +1,22 @@
1
  # app.py
2
  from fastapi import FastAPI, HTTPException
3
  from pydantic import BaseModel
4
- import os
5
- import re
6
- import json
7
- from datetime import datetime
8
  from typing import Optional, Dict, Any
 
9
 
10
- # Together client import (expects TOGETHER_API_KEY in env)
11
- try:
12
- from together import Together
13
- except Exception:
14
- Together = None
15
 
16
- TOGETHER_KEY = os.getenv("TOGETHER_API_KEY")
17
 
18
- app = FastAPI(title="Task Parsing API")
19
 
20
- # --- Configuration / Prompts (trimmed & adapted from your snippet) ---
21
- llm_task_create_agent_system_prompt = '''
22
  You are a task creation agent. Extract the following from user input:
23
 
24
  - Task Name (Text)
@@ -28,14 +26,14 @@ You are a task creation agent. Extract the following from user input:
28
  - Task Type (Work, Health, Personal)
29
  - Date Created (If not given, use current time)
30
 
31
- ⚠️ ALL datetime values must follow 'YYYY-MM-DD HH:MM:SS'. NO other format. NO natural language like 'tomorrow' or 'evening'.
32
 
33
  Output JUST a JSON object. Example:
34
- {"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"}
35
- '''
36
 
37
- # Simple regex extractor helper
38
- def extract_json_from_response(text: str) -> Optional[Dict[str, Any]]:
39
  match = re.search(r"\{[\s\S]*\}", text)
40
  if not match:
41
  return None
@@ -44,71 +42,56 @@ def extract_json_from_response(text: str) -> Optional[Dict[str, Any]]:
44
  except json.JSONDecodeError:
45
  return None
46
 
47
- # Datetime validation
48
  DATETIME_REGEX = r"\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}"
49
 
50
  def validate_datetime_format(dt_str: str) -> bool:
51
- if not isinstance(dt_str, str):
52
- return False
53
  if re.fullmatch(DATETIME_REGEX, dt_str):
54
  try:
55
  datetime.strptime(dt_str, "%Y-%m-%d %H:%M:%S")
56
  return True
57
- except Exception:
58
  return False
59
  return False
60
 
61
- # Small wrapper to call Together (or raise helpful error)
62
- def call_llm_system(system_prompt: str, user_message: str, model: str = "meta-llama/Llama-3-8b-chat-hf") -> str:
63
- if Together is None:
64
- raise RuntimeError("together package is not installed. Set TOGETHER_API_KEY and install dependency 'together'.")
65
- if not TOGETHER_KEY:
66
- raise RuntimeError("Environment variable TOGETHER_API_KEY is missing. Set it before running the container.")
67
-
68
- client = Together(api_key="2aa48b9b987fa3f745dd1862a2063f5fce1ee508c3de1a01c3ec6969d47434e6")
69
- response = client.chat.completions.create(
70
  model=model,
71
  messages=[
72
  {"role": "system", "content": system_prompt},
73
- {"role": "user", "content": user_message}
74
- ]
75
  )
76
- return response.choices[0].message.content.strip()
77
-
78
- # --- Agent functions (lightweight, synchronous) ---
79
 
80
- def run_task_creation_agent(nl_task: str) -> Dict[str, Any]:
81
- reply = call_llm_system(llm_task_create_agent_system_prompt, nl_task)
 
82
  parsed = extract_json_from_response(reply)
83
  if not parsed:
84
- # If LLM didn't return JSON, propagate error message for debugging
85
- raise ValueError(f"LLM did not return valid JSON. Raw reply:\n{reply}")
86
- # Fill defaults
87
- if "Date Created" not in parsed or not validate_datetime_format(parsed["Date Created"]):
88
- parsed["Date Created"] = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
89
- # Validate deadline
90
  if not validate_datetime_format(parsed.get("Task Deadline", "")):
91
- raise ValueError(f"Invalid or missing 'Task Deadline' in parsed JSON: {parsed.get('Task Deadline')}")
92
- # Normalize fields
 
 
 
93
  parsed.setdefault("Task Status", "Pending")
94
  parsed.setdefault("Task Priority", "Medium")
95
  parsed.setdefault("Task Type", "Work")
 
96
  return parsed
97
 
98
- # Scheduler agent (minimal — returns the original requested deadline as "scheduled" if valid)
99
- # In the original pipeline, you used other agents to suggest an optimal datetime. For this lightweight API
100
- # we'll do a simple rule: if deadline is valid, respond with the deadline; otherwise return an error.
101
 
102
  def scheduler_agent(task_json: Dict[str, Any]) -> str:
103
- # For extensibility, you can replace this function to call your LLM scheduler prompt
104
  deadline = task_json.get("Task Deadline")
105
  if not validate_datetime_format(deadline):
106
  raise ValueError("Scheduler requires a valid Task Deadline.")
107
- # Return the same deadline as scheduled time (placeholder for more advanced scheduling).
108
  return deadline
109
 
110
- # Reminder agent — produce 1-2 reminders before scheduled time (simple offsets)
111
- from datetime import timedelta
112
 
113
  def reminder_agent(task_json: Dict[str, Any], scheduled_time_str: str):
114
  scheduled = datetime.strptime(scheduled_time_str, "%Y-%m-%d %H:%M:%S")
@@ -118,7 +101,7 @@ def reminder_agent(task_json: Dict[str, Any], scheduled_time_str: str):
118
  offsets = [timedelta(hours=24), timedelta(hours=1)]
119
  elif priority == "low":
120
  offsets = [timedelta(days=1), timedelta(days=3)]
121
- else: # medium
122
  offsets = [timedelta(hours=12), timedelta(hours=1)]
123
 
124
  reminders = []
@@ -128,35 +111,27 @@ def reminder_agent(task_json: Dict[str, Any], scheduled_time_str: str):
128
  reminders.append(r.strftime("%Y-%m-%d %H:%M:%S"))
129
  return reminders
130
 
131
- # --- API models ---
132
  class ParseRequest(BaseModel):
133
  text: str
134
- # Optional flags to control behavior in future
135
- return_full_pipeline: Optional[bool] = False
136
 
137
  class ParseResponse(BaseModel):
138
  task_json: Dict[str, Any]
139
  scheduled_time: str
140
  reminders: list
141
 
142
- # --- Endpoints ---
143
  @app.post("/parse-task", response_model=ParseResponse)
144
  def parse_task(req: ParseRequest):
145
  try:
146
- # 1) Create structured task using the task creation agent
147
  task_json = run_task_creation_agent(req.text)
148
-
149
- # 2) Run scheduler (lightweight)
150
  scheduled_time = scheduler_agent(task_json)
151
-
152
- # 3) Create reminders
153
  reminders = reminder_agent(task_json, scheduled_time)
154
-
155
  return ParseResponse(task_json=task_json, scheduled_time=scheduled_time, reminders=reminders)
156
  except Exception as e:
157
  raise HTTPException(status_code=400, detail=str(e))
158
 
159
- # Healthcheck
160
  @app.get("/health")
161
  def health():
162
  return {"status": "ok"}
 
1
  # app.py
2
  from fastapi import FastAPI, HTTPException
3
  from pydantic import BaseModel
4
+ import os, re, json
5
+ from datetime import datetime, timedelta
 
 
6
  from typing import Optional, Dict, Any
7
+ from groq import Groq
8
 
9
+ # Initialize Groq client using environment variable
10
+ GROQ_KEY = os.getenv("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")
11
+ if not GROQ_KEY:
12
+ raise RuntimeError("Missing GROQ_API_KEY. Set it as an environment variable or in Hugging Face Secrets.")
 
13
 
14
+ client = Groq(api_key=GROQ_KEY)
15
 
16
+ app = FastAPI(title="Task Parsing API (Groq-powered)")
17
 
18
+ # -------------------- PROMPTS --------------------
19
+ llm_task_create_agent_system_prompt = f"""
20
  You are a task creation agent. Extract the following from user input:
21
 
22
  - Task Name (Text)
 
26
  - Task Type (Work, Health, Personal)
27
  - Date Created (If not given, use current time)
28
 
29
+ ⚠️ ALL datetime values must follow 'YYYY-MM-DD HH:MM:SS'. NO natural language like 'tomorrow' or 'evening'.
30
 
31
  Output JUST a JSON object. Example:
32
+ {{"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"}}
33
+ """
34
 
35
+ # -------------------- HELPERS --------------------
36
+ def extract_json_from_response(text: str):
37
  match = re.search(r"\{[\s\S]*\}", text)
38
  if not match:
39
  return None
 
42
  except json.JSONDecodeError:
43
  return None
44
 
 
45
  DATETIME_REGEX = r"\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}"
46
 
47
  def validate_datetime_format(dt_str: str) -> bool:
 
 
48
  if re.fullmatch(DATETIME_REGEX, dt_str):
49
  try:
50
  datetime.strptime(dt_str, "%Y-%m-%d %H:%M:%S")
51
  return True
52
+ except:
53
  return False
54
  return False
55
 
56
+ # -------------------- GROQ CALLER --------------------
57
+ def call_groq_system(system_prompt: str, user_message: str, model: str = "llama-3.3-70b-versatile"):
58
+ """Generic wrapper to call Groq chat API."""
59
+ chat_completion = client.chat.completions.create(
 
 
 
 
 
60
  model=model,
61
  messages=[
62
  {"role": "system", "content": system_prompt},
63
+ {"role": "user", "content": user_message},
64
+ ],
65
  )
66
+ return chat_completion.choices[0].message.content.strip()
 
 
67
 
68
+ # -------------------- AGENTS --------------------
69
+ def run_task_creation_agent(nl_task: str):
70
+ reply = call_groq_system(llm_task_create_agent_system_prompt, nl_task)
71
  parsed = extract_json_from_response(reply)
72
  if not parsed:
73
+ raise ValueError(f"LLM did not return valid JSON. Raw:\n{reply}")
74
+
 
 
 
 
75
  if not validate_datetime_format(parsed.get("Task Deadline", "")):
76
+ raise ValueError(f"Invalid 'Task Deadline': {parsed.get('Task Deadline')}")
77
+
78
+ if not validate_datetime_format(parsed.get("Date Created", "")):
79
+ parsed["Date Created"] = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
80
+
81
  parsed.setdefault("Task Status", "Pending")
82
  parsed.setdefault("Task Priority", "Medium")
83
  parsed.setdefault("Task Type", "Work")
84
+
85
  return parsed
86
 
 
 
 
87
 
88
  def scheduler_agent(task_json: Dict[str, Any]) -> str:
89
+ """Simplified scheduler returns the deadline as the scheduled time."""
90
  deadline = task_json.get("Task Deadline")
91
  if not validate_datetime_format(deadline):
92
  raise ValueError("Scheduler requires a valid Task Deadline.")
 
93
  return deadline
94
 
 
 
95
 
96
  def reminder_agent(task_json: Dict[str, Any], scheduled_time_str: str):
97
  scheduled = datetime.strptime(scheduled_time_str, "%Y-%m-%d %H:%M:%S")
 
101
  offsets = [timedelta(hours=24), timedelta(hours=1)]
102
  elif priority == "low":
103
  offsets = [timedelta(days=1), timedelta(days=3)]
104
+ else:
105
  offsets = [timedelta(hours=12), timedelta(hours=1)]
106
 
107
  reminders = []
 
111
  reminders.append(r.strftime("%Y-%m-%d %H:%M:%S"))
112
  return reminders
113
 
114
+ # -------------------- MODELS --------------------
115
  class ParseRequest(BaseModel):
116
  text: str
 
 
117
 
118
  class ParseResponse(BaseModel):
119
  task_json: Dict[str, Any]
120
  scheduled_time: str
121
  reminders: list
122
 
123
+ # -------------------- ENDPOINTS --------------------
124
  @app.post("/parse-task", response_model=ParseResponse)
125
  def parse_task(req: ParseRequest):
126
  try:
 
127
  task_json = run_task_creation_agent(req.text)
 
 
128
  scheduled_time = scheduler_agent(task_json)
 
 
129
  reminders = reminder_agent(task_json, scheduled_time)
 
130
  return ParseResponse(task_json=task_json, scheduled_time=scheduled_time, reminders=reminders)
131
  except Exception as e:
132
  raise HTTPException(status_code=400, detail=str(e))
133
 
134
+
135
  @app.get("/health")
136
  def health():
137
  return {"status": "ok"}