Skip to content

Commit

Permalink
Enable both text & voice inputs. Refactoring.
Browse files Browse the repository at this point in the history
  • Loading branch information
paulovcmedeiros committed Feb 25, 2024
1 parent 7942349 commit 42ddcf1
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 32 deletions.
68 changes: 39 additions & 29 deletions pyrobbot/app/app_page_templates.py
Original file line number Diff line number Diff line change
Expand Up @@ -234,29 +234,51 @@ def render_cost_estimate_page(self):
st.write()
st.caption(df.attrs["disclaimer"])

@property
def voice_output(self) -> bool:
"""Return the state of the voice output toggle."""
return st.session_state.get("toggle_voice_output", False)

def get_chat_input(self):
"""Render chat inut widgets and return the user's input."""
placeholder = (
f"Send a message to {self.chat_obj.assistant_name} ({self.chat_obj.model})"
)
min_audio_duration_seconds = 0.1
with st.container():
left, right = st.columns([0.95, 0.05])
with left:
text_prompt = st.chat_input(
placeholder=placeholder, key=f"text_input_widget_{self.page_id}"
)
with right:
audio = audiorecorder(
start_prompt="Rec",
stop_prompt="Stop",
pause_prompt="",
key=f"audiorecorder_widget_{self.page_id}",
)
recorded_prompt = None
if audio.duration_seconds > min_audio_duration_seconds:
recorded_prompt = self.chat_obj.stt(audio).text

return text_prompt or recorded_prompt

def _render_chatbot_page(self):
"""Render a chatbot page.
Adapted from:
<https://docs.streamlit.io/knowledge-base/tutorials/build-conversational-apps>
"""
self.chat_obj.reply_only_as_text = not self.voice_output

title_container = st.empty()
title_container.header(self.title, divider="rainbow")
chat_msgs_container = st.container(height=600, border=False)
prompt = self.get_chat_input()

placeholder = (
f"Send a message to {self.chat_obj.assistant_name} ({self.chat_obj.model})"
)

mic_input = st.session_state.get("toggle_mic_input", False)
self.chat_obj.reply_only_as_text = not mic_input
prompt = (
self.state.pop("recorded_prompt", None)
if mic_input
else st.chat_input(placeholder=placeholder)
)

with st.container(height=600, border=False):
with chat_msgs_container:
self.render_chat_history()
# Process user input
if prompt:
Expand All @@ -276,7 +298,6 @@ def _render_chatbot_page(self):
)

# Display (stream) assistant response in chat message container

with st.chat_message("assistant", avatar=self.avatars["assistant"]):
with st.empty():
st.markdown("▌")
Expand All @@ -291,7 +312,7 @@ def _render_chatbot_page(self):
st.markdown(full_response)

full_audio = AudioSegment.silent(duration=0)
if not self.chat_obj.reply_only_as_text:
if self.voice_output:
audio_placeholder_container = st.empty()
while not self.chat_obj.play_speech_queue.empty():
current_tts = self.chat_obj.play_speech_queue.get()
Expand Down Expand Up @@ -336,20 +357,9 @@ def _render_chatbot_page(self):
self.sidebar_title = title
title_container.header(title, divider="rainbow")

if mic_input and ("recorded_prompt" not in self.state):
_left, center, _right = st.columns([1, 1, 1])
with center:
audio = audiorecorder(
start_prompt=placeholder.replace("Send", "Record"),
stop_prompt="Stop and send prompt",
pause_prompt="",
key=f"audiorecorder_widget_{self.page_id}",
)
min_audio_duration_seconds = 0.1
if audio.duration_seconds > min_audio_duration_seconds:
self.state["recorded_prompt"] = self.chat_obj.stt(audio).text
del st.session_state[f"audiorecorder_widget_{self.page_id}"]
st.rerun()
# Need to delete the audiorecorder widget from the session state to prevent the
# previous audio from being used as input again
del st.session_state[f"audiorecorder_widget_{self.page_id}"]

def render(self):
"""Render the app's chatbot or costs page, depending on user choice."""
Expand Down
6 changes: 3 additions & 3 deletions pyrobbot/app/multipage.py
Original file line number Diff line number Diff line change
Expand Up @@ -253,11 +253,11 @@ def render(self, **kwargs):
help="Show estimated token usage and associated costs",
)
with center:
# Add button to toggle typing/recording
# Add button to toggle voice output
st.toggle(
key="toggle_mic_input",
key="toggle_voice_output",
label=":studio_microphone:",
help="Toggle typing/recording input types",
help="Toggle voice output",
)
# Add button to create a new chat
new_chat_button = st.button(label=":heavy_plus_sign: New Chat")
Expand Down

0 comments on commit 42ddcf1

Please sign in to comment.