genaitiwari commited on
Commit
a75702e
·
1 Parent(s): 5110d54

added customer support usecases

Browse files
.gitignore ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+
2
+ __pycache__/configfile.cpython-311.pyc
3
+ *.pyc
4
+ *.sqlite3
README.md CHANGED
@@ -16,3 +16,8 @@ short_description: Langgraph
16
  ### 1. Appointment Receptionist
17
  reference:
18
  ![alt text](appointment_receptionist.png)
 
 
 
 
 
 
16
  ### 1. Appointment Receptionist
17
  reference:
18
  ![alt text](appointment_receptionist.png)
19
+
20
+ ### 2. Customer Support
21
+ reference:
22
+ ![alt text](cs_flow.png)
23
+ ![alt text](image.png)
app.py CHANGED
@@ -51,12 +51,66 @@ if __name__ == "__main__":
51
  with col2:
52
  st.header("Appointments")
53
  st.write(APPOINTMENTS)
54
-
55
 
56
-
57
 
58
-
59
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
60
 
61
 
62
 
 
51
  with col2:
52
  st.header("Appointments")
53
  st.write(APPOINTMENTS)
 
54
 
 
55
 
56
+
57
+ elif user_input['selected_usecase'] == "Customer Support":
58
+ from src.csbot.customer_support_chatbot import Customer_Support_Bot
59
+ from langchain_core.messages import AIMessage, HumanMessage
60
+ from src.tools.customer_support_tools import customers_database, data_protection_checks
61
+
62
+
63
+ st.subheader('Flower Shop Chatbot' + '💐')
64
+
65
+ if 'message_history' not in st.session_state:
66
+ st.session_state.message_history = [AIMessage(content="Hiya, Im the flower shop chatbot. How can I help?")]
67
+
68
+ main_col, right_col = st.columns([2, 1])
69
+
70
+ # 1. Buttons for chat - Clear Button
71
+
72
+ with st.sidebar:
73
+ if st.button('Clear Chat'):
74
+ st.session_state.message_history = []
75
+
76
+
77
+ # 2. Chat history and input
78
+ with main_col:
79
+ user_message = st.chat_input("Type here...")
80
+
81
+ if user_message:
82
+ st.session_state.message_history.append(HumanMessage(content=user_message))
83
+ obj_llm_config = GroqLLM(user_controls_input=user_input)
84
+ llm = obj_llm_config.get_llm_model()
85
+ obj_cs_bot = Customer_Support_Bot(llm=llm)
86
+ app = obj_cs_bot.chat_bot()
87
+
88
+ response = app.invoke({
89
+ 'messages': st.session_state.message_history
90
+ })
91
+
92
+ st.session_state.message_history = response['messages']
93
+
94
+ for i in range(1, len(st.session_state.message_history) + 1):
95
+ this_message = st.session_state.message_history[-i]
96
+ if isinstance(this_message, AIMessage):
97
+ message_box = st.chat_message('assistant')
98
+ else:
99
+ message_box = st.chat_message('user')
100
+ message_box.markdown(this_message.content)
101
+ # 3. State variables
102
+
103
+ with right_col:
104
+ st.title('customers database')
105
+ st.write(customers_database)
106
+ st.title('data protection checks')
107
+ st.write(data_protection_checks)
108
+
109
+
110
+
111
+
112
+
113
+
114
 
115
 
116
 
configfile.ini CHANGED
@@ -1,6 +1,6 @@
1
  [DEFAULT]
2
  PAGE_TITLE = Langgraph IN ACTION
3
  LLM_OPTIONS = Groq
4
- USECASE_OPTIONS = Appointment Receptionist
5
  GROQ_MODEL_OPTIONS = mixtral-8x7b-32768, llama3-8b-8192, llama3-70b-8192, gemma-7b-i
6
 
 
1
  [DEFAULT]
2
  PAGE_TITLE = Langgraph IN ACTION
3
  LLM_OPTIONS = Groq
4
+ USECASE_OPTIONS = Appointment Receptionist, Customer Support
5
  GROQ_MODEL_OPTIONS = mixtral-8x7b-32768, llama3-8b-8192, llama3-70b-8192, gemma-7b-i
6
 
