[ad_1]
In today’s fast-paced world, automated systems are becoming increasingly popular to streamline tasks and improve productivity. Fortunately, advances in artificial intelligence and automation have paved the way for innovative solutions that simplify this process.
OpenAI’s function calling feature is revolutionizing the way you interact with AI models. It allows developers to make direct API calls, generating dynamic responses based on user input. Using this powerful feature of ChatGPT, we will create an appointment booking chatbot that can engage in natural and meaningful conversations, giving users a personalized and interactive experience.
In this blog post, we’ll explore how to build a chatbot using OpenAI’s function calling feature that we’ll integrate with the Google Calendar API, allowing users to seamlessly book appointments without the need for manual intervention. Let’s dive in and discover the journey of building an intelligent appointment booking chatbot using ChatGPT and OpenAI’s feature calling feature integrated with the Google Calendar API.
If you are not familiar with OpenAI function calling, we recommend you refer to our blog post titled OpenAI Function Calling With External API Examples. This comprehensive guide provides a step-by-step overview of how to use this powerful functionality. It covers the use of OpenAI’s function calling functionality and its integration with the Google Calendar API, providing detailed explanations and practical examples. The script will allow you to easily book, reschedule, delete and check the availability of appointments.
Step 1:
In order to use the Google Calendar API to schedule meetings, it is necessary to set up your environment correctly. You can perform this setup by following the instructions in the following link: https://developers.google.com/calendar/api/quickstart/python#set_up_your_environment
You must follow each step, including enabling the API, configuring the OAuth consent screen, authorizing credentials for the desktop application, and installing the Google client library required to properly set up the API.
Step 2:
After completing the setup process, it is important to specify the appropriate editing scope for your application. On the desktop, you can navigate to the “Edit App” section located next to your app name. From there, go to the realms section and enable the “https://www.googleapis.com/auth/calendar” realm in your “Your sensitive realm” settings. After adding, remember to save your changes to make sure your app has the necessary permissions to interact effectively with the Google Calendar API.
Step 3:
Next, we will configure the sample instance. To do this, you need to create a file called “quickstart.py” in your working directory. Copy and paste the provided code snippet into this file. Make sure you have a “credentials.json” file in your working directory.
from __future__ import print_function
import datetime
import os.path
from google.auth.transport.requests import Request
from google.oauth2.credentials import Credentials
from google_auth_oauthlib.flow import InstalledAppFlow
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError
# If modifying these scopes, delete the file token.json.
SCOPES = ['https://www.googleapis.com/auth/calendar']
def main():
"""Shows basic usage of the Google Calendar API.
Prints the start and name of the next 10 events on the user's calendar.
"""
creds = None
# The file token.json stores the user's access and refresh tokens, and is
# created automatically when the authorization flow completes for the first
# time.
if os.path.exists('token.json'):
creds = Credentials.from_authorized_user_file('token.json', SCOPES)
# If there are no (valid) credentials available, let the user log in.
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)
# Save the credentials for the next run
with open('token.json', 'w') as token:
token.write(creds.to_json())
try:
service = build('calendar', 'v3', credentials=creds)
# Call the Calendar API
now = datetime.datetime.utcnow().isoformat() + 'Z' # 'Z' indicates UTC time
print('Getting the upcoming 10 events')
events_result = service.events().list(calendarId='primary', timeMin=now,
maxResults=10, singleEvents=True,
orderBy='startTime').execute()
events = events_result.get('items', [])
if not events:
print('No upcoming events found.')
return
# Prints the start and name of the next 10 events
for event in events:
start = event['start'].get('dateTime', event['start'].get('date'))
print(start, event['summary'])
except HttpError as error:
print('An error occurred: %s' % error)
if __name__ == '__main__':
main()
When you run quickstart.py for the first time, it will ask you to grant access to the application. If you have multiple Google Accounts, you can select the account you want and click the “Accept” button.
This step will create a “token.json” file in your working directory. This file will be the authorization token used for access authentication and authorization when declaring the specified area.
Step 4:
Now we can continue to develop a Python script to create an appointment booking chatbot that uses OpenAI function calls to schedule, reschedule, delete and check appointments by integrating the Google Calendar API.
First, we need to import the necessary libraries.
import json
import requests
from datetime import date, datetime, timedelta
from time import time
from googleapiclient.discovery import build
from google.oauth2.credentials import Credentials
import pytz
Step 5:
Next, we need to define a scope for accessing and managing calendar-related data through the Google Calendar API. Next, we create an instance of the Credentials object using the authenticated user information stored in the “token.json” file. Finally, we pass a Credentials object to construct a service object that allows us to interact with the Google Calendar API. To do this, you need to add the code below to your script.
Make sure you have a “token.json” file in your working directory.
SCOPES = ['https://www.googleapis.com/auth/calendar']
creds = Credentials.from_authorized_user_file('token.json', SCOPES)
service = build('calendar', 'v3', credentials=creds)
Step 6:
GPT_MODEL = "gpt-3.5-turbo-0613"
openai_api_key = "<Your_OpenAI_key>"
def chat_completion_request(messages, functions=None, function_call=None, model=GPT_MODEL):
headers =
"Content-Type": "application/json",
"Authorization": "Bearer " + openai_api_key,
json_data = "model": model, "messages": messages
if functions is not None:
json_data.update("functions": functions)
if function_call is not None:
json_data.update("function_call": function_call)
try:
response = requests.post(
"https://api.openai.com/v1/chat/completions",
headers=headers,
json=json_data,
)
return response
except Exception as e:
print("Unable to generate ChatCompletion response")
print(f"Exception: e")
return e
Step 7:
Let’s create a function for booking a meeting that will extract the necessary parameters from the argument object returned as a response from the ChatGPT function call.
The user is required to provide a start date, start time and email address. The start date and time will be combined to form a single parameter that will be passed to the Google Calendar API call as the scheduled start time of the meeting. By default, the end time of the meeting will be set two hours after the start. The email address provided will be assigned as a meeting attendee. An event JSON containing these details is passed as a parameter to the Google Calendar API insert event to book the appointment.
limit1 = datetime.strptime("10:00:00", "%H:%M:%S").time()
limit2 = datetime.strptime("17:00:00", "%H:%M:%S").time()
limit3 = datetime.strptime("12:00:00", "%H:%M:%S").time()
def appointment_booking(arguments):
try:
provided_date = str(datetime.strptime(json.loads(arguments)['date'], "%Y-%m-%d").date())
provided_time = str(datetime.strptime(json.loads(arguments)['time'].replace("PM","").replace("AM","").strip(), "%H:%M:%S").time())
start_date_time = provided_date + " " + provided_time
timezone = pytz.timezone('Asia/Kolkata')
start_date_time = timezone.localize(datetime.strptime(start_date_time, "%Y-%m-%d %H:%M:%S"))
email_address = json.loads(arguments)['email_address']
end_date_time = start_date_time + timedelta(hours=2)
if provided_date and provided_time and email_address:
slot_checking = appointment_checking(arguments)
if slot_checking == "Slot is available for appointment. Would you like to proceed?":
if start_date_time < datetime.now(timezone):
return "Please enter valid date and time."
else:
if day_list[start_date_time.date().weekday()] == "Saturday":
if start_date_time.time() >= limit1 and start_date_time.time() <= limit3:
event =
'summary': "Appointment booking Chatbot using OpenAI's function calling feature",
'location': "Ahmedabad",
'description': "This appointment has been scheduled as the demo of the appointment booking chatbot using OpenAI function calling feature by Pragnakalp Techlabs.",
'start':
'dateTime': start_date_time.strftime("%Y-%m-%dT%H:%M:%S"),
'timeZone': 'Asia/Kolkata',
,
'end':
'dateTime': end_date_time.strftime("%Y-%m-%dT%H:%M:%S"),
'timeZone': 'Asia/Kolkata',
,
'attendees': [
'email': email_address,
],
'reminders':
'useDefault': False,
'overrides': [
'method': 'email', 'minutes': 24 * 60,
'method': 'popup', 'minutes': 10,
],
,
service.events().insert(calendarId='primary', body=event).execute()
return "Appointment added successfully."
else:
return "Please try to book an appointment into working hours, which is 10 AM to 2 PM at saturday."
else:
if start_date_time.time() >= limit1 and start_date_time.time() <= limit2:
event =
'summary': "Appointment booking Chatbot using OpenAI's function calling feature",
'location': "Ahmedabad",
'description': "This appointment has been scheduled as the demo of the appointment booking chatbot using OpenAI function calling feature by Pragnakalp Techlabs.",
'start':
'dateTime': start_date_time.strftime("%Y-%m-%dT%H:%M:%S"),
'timeZone': 'Asia/Kolkata',
,
'end':
'dateTime': end_date_time.strftime("%Y-%m-%dT%H:%M:%S"),
'timeZone': 'Asia/Kolkata',
,
'attendees': [
'email': email_address,
],
'reminders':
'useDefault': False,
'overrides': [
'method': 'email', 'minutes': 24 * 60,
'method': 'popup', 'minutes': 10,
],
,
service.events().insert(calendarId='primary', body=event).execute()
return "Appointment added successfully."
else:
return "Please try to book an appointment into working hours, which is 10 AM to 7 PM."
else:
return slot_checking
else:
return "Please provide all necessary details: Start date, End date and Email address."
except:
return "We are facing an error while processing your request. Please try again."
Step 8:
Now we’ll define a function that helps us reschedule meetings. During the rescheduling process, the customer will be required to provide a new date, new time and email ID for identification purposes. Subsequently, the start time of the event will be generated by concatenating the provided start time and date.
The function starts by fetching the meeting event object that is being rescheduled. It then proceeds to update the start and end times of the event. Finally, the updated event object is passed to the Google Calendar API update event as a parameter.
def appointment_reschedule(arguments):
try:
provided_date = str(datetime.strptime(json.loads(arguments)['date'], "%Y-%m-%d").date())
provided_time = str(datetime.strptime(json.loads(arguments)['time'].replace("PM","").replace("AM","").strip(), "%H:%M:%S").time())
start_date_time = provided_date + " " + provided_time
timezone = pytz.timezone('Asia/Kolkata')
start_date_time = timezone.localize(datetime.strptime(start_date_time, "%Y-%m-%d %H:%M:%S"))
email_address = json.loads(arguments)['email_address']
if provided_date and provided_time and email_address:
if start_date_time < datetime.now(timezone):
return "Please enter valid date and time."
else:
if day_list[start_date_time.date().weekday()] == "Saturday":
if start_date_time.time() >= limit1 and start_date_time.time() <= limit3:
end_date_time = start_date_time + timedelta(hours=2)
events = service.events().list(calendarId="primary").execute()
id = ""
final_event = None
for event in events['items']:
if event['attendees'][0]['email'] == email_address:
id = event['id']
final_event = event
if final_event:
if appointment_checking(arguments) == "Slot is available for appointment. Would you like to proceed?":
final_event['start']['dateTime'] = start_date_time.strftime("%Y-%m-%dT%H:%M:%S")
final_event['end']['dateTime'] = end_date_time.strftime("%Y-%m-%dT%H:%M:%S")
service.events().update(calendarId='primary', eventId=id, body=final_event).execute()
return "Appointment rescheduled."
else:
return "Sorry, slot is not available at this time, please try a different time."
else:
return "No registered event found on your id."
else:
return "Please try to book an appointment into working hours, which is 10 AM to 2 PM at saturday."
else:
if start_date_time.time() >= limit1 and start_date_time.time() <= limit2:
end_date_time = start_date_time + timedelta(hours=2)
events = service.events().list(calendarId="primary").execute()
id = ""
final_event = None
for event in events['items']:
if event['attendees'][0]['email'] == email_address:
id = event['id']
final_event = event
if final_event:
if appointment_checking(arguments) == "Slot is available for appointment. Would you like to proceed?":
final_event['start']['dateTime'] = start_date_time.strftime("%Y-%m-%dT%H:%M:%S")
final_event['end']['dateTime'] = end_date_time.strftime("%Y-%m-%dT%H:%M:%S")
service.events().update(calendarId='primary', eventId=id, body=final_event).execute()
return "Appointment rescheduled."
else:
return "Sorry, slot is not available at this time, please try a different time."
else:
return "No registered event found on your id."
else:
return "Please try to book an appointment into working hours, which is 10 AM to 7 PM."
else:
return "Please provide all necessary details: Start date, End date and Email address."
except:
return "We are unable to process, please try again."
Step 9:
As we move forward, we will add functionality to delete an appointment. During this process, the user will be asked for the date, time and email address. Next, we will check if any registered events are scheduled for the specified email address. If an event is found, it will be deleted using the delete event provided by the Google Calendar API.
To implement the delete meeting function, please enter the following lines of code:
def appointment_delete(arguments):
try:
provided_date = str(datetime.strptime(json.loads(arguments)['date'], "%Y-%m-%d").date())
provided_time = str(datetime.strptime(json.loads(arguments)['time'].replace("PM","").replace("AM","").strip(), "%H:%M:%S").time())
email_address = json.loads(arguments)['email_address']
if provided_date and provided_time and email_address:
start_date_time = provided_date + " " + provided_time
timezone = pytz.timezone('Asia/Kolkata')
start_date_time = timezone.localize(datetime.strptime(start_date_time, "%Y-%m-%d %H:%M:%S"))
if start_date_time < datetime.now(timezone):
return "Please enter valid date and time."
else:
events = service.events().list(calendarId="primary").execute()
id = ""
for event in events['items']:
if event['attendees'][0]['email'] == email_address:
if datetime.fromisoformat(str(event['start']['dateTime'])) == datetime.fromisoformat(str(start_date_time)):
id = event['id']
if id:
service.events().delete(calendarId='primary', eventId=id).execute()
return "Appointment deleted successfully."
else:
return "No registered event found on your id."
else:
return "Please provide all necessary details: Start date, End date and Email address."
except:
return "We are unable to process, please try again."
Step 10:
For our last feature, we’ll implement a meeting check-in feature. Users are required to enter the desired date and time for the slot check. To confirm availability, we’ll use the “list” event from the Google Calendar API.
Please add the below lines of code to implement the appointment checking functionality.
def appointment_checking(arguments):
try:
provided_date = str(datetime.strptime(json.loads(arguments)['date'], "%Y-%m-%d").date())
provided_time = str(datetime.strptime(json.loads(arguments)['time'].replace("PM","").replace("AM","").strip(), "%H:%M:%S").time())
start_date_time = provided_date + " " + provided_time
timezone = pytz.timezone('Asia/Kolkata')
start_date_time = timezone.localize(datetime.strptime(start_date_time, "%Y-%m-%d %H:%M:%S"))
if start_date_time < datetime.now(timezone):
return "Please enter valid date and time."
else:
if day_list[start_date_time.date().weekday()] == "Saturday":
if start_date_time.time() >= limit1 and start_date_time.time() <= limit3:
end_date_time = start_date_time + timedelta(hours=2)
events_result = service.events().list(calendarId='primary', timeMin=start_date_time.isoformat(), timeMax=end_date_time.isoformat()).execute()
if events_result['items']:
return "Sorry slot is not available."
else:
return "Slot is available for appointment. Would you like to proceed?"
else:
return "Please try to check an appointment within working hours, which is 10 AM to 2 PM at saturday."
else:
if start_date_time.time() >= limit1 and start_date_time.time() <= limit2:
end_date_time = start_date_time + timedelta(hours=2)
events_result = service.events().list(calendarId='primary', timeMin=start_date_time.isoformat(), timeMax=end_date_time.isoformat()).execute()
if events_result['items']:
return "Sorry slot is not available."
else:
return "Slot is available for appointment. Would you like to proceed?"
else:
return "Please try to check an appointment within working hours, which is 10 AM to 7 PM."
except:
return "We are unable to process, please try again."
Step 11:
Next, we define a function specification that defines all of our functions, including appointment insertion, update, deletion, and validation. This function specification describes the purpose of the function and its parameters and the meaning of each parameter. When the user provides input, the ChatGPT model determines which function should be called and extracts the appropriate parameters to pass as arguments.
To describe the function specification, you need to add the following lines of code:
functions = [
"name": "appointment_booking",
"description": "When user want to book appointment, then this function should be called.",
"parameters":
"type": "object",
"properties":
"date":
"type": "string",
"format": "date",
"example":"2023-07-23",
"description": "Date, when the user wants to book an appointment. The date must be in the format of YYYY-MM-DD.",
,
"time":
"type": "string",
"example": "20:12:45",
"description": "time, on which user wants to book an appointment on a specified date. Time must be in %H:%M:%S format.",
,
"email_address":
"type": "string",
"description": "email_address of the user gives for identification.",
,
"required": ["date","time","email_address"],
,
,
"name": "appointment_reschedule",
"description": "When user want to reschedule appointment, then this function should be called.",
"parameters":
"type": "object",
"properties":
"date":
"type": "string",
"format": "date",
"example":"2023-07-23",
"description": "It is the date on which the user wants to reschedule the appointment. The date must be in the format of YYYY-MM-DD.",
,
"time":
"type": "string",
"description": "It is the time on which user wants to reschedule the appointment. Time must be in %H:%M:%S format.",
,
"email_address":
"type": "string",
"description": "email_address of the user gives for identification.",
,
"required": ["date","time","email_address"],
,
,
"name": "appointment_delete",
"description": "When user want to delete appointment, then this function should be called.",
"parameters":
"type": "object",
"properties":
"date":
"type": "string",
"format": "date",
"example":"2023-07-23",
"description": "Date, on which user has appointment and wants to delete it. The date must be in the format of YYYY-MM-DD.",
,
"time":
"type": "string",
"description": "time, on which user has an appointment and wants to delete it. Time must be in %H:%M:%S format.",
,
"email_address":
"type": "string",
"description": "email_address of the user gives for identification.",
,
"required": ["date","time","email_address"],
,
,
"name": "appointment_checking",
"description": "When user wants to check if appointment is available or not, then this function should be called.",
"parameters":
"type": "object",
"properties":
"date":
"type": "string",
"format": "date",
"example":"2023-07-23",
"description": "Date, when the user wants to book an appointment. The date must be in the format of YYYY-MM-DD.",
,
"time":
"type": "string",
"example": "20:12:45",
"description": "time, on which user wants to book an appointment on a specified date. Time must be in %H:%M:%S format.",
,
"required": ["date","time"],
,
]
Step 12:
Finally, we will begin the testing phase for our appointment booking chatbot. When specific queries are entered, the ChatGPT model automatically interprets the appropriate function to be called, along with the appropriate parameters. It will then return the name of the function and its arguments, allowing us to execute the function and fulfill our requests.
To run the test, please enter the following lines of code:
day_list = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']
messages = ["role": "system", "content": f"""You are an expert in booking appointments. You need to ask the user for the appointment date, appointment time, and email ID. The user can book the appointment from 10 AM to 7 PM from Monday to Friday, and from 10 AM to 2 PM on Saturdays. You need to remember that today's date is date.today() and day is day_list[date.today().weekday()]. Check if the time provided by the user is within the working hours then only you will proceed.
Instructions:
- Don't make assumptions about what values to plug into functions, if the user does not provide any of the required parameters then you must need to ask for clarification.
- Make sure the email Id is valid and not empty.
- If a user request is ambiguous, then also you need to ask for clarification.
- When a user asks for a rescheduling date or time of the current appointment, then you must ask for the new appointment details only.
- If a user didn't specify "ante meridiem (AM)" or "post meridiem (PM)" while providing the time, then you must have to ask for clarification. If the user didn't provide day, month, and year while giving the time then you must have to ask for clarification.
Make sure to follow the instructions carefully while processing the request.
"""]
user_input = input("Please enter your question here: (if you want to exit then write 'exit' or 'bye'.) ")
while user_input.strip().lower() != "exit" and user_input.strip().lower() != "bye":
messages.append("role": "user", "content": user_input)
# calling chat_completion_request to call ChatGPT completion endpoint
chat_response = chat_completion_request(
messages, functions=functions
)
# fetch response of ChatGPT and call the function
assistant_message = chat_response.json()["choices"][0]["message"]
if assistant_message['content']:
print("Response is: ", assistant_message['content'])
messages.append("role": "assistant", "content": assistant_message['content'])
else:
fn_name = assistant_message["function_call"]["name"]
arguments = assistant_message["function_call"]["arguments"]
function = locals()[fn_name]
result = function(arguments)
print("Response is: ", result)
user_input = input("Please enter your question here: ")
Test results:
Meeting check:
![](https://www.pragnakalp.com/wp-content/uploads/2023/06/appointment_checking_result-1024x122.png)
Book an appointment:
![](https://www.pragnakalp.com/wp-content/uploads/2023/06/appointment_booking_result-1024x183.png)
![](https://www.pragnakalp.com/wp-content/uploads/2023/06/appointment_insertion-1024x560.png)
Meeting replay:
![](https://www.pragnakalp.com/wp-content/uploads/2023/06/appointment_updation_result-1024x132.png)
![](https://www.pragnakalp.com/wp-content/uploads/2023/06/appointment_updation-1-1024x563.png)
Delete appointment:
![](https://www.pragnakalp.com/wp-content/uploads/2023/06/appointment_deletion_result-1024x74.png)
![](https://www.pragnakalp.com/wp-content/uploads/2023/06/appointment_deletion-1024x549.png)
We learned how to create an appointment booking chatbot using OpenAI’s function call function and the Google Calendar API. We’ve seen how we can use ChatGPT to create domain-closed chatbots using function callbacks. You can create more such closed domain chatbots using ChatGPT and you can also integrate any external API.
[ad_2]
Source link