|
|
|
|
|
""" |
|
|
AI Assistant - Hugging Face Spaces Entry Point |
|
|
This is the main entry point for Hugging Face Spaces deployment |
|
|
""" |
|
|
|
|
|
import gradio as gr |
|
|
import json |
|
|
import os |
|
|
from datetime import datetime, timedelta |
|
|
from typing import List, Tuple |
|
|
from pathlib import Path |
|
|
|
|
|
class SimpleAIAssistant: |
|
|
"""Simple AI Assistant for Hugging Face Spaces""" |
|
|
|
|
|
def __init__(self): |
|
|
self.data_dir = Path("data") |
|
|
self.data_dir.mkdir(exist_ok=True) |
|
|
|
|
|
self.notes_file = self.data_dir / "notes.json" |
|
|
self.reminders_file = self.data_dir / "reminders.json" |
|
|
self.chat_history_file = self.data_dir / "chat_history.json" |
|
|
|
|
|
self.notes = self._load_json(self.notes_file, []) |
|
|
self.reminders = self._load_json(self.reminders_file, []) |
|
|
self.chat_history = self._load_json(self.chat_history_file, []) |
|
|
|
|
|
def _load_json(self, file_path: Path, default): |
|
|
try: |
|
|
if file_path.exists(): |
|
|
with open(file_path, 'r', encoding='utf-8') as f: |
|
|
return json.load(f) |
|
|
except: |
|
|
pass |
|
|
return default |
|
|
|
|
|
def _save_json(self, file_path: Path, data): |
|
|
try: |
|
|
with open(file_path, 'w', encoding='utf-8') as f: |
|
|
json.dump(data, f, indent=2, ensure_ascii=False, default=str) |
|
|
except: |
|
|
pass |
|
|
|
|
|
def chat_with_ai(self, message: str, history: List[List[str]]) -> Tuple[str, List[List[str]]]: |
|
|
if not message.strip(): |
|
|
return "", history |
|
|
|
|
|
|
|
|
response = self._generate_response(message) |
|
|
|
|
|
|
|
|
history.append([message, response]) |
|
|
self.chat_history = history |
|
|
self._save_json(self.chat_history_file, history) |
|
|
|
|
|
return "", history |
|
|
|
|
|
def _generate_response(self, message: str) -> str: |
|
|
message_lower = message.lower() |
|
|
|
|
|
if any(word in message_lower for word in ['hello', 'hi', 'hey']): |
|
|
return "Hello! π I'm your AI Assistant. I can help with notes, reminders, and answer questions!" |
|
|
|
|
|
elif any(word in message_lower for word in ['note', 'notes']): |
|
|
return f"π You have {len(self.notes)} notes. Use the Notes tab to create and manage them!" |
|
|
|
|
|
elif any(word in message_lower for word in ['remind', 'reminder']): |
|
|
active = len([r for r in self.reminders if not r.get('completed', False)]) |
|
|
return f"β° You have {active} active reminders. Use the Reminders tab to manage them!" |
|
|
|
|
|
elif any(word in message_lower for word in ['help', 'what can you do']): |
|
|
return """π€ I can help you with: |
|
|
- π¬ Chat and answer questions |
|
|
- π Create and manage notes |
|
|
- β° Set and track reminders |
|
|
- π Process documents |
|
|
- π» Show system information |
|
|
|
|
|
Try the different tabs above!""" |
|
|
|
|
|
else: |
|
|
return f"Thanks for your message! I'm here to help with notes, reminders, and questions. What would you like to do?" |
|
|
|
|
|
def create_note(self, title: str, content: str) -> str: |
|
|
if not title.strip(): |
|
|
return "β Please provide a title" |
|
|
|
|
|
note = { |
|
|
"id": len(self.notes) + 1, |
|
|
"title": title.strip(), |
|
|
"content": content.strip(), |
|
|
"created_at": datetime.now().isoformat() |
|
|
} |
|
|
|
|
|
self.notes.append(note) |
|
|
self._save_json(self.notes_file, self.notes) |
|
|
return f"β
Note '{title}' created!" |
|
|
|
|
|
def get_notes_display(self) -> str: |
|
|
if not self.notes: |
|
|
return "π No notes yet. Create your first note above!" |
|
|
|
|
|
text = f"π **Your Notes ({len(self.notes)} total)**\n\n" |
|
|
for note in sorted(self.notes, key=lambda x: x['created_at'], reverse=True): |
|
|
created = datetime.fromisoformat(note['created_at']).strftime("%Y-%m-%d %H:%M") |
|
|
text += f"**{note['title']}**\n*{created}*\n{note['content'][:100]}...\n---\n" |
|
|
return text |
|
|
|
|
|
def create_reminder(self, title: str, description: str, reminder_time: str) -> str: |
|
|
if not title.strip(): |
|
|
return "β Please provide a title" |
|
|
|
|
|
try: |
|
|
if reminder_time: |
|
|
dt = datetime.fromisoformat(reminder_time.replace('T', ' ')) |
|
|
else: |
|
|
dt = datetime.now() + timedelta(hours=1) |
|
|
except: |
|
|
return "β Invalid time format. Use YYYY-MM-DD HH:MM" |
|
|
|
|
|
reminder = { |
|
|
"id": len(self.reminders) + 1, |
|
|
"title": title.strip(), |
|
|
"description": description.strip(), |
|
|
"reminder_time": dt.isoformat(), |
|
|
"completed": False |
|
|
} |
|
|
|
|
|
self.reminders.append(reminder) |
|
|
self._save_json(self.reminders_file, self.reminders) |
|
|
return f"β
Reminder set for {dt.strftime('%Y-%m-%d %H:%M')}" |
|
|
|
|
|
def get_reminders_display(self) -> str: |
|
|
if not self.reminders: |
|
|
return "β° No reminders yet. Create your first reminder above!" |
|
|
|
|
|
active = [r for r in self.reminders if not r.get('completed', False)] |
|
|
text = f"β° **Active Reminders ({len(active)})**\n\n" |
|
|
|
|
|
for reminder in sorted(active, key=lambda x: x['reminder_time']): |
|
|
time_str = datetime.fromisoformat(reminder['reminder_time']).strftime("%Y-%m-%d %H:%M") |
|
|
text += f"**{reminder['title']}**\n*{time_str}*\n{reminder['description']}\n---\n" |
|
|
|
|
|
return text |
|
|
|
|
|
def create_interface(): |
|
|
assistant = SimpleAIAssistant() |
|
|
|
|
|
with gr.Blocks(title="π€ AI Assistant", theme=gr.themes.Soft()) as app: |
|
|
gr.Markdown(""" |
|
|
# π€ AI Assistant |
|
|
Your personal AI companion for notes, reminders, and more! |
|
|
""") |
|
|
|
|
|
with gr.Tabs(): |
|
|
with gr.Tab("π¬ Chat"): |
|
|
chatbot = gr.Chatbot(value=assistant.chat_history, height=400) |
|
|
with gr.Row(): |
|
|
msg = gr.Textbox(placeholder="Ask me anything...", scale=4) |
|
|
send = gr.Button("Send", variant="primary", scale=1) |
|
|
|
|
|
msg.submit(assistant.chat_with_ai, [msg, chatbot], [msg, chatbot]) |
|
|
send.click(assistant.chat_with_ai, [msg, chatbot], [msg, chatbot]) |
|
|
|
|
|
with gr.Tab("π Notes"): |
|
|
with gr.Row(): |
|
|
with gr.Column(): |
|
|
title = gr.Textbox(label="Title") |
|
|
content = gr.Textbox(label="Content", lines=5) |
|
|
create_btn = gr.Button("Create Note", variant="primary") |
|
|
status = gr.Textbox(label="Status", interactive=False) |
|
|
|
|
|
with gr.Column(): |
|
|
notes_display = gr.Markdown(assistant.get_notes_display()) |
|
|
refresh_btn = gr.Button("Refresh") |
|
|
|
|
|
create_btn.click(assistant.create_note, [title, content], status).then( |
|
|
lambda: ("", ""), outputs=[title, content] |
|
|
).then(assistant.get_notes_display, outputs=notes_display) |
|
|
|
|
|
refresh_btn.click(assistant.get_notes_display, outputs=notes_display) |
|
|
|
|
|
with gr.Tab("β° Reminders"): |
|
|
with gr.Row(): |
|
|
with gr.Column(): |
|
|
r_title = gr.Textbox(label="Title") |
|
|
r_desc = gr.Textbox(label="Description", lines=3) |
|
|
r_time = gr.Textbox(label="Time (YYYY-MM-DD HH:MM)", placeholder="2024-12-25 14:30") |
|
|
r_create_btn = gr.Button("Set Reminder", variant="primary") |
|
|
r_status = gr.Textbox(label="Status", interactive=False) |
|
|
|
|
|
with gr.Column(): |
|
|
reminders_display = gr.Markdown(assistant.get_reminders_display()) |
|
|
r_refresh_btn = gr.Button("Refresh") |
|
|
|
|
|
r_create_btn.click(assistant.create_reminder, [r_title, r_desc, r_time], r_status).then( |
|
|
lambda: ("", "", ""), outputs=[r_title, r_desc, r_time] |
|
|
).then(assistant.get_reminders_display, outputs=reminders_display) |
|
|
|
|
|
r_refresh_btn.click(assistant.get_reminders_display, outputs=reminders_display) |
|
|
|
|
|
gr.Markdown("Built with β€οΈ using Gradio") |
|
|
|
|
|
return app |
|
|
|
|
|
if __name__ == "__main__": |
|
|
app = create_interface() |
|
|
app.launch( |
|
|
server_name="0.0.0.0", |
|
|
server_port=int(os.environ.get("PORT", 7860)), |
|
|
share=False, |
|
|
debug=False, |
|
|
show_error=True |
|
|
) |