cs-flow.png ADDED
customer_support.png ADDED
data/FAQ.json ADDED
@@ -0,0 +1,83 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [
2
+ {
3
+ "question": "What types of flowers do you offer?",
4
+ "answer": "We offer a wide variety of flowers including roses, lilies, tulips, sunflowers, orchids, and seasonal bouquets. Our selection changes regularly to ensure freshness and variety."
5
+ },
6
+ {
7
+ "question": "How do I place an order?",
8
+ "answer": "You can place an order easily through our website. Simply browse our selection, choose your desired flowers, add them to your cart, and proceed to checkout. You'll need to provide delivery details and payment information to complete your order."
9
+ },
10
+ {
11
+ "question": "What are your delivery options?",
12
+ "answer": "We offer same-day delivery for orders placed before noon, next-day delivery, and scheduled delivery for future dates. Delivery options may vary based on your location and the availability of the flowers you've selected."
13
+ },
14
+ {
15
+ "question": "Do you offer international shipping?",
16
+ "answer": "Currently, we only offer delivery within the country. We're working on expanding our services internationally in the future."
17
+ },
18
+ {
19
+ "question": "How do I ensure my flowers stay fresh?",
20
+ "answer": "To keep your flowers fresh, change the water every 2-3 days, trim the stems at an angle, remove any leaves below the waterline, and keep the flowers away from direct sunlight and heat sources."
21
+ },
22
+ {
23
+ "question": "Can I customize my bouquet?",
24
+ "answer": "Yes, we offer customization options. You can choose specific flowers, colors, and arrangements. For special requests, please contact our customer service team."
25
+ },
26
+ {
27
+ "question": "What if my flowers arrive damaged?",
28
+ "answer": "We have a 100% satisfaction guarantee. If your flowers arrive damaged or you're not satisfied with your order, please contact us within 24 hours of delivery, and we'll either replace your order or provide a full refund."
29
+ },
30
+ {
31
+ "question": "Do you offer subscription services?",
32
+ "answer": "Yes, we offer weekly, bi-weekly, and monthly flower subscription services. You can choose the frequency, duration, and type of flowers you'd like to receive regularly."
33
+ },
34
+ {
35
+ "question": "What payment methods do you accept?",
36
+ "answer": "We accept all major credit cards, PayPal, and Apple Pay for online orders. For large corporate orders, we also offer invoicing options."
37
+ },
38
+ {
39
+ "question": "Can I include a personalized message with my flower delivery?",
40
+ "answer": "Absolutely! During the checkout process, you'll have the option to add a personalized message card to your order at no extra cost."
41
+ },
42
+ {
43
+ "question": "Do you offer eco-friendly or sustainable options?",
44
+ "answer": "Yes, we have a range of eco-friendly options including locally sourced flowers, biodegradable packaging, and potted plants that can be replanted."
45
+ },
46
+ {
47
+ "question": "What if the recipient isn't home when the flowers are delivered?",
48
+ "answer": "If the recipient isn't home, our delivery person will try to leave the flowers in a safe place. If that's not possible, we'll leave a note and attempt redelivery the next day."
49
+ },
50
+ {
51
+ "question": "Do you offer corporate or event services?",
52
+ "answer": "Yes, we provide flower arrangements for corporate events, weddings, and other special occasions. Please contact our events team for more information and custom quotes."
53
+ },
54
+ {
55
+ "question": "How far in advance should I order for special occasions like Valentine's Day?",
56
+ "answer": "For major holidays like Valentine's Day, Mother's Day, or Christmas, we recommend placing your order at least 1-2 weeks in advance to ensure availability and timely delivery."
57
+ },
58
+ {
59
+ "question": "Can I track my order?",
60
+ "answer": "Yes, once your order is dispatched, you'll receive a tracking number via email that you can use to monitor the status and estimated delivery time of your flowers."
61
+ },
62
+ {
63
+ "question": "Do you offer flower care tips?",
64
+ "answer": "Yes, each bouquet comes with a care instruction card. You can also find detailed flower care guides on our website under the 'Flower Care' section."
65
+ },
66
+ {
67
+ "question": "What if the flowers I want are out of season?",
68
+ "answer": "If certain flowers are out of season, we offer similar alternatives or can create custom arrangements using in-season blooms that match your desired style and color scheme."
69
+ },
70
+ {
71
+ "question": "Do you offer gift options besides flowers?",
72
+ "answer": "Yes, we offer complementary gifts such as chocolates, teddy bears, balloons, and gift baskets that can be added to your flower order or purchased separately."
73
+ },
74
+ {
75
+ "question": "How do I know which flowers are appropriate for different occasions?",
76
+ "answer": "Our website provides guidance on flower meanings and appropriate choices for various occasions. You can also chat with our customer service team for personalized recommendations."
77
+ },
78
+ {
79
+ "question": "What's your return policy?",
80
+ "answer": "Due to the perishable nature of flowers, we don't accept returns. However, if you're unsatisfied with your order, please contact us within 24 hours of delivery, and we'll work to resolve the issue to your satisfaction."
81
+ }
82
+
83
+ ]
data/inventory.json ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [
2
+ {"id": "P001", "name": "Romantic Red Rose Bouquet", "quantity": 15, "price": 80, "type": "bouquet", "description": "A medium-sized bouquet of red roses with green foliage, perfect for anniversaries and weddings. This moderately priced bouquet is a classic choice for romantic occasions."},
3
+ {"id": "P002", "name": "Spring Tulip Medley", "quantity": 12, "price": 65, "type": "bouquet", "description": "A medium-sized bouquet featuring a vibrant mix of yellow, pink, purple, and orange tulips, ideal for birthdays. This affordable bouquet brings the freshness of spring to any celebration."},
4
+ {"id": "P003", "name": "Elegant White Lily Arrangement", "quantity": 10, "price": 90, "type": "arrangement", "description": "A large arrangement of white lilies with green accents, suitable for weddings. This premium arrangement adds a touch of elegance to any venue."},
5
+ {"id": "P004", "name": "Vibrant Sunflower Surprise", "quantity": 8, "price": 70, "type": "bouquet", "description": "A medium-sized bouquet of bright yellow sunflowers with brown centers, great for birthdays and congratulations. This reasonably priced bouquet is sure to bring smiles."},
6
+ {"id": "P005", "name": "Pastel Peony Paradise", "quantity": 10, "price": 95, "type": "bouquet", "description": "A large bouquet featuring a soft blend of pink, purple, white, and blue peonies, perfect for Mother's Day. This luxurious bouquet is a stunning gift for any special woman."},
7
+ {"id": "P006", "name": "Exotic Orchid Ensemble", "quantity": 6, "price": 110, "type": "arrangement", "description": "A medium-sized arrangement of purple and black orchids, suitable for corporate events. This high-end arrangement adds a touch of sophistication to any business setting."},
8
+ {"id": "P007", "name": "Wildflower Wonderland Bouquet", "quantity": 14, "price": 75, "type": "bouquet", "description": "A large, colorful bouquet of mixed wildflowers in red, yellow, pink, purple, blue, and orange, ideal for birthdays and thank you gifts. This mid-range bouquet brings a burst of nature's beauty."},
9
+ {"id": "P008", "name": "Classic Carnation Cluster", "quantity": 18, "price": 60, "type": "bouquet", "description": "A medium-sized bouquet of pink and white carnations, perfect for Mother's Day. This budget-friendly bouquet is a timeless gesture of love and appreciation."},
10
+ {"id": "P009", "name": "Deluxe Mixed Bouquet", "quantity": 10, "price": 85, "type": "bouquet", "description": "A large bouquet with a variety of flowers in red, white, yellow, pink, purple, blue, and orange, suitable for general occasions and congratulations. This diverse, moderately priced bouquet is perfect for any celebration."},
11
+ {"id": "P010", "name": "Seasonal Blooms Bonanza", "quantity": 12, "price": 78, "type": "bouquet", "description": "A medium-sized bouquet featuring seasonal flowers in red, yellow, pink, purple, orange, and brown, perfect for any general occasion. This reasonably priced bouquet showcases the best of the season."},
12
+ {"id": "P011", "name": "Crystal Clear Glass Vase", "quantity": 25, "price": 30, "type": "vase", "description": "A small, clear glass vase with subtle blue tints, suitable for various flower arrangements. This affordable vase complements any bouquet or arrangement."},
13
+ {"id": "P012", "name": "Rustic Ceramic Vase", "quantity": 20, "price": 35, "type": "vase", "description": "A medium-sized ceramic vase in earthy brown and black tones, perfect for rustic or natural arrangements. This reasonably priced vase adds a touch of warmth to any display."},
14
+ {"id": "P013", "name": "Modern Metallic Vase", "quantity": 15, "price": 40, "type": "vase", "description": "A medium-sized vase with a sleek white and black metallic finish, ideal for contemporary corporate settings. This mid-range vase is perfect for modern floral designs."},
15
+ {"id": "P014", "name": "Rustic Farmhouse Arrangement", "quantity": 8, "price": 95, "type": "arrangement", "description": "A large arrangement featuring white and green flowers with brown accents in a rustic container, suitable for general and corporate events. This premium arrangement brings a touch of countryside charm."},
16
+ {"id": "P015", "name": "Tropical Paradise Arrangement", "quantity": 6, "price": 120, "type": "arrangement", "description": "A large, exotic arrangement with vibrant orange, pink, green, and blue tropical flowers, perfect for birthdays and congratulations. This high-end arrangement is a stunning centerpiece for any celebration."},
17
+ {"id": "P016", "name": "Zen Garden Succulent Arrangement", "quantity": 10, "price": 85, "type": "arrangement", "description": "A small, tranquil arrangement of various succulents in shades of green, blue, purple, and brown, ideal for corporate or general gifts. This moderately priced arrangement brings a sense of calm to any space."},
18
+ {"id": "P017", "name": "Vintage Teacup Floral Arrangement", "quantity": 12, "price": 55, "type": "arrangement", "description": "A small, charming arrangement of pink, purple, white, and yellow flowers in a vintage teacup, perfect for Mother's Day or as a thank you gift. This affordable arrangement offers a unique and delightful presentation."},
19
+ {"id": "P018", "name": "Modern Monochrome Arrangement", "quantity": 7, "price": 100, "type": "arrangement", "description": "A medium-sized, sleek arrangement featuring white and green flowers with black accents, suitable for corporate events or modern home decor. This premium arrangement adds a touch of sophistication to any setting."},
20
+ {"id": "P019", "name": "Autumn Harvest Bouquet", "quantity": 10, "price": 75, "type": "bouquet", "description": "A medium-sized bouquet with warm orange, red, yellow, and brown flowers, perfect for Thanksgiving or autumn-themed events. This reasonably priced bouquet captures the essence of fall."},
21
+ {"id": "P020", "name": "Winter Wonderland Arrangement", "quantity": 8, "price": 95, "type": "arrangement", "description": "A large arrangement featuring white and blue flowers with silver accents, ideal for Christmas or winter corporate events. This premium arrangement brings a touch of frosty elegance to any space."},
22
+ {"id": "P021", "name": "Spring Awakening Bouquet", "quantity": 12, "price": 70, "type": "bouquet", "description": "A medium-sized bouquet with fresh pink, yellow, purple, and green spring flowers, suitable for Easter or spring birthdays. This affordable bouquet is a burst of springtime joy."},
23
+ {"id": "P022", "name": "Summer Sunset Arrangement", "quantity": 9, "price": 85, "type": "arrangement", "description": "A large arrangement with warm orange, red, yellow, and pink flowers reminiscent of a summer sunset, perfect for anniversaries and summer weddings. This moderately priced arrangement captures the warmth of summer evenings."},
24
+ {"id": "P023", "name": "Zen Bamboo Arrangement", "quantity": 15, "price": 65, "type": "arrangement", "description": "A small, minimalist arrangement featuring green bamboo and white accents, ideal for corporate settings or as a general gift. This affordable arrangement brings a sense of peace and tranquility."},
25
+ {"id": "P024", "name": "Lavender Dreams Bouquet", "quantity": 11, "price": 72, "type": "bouquet", "description": "A medium-sized bouquet of fragrant purple lavender with white and green accents, perfect for Mother's Day or as a thank you gift. This reasonably priced bouquet offers a soothing and aromatic experience."},
26
+ {"id": "P025", "name": "Citrus Burst Arrangement", "quantity": 7, "price": 88, "type": "arrangement", "description": "A medium-sized arrangement featuring bright orange, yellow, and green flowers, ideal for birthdays or congratulatory occasions. This moderately priced arrangement adds a zesty pop of color to any celebration."},
27
+ {"id": "P026", "name": "Midnight Mystery Bouquet", "quantity": 6, "price": 105, "type": "bouquet", "description": "A large, dramatic bouquet with deep purple, black, and dark red flowers, perfect for Halloween or romantic anniversaries. This premium bouquet offers a bold and mysterious aesthetic."},
28
+ {"id": "P027", "name": "Cherry Blossom Delight", "quantity": 10, "price": 92, "type": "arrangement", "description": "A medium-sized arrangement featuring delicate pink and white cherry blossoms, ideal for weddings or Mother's Day. This moderately priced arrangement brings the beauty of spring to any occasion."},
29
+ {"id": "P028", "name": "Ocean Breeze Bouquet", "quantity": 13, "price": 78, "type": "bouquet", "description": "A medium-sized bouquet with blue, white, and green flowers reminiscent of the sea, perfect for birthdays or as a thank you gift. This reasonably priced bouquet offers a refreshing coastal vibe."},
30
+ {"id": "P029", "name": "Rustic Wildflower Basket", "quantity": 9, "price": 68, "type": "arrangement", "description": "A medium-sized basket filled with a colorful mix of wildflowers, ideal for housewarming gifts or general occasions. This affordable arrangement brings a touch of countryside charm to any home."},
31
+ {"id": "P030", "name": "Elegant Black and White Arrangement", "quantity": 7, "price": 110, "type": "arrangement", "description": "A large, sophisticated arrangement featuring black and white flowers, perfect for corporate events or formal weddings. This premium arrangement offers a timeless and luxurious aesthetic."},
32
+ {"id": "P031", "name": "Sunshine Daisy Bouquet", "quantity": 14, "price": 60, "type": "bouquet", "description": "A small, cheerful bouquet of yellow and white daisies, great for get well wishes or birthdays. This budget-friendly bouquet is sure to brighten anyone's day."},
33
+ {"id": "P032", "name": "Royal Purple Passion", "quantity": 8, "price": 98, "type": "arrangement", "description": "A large arrangement featuring rich purple flowers with silver accents, suitable for anniversaries or upscale corporate events. This premium arrangement exudes luxury and sophistication."},
34
+ {"id": "P033", "name": "Enchanted Forest Terrarium", "quantity": 5, "price": 120, "type": "arrangement", "description": "A small, whimsical terrarium with miniature plants in shades of green and brown, perfect for housewarming or unique birthday gifts. This high-end arrangement offers a magical miniature world."},
35
+ {"id": "P034", "name": "Candy Cane Christmas Bouquet", "quantity": 12, "price": 82, "type": "bouquet", "description": "A medium-sized bouquet with red and white flowers arranged to resemble candy canes, ideal for Christmas or winter corporate events. This moderately priced bouquet brings festive cheer to any space."},
36
+ {"id": "P035", "name": "Peacock Feather Flair", "quantity": 6, "price": 115, "type": "arrangement", "description": "A large, exotic arrangement featuring flowers in peacock-inspired colors of blue, green, and purple, perfect for weddings or high-end corporate events. This premium arrangement offers a stunning and unique display."},
37
+ {"id": "P036", "name": "Pastel Rainbow Bouquet", "quantity": 10, "price": 75, "type": "bouquet", "description": "A medium-sized bouquet featuring a soft rainbow of pastel-colored flowers, ideal for birthdays or baby showers. This reasonably priced bouquet offers a gentle and dreamy aesthetic."},
38
+ {"id": "P037", "name": "Succulent Garden Bowl", "quantity": 15, "price": 65, "type": "arrangement", "description": "A small bowl filled with a variety of green, blue, and pink succulents, perfect for housewarming gifts or corporate desks. This affordable arrangement is low-maintenance and long-lasting."},
39
+ {"id": "P038", "name": "Moonlight Serenade Bouquet", "quantity": 7, "price": 95, "type": "bouquet", "description": "A medium-sized bouquet of white flowers with silver accents, ideal for anniversaries or Valentine's Day. This premium bouquet offers an elegant and romantic gesture."},
40
+ {"id": "P039", "name": "Tropical Tiki Arrangement", "quantity": 8, "price": 108, "type": "arrangement", "description": "A large, vibrant arrangement featuring tropical flowers in orange, pink, yellow, and green, perfect for summer parties or tropical-themed birthdays. This high-end arrangement brings an exotic paradise to any event."},
41
+ {"id": "P040", "name": "English Cottage Garden Bouquet", "quantity": 11, "price": 88, "type": "bouquet", "description": "A large, romantic bouquet with a mix of pink, purple, white, and yellow flowers reminiscent of an English garden, ideal for Mother's Day or as a thank you gift. This moderately priced bouquet offers a charming and nostalgic touch."},
42
+ {"id": "P041", "name": "Desert Oasis Cactus Arrangement", "quantity": 9, "price": 72, "type": "arrangement", "description": "A small arrangement featuring various green cacti and succulents with sandy brown accents, perfect for housewarming or corporate gifts. This affordable arrangement brings a touch of the desert to any space."},
43
+ {"id": "P042", "name": "Fire and Ice Rose Duo", "quantity": 13, "price": 85, "type": "bouquet", "description": "A medium-sized bouquet featuring a striking combination of red and white roses, ideal for anniversaries or Valentine's Day. This moderately priced bouquet offers a classic and passionate statement."},
44
+ {"id": "P043", "name": "Butterfly Garden Delight", "quantity": 10, "price": 79, "type": "arrangement", "description": "A medium-sized arrangement with pink, purple, and yellow flowers that attract butterflies, perfect for spring events or Mother's Day. This reasonably priced arrangement brings the beauty of a butterfly garden indoors."},
45
+ {"id": "P044", "name": "Zen Stone and Orchid Display", "quantity": 6, "price": 118, "type": "arrangement", "description": "A small, minimalist arrangement featuring white orchids and black stones, suitable for corporate settings or modern home decor. This premium arrangement offers a sleek and calming presence."},
46
+ {"id": "P045", "name": "Fairy Tale Princess Bouquet", "quantity": 8, "price": 92, "type": "bouquet", "description": "A medium-sized bouquet with soft pink, white, and purple flowers fit for a princess, perfect for birthdays or graduations. This moderately priced bouquet brings a touch of magic to any celebration."}
47
+ ]
requirements.txt CHANGED
@@ -4,4 +4,6 @@ langgraph
4
  langchain_community
