Spaces:
Sleeping
Sleeping
import streamlit as st | |
from streamlit_chat import message | |
from chatbot import DualChatbot | |
import time | |
from gtts import gTTS | |
from io import BytesIO | |
# Define the language type settings | |
LANGUAGES = ['English', 'German', 'Spanish', 'French', 'Swahili'] | |
SESSION_LENGTHS = ['Short', 'Long'] | |
PROFICIENCY_LEVELS = ['Beginner', 'Intermediate', 'Advanced'] | |
MAX_EXCHANGE_COUNTS = { | |
'Short': {'Conversation': 4, 'Debate': 4}, | |
'Long': {'Conversation': 8, 'Debate': 8} | |
} | |
AUDIO_SPEECH = { | |
'English': 'en', | |
'German': 'de', | |
'Spanish': 'es', | |
'French': 'fr', | |
'Swahili': 'sw' | |
} | |
AVATAR_SEED = [123, 42] | |
# Define backbone llm | |
engine = 'OpenAI' | |
# Set the title of the app | |
st.title('Agrixpert Bot π€') | |
# Set the description of the app | |
st.markdown(""" | |
This app generates a dialogue between a farmer and an agricultural expert to help farmers make better farming decisions. | |
Choose your desired settings and press 'Generate' to start π | |
""") | |
# Add a selectbox for learning mode | |
learning_mode = st.sidebar.selectbox('Interaction Mode π', ('Conversation', 'Debate')) | |
if learning_mode == 'Conversation': | |
role1 = st.sidebar.text_input('Role 1 π') | |
action1 = st.sidebar.text_input('Action 1 π£οΈ') | |
role2 = st.sidebar.text_input('Role 2 π') | |
action2 = st.sidebar.text_input('Action 2 π£οΈ') | |
scenario = st.sidebar.text_input('Scenario π₯') | |
time_delay = 2 | |
# Configure role dictionary | |
role_dict = { | |
'role1': {'name': role1, 'action': action1}, | |
'role2': {'name': role2, 'action': action2} | |
} | |
else: | |
scenario = st.sidebar.text_input('Debate Topic π¬') | |
# Configure role dictionary | |
role_dict = { | |
'role1': {'name': 'Proponent'}, | |
'role2': {'name': 'Opponent'} | |
} | |
time_delay = 5 | |
language = st.sidebar.selectbox('Target Language π€', LANGUAGES) | |
session_length = st.sidebar.selectbox('Session Length β°', SESSION_LENGTHS) | |
proficiency_level = st.sidebar.selectbox('Proficiency Level π', PROFICIENCY_LEVELS) | |
if "bot1_mesg" not in st.session_state: | |
st.session_state["bot1_mesg"] = [] | |
if "bot2_mesg" not in st.session_state: | |
st.session_state["bot2_mesg"] = [] | |
if 'batch_flag' not in st.session_state: | |
st.session_state["batch_flag"] = False | |
if 'translate_flag' not in st.session_state: | |
st.session_state["translate_flag"] = False | |
if 'audio_flag' not in st.session_state: | |
st.session_state["audio_flag"] = False | |
if 'message_counter' not in st.session_state: | |
st.session_state["message_counter"] = 0 | |
def show_messages(mesg_1, mesg_2, message_counter, | |
time_delay, batch=False, audio=False, | |
translation=False): | |
"""Display conversation exchanges. This helper function supports | |
displaying original texts, translated texts, and audio speech. | |
Args: | |
-------- | |
mesg1: messages spoken by the first bot | |
mesg2: messages spoken by the second bot | |
message_counter: create unique ID key for chat messages | |
time_delay: time interval between conversations | |
batch: True/False to indicate if conversations will be shown | |
all together or with a certain time delay. | |
audio: True/False to indicate if the audio speech need to | |
be appended to the texts | |
translation: True/False to indicate if the translated texts need to | |
be displayed | |
Output: | |
------- | |
message_counter: updated counter for ID key | |
""" | |
for i, mesg in enumerate([mesg_1, mesg_2]): | |
# Show original exchange () | |
message(f"{mesg['content']}", is_user=i==1, avatar_style="bottts", | |
seed=AVATAR_SEED[i], | |
key=message_counter) | |
message_counter += 1 | |
# Mimic time interval between conversations | |
# (this time delay only appears when generating | |
# the conversation script for the first time) | |
if not batch: | |
time.sleep(time_delay) | |
# Show translated exchange | |
if translation: | |
message(f"{mesg['translation']}", is_user=i==1, avatar_style="bottts", | |
seed=AVATAR_SEED[i], | |
key=message_counter) | |
message_counter += 1 | |
# Append autio to the exchange | |
if audio: | |
tts = gTTS(text=mesg['content'], lang=AUDIO_SPEECH[language]) | |
sound_file = BytesIO() | |
tts.write_to_fp(sound_file) | |
st.audio(sound_file) | |
return message_counter | |
# Define the button layout at the beginning | |
translate_col, original_col, audio_col = st.columns(3) | |
# Create the conversation container | |
conversation_container = st.container() | |
if 'dual_chatbots' not in st.session_state: | |
if st.sidebar.button('Generate'): | |
# Add flag to indicate if this is the first time running the script | |
st.session_state["first_time_exec"] = True | |
with conversation_container: | |
if learning_mode == 'Conversation': | |
st.write(f"""#### The following conversation happens between | |
{role1} and {role2} {scenario} π""") | |
else: | |
st.write(f"""#### Debate π¬: {scenario}""") | |
# Instantiate dual-chatbot system | |
dual_chatbots = DualChatbot(engine, role_dict, language, scenario, | |
proficiency_level, learning_mode, session_length) | |
st.session_state['dual_chatbots'] = dual_chatbots | |
# Start exchanges | |
for _ in range(MAX_EXCHANGE_COUNTS[session_length][learning_mode]): | |
output1, output2, translate1, translate2 = dual_chatbots.step() | |
mesg_1 = {"role": dual_chatbots.chatbots['role1']['name'], | |
"content": output1, "translation": translate1} | |
mesg_2 = {"role": dual_chatbots.chatbots['role2']['name'], | |
"content": output2, "translation": translate2} | |
new_count = show_messages(mesg_1, mesg_2, | |
st.session_state["message_counter"], | |
time_delay=time_delay, batch=False, | |
audio=False, translation=False) | |
st.session_state["message_counter"] = new_count | |
# Update session state | |
st.session_state.bot1_mesg.append(mesg_1) | |
st.session_state.bot2_mesg.append(mesg_2) | |
if 'dual_chatbots' in st.session_state: | |
# Show translation | |
if translate_col.button('Translate to English'): | |
st.session_state['translate_flag'] = True | |
st.session_state['batch_flag'] = True | |
# Show original text | |
if original_col.button('Show original'): | |
st.session_state['translate_flag'] = False | |
st.session_state['batch_flag'] = True | |
# Append audio | |
if audio_col.button('Play audio'): | |
st.session_state['audio_flag'] = True | |
st.session_state['batch_flag'] = True | |
# Retrieve generated conversation & chatbots | |
mesg1_list = st.session_state.bot1_mesg | |
mesg2_list = st.session_state.bot2_mesg | |
dual_chatbots = st.session_state['dual_chatbots'] | |
# Control message appear | |
if st.session_state["first_time_exec"]: | |
st.session_state['first_time_exec'] = False | |
else: | |
# Show complete message | |
with conversation_container: | |
if learning_mode == 'Conversation': | |
st.write(f"""#### {role1} and {role2} {scenario} π""") | |
else: | |
st.write(f"""#### Debate π¬: {scenario}""") | |
for mesg_1, mesg_2 in zip(mesg1_list, mesg2_list): | |
new_count = show_messages(mesg_1, mesg_2, | |
st.session_state["message_counter"], | |
time_delay=time_delay, | |
batch=st.session_state['batch_flag'], | |
audio=st.session_state['audio_flag'], | |
translation=st.session_state['translate_flag']) | |
st.session_state["message_counter"] = new_count | |
# # Create summary for key learning points | |
# summary_expander = st.expander('Key Learning Points') | |
# scripts = [] | |
# for mesg_1, mesg_2 in zip(mesg1_list, mesg2_list): | |
# for i, mesg in enumerate([mesg_1, mesg_2]): | |
# scripts.append(mesg['role'] + ': ' + mesg['content']) | |
# # Compile summary | |
# if "summary" not in st.session_state: | |
# summary = dual_chatbots.summary(scripts) | |
# st.session_state["summary"] = summary | |
# else: | |
# summary = st.session_state["summary"] | |
# with summary_expander: | |
# st.markdown(f"**Here is the learning summary:**") | |
# st.write(summary) | |