You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

260 lines
9.8 KiB

import streamlit as st
import json
import numpy as np
from PIL import Image
from bot import Chatbot, Report, CheckerBot, GeneralBot, botstrings
from time import sleep
def send(message, check=True, add_to_memory=True):
"""
Sends a message to the chat interface.
Parameters:
- message (str): The message to be sent.
- check (bool): Whether to check the message for tips. Default is True.
- add_to_memory (bool): Whether to add the message to the chatbot's memory. Default is True.
Returns:
- bool: True if the message was sent successfully, False if it was a tip.
"""
store_state()
# Check if the message is a tip.
if check:
tip = checker_bot.check_for_tips(message)
else:
tip = False
if tip:
print(" I'TS A TIP ☠")
return False
else:
with st.chat_message("assistant"):
st.markdown(message)
# Add assistant response to chat history
st.session_state.messages.append({"role": "assistant", "content": message})
if add_to_memory:
chatbot.memory.append({"role":"assistant", "content": message})
return True
def store_state():
"""
Stores the current state of the chatbot and report in the session state.
"""
st.session_state.chatbot = chatbot
st.session_state.report = report
def generate_report():
"""
Generates a report using a Jinja2 template and stores it in the session state.
"""
from jinja2 import Environment, FileSystemLoader
# Load the Jinja2 template
env = Environment(loader=FileSystemLoader('.'))
template = env.get_template('report_template.html')
report_html = template.render(report=report)
st.session_state.report_html = report_html
st.rerun()
st.title("UNMAS Bot")
# Check if 'report_html', 'messages', 'upload_image',are already in the session state, if not, initialize them
if 'report_html' not in st.session_state:
st.session_state.report_html = ''
if "messages" not in st.session_state:
st.session_state.messages = []
if 'upload_image' not in st.session_state:
st.session_state.upload_image = False
# Check if 'report' and the bots are already in the session state, if not, initialize them
if "report" not in st.session_state:
report = Report()
st.session_state.report = report
else:
report = st.session_state.report
if "chatbot" not in st.session_state:
chatbot = Chatbot()
st.session_state.chatbot = chatbot
else:
# If 'chatbot' is already in the session state, retrieve it
chatbot = st.session_state.chatbot
# If the report object is not None, update the chatbot's memory with a new system prompt
if report.object is not None:
new_system_prompt = botstrings.checker_bot_system_prompt + f' The user seems to have found {report.object}.'
chatbot.memory[0] = {"role":"system", "content": new_system_prompt}
print(chatbot.memory)
if "checker_bot" not in st.session_state:
checker_bot = CheckerBot()
st.session_state.checker_bot = checker_bot
else:
checker_bot = st.session_state.checker_bot
# Display chat messages from history on app rerun
for message in st.session_state.messages:
with st.chat_message(message["role"]):
st.markdown(message["content"])
# If 'report_html' in the session state is not an empty string, write the report to the screen and reset 'report_html' to an empty string
if st.session_state.report_html != '':
st.markdown(st.session_state.report_html, unsafe_allow_html=True)
st.session_state.report_html = ''
# Check if 'upload_image' is set to True in the session state
if st.session_state.upload_image:
import base64
from io import BytesIO
# Initialize user_input to None
user_input = None
# Create a file uploader widget that accepts png, jpg, and jpeg files
img_file = st.file_uploader('Upload an image', type=['png', 'jpg', 'jpeg'])
# Create a chat input widget and store the user's input in user_input
user_input = st.chat_input('')
# If an image file was uploaded
if img_file is not None:
# Open the image file and convert it to a numpy array and store the image array in the report object
image = Image.open(img_file)
img_array = np.array(image)
# Convert the image to Base64
buffered = BytesIO()
# Convert image to RGB if it's RGBA
if image.mode == 'RGBA':
image = image.convert('RGB')
image.save(buffered, format="JPEG")
img_str = base64.b64encode(buffered.getvalue()).decode()
report.image = img_str
send('Thanks!', check=False, add_to_memory=False)
# Ask the chatbot for more information and store the question
question = chatbot.ask_for_info(report, chatbot=chatbot)
send(question, check=False)
# Set 'upload_image' to False in the session state
st.session_state.upload_image = False
store_state()
st.rerun()
# If the user entered something in the chat input widget
elif user_input:
# Check the user's answer to the image question
answer = checker_bot.check_image_answer(user_input, report)
if answer == 'no' or answer == 'help':
# If the user answered 'no'
if answer == 'no':
# Send a message to the user and set 'upload_image' to False in the session state
send('No problem, we will continue without the image.', check=False, add_to_memory=False)
st.session_state.upload_image = False
elif answer == 'help':
# Send a help message to the user and set 'upload_image' to False in the session state
send('We will provide help for sending a picture in WhatsAPP', check=False) #TODO
st.session_state.upload_image = False
# Ask the chatbot for more information and store the question
question = chatbot.ask_for_info(report, chatbot=chatbot)
send(question, check=False)
# If the user answered 'yes'
elif answer == 'yes':
send('Great! Please upload the image.', check=False, add_to_memory=False)
st.session_state.upload_image = True
store_state()
st.rerun()
else:
user_input = st.chat_input('')
if user_input and not st.session_state.upload_image:
if user_input.lower() == 'report':
# Download the report
generate_report()
st.chat_message("user").markdown(user_input)
# Add user message to chat history
st.session_state.messages.append({"role": "user", "content": user_input})
chatbot.memory.append({"role":"user", "content": user_input})
# Check the message type
print('Check message type')
message_type = checker_bot.check_message_type(message=user_input)
print('Message type:', message_type)
if not chatbot.first_instructions_sent:
# Give instructions for how to use the bot
chatbot.first_instructions_sent = True
chatbot.informations_requested = True
send(botstrings.first_instructions, check=False, add_to_memory=False)
sleep(1.2)
send('So first, tell me what you found?', check=False)
else:
if 'greeting' in message_type.lower():
# Answer the greeting
bot_answer = chatbot.generate(user_input)
send(bot_answer['content'])
elif 'question' in message_type.lower():
bot_answer = chatbot.generate(user_input) # TODO How to handle questions?
# Check if the answer is an answer to the question.
answered = checker_bot.check_answer(bot_answer['content'], user_input, chatbot)
if not answered:
bot_answer = 'I could not understand your question. Please ask again.'
send(bot_answer)
chatbot.memory.append({"role":"assistant", "content": bot_answer})
elif 'information' in message_type.lower():
if chatbot.informations_requested:
answered = checker_bot.check_answer(user_input, chatbot.memory[-1]['content'], chatbot)
question = ''
# Make the last bot message the question
for i in chatbot.memory:
if i['role'] == 'assistant':
question = i['content']
if answered:
# Ask for information and send that message to the report
result = checker_bot.check_for_info(user_input, report, looking_for=report.looking_for, question=question)
if result:
print(result)
else:
send('I could not understand your message. Please try again.', check=False)
question = chatbot.ask_for_info(report, chatbot=chatbot)
if question == 'image':
question = "Can you upload a picture of what you have found? Make sure not to get close to what you've found when taking the picture. If you can't take a picture, just say 'no'."
st.session_state.upload_image = True
print(st.session_state.upload_image)
send(question, check=False, add_to_memory=False)
st.rerun()
elif question == 'done':
send('Thank you for your help! Below is the report.', check=False)
generate_report()
else:
send(question, check=False)
else:
send('I could not understand your message. Please try again.', check=False)
else:
send('I could not understand your message. Please try again.', check=False)
store_state()