5
  langchain_openai
6
  langchain_core
7
- langchain_groq
 
 
 
4
  langchain_community
5
  langchain_openai
6
  langchain_core
7
+ langchain_groq
8
+ chromadb
9
+ llama-index-embeddings-huggingface
src/csbot/customer_support_chatbot.py ADDED
@@ -0,0 +1,80 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from langgraph.graph import StateGraph, MessagesState
2
+ from langchain_core.prompts import ChatPromptTemplate
3
+ from langgraph.prebuilt import ToolNode
4
+ from src.tools.customer_support_tools import query_knowledge_base, search_for_product_reccommendations, data_protection_check, create_new_customer, place_order, retrieve_existing_customer_orders
5
+
6
+ import os
7
+
8
+
9
+ class Customer_Support_Bot:
10
+ def __init__(self,llm):
11
+ self.llm = llm
12
+
13
+
14
+ def chat_bot(self):
15
+
16
+ prompt = """#Purpose
17
+
18
+ You are a customer service chatbot for a flower shop company. You can help the customer achieve the goals listed below.
19
+
20
+ #Goals
21
+
22
+ 1. Answer questions the user might have relating to serivces offered
23
+ 2. Recommend products to the user based on their preferences
24
+ 3. Help the customer check on an existing order, or place a new order
25
+ 4. To place and manage orders, you will need a customer profile (with an associated id). If the customer already has a profile, perform a data protection check to retrieve their details. If not, create them a profile.
26
+
27
+ #Tone
28
+
29
+ Helpful and friendly. Use gen-z emojis to keep things lighthearted. You MUST always include a funny flower related pun in every response."""
30
+
31
+ chat_template = ChatPromptTemplate.from_messages(
32
+ [
33
+ ('system', prompt),
34
+ ('placeholder', "{messages}")
35
+ ]
36
+ )
37
+
38
+
39
+
40
+ tools = [query_knowledge_base, search_for_product_reccommendations, data_protection_check, create_new_customer, place_order, retrieve_existing_customer_orders]
41
+
42
+ llm = self.llm
43
+
44
+ llm_with_prompt = chat_template | llm.bind_tools(tools)
45
+
46
+
47
+ def call_agent(message_state: MessagesState):
48
+
49
+ response = llm_with_prompt.invoke(message_state)
50
+
51
+ return {
52
+ 'messages': [response]
53
+ }
54
+
55
+ def is_there_tool_calls(state: MessagesState):
56
+ last_message = state['messages'][-1]
57
+ if last_message.tool_calls:
58
+ return 'tool_node'
59
+ else:
60
+ return '__end__'
61
+
62
+
63
+ graph = StateGraph(MessagesState)
64
+
65
+ tool_node = ToolNode(tools)
66
+
67
+ graph.add_node('agent', call_agent)
68
+ graph.add_node('tool_node', tool_node)
69
+
70
+ graph.add_conditional_edges(
71
+ "agent",
72
+ is_there_tool_calls
73
+ )
74
+ graph.add_edge('tool_node', 'agent')
75
+
76
+ graph.set_entry_point('agent')
77
+
78
+ app = graph.compile()
79
+ return app
80
+
src/streamlitui/loadui.py CHANGED
@@ -51,5 +51,8 @@ class LoadStreamlitUI:
51
 
