genaitiwari commited on
Commit
a831891
·
1 Parent(s): e1283cc

appointment booking - completed

Browse files
README.md CHANGED
@@ -159,7 +159,9 @@ To stop the Streamlit app, press `Ctrl+C` in the terminal where the app is runni
159
  **Prompt 1**: Book an appointment for priti.
160
  **Prompt 2**: Yes or No.
161
  **Reference**:
162
- ![appointment receptionist](screenshots/appointment_receptionist.png)
 
 
163
 
164
  ### 4. Customer Support
165
  **Reference**:
 
159
  **Prompt 1**: Book an appointment for priti.
160
  **Prompt 2**: Yes or No.
161
  **Reference**:
162
+ ![appointment receptionist](screenshots/appointment_receptionist.png)
163
+ ![Graph appointment booking](screenshots/graph_appointment_booking.png)
164
+
165
 
166
  ### 4. Customer Support
167
  **Reference**:
screenshots/graph_appointment_booking.png ADDED
src/langgraphagenticai/graph/graph_builder.py CHANGED
@@ -1,6 +1,9 @@
1
- from langgraph.graph import StateGraph
2
- from langgraph.prebuilt import tools_condition
3
-
 
 
 
4
  from src.langgraphagenticai.tools.search_tool import create_tool_node, get_tools
5
  from src.langgraphagenticai.node.chatbot_with_tool_node import ChatbotWithToolNode
6
  from src.langgraphagenticai.node.basic_chatbot_node import BasicChatbotNode
@@ -57,6 +60,54 @@ class GraphBuilder:
57
 
58
  # Set entry point and compile graph
59
  self.graph_builder.set_entry_point("chatbot")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
60
 
61
 
62
  def setup_graph(self, usecase: str):
@@ -67,6 +118,8 @@ class GraphBuilder:
67
  self.basic_chatbot_build_graph()
68
  elif usecase == "Chatbot with Tool":
69
  self.chatbot_with_tool_build_graph()
 
 
70
  else:
71
  raise ValueError("Invalid use case selected.")
72
  return self.graph_builder.compile()
 
1
+ from langgraph.graph import StateGraph, END, MessagesState
2
+ from langgraph.prebuilt import tools_condition,ToolNode
3
+ from langchain_core.prompts import ChatPromptTemplate
4
+ import datetime
5
+ #module import
6
+ from src.langgraphagenticai.tools.customtool import book_appointment, cancel_appointment, get_next_available_appointment
7
  from src.langgraphagenticai.tools.search_tool import create_tool_node, get_tools
8
  from src.langgraphagenticai.node.chatbot_with_tool_node import ChatbotWithToolNode
9
  from src.langgraphagenticai.node.basic_chatbot_node import BasicChatbotNode
 
60
 
61
  # Set entry point and compile graph
62
  self.graph_builder.set_entry_point("chatbot")
63
+
64
+ # Nodes
65
+ def call_caller_model(self,state: MessagesState):
66
+ state["current_time"] = datetime.datetime.now().strftime("%Y-%m-%d %H:%M")
67
+ response = self.caller_model.invoke(state)
68
+ return {"messages": [response]}
69
+
70
+ # Edges
71
+ def should_continue_caller(self,state: MessagesState):
72
+ messages = state["messages"]
73
+ last_message = messages[-1]
74
+ if not last_message.tool_calls:
75
+ return "end"
76
+ else:
77
+ return "continue"
78
+
79
+ def appointment_receptionist_bot_build_graph(self):
80
+ caller_tools = [book_appointment, get_next_available_appointment, cancel_appointment]
81
+ tool_node = ToolNode(caller_tools)
82
+
83
+ caller_pa_prompt = """You are a personal assistant, and need to help the user to book or cancel appointments, you should check the available appointments before booking anything. Be extremely polite, so much so that it is almost rude.
84
+ Current time: {current_time}
85
+ """
86
+
87
+ caller_chat_template = ChatPromptTemplate.from_messages([
88
+ ("system", caller_pa_prompt),
89
+ ("placeholder", "{messages}"),
90
+ ])
91
+
92
+ self.caller_model = caller_chat_template | self.llm.bind_tools(caller_tools)
93
+
94
+ # Add Nodes
95
+ self.graph_builder.add_node("agent", self.call_caller_model)
96
+ self.graph_builder.add_node("action", tool_node)
97
+
98
+ # Add Edges
99
+ self.graph_builder.add_conditional_edges(
100
+ "agent",
101
+ self.should_continue_caller,
102
+ {
103
+ "continue": "action",
104
+ "end": END,
105
+ },
106
+ )
107
+ self.graph_builder.add_edge("action", "agent")
108
+
109
+ # Set Entry Point and build the graph
110
+ self.graph_builder.set_entry_point("agent")
111
 
112
 
113
  def setup_graph(self, usecase: str):
 
118
  self.basic_chatbot_build_graph()
119
  elif usecase == "Chatbot with Tool":
120
  self.chatbot_with_tool_build_graph()
121
+ elif usecase == "Appointment Receptionist":
122
+ self.appointment_receptionist_bot_build_graph()
123
  else:
124
  raise ValueError("Invalid use case selected.")
125
  return self.graph_builder.compile()
