epalvarez commited on
Commit
1741112
·
verified ·
1 Parent(s): f6d92ec

Upload app.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. app.py +561 -0
app.py ADDED
@@ -0,0 +1,561 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import json
3
+ import os
4
+ import uuid
5
+
6
+ import pandas as pd
7
+ from datetime import datetime
8
+ import sqlite3
9
+ import weave
10
+
11
+ from langchain_community.embeddings.sentence_transformer import SentenceTransformerEmbeddings
12
+ from langchain_community.vectorstores import Chroma
13
+
14
+ from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
15
+ from langchain_community.utilities.sql_database import SQLDatabase
16
+ from langchain_community.agent_toolkits import create_sql_agent
17
+ from langchain.agents import create_tool_calling_agent, AgentExecutor
18
+ from langchain_core.tools import tool
19
+ from langchain_openai import AzureChatOpenAI
20
+ from openai import AzureOpenAI
21
+
22
+ from huggingface_hub import CommitScheduler
23
+ from pathlib import Path
24
+
25
+ # Setup project file paths
26
+ #-------------------------------------------------------------------------------------------------------------------------------------------------------------
27
+ # Set working directory (HuggingFace space)
28
+ hf_space_dir = os.getcwd()
29
+
30
+ # Obtain current directory and data file path
31
+ hf_space_app_dir_path = Path.cwd()
32
+ print(f"HuggingFace Space application directory: {hf_space_app_dir_path}\n")
33
+ #-------------------------------------------------------------------------------------------------------------------------------------------------------------
34
+
35
+ #====================================SETUP=====================================#
36
+ # Fetch secrets from Hugging Face Spaces
37
+
38
+ model_name = "gpt-4o"
39
+
40
+ # Extract the OpenAI key and endpoint from the configuration
41
+ openai_key = os.environ["AZURE_OPENAI_KEY"]
42
+ azure_endpoint = os.environ["AZURE_OPENAI_ENDPOINT"]
43
+ api_version = os.environ["AZURE_OPENAI_APIVERSION"]
44
+
45
+
46
+ # Define the location of the SQLite database
47
+ db_loc = 'ecomm.db'
48
+
49
+ # Create a SQLDatabase instance from the SQLite database URI
50
+ db = SQLDatabase.from_uri(f"sqlite:///{db_loc}")
51
+
52
+ # Retrieve the schema information of the database tables
53
+ database_schema = db.get_table_info()
54
+
55
+
56
+ # Let's initiate w&b weave with a project name - this will automatically save all the llm calls made using openai or gemini
57
+ # Make sure to save your w&b api key in secrets as WANDB_API_KEY
58
+ weave.init('ecomm_support') # <--------------------------------------------------------- Uncomment to log to WANDB
59
+
60
+
61
+ #=================================Setup Logging=====================================#
62
+
63
+
64
+ log_file = Path("logs/") / f"data_{uuid.uuid4()}.json"
65
+ log_folder = log_file.parent
66
+
67
+ log_scheduler = CommitScheduler(
68
+ repo_id="chatbot-logs", #Dataset name where we want to save the logs.
69
+ repo_type="dataset",
70
+ folder_path=log_folder,
71
+ path_in_repo="data",
72
+ every=5 # Saves data every x minute
73
+ )
74
+
75
+
76
+ history_file = Path("history/")/f"data_{uuid.uuid4()}.json"
77
+ history_folder = history_file.parent
78
+
79
+ history_scheduler = CommitScheduler(
80
+ repo_id="chatbot-history", #Dataset name where we want to save the logs.
81
+ repo_type="dataset",
82
+ folder_path=history_folder,
83
+ path_in_repo="data",
84
+ every=5 # Saves data every x minute
85
+ )
86
+
87
+ #=================================SQL_AGENT=====================================#
88
+
89
+ # Define the system message for the agent, including instructions and available tables
90
+ system_message = f"""You are a SQLite expert agent designed to interact with a SQLite database.
91
+ Given an input question, create a syntactically correct SQLite query to run, then look at the results of the query and return the answer.
92
+ Unless the user specifies a specific number of examples they wish to obtain, always limit your query to at most 100 results using the LIMIT clause as per SQLite. You can order the results to return the most informative data in the database..
93
+ You can order the results by a relevant column to return the most interesting examples in the database.
94
+ You must query only the columns that are needed to answer the question. Wrap each column name in double quotes (") to denote them as delimited identifiers.
95
+ You have access to tools for interacting with the database.
96
+ Only use the given tools. Only use the information returned by the tools to construct your final answer.
97
+ You MUST double check your query before executing it. If you get an error while executing a query, rewrite the query and try again.
98
+ DO NOT make any DML statements (INSERT, UPDATE, DELETE, DROP etc.) to the database.
99
+ You are not allowed to make dummy data.
100
+ If the question does not seem related to the database, just return "I don't know" as the answer.
101
+ Before you execute the query, tell us why you are executing it and what you expect to find briefly.
102
+ Only use the following tables:
103
+ {database_schema}
104
+ """
105
+
106
+ # Create a full prompt template for the agent using the system message and placeholders
107
+ full_prompt = ChatPromptTemplate.from_messages(
108
+ [
109
+ ("system", system_message),
110
+ ("human", '{input}'),
111
+ MessagesPlaceholder("agent_scratchpad")
112
+ ]
113
+ )
114
+
115
+ # Initialize the AzureChatOpenAI model with the extracted configuration
116
+ llm = AzureChatOpenAI(
117
+ model_name=model_name,
118
+ api_key=openai_key,
119
+ azure_endpoint=azure_endpoint,
120
+ api_version=api_version,
121
+ temperature=0
122
+ )
123
+ # Create the SQL agent using the AzureChatOpenAI model, database, and prompt template
124
+ sqlite_agent = create_sql_agent(
125
+ llm=llm,
126
+ db=db,
127
+ prompt=full_prompt,
128
+ agent_type="openai-tools",
129
+ agent_executor_kwargs={'handle_parsing_errors': True},
130
+ max_iterations=5,
131
+ verbose=True
132
+ )
133
+ #### Let's convert the sql agent into a tool that our fin agent can use.
134
+
135
+ @tool
136
+ def sql_tool(user_input):
137
+ """
138
+ Gathers information regarding purchases, transactions, returns, refunds, etc.
139
+ Executes a SQL query using the sqlite_agent and returns the result.
140
+ Args:
141
+ user_input (str): a natural language query string explaining what information is required while also providing the necessary details to get the information.
142
+ Returns:
143
+ str: The result of the SQL query execution. If an error occurs, the exception is returned as a string.
144
+ """
145
+ try:
146
+ # Invoke the sqlite_agent with the user input (SQL query)
147
+ response = sqlite_agent.invoke(user_input)
148
+
149
+ # Extract the output from the response
150
+ prediction = response['output']
151
+
152
+ except Exception as e:
153
+ # If an exception occurs, capture the exception message
154
+ prediction = e
155
+
156
+ # Return the result or the exception message
157
+ return prediction
158
+
159
+ #=================================== RAG TOOL======================================#
160
+ qna_system_message = """
161
+ You are an assistant to a support agent. Your task is to provide relevant information about the Python package Streamlit.
162
+ User input will include the necessary context for you to answer their questions. This context will begin with the token: ###Context.
163
+ The context contains references to specific portions of documents relevant to the user's query, along with source links.
164
+ The source for a context will begin with the token ###Source
165
+ When crafting your response:
166
+ 1. Select only context relevant to answer the question.
167
+ 2. User questions will begin with the token: ###Question.
168
+ 3. If the context provided doesn't answer the question respond with - "I do not have sufficient information to answer that"
169
+ 4. If user asks for product - list all the products that are relevant to his query. If you don't have that product try to cross sell with one of the products we have that is related to what they are interested in.
170
+ You should get information about similar products in the context.
171
+ Please adhere to the following guidelines:
172
+ - Your response should only be about the question asked and nothing else.
173
+ - Answer only using the context provided.
174
+ - Do not mention anything about the context in your final answer.
175
+ - If the answer is not found in the context, it is very very important for you to respond with "I don't know."
176
+ - Always quote the source when you use the context. Cite the relevant source at the end of your response under the section - Source:
177
+ - Do not make up sources. Use the links provided in the sources section of the context and nothing else. You are prohibited from providing other links/sources.
178
+ Here is an example of how to structure your response:
179
+ Answer:
180
+ [Answer]
181
+ Source:
182
+ [Source]
183
+ """
184
+
185
+ qna_user_message_template = """
186
+ ###Context
187
+ Here are some documents and their source that may be relevant to the question mentioned below.
188
+ {context}
189
+ ###Question
190
+ {question}
191
+ """
192
+ # Load the persisted DB
193
+ persisted_vectordb_location = 'policy_docs'
194
+ #Create a Colelction Name
195
+ collection_name = 'policy_docs'
196
+
197
+ embedding_model = SentenceTransformerEmbeddings(model_name='thenlper/gte-large')
198
+ # Load the persisted DB
199
+ vector_store = Chroma(
200
+ collection_name=collection_name,
201
+ persist_directory=persisted_vectordb_location,
202
+ embedding_function=embedding_model
203
+
204
+ )
205
+
206
+ retriever = vector_store.as_retriever(
207
+ search_type='similarity',
208
+ search_kwargs={'k': 5}
209
+ )
210
+
211
+ client = AzureOpenAI(
212
+ azure_endpoint=os.environ["AZURE_OPENAI_ENDPOINT_mini"],
213
+ api_key=os.environ["AZURE_OPENAI_KEY_mini"],
214
+ api_version=os.environ["AZURE_OPENAI_APIVERSION_mini"]
215
+ )
216
+
217
+
218
+ @tool
219
+ def rag(user_input: str) -> str:
220
+
221
+ """
222
+ Answers questions regarding products, and policies using product descriptions, product policies, and general policies of business using RAG.
223
+ Args:
224
+ user_input (str): The input question or query from the user.
225
+ Returns:
226
+ response (str): Return the generated response or an error message if an exception occurs.
227
+ """
228
+
229
+ relevant_document_chunks = retriever.invoke(user_input)
230
+ context_list = [d.page_content + "\n ###Source: " + d.metadata['source'] + "\n\n " for d in relevant_document_chunks]
231
+
232
+ context_for_query = ". ".join(context_list)
233
+
234
+ prompt = [
235
+ {'role':'system', 'content': qna_system_message},
236
+ {'role': 'user', 'content': qna_user_message_template.format(
237
+ context=context_for_query,
238
+ question=user_input
239
+ )
240
+ }
241
+ ]
242
+ try:
243
+ response = client.chat.completions.create(
244
+ model="gpt-4o-mini",
245
+ messages=prompt
246
+ )
247
+
248
+ prediction = response.choices[0].message.content
249
+ except Exception as e:
250
+ prediction = f'Sorry, I encountered the following error: \n {e}'
251
+
252
+
253
+ return prediction
254
+
255
+
256
+ #=================================== Other TOOLS======================================#
257
+
258
+ # Function to log actions
259
+ def log_history(email: str,chat_history: list) -> None:
260
+ # Save the log to the file
261
+ with history_scheduler.lock:
262
+ # Open the log file in append mode
263
+ with history_file.open("a") as f:
264
+ f.write(json.dumps({
265
+ "email": email,
266
+ "chat_history": chat_history,
267
+ "timestamp": str(datetime.now().strftime("%Y-%m-%d %H:%M:%S"))
268
+ }))
269
+
270
+ #st.write("chat_recorded")
271
+
272
+
273
+ def log_action(customer_id: str,task: str, details: str) -> None:
274
+ # Save the log to the file
275
+ with log_scheduler.lock:
276
+ # Open the log file in append mode
277
+ with log_file.open("a") as f:
278
+ f.write(json.dumps({
279
+ "customer_id": customer_id,
280
+ "task": task,
281
+ "details": details
282
+ }))
283
+
284
+
285
+ @tool
286
+ def register_feedback(intent, customer_id, feedback, rating):
287
+ """
288
+ Logs customer feedback into the feedback log.
289
+ Args:
290
+ intent (str): The category of the support query (e.g., "cancel_order", "get_refund").
291
+ customer_id (int): The unique ID of the customer.
292
+ feedback (str): The feedback provided by the customer.
293
+ rating(int): The rating provided by the customer out of 5
294
+ Returns:
295
+ str: Success message.
296
+ """
297
+ details = {
298
+ "intent": intent,
299
+ "customer_id": customer_id,
300
+ "feedback": feedback,
301
+ "rating": rating
302
+ }
303
+ log_action(customer_id,"register_feedback", details)
304
+ #print("register_feedback success")
305
+ #return "Feedback registered successfully!"
306
+
307
+ @tool
308
+ def defer_to_human(customer_id, query, intent, reason):
309
+ """
310
+ Logs customer details and the reason for deferring to a human agent.
311
+ Args:
312
+ customer_id (int): The unique ID of the customer whose query is being deferred.
313
+ query (str): The customer's query or issue that needs human intervention.
314
+ reason (str): The reason why the query cannot be resolved by the chatbot.
315
+ Returns:
316
+ str: Success message indicating the deferral was logged.
317
+ """
318
+
319
+ details = {
320
+ "customer_id": customer_id,
321
+ "query": query,
322
+ "reason": reason,
323
+ "intent": intent
324
+ }
325
+
326
+ log_action(customer_id,"defer_to_human", details)
327
+ #return "Case deferred to human agent and logged successfully!"
328
+
329
+
330
+ @tool
331
+ def days_since(delivered_date: str) ->str:
332
+ """
333
+ Calculates the number of days since the product was delivered. This helps in determining whether the product is within return period or not.
334
+ Args:
335
+ delivered_date (str): The date when the product was delivered in the format 'YYYY-MM-DD'.
336
+ """
337
+ try:
338
+ # Convert the delivered_date string to a datetime object
339
+ delivered_date = datetime.strptime(delivered_date, '%Y-%m-%d')
340
+ today = datetime.today()
341
+
342
+ # Calculate the difference in days
343
+ days_difference = (today - delivered_date).days
344
+
345
+ return str(days_difference)
346
+ except ValueError as e:
347
+ return f"Error: {e}"
348
+
349
+ def build_prompt(df):
350
+
351
+ system_message = f"""
352
+
353
+ You are an intelligent e-commerce chatbot designed to assist users with pre-order and post-order queries. Your job is to
354
+
355
+ Gather necessary information from the user to help them with their query.
356
+ If at any point you cannot determine the next steps - defer to human. you do not have clearance to go beyond the scope the following flow.
357
+ Do not provide sql inputs to the sql tool - you only need to ask in natural language what information you need.
358
+ You are only allowed to provide information relevant to the particular customer and the customer information is provided below. you can provide information of this customer only. Following is the information about the customer from the last 2 weeks:
359
+
360
+ {df}
361
+
362
+ If this information is not enough to answer question, identify the customer from data above and fetch necessary information usign the sql_tool or rag tool - do not fetch information of other customers.
363
+ use the details provided in the above file to fetch information from sql tool - like customer id, email and phone. Refrain from asking customers details unless necessary.
364
+ If customer asks about a product, you should act as a sales representative and help them understand the product as much as possible and provide all the necessary information for them. You should also provide them the link to the product which you can get from the source of the information.
365
+ If a customer asks a query about a policy, be grounded to the context provided to you. if at any point you don't the right thing to say, politely tell the customer that you are not the right person to answer this and defer it to a human.
366
+ Any time you defer it to a human, you should tell the customer why you did it in a polite manner.
367
+ MANDATORY STEP:
368
+ After helping the customer with their concern,
369
+ - Ask if the customer needs help with anything else. If they ask for anything from the above list help them and along with that,
370
+ 1. Ask for their feedback and rating out of 5.
371
+ 2. then, Use the `register_feedback` tool to log it. - you MUST ask customer feedback along with asking customer what else they need help with.
372
+ 3. After receving customer feedback exit the chat by responding with 'Bye'.
373
+
374
+ ---
375
+ ### **Handling Out-of-Scope Queries:**
376
+ If the user's query, at any point is not covered by the workflows above:
377
+ - Respond:
378
+ > "This is beyond my skill. Let me connect you to a customer service agent" and get necessary details from the customer and use the defer_to_human tool.
379
+ - Get customer feedback and rating out of 5.
380
+ - After getting feedback, end the conversation by saying 'Bye'.
381
+ ---
382
+ ### **IMPORTANT Notes for the Model:**
383
+ - Always fetch additional required details from the database and do not blindly believe details provided by the customer like customer id, email and phone number. You should get the customer id from the system prompt. Cross check with the database and stay loyal to the database.
384
+ - Be empathetic to the customer but loyal to the instructions provided to you. Try to deescalate a situation before deferring it to human and defer to human only once.
385
+ - Always aim to minimize the number of questions asked by retrieving as much information as possible from `sql_tool` and `rag` tool.
386
+ - Follow the exact workflows for each query category.
387
+ - You will always confirm the order id even if the customer has only one order before you fetch any details.
388
+ """
389
+
390
+ #st.write(system_message)
391
+ prompt = ChatPromptTemplate.from_messages([
392
+ ("system", system_message),
393
+ ("human", "{input}"),
394
+ ("placeholder", "{agent_scratchpad}"),
395
+ ])
396
+
397
+ return prompt
398
+
399
+
400
+ #===============================================Streamlit=========================================#
401
+
402
+
403
+ def login_page():
404
+ st.title("Login Page")
405
+
406
+ email = st.text_input("Email")
407
+ password = st.text_input("Password", type="password")
408
+
409
+ login_button = st.button("Login")
410
+
411
+ if login_button:
412
+ if authenticate_user(email, password):
413
+ st.session_state.logged_in = True
414
+ st.session_state.email = email
415
+ st.success("Login successful! Redirecting to Chatbot...")
416
+ st.rerun()
417
+ else:
418
+ st.error("Invalid email or password.")
419
+
420
+ def authenticate_user(email, phone):
421
+ connection = sqlite3.connect("ecomm.db") # Replace with your .db file path
422
+ cursor = connection.cursor()
423
+
424
+ query = "SELECT first_name FROM customers WHERE email = ? AND phone = ?"
425
+ cursor.execute(query, (email, phone))
426
+ user = cursor.fetchone()
427
+
428
+ if user:
429
+ return True # Login successful
430
+ return False # Login failed
431
+
432
+ ### Prefetch details
433
+
434
+ def fetch_details(email):
435
+ try:
436
+
437
+ # Connect to the SQLite database
438
+ connection = sqlite3.connect("ecomm.db") # Replace with your .db file path
439
+ cursor = connection.cursor()
440
+
441
+ query = f"""
442
+ SELECT
443
+ c.customer_id,
444
+ c.first_name || ' ' || c.last_name AS customer_name,
445
+ c.email,
446
+ c.phone,
447
+ c.address AS customer_address,
448
+ o.order_id,
449
+ o.order_date,
450
+ o.status AS order_status,
451
+ o.price AS order_price,
452
+ p.name AS product_name,
453
+ p.price AS product_price,
454
+ i.invoice_date,
455
+ i.amount AS invoice_amount,
456
+ i.invoice_url,
457
+ s.delivery_date,
458
+ s.shipping_status,
459
+ s.shipping_address,
460
+ r.refund_amount,
461
+ r.refund_status
462
+ FROM Customers c
463
+ LEFT JOIN Orders o ON c.customer_id = o.customer_id
464
+ LEFT JOIN Products p ON o.product_id = p.product_id
465
+ LEFT JOIN Invoices i ON o.order_id = i.order_id
466
+ LEFT JOIN Shipping s ON o.order_id = s.order_id
467
+ LEFT JOIN Refund r ON o.order_id = r.order_id
468
+ WHERE o.order_date >= datetime('now', '-30 days')
469
+ AND c.email = ?
470
+ ORDER BY o.order_date DESC;
471
+ """
472
+
473
+ cursor.execute(query, (email,))
474
+ columns = [description[0] for description in cursor.description] # Extract column names
475
+ results = cursor.fetchall() # Fetch all rows
476
+ #st.write(results)
477
+ # Convert results into a list of dictionaries
478
+ details = [dict(zip(columns, row)) for row in results]
479
+ #st.write(details)
480
+ return str(details).replace("{","/").replace("}","/")
481
+
482
+ except Exception as e:
483
+ st.write(f"Error: {e}")
484
+ finally:
485
+ # Close the connection
486
+ if connection:
487
+ cursor.close()
488
+ connection.close()
489
+
490
+ # Function to process user input and generate a chatbot response
491
+
492
+ def chatbot_interface():
493
+ st.title("E-Commerce Chatbot")
494
+
495
+ if 'conversation_history' not in st.session_state:
496
+ st.session_state.conversation_history = [{"role": "assistant", "content": "welcome! I am Raha, how can I help you on this beautiful day?"}]
497
+
498
+
499
+ details = fetch_details(st.session_state.email)
500
+ # st.write(details)
501
+ prompt = build_prompt(details)
502
+ tools = [sql_tool,defer_to_human, rag, register_feedback, days_since]
503
+
504
+ chatbot = AzureChatOpenAI(
505
+ model_name=model_name,
506
+ api_key=openai_key,
507
+ azure_endpoint=azure_endpoint,
508
+ api_version=api_version,
509
+ temperature=0
510
+ )
511
+
512
+ agent = create_tool_calling_agent(chatbot, tools, prompt)
513
+ agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)
514
+
515
+ # Display chat messages from history on app rerun
516
+ for message in st.session_state.conversation_history:
517
+ with st.chat_message(message["role"]):
518
+ st.markdown(message["content"])
519
+
520
+ # React to user input
521
+ if user_input := st.chat_input("You: ", key="chat_input"):
522
+ # Display user message in chat message container
523
+ st.chat_message("user").markdown(user_input)
524
+ with st.spinner("Processing..."):
525
+
526
+ # Add user message to conversation history
527
+ st.session_state.conversation_history.append({"role": "user", "content": user_input})
528
+
529
+ conversation_input = "\n".join(
530
+ [f"{turn['role'].capitalize()}: {turn['content']}" for turn in st.session_state.conversation_history]
531
+ )
532
+
533
+ try:
534
+ # Pass the history to the agent
535
+ response = agent_executor.invoke({"input": conversation_input})
536
+
537
+ # Add the chatbot's response to the history
538
+ chatbot_response = response['output']
539
+ st.session_state.conversation_history.append({"role": "assistant", "content": chatbot_response})
540
+ # Check if the assistant's response contains "exit"
541
+ if "bye" in chatbot_response.lower():
542
+ log_history(st.session_state.email,st.session_state.conversation_history)
543
+
544
+ # Display the chatbot's response
545
+ with st.chat_message("assistant"):
546
+ st.markdown(chatbot_response)
547
+
548
+ except Exception as e:
549
+ st.write("Blocked by Azure content policy \n", e )
550
+
551
+ def main():
552
+ # Check if the user is logged in
553
+ if "logged_in" in st.session_state and st.session_state["logged_in"]:
554
+ # Show chatbot page if logged in
555
+ chatbot_interface()
556
+ else:
557
+ # Show login page if not logged in
558
+ login_page()
559
+
560
+ if __name__ == "__main__":
561
+ main()