52
  with col2:
53
  st.subheader("Appointments")
 
 
 
54
 
55
  return self.user_controls
 
51
 
52
  with col2:
53
  st.subheader("Appointments")
54
+
55
+ elif self.user_controls['selected_usecase']=="Custome Support":
56
+ st.set_page_config(layout='wide', page_title='Flower Shop Chatbot', page_icon='💐')
57
 
58
  return self.user_controls
src/tools/customer_support_tools.py ADDED
@@ -0,0 +1,183 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from langchain_core.tools import tool
2
+ from typing import List, Dict
3
+ from src.vectorstores.vectore_store import FlowerShopVectorStore
4
+ import json
5
+
6
+ vector_store = FlowerShopVectorStore()
7
+ INVENTORY_FILE_PATH = './data/inventory.json'
8
+
9
+ customers_database = [
10
+ {"name": "John Doe", "postcode": "SW1A 1AA", "dob": "1990-01-01", "customer_id": "CUST001", "first_line_address": "123 Main St", "phone_number": "07712345678", "email": "john.doe@example.com"},
11
+ {"name": "Jane Smith", "postcode": "E1 6AN", "dob": "1985-05-15", "customer_id": "CUST002", "first_line_address": "456 High St", "phone_number": "07723456789", "email": "jane.smith@example.com"},
12
+ ]
13
+
14
+ orders_database = [
15
+ {"order_id": "ORD001", "customer_id": "CUST001", "status": "Processing", "items": ["Red Roses Bouquet"], "quantity": [1]},
16
+ {"order_id": "ORD002", "customer_id": "CUST002", "status": "Shipped", "items": ["Mixed Tulips", "Vase"], "quantity": [3, 1]},
17
+ ]
18
+
19
+ with open(INVENTORY_FILE_PATH, 'r') as f:
20
+ inventory_database = json.load(f)
21
+
22
+ data_protection_checks = []
23
+
24
+ @tool
25
+ def data_protection_check(name: str, postcode: str, year_of_birth: int, month_of_birth: int, day_of_birth: int) -> Dict:
26
+ """
27
+ Perform a data protection check against a customer to retrieve customer details.
28
+
29
+ Args:
30
+ name (str): Customer first and last name
31
+ postcode (str): Customer registered address
32
+ year_of_birth (int): The year the customer was born
33
+ month_of_birth (int): The month the customer was born
34
+ day_of_birth (int): The day the customer was born
35
+
36
+ Returns:
37
+ Dict: Customer details (name, postcode, dob, customer_id, first_line_address, email)
38
+ """
39
+ data_protection_checks.append(
40
+ {
41
+ 'name': name,
42
+ 'postcode': postcode,
43
+ 'year_of_birth': year_of_birth,
44
+ 'month_of_birth': month_of_birth,
45
+ 'day_of_birth': day_of_birth
46
+ }
47
+ )
48
+ for customer in customers_database:
49
+ if (customer['name'].lower() == name.lower() and
50
+ customer['postcode'].lower() == postcode.lower() and
51
+ int(customer['dob'][0:4]) == year_of_birth and
52
+ int(customer["dob"][5:7]) == month_of_birth and
53
+ int(customer["dob"][8:10]) == day_of_birth):
54
+ return f"DPA check passed - Retrieved customer details:\n{customer}"
55
+
56
+ return "DPA check failed, no customer with these details found"
57
+
58
+ @tool
59
+ def create_new_customer(first_name: str, surname: str, year_of_birth: int, month_of_birth: int, day_of_birth: int, postcode: str, first_line_of_address: str, phone_number: str, email: str) -> str:
60
+ """
61
+ Creates a customer profile, so that they can place orders.
62
+
63
+ Args:
64
+ first_name (str): Customers first name
65
+ surname (str): Customers surname
66
+ year_of_birth (int): Year customer was born
67
+ month_of_birth (int): Month customer was born
68
+ day_of_birth (int): Day customer was born
69
+ postcode (str): Customer's postcode
70
+ first_line_address (str): Customer's first line of address
71
+ phone_number (str): Customer's phone number
72
+ email (str): Customer's email address
73
+
74
+ Returns:
75
+ str: Confirmation that the profile has been created or any issues with the inputs
76
+ """
77
+ if len(phone_number) != 11:
78
+ return "Phone number must be 11 digits"
79
+ customer_id = len(customers_database) + 1
80
+ customers_database.append({
81
+ 'name': first_name + ' ' + surname,
82
+ 'dob': f'{year_of_birth}-{month_of_birth:02}-{day_of_birth:02}',
83
+ 'postcode': postcode,
84
+ 'first_line_address': first_line_of_address,
85
+ 'phone_number': phone_number,
86
+ 'email': email,
87
+ 'customer_id': f'CUST{customer_id}'
88
+ })
89
+ return f"Customer registered, with customer_id {f'CUST{customer_id}'}"
90
+
91
+
92
+ @tool
93
+ def query_knowledge_base(query: str) -> List[Dict[str, str]]:
94
+ """
95
+ Looks up information in a knowledge base to help with answering customer questions and getting information on business processes.
96
+
97
+ Args:
98
+ query (str): Question to ask the knowledge base
99
+
100
+ Return:
101
+ List[Dict[str, str]]: Potentially relevant question and answer pairs from the knowledge base
102
+ """
103
+ return vector_store.query_faqs(query=query)
104
+
105
+
106
+
107
+ @tool
108
+ def search_for_product_reccommendations(description: str):
109
+ """
110
+ Looks up information in a knowledge base to help with product recommendation for customers. For example:
111
+
112
+ "Boquets suitable for birthdays, maybe with red flowers"
113
+ "A large boquet for a wedding"
114
+ "A cheap boquet with wildflowers"
115
+
116
+ Args:
117
+ query (str): Description of product features
118
+
119
+ Return:
120
+ List[Dict[str, str]]: Potentially relevant products
121
+ """
122
+ return vector_store.query_inventories(query=description)
123
+
124
+ @tool
125
+ def retrieve_existing_customer_orders(customer_id: str) -> List[Dict]:
126
+ """
127
+ Retrieves the orders associated with the customer, including their status, items and ids
128
+
129
+ Args:
130
+ customer_id (str): Customer unique id associated with the order
131
+
132
+ Returns:
133
+ List[Dict]: All the orders associated with the customer_id passed in
134
+ """
135
+ customer_orders = [order for order in orders_database if order['customer_id'] == customer_id]
136
+ if not customer_orders:
137
+ return f"No orders associated with this customer id: {customer_id}"
138
+ return customer_orders
139
+
140
+ @tool
141
+ def place_order(items: Dict[str, int], customer_id: str) -> str:
142
+ """
143
+ Places an order for the requested items, and for the required quantities.
144
+
145
+ Args:
146
+ items (Dict[str, int]): Dictionary of items to order, with item id as the key and the quantity of that item as the value.
147
+ customer_id (str): The customer to place the order for
148
+
149
+ Returns:
150
+ str: Message indicating that the order has been placed, or, it hasnt been placed due to an issue
151
+ """
152
+ # Check that the item ids are valid
153
+ # Check that the quantities of items are valid
154
+ availability_messages = []
155
+ valid_item_ids = [
156
+ item['id'] for item in inventory_database
157
+ ]
158
+ for item_id, quantity in items.items():
159
+ if item_id not in valid_item_ids:
160
+ availability_messages.append(f'Item with id {item_id} is not found in the inventory')
161
+ else:
162
+ inventory_item = [item for item in inventory_database if item['id'] == item_id][0]
163
+ if quantity > inventory_item['quantity']:
164
+ availability_messages.append(f'There is insufficient quantity in the inventory for this item {inventory_item["name"]}\nAvailable: {inventory_item["quantity"]}\nRequested: {quantity}')
165
+ if availability_messages:
166
+ return "Order cannot be placed due to the following issues: \n" + '\n'.join(availability_messages)
167
+
168
+ # Place the order (in pretend database)
169
+ order_id = len(orders_database) + 1
170
+ orders_database.append(
171
+ {
172
+ 'order_id': order_id,
173
+ 'customer_id': customer_id,
174
+ 'status': 'Waiting for payment',
175
+ 'items': list(items.keys()),
176
+ 'quantity': list(items.values())
177
+ }
178
+ )
179
+ # Update the inventory
180
+ for item_id, quantity in items.items():
181
+ inventory_item = [item for item in inventory_database if item['id'] == item_id][0]
182
+ inventory_item['quantity'] -= quantity
183
+ return f"Order with id {order_id} has been placed successfully"
src/vectorstores/vectore_store.py ADDED
@@ -0,0 +1,122 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from chromadb import PersistentClient, EmbeddingFunction, Embeddings
2
+ from llama_index.embeddings.huggingface import HuggingFaceEmbedding
3
+ from typing import List
4
+ import json
5
+
6
+
7
+ MODEL_NAME = 'dunzhang/stella_en_1.5B_v5'
8
+ DB_PATH = './.chroma_db'
9
+ FAQ_FILE_PATH= './data/FAQ.json'
10
+ INVENTORY_FILE_PATH = './data/inventory.json'
11
+
12
+ class Product:
13
+ def __init__(self, name: str, id: str, description: str, type: str, price: float, quantity: int):
14
+ self.name = name
15
+ self.id = id
16
+ self.description = description
17
+ self.type = type
18
+ self.price = price
19
+ self.quantity = quantity
20
+
21
+ class QuestionAnswerPairs:
22
+ def __init__(self, question: str, answer: str):
23
+ self.question = question
24
+ self.answer = answer
25
+
26
+ class CustomEmbeddingClass(EmbeddingFunction):
27
+ def __init__(self, model_name):
28
+ self.embedding_model = HuggingFaceEmbedding(model_name=MODEL_NAME)
29
+
30
+ def __call__(self, input_texts: List[str]) -> Embeddings:
31
+ return [self.embedding_model.get_text_embedding(text) for text in input_texts]
32
+
33
+ class FAQCollection:
34
+ def __init__(self):
35
+ self.documents = []
36
+ self.ids = []
37
+ self.metadatas = []
38
+
39
+ def add(self, documents, ids, metadatas):
40
+ self.documents.extend(documents)
41
+ self.ids.extend(ids)
42
+ self.metadatas.extend(metadatas)
43
+
44
+ def display(self):
45
+ for doc, id_, meta in zip(self.documents, self.ids, self.metadatas):
46
+ print(f"ID: {id_}, Document: {doc}, Metadata: {meta}")
47
+
48
+ # Define the InventoryCollection class
49
+ class InventoryCollection:
50
+ def __init__(self):
51
+ self.documents = []
52
+ self.ids = []
53
+ self.metadatas = []
54
+
55
+ def add(self, documents, ids, metadatas):
56
+ self.documents.extend(documents)
57
+ self.ids.extend(ids)
58
+ self.metadatas.extend(metadatas)
59
+
60
+ def display(self):
61
+ for doc, id_, meta in zip(self.documents, self.ids, self.metadatas):
62
+ print(f"ID: {id_}, Document: {doc}, Metadata: {meta}")
63
+
64
+
65
+
66
+
67
+ class FlowerShopVectorStore:
68
+ def __init__(self):
69
+ db = PersistentClient(path=DB_PATH)
70
+
71
+ custom_embedding_function = CustomEmbeddingClass(MODEL_NAME)
72
+
73
+ self.faq_collection = db.get_or_create_collection(name='FAQ', embedding_function=custom_embedding_function)
74
+ self.inventory_collection = db.get_or_create_collection(name='Inventory', embedding_function=custom_embedding_function)
75
+
76
+ if self.faq_collection.count() == 0:
77
+ try :
78
+ self._load_faq_collection(FAQ_FILE_PATH)
79
+ except Exception as e:
80
+ raise ValueError(e)
81
+
82
+
83
+ if self.inventory_collection.count() == 0:
84
+ self._load_inventory_collection(INVENTORY_FILE_PATH)
85
+
86
+ def _load_faq_collection(self, faq_file_path: str):
87
+ try:
88
+
89
+ with open(faq_file_path, 'r') as f:
90
+ faqs = json.load(f)
91
+
92
+ # Create an instance of FAQCollection
93
+ obj_faq_collection = FAQCollection()
94
+
95
+ obj_faq_collection.add(
96
+ documents=[faq['question'] for faq in faqs] + [faq['answer'] for faq in faqs],
97
+ ids=[str(i) for i in range(0, 2*len(faqs))],
98
+ metadatas = faqs + faqs
99
+ )
100
+ self.faq_collection = obj_faq_collection
101
+ except Exception as ex:
102
+ raise ValueError(ex)
103
+
104
+ def _load_inventory_collection(self, inventory_file_path: str):
105
+ with open(inventory_file_path, 'r') as f:
106
+ inventories = json.load(f)
107
+
108
+ # Create an instance of InventoryCollection
109
+ obj_inventory_collection = InventoryCollection()
110
+
111
+ obj_inventory_collection.add(
112
+ documents=[inventory['description'] for inventory in inventories],
113
+ ids=[str(i) for i in range(0, len(inventories))],
114
+ metadatas = inventories
115
+ )
116
+ self.inventory_collection = obj_inventory_collection
117
+
118
+ def query_faqs(self, query: str):
119
+ return self.faq_collection.query(query_texts=[query], n_results=5)
120
+
121
+ def query_inventories(self, query: str):
122
+ return self.inventory_collection.query(query_texts=[query], n_results=5)