src/langgraphagenticai/tools/customtool.py ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from langchain_core.tools import tool
2
+ import datetime
3
+
4
+
5
+ APPOINTMENTS = []
6
+
7
+ @tool
8
+ def get_next_available_appointment():
9
+ """Returns the next available appointment"""
10
+ current_time = datetime.datetime.now()
11
+ return f"One appointment available at {current_time + datetime.timedelta(minutes=(30 - current_time.minute % 30))}"
12
+
13
+ @tool
14
+ def book_appointment(appointment_year: int, appointment_month: int, appointment_day: int, appointment_hour: int, appointment_minute: int, appointment_name: str):
15
+ """Book an appointment at the given time, you must know the exact time to book
16
+
17
+ Args:
18
+ appointment_year: The year of the appointment
19
+ appointment_month: The month of the appointment
20
+ appointment_day: The day of the appointment
21
+ appointment_hour: The hour of the appointment
22
+ appointment_minute: The minute of the appointment
23
+ appointment_name: The name of the person booking the appointment
24
+ """
25
+ time = datetime.datetime(appointment_year, appointment_month, appointment_day, appointment_hour, appointment_minute)
26
+ for appointment in APPOINTMENTS:
27
+ if appointment.time >= time and appointment.time < time + datetime.timedelta(minutes=30):
28
+ return f"Appointment at {time} is already booked"
29
+ APPOINTMENTS.append({"time": time, "name": appointment_name})
30
+ return f"Appointment booked for {time}"
31
+
32
+ @tool
33
+ def cancel_appointment(appointment_year: int, appointment_month: int, appointment_day: int, appointment_hour: int, appointment_minute: int):
34
+ """Cancel the appointment at the given time
35
+
36
+ Args:
37
+ appointment_year: The year of the appointment
38
+ appointment_month: The month of the appointment
39
+ appointment_day: The day of the appointment
40
+ appointment_hour: The hour of the appointment
41
+ appointment_minute: The minute of the appointment
42
+ """
43
+ time = datetime.datetime(appointment_year, appointment_month, appointment_day, appointment_hour, appointment_minute)
44
+ for appointment in APPOINTMENTS:
45
+ if appointment["time"] == time:
46
+ APPOINTMENTS.remove(appointment)
47
+ return f"Appointment at {time} cancelled"
48
+ return f"No appointment found at {time}"
src/langgraphagenticai/ui/streamlitui/display_result.py CHANGED
@@ -1,6 +1,8 @@
1
  import streamlit as st
2
  from langchain_core.messages import HumanMessage,AIMessage,ToolMessage
3
 
 
 
4
  class DisplayResultStreamlit:
5
  def __init__(self,usecase,graph,user_message):
6
  self.usecase= usecase
@@ -37,8 +39,30 @@ class DisplayResultStreamlit:
37
  elif type(message)==AIMessage and message.content:
38
  with st.chat_message("assistant"):
39
  st.write(message.content)
40
-
41
- # display graph
42
- if graph:
43
- st.write('state graph - workflow')
44
- st.image(graph.get_graph(xray=True).draw_mermaid_png())
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import streamlit as st
2
  from langchain_core.messages import HumanMessage,AIMessage,ToolMessage
3
 
4
+ from src.langgraphagenticai.tools.customtool import APPOINTMENTS
5
+
6
  class DisplayResultStreamlit:
7
  def __init__(self,usecase,graph,user_message):
8
  self.usecase= usecase
 
39
  elif type(message)==AIMessage and message.content:
40
  with st.chat_message("assistant"):
41
  st.write(message.content)
42
+ elif usecase == "Appointment Receptionist":
43
+ CONVERSATION=[]
44
+ CONVERSATION.append(HumanMessage(content=user_message, type="human"))
45
+ state = {
46
+ "messages": CONVERSATION,
47
+ }
48
+ print(state)
49
+ new_state = graph.invoke(state)
50
+ CONVERSATION.extend(new_state["messages"][len(CONVERSATION):])
51
+ col1, col2 = st.columns(2)
52
+ with col1:
53
+ for message in CONVERSATION:
54
+ if message and message.content:
55
+ if type(message) == HumanMessage:
56
+ with st.chat_message("user"):
57
+ st.write(message.content)
58
+ else:
59
+ with st.chat_message("assistant"):
60
+ st.write(message.content)
61
+
62
+ with col2:
63
+ st.header("Appointments")
64
+ st.write(APPOINTMENTS)
65
+ # display graph
66
+ if graph:
67
+ st.write('state graph - workflow')
68
+ st.image(graph.get_graph(xray=True).draw_mermaid_png())
src/langgraphagenticai/ui/streamlitui/loadui.py CHANGED
@@ -40,15 +40,10 @@ class LoadStreamlitUI:
40
 
41
  if self.user_controls['selected_usecase'] == "Appointment Receptionist":
42
  col1, col2 = st.columns(2)
43
-
44
  with col1:
45
  st.subheader("Appointment Manager")
46
-
47
  with col2:
48
  st.subheader("Appointments")
49
-
50
- # TODO :: to be removed
51
- st.warning("⌛Revamp is in progress...")
52
 
53
  elif self.user_controls['selected_usecase']=="Customer Support":
54
  # TODO :: to be removed
 
40
 
41
  if self.user_controls['selected_usecase'] == "Appointment Receptionist":
42
  col1, col2 = st.columns(2)
 
43
  with col1:
44
  st.subheader("Appointment Manager")
 
45
  with col2:
46
  st.subheader("Appointments")
 
 
 
47
 
48
  elif self.user_controls['selected_usecase']=="Customer Support":
49
  # TODO :: to be removed