scheduler / app.py
asiaao's picture
Update app.py
da20b6f verified
import gradio as gr
import os
import pickle
import datetime
import pandas as pd
import plotly.graph_objects as go
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
import io
from googleapiclient.http import MediaIoBaseDownload
from huggingface_hub import InferenceClient
# Google Calendar API setup
SCOPES = ['https://www.googleapis.com/auth/calendar']
def authenticate_google_calendar():
"""Authenticate and return the Google Calendar API service."""
creds = None
# Check if token.pickle exists and is valid
if os.path.exists('token.pickle'):
with open('token.pickle', 'rb') as token:
creds = pickle.load(token)
# If no valid credentials are found, trigger OAuth2 flow
if not creds or not creds.valid:
if creds and creds.expired and creds.refresh_token:
creds.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file(
'credentials.json', SCOPES)
creds = flow.run_local_server(port=0) # This will open a browser for user authorization
# Save the credentials for future use
with open('token.pickle', 'wb') as token:
pickle.dump(creds, token)
return build('calendar', 'v3', credentials=creds)
def add_event_to_calendar(event_details):
"""Add the event to the user's Google Calendar."""
service = authenticate_google_calendar()
event = {
'summary': event_details['title'],
'start': {
'dateTime': f"{event_details['date']}T{event_details['time']}:00",
'timeZone': 'UTC', # Adjust for user's timezone if needed
},
'end': {
'dateTime': f"{event_details['date']}T{event_details['time']}:00",
'timeZone': 'UTC',
},
}
try:
# Create the event
created_event = service.events().insert(calendarId='primary', body=event).execute()
return created_event
except Exception as e:
return f"Failed to add event: {str(e)}"
def get_calendar_events():
"""Fetch events from the user's Google Calendar."""
service = authenticate_google_calendar()
now = datetime.datetime.utcnow().isoformat() + 'Z' # 'Z' indicates UTC time
events_result = service.events().list(calendarId='primary', timeMin=now, maxResults=10, singleEvents=True, orderBy='startTime').execute()
events = events_result.get('items', [])
# Prepare data for visualization
events_data = []
for event in events:
event_start = event['start'].get('dateTime', event['start'].get('date'))
events_data.append({
'Event': event['summary'],
'Start Time': event_start
})
# Convert to DataFrame for use with Plotly
df = pd.DataFrame(events_data)
df['Start Time'] = pd.to_datetime(df['Start Time'])
return df
def plot_calendar(events_df):
"""Plot an interactive calendar using Plotly with a Notion-like clean design."""
# Convert the event DataFrame into a format suitable for Plotly
events_df['Start Time'] = pd.to_datetime(events_df['Start Time'])
events_df['Date'] = events_df['Start Time'].dt.date
events_df['Hour'] = events_df['Start Time'].dt.hour
events_df['Minute'] = events_df['Start Time'].dt.minute
# Create a list of unique dates in the event data
unique_dates = events_df['Date'].unique()
# Create a calendar grid (e.g., 7 days in a week, so the grid could be 7xN)
calendar_grid = go.Figure()
calendar_grid.update_layout(
title="Upcoming Events",
xaxis=dict(tickvals=list(range(len(unique_dates))), ticktext=unique_dates, title="Date"),
yaxis=dict(tickvals=[0, 1, 2, 3, 4, 5], ticktext=["9 AM", "12 PM", "3 PM", "6 PM", "9 PM", "12 AM"], title="Time Slot"),
showlegend=False,
margin=dict(l=40, r=40, b=40, t=40),
height=600, # Adjust the height for better readability
template="plotly_white" # Clean, minimalistic Plotly theme
)
# Add events to the grid
for _, event in events_df.iterrows():
start_hour = event['Hour']
event_date = event['Date']
event_time = f"{start_hour}:00"
event_text = event['Event']
calendar_grid.add_trace(go.Scatter(
x=[list(unique_dates).index(event_date)], # Position along the x-axis (dates)
y=[start_hour % 12], # Position on the y-axis (time slots)
text=event_text,
mode="markers+text",
textposition="middle center",
marker=dict(color="blue", size=12, opacity=0.7),
name=event_text
))
return calendar_grid
# Hugging Face InferenceClient setup
client = InferenceClient("HuggingFaceH4/zephyr-7b-beta")
def respond(
message,
history: list[tuple[str, str]],
system_message,
max_tokens,
temperature,
top_p,
):
# Prepare the conversation messages
messages = [{"role": "system", "content": system_message}]
for val in history:
if val[0]:
messages.append({"role": "user", "content": val[0]})
if val[1]:
messages.append({"role": "assistant", "content": val[1]})
messages.append({"role": "user", "content": message})
# Get response from Hugging Face model
response = ""
for message in client.chat_completion(
messages,
max_tokens=max_tokens,
stream=True,
temperature=temperature,
top_p=top_p,
):
token = message.choices[0].delta.content
response += token
yield response
# If the response is a scheduling request, handle it
if "schedule" in message.lower():
# Example: "Schedule meeting tomorrow at 3 PM"
event_details = parse_event_details(message)
created_event = add_event_to_calendar(event_details)
events_df = get_calendar_events() # Get updated events
return f"Event scheduled for {event_details['date']} at {event_details['time']}.\n{plot_calendar(events_df)}"
def parse_event_details(user_input):
"""Parse user input to extract event details like title, date, and time."""
today = datetime.date.today()
tomorrow = today + datetime.timedelta(days=1)
# Extract title and time (just for demonstration purposes)
event_title = "Meeting" # Could be improved by NLP parsing
event_date = tomorrow.strftime("%Y-%m-%d")
event_time = "15:00" # Hardcoded to 3 PM for simplicity
return {"title": event_title, "date": event_date, "time": event_time}
# Gradio Interface
with gr.Blocks() as demo:
gr.Markdown("## Chatbot for Scheduling and Calendar")
chatbot = gr.ChatInterface(
respond,
additional_inputs=[
gr.Textbox(value="You are a friendly chatbot. You can help schedule events.", label="System message"),
gr.Slider(minimum=1, maximum=2048, value=512, step=1, label="Max new tokens"),
gr.Slider(minimum=0.1, maximum=4.0, value=0.7, step=0.1, label="Temperature"),
gr.Slider(minimum=0.1, maximum=1.0, value=0.95, step=0.05, label="Top-p (nucleus sampling)"),
],
)
with gr.Row():
calendar_button = gr.Button("Show Calendar")
calendar_plot = gr.Plot()
calendar_button.click(
lambda: plot_calendar(get_calendar_events()),
outputs=calendar_plot
)
if __name__ == "__main__":
demo.launch()