Spaces:
Sleeping
Sleeping
Updated README, app.py and requirements.txt
Browse files- README.md +58 -46
- app.py +53 -40
- requirements.txt +2 -1
README.md
CHANGED
@@ -12,63 +12,76 @@ short_description: Agent that manages user reminders with in-session memory
|
|
12 |
|
13 |
Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
|
14 |
|
|
|
15 |
|
16 |
-
|
17 |
-
|
18 |
-
A lightweight agentic AI app that lets you create, check, and delete remindersβall in-session. Built with Python and Gradio, it demonstrates how an agent can maintain state, respond to commands, and simulate real-world utility.
|
19 |
|
20 |
---
|
21 |
|
22 |
## π Live Demo
|
23 |
|
24 |
-
π [Launch on Hugging Face Spaces](https://huggingface.co/spaces/ujwal55/Stateful_Reminder_Agent) *(
|
25 |
|
26 |
---
|
27 |
|
28 |
## π§ Features
|
29 |
|
30 |
-
- β
**Add Reminders** β
|
31 |
-
-
|
32 |
-
-
|
33 |
-
-
|
34 |
-
-
|
|
|
35 |
|
36 |
---
|
37 |
|
38 |
## π¦ Tech Stack
|
39 |
|
40 |
-
- **Python
|
41 |
-
- **Gradio** β
|
42 |
-
- **
|
43 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
44 |
|
45 |
---
|
46 |
|
47 |
-
##
|
|
|
|
|
48 |
|
49 |
-
|
50 |
-
-
|
51 |
-
-
|
52 |
-
-
|
53 |
-
- Performs real-time computation (e.g., checking due reminders)
|
54 |
|
55 |
---
|
56 |
|
57 |
-
##
|
58 |
|
59 |
-
1. Clone the repo
|
60 |
```bash
|
61 |
git clone https://huggingface.co/spaces/ujwal55/Stateful_Reminder_Agent
|
62 |
cd Stateful_Reminder_Agent
|
63 |
````
|
64 |
|
65 |
-
2. Install dependencies
|
66 |
|
67 |
```bash
|
68 |
-
pip install
|
69 |
```
|
70 |
|
71 |
-
3. Run the app
|
72 |
|
73 |
```bash
|
74 |
python app.py
|
@@ -76,41 +89,40 @@ python app.py
|
|
76 |
|
77 |
---
|
78 |
|
79 |
-
##
|
80 |
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
```
|
86 |
|
87 |
-
|
|
|
88 |
|
89 |
-
|
|
|
90 |
|
91 |
-
* **
|
92 |
-
|
93 |
-
* **Check:** Ask βWhat's next?β to find out whatβs due now
|
94 |
-
* **Delete:** Remove the reminder using its exact timestamp
|
95 |
|
96 |
---
|
97 |
|
98 |
-
## β οΈ Limitations
|
99 |
|
100 |
-
*
|
101 |
-
* No background scheduler (must press
|
|
|
102 |
|
103 |
---
|
104 |
|
105 |
-
##
|
106 |
|
107 |
-
*
|
108 |
-
*
|
109 |
-
*
|
110 |
-
*
|
111 |
|
112 |
---
|
113 |
|
114 |
-
π¨βπ» Built by [@ujwal55](https://huggingface.co/ujwal55) β Agentic AI Developer
|
115 |
|
116 |
-
```
|
|
|
12 |
|
13 |
Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
|
14 |
|
15 |
+
# β° Stateful Reminder Agent (Timezone-Aware)
|
16 |
|
17 |
+
A simple agentic AI app to help you add, view, check, and delete reminders β now with **timezone support**! Built using Python and Gradio, this project showcases stateful behavior and time-based task handling in real-time.
|
|
|
|
|
18 |
|
19 |
---
|
20 |
|
21 |
## π Live Demo
|
22 |
|
23 |
+
π [Launch on Hugging Face Spaces](https://huggingface.co/spaces/ujwal55/Stateful_Reminder_Agent) *(Replace with your actual link)*
|
24 |
|
25 |
---
|
26 |
|
27 |
## π§ Features
|
28 |
|
29 |
+
- β
**Add Reminders** β set reminders using a chosen timezone.
|
30 |
+
- π **Timezone Support** β select from common timezones (e.g., Asia/Kolkata, UTC).
|
31 |
+
- π **List Reminders** β shows upcoming reminders with time left.
|
32 |
+
- π **Check βWhatβs Next?β** β tells you if something is due right now.
|
33 |
+
- ποΈ **Delete Reminders** β remove a reminder by exact time + timezone.
|
34 |
+
- πΎ **In-Session State** β reminders are stored in memory (not persisted).
|
35 |
|
36 |
---
|
37 |
|
38 |
## π¦ Tech Stack
|
39 |
|
40 |
+
- **Python 3.6+**
|
41 |
+
- **Gradio** β interactive UI
|
42 |
+
- **pytz** β for timezone-aware datetime handling
|
43 |
+
|
44 |
+
---
|
45 |
+
|
46 |
+
## π File Structure
|
47 |
+
|
48 |
+
```
|
49 |
+
|
50 |
+
Stateful\_Reminder\_Agent/
|
51 |
+
βββ app.py # Main app logic
|
52 |
+
βββ README.md # This file
|
53 |
+
βββ requirements.txt # Dependencies
|
54 |
+
|
55 |
+
````
|
56 |
|
57 |
---
|
58 |
|
59 |
+
## π§ Agentic AI Concepts
|
60 |
+
|
61 |
+
This agent simulates key agentic AI principles:
|
62 |
|
63 |
+
- Maintains **session memory** of tasks (reminders)
|
64 |
+
- Responds to user input with **goal-oriented behavior**
|
65 |
+
- Operates with **real-time logic** and conditional decisions
|
66 |
+
- Supports **multi-function interaction** via tabs
|
|
|
67 |
|
68 |
---
|
69 |
|
70 |
+
## π οΈ Setup & Run Locally
|
71 |
|
72 |
+
### 1. Clone the repo
|
73 |
```bash
|
74 |
git clone https://huggingface.co/spaces/ujwal55/Stateful_Reminder_Agent
|
75 |
cd Stateful_Reminder_Agent
|
76 |
````
|
77 |
|
78 |
+
### 2. Install dependencies
|
79 |
|
80 |
```bash
|
81 |
+
pip install -r requirements.txt
|
82 |
```
|
83 |
|
84 |
+
### 3. Run the app
|
85 |
|
86 |
```bash
|
87 |
python app.py
|
|
|
89 |
|
90 |
---
|
91 |
|
92 |
+
## π§ͺ Example Usage
|
93 |
|
94 |
+
* **Add Reminder**
|
95 |
+
β€ Time: `2025-06-07 09:00`
|
96 |
+
β€ Message: `Join Turing Test Interview`
|
97 |
+
β€ Timezone: `Asia/Kolkata`
|
|
|
98 |
|
99 |
+
* **List All**
|
100 |
+
β Shows upcoming reminders in your selected timezone.
|
101 |
|
102 |
+
* **Check "What's Next?"**
|
103 |
+
β Tells if anything is due within the next 60 seconds.
|
104 |
|
105 |
+
* **Delete Reminder**
|
106 |
+
β Input same time + timezone to remove.
|
|
|
|
|
107 |
|
108 |
---
|
109 |
|
110 |
+
## β οΈ Known Limitations
|
111 |
|
112 |
+
* Data is not persisted β reminders are lost when session ends.
|
113 |
+
* No background scheduler (must manually press "What's Next?")
|
114 |
+
* Limited timezone dropdown (can be expanded easily)
|
115 |
|
116 |
---
|
117 |
|
118 |
+
## π‘ Possible Extensions
|
119 |
|
120 |
+
* Persist reminders with SQLite or JSON
|
121 |
+
* Use natural language input like: *"Remind me to drink water in 2 hours"*
|
122 |
+
* Add background trigger or sound alert
|
123 |
+
* Detect userβs timezone automatically (via browser)
|
124 |
|
125 |
---
|
126 |
|
127 |
+
π¨βπ» Built by [@ujwal55](https://huggingface.co/ujwal55) β aspiring Agentic AI Developer
|
128 |
|
|
app.py
CHANGED
@@ -1,78 +1,91 @@
|
|
1 |
import gradio as gr
|
2 |
-
from datetime import datetime
|
|
|
3 |
|
4 |
# In-session reminder list
|
5 |
-
reminders = []
|
6 |
|
7 |
-
#
|
8 |
-
def add_reminder(time_str, message):
|
9 |
try:
|
10 |
-
|
11 |
-
|
12 |
-
|
|
|
|
|
|
|
13 |
return "β Time is in the past. Please enter a future time."
|
14 |
-
|
15 |
-
reminders.
|
16 |
-
|
|
|
17 |
except Exception as e:
|
18 |
return f"β Error: {str(e)}"
|
19 |
|
|
|
20 |
def list_reminders():
|
21 |
if not reminders:
|
22 |
return "π No reminders yet."
|
|
|
23 |
result = []
|
24 |
-
now = datetime.now()
|
25 |
for r in reminders:
|
26 |
-
|
|
|
27 |
mins = int(time_left.total_seconds() / 60)
|
28 |
-
result.append(f"π {
|
29 |
return "\n".join(result)
|
30 |
|
|
|
31 |
def check_next():
|
32 |
-
now = datetime.now()
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
|
|
37 |
|
38 |
-
|
|
|
39 |
try:
|
40 |
-
|
|
|
41 |
global reminders
|
42 |
-
|
43 |
-
reminders = [r for r in reminders if
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
return f"
|
48 |
-
|
49 |
-
|
|
|
|
|
|
|
|
|
50 |
|
51 |
# Gradio UI
|
52 |
with gr.Blocks() as demo:
|
53 |
-
gr.Markdown("## β° Stateful Reminder Agent")
|
54 |
-
|
55 |
with gr.Tab("β Add Reminder"):
|
56 |
-
time_in = gr.Textbox(label="Time (YYYY-MM-DD HH:MM)", placeholder="2025-06-
|
57 |
-
msg_in = gr.Textbox(label="Reminder Message", placeholder="
|
|
|
58 |
out_add = gr.Textbox(label="Status")
|
59 |
-
|
60 |
-
btn_add.click(fn=add_reminder, inputs=[time_in, msg_in], outputs=out_add)
|
61 |
|
62 |
with gr.Tab("π View All Reminders"):
|
63 |
out_list = gr.Textbox(label="Reminders", lines=10)
|
64 |
-
|
65 |
-
btn_list.click(fn=list_reminders, outputs=out_list)
|
66 |
|
67 |
with gr.Tab("π Check Whatβs Due"):
|
68 |
out_next = gr.Textbox(label="Next Reminder")
|
69 |
-
|
70 |
-
btn_next.click(fn=check_next, outputs=out_next)
|
71 |
|
72 |
with gr.Tab("ποΈ Delete Reminder"):
|
73 |
del_time = gr.Textbox(label="Time to Delete (YYYY-MM-DD HH:MM)")
|
|
|
74 |
out_del = gr.Textbox(label="Status")
|
75 |
-
|
76 |
-
btn_del.click(fn=delete_reminder, inputs=del_time, outputs=out_del)
|
77 |
|
78 |
demo.launch()
|
|
|
1 |
import gradio as gr
|
2 |
+
from datetime import datetime
|
3 |
+
import pytz
|
4 |
|
5 |
# In-session reminder list
|
6 |
+
reminders = [] # Format: {'time': datetime, 'message': str, 'tz': str}
|
7 |
|
8 |
+
# Add a reminder
|
9 |
+
def add_reminder(time_str, message, timezone):
|
10 |
try:
|
11 |
+
user_tz = pytz.timezone(timezone)
|
12 |
+
naive_dt = datetime.strptime(time_str, "%Y-%m-%d %H:%M")
|
13 |
+
aware_dt = user_tz.localize(naive_dt)
|
14 |
+
|
15 |
+
now_utc = datetime.now(pytz.utc)
|
16 |
+
if aware_dt.astimezone(pytz.utc) < now_utc:
|
17 |
return "β Time is in the past. Please enter a future time."
|
18 |
+
|
19 |
+
reminders.append({'time': aware_dt, 'message': message, 'tz': timezone})
|
20 |
+
reminders.sort(key=lambda x: x['time'].astimezone(pytz.utc))
|
21 |
+
return f"β
Reminder added for {aware_dt.strftime('%Y-%m-%d %H:%M %Z')}"
|
22 |
except Exception as e:
|
23 |
return f"β Error: {str(e)}"
|
24 |
|
25 |
+
# List reminders
|
26 |
def list_reminders():
|
27 |
if not reminders:
|
28 |
return "π No reminders yet."
|
29 |
+
now = datetime.now(pytz.utc)
|
30 |
result = []
|
|
|
31 |
for r in reminders:
|
32 |
+
local_time = r['time'].astimezone(pytz.timezone(r['tz']))
|
33 |
+
time_left = r['time'].astimezone(pytz.utc) - now
|
34 |
mins = int(time_left.total_seconds() / 60)
|
35 |
+
result.append(f"π {local_time.strftime('%Y-%m-%d %H:%M %Z')} β {r['message']} ({mins} min left)")
|
36 |
return "\n".join(result)
|
37 |
|
38 |
+
# Check next due reminder
|
39 |
def check_next():
|
40 |
+
now = datetime.now(pytz.utc)
|
41 |
+
for r in reminders:
|
42 |
+
if abs((r['time'].astimezone(pytz.utc) - now).total_seconds()) < 60:
|
43 |
+
local_time = r['time'].astimezone(pytz.timezone(r['tz']))
|
44 |
+
return f"π Due now: {r['message']} ({local_time.strftime('%H:%M %Z')})"
|
45 |
+
return "β
Nothing due right now."
|
46 |
|
47 |
+
# Delete reminder
|
48 |
+
def delete_reminder(time_str, timezone):
|
49 |
try:
|
50 |
+
user_tz = pytz.timezone(timezone)
|
51 |
+
target_time = user_tz.localize(datetime.strptime(time_str, "%Y-%m-%d %H:%M"))
|
52 |
global reminders
|
53 |
+
original_len = len(reminders)
|
54 |
+
reminders = [r for r in reminders if not (
|
55 |
+
r['time'].astimezone(pytz.utc) == target_time.astimezone(pytz.utc)
|
56 |
+
)]
|
57 |
+
if len(reminders) < original_len:
|
58 |
+
return f"ποΈ Reminder at {time_str} ({timezone}) deleted."
|
59 |
+
return "β οΈ No matching reminder found."
|
60 |
+
except Exception as e:
|
61 |
+
return f"β Error: {str(e)}"
|
62 |
+
|
63 |
+
# Common timezone choices
|
64 |
+
timezone_choices = ["UTC", "Asia/Kolkata", "America/New_York", "Europe/London", "Asia/Tokyo"]
|
65 |
|
66 |
# Gradio UI
|
67 |
with gr.Blocks() as demo:
|
68 |
+
gr.Markdown("## β° Stateful Reminder Agent with Timezone Support")
|
69 |
+
|
70 |
with gr.Tab("β Add Reminder"):
|
71 |
+
time_in = gr.Textbox(label="Time (YYYY-MM-DD HH:MM)", placeholder="2025-06-07 09:00")
|
72 |
+
msg_in = gr.Textbox(label="Reminder Message", placeholder="Doctor appointment")
|
73 |
+
tz_in = gr.Dropdown(label="Timezone", choices=timezone_choices, value="UTC")
|
74 |
out_add = gr.Textbox(label="Status")
|
75 |
+
gr.Button("Add Reminder").click(fn=add_reminder, inputs=[time_in, msg_in, tz_in], outputs=out_add)
|
|
|
76 |
|
77 |
with gr.Tab("π View All Reminders"):
|
78 |
out_list = gr.Textbox(label="Reminders", lines=10)
|
79 |
+
gr.Button("List Reminders").click(fn=list_reminders, outputs=out_list)
|
|
|
80 |
|
81 |
with gr.Tab("π Check Whatβs Due"):
|
82 |
out_next = gr.Textbox(label="Next Reminder")
|
83 |
+
gr.Button("What's Next?").click(fn=check_next, outputs=out_next)
|
|
|
84 |
|
85 |
with gr.Tab("ποΈ Delete Reminder"):
|
86 |
del_time = gr.Textbox(label="Time to Delete (YYYY-MM-DD HH:MM)")
|
87 |
+
del_tz = gr.Dropdown(label="Timezone of Reminder", choices=timezone_choices, value="UTC")
|
88 |
out_del = gr.Textbox(label="Status")
|
89 |
+
gr.Button("Delete").click(fn=delete_reminder, inputs=[del_time, del_tz], outputs=out_del)
|
|
|
90 |
|
91 |
demo.launch()
|
requirements.txt
CHANGED
@@ -1 +1,2 @@
|
|
1 |
-
gradio
|
|
|
|
1 |
+
gradio
|
2 |
+
pytz
|