New chat_conversation Streamlit App

New app for guided chat with GPT4. Target audience is language learners.

Some things to add yet:

  • observability (probably with Python logging library)
  • better print output
  • more language learning options
  • more conversations
  • more robust code
2 Likes

Great work @shawngiese! Especially how you managed to get the scrolling chat working without the input field dropping of the screen :clap: could you share your script please? Would really appreciate it.

Thanks @kamenxrider. I got the scroll technique from How do I move the default scroll of 'st.text_area' to the bottom? - #4 by piam . Got to run now but let me know if that discussion is not working for you.

Thanks a lot for sharing @shawngiese ! that worked for me. While it is much better than before, the text input field still scrolls of the screen when the response is long. It does pop back into view when you scroll so it’s a good start.
I am trying to get this to work in this component below to make it easy to scroll through the history and have a more static chat experience. Works well except for streaming chat.

Cool, I will take a look. I have the same problem when too much text is generated. That chat component has some strange CSS code inside that stops people from printing out their chat… maybe affecting other things too. My main use case for that scrolling hack was for mobile use.

My next challenge is to find a way to get better logs out of the Streamlit app… things like if the API throws an error, tokens used, time to resolve the API query, and maybe some of the queried text too. I have not found a best practices in Streamlit apps to export logs.

So far I am getting some okay logs with the Python logging library and Sentry. I am trying to catch API errors and to get some stats on the API usage… time to respond, token count, cost, which conversation was asked for and what was the question. No IP addresses or stuff like that.

The logging library in Python is pretty nice… I can generate console logs easily for my local tests and with Sentry.io I can collect the log messages and even get alerts. As for the cons I have sending to sentry:

  • Not sure what I will get when I migrate to the free plan.
  • I had to set my logs as errors to appear in the sentry interface.
  • There does not seem to be an easy way to export my data from Sentry to say, a spreadsheet

So for now it is fine. I saw some interesting Python logging handlers for Slack and Discord so I might give those a try down the road.

Updated with the streamlit 1.24 chat_message and input methods. Also added optional readback from Google Text to Speech service.

When using a desktop browser it can even auto play the generated audio… that in combination with Voice Control, on say a MacOS computer allows you to do everything with voice : )

Can we see the code for this ?

Hi @Richard_Rafferty, planning to release it. Wanted to write a Medium article about it first and clean up the code some : )

Would you consider sharing how you have done the audio playback ?

I have an issue where I load previous questions to the bot with audio. Then when I ask the next question it works fine but after that all audio on the page plays and the question isnt answered.

Great that you already got audio working. I am using Google TTS and it was a pain to get the credentials working the first time. How are you working with the audio from your TTS provider? You could load it into memory or save it as a file. I load the Google TTS response into memory and only offer the latest audio for playback.

Then I display the audio playback as

def autoplay_audio3(file):
    b64 = base64.b64encode(file).decode()
    if autoplay:
        md = f"""
            <audio id="audioTag" controls autoplay>
            <source src="data:audio/mp3;base64,{b64}"  type="audio/mpeg" format="audio/mpeg">
            </audio>
            """
    else:
        md = f"""
            <audio id="audioTag" controls>
            <source src="data:audio/mp3;base64,{b64}"  type="audio/mpeg" format="audio/mpeg">
            </audio>
            """
    st.markdown(
        md,
        unsafe_allow_html=True,
    )

My autoplay variable is actually just my audio enabled button (like I said a little messy, autoplay on mobile was harder to manage than I thought so I just say now: if audio, assume auto play. Then I let the browser figure out if it can or not).

autoplay = st.sidebar.checkbox("Enable audio",key="disabled")

Here is the code where I am making the call to Google for TTS:

synthesis_input = texttospeech.SynthesisInput(text=full_response)  
response = client.synthesize_speech(
    input=synthesis_input, voice=voice, audio_config=audio_config)

if autoplay:
    autoplay_audio3(response.audio_content)
return full_response

Maybe you have multiple copies of the same id (in my case this is “audioTag”) and all are getting triggered to play at the same time.

Sorry for the wait to get back to you.

That’s interesting I’m doing it essentially the same way you are but what you mention about tags has me thinking. Streamlit is definitely doing something in the background that triggers a page refresh and causes all the audio to be played and the current question doesn’t get an answer.

How are you getting around the issue of multiple tags ?

ah on reflection as I read your post I’m trying to make it possible that you can autoplay the historical answers aswell. Streamlist isn’t handling it well.

I only have one autoplay tag at any given time on my pages. Maybe have a jquery script to remove any autoplay tags before creating the next audio playback snippet is created?

Think I’ve given up with it and I’ve taken the approach you have with the last answer having the audio. Maybe I could add a button or something to move the audio to whichever answer the user wants to hear. I had hoped to do audio input as well but that seems not great on streamlit.